aboutsummaryrefslogtreecommitdiffhomepage
path: root/samples/tracebld/trcbld.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'samples/tracebld/trcbld.cpp')
-rw-r--r--samples/tracebld/trcbld.cpp4573
1 files changed, 4573 insertions, 0 deletions
diff --git a/samples/tracebld/trcbld.cpp b/samples/tracebld/trcbld.cpp
new file mode 100644
index 0000000..5392f90
--- /dev/null
+++ b/samples/tracebld/trcbld.cpp
@@ -0,0 +1,4573 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// 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 = &pi;
+ }
+
+ 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 = &pi;
+ }
+
+ 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>&quot;%le&quot; %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.