aboutsummaryrefslogtreecommitdiffhomepage
path: root/ext/detours/samples/traceapi/trcapi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ext/detours/samples/traceapi/trcapi.cpp')
-rw-r--r--ext/detours/samples/traceapi/trcapi.cpp473
1 files changed, 473 insertions, 0 deletions
diff --git a/ext/detours/samples/traceapi/trcapi.cpp b/ext/detours/samples/traceapi/trcapi.cpp
new file mode 100644
index 0000000..e7b7240
--- /dev/null
+++ b/ext/detours/samples/traceapi/trcapi.cpp
@@ -0,0 +1,473 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// Detours Test Program (trcapi.cpp of trcapi.dll)
+//
+// Microsoft Research Detours Package
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+#undef WIN32_LEAN_AND_MEAN
+#define _WIN32_WINNT 0x400
+#define WIN32
+#define NT
+#define _WINSOCK_DEPRECATED_NO_WARNINGS
+
+#define DBG_TRACE 0
+
+#if _MSC_VER >= 1300
+#include <winsock2.h>
+#endif
+#include <windows.h>
+#include <stdio.h>
+#pragma warning(push)
+#if _MSC_VER > 1400
+#pragma warning(disable:6102 6103) // /analyze warnings
+#endif
+#include <strsafe.h>
+#pragma warning(pop)
+#include "detours.h"
+#include "syelog.h"
+
+#if (_MSC_VER < 1299)
+#define LONG_PTR LONG
+#define ULONG_PTR ULONG
+#define PLONG_PTR PLONG
+#define PULONG_PTR PULONG
+#define INT_PTR INT
+#define UINT_PTR UINT
+#define PINT_PTR PINT
+#define PUINT_PTR PUINT
+#define DWORD_PTR DWORD
+#define PDWORD_PTR PDWORD
+#endif
+
+#pragma warning(disable:4996) // We don't care about deprecated APIs.
+
+//////////////////////////////////////////////////////////////////////////////
+#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 WCHAR s_wzDllPath[MAX_PATH];
+static CHAR s_szDllPath[MAX_PATH];
+
+BOOL ProcessEnumerate();
+BOOL InstanceEnumerate(HINSTANCE hInst);
+
+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" {
+ // Trampolines for SYELOG library.
+ //
+ extern HANDLE (WINAPI *Real_CreateFileW)(LPCWSTR a0, DWORD a1, DWORD a2,
+ LPSECURITY_ATTRIBUTES a3, DWORD a4, DWORD a5,
+ HANDLE a6);
+ extern BOOL (WINAPI *Real_WriteFile)(HANDLE hFile,
+ LPCVOID lpBuffer,
+ DWORD nNumberOfBytesToWrite,
+ LPDWORD lpNumberOfBytesWritten,
+ LPOVERLAPPED lpOverlapped);
+ extern BOOL (WINAPI *Real_FlushFileBuffers)(HANDLE hFile);
+ extern BOOL (WINAPI *Real_CloseHandle)(HANDLE hObject);
+ extern BOOL (WINAPI *Real_WaitNamedPipeW)(LPCWSTR lpNamedPipeName, DWORD nTimeOut);
+ extern BOOL (WINAPI *Real_SetNamedPipeHandleState)(HANDLE hNamedPipe,
+ LPDWORD lpMode,
+ LPDWORD lpMaxCollectionCount,
+ LPDWORD lpCollectDataTimeout);
+ extern DWORD (WINAPI *Real_GetCurrentProcessId)(VOID);
+ extern VOID (WINAPI *Real_GetSystemTimeAsFileTime)(LPFILETIME lpSystemTimeAsFileTime);
+
+ VOID ( WINAPI * Real_InitializeCriticalSection)(LPCRITICAL_SECTION lpSection)
+ = InitializeCriticalSection;
+ VOID ( WINAPI * Real_EnterCriticalSection)(LPCRITICAL_SECTION lpSection)
+ = EnterCriticalSection;
+ VOID ( WINAPI * Real_LeaveCriticalSection)(LPCRITICAL_SECTION lpSection)
+ = LeaveCriticalSection;
+}
+
+#include "_win32.cpp"
+
+////////////////////////////////////////////////////////////// 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++ = ' ';
+ }
+ *pszBuf++ = '+';
+ *pszBuf = '\0';
+
+ 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_ALWAYS(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 pszEnd = szBuf + ARRAYSIZE(szBuf) - 1;
+ PCHAR pszBuf = szBuf;
+ 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++ = ' ';
+ }
+ *pszBuf++ = '-';
+ *pszBuf = '\0';
+
+ 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 pszEnd = szBuf + ARRAYSIZE(szBuf) - 1;
+ PCHAR pszBuf = szBuf;
+ 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++ = ' ';
+ }
+ *pszBuf = '\0';
+
+ 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);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+PIMAGE_NT_HEADERS NtHeadersForInstance(HINSTANCE hInst)
+{
+ PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hInst;
+ __try {
+ if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
+ SetLastError(ERROR_BAD_EXE_FORMAT);
+ return NULL;
+ }
+
+ PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
+ pDosHeader->e_lfanew);
+ if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
+ SetLastError(ERROR_INVALID_EXE_SIGNATURE);
+ return NULL;
+ }
+ if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
+ SetLastError(ERROR_EXE_MARKED_INVALID);
+ return NULL;
+ }
+ return pNtHeader;
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+ }
+ SetLastError(ERROR_EXE_MARKED_INVALID);
+
+ return NULL;
+}
+
+BOOL InstanceEnumerate(HINSTANCE hInst)
+{
+ WCHAR wzDllName[MAX_PATH];
+
+ PIMAGE_NT_HEADERS pinh = NtHeadersForInstance(hInst);
+ if (pinh && Real_GetModuleFileNameW(hInst, wzDllName, ARRAYSIZE(wzDllName))) {
+ Syelog(SYELOG_SEVERITY_INFORMATION, "### %p: %ls\n", hInst, wzDllName);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL ProcessEnumerate()
+{
+ Syelog(SYELOG_SEVERITY_INFORMATION,
+ "######################################################### Binaries\n");
+
+ PBYTE pbNext;
+ for (PBYTE pbRegion = (PBYTE)0x10000;; pbRegion = pbNext) {
+ MEMORY_BASIC_INFORMATION mbi;
+ ZeroMemory(&mbi, sizeof(mbi));
+
+ if (VirtualQuery((PVOID)pbRegion, &mbi, sizeof(mbi)) <= 0) {
+ break;
+ }
+ pbNext = (PBYTE)mbi.BaseAddress + mbi.RegionSize;
+
+ // Skip free regions, reserver regions, and guard pages.
+ //
+ if (mbi.State == MEM_FREE || mbi.State == MEM_RESERVE) {
+ continue;
+ }
+ if (mbi.Protect & PAGE_GUARD || mbi.Protect & PAGE_NOCACHE) {
+ continue;
+ }
+ if (mbi.Protect == PAGE_NOACCESS) {
+ continue;
+ }
+
+ // Skip over regions from the same allocation...
+ {
+ MEMORY_BASIC_INFORMATION mbiStep;
+
+ while (VirtualQuery((PVOID)pbNext, &mbiStep, sizeof(mbiStep)) > 0) {
+ if ((PBYTE)mbiStep.AllocationBase != pbRegion) {
+ break;
+ }
+ pbNext = (PBYTE)mbiStep.BaseAddress + mbiStep.RegionSize;
+ mbi.Protect |= mbiStep.Protect;
+ }
+ }
+
+ WCHAR wzDllName[MAX_PATH];
+ PIMAGE_NT_HEADERS pinh = NtHeadersForInstance((HINSTANCE)pbRegion);
+
+ if (pinh &&
+ Real_GetModuleFileNameW((HINSTANCE)pbRegion,wzDllName,ARRAYSIZE(wzDllName))) {
+
+ Syelog(SYELOG_SEVERITY_INFORMATION,
+ "### %p..%p: %ls\n", pbRegion, pbNext, wzDllName);
+ }
+ else {
+ Syelog(SYELOG_SEVERITY_INFORMATION,
+ "### %p..%p: State=%04x, Protect=%08x\n",
+ pbRegion, pbNext, mbi.State, mbi.Protect);
+ }
+ }
+ Syelog(SYELOG_SEVERITY_INFORMATION, "###\n");
+
+ LPVOID lpvEnv = Real_GetEnvironmentStrings();
+ Syelog(SYELOG_SEVERITY_INFORMATION, "### Env= %08x [%08x %08x]\n",
+ lpvEnv, ((PVOID*)lpvEnv)[0], ((PVOID*)lpvEnv)[1]);
+
+ return TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// 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();
+ ThreadAttach(hDll);
+
+ WCHAR wzExeName[MAX_PATH];
+
+ s_hInst = hDll;
+ Real_GetModuleFileNameW(hDll, s_wzDllPath, ARRAYSIZE(s_wzDllPath));
+ Real_GetModuleFileNameW(NULL, wzExeName, ARRAYSIZE(wzExeName));
+ StringCchPrintfA(s_szDllPath, ARRAYSIZE(s_szDllPath), "%ls", s_wzDllPath);
+
+ SyelogOpen("trcapi" DETOURS_STRINGIFY(DETOURS_BITS), SYELOG_FACILITY_APPLICATION);
+ ProcessEnumerate();
+
+ LONG error = AttachDetours();
+ if (error != NO_ERROR) {
+ Syelog(SYELOG_SEVERITY_FATAL, "### Error attaching detours: %d\n", error);
+ }
+
+ 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;
+ BOOL ret;
+
+ if (DetourIsHelperProcess()) {
+ return TRUE;
+ }
+
+ switch (dwReason) {
+ case DLL_PROCESS_ATTACH:
+ DetourRestoreAfterWith();
+ OutputDebugStringA("trcapi" DETOURS_STRINGIFY(DETOURS_BITS) ".dll:"
+ " DllMain DLL_PROCESS_ATTACH\n");
+ return ProcessAttach(hModule);
+ case DLL_PROCESS_DETACH:
+ ret = ProcessDetach(hModule);
+ OutputDebugStringA("trcapi" DETOURS_STRINGIFY(DETOURS_BITS) ".dll:"
+ " DllMain DLL_PROCESS_DETACH\n");
+ return ret;
+ case DLL_THREAD_ATTACH:
+ OutputDebugStringA("trcapi" DETOURS_STRINGIFY(DETOURS_BITS) ".dll:"
+ " DllMain DLL_THREAD_ATTACH\n");
+ return ThreadAttach(hModule);
+ case DLL_THREAD_DETACH:
+ OutputDebugStringA("trcapi" DETOURS_STRINGIFY(DETOURS_BITS) ".dll:"
+ " DllMain DLL_THREAD_DETACH\n");
+ return ThreadDetach(hModule);
+ }
+ return TRUE;
+}
+//
+///////////////////////////////////////////////////////////////// End of File.