diff options
Diffstat (limited to 'samples/tracemem/trcmem.cpp')
-rw-r--r-- | samples/tracemem/trcmem.cpp | 521 |
1 files changed, 521 insertions, 0 deletions
diff --git a/samples/tracemem/trcmem.cpp b/samples/tracemem/trcmem.cpp new file mode 100644 index 0000000..85f72b9 --- /dev/null +++ b/samples/tracemem/trcmem.cpp @@ -0,0 +1,521 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Detours Test Program (trcmem.cpp of trcmem.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 _PrintEnter(const CHAR *psz, ...); +VOID _PrintExit(const CHAR *psz, ...); +VOID _Print(const CHAR *psz, ...); +VOID _VPrint(PCSTR msg, va_list args, PCHAR pszBuf, LONG cbBuf); + +VOID AssertMessage(CONST PCHAR pszMsg, CONST PCHAR pszFile, ULONG nLine); + +////////////////////////////////////////////////////////////////////////////// +// Trampolines +// +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; +} + +#if _MSC_VER < 1300 +LPVOID (WINAPI * + Real_HeapAlloc)(HANDLE hHeap, DWORD dwFlags, DWORD dwBytes) + = HeapAlloc; +#else +LPVOID (WINAPI * + Real_HeapAlloc)(HANDLE hHeap, DWORD dwFlags, DWORD_PTR dwBytes) + = HeapAlloc; +#endif + +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; + +////////////////////////////////////////////////////////////////////////////// +// Detours +// +#if _MSC_VER < 1300 +LPVOID WINAPI Mine_HeapAlloc(HANDLE hHeap, DWORD dwFlags, DWORD dwBytes) +#else +LPVOID WINAPI Mine_HeapAlloc(HANDLE hHeap, DWORD dwFlags, DWORD_PTR dwBytes) +#endif +{ + _PrintEnter("HeapAlloc(%p, %x, %p))\n", hHeap, dwFlags, dwBytes); + + LPVOID rv = 0; + __try { + rv = Real_HeapAlloc(hHeap, dwFlags, dwBytes); + } __finally { + _PrintExit("HeapAlloc() -> %p\n", rv); + }; + return rv; +} + +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; +} + +////////////////////////////////////////////////////////////////////////////// +// 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(CreateProcessW); + ATTACH(HeapAlloc); + + return DetourTransactionCommit(); +} + +LONG DetachDetours(VOID) +{ + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + + DETACH(CreateProcessW); + DETACH(HeapAlloc); + + return DetourTransactionCommit(); +} + +////////////////////////////////////////////////////////////// Logging System. +// +static BOOL s_bLog = FALSE; +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("trcmem" 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. |