aboutsummaryrefslogtreecommitdiffhomepage
path: root/samples/tracemem/trcmem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'samples/tracemem/trcmem.cpp')
-rw-r--r--samples/tracemem/trcmem.cpp521
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.