1181 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			1181 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
	
	
|  | //////////////////////////////////////////////////////////////////////////////
 | ||
|  | //
 | ||
|  | //  Detours Test Program (trcser.cpp of trcser.dll)
 | ||
|  | //
 | ||
|  | //  Microsoft Research Detours Package
 | ||
|  | //
 | ||
|  | //  Copyright (c) Microsoft Corporation.  All rights reserved.
 | ||
|  | //
 | ||
|  | #define _WIN32_WINNT        0x0400
 | ||
|  | #define WIN32
 | ||
|  | #define NT
 | ||
|  | 
 | ||
|  | #define DBG_TRACE   0
 | ||
|  | 
 | ||
|  | #include <windows.h>
 | ||
|  | #include <stdio.h>
 | ||
|  | #include "detours.h"
 | ||
|  | #include "syelog.h"
 | ||
|  | 
 | ||
|  | #define PULONG_PTR          PVOID
 | ||
|  | #define PLONG_PTR           PVOID
 | ||
|  | #define ULONG_PTR           PVOID
 | ||
|  | #define ENUMRESNAMEPROCA    PVOID
 | ||
|  | #define ENUMRESNAMEPROCW    PVOID
 | ||
|  | #define ENUMRESLANGPROCA    PVOID
 | ||
|  | #define ENUMRESLANGPROCW    PVOID
 | ||
|  | #define ENUMRESTYPEPROCA    PVOID
 | ||
|  | #define ENUMRESTYPEPROCW    PVOID
 | ||
|  | #define STGOPTIONS          PVOID
 | ||
|  | 
 | ||
|  | //////////////////////////////////////////////////////////////////////
 | ||
|  | #pragma warning(disable:4127)   // Many of our asserts are constants.
 | ||
|  | 
 | ||
|  | #define ASSERT_ALWAYS(x)   \
 | ||
|  |     do {                                                        \ | ||
|  |     if (!(x)) {                                                 \ | ||
|  |             AssertMessage(#x, __FILE__, __LINE__);              \ | ||
|  |             DebugBreak();                                       \ | ||
|  |     }                                                           \ | ||
|  |     } while (0) | ||
|  | 
 | ||
|  | #ifndef NDEBUG
 | ||
|  | #define ASSERT(x)           ASSERT_ALWAYS(x)
 | ||
|  | #else
 | ||
|  | #define ASSERT(x)
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #define UNUSED(c)       (c) = (c)
 | ||
|  | 
 | ||
|  | //////////////////////////////////////////////////////////////////////
 | ||
|  | static HMODULE s_hInst = NULL; | ||
|  | static CHAR s_szDllPath[MAX_PATH]; | ||
|  | 
 | ||
|  | VOID _PrintDump(HANDLE h, PCHAR pszData, INT cbData); | ||
|  | VOID _PrintEnter(PCSTR psz, ...); | ||
|  | VOID _PrintExit(PCSTR psz, ...); | ||
|  | VOID _Print(PCSTR psz, ...); | ||
|  | 
 | ||
|  | VOID AssertMessage(CONST PCHAR pszMsg, CONST PCHAR pszFile, ULONG nLine); | ||
|  | 
 | ||
|  | //////////////////////////////////////////////////////////////////////////////
 | ||
|  | //
 | ||
|  | extern "C" { | ||
|  |     HANDLE (WINAPI * Real_CreateFileW)(LPCWSTR a0, | ||
|  |                                        DWORD a1, | ||
|  |                                        DWORD a2, | ||
|  |                                        LPSECURITY_ATTRIBUTES a3, | ||
|  |                                        DWORD a4, | ||
|  |                                        DWORD a5, | ||
|  |                                        HANDLE a6) | ||
|  |         = CreateFileW; | ||
|  | 
 | ||
|  |     BOOL (WINAPI * Real_WriteFile)(HANDLE hFile, | ||
|  |                                      LPCVOID lpBuffer, | ||
|  |                                      DWORD nNumberOfBytesToWrite, | ||
|  |                                      LPDWORD lpNumberOfBytesWritten, | ||
|  |                                      LPOVERLAPPED lpOverlapped) | ||
|  |         = WriteFile; | ||
|  |     BOOL (WINAPI * Real_FlushFileBuffers)(HANDLE hFile) | ||
|  |         = FlushFileBuffers; | ||
|  |     BOOL (WINAPI * Real_CloseHandle)(HANDLE hObject) | ||
|  |         = CloseHandle; | ||
|  | 
 | ||
|  |     BOOL (WINAPI * Real_WaitNamedPipeW)(LPCWSTR lpNamedPipeName, DWORD nTimeOut) | ||
|  |         = WaitNamedPipeW; | ||
|  |     BOOL (WINAPI * Real_SetNamedPipeHandleState)(HANDLE hNamedPipe, | ||
|  |                                                    LPDWORD lpMode, | ||
|  |                                                    LPDWORD lpMaxCollectionCount, | ||
|  |                                                    LPDWORD lpCollectDataTimeout) | ||
|  |         = SetNamedPipeHandleState; | ||
|  | 
 | ||
|  |     DWORD (WINAPI * Real_GetCurrentProcessId)(VOID) | ||
|  |         = GetCurrentProcessId; | ||
|  |     VOID (WINAPI * Real_GetSystemTimeAsFileTime)(LPFILETIME lpSystemTimeAsFileTime) | ||
|  |         = GetSystemTimeAsFileTime; | ||
|  | 
 | ||
|  |     VOID (WINAPI * Real_InitializeCriticalSection)(LPCRITICAL_SECTION lpSection) | ||
|  |         = InitializeCriticalSection; | ||
|  |     VOID (WINAPI * Real_EnterCriticalSection)(LPCRITICAL_SECTION lpSection) | ||
|  |         = EnterCriticalSection; | ||
|  |     VOID (WINAPI * Real_LeaveCriticalSection)(LPCRITICAL_SECTION lpSection) | ||
|  |         = LeaveCriticalSection; | ||
|  | } | ||
|  | 
 | ||
|  | DWORD (WINAPI * Real_GetModuleFileNameW)(HMODULE a0, | ||
|  |                                          LPWSTR a1, | ||
|  |                                          DWORD a2) | ||
|  |     = GetModuleFileNameW; | ||
|  | 
 | ||
|  | DWORD (WINAPI * Real_GetModuleFileNameA)(HMODULE a0, | ||
|  |                                          LPSTR a1, | ||
|  |                                          DWORD a2) | ||
|  |     = GetModuleFileNameA; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_CreateProcessW)(LPCWSTR a0, | ||
|  |                                     LPWSTR a1, | ||
|  |                                     LPSECURITY_ATTRIBUTES a2, | ||
|  |                                     LPSECURITY_ATTRIBUTES a3, | ||
|  |                                     BOOL a4, | ||
|  |                                     DWORD a5, | ||
|  |                                     LPVOID a6, | ||
|  |                                     LPCWSTR a7, | ||
|  |                                     struct _STARTUPINFOW* a8, | ||
|  |                                     LPPROCESS_INFORMATION a9) | ||
|  |     = CreateProcessW; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_BuildCommDCBA)(LPCSTR a0, | ||
|  |                                    struct _DCB* a1) | ||
|  |     = BuildCommDCBA; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_BuildCommDCBAndTimeoutsA)(LPCSTR a0, | ||
|  |                                               struct _DCB* a1, | ||
|  |                                               struct _COMMTIMEOUTS* a2) | ||
|  |     = BuildCommDCBAndTimeoutsA; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_BuildCommDCBAndTimeoutsW)(LPCWSTR a0, | ||
|  |                                               struct _DCB* a1, | ||
|  |                                               struct _COMMTIMEOUTS* a2) | ||
|  |     = BuildCommDCBAndTimeoutsW; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_BuildCommDCBW)(LPCWSTR a0, | ||
|  |                                    struct _DCB* a1) | ||
|  |     = BuildCommDCBW; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_ClearCommBreak)(HANDLE a0) | ||
|  |     = ClearCommBreak; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_ClearCommError)(HANDLE a0, | ||
|  |                                     LPDWORD a1, | ||
|  |                                     struct _COMSTAT* a2) | ||
|  |     = ClearCommError; | ||
|  | 
 | ||
|  | HANDLE (WINAPI * Real_CreateFileA)(LPCSTR a0, | ||
|  |                                    DWORD a1, | ||
|  |                                    DWORD a2, | ||
|  |                                    LPSECURITY_ATTRIBUTES a3, | ||
|  |                                    DWORD a4, | ||
|  |                                    DWORD a5, | ||
|  |                                    HANDLE a6) | ||
|  |     = CreateFileA; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_EscapeCommFunction)(HANDLE a0, | ||
|  |                                         DWORD a1) | ||
|  |     = EscapeCommFunction; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_GetCommConfig)(HANDLE a0, | ||
|  |                                    LPCOMMCONFIG a1, | ||
|  |                                    LPDWORD a2) | ||
|  |     = GetCommConfig; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_GetCommMask)(HANDLE a0, | ||
|  |                                  LPDWORD a1) | ||
|  |     = GetCommMask; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_GetCommModemStatus)(HANDLE a0, | ||
|  |                                         LPDWORD a1) | ||
|  |     = GetCommModemStatus; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_GetCommProperties)(HANDLE a0, | ||
|  |                                        LPCOMMPROP a1) | ||
|  |     = GetCommProperties; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_GetCommState)(HANDLE a0, | ||
|  |                                   struct _DCB* a1) | ||
|  |     = GetCommState; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_GetCommTimeouts)(HANDLE a0, | ||
|  |                                      struct _COMMTIMEOUTS* a1) | ||
|  |     = GetCommTimeouts; | ||
|  | 
 | ||
|  | DWORD (WINAPI * Real_GetCurrentThreadId)(void) | ||
|  |     = GetCurrentThreadId; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_GetOverlappedResult)(HANDLE a0, | ||
|  |                                          LPOVERLAPPED a1, | ||
|  |                                          LPDWORD a2, | ||
|  |                                          BOOL a3) | ||
|  |     = GetOverlappedResult; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_PurgeComm)(HANDLE a0, | ||
|  |                                DWORD a1) | ||
|  |     = PurgeComm; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_ReadFile)(HANDLE a0, | ||
|  |                               LPVOID a1, | ||
|  |                               DWORD a2, | ||
|  |                               LPDWORD a3, | ||
|  |                               LPOVERLAPPED a4) | ||
|  |     = ReadFile; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_SetCommBreak)(HANDLE a0) | ||
|  |     = SetCommBreak; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_SetCommConfig)(HANDLE a0, | ||
|  |                                    LPCOMMCONFIG a1, | ||
|  |                                    DWORD a2) | ||
|  |     = SetCommConfig; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_SetCommMask)(HANDLE a0, | ||
|  |                                  DWORD a1) | ||
|  |     = SetCommMask; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_SetCommState)(HANDLE a0, | ||
|  |                                   struct _DCB* a1) | ||
|  |     = SetCommState; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_SetCommTimeouts)(HANDLE a0, | ||
|  |                                      struct _COMMTIMEOUTS* a1) | ||
|  |     = SetCommTimeouts; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_SetupComm)(HANDLE a0, | ||
|  |                                DWORD a1, | ||
|  |                                DWORD a2) | ||
|  |     = SetupComm; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_TransmitCommChar)(HANDLE a0, | ||
|  |                                       char a1) | ||
|  |     = TransmitCommChar; | ||
|  | 
 | ||
|  | BOOL (WINAPI * Real_WaitCommEvent)(HANDLE a0, | ||
|  |                                    LPDWORD a1, | ||
|  |                                    LPOVERLAPPED a2) | ||
|  |     = WaitCommEvent; | ||
|  | 
 | ||
|  | /////////////////////////////////////////////////////////////
 | ||
|  | // Detours
 | ||
|  | //
 | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_CreateProcessW(LPCWSTR lpApplicationName, | ||
|  |                                 LPWSTR lpCommandLine, | ||
|  |                                 LPSECURITY_ATTRIBUTES lpProcessAttributes, | ||
|  |                                 LPSECURITY_ATTRIBUTES lpThreadAttributes, | ||
|  |                                 BOOL bInheritHandles, | ||
|  |                                 DWORD dwCreationFlags, | ||
|  |                                 LPVOID lpEnvironment, | ||
|  |                                 LPCWSTR lpCurrentDirectory, | ||
|  |                                 LPSTARTUPINFOW lpStartupInfo, | ||
|  |                                 LPPROCESS_INFORMATION lpProcessInformation) | ||
|  | { | ||
|  |     _PrintEnter("CreateProcessW(%ls,%ls,%p,%p,%x,%x,%p,%ls,%p,%p)\n", | ||
|  |                 lpApplicationName, | ||
|  |                 lpCommandLine, | ||
|  |                 lpProcessAttributes, | ||
|  |                 lpThreadAttributes, | ||
|  |                 bInheritHandles, | ||
|  |                 dwCreationFlags, | ||
|  |                 lpEnvironment, | ||
|  |                 lpCurrentDirectory, | ||
|  |                 lpStartupInfo, | ||
|  |                 lpProcessInformation); | ||
|  | 
 | ||
|  |     _Print("Calling DetourCreateProcessWithDllExW(,%hs)\n", s_szDllPath); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = DetourCreateProcessWithDllExW(lpApplicationName, | ||
|  |                                            lpCommandLine, | ||
|  |                                            lpProcessAttributes, | ||
|  |                                            lpThreadAttributes, | ||
|  |                                            bInheritHandles, | ||
|  |                                            dwCreationFlags, | ||
|  |                                            lpEnvironment, | ||
|  |                                            lpCurrentDirectory, | ||
|  |                                            lpStartupInfo, | ||
|  |                                            lpProcessInformation, | ||
|  |                                            s_szDllPath, | ||
|  |                                            Real_CreateProcessW); | ||
|  |     } __finally { | ||
|  |         _PrintExit("CreateProcessW(,,,,,,,,,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_BuildCommDCBA(LPCSTR a0, | ||
|  |                                LPDCB a1) | ||
|  | { | ||
|  |     _PrintEnter("BuildCommDCBA(%hs,%p)\n", a0, a1); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_BuildCommDCBA(a0, a1); | ||
|  |     } __finally { | ||
|  |         _PrintExit("BuildCommDCBA(,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_BuildCommDCBAndTimeoutsA(LPCSTR a0, | ||
|  |                                           LPDCB a1, | ||
|  |                                           LPCOMMTIMEOUTS a2) | ||
|  | { | ||
|  |     _PrintEnter("BuildCommDCBAndTimeoutsA(%hs,%p,%p)\n", a0, a1, a2); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_BuildCommDCBAndTimeoutsA(a0, a1, a2); | ||
|  |     } __finally { | ||
|  |         _PrintExit("BuildCommDCBAndTimeoutsA(,,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_BuildCommDCBAndTimeoutsW(LPCWSTR a0, | ||
|  |                                           LPDCB a1, | ||
|  |                                           LPCOMMTIMEOUTS a2) | ||
|  | { | ||
|  |     _PrintEnter("BuildCommDCBAndTimeoutsW(%ls,%p,%p)\n", a0, a1, a2); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_BuildCommDCBAndTimeoutsW(a0, a1, a2); | ||
|  |     } __finally { | ||
|  |         _PrintExit("BuildCommDCBAndTimeoutsW(,,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_BuildCommDCBW(LPCWSTR a0, | ||
|  |                                LPDCB a1) | ||
|  | { | ||
|  |     _PrintEnter("BuildCommDCBW(%ls,%p)\n", a0, a1); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_BuildCommDCBW(a0, a1); | ||
|  |     } __finally { | ||
|  |         _PrintExit("BuildCommDCBW(,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_ClearCommBreak(HANDLE a0) | ||
|  | { | ||
|  |     _PrintEnter("ClearCommBreak(%p)\n", a0); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_ClearCommBreak(a0); | ||
|  |     } __finally { | ||
|  |         _PrintExit("ClearCommBreak() -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_ClearCommError(HANDLE a0, | ||
|  |                                 LPDWORD a1, | ||
|  |                                 LPCOMSTAT a2) | ||
|  | { | ||
|  |     _PrintEnter("ClearCommError(%p,%p,%p)\n", a0, a1, a2); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_ClearCommError(a0, a1, a2); | ||
|  |     } __finally { | ||
|  |         _PrintExit("ClearCommError(,,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_CloseHandle(HANDLE a0) | ||
|  | { | ||
|  |     _PrintEnter("CloseHandle(%p)\n", a0); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_CloseHandle(a0); | ||
|  |     } __finally { | ||
|  |         _PrintExit("CloseHandle() -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | HANDLE WINAPI Mine_CreateFileA(LPCSTR a0, | ||
|  |                                DWORD a1, | ||
|  |                                DWORD a2, | ||
|  |                                LPSECURITY_ATTRIBUTES a3, | ||
|  |                                DWORD a4, | ||
|  |                                DWORD a5, | ||
|  |                                HANDLE a6) | ||
|  | { | ||
|  |     _PrintEnter("CreateFileA(%hs,%x,%x,%p,%x,%x,%p)\n", a0, a1, a2, a3, a4, a5, a6); | ||
|  | 
 | ||
|  |     HANDLE rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_CreateFileA(a0, a1, a2, a3, a4, a5, a6); | ||
|  |     } __finally { | ||
|  |         _PrintExit("CreateFileA(,,,,,,) -> %p\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | HANDLE WINAPI Mine_CreateFileW(LPCWSTR a0, | ||
|  |                                DWORD a1, | ||
|  |                                DWORD a2, | ||
|  |                                LPSECURITY_ATTRIBUTES a3, | ||
|  |                                DWORD a4, | ||
|  |                                DWORD a5, | ||
|  |                                HANDLE a6) | ||
|  | { | ||
|  |     _PrintEnter("CreateFileW(%ls,%x,%x,%p,%x,%x,%p)\n", a0, a1, a2, a3, a4, a5, a6); | ||
|  | 
 | ||
|  |     HANDLE rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_CreateFileW(a0, a1, a2, a3, a4, a5, a6); | ||
|  |     } __finally { | ||
|  |         _PrintExit("CreateFileW(,,,,,,) -> %p\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_EscapeCommFunction(HANDLE a0, | ||
|  |                                     DWORD a1) | ||
|  | { | ||
|  |     _PrintEnter("EscapeCommFunction(%p,%x)\n", a0, a1); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_EscapeCommFunction(a0, a1); | ||
|  |     } __finally { | ||
|  |         _PrintExit("EscapeCommFunction(,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_GetCommConfig(HANDLE a0, | ||
|  |                                LPCOMMCONFIG a1, | ||
|  |                                LPDWORD a2) | ||
|  | { | ||
|  |     _PrintEnter("GetCommConfig(%p,%p,%p)\n", a0, a1, a2); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_GetCommConfig(a0, a1, a2); | ||
|  |     } __finally { | ||
|  |         _PrintExit("GetCommConfig(,,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_GetCommMask(HANDLE a0, | ||
|  |                                 LPDWORD a1) | ||
|  | { | ||
|  |     _PrintEnter("GetCommMask(%p,%p)\n", a0, a1); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_GetCommMask(a0, a1); | ||
|  |     } __finally { | ||
|  |         _PrintExit("GetCommMask(,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_GetCommModemStatus(HANDLE a0, | ||
|  |                                     LPDWORD a1) | ||
|  | { | ||
|  |     _PrintEnter("GetCommModemStatus(%p,%p)\n", a0, a1); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_GetCommModemStatus(a0, a1); | ||
|  |     } __finally { | ||
|  |         _PrintExit("GetCommModemStatus(,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_GetCommProperties(HANDLE a0, | ||
|  |                                    LPCOMMPROP a1) | ||
|  | { | ||
|  |     _PrintEnter("GetCommProperties(%p,%p)\n", a0, a1); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_GetCommProperties(a0, a1); | ||
|  |     } __finally { | ||
|  |         _PrintExit("GetCommProperties(,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_GetCommState(HANDLE a0, | ||
|  |                               LPDCB a1) | ||
|  | { | ||
|  |     _PrintEnter("GetCommState(%p,%p)\n", a0, a1); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_GetCommState(a0, a1); | ||
|  |     } __finally { | ||
|  |         _PrintExit("GetCommState(,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_GetCommTimeouts(HANDLE a0, | ||
|  |                                  LPCOMMTIMEOUTS a1) | ||
|  | { | ||
|  |     _PrintEnter("GetCommTimeouts(%p,%p)\n", a0, a1); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_GetCommTimeouts(a0, a1); | ||
|  |     } __finally { | ||
|  |         _PrintExit("GetCommTimeouts(,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | DWORD WINAPI Mine_GetCurrentThreadId(void) | ||
|  | { | ||
|  |     _PrintEnter("GetCurrentThreadId()\n"); | ||
|  | 
 | ||
|  |     DWORD rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_GetCurrentThreadId(); | ||
|  |     } __finally { | ||
|  |         _PrintExit("GetCurrentThreadId() -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | DWORD WINAPI Mine_GetModuleFileNameW(HINSTANCE a0, | ||
|  |                                      LPWSTR a1, | ||
|  |                                      DWORD a2) | ||
|  | { | ||
|  |     _PrintEnter("GetModuleFileNameW(%p,%p,%x)\n", a0, a1, a2); | ||
|  | 
 | ||
|  |     DWORD rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_GetModuleFileNameW(a0, a1, a2); | ||
|  |     } __finally { | ||
|  |         _PrintExit("GetModuleFileNameW(,%ls,) -> %x\n", a1, rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_GetOverlappedResult(HANDLE a0, | ||
|  |                                      LPOVERLAPPED a1, | ||
|  |                                      LPDWORD a2, | ||
|  |                                      BOOL a3) | ||
|  | { | ||
|  |     _PrintEnter("GetOverlappedResult(%p,%p,%p,%x)\n", a0, a1, a2, a3); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_GetOverlappedResult(a0, a1, a2, a3); | ||
|  |     } __finally { | ||
|  |         _PrintExit("GetOverlappedResult(,,,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_PurgeComm(HANDLE a0, | ||
|  |                            DWORD a1) | ||
|  | { | ||
|  |     _PrintEnter("PurgeComm(%p,%x)\n", a0, a1); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_PurgeComm(a0, a1); | ||
|  |     } __finally { | ||
|  |         _PrintExit("PurgeComm(,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_ReadFile(HANDLE a0, | ||
|  |                           LPVOID a1, | ||
|  |                           DWORD a2, | ||
|  |                           LPDWORD a3, | ||
|  |                           LPOVERLAPPED a4) | ||
|  | { | ||
|  |     _PrintEnter("ReadFile(%p,%p,%x,%p,%p)\n", a0, a1, a2, a3, a4); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_ReadFile(a0, a1, a2, a3, a4); | ||
|  |     } __finally { | ||
|  |         _PrintExit("ReadFile(,,,,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_SetCommBreak(HANDLE a0) | ||
|  | { | ||
|  |     _PrintEnter("SetCommBreak(%p)\n", a0); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_SetCommBreak(a0); | ||
|  |     } __finally { | ||
|  |         _PrintExit("SetCommBreak() -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_SetCommConfig(HANDLE a0, | ||
|  |                                LPCOMMCONFIG a1, | ||
|  |                                DWORD a2) | ||
|  | { | ||
|  |     _PrintEnter("SetCommConfig(%p,%p,%x)\n", a0, a1, a2); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_SetCommConfig(a0, a1, a2); | ||
|  |     } __finally { | ||
|  |         _PrintExit("SetCommConfig(,,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_SetCommMask(HANDLE a0, | ||
|  |                              DWORD a1) | ||
|  | { | ||
|  |     _PrintEnter("SetCommMask(%p,%x)\n", a0, a1); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_SetCommMask(a0, a1); | ||
|  |     } __finally { | ||
|  |         _PrintExit("SetCommMask(,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_SetCommState(HANDLE a0, | ||
|  |                               LPDCB a1) | ||
|  | { | ||
|  |     _PrintEnter("SetCommState(%p,%p)\n", a0, a1); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_SetCommState(a0, a1); | ||
|  |     } __finally { | ||
|  |         _PrintExit("SetCommState(,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_SetCommTimeouts(HANDLE a0, | ||
|  |                                  LPCOMMTIMEOUTS a1) | ||
|  | { | ||
|  |     _PrintEnter("SetCommTimeouts(%p,%p)\n", a0, a1); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_SetCommTimeouts(a0, a1); | ||
|  |     } __finally { | ||
|  |         _PrintExit("SetCommTimeouts(,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_SetupComm(HANDLE a0, | ||
|  |                            DWORD a1, | ||
|  |                            DWORD a2) | ||
|  | { | ||
|  |     _PrintEnter("SetupComm(%p,%x,%x)\n", a0, a1, a2); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_SetupComm(a0, a1, a2); | ||
|  |     } __finally { | ||
|  |         _PrintExit("SetupComm(,,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_TransmitCommChar(HANDLE a0, | ||
|  |                                   char a1) | ||
|  | { | ||
|  |     _PrintEnter("TransmitCommChar(%p,%x)\n", a0, a1); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_TransmitCommChar(a0, a1); | ||
|  |     } __finally { | ||
|  |         _PrintExit("TransmitCommChar(,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_WaitCommEvent(HANDLE a0, | ||
|  |                                LPDWORD a1, | ||
|  |                                LPOVERLAPPED a2) | ||
|  | { | ||
|  |     _PrintEnter("WaitCommEvent(%p,%p,%p)\n", a0, a1, a2); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_WaitCommEvent(a0, a1, a2); | ||
|  |     } __finally { | ||
|  |         _PrintExit("WaitCommEvent(,,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI Mine_WriteFile(HANDLE a0, | ||
|  |                            LPCVOID a1, | ||
|  |                            DWORD a2, | ||
|  |                            LPDWORD a3, | ||
|  |                            LPOVERLAPPED a4) | ||
|  | { | ||
|  |     _PrintEnter("WriteFile(%p,%p,%x,%p,%p)\n", a0, a1, a2, a3, a4); | ||
|  | 
 | ||
|  |     BOOL rv = 0; | ||
|  |     __try { | ||
|  |         _PrintDump(a0, (PCHAR)a1, a2); | ||
|  |         rv = Real_WriteFile(a0, a1, a2, a3, a4); | ||
|  |     } __finally { | ||
|  |         _PrintExit("WriteFile(,,,,) -> %x\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | /////////////////////////////////////////////////////////////
 | ||
|  | // AttachDetours
 | ||
|  | //
 | ||
|  | PCHAR DetRealName(PCHAR psz) | ||
|  | { | ||
|  |     PCHAR pszBeg = psz; | ||
|  |     // Move to end of name.
 | ||
|  |     while (*psz) { | ||
|  |         psz++; | ||
|  |     } | ||
|  |     // Move back through A-Za-z0-9 names.
 | ||
|  |     while (psz > pszBeg && | ||
|  |            ((psz[-1] >= 'A' && psz[-1] <= 'Z') || | ||
|  |             (psz[-1] >= 'a' && psz[-1] <= 'z') || | ||
|  |             (psz[-1] >= '0' && psz[-1] <= '9'))) { | ||
|  |         psz--; | ||
|  |     } | ||
|  |     return psz; | ||
|  | } | ||
|  | 
 | ||
|  | VOID DetAttach(PVOID *ppbReal, PVOID pbMine, PCHAR psz) | ||
|  | { | ||
|  |     LONG l = DetourAttach(ppbReal, pbMine); | ||
|  |     if (l != 0) { | ||
|  |         Syelog(SYELOG_SEVERITY_NOTICE, | ||
|  |                "Attach failed: `%s': error %d\n", DetRealName(psz), l); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | VOID DetDetach(PVOID *ppbReal, PVOID pbMine, PCHAR psz) | ||
|  | { | ||
|  |     LONG l = DetourDetach(ppbReal, pbMine); | ||
|  |     if (l != 0) { | ||
|  |         Syelog(SYELOG_SEVERITY_NOTICE, | ||
|  |                "Detach failed: `%s': error %d\n", DetRealName(psz), l); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | #define ATTACH(x)       DetAttach(&(PVOID&)Real_##x,Mine_##x,#x)
 | ||
|  | #define DETACH(x)       DetDetach(&(PVOID&)Real_##x,Mine_##x,#x)
 | ||
|  | 
 | ||
|  | LONG AttachDetours(VOID) | ||
|  | { | ||
|  |     DetourTransactionBegin(); | ||
|  |     DetourUpdateThread(GetCurrentThread()); | ||
|  | 
 | ||
|  |     ATTACH(BuildCommDCBA); | ||
|  |     ATTACH(BuildCommDCBAndTimeoutsA); | ||
|  |     ATTACH(BuildCommDCBAndTimeoutsW); | ||
|  |     ATTACH(BuildCommDCBW); | ||
|  |     ATTACH(ClearCommBreak); | ||
|  |     ATTACH(ClearCommError); | ||
|  |     ATTACH(CloseHandle); | ||
|  |     ATTACH(CreateFileA); | ||
|  |     ATTACH(CreateFileW); | ||
|  |     ATTACH(EscapeCommFunction); | ||
|  |     ATTACH(GetCommConfig); | ||
|  |     ATTACH(GetCommMask); | ||
|  |     ATTACH(GetCommModemStatus); | ||
|  |     ATTACH(GetCommProperties); | ||
|  |     ATTACH(GetCommState); | ||
|  |     ATTACH(GetCommTimeouts); | ||
|  |     ATTACH(GetCurrentThreadId); | ||
|  |     ATTACH(GetModuleFileNameW); | ||
|  |     ATTACH(GetOverlappedResult); | ||
|  |     ATTACH(PurgeComm); | ||
|  |     ATTACH(ReadFile); | ||
|  |     ATTACH(SetCommBreak); | ||
|  |     ATTACH(SetCommConfig); | ||
|  |     ATTACH(SetCommMask); | ||
|  |     ATTACH(SetCommState); | ||
|  |     ATTACH(SetCommTimeouts); | ||
|  |     ATTACH(SetupComm); | ||
|  |     ATTACH(TransmitCommChar); | ||
|  |     ATTACH(WaitCommEvent); | ||
|  |     ATTACH(WriteFile); | ||
|  | 
 | ||
|  |     return DetourTransactionCommit(); | ||
|  | } | ||
|  | 
 | ||
|  | LONG DetachDetours(VOID) | ||
|  | { | ||
|  |     DetourTransactionBegin(); | ||
|  |     DetourUpdateThread(GetCurrentThread()); | ||
|  | 
 | ||
|  |     DETACH(BuildCommDCBA); | ||
|  |     DETACH(BuildCommDCBAndTimeoutsA); | ||
|  |     DETACH(BuildCommDCBAndTimeoutsW); | ||
|  |     DETACH(BuildCommDCBW); | ||
|  |     DETACH(ClearCommBreak); | ||
|  |     DETACH(ClearCommError); | ||
|  |     DETACH(CloseHandle); | ||
|  |     DETACH(CreateFileA); | ||
|  |     DETACH(CreateFileW); | ||
|  |     DETACH(EscapeCommFunction); | ||
|  |     DETACH(GetCommConfig); | ||
|  |     DETACH(GetCommMask); | ||
|  |     DETACH(GetCommModemStatus); | ||
|  |     DETACH(GetCommProperties); | ||
|  |     DETACH(GetCommState); | ||
|  |     DETACH(GetCommTimeouts); | ||
|  |     DETACH(GetCurrentThreadId); | ||
|  |     DETACH(GetModuleFileNameW); | ||
|  |     DETACH(GetOverlappedResult); | ||
|  |     DETACH(PurgeComm); | ||
|  |     DETACH(ReadFile); | ||
|  |     DETACH(SetCommBreak); | ||
|  |     DETACH(SetCommConfig); | ||
|  |     DETACH(SetCommMask); | ||
|  |     DETACH(SetCommState); | ||
|  |     DETACH(SetCommTimeouts); | ||
|  |     DETACH(SetupComm); | ||
|  |     DETACH(TransmitCommChar); | ||
|  |     DETACH(WaitCommEvent); | ||
|  |     DETACH(WriteFile); | ||
|  | 
 | ||
|  |     return DetourTransactionCommit(); | ||
|  | } | ||
|  | 
 | ||
|  | /////////////////////////////////////////////////////////////
 | ||
|  | // Detours
 | ||
|  | //
 | ||
|  | 
 | ||
|  | VOID _PrintDump(HANDLE h, PCHAR pszData, INT cbData) | ||
|  | { | ||
|  |     if (pszData && cbData > 0) { | ||
|  |         CHAR szBuffer[256]; | ||
|  |         PCHAR pszBuffer = szBuffer; | ||
|  |         INT cbBuffer = 0; | ||
|  |         INT nLines = 0; | ||
|  | 
 | ||
|  |         while (cbData > 0) { | ||
|  |             if (nLines > 20) { | ||
|  |                 *pszBuffer++ = '.'; | ||
|  |                 *pszBuffer++ = '.'; | ||
|  |                 *pszBuffer++ = '.'; | ||
|  |                 cbBuffer += 3; | ||
|  |                 break; | ||
|  |             } | ||
|  | 
 | ||
|  |             if (*pszData == '\t') { | ||
|  |                 *pszBuffer++ = '\\'; | ||
|  |                 *pszBuffer++ = 't'; | ||
|  |                 cbBuffer += 2; | ||
|  |                 pszData++; | ||
|  |                 cbData--; | ||
|  |                 continue; | ||
|  |             } | ||
|  |             if (*pszData == '\r') { | ||
|  |                 *pszBuffer++ = '\\'; | ||
|  |                 *pszBuffer++ = 'r'; | ||
|  |                 cbBuffer += 2; | ||
|  |                 pszData++; | ||
|  |                 cbData--; | ||
|  |                 continue; | ||
|  |             } | ||
|  |             else if (*pszData == '\n') { | ||
|  |                 *pszBuffer++ = '\\'; | ||
|  |                 *pszBuffer++ = 'n'; | ||
|  |                 cbBuffer += 2; | ||
|  |                 *pszBuffer++ = '\0'; | ||
|  |                 _Print("%p:   %hs\n", h, szBuffer); | ||
|  |                 nLines++; | ||
|  |                 pszBuffer = szBuffer; | ||
|  |                 cbBuffer = 0; | ||
|  |                 pszData++; | ||
|  |                 cbData--; | ||
|  |                 continue; | ||
|  |             } | ||
|  |             else if (cbBuffer >= 80) { | ||
|  |                 *pszBuffer++ = '\0'; | ||
|  |                 _Print("%p:   %hs\n", h, szBuffer); | ||
|  |                 nLines++; | ||
|  |                 pszBuffer = szBuffer; | ||
|  |                 cbBuffer = 0; | ||
|  |             } | ||
|  | 
 | ||
|  |             if (*pszData < ' ' || *pszData >= 127) { | ||
|  |                 *pszBuffer++ = '\\'; | ||
|  |                 *pszBuffer++ = 'x'; | ||
|  |                 *pszBuffer++ = "0123456789ABCDEF"[(*pszData & 0xf0) >> 4]; | ||
|  |                 *pszBuffer++ = "0123456789ABCDEF"[(*pszData & 0x0f)]; | ||
|  |                 cbBuffer += 4; | ||
|  |             } | ||
|  |             else { | ||
|  |                 *pszBuffer++ = *pszData; | ||
|  |             } | ||
|  |             cbBuffer++; | ||
|  |             pszData++; | ||
|  |             cbData--; | ||
|  |         } | ||
|  | 
 | ||
|  |         if (cbBuffer > 0) { | ||
|  |             *pszBuffer++ = '\0'; | ||
|  |             _Print("%p:   %hs\n", h, szBuffer); | ||
|  |         } | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | ////////////////////////////////////////////////////////////// Logging System.
 | ||
|  | //
 | ||
|  | static BOOL s_bLog = 1; | ||
|  | static LONG s_nTlsIndent = -1; | ||
|  | static LONG s_nTlsThread = -1; | ||
|  | static LONG s_nThreadCnt = 0; | ||
|  | 
 | ||
|  | VOID _PrintEnter(const CHAR *psz, ...) | ||
|  | { | ||
|  |     DWORD dwErr = GetLastError(); | ||
|  | 
 | ||
|  |     LONG nIndent = 0; | ||
|  |     LONG nThread = 0; | ||
|  |     if (s_nTlsIndent >= 0) { | ||
|  |         nIndent = (LONG)(LONG_PTR)TlsGetValue(s_nTlsIndent); | ||
|  |         TlsSetValue(s_nTlsIndent, (PVOID)(LONG_PTR)(nIndent + 1)); | ||
|  |     } | ||
|  |     if (s_nTlsThread >= 0) { | ||
|  |         nThread = (LONG)(LONG_PTR)TlsGetValue(s_nTlsThread); | ||
|  |     } | ||
|  | 
 | ||
|  |     if (s_bLog && psz) { | ||
|  |         CHAR szBuf[1024]; | ||
|  |         PCHAR pszBuf = szBuf; | ||
|  |         PCHAR pszEnd = szBuf + ARRAYSIZE(szBuf) - 1; | ||
|  |         LONG nLen = (nIndent > 0) ? (nIndent < 35 ? nIndent * 2 : 70) : 0; | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 100) % 10)); | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 10) % 10)); | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 1) % 10)); | ||
|  |         *pszBuf++ = ' '; | ||
|  |         while (nLen-- > 0) { | ||
|  |             *pszBuf++ = ' '; | ||
|  |         } | ||
|  | 
 | ||
|  |         va_list  args; | ||
|  |         va_start(args, psz); | ||
|  | 
 | ||
|  |         while ((*pszBuf++ = *psz++) != 0 && pszBuf < pszEnd) { | ||
|  |             // Copy characters.
 | ||
|  |         } | ||
|  |         *pszEnd = '\0'; | ||
|  |         SyelogV(SYELOG_SEVERITY_INFORMATION, | ||
|  |                 szBuf, args); | ||
|  | 
 | ||
|  |         va_end(args); | ||
|  |     } | ||
|  |     SetLastError(dwErr); | ||
|  | } | ||
|  | 
 | ||
|  | VOID _PrintExit(const CHAR *psz, ...) | ||
|  | { | ||
|  |     DWORD dwErr = GetLastError(); | ||
|  | 
 | ||
|  |     LONG nIndent = 0; | ||
|  |     LONG nThread = 0; | ||
|  |     if (s_nTlsIndent >= 0) { | ||
|  |         nIndent = (LONG)(LONG_PTR)TlsGetValue(s_nTlsIndent) - 1; | ||
|  |         ASSERT(nIndent >= 0); | ||
|  |         TlsSetValue(s_nTlsIndent, (PVOID)(LONG_PTR)nIndent); | ||
|  |     } | ||
|  |     if (s_nTlsThread >= 0) { | ||
|  |         nThread = (LONG)(LONG_PTR)TlsGetValue(s_nTlsThread); | ||
|  |     } | ||
|  | 
 | ||
|  |     if (s_bLog && psz) { | ||
|  |         CHAR szBuf[1024]; | ||
|  |         PCHAR pszBuf = szBuf; | ||
|  |         PCHAR pszEnd = szBuf + ARRAYSIZE(szBuf) - 1; | ||
|  |         LONG nLen = (nIndent > 0) ? (nIndent < 35 ? nIndent * 2 : 70) : 0; | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 100) % 10)); | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 10) % 10)); | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 1) % 10)); | ||
|  |         *pszBuf++ = ' '; | ||
|  |         while (nLen-- > 0) { | ||
|  |             *pszBuf++ = ' '; | ||
|  |         } | ||
|  | 
 | ||
|  |         va_list  args; | ||
|  |         va_start(args, psz); | ||
|  | 
 | ||
|  |         while ((*pszBuf++ = *psz++) != 0 && pszBuf < pszEnd) { | ||
|  |             // Copy characters.
 | ||
|  |         } | ||
|  |         *pszEnd = '\0'; | ||
|  |         SyelogV(SYELOG_SEVERITY_INFORMATION, | ||
|  |                 szBuf, args); | ||
|  | 
 | ||
|  |         va_end(args); | ||
|  |     } | ||
|  |     SetLastError(dwErr); | ||
|  | } | ||
|  | 
 | ||
|  | VOID _Print(const CHAR *psz, ...) | ||
|  | { | ||
|  |     DWORD dwErr = GetLastError(); | ||
|  | 
 | ||
|  |     LONG nIndent = 0; | ||
|  |     LONG nThread = 0; | ||
|  |     if (s_nTlsIndent >= 0) { | ||
|  |         nIndent = (LONG)(LONG_PTR)TlsGetValue(s_nTlsIndent); | ||
|  |     } | ||
|  |     if (s_nTlsThread >= 0) { | ||
|  |         nThread = (LONG)(LONG_PTR)TlsGetValue(s_nTlsThread); | ||
|  |     } | ||
|  | 
 | ||
|  |     if (s_bLog && psz) { | ||
|  |         CHAR szBuf[1024]; | ||
|  |         PCHAR pszBuf = szBuf; | ||
|  |         PCHAR pszEnd = szBuf + ARRAYSIZE(szBuf) - 1; | ||
|  |         LONG nLen = (nIndent > 0) ? (nIndent < 35 ? nIndent * 2 : 70) : 0; | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 100) % 10)); | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 10) % 10)); | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 1) % 10)); | ||
|  |         *pszBuf++ = ' '; | ||
|  |         while (nLen-- > 0) { | ||
|  |             *pszBuf++ = ' '; | ||
|  |         } | ||
|  | 
 | ||
|  |         va_list  args; | ||
|  |         va_start(args, psz); | ||
|  | 
 | ||
|  |         while ((*pszBuf++ = *psz++) != 0 && pszBuf < pszEnd) { | ||
|  |             // Copy characters.
 | ||
|  |         } | ||
|  |         *pszEnd = '\0'; | ||
|  |         SyelogV(SYELOG_SEVERITY_INFORMATION, | ||
|  |                 szBuf, args); | ||
|  | 
 | ||
|  |         va_end(args); | ||
|  |     } | ||
|  | 
 | ||
|  |     SetLastError(dwErr); | ||
|  | } | ||
|  | 
 | ||
|  | VOID AssertMessage(CONST PCHAR pszMsg, CONST PCHAR pszFile, ULONG nLine) | ||
|  | { | ||
|  |     Syelog(SYELOG_SEVERITY_FATAL, | ||
|  |            "ASSERT(%s) failed in %s, line %d.\n", pszMsg, pszFile, nLine); | ||
|  | } | ||
|  | 
 | ||
|  | //////////////////////////////////////////////////////////////////////////////
 | ||
|  | //
 | ||
|  | // DLL module information
 | ||
|  | //
 | ||
|  | BOOL ThreadAttach(HMODULE hDll) | ||
|  | { | ||
|  |     (void)hDll; | ||
|  | 
 | ||
|  |     if (s_nTlsIndent >= 0) { | ||
|  |         TlsSetValue(s_nTlsIndent, (PVOID)0); | ||
|  |     } | ||
|  |     if (s_nTlsThread >= 0) { | ||
|  |         LONG nThread = InterlockedIncrement(&s_nThreadCnt); | ||
|  |         TlsSetValue(s_nTlsThread, (PVOID)(LONG_PTR)nThread); | ||
|  |     } | ||
|  |     return TRUE; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL ThreadDetach(HMODULE hDll) | ||
|  | { | ||
|  |     (void)hDll; | ||
|  | 
 | ||
|  |     if (s_nTlsIndent >= 0) { | ||
|  |         TlsSetValue(s_nTlsIndent, (PVOID)0); | ||
|  |     } | ||
|  |     if (s_nTlsThread >= 0) { | ||
|  |         TlsSetValue(s_nTlsThread, (PVOID)0); | ||
|  |     } | ||
|  |     return TRUE; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL ProcessAttach(HMODULE hDll) | ||
|  | { | ||
|  |     s_bLog = FALSE; | ||
|  |     s_nTlsIndent = TlsAlloc(); | ||
|  |     s_nTlsThread = TlsAlloc(); | ||
|  | 
 | ||
|  |     WCHAR wzExePath[MAX_PATH]; | ||
|  | 
 | ||
|  |     s_hInst = hDll; | ||
|  |     Real_GetModuleFileNameA(s_hInst, s_szDllPath, ARRAYSIZE(s_szDllPath)); | ||
|  |     Real_GetModuleFileNameW(NULL, wzExePath, ARRAYSIZE(wzExePath)); | ||
|  | 
 | ||
|  |     SyelogOpen("trcser" DETOURS_STRINGIFY(DETOURS_BITS), SYELOG_FACILITY_APPLICATION); | ||
|  |     Syelog(SYELOG_SEVERITY_INFORMATION, | ||
|  |            "##################################################################\n"); | ||
|  |     Syelog(SYELOG_SEVERITY_INFORMATION, | ||
|  |            "### %ls\n", wzExePath); | ||
|  |     LONG error = AttachDetours(); | ||
|  |     if (error != NO_ERROR) { | ||
|  |         Syelog(SYELOG_SEVERITY_FATAL, "### Error attaching detours: %d\n", error); | ||
|  |     } | ||
|  | 
 | ||
|  |     ThreadAttach(hDll); | ||
|  | 
 | ||
|  |     s_bLog = TRUE; | ||
|  |     return TRUE; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL ProcessDetach(HMODULE hDll) | ||
|  | { | ||
|  |     ThreadDetach(hDll); | ||
|  |     s_bLog = FALSE; | ||
|  | 
 | ||
|  |     LONG error = DetachDetours(); | ||
|  |     if (error != NO_ERROR) { | ||
|  |         Syelog(SYELOG_SEVERITY_FATAL, "### Error detaching detours: %d\n", error); | ||
|  |     } | ||
|  | 
 | ||
|  |     Syelog(SYELOG_SEVERITY_NOTICE, "### Closing.\n"); | ||
|  |     SyelogClose(FALSE); | ||
|  | 
 | ||
|  |     if (s_nTlsIndent >= 0) { | ||
|  |         TlsFree(s_nTlsIndent); | ||
|  |     } | ||
|  |     if (s_nTlsThread >= 0) { | ||
|  |         TlsFree(s_nTlsThread); | ||
|  |     } | ||
|  |     return TRUE; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason, PVOID lpReserved) | ||
|  | { | ||
|  |     (void)hModule; | ||
|  |     (void)lpReserved; | ||
|  | 
 | ||
|  |     if (DetourIsHelperProcess()) { | ||
|  |         return TRUE; | ||
|  |     } | ||
|  | 
 | ||
|  |     switch (dwReason) { | ||
|  |       case DLL_PROCESS_ATTACH: | ||
|  |         DetourRestoreAfterWith(); | ||
|  |         return ProcessAttach(hModule); | ||
|  |       case DLL_PROCESS_DETACH: | ||
|  |         return ProcessDetach(hModule); | ||
|  |       case DLL_THREAD_ATTACH: | ||
|  |         return ThreadAttach(hModule); | ||
|  |       case DLL_THREAD_DETACH: | ||
|  |         return ThreadDetach(hModule); | ||
|  |     } | ||
|  |     return TRUE; | ||
|  | } | ||
|  | //
 | ||
|  | ///////////////////////////////////////////////////////////////// End of File.
 |