mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-04-28 19:18:21 +00:00
4573 lines
129 KiB
C++
Vendored
4573 lines
129 KiB
C++
Vendored
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Detours Test Program (trcbld.cpp of trcbld.dll)
|
|
//
|
|
// Microsoft Research Detours Package
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
|
|
#define _WIN32_WINNT 0x0500
|
|
#define WIN32
|
|
#define NT
|
|
|
|
#define DBG_TRACE 0
|
|
|
|
#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 "tracebld.h"
|
|
|
|
#define PULONG_PTR PVOID
|
|
#define PLONG_PTR PVOID
|
|
#define ULONG_PTR PVOID
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#pragma warning(disable:4127) // Many of our asserts are constants.
|
|
|
|
#define DEBUG_BREAK() DebugBreak()
|
|
|
|
#define ASSERT_ALWAYS(x) \
|
|
do { \
|
|
if (!(x)) { \
|
|
AssertFailed(#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 HMODULE s_hKernel32 = NULL;
|
|
static CHAR s_szDllPath[MAX_PATH];
|
|
static TBLOG_PAYLOAD s_Payload;
|
|
static TBLOG_PAYLOAD s_ChildPayload;
|
|
static CRITICAL_SECTION s_csChildPayload;
|
|
static DWORD s_nTraceProcessId = 0;
|
|
static LONG s_nChildCnt = 0;
|
|
|
|
static CRITICAL_SECTION s_csPipe; // Guards access to hPipe.
|
|
static HANDLE s_hPipe = INVALID_HANDLE_VALUE;
|
|
static TBLOG_MESSAGE s_rMessage;
|
|
|
|
// Logging Functions.
|
|
//
|
|
VOID Tblog(PCSTR pszMsgf, ...);
|
|
VOID TblogV(PCSTR pszMsgf, va_list args);
|
|
|
|
VOID VSafePrintf(PCSTR pszMsg, va_list args, PCHAR pszBuffer, LONG cbBuffer);
|
|
PCHAR SafePrintf(PCHAR pszBuffer, LONG cbBuffer, PCSTR pszMsg, ...);
|
|
|
|
LONG EnterFunc();
|
|
VOID ExitFunc();
|
|
VOID Print(PCSTR psz, ...);
|
|
VOID NoteRead(PCSTR psz);
|
|
VOID NoteRead(PCWSTR pwz);
|
|
VOID NoteWrite(PCSTR psz);
|
|
VOID NoteWrite(PCWSTR pwz);
|
|
VOID NoteDelete(PCSTR psz);
|
|
VOID NoteDelete(PCWSTR pwz);
|
|
VOID NoteCleanup(PCSTR psz);
|
|
VOID NoteCleanup(PCWSTR pwz);
|
|
|
|
PBYTE LoadFile(HANDLE hFile, DWORD cbFile);
|
|
static PCHAR RemoveReturns(PCHAR pszBuffer);
|
|
static PWCHAR RemoveReturns(PWCHAR pwzBuffer);
|
|
|
|
VOID AssertFailed(CONST PCHAR pszMsg, CONST PCHAR pszFile, ULONG nLine);
|
|
|
|
int WINAPI Mine_EntryPoint(VOID);
|
|
VOID WINAPI Mine_ExitProcess(UINT a0);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
int (WINAPI * Real_EntryPoint)(VOID)
|
|
= NULL;
|
|
|
|
BOOL (WINAPI * Real_CreateDirectoryW)(LPCWSTR a0,
|
|
LPSECURITY_ATTRIBUTES a1)
|
|
= CreateDirectoryW;
|
|
|
|
BOOL (WINAPI * Real_CreateDirectoryExW)(LPCWSTR a0,
|
|
LPCWSTR a1,
|
|
LPSECURITY_ATTRIBUTES a2)
|
|
= CreateDirectoryExW;
|
|
|
|
HANDLE (WINAPI * Real_CreateFileW)(LPCWSTR a0,
|
|
DWORD a1,
|
|
DWORD a2,
|
|
LPSECURITY_ATTRIBUTES a3,
|
|
DWORD a4,
|
|
DWORD a5,
|
|
HANDLE a6)
|
|
= CreateFileW;
|
|
|
|
HANDLE (WINAPI * Real_CreateFileMappingW)(HANDLE hFile,
|
|
LPSECURITY_ATTRIBUTES lpAttributes,
|
|
DWORD flProtect,
|
|
DWORD dwMaximumSizeHigh,
|
|
DWORD dwMaximumSizeLow,
|
|
LPCWSTR lpName
|
|
)
|
|
= CreateFileMappingW;
|
|
|
|
BOOL (WINAPI * Real_CreatePipe)(PHANDLE hReadPipe,
|
|
PHANDLE hWritePipe,
|
|
LPSECURITY_ATTRIBUTES lpPipeAttributes,
|
|
DWORD nSize)
|
|
= CreatePipe;
|
|
|
|
BOOL (WINAPI * Real_CloseHandle)(HANDLE a0)
|
|
= CloseHandle;
|
|
|
|
BOOL (WINAPI * Real_DuplicateHandle)(HANDLE hSourceProcessHandle,
|
|
HANDLE hSourceHandle,
|
|
HANDLE hTargetProcessHandle,
|
|
LPHANDLE lpTargetHandle,
|
|
DWORD dwDesiredAccess,
|
|
BOOL bInheritHandle,
|
|
DWORD dwOptions)
|
|
= DuplicateHandle;
|
|
|
|
BOOL (WINAPI * Real_CreateProcessW)(LPCWSTR lpApplicationName,
|
|
LPWSTR lpCommandLine,
|
|
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
|
BOOL bInheritHandles,
|
|
DWORD dwCreationFlags,
|
|
LPVOID lpEnvironment,
|
|
LPCWSTR lpCurrentDirectory,
|
|
LPSTARTUPINFOW lpStartupInfo,
|
|
LPPROCESS_INFORMATION lpProcessInformation)
|
|
= CreateProcessW;
|
|
|
|
BOOL (WINAPI * Real_CreateProcessA)(LPCSTR lpApplicationName,
|
|
LPSTR lpCommandLine,
|
|
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
|
BOOL bInheritHandles,
|
|
DWORD dwCreationFlags,
|
|
LPVOID lpEnvironment,
|
|
LPCSTR lpCurrentDirectory,
|
|
LPSTARTUPINFOA lpStartupInfo,
|
|
LPPROCESS_INFORMATION lpProcessInformation)
|
|
= CreateProcessA;
|
|
|
|
BOOL (WINAPI * Real_DeleteFileW)(LPCWSTR a0)
|
|
= DeleteFileW;
|
|
BOOL (WINAPI * Real_DeviceIoControl)(HANDLE a0,
|
|
DWORD dwIoControlCode,
|
|
LPVOID lpInBuffer,
|
|
DWORD nInBufferSize,
|
|
LPVOID lpOutBuffer,
|
|
DWORD nOutBufferSize,
|
|
LPDWORD lpBytesReturned,
|
|
LPOVERLAPPED lpOverlapped)
|
|
= DeviceIoControl;
|
|
|
|
DWORD (WINAPI * Real_GetFileAttributesW)(LPCWSTR a0)
|
|
= GetFileAttributesW;
|
|
|
|
BOOL (WINAPI * Real_MoveFileWithProgressW)(LPCWSTR lpExistingFileName,
|
|
LPCWSTR lpNewFileName,
|
|
LPPROGRESS_ROUTINE lpProgressRoutine,
|
|
LPVOID lpData,
|
|
DWORD dwFlags)
|
|
= MoveFileWithProgressW;
|
|
|
|
BOOL (WINAPI * Real_MoveFileA)(LPCSTR a0,
|
|
LPCSTR a1)
|
|
= MoveFileA;
|
|
|
|
BOOL (WINAPI * Real_MoveFileW)(LPCWSTR a0,
|
|
LPCWSTR a12)
|
|
= MoveFileW;
|
|
|
|
BOOL (WINAPI * Real_MoveFileExA)(LPCSTR a0,
|
|
LPCSTR a1,
|
|
DWORD a2)
|
|
= MoveFileExA;
|
|
|
|
BOOL (WINAPI * Real_MoveFileExW)(LPCWSTR a0,
|
|
LPCWSTR a1,
|
|
DWORD a2)
|
|
= MoveFileExW;
|
|
|
|
BOOL (WINAPI * Real_CopyFileExA)(LPCSTR a0,
|
|
LPCSTR a1,
|
|
LPPROGRESS_ROUTINE a2,
|
|
LPVOID a4,
|
|
LPBOOL a5,
|
|
DWORD a6)
|
|
= CopyFileExA;
|
|
|
|
BOOL (WINAPI * Real_CopyFileExW)(LPCWSTR a0,
|
|
LPCWSTR a1,
|
|
LPPROGRESS_ROUTINE a2,
|
|
LPVOID a4,
|
|
LPBOOL a5,
|
|
DWORD a6)
|
|
= CopyFileExW;
|
|
|
|
BOOL (WINAPI * Real_PrivCopyFileExW)(LPCWSTR lpExistingFileName,
|
|
LPCWSTR lpNewFileName,
|
|
LPPROGRESS_ROUTINE lpProgressRoutine,
|
|
LPVOID lpData,
|
|
LPBOOL pbCancel,
|
|
DWORD dwCopyFlags)
|
|
= NULL;
|
|
|
|
BOOL (WINAPI * Real_CreateHardLinkA)(LPCSTR a0,
|
|
LPCSTR a1,
|
|
LPSECURITY_ATTRIBUTES a2)
|
|
= CreateHardLinkA;
|
|
|
|
BOOL (WINAPI * Real_CreateHardLinkW)(LPCWSTR a0,
|
|
LPCWSTR a1,
|
|
LPSECURITY_ATTRIBUTES a2)
|
|
= CreateHardLinkW;
|
|
|
|
BOOL (WINAPI * Real_SetStdHandle)(DWORD a0,
|
|
HANDLE a1)
|
|
= SetStdHandle;
|
|
|
|
HMODULE (WINAPI * Real_LoadLibraryA)(LPCSTR a0)
|
|
= LoadLibraryA;
|
|
|
|
HMODULE (WINAPI * Real_LoadLibraryW)(LPCWSTR a0)
|
|
= LoadLibraryW;
|
|
|
|
HMODULE (WINAPI * Real_LoadLibraryExA)(LPCSTR a0,
|
|
HANDLE a1,
|
|
DWORD a2)
|
|
= LoadLibraryExA;
|
|
|
|
HMODULE (WINAPI * Real_LoadLibraryExW)(LPCWSTR a0,
|
|
HANDLE a1,
|
|
DWORD a2)
|
|
= LoadLibraryExW;
|
|
|
|
DWORD (WINAPI * Real_SetFilePointer)(HANDLE hFile,
|
|
LONG lDistanceToMove,
|
|
PLONG lpDistanceToMoveHigh,
|
|
DWORD dwMoveMethod)
|
|
= SetFilePointer;
|
|
|
|
BOOL (WINAPI * Real_SetFilePointerEx)(HANDLE hFile,
|
|
LARGE_INTEGER liDistanceToMove,
|
|
PLARGE_INTEGER lpNewFilePointer,
|
|
DWORD dwMoveMethod)
|
|
= SetFilePointerEx;
|
|
|
|
BOOL (WINAPI * Real_ReadFile)(HANDLE a0,
|
|
LPVOID a1,
|
|
DWORD a2,
|
|
LPDWORD a3,
|
|
LPOVERLAPPED a4)
|
|
= ReadFile;
|
|
|
|
BOOL (WINAPI * Real_ReadFileEx)(HANDLE a0,
|
|
LPVOID a1,
|
|
DWORD a2,
|
|
LPOVERLAPPED a3,
|
|
LPOVERLAPPED_COMPLETION_ROUTINE a4)
|
|
= ReadFileEx;
|
|
|
|
BOOL (WINAPI * Real_WriteFile)(HANDLE a0,
|
|
LPCVOID a1,
|
|
DWORD a2,
|
|
LPDWORD a3,
|
|
LPOVERLAPPED a4)
|
|
= WriteFile;
|
|
|
|
BOOL (WINAPI * Real_WriteFileEx)(HANDLE a0,
|
|
LPCVOID a1,
|
|
DWORD a2,
|
|
LPOVERLAPPED a3,
|
|
LPOVERLAPPED_COMPLETION_ROUTINE a4)
|
|
= WriteFileEx;
|
|
|
|
BOOL (WINAPI * Real_WriteConsoleA)(HANDLE a0,
|
|
const VOID* a1,
|
|
DWORD a2,
|
|
LPDWORD a3,
|
|
LPVOID a4)
|
|
= WriteConsoleA;
|
|
|
|
BOOL (WINAPI * Real_WriteConsoleW)(HANDLE a0,
|
|
const VOID* a1,
|
|
DWORD a2,
|
|
LPDWORD a3,
|
|
LPVOID a4)
|
|
= WriteConsoleW;
|
|
|
|
VOID (WINAPI * Real_ExitProcess)(UINT a0)
|
|
= ExitProcess;
|
|
|
|
DWORD (WINAPI * Real_ExpandEnvironmentStringsA)(PCSTR lpSrc, PCHAR lpDst, DWORD nSize)
|
|
= ExpandEnvironmentStringsA;
|
|
|
|
DWORD (WINAPI * Real_ExpandEnvironmentStringsW)(PCWSTR lpSrc, PWCHAR lpDst, DWORD nSize)
|
|
= ExpandEnvironmentStringsW;
|
|
|
|
DWORD (WINAPI * Real_GetEnvironmentVariableA)(PCSTR lpName, PCHAR lpBuffer, DWORD nSize)
|
|
= GetEnvironmentVariableA;
|
|
|
|
DWORD (WINAPI * Real_GetEnvironmentVariableW)(PCWSTR lpName, PWCHAR lpBuffer, DWORD nSize)
|
|
= GetEnvironmentVariableW;
|
|
|
|
PCWSTR (CDECL * Real_wgetenv)(PCWSTR var) = NULL;
|
|
PCSTR (CDECL * Real_getenv)(PCSTR var) = NULL;
|
|
DWORD (CDECL * Real_getenv_s)(DWORD *pValue, PCHAR pBuffer, DWORD cBuffer, PCSTR varname) = NULL;
|
|
DWORD (CDECL * Real_wgetenv_s)(DWORD *pValue, PWCHAR pBuffer, DWORD cBuffer, PCWSTR varname) = NULL;
|
|
DWORD (CDECL * Real_dupenv_s)(PCHAR *ppBuffer, DWORD *pcBuffer, PCSTR varname) = NULL;
|
|
DWORD (CDECL * Real_wdupenv_s)(PWCHAR *ppBuffer, DWORD *pcBuffer, PCWSTR varname) = NULL;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
static VOID Copy(PWCHAR pwzDst, PCWSTR pwzSrc)
|
|
{
|
|
while (*pwzSrc) {
|
|
*pwzDst++ = *pwzSrc++;
|
|
}
|
|
*pwzDst = '\0';
|
|
}
|
|
|
|
static DWORD Size(PCWSTR pwzSrc)
|
|
{
|
|
DWORD c = 0;
|
|
while (pwzSrc[c]) {
|
|
c++;
|
|
}
|
|
return c;
|
|
}
|
|
|
|
static PCWSTR Save(PCWSTR pwzSrc)
|
|
{
|
|
DWORD c = (Size(pwzSrc) + 1) * sizeof(WCHAR);
|
|
PWCHAR pwzDst = (PWCHAR)GlobalAlloc(GPTR, c);
|
|
CopyMemory(pwzDst, pwzSrc, c);
|
|
|
|
return pwzDst;
|
|
}
|
|
|
|
static BOOL HasSpace(PCWSTR pwz)
|
|
{
|
|
for (; *pwz; pwz++) {
|
|
if (*pwz == ' ' || *pwz == '\t' || *pwz == '\r' || *pwz == '\n') {
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL HasChar(PCWSTR pwz, WCHAR w)
|
|
{
|
|
for (; *pwz; pwz++) {
|
|
if (*pwz == w) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static DWORD Compare(PCWSTR pwzA, PCWSTR pwzB)
|
|
{
|
|
for (;;) {
|
|
WCHAR cA = *pwzA++;
|
|
WCHAR cB = *pwzB++;
|
|
|
|
if (cA >= 'A' && cA <= 'Z') {
|
|
cA += ('a' - 'A');
|
|
}
|
|
if (cB >= 'A' && cB <= 'Z') {
|
|
cB += ('a' - 'A');
|
|
}
|
|
|
|
if (cA == 0 && cB == 0) {
|
|
return 0;
|
|
}
|
|
if (cA != cB) {
|
|
return cA - cB;
|
|
}
|
|
}
|
|
}
|
|
|
|
static DWORD Compare(PCWSTR pwzA, PCSTR pszB)
|
|
{
|
|
for (;;) {
|
|
WCHAR cA = *pwzA++;
|
|
WCHAR cB = *pszB++;
|
|
|
|
if (cA >= 'A' && cA <= 'Z') {
|
|
cA += ('a' - 'A');
|
|
}
|
|
if (cB >= 'A' && cB <= 'Z') {
|
|
cB += ('a' - 'A');
|
|
}
|
|
|
|
if (cA == 0 && cB == 0) {
|
|
return 0;
|
|
}
|
|
if (cA != cB) {
|
|
return cA - cB;
|
|
}
|
|
}
|
|
}
|
|
|
|
static DWORD Compare(PCSTR pszA, PCSTR pszB)
|
|
{
|
|
for (;;) {
|
|
CHAR cA = *pszA++;
|
|
CHAR cB = *pszB++;
|
|
|
|
if (cA >= 'A' && cA <= 'Z') {
|
|
cA += ('a' - 'A');
|
|
}
|
|
if (cB >= 'A' && cB <= 'Z') {
|
|
cB += ('a' - 'A');
|
|
}
|
|
|
|
if (cA == 0 && cB == 0) {
|
|
return 0;
|
|
}
|
|
if (cA != cB) {
|
|
return cA - cB;
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static PCSTR s_rpszMsvcrNames[] = {
|
|
"msvcr80.dll",
|
|
"msvcr80d.dll",
|
|
"msvcr71.dll",
|
|
"msvcr71d.dll",
|
|
"msvcr70.dll",
|
|
"msvcr70d.dll",
|
|
NULL
|
|
};
|
|
|
|
HMODULE s_hMsvcr = NULL;
|
|
PCSTR s_pszMsvcr = NULL;
|
|
|
|
static BOOL WINAPI ImportFileCallback(PVOID pContext, HMODULE hFile, PCSTR pszFile)
|
|
{
|
|
UNUSED(pContext);
|
|
|
|
if (pszFile != NULL) {
|
|
for (int i = 0; s_rpszMsvcrNames[i]; i++) {
|
|
if (Compare(pszFile, s_rpszMsvcrNames[i]) == 0) {
|
|
s_hMsvcr = hFile;
|
|
s_pszMsvcr = s_rpszMsvcrNames[i];
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL FindMsvcr()
|
|
{
|
|
DetourEnumerateImports(NULL, NULL, ImportFileCallback, NULL);
|
|
|
|
if (s_hMsvcr != NULL) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL FindProc(PVOID * ppvCode, PCSTR pwzFunc)
|
|
{
|
|
PVOID pv = GetProcAddress(s_hMsvcr, pwzFunc);
|
|
if (pv != NULL) {
|
|
*ppvCode = pv;
|
|
return TRUE;
|
|
}
|
|
else {
|
|
*ppvCode = NULL;
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
struct EnvInfo
|
|
{
|
|
DWORD m_nHash;
|
|
DWORD m_nIndex;
|
|
PCWSTR m_pwzVar;
|
|
PCWSTR m_pwzVal;
|
|
BOOL m_fDefined;
|
|
BOOL m_fUsed;
|
|
BOOL m_fOriginal;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
class EnvVars
|
|
{
|
|
private:
|
|
static CRITICAL_SECTION s_csLock;
|
|
static DWORD s_nVars;
|
|
static DWORD s_nCapacity;
|
|
static EnvInfo ** s_pVars;
|
|
|
|
private:
|
|
static DWORD Hash(PCWSTR pwzVar)
|
|
{
|
|
DWORD hash = 5381;
|
|
while (*pwzVar != 0) {
|
|
WCHAR c = *pwzVar++;
|
|
if (c >= 'A' && c <= 'Z') {
|
|
c += ('a' - 'A');
|
|
}
|
|
hash = ((hash << 5) + hash) + c;
|
|
}
|
|
return hash;
|
|
}
|
|
|
|
static VOID LockAcquire()
|
|
{
|
|
EnterCriticalSection(&s_csLock);
|
|
}
|
|
|
|
static VOID LockRelease()
|
|
{
|
|
LeaveCriticalSection(&s_csLock);
|
|
}
|
|
|
|
static VOID Resize(DWORD nCapacity);
|
|
static VOID Set(EnvInfo *info);
|
|
static EnvInfo * Find(PCWSTR pwzVar);
|
|
|
|
public:
|
|
static BOOL Equal(PCWSTR pwzA, PCWSTR pwzB)
|
|
{
|
|
return (Compare(pwzA, pwzB) == 0);
|
|
}
|
|
|
|
public:
|
|
static VOID Initialize();
|
|
static VOID Dump();
|
|
|
|
static VOID Add(PCWSTR pwzVar, PCWSTR pwzVal);
|
|
|
|
static VOID Used(PCWSTR pwzVar);
|
|
static VOID Used(PCSTR pszVar);
|
|
};
|
|
|
|
CRITICAL_SECTION EnvVars::s_csLock;
|
|
DWORD EnvVars::s_nVars = 0;
|
|
DWORD EnvVars::s_nCapacity = 0;
|
|
EnvInfo ** EnvVars::s_pVars = NULL;
|
|
|
|
VOID EnvVars::Initialize()
|
|
{
|
|
InitializeCriticalSection(&s_csLock);
|
|
|
|
Resize(919);
|
|
}
|
|
|
|
VOID EnvVars::Resize(DWORD nCapacity)
|
|
{
|
|
if (nCapacity > s_nCapacity) {
|
|
DWORD nOld = s_nCapacity;
|
|
EnvInfo ** pOld = s_pVars;
|
|
|
|
// DEBUG_BREAK();
|
|
|
|
s_pVars = (EnvInfo **)GlobalAlloc(GPTR, nCapacity * sizeof(EnvInfo *));
|
|
s_nCapacity = nCapacity;
|
|
|
|
if (pOld != NULL) {
|
|
for (DWORD n = 0; n < nOld; n++) {
|
|
if (pOld[n] != NULL) {
|
|
Set(pOld[n]);
|
|
}
|
|
}
|
|
GlobalFree((HGLOBAL)pOld);
|
|
pOld = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID EnvVars::Set(EnvInfo *info)
|
|
{
|
|
DWORD hash = info->m_nHash;
|
|
DWORD slot = hash % s_nCapacity;
|
|
DWORD death = 0;
|
|
|
|
// Find an empty slot.
|
|
for (; s_pVars[slot] != NULL; slot = (slot + 1) % s_nCapacity) {
|
|
if (++death > s_nCapacity) {
|
|
// We should have dropped out at some point...
|
|
DEBUG_BREAK();
|
|
}
|
|
}
|
|
|
|
s_pVars[slot] = info;
|
|
}
|
|
|
|
EnvInfo * EnvVars::Find(PCWSTR pwzVar)
|
|
{
|
|
DWORD hash = Hash(pwzVar);
|
|
DWORD slot = hash % s_nCapacity;
|
|
|
|
LockAcquire();
|
|
|
|
// Find the the matching slot, or an empty one.
|
|
for (; s_pVars[slot] != NULL; slot = (slot + 1) % s_nCapacity) {
|
|
if (Equal(s_pVars[slot]->m_pwzVar, pwzVar)) {
|
|
LockRelease();
|
|
return s_pVars[slot];
|
|
}
|
|
}
|
|
LockRelease();
|
|
return NULL;
|
|
}
|
|
|
|
VOID EnvVars::Add(PCWSTR pwzVar, PCWSTR pwzVal)
|
|
{
|
|
if (pwzVar == NULL) {
|
|
return;
|
|
}
|
|
|
|
WCHAR wzVar[MAX_PATH];
|
|
PWCHAR pwzDst = wzVar;
|
|
while (*pwzVar) {
|
|
if (*pwzVar >= 'a' && *pwzVar <= 'z') {
|
|
*pwzDst++ = *pwzVar - ('a' - 'A');
|
|
}
|
|
else {
|
|
*pwzDst++ = *pwzVar;
|
|
}
|
|
pwzVar++;
|
|
}
|
|
*pwzDst = '\0';
|
|
pwzVar = wzVar;
|
|
|
|
WCHAR wzVal[] = L"";
|
|
if (pwzVal != NULL) {
|
|
while (*pwzVal == ' ' || *pwzVal == '\t') {
|
|
*pwzVal++;
|
|
}
|
|
}
|
|
else {
|
|
pwzVal = wzVal;
|
|
}
|
|
|
|
// Tblog("<!-- ::Add var=[%le] val=[%le] -->\n", pwzVar, pwzVal);
|
|
LockAcquire();
|
|
|
|
// DEBUG_BREAK();
|
|
|
|
DWORD hash = Hash(pwzVar);
|
|
DWORD slot = hash % s_nCapacity;
|
|
EnvInfo *info = NULL;
|
|
DWORD death = 0;
|
|
|
|
// Find the the matching slot, or an empty one.
|
|
for (; s_pVars[slot] != NULL; slot = (slot + 1) % s_nCapacity) {
|
|
if (Equal(s_pVars[slot]->m_pwzVar, pwzVar)) {
|
|
LockRelease();
|
|
return;
|
|
}
|
|
if (++death > s_nCapacity) {
|
|
// We should have dropped out at some point...
|
|
DEBUG_BREAK();
|
|
}
|
|
}
|
|
|
|
// Add the var to list of known vars.
|
|
info = (EnvInfo *)GlobalAlloc(GPTR, sizeof(EnvInfo));
|
|
info->m_nHash = hash;
|
|
info->m_nIndex = s_nVars++;
|
|
info->m_pwzVar = Save(pwzVar);
|
|
info->m_pwzVal = Save(pwzVal);
|
|
if (pwzVal[0] == '\0') {
|
|
info->m_fDefined = FALSE;
|
|
info->m_fUsed = TRUE;
|
|
}
|
|
else {
|
|
info->m_fDefined = TRUE;
|
|
}
|
|
s_pVars[slot] = info;
|
|
|
|
// Check if we should grow the table.
|
|
if (s_nVars > (s_nCapacity / 2)) {
|
|
Resize(s_nCapacity * 2 - 1);
|
|
}
|
|
|
|
LockRelease();
|
|
}
|
|
|
|
VOID EnvVars::Used(PCWSTR pwzVar)
|
|
{
|
|
if (pwzVar != NULL) {
|
|
// Tblog("<!-- Used [%le] -->\n", pwzVar);
|
|
EnvInfo *pInfo = Find(pwzVar);
|
|
if (pInfo) {
|
|
pInfo->m_fUsed = TRUE;
|
|
}
|
|
#if 0
|
|
else {
|
|
Add(pwzVar, NULL);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
VOID EnvVars::Used(PCSTR pszVar)
|
|
{
|
|
if (pszVar != NULL) {
|
|
WCHAR wzVar[MAX_PATH];
|
|
PWCHAR pwzVar = wzVar;
|
|
while (*pszVar) {
|
|
*pwzVar++ = *pszVar++;
|
|
}
|
|
*pwzVar = '\0';
|
|
|
|
Used(wzVar);
|
|
}
|
|
}
|
|
|
|
VOID EnvVars::Dump()
|
|
{
|
|
if (s_nVars == 0) {
|
|
return;
|
|
}
|
|
|
|
LockAcquire();
|
|
|
|
Tblog("<t:Vars>\n");
|
|
|
|
// Remove any variables that match the original environment.
|
|
PCWSTR pwzz = s_Payload.wzzEnvironment;
|
|
while (*pwzz) {
|
|
WCHAR wzVar[MAX_PATH];
|
|
PWCHAR pwzVar = wzVar;
|
|
|
|
while (*pwzz && *pwzz != '=') {
|
|
*pwzVar++ = *pwzz++;
|
|
}
|
|
*pwzVar = '\0';
|
|
if (*pwzz == '=') {
|
|
pwzz++;
|
|
}
|
|
|
|
EnvInfo *pInfo = Find(wzVar);
|
|
if (pInfo) {
|
|
if (Compare(pwzz, pInfo->m_pwzVal) == 0) {
|
|
pInfo->m_fUsed = FALSE;
|
|
}
|
|
}
|
|
pwzz += Size(pwzz) + 1;
|
|
}
|
|
|
|
|
|
EnvInfo ** pSorted = (EnvInfo **)GlobalAlloc(GPTR, s_nVars * sizeof(EnvInfo *));
|
|
|
|
for (DWORD n = 0; n < s_nCapacity; n++) {
|
|
if (s_pVars[n] != NULL) {
|
|
if (s_pVars[n]->m_nIndex > s_nVars) {
|
|
DEBUG_BREAK();
|
|
}
|
|
pSorted[s_pVars[n]->m_nIndex] = s_pVars[n];
|
|
}
|
|
}
|
|
|
|
for (DWORD n = 0; n < s_nVars; n++) {
|
|
EnvInfo *pInfo = pSorted[n];
|
|
|
|
if (pInfo == NULL) {
|
|
Print("<!-- Warning: Missing %d of %d -->\n", n, s_nVars);
|
|
continue;
|
|
}
|
|
|
|
if (pInfo->m_fUsed && pInfo->m_pwzVal[0]) {
|
|
Print("<t:Var var=\"%le\">%le</t:Var>\n", pInfo->m_pwzVar, pInfo->m_pwzVal);
|
|
}
|
|
}
|
|
GlobalFree((HGLOBAL)pSorted);
|
|
|
|
Tblog("</t:Vars>\n");
|
|
|
|
LockRelease();
|
|
}
|
|
|
|
void SaveEnvironment()
|
|
{
|
|
LPWCH pwStrings = GetEnvironmentStringsW();
|
|
PCWSTR pwEnv = (PCWSTR)pwStrings;
|
|
|
|
while (*pwEnv != '\0') {
|
|
WCHAR wzVar[MAX_PATH];
|
|
PWCHAR pwzDst = wzVar;
|
|
PCWSTR pwzVal = NULL;
|
|
|
|
if (*pwEnv == '=') {
|
|
*pwzDst++ = *pwEnv++;
|
|
}
|
|
while (*pwEnv != '\0' && *pwEnv != '=') {
|
|
*pwzDst++ = *pwEnv++;
|
|
}
|
|
*pwzDst++ = '\0';
|
|
|
|
if (*pwEnv == '=') {
|
|
pwEnv++;
|
|
}
|
|
|
|
pwzVal = pwEnv;
|
|
while (*pwEnv != '\0') {
|
|
pwEnv++;
|
|
}
|
|
if (*pwEnv == '\0') {
|
|
pwEnv++;
|
|
}
|
|
if (wzVar[0] != '=') {
|
|
EnvVars::Add(wzVar, pwzVal);
|
|
}
|
|
}
|
|
FreeEnvironmentStringsW(pwStrings);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
struct ProcInfo
|
|
{
|
|
HANDLE m_hProc;
|
|
DWORD m_nProcId;
|
|
DWORD m_nProc;
|
|
};
|
|
|
|
class Procs
|
|
{
|
|
private:
|
|
static CRITICAL_SECTION s_csLock;
|
|
static DWORD s_nProcs;
|
|
static ProcInfo s_rProcs[4049];
|
|
|
|
private:
|
|
static ProcInfo& HashToSlot(HANDLE handle)
|
|
{
|
|
return s_rProcs[((DWORD_PTR)handle) % ARRAYSIZE(s_rProcs)];
|
|
}
|
|
|
|
static VOID LockAcquire()
|
|
{
|
|
EnterCriticalSection(&s_csLock);
|
|
}
|
|
|
|
static VOID LockRelease()
|
|
{
|
|
LeaveCriticalSection(&s_csLock);
|
|
}
|
|
|
|
public:
|
|
static VOID Initialize();
|
|
static ProcInfo * Create(HANDLE hProc, DWORD nProcId);
|
|
static BOOL Close(HANDLE hProc);
|
|
};
|
|
|
|
CRITICAL_SECTION Procs::s_csLock;
|
|
DWORD Procs::s_nProcs = 0;
|
|
ProcInfo Procs::s_rProcs[4049];
|
|
|
|
VOID Procs::Initialize()
|
|
{
|
|
InitializeCriticalSection(&s_csLock);
|
|
for (DWORD i = 0; i < ARRAYSIZE(s_rProcs); i++) {
|
|
s_rProcs[i].m_hProc = INVALID_HANDLE_VALUE;
|
|
}
|
|
}
|
|
|
|
ProcInfo * Procs::Create(HANDLE hProc, DWORD nProcId)
|
|
{
|
|
LockAcquire();
|
|
s_nProcs++;
|
|
ProcInfo& slot = HashToSlot(hProc);
|
|
slot.m_hProc = hProc;
|
|
slot.m_nProcId = nProcId;
|
|
slot.m_nProc = s_nProcs;
|
|
Print("<!-- CreateProcess (%d)-->\n", slot.m_nProc);
|
|
LockRelease();
|
|
|
|
return &slot;
|
|
}
|
|
|
|
BOOL Procs::Close(HANDLE hProc)
|
|
{
|
|
BOOL first = false;
|
|
|
|
LockAcquire();
|
|
ProcInfo& slot = HashToSlot(hProc);
|
|
if (slot.m_hProc == hProc) {
|
|
first = true;
|
|
Print("<!-- CloseProcess (%d)-->\n", slot.m_nProc);
|
|
slot.m_hProc = INVALID_HANDLE_VALUE;
|
|
slot.m_nProcId = 0;
|
|
slot.m_nProc = 0;
|
|
s_nProcs--;
|
|
}
|
|
LockRelease();
|
|
|
|
return first;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
struct FileInfo
|
|
{
|
|
DWORD m_nHash;
|
|
DWORD m_nIndex;
|
|
|
|
BOOL m_fCantRead; // Set for file that are opened Create
|
|
BOOL m_fRead;
|
|
BOOL m_fWrite;
|
|
|
|
BOOL m_fDelete;
|
|
BOOL m_fCleanup;
|
|
BOOL m_fSystemPath;
|
|
BOOL m_fTemporaryPath;
|
|
BOOL m_fTemporaryFile;
|
|
|
|
DWORD m_cbRead;
|
|
DWORD m_cbWrite;
|
|
|
|
BOOL m_fAppend;
|
|
BOOL m_fAbsorbed; // Absorbed by TraceBld.
|
|
BOOL m_fDirectory;
|
|
|
|
PCWSTR m_pwzPath;
|
|
PBYTE m_pbContent;
|
|
DWORD m_cbContent;
|
|
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
class FileNames
|
|
{
|
|
private:
|
|
static CRITICAL_SECTION s_csLock;
|
|
static DWORD s_nFiles;
|
|
static DWORD s_nCapacity;
|
|
static FileInfo ** s_pFiles;
|
|
|
|
public:
|
|
static WCHAR s_wzSysPath[MAX_PATH];
|
|
static WCHAR s_wzS64Path[MAX_PATH];
|
|
static WCHAR s_wzTmpPath[MAX_PATH];
|
|
static WCHAR s_wzExePath[MAX_PATH];
|
|
static DWORD s_wcSysPath;
|
|
static DWORD s_wcS64Path;
|
|
static DWORD s_wcTmpPath;
|
|
static DWORD s_wcExePath;
|
|
|
|
private:
|
|
static DWORD Hash(PCWSTR pwzFile)
|
|
{
|
|
DWORD hash = 5381;
|
|
while (*pwzFile != 0) {
|
|
WCHAR c = *pwzFile++;
|
|
if (c >= 'A' && c <= 'Z') {
|
|
c += ('a' - 'A');
|
|
}
|
|
hash = ((hash << 5) + hash) + c;
|
|
}
|
|
return hash;
|
|
}
|
|
|
|
static VOID LockAcquire()
|
|
{
|
|
EnterCriticalSection(&s_csLock);
|
|
}
|
|
|
|
static VOID LockRelease()
|
|
{
|
|
LeaveCriticalSection(&s_csLock);
|
|
}
|
|
|
|
static VOID Resize(DWORD nCapacity);
|
|
static VOID Set(FileInfo *info);
|
|
static VOID Replace(PWCHAR pwzBuffer, PWCHAR pwzDstEnd, DWORD cwOld, PCWSTR pwzNew);
|
|
|
|
public:
|
|
static BOOL Equal(PCWSTR pwzA, PCWSTR pwzB)
|
|
{
|
|
return (Compare(pwzA, pwzB) == 0);
|
|
}
|
|
|
|
static BOOL PrefixMatch(PCWSTR pwzFile, PCWSTR pwzPrefix)
|
|
{
|
|
for (;;) {
|
|
WCHAR cFile = *pwzFile++;
|
|
WCHAR cPrefix = *pwzPrefix++;
|
|
|
|
if (cFile >= 'A' && cFile <= 'Z') {
|
|
cFile += ('a' - 'A');
|
|
}
|
|
if (cPrefix >= 'A' && cPrefix <= 'Z') {
|
|
cPrefix += ('a' - 'A');
|
|
}
|
|
|
|
if (cPrefix == 0) {
|
|
return TRUE;
|
|
}
|
|
if (cFile != cPrefix) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
static BOOL SuffixMatch(PCWSTR pwzFile, PCWSTR pwzSuffix)
|
|
{
|
|
// Move both pointers to the end of the strings.
|
|
PCWSTR pwzFileBeg = pwzFile;
|
|
while (*pwzFile) {
|
|
pwzFile++;
|
|
}
|
|
|
|
PCWSTR pwzSuffixBeg = pwzSuffix;
|
|
while (*pwzSuffix) {
|
|
pwzSuffix++;
|
|
}
|
|
|
|
// Now walk backwards comparing strings.
|
|
for (;;) {
|
|
WCHAR cFile = (pwzFile > pwzFileBeg) ? *--pwzFile : 0;
|
|
WCHAR cSuffix = (pwzSuffix > pwzSuffixBeg) ? *--pwzSuffix : 0;
|
|
|
|
if (cFile >= 'A' && cFile <= 'Z') {
|
|
cFile += ('a' - 'A');
|
|
}
|
|
if (cSuffix >= 'A' && cSuffix <= 'Z') {
|
|
cSuffix += ('a' - 'A');
|
|
}
|
|
|
|
if (cSuffix == 0) {
|
|
return TRUE;
|
|
}
|
|
if (cFile != cSuffix) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
static VOID EndInSlash(PWCHAR pwzPath)
|
|
{
|
|
if (*pwzPath) {
|
|
while (*pwzPath) {
|
|
pwzPath++;
|
|
}
|
|
if (pwzPath[-1] != '\\') {
|
|
*pwzPath++ = '\\';
|
|
*pwzPath = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
public:
|
|
static VOID Initialize();
|
|
static VOID Dump();
|
|
static FileInfo * FindPartial(PCWSTR pwzPath);
|
|
static FileInfo * FindPartial(PCSTR pszPath);
|
|
static FileInfo * FindFull(PCWSTR pwzPath);
|
|
static PCWSTR ParameterizeName(PWCHAR pwzDst, DWORD cMaxDst, PCWSTR pwzPath);
|
|
static PCWSTR ParameterizeName(PWCHAR pwzDst, DWORD cMaxDst, FileInfo *pInfo);
|
|
static VOID ParameterizeLine(PWCHAR pwzDst, PWCHAR pwzDstEnd);
|
|
};
|
|
|
|
CRITICAL_SECTION FileNames::s_csLock;
|
|
DWORD FileNames::s_nFiles = 0;
|
|
DWORD FileNames::s_nCapacity = 0;
|
|
FileInfo ** FileNames::s_pFiles;
|
|
WCHAR FileNames::s_wzSysPath[MAX_PATH];
|
|
WCHAR FileNames::s_wzS64Path[MAX_PATH];
|
|
WCHAR FileNames::s_wzTmpPath[MAX_PATH];
|
|
WCHAR FileNames::s_wzExePath[MAX_PATH];
|
|
DWORD FileNames::s_wcSysPath;
|
|
DWORD FileNames::s_wcS64Path;
|
|
DWORD FileNames::s_wcTmpPath;
|
|
DWORD FileNames::s_wcExePath;
|
|
|
|
VOID FileNames::Initialize()
|
|
{
|
|
InitializeCriticalSection(&s_csLock);
|
|
|
|
s_wzSysPath[0] = '\0';
|
|
GetSystemDirectoryW(s_wzSysPath, ARRAYSIZE(s_wzSysPath));
|
|
EndInSlash(s_wzSysPath);
|
|
|
|
s_wzS64Path[0] = '\0';
|
|
GetWindowsDirectoryW(s_wzS64Path, ARRAYSIZE(s_wzS64Path));
|
|
EndInSlash(s_wzS64Path);
|
|
Copy(s_wzS64Path + Size(s_wzS64Path), L"SysWOW64\\");
|
|
|
|
s_wzTmpPath[0] = '\0';
|
|
GetTempPathW(ARRAYSIZE(s_wzTmpPath), s_wzTmpPath);
|
|
EndInSlash(s_wzTmpPath);
|
|
|
|
s_wzExePath[0] = '\0';
|
|
GetModuleFileNameW(NULL, s_wzExePath, ARRAYSIZE(s_wzExePath));
|
|
PWCHAR pwzLast = s_wzExePath;
|
|
for (PWCHAR pwz = s_wzExePath; *pwz; pwz++) {
|
|
if (*pwz == '\\') {
|
|
pwzLast = pwz;
|
|
}
|
|
}
|
|
if (*pwzLast == '\\') {
|
|
*++pwzLast = '\0';
|
|
}
|
|
|
|
s_wcSysPath = Size(s_wzSysPath);
|
|
s_wcS64Path = Size(s_wzS64Path);
|
|
s_wcTmpPath = Size(s_wzTmpPath);
|
|
s_wcExePath = Size(s_wzExePath);
|
|
|
|
Resize(4049);
|
|
}
|
|
|
|
VOID FileNames::Resize(DWORD nCapacity)
|
|
{
|
|
if (nCapacity > s_nCapacity) {
|
|
DWORD nOld = s_nCapacity;
|
|
FileInfo ** pOld = s_pFiles;
|
|
|
|
s_pFiles = (FileInfo **)GlobalAlloc(GPTR, nCapacity * sizeof(FileInfo *));
|
|
s_nCapacity = nCapacity;
|
|
|
|
if (pOld != NULL) {
|
|
for (DWORD n = 0; n < nOld; n++) {
|
|
if (pOld[n] != NULL) {
|
|
Set(pOld[n]);
|
|
}
|
|
}
|
|
GlobalFree((HGLOBAL)pOld);
|
|
pOld = NULL;
|
|
}
|
|
s_nCapacity = nCapacity;
|
|
}
|
|
}
|
|
|
|
VOID FileNames::Set(FileInfo *info)
|
|
{
|
|
DWORD hash = info->m_nHash;
|
|
DWORD slot = hash % s_nCapacity;
|
|
DWORD death = 0;
|
|
|
|
// Find an empty slot.
|
|
for (; s_pFiles[slot] != NULL; slot = (slot + 1) % s_nCapacity) {
|
|
if (++death > s_nCapacity) {
|
|
// We should have dropped out at some point...
|
|
DEBUG_BREAK();
|
|
}
|
|
}
|
|
|
|
s_pFiles[slot] = info;
|
|
}
|
|
|
|
FileInfo * FileNames::FindFull(PCWSTR pwzPath)
|
|
{
|
|
if (pwzPath == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
LockAcquire();
|
|
|
|
DWORD hash = Hash(pwzPath);
|
|
DWORD slot = hash % s_nCapacity;
|
|
FileInfo *info = NULL;
|
|
DWORD death = 0;
|
|
|
|
// Find the the matching slot, or an empty one.
|
|
for (; s_pFiles[slot] != NULL; slot = (slot + 1) % s_nCapacity) {
|
|
if (Equal(s_pFiles[slot]->m_pwzPath, pwzPath)) {
|
|
info = s_pFiles[slot];
|
|
goto succeed;
|
|
}
|
|
if (++death > s_nCapacity) {
|
|
// We should have dropped out at some point...
|
|
DEBUG_BREAK();
|
|
}
|
|
}
|
|
|
|
// Add the file to list of known files.
|
|
info = (FileInfo *)GlobalAlloc(GPTR, sizeof(FileInfo));
|
|
info->m_nHash = hash;
|
|
info->m_nIndex = s_nFiles++;
|
|
info->m_pwzPath = Save(pwzPath);
|
|
info->m_fSystemPath = (PrefixMatch(info->m_pwzPath, s_wzSysPath) ||
|
|
PrefixMatch(info->m_pwzPath, s_wzS64Path));
|
|
info->m_fTemporaryPath = PrefixMatch(info->m_pwzPath, s_wzTmpPath);
|
|
info->m_fTemporaryFile = SuffixMatch(info->m_pwzPath, L".tmp");
|
|
|
|
s_pFiles[slot] = info;
|
|
|
|
// Check if we should grow the table.
|
|
if (s_nFiles > (s_nCapacity / 2)) {
|
|
Resize(s_nCapacity * 2 - 1);
|
|
}
|
|
|
|
succeed:
|
|
LockRelease();
|
|
|
|
return info;
|
|
}
|
|
|
|
FileInfo * FileNames::FindPartial(PCWSTR pwzPath)
|
|
{
|
|
WCHAR wzPath[MAX_PATH];
|
|
PWCHAR pwzFile = NULL;
|
|
|
|
if (!GetFullPathNameW(pwzPath, ARRAYSIZE(wzPath), wzPath, &pwzFile)) {
|
|
return FindFull(pwzPath);
|
|
}
|
|
else {
|
|
return FindFull(wzPath);
|
|
}
|
|
}
|
|
|
|
FileInfo * FileNames::FindPartial(PCSTR pwzPath)
|
|
{
|
|
WCHAR wzPath[MAX_PATH];
|
|
PWCHAR pwzFile = wzPath;
|
|
|
|
while (*pwzPath) {
|
|
*pwzFile++ = *pwzPath++;
|
|
}
|
|
*pwzFile = '\0';
|
|
|
|
return FindPartial(wzPath);
|
|
}
|
|
|
|
PCWSTR FileNames::ParameterizeName(PWCHAR pwzDst, DWORD cMaxDst, FileInfo *pInfo)
|
|
{
|
|
return ParameterizeName(pwzDst, cMaxDst, pInfo->m_pwzPath);
|
|
}
|
|
|
|
PCWSTR FileNames::ParameterizeName(PWCHAR pwzDst, DWORD cMaxDst, PCWSTR pwzPath)
|
|
{
|
|
if (PrefixMatch(pwzPath, s_wzSysPath)) {
|
|
Copy(pwzDst, L"%SYSDIR%\\");
|
|
Copy(pwzDst + Size(pwzDst), pwzPath + s_wcSysPath);
|
|
goto finish;
|
|
}
|
|
else if (PrefixMatch(pwzPath, s_wzS64Path)) {
|
|
Copy(pwzDst, L"%SYSDIR%\\");
|
|
Copy(pwzDst + Size(pwzDst), pwzPath + s_wcS64Path);
|
|
goto finish;
|
|
}
|
|
else if (PrefixMatch(pwzPath, s_wzTmpPath)) {
|
|
Copy(pwzDst, L"%TMPDIR%\\");
|
|
Copy(pwzDst + Size(pwzDst), pwzPath + s_wcTmpPath);
|
|
goto finish;
|
|
}
|
|
else {
|
|
Copy(pwzDst, pwzPath);
|
|
|
|
finish:
|
|
#if 0 // to convert to all lower case.
|
|
for (PWCHAR pwz = pwzDst; *pwz && pwz < pwzDst + cMaxDst; pwz++) {
|
|
if (*pwz >= 'A' && *pwz <= 'Z') {
|
|
*pwz = 'a' + (*pwz - 'A');
|
|
}
|
|
}
|
|
#else
|
|
(void)cMaxDst;
|
|
#endif
|
|
return pwzDst;
|
|
}
|
|
}
|
|
|
|
VOID FileNames::Replace(PWCHAR pwzDst, PWCHAR pwzDstEnd, DWORD cwOld, PCWSTR pwzNew)
|
|
{
|
|
DWORD cwNew = Size(pwzNew);
|
|
DWORD cwDst = Size(pwzDst);
|
|
|
|
if (cwOld < cwNew) { // We have to insert.
|
|
if ((cwDst + cwNew - cwOld) >= (DWORD)(pwzDstEnd - pwzDst)) {
|
|
// Won't fit, so abort.
|
|
return;
|
|
}
|
|
|
|
PWCHAR pwzTo = pwzDst + cwDst + (cwNew - cwOld);
|
|
PWCHAR pwzFm = pwzDst + cwDst;
|
|
|
|
while (pwzTo >= pwzDst) {
|
|
*pwzTo-- = *pwzFm--;
|
|
}
|
|
}
|
|
else if (cwOld > cwNew) { // We have to remove.
|
|
PWCHAR pwzTo = pwzDst + cwNew;
|
|
PWCHAR pwzFm = pwzDst + cwOld;
|
|
|
|
while (*pwzFm) {
|
|
*pwzTo++ = *pwzFm++;
|
|
}
|
|
*pwzTo = '\0';
|
|
}
|
|
|
|
// Now write the new string.
|
|
while (*pwzNew) {
|
|
*pwzDst++ = *pwzNew++;
|
|
}
|
|
}
|
|
|
|
VOID FileNames::ParameterizeLine(PWCHAR pwzDst, PWCHAR pwzDstEnd)
|
|
{
|
|
for (; *pwzDst != '\0'; pwzDst++) {
|
|
if (PrefixMatch(pwzDst, s_wzSysPath)) {
|
|
Replace(pwzDst, pwzDstEnd, s_wcSysPath, L"%SYSDIR%\\");
|
|
}
|
|
else if (PrefixMatch(pwzDst, s_wzS64Path)) {
|
|
Replace(pwzDst, pwzDstEnd, s_wcS64Path, L"%SYSDIR%\\");
|
|
}
|
|
else if (PrefixMatch(pwzDst, s_wzTmpPath)) {
|
|
Replace(pwzDst, pwzDstEnd, s_wcTmpPath, L"%TMPDIR%\\");
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID FileNames::Dump()
|
|
{
|
|
WCHAR wzPath[MAX_PATH];
|
|
|
|
if (s_nFiles == 0) {
|
|
return;
|
|
}
|
|
|
|
LockAcquire();
|
|
|
|
Tblog("<t:Files>\n");
|
|
|
|
FileInfo ** pSorted = (FileInfo **)GlobalAlloc(GPTR, s_nFiles * sizeof(FileInfo *));
|
|
|
|
for (DWORD n = 0; n < s_nCapacity; n++) {
|
|
if (s_pFiles[n] != NULL) {
|
|
if (s_pFiles[n]->m_nIndex > s_nFiles) {
|
|
DEBUG_BREAK();
|
|
}
|
|
pSorted[s_pFiles[n]->m_nIndex] = s_pFiles[n];
|
|
}
|
|
}
|
|
|
|
for (DWORD n = 0; n < s_nFiles; n++) {
|
|
FileInfo *pInfo = pSorted[n];
|
|
|
|
if (pInfo == NULL) {
|
|
Print("<!-- Warning: Missing %d of %d -->\n", n, s_nFiles);
|
|
continue;
|
|
}
|
|
|
|
BOOL fRead = pInfo->m_fRead;
|
|
BOOL fWrite = pInfo->m_fWrite;
|
|
BOOL fDelete = (pInfo->m_fDelete);
|
|
BOOL fCleanup = (pInfo->m_fCleanup);
|
|
BOOL fAppend = (pInfo->m_fAppend);
|
|
|
|
#if 0
|
|
if (fDelete && !fRead && !fWrite) {
|
|
Print("<!-- Discarding: %ls -->\n", pInfo->m_pwzPath);
|
|
// Discard pipe files only passed to children.
|
|
continue;
|
|
}
|
|
#endif
|
|
if (pInfo->m_fAbsorbed) {
|
|
// Discard response fles
|
|
continue;
|
|
}
|
|
|
|
if (PrefixMatch(pInfo->m_pwzPath, s_wzExePath) ||
|
|
PrefixMatch(pInfo->m_pwzPath, s_wzSysPath) ||
|
|
PrefixMatch(pInfo->m_pwzPath, s_wzS64Path)) {
|
|
// Discard files from exec directory (because considered internal to code).
|
|
continue;
|
|
}
|
|
|
|
#if 1 // Ignore PIPEs.
|
|
if (FileNames::PrefixMatch(pInfo->m_pwzPath, L"\\\\.\\PIPE\\")) {
|
|
continue;
|
|
}
|
|
#endif
|
|
if (FileNames::SuffixMatch(pInfo->m_pwzPath, L"\\conout$")) {
|
|
continue;
|
|
}
|
|
if (FileNames::SuffixMatch(pInfo->m_pwzPath, L"\\conin$")) {
|
|
continue;
|
|
}
|
|
if (FileNames::SuffixMatch(pInfo->m_pwzPath, L"\\nul")) {
|
|
continue;
|
|
}
|
|
|
|
ParameterizeName(wzPath, ARRAYSIZE(wzPath), pInfo);
|
|
|
|
if (pInfo->m_fDirectory) {
|
|
Print("<t:File mkdir=\"true\">%ls</t:File>\n", wzPath);
|
|
continue;
|
|
}
|
|
|
|
if (!fRead && !fWrite && !fDelete && !fCleanup) {
|
|
// Discard do "none" files.
|
|
continue;
|
|
}
|
|
|
|
if (pInfo->m_pbContent == NULL ||
|
|
pInfo->m_fDelete ||
|
|
pInfo->m_fCleanup ||
|
|
pInfo->m_fWrite) {
|
|
|
|
Print("<t:File%s%s%s%s%s>%ls</t:File>\n",
|
|
fRead ? " read=\"true\"" : "",
|
|
fWrite ? " write=\"true\"" : "",
|
|
fDelete ? " delete=\"true\"" : "",
|
|
fCleanup ? " cleanup=\"true\"" : "",
|
|
fAppend ? " append=\"true\"" : "",
|
|
// size=\"%d\" pInfo->m_cbContent,
|
|
wzPath);
|
|
}
|
|
else if ((pInfo->m_pbContent)[0] == 0xff && (pInfo->m_pbContent)[1] == 0xfe) {
|
|
// Unicode
|
|
Print("<t:File%s%s%s%s%s>%ls<t:Data>%le</t:Data></t:File>\n",
|
|
fRead ? " read=\"true\"" : "",
|
|
fWrite ? " write=\"true\"" : "",
|
|
fDelete ? " delete=\"true\"" : "",
|
|
fCleanup ? " cleanup=\"true\"" : "",
|
|
fAppend ? " append=\"true\"" : "",
|
|
// size=\"%d\" pInfo->m_cbContent,
|
|
wzPath,
|
|
RemoveReturns((PWCHAR)pInfo->m_pbContent));
|
|
}
|
|
else {
|
|
// Ascii
|
|
Print("<t:File%s%s%s%s%s>%ls<t:Data>%he</t:Data></t:File>\n",
|
|
fRead ? " read=\"true\"" : "",
|
|
fWrite ? " write=\"true\"" : "",
|
|
fDelete ? " delete=\"true\"" : "",
|
|
fCleanup ? " cleanup=\"true\"" : "",
|
|
fAppend ? " append=\"true\"" : "",
|
|
// size=\"%d\" pInfo->m_cbContent,
|
|
wzPath,
|
|
RemoveReturns((PCHAR)pInfo->m_pbContent));
|
|
}
|
|
|
|
if (pInfo->m_pbContent != NULL) {
|
|
GlobalFree((HGLOBAL)pInfo->m_pbContent);
|
|
pInfo->m_pbContent = NULL;
|
|
}
|
|
}
|
|
GlobalFree((HGLOBAL)pSorted);
|
|
|
|
Tblog("</t:Files>\n");
|
|
|
|
LockRelease();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
class OpenFiles
|
|
{
|
|
private:
|
|
struct SLOT
|
|
{
|
|
HANDLE m_hHandle;
|
|
FileInfo * m_pFile;
|
|
ProcInfo * m_pProc;
|
|
};
|
|
|
|
private:
|
|
static CRITICAL_SECTION s_csLock;
|
|
static DWORD s_nHandles;
|
|
static SLOT s_rHandles[4049];
|
|
|
|
private:
|
|
static SLOT& HashToSlot(HANDLE handle)
|
|
{
|
|
return s_rHandles[((DWORD_PTR)handle) % ARRAYSIZE(s_rHandles)];
|
|
}
|
|
|
|
static VOID LockAcquire()
|
|
{
|
|
EnterCriticalSection(&s_csLock);
|
|
}
|
|
|
|
static VOID LockRelease()
|
|
{
|
|
LeaveCriticalSection(&s_csLock);
|
|
}
|
|
|
|
public:
|
|
static VOID Initialize();
|
|
|
|
static VOID SetWrite(HANDLE hFile, DWORD cbData)
|
|
{
|
|
SLOT& slot = HashToSlot(hFile);
|
|
if (slot.m_hHandle == hFile) {
|
|
slot.m_pFile->m_fWrite = TRUE;
|
|
slot.m_pFile->m_cbWrite += cbData;
|
|
}
|
|
}
|
|
|
|
static VOID SetRead(HANDLE hFile, DWORD cbData)
|
|
{
|
|
SLOT& slot = HashToSlot(hFile);
|
|
if (slot.m_hHandle == hFile) {
|
|
slot.m_pFile->m_fRead = TRUE;
|
|
slot.m_pFile->m_cbRead += cbData;
|
|
}
|
|
}
|
|
|
|
static BOOL Forget(HANDLE handle);
|
|
static BOOL Remember(HANDLE hFile, FileInfo *pInfo);
|
|
static BOOL Remember(HANDLE hProc, ProcInfo *pInfo);
|
|
static FileInfo * RecallFile(HANDLE hFile);
|
|
static ProcInfo * RecallProc(HANDLE hProc);
|
|
};
|
|
|
|
CRITICAL_SECTION OpenFiles::s_csLock; // Guards access to OpenFile stuctures.
|
|
DWORD OpenFiles::s_nHandles = 0;
|
|
OpenFiles::SLOT OpenFiles::s_rHandles[4049];
|
|
|
|
VOID OpenFiles::Initialize()
|
|
{
|
|
InitializeCriticalSection(&s_csLock);
|
|
for (DWORD n = 0; n < ARRAYSIZE(s_rHandles); n++) {
|
|
s_rHandles[n].m_hHandle = INVALID_HANDLE_VALUE;
|
|
s_rHandles[n].m_pFile = NULL;
|
|
s_rHandles[n].m_pProc = NULL;
|
|
}
|
|
}
|
|
|
|
BOOL OpenFiles::Forget(HANDLE handle)
|
|
{
|
|
LockAcquire();
|
|
OpenFiles::SLOT& slot = HashToSlot(handle);
|
|
|
|
if (slot.m_hHandle == handle ) {
|
|
slot.m_hHandle = INVALID_HANDLE_VALUE;
|
|
slot.m_pFile = NULL;
|
|
slot.m_pProc = NULL;
|
|
s_nHandles--;
|
|
}
|
|
LockRelease();
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL OpenFiles::Remember(HANDLE hFile, FileInfo *pFile)
|
|
{
|
|
LockAcquire();
|
|
|
|
OpenFiles::SLOT& slot = HashToSlot(hFile);
|
|
if (slot.m_hHandle != hFile && slot.m_hHandle != INVALID_HANDLE_VALUE) {
|
|
// hash collision
|
|
DEBUG_BREAK();
|
|
}
|
|
|
|
slot.m_hHandle = hFile;
|
|
slot.m_pFile = pFile;
|
|
slot.m_pProc = NULL;
|
|
s_nHandles++;
|
|
|
|
LockRelease();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL OpenFiles::Remember(HANDLE hProc, ProcInfo *pProc)
|
|
{
|
|
LockAcquire();
|
|
|
|
OpenFiles::SLOT& slot = HashToSlot(hProc);
|
|
if (slot.m_hHandle != hProc && slot.m_hHandle != INVALID_HANDLE_VALUE) {
|
|
// hash collision
|
|
DEBUG_BREAK();
|
|
}
|
|
|
|
slot.m_hHandle = hProc;
|
|
slot.m_pProc = pProc;
|
|
slot.m_pFile = NULL;
|
|
s_nHandles++;
|
|
|
|
LockRelease();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
FileInfo * OpenFiles::RecallFile(HANDLE hFile)
|
|
{
|
|
LockAcquire();
|
|
|
|
OpenFiles::SLOT& slot = HashToSlot(hFile);
|
|
|
|
if (slot.m_hHandle == hFile) {
|
|
LockRelease();
|
|
return slot.m_pFile;
|
|
}
|
|
LockRelease();
|
|
return NULL;
|
|
}
|
|
|
|
ProcInfo * OpenFiles::RecallProc(HANDLE hProc)
|
|
{
|
|
LockAcquire();
|
|
|
|
OpenFiles::SLOT& slot = HashToSlot(hProc);
|
|
|
|
if (slot.m_hHandle == hProc) {
|
|
LockRelease();
|
|
return slot.m_pProc;
|
|
}
|
|
LockRelease();
|
|
return NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////// VPrintf.
|
|
//
|
|
// Completely side-effect free printf replacement (but no FP numbers).
|
|
//
|
|
static PCHAR do_base(PCHAR pszOut, UINT64 nValue, UINT nBase, PCSTR pszDigits)
|
|
{
|
|
CHAR szTmp[96];
|
|
int nDigit = sizeof(szTmp)-2;
|
|
for (; nDigit >= 0; nDigit--) {
|
|
szTmp[nDigit] = pszDigits[nValue % nBase];
|
|
nValue /= nBase;
|
|
}
|
|
for (nDigit = 0; nDigit < sizeof(szTmp) - 2 && szTmp[nDigit] == '0'; nDigit++) {
|
|
// skip leading zeros.
|
|
}
|
|
for (; nDigit < sizeof(szTmp) - 1; nDigit++) {
|
|
*pszOut++ = szTmp[nDigit];
|
|
}
|
|
*pszOut = '\0';
|
|
return pszOut;
|
|
}
|
|
|
|
static PCHAR do_str(PCHAR pszOut, PCHAR pszEnd, PCSTR pszIn)
|
|
{
|
|
while (*pszIn && pszOut < pszEnd) {
|
|
*pszOut++ = *pszIn++;
|
|
}
|
|
*pszOut = '\0';
|
|
return pszOut;
|
|
}
|
|
|
|
static PCHAR do_wstr(PCHAR pszOut, PCHAR pszEnd, PCWSTR pszIn)
|
|
{
|
|
while (*pszIn && pszOut < pszEnd) {
|
|
*pszOut++ = (CHAR)*pszIn++;
|
|
}
|
|
*pszOut = '\0';
|
|
return pszOut;
|
|
}
|
|
|
|
static PCHAR do_estr(PCHAR pszOut, PCHAR pszEnd, PCSTR pszIn)
|
|
{
|
|
while (*pszIn && pszOut < pszEnd) {
|
|
if (*pszIn == '<') {
|
|
if (pszOut + 4 > pszEnd) {
|
|
break;
|
|
}
|
|
pszIn++;
|
|
*pszOut++ = '&';
|
|
*pszOut++ = 'l';
|
|
*pszOut++ = 't';
|
|
*pszOut++ = ';';
|
|
}
|
|
else if (*pszIn == '>') {
|
|
if (pszOut + 4 > pszEnd) {
|
|
break;
|
|
}
|
|
pszIn++;
|
|
*pszOut++ = '&';
|
|
*pszOut++ = 'g';
|
|
*pszOut++ = 't';
|
|
*pszOut++ = ';';
|
|
}
|
|
else if (*pszIn == '&') {
|
|
if (pszOut + 5 > pszEnd) {
|
|
break;
|
|
}
|
|
pszIn++;
|
|
*pszOut++ = '&';
|
|
*pszOut++ = 'a';
|
|
*pszOut++ = 'm';
|
|
*pszOut++ = 'p';
|
|
*pszOut++ = ';';
|
|
}
|
|
else if (*pszIn == '\"') {
|
|
if (pszOut + 6 > pszEnd) {
|
|
break;
|
|
}
|
|
pszIn++;
|
|
*pszOut++ = '&';
|
|
*pszOut++ = 'q';
|
|
*pszOut++ = 'u';
|
|
*pszOut++ = 'o';
|
|
*pszOut++ = 't';
|
|
*pszOut++ = ';';
|
|
}
|
|
else if (*pszIn == '\'') {
|
|
if (pszOut + 6 > pszEnd) {
|
|
break;
|
|
}
|
|
pszIn++;
|
|
*pszOut++ = '&';
|
|
*pszOut++ = 'a';
|
|
*pszOut++ = 'p';
|
|
*pszOut++ = 'o';
|
|
*pszOut++ = 's';
|
|
*pszOut++ = ';';
|
|
}
|
|
else if (*pszIn < ' ') {
|
|
BYTE c = (BYTE)(*pszIn++);
|
|
if (c < 10 && pszOut + 4 <= pszEnd) {
|
|
*pszOut++ = '&';
|
|
*pszOut++ = '#';
|
|
*pszOut++ = '0' + (c % 10);
|
|
*pszOut++ = ';';
|
|
}
|
|
else if (c < 100 && pszOut + 5 <= pszEnd) {
|
|
*pszOut++ = '&';
|
|
*pszOut++ = '#';
|
|
*pszOut++ = '0' + ((c / 10) % 10);
|
|
*pszOut++ = '0' + (c % 10);
|
|
*pszOut++ = ';';
|
|
}
|
|
else if (c < 1000 && pszOut + 6 <= pszEnd) {
|
|
*pszOut++ = '&';
|
|
*pszOut++ = '#';
|
|
*pszOut++ = '0' + ((c / 100) % 10);
|
|
*pszOut++ = '0' + ((c / 10) % 10);
|
|
*pszOut++ = '0' + (c % 10);
|
|
*pszOut++ = ';';
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
*pszOut++ = *pszIn++;
|
|
}
|
|
}
|
|
*pszOut = '\0';
|
|
return pszOut;
|
|
}
|
|
|
|
static PCHAR do_ewstr(PCHAR pszOut, PCHAR pszEnd, PCWSTR pszIn)
|
|
{
|
|
while (*pszIn && pszOut < pszEnd) {
|
|
if (*pszIn == '<') {
|
|
if (pszOut + 4 > pszEnd) {
|
|
break;
|
|
}
|
|
pszIn++;
|
|
*pszOut++ = '&';
|
|
*pszOut++ = 'l';
|
|
*pszOut++ = 't';
|
|
*pszOut++ = ';';
|
|
}
|
|
else if (*pszIn == '>') {
|
|
if (pszOut + 4 > pszEnd) {
|
|
break;
|
|
}
|
|
pszIn++;
|
|
*pszOut++ = '&';
|
|
*pszOut++ = 'g';
|
|
*pszOut++ = 't';
|
|
*pszOut++ = ';';
|
|
}
|
|
else if (*pszIn == '&') {
|
|
if (pszOut + 5 > pszEnd) {
|
|
break;
|
|
}
|
|
pszIn++;
|
|
*pszOut++ = '&';
|
|
*pszOut++ = 'a';
|
|
*pszOut++ = 'm';
|
|
*pszOut++ = 'p';
|
|
*pszOut++ = ';';
|
|
}
|
|
else if (*pszIn == '\"') {
|
|
if (pszOut + 6 > pszEnd) {
|
|
break;
|
|
}
|
|
pszIn++;
|
|
*pszOut++ = '&';
|
|
*pszOut++ = 'q';
|
|
*pszOut++ = 'u';
|
|
*pszOut++ = 'o';
|
|
*pszOut++ = 't';
|
|
*pszOut++ = ';';
|
|
}
|
|
else if (*pszIn == '\'') {
|
|
if (pszOut + 6 > pszEnd) {
|
|
break;
|
|
}
|
|
pszIn++;
|
|
*pszOut++ = '&';
|
|
*pszOut++ = 'a';
|
|
*pszOut++ = 'p';
|
|
*pszOut++ = 'o';
|
|
*pszOut++ = 's';
|
|
*pszOut++ = ';';
|
|
}
|
|
else if (*pszIn < ' ' || *pszIn > 127) {
|
|
WCHAR c = *pszIn++;
|
|
if (c < 10 && pszOut + 4 <= pszEnd) {
|
|
*pszOut++ = '&';
|
|
*pszOut++ = '#';
|
|
*pszOut++ = '0' + (CHAR)(c % 10);
|
|
*pszOut++ = ';';
|
|
}
|
|
else if (c < 100 && pszOut + 5 <= pszEnd) {
|
|
*pszOut++ = '&';
|
|
*pszOut++ = '#';
|
|
*pszOut++ = '0' + (CHAR)((c / 10) % 10);
|
|
*pszOut++ = '0' + (CHAR)(c % 10);
|
|
*pszOut++ = ';';
|
|
}
|
|
else if (c < 1000 && pszOut + 6 <= pszEnd) {
|
|
*pszOut++ = '&';
|
|
*pszOut++ = '#';
|
|
*pszOut++ = '0' + (CHAR)((c / 100) % 10);
|
|
*pszOut++ = '0' + (CHAR)((c / 10) % 10);
|
|
*pszOut++ = '0' + (CHAR)(c % 10);
|
|
*pszOut++ = ';';
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
*pszOut++ = (CHAR)*pszIn++;
|
|
}
|
|
}
|
|
*pszOut = '\0';
|
|
return pszOut;
|
|
}
|
|
|
|
#if _MSC_VER >= 1900
|
|
#pragma warning(push)
|
|
#pragma warning(disable:4456) // declaration hides previous local declaration
|
|
#endif
|
|
|
|
VOID VSafePrintf(PCSTR pszMsg, va_list args, PCHAR pszBuffer, LONG cbBuffer)
|
|
{
|
|
PCHAR pszOut = pszBuffer;
|
|
PCHAR pszEnd = pszBuffer + cbBuffer - 1;
|
|
pszBuffer[0] = '\0';
|
|
|
|
__try {
|
|
while (*pszMsg && pszOut < pszEnd) {
|
|
if (*pszMsg == '%') {
|
|
CHAR szHead[4] = "";
|
|
INT nLen;
|
|
INT nWidth = 0;
|
|
INT nPrecision = 0;
|
|
BOOL fLeft = FALSE;
|
|
BOOL fPositive = FALSE;
|
|
BOOL fPound = FALSE;
|
|
BOOL fBlank = FALSE;
|
|
BOOL fZero = FALSE;
|
|
BOOL fDigit = FALSE;
|
|
BOOL fSmall = FALSE;
|
|
BOOL fLarge = FALSE;
|
|
BOOL f64Bit = FALSE;
|
|
PCSTR pszArg = pszMsg;
|
|
|
|
pszMsg++;
|
|
|
|
for (; (*pszMsg == '-' ||
|
|
*pszMsg == '+' ||
|
|
*pszMsg == '#' ||
|
|
*pszMsg == ' ' ||
|
|
*pszMsg == '0'); pszMsg++) {
|
|
switch (*pszMsg) {
|
|
case '-': fLeft = TRUE; break;
|
|
case '+': fPositive = TRUE; break;
|
|
case '#': fPound = TRUE; break;
|
|
case ' ': fBlank = TRUE; break;
|
|
case '0': fZero = TRUE; break;
|
|
}
|
|
}
|
|
|
|
if (*pszMsg == '*') {
|
|
nWidth = va_arg(args, INT);
|
|
pszMsg++;
|
|
}
|
|
else {
|
|
while (*pszMsg >= '0' && *pszMsg <= '9') {
|
|
nWidth = nWidth * 10 + (*pszMsg++ - '0');
|
|
}
|
|
}
|
|
if (*pszMsg == '.') {
|
|
pszMsg++;
|
|
fDigit = TRUE;
|
|
if (*pszMsg == '*') {
|
|
nPrecision = va_arg(args, INT);
|
|
pszMsg++;
|
|
}
|
|
else {
|
|
while (*pszMsg >= '0' && *pszMsg <= '9') {
|
|
nPrecision = nPrecision * 10 + (*pszMsg++ - '0');
|
|
}
|
|
}
|
|
}
|
|
|
|
if (*pszMsg == 'h') {
|
|
fSmall = TRUE;
|
|
pszMsg++;
|
|
}
|
|
else if (*pszMsg == 'l') {
|
|
fLarge = TRUE;
|
|
pszMsg++;
|
|
}
|
|
else if (*pszMsg == 'I' && pszMsg[1] == '6' && pszMsg[2] == '4') {
|
|
f64Bit = TRUE;
|
|
pszMsg += 3;
|
|
}
|
|
|
|
if (*pszMsg == 's' || *pszMsg == 'e' || *pszMsg == 'c') {
|
|
// We ignore the length, precision, and alignment
|
|
// to avoid using a temporary buffer.
|
|
|
|
if (*pszMsg == 's') { // [GalenH] need to not use temp.
|
|
PVOID pvData = va_arg(args, PVOID);
|
|
|
|
pszMsg++;
|
|
|
|
if (fSmall) {
|
|
fLarge = FALSE;
|
|
}
|
|
|
|
__try {
|
|
if (pvData == NULL) {
|
|
pszOut = do_str(pszOut, pszEnd, "-NULL-");
|
|
}
|
|
else if (fLarge) {
|
|
pszOut = do_wstr(pszOut, pszEnd, (PWCHAR)pvData);
|
|
}
|
|
else {
|
|
pszOut = do_str(pszOut, pszEnd, (PCHAR)pvData);
|
|
}
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
pszOut = do_str(pszOut, pszEnd, "-");
|
|
pszOut = do_base(pszOut, (UINT64)pvData, 16,
|
|
"0123456789ABCDEF");
|
|
pszOut = do_str(pszOut, pszEnd, "-");
|
|
}
|
|
}
|
|
else if (*pszMsg == 'e') { // Escape the string.
|
|
PVOID pvData = va_arg(args, PVOID);
|
|
|
|
pszMsg++;
|
|
|
|
if (fSmall) {
|
|
fLarge = FALSE;
|
|
}
|
|
|
|
__try {
|
|
if (pvData == NULL) {
|
|
pszOut = do_str(pszOut, pszEnd, "-NULL-");
|
|
}
|
|
else if (fLarge) {
|
|
pszOut = do_ewstr(pszOut, pszEnd, (PWCHAR)pvData);
|
|
}
|
|
else {
|
|
pszOut = do_estr(pszOut, pszEnd, (PCHAR)pvData);
|
|
}
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
pszOut = do_str(pszOut, pszEnd, "-");
|
|
pszOut = do_base(pszOut, (UINT64)pvData, 16,
|
|
"0123456789ABCDEF");
|
|
pszOut = do_str(pszOut, pszEnd, "-");
|
|
}
|
|
}
|
|
else {
|
|
CHAR szTemp[2];
|
|
pszMsg++;
|
|
|
|
szTemp[0] = (CHAR)va_arg(args, INT);
|
|
szTemp[1] = '\0';
|
|
pszOut = do_str(pszOut, pszEnd, szTemp);
|
|
}
|
|
}
|
|
else if (*pszMsg == 'd' || *pszMsg == 'i' || *pszMsg == 'o' ||
|
|
*pszMsg == 'x' || *pszMsg == 'X' || *pszMsg == 'b' ||
|
|
*pszMsg == 'u') {
|
|
CHAR szTemp[128];
|
|
UINT64 value;
|
|
if (f64Bit) {
|
|
value = va_arg(args, UINT64);
|
|
}
|
|
else {
|
|
value = va_arg(args, UINT);
|
|
}
|
|
|
|
if (*pszMsg == 'x') {
|
|
pszMsg++;
|
|
nLen = (int)(do_base(szTemp, value, 16, "0123456789abcdef") - szTemp);
|
|
if (fPound && value) {
|
|
do_str(szHead, szHead + sizeof(szHead) - 1, "0x");
|
|
}
|
|
}
|
|
else if (*pszMsg == 'X') {
|
|
pszMsg++;
|
|
nLen = (int)(do_base(szTemp, value, 16, "0123456789ABCDEF") - szTemp);
|
|
if (fPound && value) {
|
|
do_str(szHead, szHead + sizeof(szHead) - 1, "0X");
|
|
}
|
|
}
|
|
else if (*pszMsg == 'd') {
|
|
pszMsg++;
|
|
if ((INT64)value < 0) {
|
|
value = -(INT64)value;
|
|
do_str(szHead, szHead + sizeof(szHead) - 1, "-");
|
|
}
|
|
else if (fPositive) {
|
|
if (value > 0) {
|
|
do_str(szHead, szHead + sizeof(szHead) - 1, "+");
|
|
}
|
|
}
|
|
else if (fBlank) {
|
|
if (value > 0) {
|
|
do_str(szHead, szHead + sizeof(szHead) - 1, " ");
|
|
}
|
|
}
|
|
nLen = (int)(do_base(szTemp, value, 10, "0123456789") - szTemp);
|
|
nPrecision = 0;
|
|
}
|
|
else if (*pszMsg == 'u') {
|
|
pszMsg++;
|
|
nLen = (int)(do_base(szTemp, value, 10, "0123456789") - szTemp);
|
|
nPrecision = 0;
|
|
}
|
|
else if (*pszMsg == 'o') {
|
|
pszMsg++;
|
|
nLen = (int)(do_base(szTemp, value, 8, "01234567") - szTemp);
|
|
nPrecision = 0;
|
|
|
|
if (fPound && value) {
|
|
do_str(szHead, szHead + sizeof(szHead) - 1, "0");
|
|
}
|
|
}
|
|
else if (*pszMsg == 'b') {
|
|
pszMsg++;
|
|
nLen = (int)(do_base(szTemp, value, 2, "01") - szTemp);
|
|
nPrecision = 0;
|
|
|
|
if (fPound && value) {
|
|
do_str(szHead, szHead + sizeof(szHead) - 1, "0b");
|
|
}
|
|
}
|
|
else {
|
|
pszMsg++;
|
|
if ((INT64)value < 0) {
|
|
value = -(INT64)value;
|
|
do_str(szHead, szHead + sizeof(szHead) - 1, "-");
|
|
}
|
|
else if (fPositive) {
|
|
if (value > 0) {
|
|
do_str(szHead, szHead + sizeof(szHead) - 1, "+");
|
|
}
|
|
}
|
|
else if (fBlank) {
|
|
if (value > 0) {
|
|
do_str(szHead, szHead + sizeof(szHead) - 1, " ");
|
|
}
|
|
}
|
|
nLen = (int)(do_base(szTemp, value, 10, "0123456789") - szTemp);
|
|
nPrecision = 0;
|
|
}
|
|
|
|
INT nHead = 0;
|
|
for (; szHead[nHead]; nHead++) {
|
|
// Count characters in head string.
|
|
}
|
|
|
|
if (fLeft) {
|
|
if (nHead) {
|
|
pszOut = do_str(pszOut, pszEnd, szHead);
|
|
nLen += nHead;
|
|
}
|
|
pszOut = do_str(pszOut, pszEnd, szTemp);
|
|
for (; nLen < nWidth && pszOut < pszEnd; nLen++) {
|
|
*pszOut++ = ' ';
|
|
}
|
|
}
|
|
else if (fZero) {
|
|
if (nHead) {
|
|
pszOut = do_str(pszOut, pszEnd, szHead);
|
|
nLen += nHead;
|
|
}
|
|
for (; nLen < nWidth && pszOut < pszEnd; nLen++) {
|
|
*pszOut++ = '0';
|
|
}
|
|
pszOut = do_str(pszOut, pszEnd, szTemp);
|
|
}
|
|
else {
|
|
if (nHead) {
|
|
nLen += nHead;
|
|
}
|
|
for (; nLen < nWidth && pszOut < pszEnd; nLen++) {
|
|
*pszOut++ = ' ';
|
|
}
|
|
if (nHead) {
|
|
pszOut = do_str(pszOut, pszEnd, szHead);
|
|
}
|
|
pszOut = do_str(pszOut, pszEnd, szTemp);
|
|
}
|
|
}
|
|
else if (*pszMsg == 'p') {
|
|
CHAR szTemp[64];
|
|
ULONG_PTR value;
|
|
value = va_arg(args, ULONG_PTR);
|
|
|
|
if (*pszMsg == 'p') {
|
|
pszMsg++;
|
|
nLen = (int)(do_base(szTemp, (UINT64)value, 16, "0123456789abcdef") - szTemp);
|
|
if (fPound && value) {
|
|
do_str(szHead, szHead + sizeof(szHead) - 1, "0x");
|
|
}
|
|
}
|
|
else {
|
|
pszMsg++;
|
|
nLen = (int)(do_base(szTemp, (UINT64)value, 16, "0123456789ABCDEF") - szTemp);
|
|
if (fPound && value) {
|
|
do_str(szHead, szHead + sizeof(szHead) - 1, "0x");
|
|
}
|
|
}
|
|
|
|
INT nHead = 0;
|
|
for (; szHead[nHead]; nHead++) {
|
|
// Count characters in head string.
|
|
}
|
|
|
|
if (nHead) {
|
|
pszOut = do_str(pszOut, pszEnd, szHead);
|
|
nLen += nHead;
|
|
}
|
|
for (; nLen < nWidth && pszOut < pszEnd; nLen++) {
|
|
*pszOut++ = '0';
|
|
}
|
|
pszOut = do_str(pszOut, pszEnd, szTemp);
|
|
}
|
|
else {
|
|
pszMsg++;
|
|
while (pszArg < pszMsg && pszOut < pszEnd) {
|
|
*pszOut++ = *pszArg++;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (pszOut < pszEnd) {
|
|
*pszOut++ = *pszMsg++;
|
|
}
|
|
}
|
|
}
|
|
*pszOut = '\0';
|
|
pszBuffer[cbBuffer - 1] = '\0';
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
PCHAR pszOut = pszBuffer;
|
|
*pszOut = '\0';
|
|
pszOut = do_str(pszOut, pszEnd, "-exception:");
|
|
pszOut = do_base(pszOut, (UINT64)GetExceptionCode(), 10, "0123456789");
|
|
pszOut = do_str(pszOut, pszEnd, "-");
|
|
}
|
|
}
|
|
|
|
#if _MSC_VER >= 1900
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
PCHAR SafePrintf(PCHAR pszBuffer, LONG cbBuffer, PCSTR pszMsg, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, pszMsg);
|
|
VSafePrintf(pszMsg, args, pszBuffer, cbBuffer);
|
|
va_end(args);
|
|
|
|
while (*pszBuffer) {
|
|
pszBuffer++;
|
|
}
|
|
return pszBuffer;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
BOOL TblogOpen()
|
|
{
|
|
EnterCriticalSection(&s_csPipe);
|
|
|
|
WCHAR wzPipe[256];
|
|
StringCchPrintfW(wzPipe, ARRAYSIZE(wzPipe), L"%ls.%d", TBLOG_PIPE_NAMEW, s_nTraceProcessId);
|
|
|
|
for (int retries = 0; retries < 10; retries++) {
|
|
WaitNamedPipeW(wzPipe, 10000); // Wait up to 10 seconds for a pipe to appear.
|
|
|
|
s_hPipe = Real_CreateFileW(wzPipe, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
|
if (s_hPipe != INVALID_HANDLE_VALUE) {
|
|
DWORD dwMode = PIPE_READMODE_MESSAGE;
|
|
if (SetNamedPipeHandleState(s_hPipe, &dwMode, NULL, NULL)) {
|
|
LeaveCriticalSection(&s_csPipe);
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&s_csPipe);
|
|
|
|
// Couldn't open pipe.
|
|
DEBUG_BREAK();
|
|
Real_ExitProcess(9990);
|
|
return FALSE;
|
|
}
|
|
|
|
VOID TblogV(PCSTR pszMsgf, va_list args)
|
|
{
|
|
if (s_hPipe == INVALID_HANDLE_VALUE) {
|
|
return;
|
|
}
|
|
|
|
EnterCriticalSection(&s_csPipe);
|
|
|
|
DWORD cbWritten = 0;
|
|
|
|
PCHAR pszBuf = s_rMessage.szMessage;
|
|
VSafePrintf(pszMsgf, args,
|
|
pszBuf, (int)(s_rMessage.szMessage + sizeof(s_rMessage.szMessage) - pszBuf));
|
|
|
|
PCHAR pszEnd = s_rMessage.szMessage;
|
|
for (; *pszEnd; pszEnd++) {
|
|
// no internal contents.
|
|
}
|
|
s_rMessage.nBytes = (DWORD)(pszEnd - ((PCSTR)&s_rMessage));
|
|
|
|
// If the write fails, then we abort
|
|
if (s_hPipe != INVALID_HANDLE_VALUE) {
|
|
if (!Real_WriteFile(s_hPipe, &s_rMessage, s_rMessage.nBytes, &cbWritten, NULL)) {
|
|
Real_ExitProcess(9991);
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&s_csPipe);
|
|
}
|
|
|
|
VOID Tblog(PCSTR pszMsgf, ...)
|
|
{
|
|
if (s_hPipe == INVALID_HANDLE_VALUE) {
|
|
return;
|
|
}
|
|
|
|
va_list args;
|
|
va_start(args, pszMsgf);
|
|
TblogV(pszMsgf, args);
|
|
va_end(args);
|
|
}
|
|
|
|
VOID TblogClose()
|
|
{
|
|
EnterCriticalSection(&s_csPipe);
|
|
|
|
if (s_hPipe != INVALID_HANDLE_VALUE) {
|
|
DWORD cbWritten = 0;
|
|
|
|
s_rMessage.nBytes = 0;
|
|
|
|
Real_WriteFile(s_hPipe, &s_rMessage, 4, &cbWritten, NULL);
|
|
FlushFileBuffers(s_hPipe);
|
|
Real_CloseHandle(s_hPipe);
|
|
s_hPipe = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
LeaveCriticalSection(&s_csPipe);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// Detours
|
|
//
|
|
static BOOL IsInherited(HANDLE hHandle)
|
|
{
|
|
DWORD dwFlags;
|
|
|
|
if (GetHandleInformation(hHandle, &dwFlags)) {
|
|
return (dwFlags & HANDLE_FLAG_INHERIT) ? TRUE : FALSE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static void SaveStdHandleName(HANDLE hFile, PWCHAR pwzBuffer, BOOL *fAppend)
|
|
{
|
|
pwzBuffer[0] = '\0';
|
|
|
|
if ((hFile != INVALID_HANDLE_VALUE) && IsInherited(hFile)) {
|
|
FileInfo * pInfo = OpenFiles::RecallFile(hFile);
|
|
if (pInfo) {
|
|
Copy(pwzBuffer, pInfo->m_pwzPath);
|
|
if (pInfo->m_fAppend && fAppend != NULL) {
|
|
*fAppend = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void LoadStdHandleName(DWORD id, PCWSTR pwzBuffer, BOOL fAppend)
|
|
{
|
|
HANDLE hFile = GetStdHandle(id);
|
|
|
|
if ((hFile != INVALID_HANDLE_VALUE) && pwzBuffer[0] != '\0') {
|
|
FileInfo *pInfo = FileNames::FindPartial(pwzBuffer);
|
|
if (fAppend) {
|
|
pInfo->m_fAppend = TRUE;
|
|
}
|
|
OpenFiles::Remember(hFile, pInfo);
|
|
}
|
|
}
|
|
|
|
BOOL CreateProcessInternals(HANDLE hProcess, DWORD nProcessId, PCHAR pszId,
|
|
HANDLE hStdin, HANDLE hStdout, HANDLE hStderr)
|
|
{
|
|
EnterCriticalSection(&s_csChildPayload);
|
|
|
|
ProcInfo *proc = Procs::Create(hProcess, nProcessId);
|
|
OpenFiles::Remember(hProcess, proc);
|
|
|
|
ZeroMemory(&s_ChildPayload, sizeof(s_ChildPayload));
|
|
CopyMemory(&s_ChildPayload, &s_Payload, sizeof(s_ChildPayload));
|
|
|
|
s_ChildPayload.nParentProcessId = GetCurrentProcessId();
|
|
s_ChildPayload.rGeneology[s_ChildPayload.nGeneology]
|
|
= (DWORD)InterlockedIncrement(&s_nChildCnt);
|
|
s_ChildPayload.nGeneology++;
|
|
|
|
SaveStdHandleName(hStdin, s_ChildPayload.wzStdin, NULL);
|
|
SaveStdHandleName(hStdout, s_ChildPayload.wzStdout, &s_ChildPayload.fStdoutAppend);
|
|
SaveStdHandleName(hStderr, s_ChildPayload.wzStderr, &s_ChildPayload.fStderrAppend);
|
|
|
|
DetourCopyPayloadToProcess(hProcess, s_guidTrace, &s_ChildPayload, sizeof(s_ChildPayload));
|
|
|
|
for (DWORD i = 0; i < s_ChildPayload.nGeneology; i++) {
|
|
pszId = SafePrintf(pszId, 16, "%d.", s_ChildPayload.rGeneology[i]);
|
|
}
|
|
*pszId = '\0';
|
|
|
|
LeaveCriticalSection(&s_csChildPayload);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
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)
|
|
{
|
|
EnterFunc();
|
|
|
|
if (lpCommandLine == NULL) {
|
|
lpCommandLine = (LPWSTR)lpApplicationName;
|
|
}
|
|
|
|
CHAR szProc[MAX_PATH];
|
|
BOOL rv = 0;
|
|
__try {
|
|
LPPROCESS_INFORMATION ppi = lpProcessInformation;
|
|
PROCESS_INFORMATION pi;
|
|
if (ppi == NULL) {
|
|
ppi = π
|
|
}
|
|
|
|
rv = DetourCreateProcessWithDllExW(lpApplicationName,
|
|
lpCommandLine,
|
|
lpProcessAttributes,
|
|
lpThreadAttributes,
|
|
bInheritHandles,
|
|
dwCreationFlags | CREATE_SUSPENDED,
|
|
lpEnvironment,
|
|
lpCurrentDirectory,
|
|
lpStartupInfo,
|
|
ppi,
|
|
s_szDllPath,
|
|
Real_CreateProcessW);
|
|
|
|
if (rv) {
|
|
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
|
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
|
|
|
|
if (lpStartupInfo != NULL && (lpStartupInfo->dwFlags & STARTF_USESTDHANDLES) != 0) {
|
|
hStdin = lpStartupInfo->hStdInput;
|
|
hStdout = lpStartupInfo->hStdOutput;
|
|
hStderr = lpStartupInfo->hStdError;
|
|
}
|
|
CreateProcessInternals(ppi->hProcess, ppi->dwProcessId,
|
|
szProc, hStdin, hStdout, hStderr);
|
|
|
|
Print("<t:Child id=\"::%hs::\">\n", szProc);
|
|
|
|
WCHAR wzPath[MAX_PATH];
|
|
FileInfo *pInfo = NULL;
|
|
if (lpApplicationName == NULL) {
|
|
PWCHAR pwzDst = wzPath;
|
|
PWCHAR pwzSrc = lpCommandLine;
|
|
|
|
if (*pwzSrc == '\"') {
|
|
WCHAR cQuote = *pwzSrc++;
|
|
|
|
while (*pwzSrc && *pwzSrc != cQuote) {
|
|
*pwzDst++ = *pwzSrc++;
|
|
}
|
|
*pwzDst++ = '\0';
|
|
}
|
|
else {
|
|
while (*pwzSrc && *pwzSrc != ' ' && *pwzSrc != '\t') {
|
|
if (*pwzSrc == '\t') {
|
|
*pwzSrc = ' ';
|
|
}
|
|
*pwzDst++ = *pwzSrc++;
|
|
}
|
|
*pwzDst++ = '\0';
|
|
}
|
|
pInfo = FileNames::FindPartial(wzPath);
|
|
}
|
|
else {
|
|
pInfo = FileNames::FindPartial(lpApplicationName);
|
|
}
|
|
|
|
Print("<t:Executable>%ls</t:Executable>\n",
|
|
FileNames::ParameterizeName(wzPath, ARRAYSIZE(wzPath), pInfo));
|
|
Print("<t:Line>%le</t:Line>\n", lpCommandLine);
|
|
Print("</t:Child>\n");
|
|
|
|
if (pInfo) {
|
|
pInfo->m_fAbsorbed = true;
|
|
}
|
|
|
|
if (!(dwCreationFlags & CREATE_SUSPENDED)) {
|
|
ResumeThread(ppi->hThread);
|
|
}
|
|
|
|
if (ppi == &pi) {
|
|
Real_CloseHandle(ppi->hThread);
|
|
Real_CloseHandle(ppi->hProcess);
|
|
}
|
|
}
|
|
} __finally {
|
|
ExitFunc();
|
|
if (!rv) {
|
|
Print("<!-- Warning: CreateProcessW failed %d: %ls; %ls -->\n",
|
|
GetLastError(), lpApplicationName, lpCommandLine);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_CreateProcessA(LPCSTR lpApplicationName,
|
|
LPSTR lpCommandLine,
|
|
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
|
BOOL bInheritHandles,
|
|
DWORD dwCreationFlags,
|
|
LPVOID lpEnvironment,
|
|
LPCSTR lpCurrentDirectory,
|
|
LPSTARTUPINFOA lpStartupInfo,
|
|
LPPROCESS_INFORMATION lpProcessInformation)
|
|
{
|
|
EnterFunc();
|
|
|
|
if (lpCommandLine == NULL) {
|
|
lpCommandLine = (LPSTR)lpApplicationName;
|
|
}
|
|
|
|
CHAR szProc[MAX_PATH];
|
|
BOOL rv = 0;
|
|
__try {
|
|
LPPROCESS_INFORMATION ppi = lpProcessInformation;
|
|
PROCESS_INFORMATION pi;
|
|
if (ppi == NULL) {
|
|
ppi = π
|
|
}
|
|
|
|
rv = DetourCreateProcessWithDllExA(lpApplicationName,
|
|
lpCommandLine,
|
|
lpProcessAttributes,
|
|
lpThreadAttributes,
|
|
bInheritHandles,
|
|
dwCreationFlags | CREATE_SUSPENDED,
|
|
lpEnvironment,
|
|
lpCurrentDirectory,
|
|
lpStartupInfo,
|
|
ppi,
|
|
s_szDllPath,
|
|
Real_CreateProcessA);
|
|
|
|
if (rv) {
|
|
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
|
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
|
|
|
|
if (lpStartupInfo != NULL && (lpStartupInfo->dwFlags & STARTF_USESTDHANDLES) != 0) {
|
|
hStdin = lpStartupInfo->hStdInput;
|
|
hStdout = lpStartupInfo->hStdOutput;
|
|
hStderr = lpStartupInfo->hStdError;
|
|
}
|
|
CreateProcessInternals(ppi->hProcess, ppi->dwProcessId,
|
|
szProc, hStdin, hStdout, hStderr);
|
|
|
|
Print("<t:Child id=\"::%hs::\">\n", szProc);
|
|
|
|
WCHAR wzPath[MAX_PATH];
|
|
FileInfo *pInfo = NULL;
|
|
if (lpApplicationName == NULL) {
|
|
PCHAR pszDst = szProc;
|
|
PCHAR pszSrc = lpCommandLine;
|
|
|
|
if (*pszSrc == '\"') {
|
|
CHAR cQuote = *pszSrc++;
|
|
|
|
while (*pszSrc && *pszSrc != cQuote) {
|
|
*pszDst++ = *pszSrc++;
|
|
}
|
|
*pszDst++ = '\0';
|
|
}
|
|
else {
|
|
while (*pszSrc && *pszSrc != ' ' && *pszSrc != '\t') {
|
|
if (*pszSrc == '\t') {
|
|
*pszSrc = ' ';
|
|
}
|
|
*pszDst++ = *pszSrc++;
|
|
}
|
|
*pszDst++ = '\0';
|
|
}
|
|
pInfo = FileNames::FindPartial(szProc);
|
|
}
|
|
else {
|
|
pInfo = FileNames::FindPartial(lpApplicationName);
|
|
}
|
|
|
|
Print("<t:Executable>%ls</t:Executable>\n",
|
|
FileNames::ParameterizeName(wzPath, ARRAYSIZE(wzPath), pInfo));
|
|
Print("<t:Line>%he</t:Line>\n", lpCommandLine);
|
|
Print("</t:Child>\n");
|
|
|
|
if (pInfo) {
|
|
pInfo->m_fAbsorbed = true;
|
|
}
|
|
|
|
if (!(dwCreationFlags & CREATE_SUSPENDED)) {
|
|
ResumeThread(ppi->hThread);
|
|
}
|
|
if (ppi == &pi) {
|
|
Real_CloseHandle(ppi->hThread);
|
|
Real_CloseHandle(ppi->hProcess);
|
|
}
|
|
}
|
|
} __finally {
|
|
ExitFunc();
|
|
if (!rv) {
|
|
Print("<!-- Warning: CreateProcessA failed %d: %hs; %hs -->\n",
|
|
GetLastError(), lpApplicationName, lpCommandLine);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL WINAPI Mine_CopyFileExA(LPCSTR a0,
|
|
LPCSTR a1,
|
|
LPPROGRESS_ROUTINE a2,
|
|
LPVOID a3,
|
|
LPBOOL a4,
|
|
DWORD a5)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_CopyFileExA(a0, a1, a2, a3, a4, a5);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (rv) {
|
|
#if 0
|
|
Print("<!-- CopyFileExA %he to %he -->\n", a0, a1);
|
|
#endif
|
|
NoteRead(a0);
|
|
NoteWrite(a1);
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_CopyFileExW(LPCWSTR a0,
|
|
LPCWSTR a1,
|
|
LPPROGRESS_ROUTINE a2,
|
|
LPVOID a3,
|
|
LPBOOL a4,
|
|
DWORD a5)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
#if 0
|
|
Print("\n");
|
|
Print("<!-- CopyFileExW %le to %le before -->\n", a0, a1);
|
|
#endif
|
|
rv = Real_CopyFileExW(a0, a1, a2, a3, a4, a5);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (rv) {
|
|
#if 0
|
|
Print("<!-- CopyFileExW %le to %le -->\n", a0, a1);
|
|
#endif
|
|
NoteRead(a0);
|
|
NoteWrite(a1);
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_PrivCopyFileExW(LPCWSTR a0,
|
|
LPCWSTR a1,
|
|
LPPROGRESS_ROUTINE a2,
|
|
LPVOID a3,
|
|
LPBOOL a4,
|
|
DWORD a5)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_PrivCopyFileExW(a0, a1, a2, a3, a4, a5);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (rv) {
|
|
#if 0
|
|
Print("<!-- PrivCopyFileExW %le to %le -->\n", a0, a1);
|
|
#endif
|
|
NoteRead(a0);
|
|
NoteWrite(a1);
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_CreateHardLinkA(LPCSTR a0,
|
|
LPCSTR a1,
|
|
LPSECURITY_ATTRIBUTES a2)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_CreateHardLinkA(a0, a1, a2);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (rv) {
|
|
#if 0
|
|
Print("<!-- CreateHardLinkA %he to %he -->\n", a0, a1);
|
|
#endif
|
|
NoteRead(a1);
|
|
NoteWrite(a0);
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_CreateHardLinkW(LPCWSTR a0,
|
|
LPCWSTR a1,
|
|
LPSECURITY_ATTRIBUTES a2)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_CreateHardLinkW(a0, a1, a2);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (rv) {
|
|
#if 0
|
|
Print("<!-- CreateHardLinkW %le to %le -->\n", a0, a1);
|
|
#endif
|
|
NoteRead(a1);
|
|
NoteWrite(a0);
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_CloseHandle(HANDLE a0)
|
|
{
|
|
/*int nIndent =*/ EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
ProcInfo * pProc = OpenFiles::RecallProc(a0);
|
|
if (pProc != NULL) {
|
|
Procs::Close(pProc->m_hProc);
|
|
}
|
|
|
|
FileInfo * pFile = OpenFiles::RecallFile(a0);
|
|
if (pFile != NULL) {
|
|
DWORD dwErr = GetLastError();
|
|
pFile->m_cbContent = GetFileSize(a0, NULL);
|
|
if (pFile->m_cbContent == INVALID_FILE_SIZE) {
|
|
pFile->m_cbContent = 0;
|
|
}
|
|
|
|
if (pFile->m_fCantRead) {
|
|
if (pFile->m_fRead) {
|
|
#if 0
|
|
Print("<!-- Warning: Removing read from %le -->\n", pFile->m_pwzPath);
|
|
#endif
|
|
pFile->m_fRead = FALSE;
|
|
}
|
|
}
|
|
|
|
// Here we should think about reading the file contents as appropriate.
|
|
if (pFile->m_fTemporaryPath && pFile->m_fRead && !pFile->m_fAbsorbed &&
|
|
!pFile->m_fDelete && !pFile->m_fCleanup && !pFile->m_fWrite &&
|
|
pFile->m_pbContent == NULL &&
|
|
pFile->m_cbContent < 16384) {
|
|
|
|
pFile->m_pbContent = LoadFile(a0, pFile->m_cbContent);
|
|
}
|
|
|
|
SetLastError(dwErr);
|
|
}
|
|
rv = Real_CloseHandle(a0);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (rv /* && nIndent == 0*/) {
|
|
OpenFiles::Forget(a0);
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_DuplicateHandle(HANDLE hSourceProcessHandle,
|
|
HANDLE hSourceHandle,
|
|
HANDLE hTargetProcessHandle,
|
|
LPHANDLE lpTargetHandle,
|
|
DWORD dwDesiredAccess,
|
|
BOOL bInheritHandle,
|
|
DWORD dwOptions)
|
|
{
|
|
HANDLE hTemp = INVALID_HANDLE_VALUE;
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
if (lpTargetHandle == NULL) {
|
|
lpTargetHandle = &hTemp;
|
|
}
|
|
*lpTargetHandle = INVALID_HANDLE_VALUE;
|
|
|
|
rv = Real_DuplicateHandle(hSourceProcessHandle,
|
|
hSourceHandle,
|
|
hTargetProcessHandle,
|
|
lpTargetHandle,
|
|
dwDesiredAccess,
|
|
bInheritHandle,
|
|
dwOptions);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (*lpTargetHandle != INVALID_HANDLE_VALUE) {
|
|
FileInfo *pInfo = OpenFiles::RecallFile(hSourceHandle);
|
|
if (pInfo) {
|
|
OpenFiles::Remember(*lpTargetHandle, pInfo);
|
|
}
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
static LONG s_nPipeCnt = 0;
|
|
|
|
BOOL WINAPI Mine_CreatePipe(PHANDLE hReadPipe,
|
|
PHANDLE hWritePipe,
|
|
LPSECURITY_ATTRIBUTES lpPipeAttributes,
|
|
DWORD nSize)
|
|
{
|
|
HANDLE hRead = INVALID_HANDLE_VALUE;
|
|
HANDLE hWrite = INVALID_HANDLE_VALUE;
|
|
|
|
if (hReadPipe == NULL) {
|
|
hReadPipe = &hRead;
|
|
}
|
|
if (hWritePipe == NULL) {
|
|
hWritePipe = &hWrite;
|
|
}
|
|
|
|
/*int nIndent = */ EnterFunc();
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_CreatePipe(hReadPipe, hWritePipe, lpPipeAttributes, nSize);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (rv) {
|
|
CHAR szPipe[128];
|
|
|
|
SafePrintf(szPipe, ARRAYSIZE(szPipe), "\\\\.\\PIPE\\Temp.%d.%d",
|
|
GetCurrentProcessId(),
|
|
InterlockedIncrement(&s_nPipeCnt));
|
|
|
|
FileInfo *pInfo = FileNames::FindPartial(szPipe);
|
|
|
|
pInfo->m_fCleanup = TRUE;
|
|
OpenFiles::Remember(*hReadPipe, pInfo);
|
|
OpenFiles::Remember(*hWritePipe, pInfo);
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_CreateDirectoryW(LPCWSTR a0,
|
|
LPSECURITY_ATTRIBUTES a1)
|
|
{
|
|
/* int nIndent = */ EnterFunc();
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_CreateDirectoryW(a0, a1);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (rv) {
|
|
FileInfo *pInfo = FileNames::FindPartial(a0);
|
|
pInfo->m_fDirectory = TRUE;
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_CreateDirectoryExW(LPCWSTR a0,
|
|
LPCWSTR a1,
|
|
LPSECURITY_ATTRIBUTES a2)
|
|
{
|
|
/* int nIndent = */ EnterFunc();
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_CreateDirectoryExW(a0, a1, a2);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (rv) {
|
|
FileInfo *pInfo = FileNames::FindPartial(a1);
|
|
pInfo->m_fDirectory = TRUE;
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
HANDLE WINAPI Mine_CreateFileW(LPCWSTR a0,
|
|
DWORD access,
|
|
DWORD share,
|
|
LPSECURITY_ATTRIBUTES a3,
|
|
DWORD create,
|
|
DWORD flags,
|
|
HANDLE a6)
|
|
{
|
|
/* int nIndent = */ EnterFunc();
|
|
HANDLE rv = 0;
|
|
__try {
|
|
rv = Real_CreateFileW(a0, access, share, a3, create, flags, a6);
|
|
} __finally {
|
|
ExitFunc();
|
|
#if 0
|
|
Print("<!-- CreateFileW(%le, ac=%08x, cr=%08x, fl=%08x -->\n",
|
|
a0,
|
|
access,
|
|
create,
|
|
flags);
|
|
#endif
|
|
|
|
if (access != 0 && /* nIndent == 0 && */ rv != INVALID_HANDLE_VALUE) {
|
|
|
|
FileInfo *pInfo = FileNames::FindPartial(a0);
|
|
|
|
// FILE_FLAG_WRITE_THROUGH 0x80000000
|
|
// FILE_FLAG_OVERLAPPED 0x40000000
|
|
// FILE_FLAG_NO_BUFFERING 0x20000000
|
|
// FILE_FLAG_RANDOM_ACCESS 0x10000000
|
|
// FILE_FLAG_SEQUENTIAL_SCAN 0x08000000
|
|
// FILE_FLAG_DELETE_ON_CLOSE 0x04000000
|
|
// FILE_FLAG_BACKUP_SEMANTICS 0x02000000
|
|
// FILE_FLAG_POSIX_SEMANTICS 0x01000000
|
|
// FILE_FLAG_OPEN_REPARSE_POINT 0x00200000
|
|
// FILE_FLAG_OPEN_NO_RECALL 0x00100000
|
|
// FILE_FLAG_FIRST_PIPE_INSTANCE 0x00080000
|
|
// FILE_ATTRIBUTE_ENCRYPTED 0x00004000
|
|
// FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
|
|
// FILE_ATTRIBUTE_OFFLINE 0x00001000
|
|
// FILE_ATTRIBUTE_COMPRESSED 0x00000800
|
|
// FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
|
|
// FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
|
|
// FILE_ATTRIBUTE_TEMPORARY 0x00000100
|
|
// FILE_ATTRIBUTE_NORMAL 0x00000080
|
|
// FILE_ATTRIBUTE_DEVICE 0x00000040
|
|
// FILE_ATTRIBUTE_ARCHIVE 0x00000020
|
|
// FILE_ATTRIBUTE_DIRECTORY 0x00000010
|
|
// FILE_ATTRIBUTE_SYSTEM 0x00000004
|
|
// FILE_ATTRIBUTE_HIDDEN 0x00000002
|
|
// FILE_ATTRIBUTE_READONLY 0x00000001
|
|
|
|
// CREATE_NEW 1
|
|
// CREATE_ALWAYS 2
|
|
// OPEN_EXISTING 3
|
|
// OPEN_ALWAYS 4
|
|
// TRUNCATE_EXISTING 5
|
|
|
|
if (create == CREATE_NEW ||
|
|
create == CREATE_ALWAYS ||
|
|
create == TRUNCATE_EXISTING) {
|
|
|
|
if (!pInfo->m_fRead) {
|
|
pInfo->m_fCantRead = TRUE;
|
|
}
|
|
}
|
|
else if (create == OPEN_EXISTING) {
|
|
}
|
|
else if (create == OPEN_ALWAYS) {
|
|
// pInfo->m_fAppend = TRUE; // !!!
|
|
}
|
|
|
|
if ((flags & FILE_FLAG_DELETE_ON_CLOSE)) {
|
|
pInfo->m_fCleanup = TRUE;
|
|
}
|
|
|
|
OpenFiles::Remember(rv, pInfo);
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
HANDLE WINAPI Mine_CreateFileMappingW(HANDLE hFile,
|
|
LPSECURITY_ATTRIBUTES a1,
|
|
DWORD flProtect,
|
|
DWORD a3,
|
|
DWORD a4,
|
|
LPCWSTR a5)
|
|
{
|
|
/* int nIndent = */ EnterFunc();
|
|
HANDLE rv = 0;
|
|
__try {
|
|
rv = Real_CreateFileMappingW(hFile, a1, flProtect, a3, a4, a5);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (rv != INVALID_HANDLE_VALUE) {
|
|
|
|
FileInfo *pInfo = OpenFiles::RecallFile(hFile);
|
|
|
|
if (pInfo != NULL) {
|
|
switch (flProtect) {
|
|
case PAGE_READONLY:
|
|
pInfo->m_fRead = TRUE;
|
|
break;
|
|
case PAGE_READWRITE:
|
|
pInfo->m_fRead = TRUE;
|
|
pInfo->m_fWrite = TRUE;
|
|
break;
|
|
case PAGE_WRITECOPY:
|
|
pInfo->m_fRead = TRUE;
|
|
break;
|
|
case PAGE_EXECUTE_READ:
|
|
pInfo->m_fRead = TRUE;
|
|
break;
|
|
case PAGE_EXECUTE_READWRITE:
|
|
pInfo->m_fRead = TRUE;
|
|
pInfo->m_fWrite = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_DeleteFileW(LPCWSTR a0)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_DeleteFileW(a0);
|
|
} __finally {
|
|
ExitFunc();
|
|
#if 0
|
|
Print("<!-- DeleteFileW(%le -->\n", a0);
|
|
#endif
|
|
NoteDelete(a0);
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
static VOID Dump(LPVOID pvData, DWORD cbData)
|
|
{
|
|
CHAR szBuffer[128];
|
|
PBYTE pbData = (PBYTE)pvData;
|
|
|
|
for (DWORD i = 0; i < cbData; i += 16) {
|
|
PCHAR psz = szBuffer;
|
|
psz = SafePrintf(psz, (LONG)(szBuffer + ARRAYSIZE(szBuffer) - psz), "%4d: ", i);
|
|
|
|
for (DWORD j = i; j < i + 16; j++) {
|
|
if (j < cbData) {
|
|
psz = SafePrintf(psz, (LONG)(szBuffer + ARRAYSIZE(szBuffer) - psz),
|
|
"%02x", pbData[j]);
|
|
}
|
|
else {
|
|
psz = SafePrintf(psz, (LONG)(szBuffer + ARRAYSIZE(szBuffer) - psz), " ");
|
|
}
|
|
}
|
|
|
|
for (DWORD j = i; j < i + 16; j++) {
|
|
if (j < cbData) {
|
|
if (pbData[j] >= ' ' && pbData[j] <= 127) {
|
|
psz = SafePrintf(psz, (LONG)(szBuffer + ARRAYSIZE(szBuffer) - psz),
|
|
"%c", pbData[j]);
|
|
}
|
|
else {
|
|
psz = SafePrintf(psz, (LONG)(szBuffer + ARRAYSIZE(szBuffer) - psz), ".");
|
|
}
|
|
}
|
|
else {
|
|
psz = SafePrintf(psz, (LONG)(szBuffer + ARRAYSIZE(szBuffer) - psz), " ");
|
|
}
|
|
}
|
|
Print("%s\n", szBuffer);
|
|
}
|
|
}
|
|
|
|
BOOL WINAPI Mine_DeviceIoControl(HANDLE a0,
|
|
DWORD a1,
|
|
LPVOID a2,
|
|
DWORD a3,
|
|
LPVOID a4,
|
|
DWORD a5,
|
|
LPDWORD a6,
|
|
LPOVERLAPPED a7)
|
|
{
|
|
EnterFunc();
|
|
DWORD d6 = 0;
|
|
if (a6 == NULL) {
|
|
a6 = &d6;
|
|
|
|
}
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_DeviceIoControl(a0, a1, a2, a3, a4, a5, a6, a7);
|
|
} __finally {
|
|
ExitFunc();
|
|
OpenFiles::SetRead(a0, 0);
|
|
OpenFiles::SetWrite(a0, 0);
|
|
if (rv && a1 != 0x390008 && a1 != 0x4d0008 && a1 != 0x6d0008) {
|
|
FileInfo *pInfo = OpenFiles::RecallFile(a0);
|
|
|
|
DWORD DeviceType = (a1 & 0xffff0000) >> 16;
|
|
DWORD Access = (a1 & 0x0000c000) >> 14;
|
|
DWORD Function = (a1 & 0x00003ffc) >> 2;
|
|
DWORD Method = (a1 & 0x00000003) >> 0;
|
|
|
|
if (pInfo) {
|
|
Print("<!-- DeviceIoControl %x [dev=%x,acc=%x,fun=%x,mth=%x] on %ls! -->\n",
|
|
a1, DeviceType, Access, Function, Method, pInfo->m_pwzPath);
|
|
}
|
|
else {
|
|
Print("<!-- DeviceIoControl %x [dev=%x,acc=%x,fun=%x,mth=%x,in=%d,out=%d/%d] on (%x)! -->\n",
|
|
a1, DeviceType, Access, Function, Method, a3, *a6, a5, a0);
|
|
|
|
if (a3 > 0) {
|
|
Dump(a2, a3);
|
|
}
|
|
if (a5 > 0) {
|
|
Dump(a4, (*a6 < a5) ? *a6 : a5);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
DWORD WINAPI Mine_GetFileAttributesW(LPCWSTR a0)
|
|
{
|
|
EnterFunc();
|
|
|
|
DWORD rv = 0;
|
|
__try {
|
|
rv = Real_GetFileAttributesW(a0);
|
|
} __finally {
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_MoveFileWithProgressW(LPCWSTR a0,
|
|
LPCWSTR a1,
|
|
LPPROGRESS_ROUTINE a2,
|
|
LPVOID a3,
|
|
DWORD a4)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_MoveFileWithProgressW(a0, a1, a2, a3, a4);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (rv) {
|
|
NoteRead(a0);
|
|
NoteWrite(a1);
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_MoveFileA(LPCSTR a0,
|
|
LPCSTR a1)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_MoveFileA(a0, a1);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (rv) {
|
|
NoteRead(a0);
|
|
NoteCleanup(a0);
|
|
NoteWrite(a1);
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_MoveFileW(LPCWSTR a0,
|
|
LPCWSTR a1)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_MoveFileW(a0, a1);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (rv) {
|
|
NoteRead(a0);
|
|
NoteCleanup(a0);
|
|
NoteWrite(a1);
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_MoveFileExA(LPCSTR a0,
|
|
LPCSTR a1,
|
|
DWORD a2)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_MoveFileExA(a0, a1, a2);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (rv) {
|
|
NoteRead(a0);
|
|
NoteCleanup(a0);
|
|
NoteWrite(a1);
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_MoveFileExW(LPCWSTR a0,
|
|
LPCWSTR a1,
|
|
DWORD a2)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_MoveFileExW(a0, a1, a2);
|
|
} __finally {
|
|
ExitFunc();
|
|
if (rv) {
|
|
NoteRead(a0);
|
|
NoteCleanup(a0);
|
|
NoteWrite(a1);
|
|
}
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
void SetHandle(PCSTR pszName, HANDLE h)
|
|
{
|
|
#if 0
|
|
FileInfo *pInfo = OpenFiles::RecallFile(h);
|
|
|
|
if (pInfo != NULL) {
|
|
Tblog("<!-- hset: %hs (%x) %ls -->\n", pszName, h, pInfo->m_pwzPath);
|
|
}
|
|
else {
|
|
Tblog("<!-- hset: %hs (%x) ***Unknown*** -->\n", pszName, h);
|
|
}
|
|
#else
|
|
(void)pszName;
|
|
(void)h;
|
|
#endif
|
|
}
|
|
|
|
|
|
BOOL WINAPI Mine_SetStdHandle(DWORD a0,
|
|
HANDLE a1)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_SetStdHandle(a0, a1);
|
|
if (rv && a1 != 0) {
|
|
switch (a0) {
|
|
case STD_INPUT_HANDLE:
|
|
SetHandle("stdin", a1);
|
|
break;
|
|
case STD_OUTPUT_HANDLE:
|
|
SetHandle("stdout", a1);
|
|
break;
|
|
case STD_ERROR_HANDLE:
|
|
SetHandle("stderr", a1);
|
|
break;
|
|
}
|
|
}
|
|
} __finally {
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
HMODULE WINAPI Mine_LoadLibraryA(LPCSTR a0)
|
|
{
|
|
EnterFunc();
|
|
|
|
HMODULE rv = 0;
|
|
__try {
|
|
rv = Real_LoadLibraryA(a0);
|
|
} __finally {
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
HMODULE WINAPI Mine_LoadLibraryW(LPCWSTR a0)
|
|
{
|
|
EnterFunc();
|
|
|
|
HMODULE rv = 0;
|
|
__try {
|
|
rv = Real_LoadLibraryW(a0);
|
|
} __finally {
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
HMODULE WINAPI Mine_LoadLibraryExA(LPCSTR a0,
|
|
HANDLE a1,
|
|
DWORD a2)
|
|
{
|
|
EnterFunc();
|
|
|
|
HMODULE rv = 0;
|
|
__try {
|
|
rv = Real_LoadLibraryExA(a0, a1, a2);
|
|
} __finally {
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
HMODULE WINAPI Mine_LoadLibraryExW(LPCWSTR a0,
|
|
HANDLE a1,
|
|
DWORD a2)
|
|
{
|
|
EnterFunc();
|
|
|
|
HMODULE rv = 0;
|
|
__try {
|
|
rv = Real_LoadLibraryExW(a0, a1, a2);
|
|
} __finally {
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
DWORD WINAPI Mine_SetFilePointer(HANDLE hFile,
|
|
LONG lDistanceToMove,
|
|
PLONG lpDistanceToMoveHigh,
|
|
DWORD dwMoveMethod)
|
|
{
|
|
EnterFunc();
|
|
|
|
DWORD rv = 0;
|
|
__try {
|
|
rv = Real_SetFilePointer(hFile,
|
|
lDistanceToMove,
|
|
lpDistanceToMoveHigh,
|
|
dwMoveMethod);
|
|
} __finally {
|
|
LONG high = 0;
|
|
if (lpDistanceToMoveHigh == NULL) {
|
|
lpDistanceToMoveHigh = &high;
|
|
}
|
|
|
|
FileInfo * pInfo = OpenFiles::RecallFile(hFile);
|
|
if (pInfo != NULL) {
|
|
if (dwMoveMethod == FILE_END && lDistanceToMove == 0xffffffff) {
|
|
#if 0
|
|
Print("<!-- SetFilePointer(APPEND, %le) -->\n",
|
|
pInfo->m_pwzPath);
|
|
#endif
|
|
pInfo->m_fAppend = TRUE;
|
|
}
|
|
#if 0
|
|
else if (dwMoveMethod == FILE_END) {
|
|
Print("<!-- SetFilePointer(END:%08x:%08x, %le) -->\n",
|
|
(int)lDistanceToMove,
|
|
*lpDistanceToMoveHigh,
|
|
pInfo->m_pwzPath);
|
|
}
|
|
else if (dwMoveMethod == FILE_BEGIN) {
|
|
Print("<!-- SetFilePointer(BEG:%08x:%08x, %le) -->\n",
|
|
(int)lDistanceToMove,
|
|
*lpDistanceToMoveHigh,
|
|
pInfo->m_pwzPath);
|
|
}
|
|
else if (dwMoveMethod == FILE_CURRENT) {
|
|
Print("<!-- SetFilePointer(CUR:%08x:%08x, %le) -->\n",
|
|
(int)lDistanceToMove,
|
|
*lpDistanceToMoveHigh,
|
|
pInfo->m_pwzPath);
|
|
}
|
|
#endif
|
|
}
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_SetFilePointerEx(HANDLE hFile,
|
|
LARGE_INTEGER liDistanceToMove,
|
|
PLARGE_INTEGER lpNewFilePointer,
|
|
DWORD dwMoveMethod)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_SetFilePointerEx(hFile,
|
|
liDistanceToMove,
|
|
lpNewFilePointer,
|
|
dwMoveMethod);
|
|
} __finally {
|
|
#if 0
|
|
FileInfo * pInfo = OpenFiles::RecallFile(hFile);
|
|
if (pInfo != NULL) {
|
|
if (dwMoveMethod == FILE_END) {
|
|
Print("<!-- SetFilePointerEx(END:%I64d, %le) -->\n",
|
|
liDistanceToMove.QuadPart,
|
|
pInfo->m_pwzPath);
|
|
}
|
|
else if (dwMoveMethod == FILE_BEGIN) {
|
|
Print("<!-- SetFilePointerEx(BEG:%I64d, %le) -->\n",
|
|
liDistanceToMove.QuadPart,
|
|
pInfo->m_pwzPath);
|
|
}
|
|
else if (dwMoveMethod == FILE_CURRENT) {
|
|
Print("<!-- SetFilePointerEx(CUR:%I64d, %le) -->\n",
|
|
liDistanceToMove.QuadPart,
|
|
pInfo->m_pwzPath);
|
|
}
|
|
}
|
|
#endif
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_ReadFile(HANDLE a0,
|
|
LPVOID a1,
|
|
DWORD a2,
|
|
LPDWORD a3,
|
|
LPOVERLAPPED a4)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_ReadFile(a0, a1, a2, a3, a4);
|
|
} __finally {
|
|
if (rv) {
|
|
OpenFiles::SetRead(a0, a2);
|
|
}
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_ReadFileEx(HANDLE a0,
|
|
LPVOID a1,
|
|
DWORD a2,
|
|
LPOVERLAPPED a3,
|
|
LPOVERLAPPED_COMPLETION_ROUTINE a4)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_ReadFileEx(a0, a1, a2, a3, a4);
|
|
} __finally {
|
|
if (rv) {
|
|
OpenFiles::SetRead(a0, a2);
|
|
}
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_WriteFile(HANDLE a0,
|
|
LPCVOID a1,
|
|
DWORD a2,
|
|
LPDWORD a3,
|
|
LPOVERLAPPED a4)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_WriteFile(a0, a1, a2, a3, a4);
|
|
} __finally {
|
|
OpenFiles::SetWrite(a0, a2);
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_WriteFileEx(HANDLE a0,
|
|
LPCVOID a1,
|
|
DWORD a2,
|
|
LPOVERLAPPED a3,
|
|
LPOVERLAPPED_COMPLETION_ROUTINE a4)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_WriteFileEx(a0, a1, a2, a3, a4);
|
|
} __finally {
|
|
OpenFiles::SetWrite(a0, a2);
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_WriteConsoleA(HANDLE a0,
|
|
const VOID* a1,
|
|
DWORD a2,
|
|
LPDWORD a3,
|
|
LPVOID a4)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_WriteConsoleA(a0, a1, a2, a3, a4);
|
|
} __finally {
|
|
OpenFiles::SetWrite(a0, a2);
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
BOOL WINAPI Mine_WriteConsoleW(HANDLE a0,
|
|
const VOID* a1,
|
|
DWORD a2,
|
|
LPDWORD a3,
|
|
LPVOID a4)
|
|
{
|
|
EnterFunc();
|
|
|
|
BOOL rv = 0;
|
|
__try {
|
|
rv = Real_WriteConsoleW(a0, a1, a2, a3, a4);
|
|
} __finally {
|
|
OpenFiles::SetWrite(a0, a2);
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
DWORD WINAPI Mine_ExpandEnvironmentStringsA(PCSTR lpSrc, PCHAR lpDst, DWORD nSize)
|
|
{
|
|
EnterFunc();
|
|
DWORD rv = 0;
|
|
__try {
|
|
rv = Real_ExpandEnvironmentStringsA(lpSrc, lpDst, nSize);
|
|
}
|
|
__finally {
|
|
if (rv > 0) {
|
|
#if 0
|
|
Print("<!-- ExpandEnvironmentStringsA(%he) -->\n", lpSrc);
|
|
#endif
|
|
}
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
DWORD WINAPI Mine_ExpandEnvironmentStringsW(PCWSTR lpSrc, PWCHAR lpDst, DWORD nSize)
|
|
{
|
|
EnterFunc();
|
|
DWORD rv = 0;
|
|
__try {
|
|
rv = Real_ExpandEnvironmentStringsW(lpSrc, lpDst, nSize);
|
|
}
|
|
__finally {
|
|
if (rv > 0) {
|
|
#if 0
|
|
Print("<!-- ExpandEnvironmentStringsW(%le) -->\n", lpSrc);
|
|
#endif
|
|
}
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
DWORD WINAPI Mine_GetEnvironmentVariableA(PCSTR lpName, PCHAR lpBuffer, DWORD nSize)
|
|
{
|
|
EnterFunc();
|
|
DWORD rv = 0;
|
|
__try {
|
|
rv = Real_GetEnvironmentVariableA(lpName, lpBuffer, nSize);
|
|
// if (rv > 0 && rv < nSize && lpBuffer != NULL) {
|
|
// EnvVars::Used(lpName);
|
|
// }
|
|
}
|
|
__finally {
|
|
EnvVars::Used(lpName);
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
DWORD WINAPI Mine_GetEnvironmentVariableW(PCWSTR lpName, PWCHAR lpBuffer, DWORD nSize)
|
|
{
|
|
EnterFunc();
|
|
DWORD rv = 0;
|
|
__try {
|
|
rv = Real_GetEnvironmentVariableW(lpName, lpBuffer, nSize);
|
|
// if (rv > 0 && rv < nSize && lpBuffer != NULL) {
|
|
// EnvVars::Used(lpName);
|
|
// }
|
|
}
|
|
__finally {
|
|
EnvVars::Used(lpName);
|
|
ExitFunc();
|
|
};
|
|
return rv;
|
|
}
|
|
|
|
PCWSTR CDECL Mine_wgetenv(PCWSTR var)
|
|
{
|
|
EnterFunc();
|
|
PCWSTR rv = 0;
|
|
__try {
|
|
rv = Real_wgetenv(var);
|
|
// if (rv != NULL) {
|
|
// EnvVars::Used(var);
|
|
// }
|
|
}
|
|
__finally {
|
|
EnvVars::Used(var);
|
|
ExitFunc();
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
PCSTR CDECL Mine_getenv(PCSTR var)
|
|
{
|
|
EnterFunc();
|
|
PCSTR rv = 0;
|
|
__try {
|
|
rv = Real_getenv(var);
|
|
// if (rv) {
|
|
// EnvVars::Used(var);
|
|
// }
|
|
}
|
|
__finally {
|
|
EnvVars::Used(var);
|
|
ExitFunc();
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
DWORD CDECL Mine_getenv_s(DWORD *pValue, PCHAR pBuffer, DWORD cBuffer, PCSTR varname)
|
|
{
|
|
EnterFunc();
|
|
DWORD rv = 0;
|
|
__try {
|
|
DWORD value;
|
|
if (pValue == NULL) {
|
|
pValue = &value;
|
|
}
|
|
rv = Real_getenv_s(pValue, pBuffer, cBuffer, varname);
|
|
// if (rv == 0 && *pValue > 0) {
|
|
// EnvVars::Used(varname);
|
|
// }
|
|
}
|
|
__finally {
|
|
EnvVars::Used(varname);
|
|
ExitFunc();
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
DWORD CDECL Mine_wgetenv_s(DWORD *pValue, PWCHAR pBuffer, DWORD cBuffer, PCWSTR varname)
|
|
{
|
|
EnterFunc();
|
|
DWORD rv = 0;
|
|
__try {
|
|
DWORD value;
|
|
if (pValue == NULL) {
|
|
pValue = &value;
|
|
}
|
|
rv = Real_wgetenv_s(pValue, pBuffer, cBuffer, varname);
|
|
// if (rv == 0 && *pValue > 0) {
|
|
// EnvVars::Used(varname);
|
|
// }
|
|
}
|
|
__finally {
|
|
EnvVars::Used(varname);
|
|
ExitFunc();
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
DWORD CDECL Mine_dupenv_s(PCHAR *ppBuffer, DWORD *pcBuffer, PCSTR varname)
|
|
{
|
|
EnterFunc();
|
|
DWORD rv = 0;
|
|
__try {
|
|
PCHAR pb;
|
|
DWORD cb;
|
|
if (ppBuffer == NULL) {
|
|
ppBuffer = &pb;
|
|
}
|
|
if (pcBuffer == NULL) {
|
|
pcBuffer = &cb;
|
|
}
|
|
rv = Real_dupenv_s(ppBuffer, pcBuffer, varname);
|
|
// if (rv == 0 && *pcBuffer > 0 && *ppBuffer != NULL) {
|
|
// EnvVars::Used(varname);
|
|
// }
|
|
}
|
|
__finally {
|
|
EnvVars::Used(varname);
|
|
ExitFunc();
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
DWORD CDECL Mine_wdupenv_s(PWCHAR *ppBuffer, DWORD *pcBuffer, PCWSTR varname)
|
|
{
|
|
EnterFunc();
|
|
DWORD rv = 0;
|
|
__try {
|
|
PWCHAR pb;
|
|
DWORD cb;
|
|
if (ppBuffer == NULL) {
|
|
ppBuffer = &pb;
|
|
}
|
|
if (pcBuffer == NULL) {
|
|
pcBuffer = &cb;
|
|
}
|
|
rv = Real_wdupenv_s(ppBuffer, pcBuffer, varname);
|
|
// if (rv == 0 && *pcBuffer > 0 && *ppBuffer != NULL) {
|
|
// EnvVars::Used(varname);
|
|
// }
|
|
}
|
|
__finally {
|
|
EnvVars::Used(varname);
|
|
ExitFunc();
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// AttachDetours
|
|
//
|
|
LONG AttachDetours(VOID)
|
|
{
|
|
DetourTransactionBegin();
|
|
DetourUpdateThread(GetCurrentThread());
|
|
|
|
DetourAttach(&(PVOID&)Real_EntryPoint, Mine_EntryPoint);
|
|
DetourAttach(&(PVOID&)Real_ExitProcess, Mine_ExitProcess);
|
|
DetourAttach(&(PVOID&)Real_CopyFileExA, Mine_CopyFileExA);
|
|
DetourAttach(&(PVOID&)Real_CopyFileExW, Mine_CopyFileExW);
|
|
DetourAttach(&(PVOID&)Real_PrivCopyFileExW, Mine_PrivCopyFileExW);
|
|
DetourAttach(&(PVOID&)Real_CreateHardLinkA, Mine_CreateHardLinkA);
|
|
DetourAttach(&(PVOID&)Real_CreateHardLinkW, Mine_CreateHardLinkW);
|
|
DetourAttach(&(PVOID&)Real_CreateDirectoryW, Mine_CreateDirectoryW);
|
|
DetourAttach(&(PVOID&)Real_CreateDirectoryExW, Mine_CreateDirectoryExW);
|
|
DetourAttach(&(PVOID&)Real_CreateFileW, Mine_CreateFileW);
|
|
DetourAttach(&(PVOID&)Real_CreatePipe, Mine_CreatePipe);
|
|
DetourAttach(&(PVOID&)Real_CreateFileMappingW, Mine_CreateFileMappingW);
|
|
DetourAttach(&(PVOID&)Real_CloseHandle, Mine_CloseHandle);
|
|
DetourAttach(&(PVOID&)Real_DuplicateHandle, Mine_DuplicateHandle);
|
|
DetourAttach(&(PVOID&)Real_CreateProcessW, Mine_CreateProcessW);
|
|
DetourAttach(&(PVOID&)Real_CreateProcessA, Mine_CreateProcessA);
|
|
DetourAttach(&(PVOID&)Real_DeleteFileW, Mine_DeleteFileW);
|
|
DetourAttach(&(PVOID&)Real_DeviceIoControl, Mine_DeviceIoControl);
|
|
DetourAttach(&(PVOID&)Real_GetFileAttributesW, Mine_GetFileAttributesW);
|
|
DetourAttach(&(PVOID&)Real_MoveFileA, Mine_MoveFileA);
|
|
DetourAttach(&(PVOID&)Real_MoveFileW, Mine_MoveFileW);
|
|
DetourAttach(&(PVOID&)Real_MoveFileExA, Mine_MoveFileExA);
|
|
DetourAttach(&(PVOID&)Real_MoveFileExW, Mine_MoveFileExW);
|
|
DetourAttach(&(PVOID&)Real_MoveFileWithProgressW, Mine_MoveFileWithProgressW);
|
|
DetourAttach(&(PVOID&)Real_SetStdHandle, Mine_SetStdHandle);
|
|
DetourAttach(&(PVOID&)Real_LoadLibraryA, Mine_LoadLibraryA);
|
|
DetourAttach(&(PVOID&)Real_LoadLibraryW, Mine_LoadLibraryW);
|
|
DetourAttach(&(PVOID&)Real_LoadLibraryExA, Mine_LoadLibraryExA);
|
|
DetourAttach(&(PVOID&)Real_LoadLibraryExW, Mine_LoadLibraryExW);
|
|
DetourAttach(&(PVOID&)Real_SetFilePointer, Mine_SetFilePointer);
|
|
DetourAttach(&(PVOID&)Real_SetFilePointerEx, Mine_SetFilePointerEx);
|
|
DetourAttach(&(PVOID&)Real_ReadFile, Mine_ReadFile);
|
|
DetourAttach(&(PVOID&)Real_ReadFileEx, Mine_ReadFileEx);
|
|
DetourAttach(&(PVOID&)Real_WriteFile, Mine_WriteFile);
|
|
DetourAttach(&(PVOID&)Real_WriteFileEx, Mine_WriteFileEx);
|
|
DetourAttach(&(PVOID&)Real_WriteConsoleA, Mine_WriteConsoleA);
|
|
DetourAttach(&(PVOID&)Real_WriteConsoleW, Mine_WriteConsoleW);
|
|
DetourAttach(&(PVOID&)Real_ExpandEnvironmentStringsA, Mine_ExpandEnvironmentStringsA);
|
|
DetourAttach(&(PVOID&)Real_ExpandEnvironmentStringsW, Mine_ExpandEnvironmentStringsW);
|
|
DetourAttach(&(PVOID&)Real_GetEnvironmentVariableA, Mine_GetEnvironmentVariableA);
|
|
DetourAttach(&(PVOID&)Real_GetEnvironmentVariableW, Mine_GetEnvironmentVariableW);
|
|
|
|
return DetourTransactionCommit();
|
|
}
|
|
|
|
LONG DetachDetours(VOID)
|
|
{
|
|
DetourTransactionBegin();
|
|
DetourUpdateThread(GetCurrentThread());
|
|
|
|
DetourDetach(&(PVOID&)Real_EntryPoint, Mine_EntryPoint);
|
|
DetourAttach(&(PVOID&)Real_ExitProcess, Mine_ExitProcess);
|
|
DetourDetach(&(PVOID&)Real_CopyFileExA, Mine_CopyFileExA);
|
|
DetourDetach(&(PVOID&)Real_CopyFileExW, Mine_CopyFileExW);
|
|
DetourDetach(&(PVOID&)Real_PrivCopyFileExW, Mine_PrivCopyFileExW);
|
|
DetourDetach(&(PVOID&)Real_CreateHardLinkA, Mine_CreateHardLinkA);
|
|
DetourDetach(&(PVOID&)Real_CreateHardLinkW, Mine_CreateHardLinkW);
|
|
DetourDetach(&(PVOID&)Real_CreateDirectoryW, Mine_CreateDirectoryW);
|
|
DetourDetach(&(PVOID&)Real_CreateDirectoryExW, Mine_CreateDirectoryExW);
|
|
DetourDetach(&(PVOID&)Real_CreateFileW, Mine_CreateFileW);
|
|
DetourDetach(&(PVOID&)Real_CreatePipe, Mine_CreatePipe);
|
|
DetourDetach(&(PVOID&)Real_CreateFileMappingW, Mine_CreateFileMappingW);
|
|
DetourDetach(&(PVOID&)Real_CloseHandle, Mine_CloseHandle);
|
|
DetourDetach(&(PVOID&)Real_DuplicateHandle, Mine_DuplicateHandle);
|
|
DetourDetach(&(PVOID&)Real_CreateProcessW, Mine_CreateProcessW);
|
|
DetourDetach(&(PVOID&)Real_CreateProcessA, Mine_CreateProcessA);
|
|
DetourDetach(&(PVOID&)Real_DeleteFileW, Mine_DeleteFileW);
|
|
DetourDetach(&(PVOID&)Real_DeviceIoControl, Mine_DeviceIoControl);
|
|
DetourDetach(&(PVOID&)Real_GetFileAttributesW, Mine_GetFileAttributesW);
|
|
DetourDetach(&(PVOID&)Real_MoveFileA, Mine_MoveFileA);
|
|
DetourDetach(&(PVOID&)Real_MoveFileW, Mine_MoveFileW);
|
|
DetourDetach(&(PVOID&)Real_MoveFileExA, Mine_MoveFileExA);
|
|
DetourDetach(&(PVOID&)Real_MoveFileExW, Mine_MoveFileExW);
|
|
DetourDetach(&(PVOID&)Real_MoveFileWithProgressW, Mine_MoveFileWithProgressW);
|
|
DetourDetach(&(PVOID&)Real_SetStdHandle, Mine_SetStdHandle);
|
|
DetourDetach(&(PVOID&)Real_LoadLibraryA, Mine_LoadLibraryA);
|
|
DetourDetach(&(PVOID&)Real_LoadLibraryW, Mine_LoadLibraryW);
|
|
DetourDetach(&(PVOID&)Real_LoadLibraryExA, Mine_LoadLibraryExA);
|
|
DetourDetach(&(PVOID&)Real_LoadLibraryExW, Mine_LoadLibraryExW);
|
|
DetourDetach(&(PVOID&)Real_SetFilePointer, Mine_SetFilePointer);
|
|
DetourDetach(&(PVOID&)Real_SetFilePointerEx, Mine_SetFilePointerEx);
|
|
DetourDetach(&(PVOID&)Real_ReadFile, Mine_ReadFile);
|
|
DetourDetach(&(PVOID&)Real_ReadFileEx, Mine_ReadFileEx);
|
|
DetourDetach(&(PVOID&)Real_WriteFile, Mine_WriteFile);
|
|
DetourDetach(&(PVOID&)Real_WriteFileEx, Mine_WriteFileEx);
|
|
DetourDetach(&(PVOID&)Real_WriteConsoleA, Mine_WriteConsoleA);
|
|
DetourDetach(&(PVOID&)Real_WriteConsoleW, Mine_WriteConsoleW);
|
|
DetourDetach(&(PVOID&)Real_ExpandEnvironmentStringsA, Mine_ExpandEnvironmentStringsA);
|
|
DetourDetach(&(PVOID&)Real_ExpandEnvironmentStringsW, Mine_ExpandEnvironmentStringsW);
|
|
DetourDetach(&(PVOID&)Real_GetEnvironmentVariableA, Mine_GetEnvironmentVariableA);
|
|
DetourDetach(&(PVOID&)Real_GetEnvironmentVariableW, Mine_GetEnvironmentVariableW);
|
|
|
|
if (Real_getenv) { DetourDetach(&(PVOID&)Real_getenv, Mine_getenv); }
|
|
if (Real_getenv_s) { DetourDetach(&(PVOID&)Real_getenv_s, Mine_getenv_s); }
|
|
if (Real_wgetenv) { DetourDetach(&(PVOID&)Real_wgetenv, Mine_wgetenv); }
|
|
if (Real_wgetenv_s) { DetourDetach(&(PVOID&)Real_wgetenv, Mine_wgetenv_s); }
|
|
if (Real_dupenv_s) { DetourDetach(&(PVOID&)Real_dupenv_s, Mine_dupenv_s); }
|
|
if (Real_wdupenv_s) { DetourDetach(&(PVOID&)Real_wdupenv_s, Mine_wdupenv_s); }
|
|
|
|
return DetourTransactionCommit();
|
|
}
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID NoteRead(PCSTR psz)
|
|
{
|
|
FileInfo *pInfo = FileNames::FindPartial(psz);
|
|
pInfo->m_fRead = TRUE;
|
|
}
|
|
|
|
VOID NoteRead(PCWSTR pwz)
|
|
{
|
|
FileInfo *pInfo = FileNames::FindPartial(pwz);
|
|
pInfo->m_fRead = TRUE;
|
|
}
|
|
|
|
VOID NoteWrite(PCSTR psz)
|
|
{
|
|
FileInfo *pInfo = FileNames::FindPartial(psz);
|
|
pInfo->m_fWrite = TRUE;
|
|
if (!pInfo->m_fRead) {
|
|
pInfo->m_fCantRead = TRUE;
|
|
}
|
|
}
|
|
|
|
VOID NoteWrite(PCWSTR pwz)
|
|
{
|
|
FileInfo *pInfo = FileNames::FindPartial(pwz);
|
|
pInfo->m_fWrite = TRUE;
|
|
if (!pInfo->m_fRead) {
|
|
pInfo->m_fCantRead = TRUE;
|
|
}
|
|
}
|
|
|
|
VOID NoteDelete(PCSTR psz)
|
|
{
|
|
FileInfo *pInfo = FileNames::FindPartial(psz);
|
|
if (pInfo->m_fWrite || pInfo->m_fRead) {
|
|
pInfo->m_fCleanup = TRUE;
|
|
}
|
|
else {
|
|
pInfo->m_fDelete = TRUE;
|
|
}
|
|
if (!pInfo->m_fRead) {
|
|
pInfo->m_fCantRead = TRUE;
|
|
}
|
|
}
|
|
|
|
VOID NoteDelete(PCWSTR pwz)
|
|
{
|
|
FileInfo *pInfo = FileNames::FindPartial(pwz);
|
|
if (pInfo->m_fWrite || pInfo->m_fRead) {
|
|
pInfo->m_fCleanup = TRUE;
|
|
}
|
|
else {
|
|
pInfo->m_fDelete = TRUE;
|
|
}
|
|
if (!pInfo->m_fRead) {
|
|
pInfo->m_fCantRead = TRUE;
|
|
}
|
|
}
|
|
|
|
VOID NoteCleanup(PCSTR psz)
|
|
{
|
|
FileInfo *pInfo = FileNames::FindPartial(psz);
|
|
pInfo->m_fCleanup = TRUE;
|
|
}
|
|
|
|
VOID NoteCleanup(PCWSTR pwz)
|
|
{
|
|
FileInfo *pInfo = FileNames::FindPartial(pwz);
|
|
pInfo->m_fCleanup = TRUE;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////// Logging System.
|
|
//
|
|
static BOOL s_bLog = 1;
|
|
static LONG s_nTlsIndent = -1;
|
|
static LONG s_nTlsThread = -1;
|
|
static LONG s_nThreadCnt = 0;
|
|
|
|
LONG EnterFunc()
|
|
{
|
|
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);
|
|
}
|
|
|
|
SetLastError(dwErr);
|
|
|
|
return nIndent;
|
|
}
|
|
|
|
VOID ExitFunc()
|
|
{
|
|
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);
|
|
}
|
|
|
|
SetLastError(dwErr);
|
|
}
|
|
|
|
VOID Print(const CHAR *psz, ...)
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
|
|
if (s_bLog && psz) {
|
|
va_list args;
|
|
va_start(args, psz);
|
|
|
|
TblogV(psz, args);
|
|
|
|
va_end(args);
|
|
}
|
|
|
|
SetLastError(dwErr);
|
|
}
|
|
|
|
VOID AssertFailed(CONST PCHAR pszMsg, CONST PCHAR pszFile, ULONG nLine)
|
|
{
|
|
Tblog("ASSERT(%hs) 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)
|
|
{
|
|
InitializeCriticalSection(&s_csPipe);
|
|
InitializeCriticalSection(&s_csChildPayload);
|
|
|
|
Procs::Initialize();
|
|
EnvVars::Initialize();
|
|
FileNames::Initialize();
|
|
OpenFiles::Initialize();
|
|
|
|
s_bLog = FALSE;
|
|
s_nTlsIndent = TlsAlloc();
|
|
s_nTlsThread = TlsAlloc();
|
|
|
|
s_hInst = hDll;
|
|
s_hKernel32 = NULL;
|
|
|
|
PBYTE xCreate = (PBYTE)DetourCodeFromPointer((PVOID)Real_CreateProcessW, NULL);
|
|
PTBLOG_PAYLOAD pPayload = NULL;
|
|
|
|
for (HMODULE hMod = NULL; (hMod = DetourEnumerateModules(hMod)) != NULL;) {
|
|
ULONG cbData;
|
|
PVOID pvData = DetourFindPayload(hMod, s_guidTrace, &cbData);
|
|
|
|
if (pvData != NULL && pPayload == NULL) {
|
|
pPayload = (PTBLOG_PAYLOAD)pvData;
|
|
}
|
|
|
|
ULONG cbMod = DetourGetModuleSize(hMod);
|
|
|
|
if (((PBYTE)hMod) < xCreate && ((PBYTE)hMod + cbMod) > xCreate) {
|
|
s_hKernel32 = hMod;
|
|
}
|
|
}
|
|
|
|
ZeroMemory(&s_Payload, sizeof(s_Payload));
|
|
|
|
if (pPayload == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
CopyMemory(&s_Payload, pPayload, sizeof(s_Payload));
|
|
|
|
LoadStdHandleName(STD_INPUT_HANDLE, s_Payload.wzStdin, FALSE);
|
|
LoadStdHandleName(STD_OUTPUT_HANDLE, s_Payload.wzStdout, s_Payload.fStdoutAppend);
|
|
LoadStdHandleName(STD_ERROR_HANDLE, s_Payload.wzStderr, s_Payload.fStderrAppend);
|
|
s_nTraceProcessId = s_Payload.nTraceProcessId;
|
|
|
|
GetModuleFileNameA(s_hInst, s_szDllPath, ARRAYSIZE(s_szDllPath));
|
|
|
|
// Find hidden functions.
|
|
Real_PrivCopyFileExW =
|
|
(BOOL (WINAPI *)(LPCWSTR, LPCWSTR, LPPROGRESS_ROUTINE, LPVOID, LPBOOL, DWORD))
|
|
GetProcAddress(s_hKernel32, "PrivCopyFileExW");
|
|
if (Real_PrivCopyFileExW == NULL) {
|
|
DEBUG_BREAK();
|
|
}
|
|
|
|
LONG error = AttachDetours();
|
|
if (error != NO_ERROR) {
|
|
DEBUG_BREAK();
|
|
Tblog("<!-- 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) {
|
|
Tblog("<!-- Error detaching detours: %d -->\n", error);
|
|
}
|
|
|
|
TblogClose();
|
|
|
|
if (s_nTlsIndent >= 0) {
|
|
TlsFree(s_nTlsIndent);
|
|
}
|
|
if (s_nTlsThread >= 0) {
|
|
TlsFree(s_nTlsThread);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
inline VOID UpdateIfRoom(PWCHAR& pwzDst, PWCHAR pwzDstEnd, WCHAR c)
|
|
{
|
|
if (pwzDst < pwzDstEnd) {
|
|
*pwzDst++ = c; // Write character if room in buffer.
|
|
}
|
|
else {
|
|
pwzDst++; // If no room, just advance pointer (to alloc calculation)
|
|
}
|
|
}
|
|
|
|
static PCHAR RemoveReturns(PCHAR pszBuffer)
|
|
{
|
|
PCHAR pszIn = pszBuffer;
|
|
PCHAR pszOut = pszBuffer;
|
|
|
|
while (*pszIn) {
|
|
if (*pszIn == '\r') {
|
|
pszIn++;
|
|
continue;
|
|
}
|
|
*pszOut++ = *pszIn++;
|
|
}
|
|
*pszOut = '\0';
|
|
|
|
return pszBuffer;
|
|
}
|
|
|
|
static PWCHAR RemoveReturns(PWCHAR pwzBuffer)
|
|
{
|
|
PWCHAR pwzIn = pwzBuffer;
|
|
PWCHAR pwzOut = pwzBuffer;
|
|
|
|
while (*pwzIn) {
|
|
if (*pwzIn == '\r') {
|
|
pwzIn++;
|
|
continue;
|
|
}
|
|
*pwzOut++ = *pwzIn++;
|
|
}
|
|
*pwzOut = '\0';
|
|
|
|
return pwzBuffer;
|
|
}
|
|
|
|
PBYTE LoadFile(HANDLE hFile, DWORD cbFile)
|
|
{
|
|
PBYTE pbFile = (PBYTE)GlobalAlloc(GPTR, cbFile + 3);
|
|
if (pbFile == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
DWORD cbRead = 0;
|
|
Real_SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
|
|
Real_ReadFile(hFile, pbFile, cbFile, &cbRead, NULL);
|
|
|
|
// Make sure the file is zero terminated.
|
|
pbFile[cbRead + 0] = 0;
|
|
pbFile[cbRead + 1] = 0;
|
|
pbFile[cbRead + 2] = 0;
|
|
|
|
return pbFile;
|
|
}
|
|
|
|
PWCHAR More(PCWSTR pwzPath, PWCHAR pwzDst, PWCHAR pwzDstEnd)
|
|
{
|
|
HANDLE hFile = Real_CreateFileW(pwzPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
return NULL;
|
|
}
|
|
|
|
FileInfo *pInfo = FileNames::FindPartial(pwzPath);
|
|
pInfo->m_fAbsorbed = true;
|
|
|
|
DWORD cbFile = Real_SetFilePointer(hFile, 0, NULL, FILE_END);
|
|
DWORD cbRead = 0;
|
|
|
|
PCHAR pszFile = (PCHAR)GlobalAlloc(GPTR, cbFile + 2); // 2 bytes null for Unicode or Ascii.
|
|
if (pszFile != NULL) {
|
|
Real_SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
|
|
Real_ReadFile(hFile, pszFile, cbFile, &cbRead, NULL);
|
|
|
|
if (((PUCHAR)pszFile)[0] == 0xff && ((PUCHAR)pszFile)[1] == 0xfe) {
|
|
// Unicode
|
|
PWCHAR pwzFile = ((PWCHAR)pszFile) + 1;
|
|
PCWSTR pwzIn = pwzFile;
|
|
while (*pwzIn) {
|
|
if (*pwzIn == ' ' || *pwzIn == '\t' || *pwzIn == '\r' || *pwzIn == '\n') {
|
|
UpdateIfRoom(pwzDst, pwzDstEnd, ' ');
|
|
while (*pwzIn == ' ' || *pwzIn == '\t' || *pwzIn == '\r' || *pwzIn == '\n') {
|
|
pwzIn++;
|
|
}
|
|
}
|
|
else {
|
|
UpdateIfRoom(pwzDst, pwzDstEnd, *pwzIn++);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
PCSTR pszIn = pszFile;
|
|
while (*pszIn) {
|
|
if (*pszIn == ' ' || *pszIn == '\t' || *pszIn == '\r' || *pszIn == '\n') {
|
|
UpdateIfRoom(pwzDst, pwzDstEnd, ' ');
|
|
while (*pszIn == ' ' || *pszIn == '\t' || *pszIn == '\r' || *pszIn == '\n') {
|
|
pszIn++;
|
|
}
|
|
}
|
|
else {
|
|
UpdateIfRoom(pwzDst, pwzDstEnd, *pszIn++);
|
|
}
|
|
}
|
|
}
|
|
|
|
GlobalFree(pszFile);
|
|
}
|
|
|
|
Real_CloseHandle(hFile);
|
|
|
|
return pwzDst;
|
|
}
|
|
|
|
// This function is called twice. On the first call, pwzDstEnd <= pwzDst and
|
|
// no data is copied, but pwzDst is advanced so we can see how big of a
|
|
// buffer is needed to hold the command line.
|
|
//
|
|
// On the second call, the command line is actually populated.
|
|
PWCHAR LoadCommandLine(PCWSTR pwz, PWCHAR pwzDst, PWCHAR pwzDstEnd)
|
|
{
|
|
while (*pwz) {
|
|
PCWSTR pwzArgBeg = NULL;
|
|
PCWSTR pwzArgEnd = NULL;
|
|
WCHAR cQuote = '\0';
|
|
BOOL fMore = false;
|
|
|
|
if (*pwz == '@') {
|
|
fMore = true;
|
|
pwz++;
|
|
}
|
|
|
|
if (*pwz == '\"' || *pwz == '\'') {
|
|
cQuote = *pwz++;
|
|
|
|
pwzArgBeg = pwz;
|
|
while (*pwz != '\0' && *pwz != cQuote) {
|
|
pwz++;
|
|
}
|
|
pwzArgEnd = pwz;
|
|
|
|
if (*pwz == cQuote) {
|
|
pwz++;
|
|
}
|
|
}
|
|
else {
|
|
pwzArgBeg = pwz;
|
|
while (*pwz != '\0' && *pwz != ' ' && *pwz != '\t' && *pwz != '\n' && *pwz != '\r') {
|
|
pwz++;
|
|
}
|
|
pwzArgEnd = pwz;
|
|
}
|
|
|
|
if (fMore) {
|
|
// More arguments!
|
|
WCHAR wzPath[MAX_PATH];
|
|
PWCHAR pwzPath = wzPath;
|
|
PCWSTR pwzTmp = pwzArgBeg + 1;
|
|
while (pwzTmp < pwzArgEnd && pwzPath < wzPath + ARRAYSIZE(wzPath)-2) {
|
|
*pwzPath++ = *pwzTmp++;
|
|
}
|
|
*pwzPath = '\0';
|
|
|
|
PWCHAR pwzOut = More(wzPath, pwzDst, pwzDstEnd);
|
|
if (pwzOut != NULL) {
|
|
pwzDst = pwzOut;
|
|
|
|
cQuote = 0;
|
|
pwzArgBeg = pwzArgEnd;
|
|
}
|
|
}
|
|
|
|
if (cQuote) {
|
|
UpdateIfRoom(pwzDst, pwzDstEnd, cQuote);
|
|
}
|
|
for (; pwzArgBeg < pwzArgEnd; pwzArgBeg++) {
|
|
UpdateIfRoom(pwzDst, pwzDstEnd, *pwzArgBeg);
|
|
}
|
|
if (cQuote) {
|
|
UpdateIfRoom(pwzDst, pwzDstEnd, cQuote);
|
|
}
|
|
|
|
if (*pwz) {
|
|
UpdateIfRoom(pwzDst, pwzDstEnd, ' ');
|
|
}
|
|
|
|
// skip over separating spaces.
|
|
while (*pwz == ' ' || *pwz == '\t' || *pwz == '\n' || *pwz == '\r') {
|
|
pwz++;
|
|
}
|
|
}
|
|
return pwzDst;
|
|
}
|
|
|
|
void TestHandle(PCSTR pszName, HANDLE h)
|
|
{
|
|
FileInfo *pInfo = OpenFiles::RecallFile(h);
|
|
|
|
if (pInfo != NULL) {
|
|
#if 1 // Ignore PIPEs.
|
|
if (FileNames::PrefixMatch(pInfo->m_pwzPath, L"\\\\.\\PIPE\\")) {
|
|
// Ignore;
|
|
}
|
|
else
|
|
#endif
|
|
if (FileNames::SuffixMatch(pInfo->m_pwzPath, L"\\conout$")) {
|
|
// Ignore;
|
|
}
|
|
else if (FileNames::SuffixMatch(pInfo->m_pwzPath, L"\\conin$")) {
|
|
// Ignore;
|
|
}
|
|
else if (FileNames::SuffixMatch(pInfo->m_pwzPath, L"\\nul")) {
|
|
// Ignore;
|
|
}
|
|
else {
|
|
Tblog("<%hs%hs>%le</%hs>\n",
|
|
pszName, pInfo->m_fAppend ? " append=\"true\"" : "", pInfo->m_pwzPath, pszName);
|
|
}
|
|
}
|
|
else {
|
|
Tblog("<!-- hand: %hs (%x) ***Unknown*** -->\n", pszName, h);
|
|
}
|
|
}
|
|
|
|
LONG WINAPI DetourAttachIf(PVOID *ppPointer, PVOID pDetour)
|
|
{
|
|
if (*ppPointer == NULL) {
|
|
Tblog("<!-- DetourAttachIf failed: %p -->\n", pDetour);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
PDETOUR_TRAMPOLINE pRealTrampoline;
|
|
PVOID pRealTarget;
|
|
PVOID pRealDetour;
|
|
|
|
LONG err = DetourAttachEx(ppPointer, pDetour, &pRealTrampoline, &pRealTarget, &pRealDetour);
|
|
if (err == NO_ERROR) {
|
|
// Tblog("<!-- DetourAttachIf %p at %p -->\n", pDetour, pRealTarget);
|
|
return NO_ERROR;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
int WINAPI Mine_EntryPoint(VOID)
|
|
{
|
|
// This function is invoked instead of the process EntryPoint (Real_EntryPoint).
|
|
|
|
TblogOpen();
|
|
|
|
SaveEnvironment();
|
|
|
|
{
|
|
CHAR szExeName[MAX_PATH];
|
|
CHAR szId[128];
|
|
CHAR szParent[128];
|
|
WCHAR wzPath[MAX_PATH];
|
|
PCHAR pszExeName = szExeName;
|
|
|
|
// Get the base command line (skipping over the executable name)
|
|
PCWSTR pwzLine = GetCommandLineW();
|
|
if (*pwzLine == '\"') {
|
|
pwzLine++;
|
|
while (*pwzLine && *pwzLine != '\"') {
|
|
pwzLine++;
|
|
}
|
|
if (*pwzLine == '\"') {
|
|
pwzLine++;
|
|
}
|
|
}
|
|
else {
|
|
while (*pwzLine && *pwzLine != ' ' && *pwzLine != '\t') {
|
|
pwzLine++;
|
|
}
|
|
}
|
|
while (*pwzLine && (*pwzLine == ' ' || *pwzLine == '\t')) {
|
|
pwzLine++;
|
|
}
|
|
|
|
// Get the root executable name.
|
|
if (GetModuleFileNameA(0, szExeName, ARRAYSIZE(szExeName))) {
|
|
PCHAR psz = szExeName;
|
|
|
|
while (*psz) {
|
|
psz++;
|
|
}
|
|
|
|
while (psz > szExeName && psz[-1] != ':' && psz[-1] != '\\' && psz[-1] != '/') {
|
|
psz--;
|
|
}
|
|
pszExeName = psz;
|
|
while (*psz && *psz != '.') {
|
|
psz++;
|
|
}
|
|
*psz = '\0';
|
|
}
|
|
else {
|
|
szExeName[0] = '\0';
|
|
}
|
|
|
|
// Start the XML process node.
|
|
Tblog("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
|
{
|
|
PCHAR pszId = szId;
|
|
PCHAR pszParent = szParent;
|
|
for (DWORD i = 0; i < s_Payload.nGeneology; i++) {
|
|
pszId = SafePrintf(pszId, 16, "%d.", s_Payload.rGeneology[i]);
|
|
if (i < s_Payload.nGeneology - 1) {
|
|
pszParent = SafePrintf(pszParent, 16, "%d.", s_Payload.rGeneology[i]);
|
|
}
|
|
}
|
|
*pszId = '\0';
|
|
*pszParent = '\0';
|
|
|
|
if (szParent[0] == '\0') {
|
|
Tblog("<t:Process id=\"::%hs::\"", szId);
|
|
}
|
|
else {
|
|
Tblog("<t:Process id=\"::%hs::\" parentId=\"::%hs::\"", szId, szParent);
|
|
}
|
|
|
|
Tblog(" par=\"%ls\" exe=\"%hs\"", s_Payload.wzParents, pszExeName);
|
|
|
|
BOOL drop = false;
|
|
PCWSTR pwzz = s_Payload.wzzDrop;
|
|
while (*pwzz) {
|
|
if (Compare(pwzz, pszExeName) == 0) {
|
|
// match
|
|
drop = true;
|
|
break;
|
|
}
|
|
pwzz += Size(pwzz) + 1;
|
|
}
|
|
if (drop) {
|
|
Tblog(" drop=\"true\"");
|
|
}
|
|
}
|
|
|
|
{
|
|
PWCHAR pwz = s_Payload.wzParents;
|
|
while (*pwz) {
|
|
pwz++;
|
|
}
|
|
*pwz++ = '/';
|
|
PCSTR psz = pszExeName;
|
|
while (*psz) {
|
|
*pwz++ = *psz++;
|
|
}
|
|
*pwz = '\0';
|
|
}
|
|
|
|
|
|
if (HasChar(pwzLine, '|')) {
|
|
Tblog(" pipes=\"true\"");
|
|
}
|
|
if (HasChar(pwzLine, '>')) {
|
|
Tblog(" redirects=\"true\"");
|
|
}
|
|
|
|
Tblog(" xmlns:t=\"http://schemas.microsoft.com/research/tracebld/2008\">\n");
|
|
|
|
// Get the directory.
|
|
DWORD dwSize = GetCurrentDirectoryA(ARRAYSIZE(szExeName), szExeName);
|
|
if (dwSize > 0 && dwSize < ARRAYSIZE(szExeName)) {
|
|
Tblog("<t:Directory>%hs</t:Directory>\n", szExeName);
|
|
}
|
|
|
|
// Get the real executable name.
|
|
wzPath[0] = '\0';
|
|
if (GetModuleFileNameA(0, szExeName, ARRAYSIZE(szExeName))) {
|
|
FileInfo *pInfo = FileNames::FindPartial(szExeName);
|
|
Tblog("<t:Executable>%ls</t:Executable>\n",
|
|
FileNames::ParameterizeName(wzPath, ARRAYSIZE(wzPath), pInfo));
|
|
}
|
|
|
|
// Construct the processed command line.
|
|
PWCHAR pwzDstEnd = (PWCHAR)pwzLine;
|
|
PWCHAR pwzDst = pwzDstEnd;
|
|
pwzDst = LoadCommandLine(pwzLine, pwzDst, pwzDstEnd);
|
|
DWORD wcNew = (DWORD)((pwzDst - pwzDstEnd) + 1);
|
|
PWCHAR pwzFin = (PWCHAR)GlobalAlloc(GPTR, wcNew * sizeof(WCHAR));
|
|
pwzDst = pwzFin;
|
|
pwzDstEnd = pwzFin + wcNew;
|
|
pwzDst = LoadCommandLine(pwzLine, pwzDst, pwzDstEnd);
|
|
*pwzDst = '\0';
|
|
|
|
FileNames::ParameterizeLine(pwzFin, pwzFin + wcNew);
|
|
if (HasSpace(wzPath)) {
|
|
Tblog("<t:Line>"%le" %le</t:Line>\n", wzPath, pwzFin);
|
|
}
|
|
else {
|
|
Tblog("<t:Line>%le %le</t:Line>\n", wzPath, pwzFin);
|
|
}
|
|
|
|
TestHandle("t:StdIn", GetStdHandle(STD_INPUT_HANDLE));
|
|
TestHandle("t:StdOut", GetStdHandle(STD_OUTPUT_HANDLE));
|
|
TestHandle("t:StdErr", GetStdHandle(STD_ERROR_HANDLE));
|
|
}
|
|
|
|
if (FindMsvcr()) {
|
|
FindProc(&(PVOID&)Real_getenv, "getenv");
|
|
FindProc(&(PVOID&)Real_wgetenv, "_wgetenv");
|
|
FindProc(&(PVOID&)Real_getenv_s, "getenv_s");
|
|
FindProc(&(PVOID&)Real_wgetenv_s, "_wgetenv_s");
|
|
FindProc(&(PVOID&)Real_dupenv_s, "_dupenv_s");
|
|
FindProc(&(PVOID&)Real_wdupenv_s, "_wdupenv_s");
|
|
|
|
DetourTransactionBegin();
|
|
DetourUpdateThread(GetCurrentThread());
|
|
|
|
DetourAttachIf(&(PVOID&)Real_getenv, Mine_getenv);
|
|
DetourAttachIf(&(PVOID&)Real_getenv_s, Mine_getenv_s);
|
|
DetourAttachIf(&(PVOID&)Real_wgetenv, Mine_wgetenv);
|
|
DetourAttachIf(&(PVOID&)Real_wgetenv, Mine_wgetenv_s);
|
|
DetourAttachIf(&(PVOID&)Real_dupenv_s, Mine_dupenv_s);
|
|
DetourAttachIf(&(PVOID&)Real_wdupenv_s, Mine_wdupenv_s);
|
|
|
|
DetourTransactionCommit();
|
|
}
|
|
|
|
return Real_EntryPoint();
|
|
}
|
|
|
|
VOID WINAPI Mine_ExitProcess(UINT a0)
|
|
{
|
|
if (a0 & 0x80000000) {
|
|
Tblog("<t:Return>%d</t:Return>\n", -(int)a0);
|
|
}
|
|
else {
|
|
Tblog("<t:Return>%d</t:Return>\n", a0);
|
|
}
|
|
|
|
FileNames::Dump();
|
|
EnvVars::Dump();
|
|
|
|
TblogClose();
|
|
|
|
Real_ExitProcess(a0);
|
|
}
|
|
|
|
BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason, PVOID lpReserved)
|
|
{
|
|
(void)hModule;
|
|
(void)lpReserved;
|
|
|
|
if (DetourIsHelperProcess()) {
|
|
return TRUE;
|
|
}
|
|
|
|
if (dwReason == DLL_PROCESS_ATTACH) {
|
|
DetourRestoreAfterWith();
|
|
Real_EntryPoint = (int (WINAPI *)(VOID))DetourGetEntryPoint(NULL);
|
|
return ProcessAttach(hModule);
|
|
}
|
|
else if (dwReason == DLL_PROCESS_DETACH) {
|
|
return ProcessDetach(hModule);
|
|
}
|
|
else if (dwReason == DLL_THREAD_ATTACH) {
|
|
return ThreadAttach(hModule);
|
|
}
|
|
else if (dwReason == DLL_THREAD_DETACH) {
|
|
return ThreadDetach(hModule);
|
|
}
|
|
return TRUE;
|
|
}
|
|
//
|
|
///////////////////////////////////////////////////////////////// End of File.
|