mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-04-29 14:07:57 +03:00
522 lines
15 KiB
C++
522 lines
15 KiB
C++
![]() |
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// 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.
|