///////////////////////////////////////////////////////////////////////////// // // Detours Test Program (trcbld.cpp of trcbld.dll) // // Microsoft Research Detours Package // // Copyright (c) Microsoft Corporation. All rights reserved. // #define _WIN32_WINNT 0x0501 #define WIN32 #define NT #define DBG_TRACE 0 #include #include #pragma warning(push) #if _MSC_VER > 1400 #pragma warning(disable:6102 6103) // /analyze warnings #endif #include #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("\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("\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("\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("\n", n, s_nVars); continue; } if (pInfo->m_fUsed && pInfo->m_pwzVal[0]) { Print("%le\n", pInfo->m_pwzVar, pInfo->m_pwzVal); } } GlobalFree((HGLOBAL)pSorted); Tblog("\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("\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("\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("\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("\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("\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("%ls\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("%ls\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("%ls%le\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("%ls%he\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("\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("\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("%ls\n", FileNames::ParameterizeName(wzPath, ARRAYSIZE(wzPath), pInfo)); Print("%le\n", lpCommandLine); Print("\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("\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("\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("%ls\n", FileNames::ParameterizeName(wzPath, ARRAYSIZE(wzPath), pInfo)); Print("%he\n", lpCommandLine); Print("\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("\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("\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("\n", a0, a1); #endif rv = Real_CopyFileExW(a0, a1, a2, a3, a4, a5); } __finally { ExitFunc(); if (rv) { #if 0 Print("\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("\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("\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("\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("\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("\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("\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("\n", a1, DeviceType, Access, Function, Method, pInfo->m_pwzPath); } else { Print("\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("\n", pszName, h, pInfo->m_pwzPath); } else { Tblog("\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("\n", pInfo->m_pwzPath); #endif pInfo->m_fAppend = TRUE; } #if 0 else if (dwMoveMethod == FILE_END) { Print("\n", (int)lDistanceToMove, *lpDistanceToMoveHigh, pInfo->m_pwzPath); } else if (dwMoveMethod == FILE_BEGIN) { Print("\n", (int)lDistanceToMove, *lpDistanceToMoveHigh, pInfo->m_pwzPath); } else if (dwMoveMethod == FILE_CURRENT) { Print("\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("\n", liDistanceToMove.QuadPart, pInfo->m_pwzPath); } else if (dwMoveMethod == FILE_BEGIN) { Print("\n", liDistanceToMove.QuadPart, pInfo->m_pwzPath); } else if (dwMoveMethod == FILE_CURRENT) { Print("\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("\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("\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("\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("\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\n", pszName, pInfo->m_fAppend ? " append=\"true\"" : "", pInfo->m_pwzPath, pszName); } } else { Tblog("\n", pszName, h); } } LONG WINAPI DetourAttachIf(PVOID *ppPointer, PVOID pDetour) { if (*ppPointer == NULL) { Tblog("\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("\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("\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("')) { 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("%hs\n", szExeName); } // Get the real executable name. wzPath[0] = '\0'; if (GetModuleFileNameA(0, szExeName, ARRAYSIZE(szExeName))) { FileInfo *pInfo = FileNames::FindPartial(szExeName); Tblog("%ls\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(""%le" %le\n", wzPath, pwzFin); } else { Tblog("%le %le\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("%d\n", -(int)a0); } else { Tblog("%d\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.