[Pkg-virtualbox-commits] [kbuild] 01/03: Imported Upstream version 0.1.9998svn2911+dfsg
Gianfranco Costamagna
locutusofborg at moszumanska.debian.org
Tue Sep 13 14:40:40 UTC 2016
This is an automated email from the git hooks/post-receive script.
locutusofborg pushed a commit to branch experimental
in repository kbuild.
commit 96e32c91d68fe624656ef9bbe249a5d96f01c93d
Author: Gianfranco Costamagna <locutusofborg at debian.org>
Date: Tue Sep 13 16:34:44 2016 +0200
Imported Upstream version 0.1.9998svn2911+dfsg
---
kBuild/tools/VCC100AMD64.kmk | 14 +-
kBuild/tools/VCC100X86.kmk | 14 +-
src/kWorker/kWorker.c | 970 ++++++++++++++++++++++++++++++++++++++++--
src/kmk/Makefile.kmk | 6 +-
src/kmk/kmkbuiltin.h | 3 +-
src/kmk/kmkbuiltin/cat.c | 16 +-
src/kmk/kmkbuiltin/err.c | 112 ++++-
src/kmk/kmkbuiltin/mscfakes.c | 6 +-
src/kmk/kmkbuiltin/printf.c | 126 +++++-
src/kmk/kmkbuiltin/solfakes.c | 6 +-
src/kmk/main.c | 4 +-
src/kmk/misc.c | 89 ++++
src/lib/Makefile.kmk | 5 +-
src/lib/maybe_con_fwrite.c | 114 +++++
src/lib/maybe_con_write.c | 116 +++++
src/lib/msc_buffered_printf.c | 254 +++++++++++
src/lib/nt/ntstuff.h | 55 ++-
src/sed/Makefile.kmk | 4 +-
src/sed/lib/utils.c | 5 +
19 files changed, 1839 insertions(+), 80 deletions(-)
diff --git a/kBuild/tools/VCC100AMD64.kmk b/kBuild/tools/VCC100AMD64.kmk
index 5261eeb..a4740db 100644
--- a/kBuild/tools/VCC100AMD64.kmk
+++ b/kBuild/tools/VCC100AMD64.kmk
@@ -1,4 +1,4 @@
-# $Id: VCC100AMD64.kmk 2895 2016-09-08 13:28:37Z bird $
+# $Id: VCC100AMD64.kmk 2902 2016-09-09 17:15:22Z bird $
## @file
# kBuild Tool Config - Visual C++ 10.0 (aka Visual 2010 and MSC v16), targeting AMD64.
#
@@ -68,7 +68,8 @@ PATH_TOOL_VCC100AMD64_ATLMFC_LIB ?= $(PATH_TOOL_VCC100AMD64_ATLMFC)/lib/amd64
TOOL_VCC100AMD64_CC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/cl.exe
TOOL_VCC100AMD64_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/cl.exe
TOOL_VCC100AMD64_AS ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/ml64.exe
-TOOL_VCC100AMD64_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/lib.exe
+#TOOL_VCC100AMD64_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/lib.exe - just an exec wrapper for the below
+TOOL_VCC100AMD64_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/link.exe /LIB
TOOL_VCC100AMD64_LD ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/link.exe
TOOL_VCC100AMD64_DUMPBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/dumpbin.exe
TOOL_VCC100AMD64_EDITBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/editbin.exe
@@ -81,6 +82,7 @@ ifdef TOOL_VCC100AMD64_USE_KSUBMIT
else
TOOL_VCC100AMD64_KSUBMIT ?= kmk_builtin_kSubmit --32-bit
endif
+ TOOL_VCC100AMD64_KSUBMIT_DD = $(TOOL_VCC100AMD64_KSUBMIT) --
endif
endif
@@ -301,7 +303,7 @@ define TOOL_VCC100AMD64_LINK_LIBRARY_CMDS
$(filter-out %.def,$(othersrc))) \
$(addprefix /DEF:,$(filter %.def,$(othersrc))) \
,\"$(arg)\")
- $(QUIET)$(TOOL_VCC100AMD64_AR) $(flags) /OUT:$(out) @$(outbase).rsp
+ $(QUIET)$(TOOL_VCC100AMD64_KSUBMIT_DD) $(TOOL_VCC100AMD64_AR) $(flags) /OUT:$(out) @$(outbase).rsp
endef
@@ -331,7 +333,7 @@ define TOOL_VCC100AMD64_LINK_PROGRAM_CMDS
$(subst /,\\,$(objs)) \
$(subst /,\\,$(libs)) \
,\"$(arg)\")
- $(QUIET)$(TOOL_VCC100AMD64_LD) $(flags) \
+ $(QUIET)$(TOOL_VCC100AMD64_KSUBMIT_DD) $(TOOL_VCC100AMD64_LD) $(flags) \
/OUT:$(out) \
/MAPINFO:EXPORTS /INCREMENTAL:NO \
/MAP:$(outbase).map \
@@ -373,7 +375,7 @@ define TOOL_VCC100AMD64_LINK_DLL_CMDS
$(subst /,\\,$(objs)) \
$(subst /,\\,$(libs)) \
,\"$(arg)\")
- $(QUIET)$(TOOL_VCC100AMD64_LD) $(flags) \
+ $(QUIET)$(TOOL_VCC100AMD64_KSUBMIT_DD) $(TOOL_VCC100AMD64_LD) $(flags) \
/OUT:$(out) \
/IMPLIB:$(outbase).lib \
/MAPINFO:EXPORTS /INCREMENTAL:NO \
@@ -419,7 +421,7 @@ define TOOL_VCC100AMD64_LINK_SYSMOD_CMDS
$(subst /,\\,$(objs)) \
$(subst /,\\,$(libs)) \
,\"$(arg)\")
- $(QUIET)$(TOOL_VCC100AMD64_LD) $(flags) \
+ $(QUIET)$(TOOL_VCC100AMD64_KSUBMIT_DD) $(TOOL_VCC100AMD64_LD) $(flags) \
/OUT:$(out) \
/MAPINFO:EXPORTS /INCREMENTAL:NO \
/MAP:$(outbase).map \
diff --git a/kBuild/tools/VCC100X86.kmk b/kBuild/tools/VCC100X86.kmk
index e3ad436..95d6ac8 100644
--- a/kBuild/tools/VCC100X86.kmk
+++ b/kBuild/tools/VCC100X86.kmk
@@ -1,4 +1,4 @@
-# $Id: VCC100X86.kmk 2895 2016-09-08 13:28:37Z bird $
+# $Id: VCC100X86.kmk 2902 2016-09-09 17:15:22Z bird $
## @file
# kBuild Tool Config - Visual C++ 10.0 (aka Visual 2010 and MSC v16), targeting x86.
#
@@ -67,7 +67,8 @@ PATH_TOOL_VCC100X86_ATLMFC_LIB ?= $(PATH_TOOL_VCC100X86_ATLMFC)/lib
TOOL_VCC100X86_CC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/cl.exe
TOOL_VCC100X86_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/cl.exe
TOOL_VCC100X86_AS ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/ml.exe
-TOOL_VCC100X86_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/lib.exe
+#TOOL_VCC100X86_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/lib.exe - just an exec wrapper for the below
+TOOL_VCC100X86_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/link.exe /LIB
TOOL_VCC100X86_LD ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/link.exe
TOOL_VCC100X86_DUMPBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/dumpbin.exe
TOOL_VCC100X86_EDITBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/editbin.exe
@@ -76,6 +77,7 @@ TOOL_VCC100X86_MT ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,mt.e
ifdef TOOL_VCC100X86_USE_KSUBMIT
ifeq ($(KBUILD_HOST),win)
TOOL_VCC100X86_KSUBMIT ?= kmk_builtin_kSubmit --32-bit
+ TOOL_VCC100X86_KSUBMIT_DD = $(TOOL_VCC100X86_KSUBMIT) --
endif
endif
@@ -298,7 +300,7 @@ define TOOL_VCC100X86_LINK_LIBRARY_CMDS
$(filter-out %.def,$(othersrc))) \
$(addprefix /DEF:,$(filter %.def,$(othersrc))) \
,\"$(arg)\")
- $(QUIET)$(TOOL_VCC100X86_AR) $(flags) /OUT:$(out) @$(outbase).rsp
+ $(QUIET)$(TOOL_VCC100X86_KSUBMIT_DD) $(TOOL_VCC100X86_AR) $(flags) /OUT:$(out) @$(outbase).rsp
endef
@@ -328,7 +330,7 @@ define TOOL_VCC100X86_LINK_PROGRAM_CMDS
$(subst /,\\,$(objs)) \
$(subst /,\\,$(libs)) \
,\"$(arg)\")
- $(QUIET)$(TOOL_VCC100X86_LD) $(flags) \
+ $(QUIET)$(TOOL_VCC100X86_KSUBMIT_DD) $(TOOL_VCC100X86_LD) $(flags) \
/OUT:$(out) \
/MAPINFO:EXPORTS /INCREMENTAL:NO \
/MAP:$(outbase).map \
@@ -370,7 +372,7 @@ define TOOL_VCC100X86_LINK_DLL_CMDS
$(subst /,\\,$(objs)) \
$(subst /,\\,$(libs)) \
,\"$(arg)\")
- $(QUIET)$(TOOL_VCC100X86_LD) $(flags) \
+ $(QUIET)$(TOOL_VCC100X86_KSUBMIT_DD) $(TOOL_VCC100X86_LD) $(flags) \
/OUT:$(out) \
/IMPLIB:$(outbase).lib \
/MAPINFO:EXPORTS /INCREMENTAL:NO \
@@ -416,7 +418,7 @@ define TOOL_VCC100X86_LINK_SYSMOD_CMDS
$(subst /,\\,$(objs)) \
$(subst /,\\,$(libs)) \
,\"$(arg)\")
- $(QUIET)$(TOOL_VCC100X86_LD) $(flags) \
+ $(QUIET)$(TOOL_VCC100X86_KSUBMIT_DD) $(TOOL_VCC100X86_LD) $(flags) \
/OUT:$(out) \
/MAPINFO:EXPORTS /INCREMENTAL:NO \
/MAP:$(outbase).map \
diff --git a/src/kWorker/kWorker.c b/src/kWorker/kWorker.c
index d4add04..6962738 100644
--- a/src/kWorker/kWorker.c
+++ b/src/kWorker/kWorker.c
@@ -1,4 +1,4 @@
-/* $Id: kWorker.c 2898 2016-09-08 15:38:50Z bird $ */
+/* $Id: kWorker.c 2906 2016-09-09 22:15:57Z bird $ */
/** @file
* kWorker - experimental process reuse worker for Windows.
*
@@ -69,6 +69,11 @@ extern void nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull);
* they are included. */
#define WITH_HASH_MD5_CACHE
+/** @def WITH_CONSOLE_OUTPUT_BUFFERING
+ * Enables buffering of all console output as well as removal of annoying
+ * source file echo by cl.exe. */
+#define WITH_CONSOLE_OUTPUT_BUFFERING
+
/** String constant comma length. */
#define TUPLE(a_sz) a_sz, sizeof(a_sz) - 1
@@ -275,8 +280,8 @@ typedef struct KFSWCACHEDFILE
/** Pointer to a cached filed. */
typedef KFSWCACHEDFILE *PKFSWCACHEDFILE;
-
#ifdef WITH_HASH_MD5_CACHE
+
/** Pointer to a MD5 hash instance. */
typedef struct KWHASHMD5 *PKWHASHMD5;
/**
@@ -306,9 +311,9 @@ typedef struct KWHASHMD5
} KWHASHMD5;
/** Magic value for KWHASHMD5::uMagic (Les McCann). */
# define KWHASHMD5_MAGIC KUPTR_C(0x19350923)
-#endif /* WITH_HASH_MD5_CACHE */
-
+#endif /* WITH_HASH_MD5_CACHE */
+#ifdef WITH_TEMP_MEMORY_FILES
typedef struct KWFSTEMPFILESEG *PKWFSTEMPFILESEG;
typedef struct KWFSTEMPFILESEG
@@ -344,6 +349,52 @@ typedef struct KWFSTEMPFILE
PKWFSTEMPFILESEG paSegs;
} KWFSTEMPFILE;
+#endif /* WITH_TEMP_MEMORY_FILES */
+#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
+
+/**
+ * Console line buffer.
+ */
+typedef struct KWCONSOLEOUTPUTLINE
+{
+ /** The main output handle. */
+ HANDLE hOutput;
+ /** Our backup handle. */
+ HANDLE hBackup;
+ /** Set if this is a console handle. */
+ KBOOL fIsConsole;
+ /** Amount of pending console output in wchar_t's. */
+ KU32 cwcBuf;
+ /** The allocated buffer size. */
+ KU32 cwcBufAlloc;
+ /** Pending console output. */
+ wchar_t *pwcBuf;
+} KWCONSOLEOUTPUTLINE;
+/** Pointer to a console line buffer. */
+typedef KWCONSOLEOUTPUTLINE *PKWCONSOLEOUTPUTLINE;
+
+/**
+ * Combined console buffer of complete lines.
+ */
+typedef struct KWCONSOLEOUTPUT
+{
+ /** The console output handle.
+ * INVALID_HANDLE_VALUE if we haven't got a console and shouldn't be doing any
+ * combined output buffering. */
+ HANDLE hOutput;
+ /** The current code page for the console. */
+ KU32 uCodepage;
+ /** Amount of pending console output in wchar_t's. */
+ KU32 cwcBuf;
+ /** Number of times we've flushed it in any way (for cl.exe hack). */
+ KU32 cFlushes;
+ /** Pending console output. */
+ wchar_t wszBuf[8192];
+} KWCONSOLEOUTPUT;
+/** Pointer to a combined console buffer. */
+typedef KWCONSOLEOUTPUT *PKWCONSOLEOUTPUT;
+
+#endif /* WITH_CONSOLE_OUTPUT_BUFFERING */
/** Handle type. */
typedef enum KWHANDLETYPE
@@ -391,6 +442,18 @@ typedef struct KWVIRTALLOC
} KWVIRTALLOC;
+/** Pointer to a heap (HeapCreate) tracker entry. */
+typedef struct KWHEAP *PKWHEAP;
+/**
+ * Tracking an heap (HeapCreate)
+ */
+typedef struct KWHEAP
+{
+ PKWHEAP pNext;
+ HANDLE hHeap;
+} KWHEAP;
+
+
/** Pointer to a FlsAlloc/TlsAlloc tracker entry. */
typedef struct KWLOCALSTORAGE *PKWLOCALSTORAGE;
/**
@@ -403,6 +466,20 @@ typedef struct KWLOCALSTORAGE
} KWLOCALSTORAGE;
+/** Pointer to an at exit callback record */
+typedef struct KWEXITCALLACK *PKWEXITCALLACK;
+/**
+ * At exit callback record.
+ */
+typedef struct KWEXITCALLACK
+{
+ PKWEXITCALLACK pNext;
+ _onexit_t pfnCallback;
+ /** At exit doesn't have an exit code. */
+ KBOOL fAtExit;
+} KWEXITCALLACK;
+
+
typedef enum KWTOOLTYPE
{
KWTOOLTYPE_INVALID = 0,
@@ -417,6 +494,7 @@ typedef enum KWTOOLHINT
KWTOOLHINT_INVALID = 0,
KWTOOLHINT_NONE,
KWTOOLHINT_VISUAL_CPP_CL,
+ KWTOOLHINT_VISUAL_CPP_LINK,
KWTOOLHINT_END
} KWTOOLHINT;
@@ -525,11 +603,18 @@ typedef struct KWSANDBOX
/** Head of the virtual alloc allocations. */
PKWVIRTALLOC pVirtualAllocHead;
+ /** Head of the heap list (HeapCreate).
+ * This is only done from images we forcibly restore. */
+ PKWHEAP pHeapHead;
/** Head of the FlsAlloc indexes. */
PKWLOCALSTORAGE pFlsAllocHead;
/** Head of the TlsAlloc indexes. */
PKWLOCALSTORAGE pTlsAllocHead;
+ /** The at exit callback head.
+ * This is only done from images we forcibly restore. */
+ PKWEXITCALLACK pExitCallbackHead;
+
UNICODE_STRING SavedCommandLine;
#ifdef WITH_HASH_MD5_CACHE
@@ -553,6 +638,15 @@ typedef struct KWSANDBOX
void *pvRead;
} LastHashRead;
#endif
+
+#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
+ /** Standard output (and whatever else) line buffer. */
+ KWCONSOLEOUTPUTLINE StdOut;
+ /** Standard error line buffer. */
+ KWCONSOLEOUTPUTLINE StdErr;
+ /** Combined buffer of completed lines. */
+ KWCONSOLEOUTPUT Combined;
+#endif
} KWSANDBOX;
/** Replacement function entry. */
@@ -566,6 +660,9 @@ typedef struct KWREPLACEMENTFUNCTION
const char *pszModule;
/** The replacement function or data address. */
KUPTR pfnReplacement;
+ /** Only replace in the executable.
+ * @todo fix the reinitialization of non-native DLLs! */
+ KBOOL fOnlyExe;
} KWREPLACEMENTFUNCTION;
typedef KWREPLACEMENTFUNCTION const *PCKWREPLACEMENTFUNCTION;
@@ -639,6 +736,9 @@ static KU8 g_abDefLdBuf[16*1024*1024];
static FNKLDRMODGETIMPORT kwLdrModuleGetImportCallback;
static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWMODULE pImporter, PKWMODULE *ppMod);
static KBOOL kwSandboxHandleTableEnter(PKWSANDBOX pSandbox, PKWHANDLE pHandle);
+#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
+static void kwSandboxConsoleWriteA(PKWSANDBOX pSandbox, PKWCONSOLEOUTPUTLINE pLineBuf, const char *pchBuffer, KU32 cchToWrite);
+#endif
@@ -1695,8 +1795,12 @@ static int kwLdrModuleGetImportCallback(PKLDRMOD pMod, KU32 iImport, KU32 iSymbo
if ( !g_aSandboxReplacements[i].pszModule
|| kHlpStrICompAscii(g_aSandboxReplacements[i].pszModule, &pImpMod->pszPath[pImpMod->offFilename]) == 0)
{
- KW_LOG(("replacing %s!%s\n", &pImpMod->pszPath[pImpMod->offFilename], g_aSandboxReplacements[i].pszFunction));
- *puValue = g_aSandboxReplacements[i].pfnReplacement;
+ if ( pCurMod->fExe
+ || !g_aSandboxReplacements[i].fOnlyExe)
+ {
+ KW_LOG(("replacing %s!%s\n",&pImpMod->pszPath[pImpMod->offFilename], g_aSandboxReplacements[i].pszFunction));
+ *puValue = g_aSandboxReplacements[i].pfnReplacement;
+ }
break;
}
}
@@ -2228,6 +2332,8 @@ static PKWTOOL kwToolEntryCreate(PKFSOBJ pToolFsObj)
{
if (kHlpStrICompAscii(pToolFsObj->pszName, "cl.exe") == 0)
pTool->u.Sandboxed.enmHint = KWTOOLHINT_VISUAL_CPP_CL;
+ else if (kHlpStrICompAscii(pToolFsObj->pszName, "link.exe") == 0)
+ pTool->u.Sandboxed.enmHint = KWTOOLHINT_VISUAL_CPP_LINK;
else
pTool->u.Sandboxed.enmHint = KWTOOLHINT_NONE;
kwToolAddModuleAndImports(pTool, pTool->u.Sandboxed.pExe);
@@ -2528,6 +2634,56 @@ static void __cdecl kwSandbox_msvcrt_terminate(void)
}
+/** CRT - _onexit */
+static _onexit_t __cdecl kwSandbox_msvcrt__onexit(_onexit_t pfnFunc)
+{
+ if (g_Sandbox.pTool->u.Sandboxed.enmHint == KWTOOLHINT_VISUAL_CPP_LINK)
+ {
+ PKWEXITCALLACK pCallback;
+ KW_LOG(("_onexit(%p)\n", pfnFunc));
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ pCallback = kHlpAlloc(sizeof(*pCallback));
+ if (pCallback)
+ {
+ pCallback->pfnCallback = pfnFunc;
+ pCallback->fAtExit = K_FALSE;
+ pCallback->pNext = g_Sandbox.pExitCallbackHead;
+ g_Sandbox.pExitCallbackHead = pCallback;
+ return pfnFunc;
+ }
+ return NULL;
+ }
+ KW_LOG(("_onexit(%p) - IGNORED\n", pfnFunc));
+ return pfnFunc;
+}
+
+
+/** CRT - atexit */
+static int __cdecl kwSandbox_msvcrt_atexit(int (__cdecl *pfnFunc)(void))
+{
+ if (g_Sandbox.pTool->u.Sandboxed.enmHint == KWTOOLHINT_VISUAL_CPP_LINK)
+ {
+ PKWEXITCALLACK pCallback;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+ KW_LOG(("atexit(%p)\n", pfnFunc));
+
+ pCallback = kHlpAlloc(sizeof(*pCallback));
+ if (pCallback)
+ {
+ pCallback->pfnCallback = (_onexit_t)pfnFunc;
+ pCallback->fAtExit = K_TRUE;
+ pCallback->pNext = g_Sandbox.pExitCallbackHead;
+ g_Sandbox.pExitCallbackHead = pCallback;
+ return 0;
+ }
+ return -1;
+ }
+ KW_LOG(("atexit(%p) - IGNORED!\n", pfnFunc));
+ return 0;
+}
+
+
/** Kernel32 - SetConsoleCtrlHandler(). */
static BOOL WINAPI kwSandbox_Kernel32_SetConsoleCtrlHandler(PHANDLER_ROUTINE pfnHandler, BOOL fAdd)
{
@@ -2540,6 +2696,7 @@ static BOOL WINAPI kwSandbox_Kernel32_SetConsoleCtrlHandler(PHANDLER_ROUTINE pfn
static int __cdecl kwSandbox_msvcrt___getmainargs(int *pargc, char ***pargv, char ***penvp,
int dowildcard, int const *piNewMode)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
*pargc = g_Sandbox.cArgs;
*pargv = g_Sandbox.papszArgs;
*penvp = g_Sandbox.environ;
@@ -2553,6 +2710,7 @@ static int __cdecl kwSandbox_msvcrt___getmainargs(int *pargc, char ***pargv, cha
static int __cdecl kwSandbox_msvcrt___wgetmainargs(int *pargc, wchar_t ***pargv, wchar_t ***penvp,
int dowildcard, int const *piNewMode)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
*pargc = g_Sandbox.cArgs;
*pargv = g_Sandbox.papwszArgs;
*penvp = g_Sandbox.wenviron;
@@ -2566,6 +2724,7 @@ static int __cdecl kwSandbox_msvcrt___wgetmainargs(int *pargc, wchar_t ***pargv,
/** Kernel32 - GetCommandLineA() */
static LPCSTR /*LPSTR*/ WINAPI kwSandbox_Kernel32_GetCommandLineA(VOID)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
return g_Sandbox.pszCmdLine;
}
@@ -2573,6 +2732,7 @@ static LPCSTR /*LPSTR*/ WINAPI kwSandbox_Kernel32_GetCommandLineA(VOID)
/** Kernel32 - GetCommandLineW() */
static LPCWSTR /*LPWSTR*/ WINAPI kwSandbox_Kernel32_GetCommandLineW(VOID)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
return g_Sandbox.pwszCmdLine;
}
@@ -2604,6 +2764,7 @@ static VOID WINAPI kwSandbox_Kernel32_GetStartupInfoW(LPSTARTUPINFOW pStartupInf
/** CRT - __p___argc(). */
static int * __cdecl kwSandbox_msvcrt___p___argc(void)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
return &g_Sandbox.cArgs;
}
@@ -2611,6 +2772,7 @@ static int * __cdecl kwSandbox_msvcrt___p___argc(void)
/** CRT - __p___argv(). */
static char *** __cdecl kwSandbox_msvcrt___p___argv(void)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
return &g_Sandbox.papszArgs;
}
@@ -2618,6 +2780,7 @@ static char *** __cdecl kwSandbox_msvcrt___p___argv(void)
/** CRT - __p___sargv(). */
static wchar_t *** __cdecl kwSandbox_msvcrt___p___wargv(void)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
return &g_Sandbox.papwszArgs;
}
@@ -2625,6 +2788,7 @@ static wchar_t *** __cdecl kwSandbox_msvcrt___p___wargv(void)
/** CRT - __p__acmdln(). */
static char ** __cdecl kwSandbox_msvcrt___p__acmdln(void)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
return (char **)&g_Sandbox.pszCmdLine;
}
@@ -2632,6 +2796,7 @@ static char ** __cdecl kwSandbox_msvcrt___p__acmdln(void)
/** CRT - __p__acmdln(). */
static wchar_t ** __cdecl kwSandbox_msvcrt___p__wcmdln(void)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
return &g_Sandbox.pwszCmdLine;
}
@@ -2639,6 +2804,7 @@ static wchar_t ** __cdecl kwSandbox_msvcrt___p__wcmdln(void)
/** CRT - __p__pgmptr(). */
static char ** __cdecl kwSandbox_msvcrt___p__pgmptr(void)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
return &g_Sandbox.pgmptr;
}
@@ -2646,6 +2812,7 @@ static char ** __cdecl kwSandbox_msvcrt___p__pgmptr(void)
/** CRT - __p__wpgmptr(). */
static wchar_t ** __cdecl kwSandbox_msvcrt___p__wpgmptr(void)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
return &g_Sandbox.wpgmptr;
}
@@ -2653,6 +2820,7 @@ static wchar_t ** __cdecl kwSandbox_msvcrt___p__wpgmptr(void)
/** CRT - _get_pgmptr(). */
static errno_t __cdecl kwSandbox_msvcrt__get_pgmptr(char **ppszValue)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
*ppszValue = g_Sandbox.pgmptr;
return 0;
}
@@ -2661,6 +2829,7 @@ static errno_t __cdecl kwSandbox_msvcrt__get_pgmptr(char **ppszValue)
/** CRT - _get_wpgmptr(). */
static errno_t __cdecl kwSandbox_msvcrt__get_wpgmptr(wchar_t **ppwszValue)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
*ppwszValue = g_Sandbox.wpgmptr;
return 0;
}
@@ -2668,6 +2837,7 @@ static errno_t __cdecl kwSandbox_msvcrt__get_wpgmptr(wchar_t **ppwszValue)
/** Just in case. */
static void kwSandbox_msvcrt__wincmdln(void)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
KWFS_TODO();
}
@@ -2675,6 +2845,7 @@ static void kwSandbox_msvcrt__wincmdln(void)
/** Just in case. */
static void kwSandbox_msvcrt__wwincmdln(void)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
KWFS_TODO();
}
@@ -2683,14 +2854,26 @@ static HANDLE WINAPI kwSandbox_Kernel32_CreateThread(LPSECURITY_ATTRIBUTES pSecA
PTHREAD_START_ROUTINE pfnThreadProc, PVOID pvUser,
DWORD fFlags, PDWORD pidThread)
{
- KWFS_TODO();
- return NULL;
+ HANDLE hThread = NULL;
+ KW_LOG(("CreateThread: pSecAttr=%p (inh=%d) cbStack=%#x pfnThreadProc=%p pvUser=%p fFlags=%#x pidThread=%p\n",
+ pSecAttr, pSecAttr ? pSecAttr->bInheritHandle : 0, cbStack, pfnThreadProc, pvUser, fFlags, pidThread));
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+ if (g_Sandbox.pTool->u.Sandboxed.enmHint == KWTOOLHINT_VISUAL_CPP_LINK)
+ {
+ /* Allow link::DbgThread. */
+ hThread = CreateThread(pSecAttr, cbStack, pfnThreadProc, pvUser, fFlags, pidThread);
+ KW_LOG(("CreateThread -> %p, *pidThread=%#x\n", hThread, pidThread ? *pidThread : 0));
+ }
+ else
+ KWFS_TODO();
+ return hThread;
}
/** _beginthread - create a new thread. */
static uintptr_t __cdecl kwSandbox_msvcrt__beginthread(void (__cdecl *pfnThreadProc)(void *), unsigned cbStack, void *pvUser)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
KWFS_TODO();
return 0;
}
@@ -2701,6 +2884,7 @@ static uintptr_t __cdecl kwSandbox_msvcrt__beginthreadex(void *pvSecAttr, unsign
unsigned (__stdcall *pfnThreadProc)(void *), void *pvUser,
unsigned fCreate, unsigned *pidThread)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
KWFS_TODO();
return 0;
}
@@ -2718,11 +2902,13 @@ static uintptr_t __cdecl kwSandbox_msvcrt__beginthreadex(void *pvSecAttr, unsign
static LPCH WINAPI kwSandbox_Kernel32_GetEnvironmentStringsA(void)
{
char *pszzEnv;
-
- /* Figure how space much we need first. */
char *pszCur;
KSIZE cbNeeded = 1;
KSIZE iVar = 0;
+
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ /* Figure how space much we need first. */
while ((pszCur = g_Sandbox.papszEnvVars[iVar++]) != NULL)
cbNeeded += kHlpStrLen(pszCur) + 1;
@@ -2773,11 +2959,13 @@ static LPCH WINAPI kwSandbox_Kernel32_GetEnvironmentStrings(void)
static LPWCH WINAPI kwSandbox_Kernel32_GetEnvironmentStringsW(void)
{
wchar_t *pwszzEnv;
-
- /* Figure how space much we need first. */
wchar_t *pwszCur;
KSIZE cwcNeeded = 1;
KSIZE iVar = 0;
+
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ /* Figure how space much we need first. */
while ((pwszCur = g_Sandbox.papwszEnvVars[iVar++]) != NULL)
cwcNeeded += kwUtf16Len(pwszCur) + 1;
@@ -2806,6 +2994,7 @@ static LPWCH WINAPI kwSandbox_Kernel32_GetEnvironmentStringsW(void)
static BOOL WINAPI kwSandbox_Kernel32_FreeEnvironmentStringsA(LPCH pszzEnv)
{
KW_LOG(("FreeEnvironmentStringsA: %p -> TRUE\n", pszzEnv));
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
kHlpFree(pszzEnv);
return TRUE;
}
@@ -2815,6 +3004,7 @@ static BOOL WINAPI kwSandbox_Kernel32_FreeEnvironmentStringsA(LPCH pszzEnv)
static BOOL WINAPI kwSandbox_Kernel32_FreeEnvironmentStringsW(LPWCH pwszzEnv)
{
KW_LOG(("FreeEnvironmentStringsW: %p -> TRUE\n", pwszzEnv));
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
kHlpFree(pwszzEnv);
return TRUE;
}
@@ -3142,7 +3332,10 @@ static wchar_t *kwSandboxDoGetEnvW(PKWSANDBOX pSandbox, const wchar_t *pwcVar, K
/** Kernel32 - GetEnvironmentVariableA() */
static DWORD WINAPI kwSandbox_Kernel32_GetEnvironmentVariableA(LPCSTR pszVar, LPSTR pszValue, DWORD cbValue)
{
- char *pszFoundValue = kwSandboxDoGetEnvA(&g_Sandbox, pszVar, kHlpStrLen(pszVar));
+ char *pszFoundValue;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ pszFoundValue = kwSandboxDoGetEnvA(&g_Sandbox, pszVar, kHlpStrLen(pszVar));
if (pszFoundValue)
{
DWORD cchRet = kwStrCopyStyle1(pszFoundValue, pszValue, cbValue);
@@ -3158,7 +3351,10 @@ static DWORD WINAPI kwSandbox_Kernel32_GetEnvironmentVariableA(LPCSTR pszVar, LP
/** Kernel32 - GetEnvironmentVariableW() */
static DWORD WINAPI kwSandbox_Kernel32_GetEnvironmentVariableW(LPCWSTR pwszVar, LPWSTR pwszValue, DWORD cwcValue)
{
- wchar_t *pwszFoundValue = kwSandboxDoGetEnvW(&g_Sandbox, pwszVar, kwUtf16Len(pwszVar));
+ wchar_t *pwszFoundValue;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ pwszFoundValue = kwSandboxDoGetEnvW(&g_Sandbox, pwszVar, kwUtf16Len(pwszVar));
if (pwszFoundValue)
{
DWORD cchRet = kwUtf16CopyStyle1(pwszFoundValue, pwszValue, cwcValue);
@@ -3175,6 +3371,8 @@ static DWORD WINAPI kwSandbox_Kernel32_GetEnvironmentVariableW(LPCWSTR pwszVar,
static BOOL WINAPI kwSandbox_Kernel32_SetEnvironmentVariableA(LPCSTR pszVar, LPCSTR pszValue)
{
int rc;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
if (pszValue)
rc = kwSandboxDoSetEnvA(&g_Sandbox, pszVar, kHlpStrLen(pszVar), pszValue);
else
@@ -3197,6 +3395,8 @@ static BOOL WINAPI kwSandbox_Kernel32_SetEnvironmentVariableA(LPCSTR pszVar, LPC
static BOOL WINAPI kwSandbox_Kernel32_SetEnvironmentVariableW(LPCWSTR pwszVar, LPCWSTR pwszValue)
{
int rc;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
if (pwszValue)
rc = kwSandboxDoSetEnvW(&g_Sandbox, pwszVar, kwUtf16Len(pwszVar), pwszValue);
else
@@ -3218,6 +3418,7 @@ static BOOL WINAPI kwSandbox_Kernel32_SetEnvironmentVariableW(LPCWSTR pwszVar, L
/** Kernel32 - ExpandEnvironmentStringsA() */
static DWORD WINAPI kwSandbox_Kernel32_ExpandEnvironmentStringsA(LPCSTR pszSrc, LPSTR pwszDst, DWORD cbDst)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
KWFS_TODO();
return 0;
}
@@ -3226,6 +3427,7 @@ static DWORD WINAPI kwSandbox_Kernel32_ExpandEnvironmentStringsA(LPCSTR pszSrc,
/** Kernel32 - ExpandEnvironmentStringsW() */
static DWORD WINAPI kwSandbox_Kernel32_ExpandEnvironmentStringsW(LPCWSTR pwszSrc, LPWSTR pwszDst, DWORD cbDst)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
KWFS_TODO();
return 0;
}
@@ -3235,7 +3437,10 @@ static DWORD WINAPI kwSandbox_Kernel32_ExpandEnvironmentStringsW(LPCWSTR pwszSrc
static int __cdecl kwSandbox_msvcrt__putenv(const char *pszVarEqualValue)
{
int rc;
- char const *pszEqual = kHlpStrChr(pszVarEqualValue, '=');
+ char const *pszEqual;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ pszEqual = kHlpStrChr(pszVarEqualValue, '=');
if (pszEqual)
{
rc = kwSandboxDoSetEnvA(&g_Sandbox, pszVarEqualValue, pszEqual - pszVarEqualValue, pszEqual + 1);
@@ -3258,7 +3463,10 @@ static int __cdecl kwSandbox_msvcrt__putenv(const char *pszVarEqualValue)
static int __cdecl kwSandbox_msvcrt__wputenv(const wchar_t *pwszVarEqualValue)
{
int rc;
- wchar_t const *pwszEqual = wcschr(pwszVarEqualValue, '=');
+ wchar_t const *pwszEqual;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ pwszEqual = wcschr(pwszVarEqualValue, '=');
if (pwszEqual)
{
rc = kwSandboxDoSetEnvW(&g_Sandbox, pwszVarEqualValue, pwszEqual - pwszVarEqualValue, pwszEqual + 1);
@@ -3280,7 +3488,10 @@ static int __cdecl kwSandbox_msvcrt__wputenv(const wchar_t *pwszVarEqualValue)
/** CRT - _putenv_s(). */
static errno_t __cdecl kwSandbox_msvcrt__putenv_s(const char *pszVar, const char *pszValue)
{
- char const *pszEqual = kHlpStrChr(pszVar, '=');
+ char const *pszEqual;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ pszEqual = kHlpStrChr(pszVar, '=');
if (pszEqual == NULL)
{
if (pszValue)
@@ -3309,7 +3520,10 @@ static errno_t __cdecl kwSandbox_msvcrt__putenv_s(const char *pszVar, const char
/** CRT - _wputenv_s(). */
static errno_t __cdecl kwSandbox_msvcrt__wputenv_s(const wchar_t *pwszVar, const wchar_t *pwszValue)
{
- wchar_t const *pwszEqual = wcschr(pwszVar, '=');
+ wchar_t const *pwszEqual;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ pwszEqual = wcschr(pwszVar, '=');
if (pwszEqual == NULL)
{
if (pwszValue)
@@ -3339,6 +3553,7 @@ static errno_t __cdecl kwSandbox_msvcrt__wputenv_s(const wchar_t *pwszVar, const
static char *** __cdecl kwSandbox_msvcrt___p___initenv(void)
{
KW_LOG(("__p___initenv\n"));
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
KWFS_TODO();
return &g_Sandbox.initenv;
}
@@ -3348,6 +3563,7 @@ static char *** __cdecl kwSandbox_msvcrt___p___initenv(void)
static wchar_t *** __cdecl kwSandbox_msvcrt___p___winitenv(void)
{
KW_LOG(("__p___winitenv\n"));
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
KWFS_TODO();
return &g_Sandbox.winitenv;
}
@@ -3357,6 +3573,7 @@ static wchar_t *** __cdecl kwSandbox_msvcrt___p___winitenv(void)
static char *** __cdecl kwSandbox_msvcrt___p__environ(void)
{
KW_LOG(("__p__environ\n"));
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
return &g_Sandbox.environ;
}
@@ -3365,6 +3582,7 @@ static char *** __cdecl kwSandbox_msvcrt___p__environ(void)
static wchar_t *** __cdecl kwSandbox_msvcrt___p__wenviron(void)
{
KW_LOG(("__p__wenviron\n"));
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
return &g_Sandbox.wenviron;
}
@@ -3374,6 +3592,7 @@ static wchar_t *** __cdecl kwSandbox_msvcrt___p__wenviron(void)
static KUPTR /*void*/ __cdecl kwSandbox_msvcrt__get_environ(char ***ppapszEnviron)
{
KWFS_TODO(); /** @todo check the callers expectations! */
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
*ppapszEnviron = g_Sandbox.environ;
return 0;
}
@@ -3384,6 +3603,7 @@ static KUPTR /*void*/ __cdecl kwSandbox_msvcrt__get_environ(char ***ppapszEnviro
static KUPTR /*void*/ __cdecl kwSandbox_msvcrt__get_wenviron(wchar_t ***ppapwszEnviron)
{
KWFS_TODO(); /** @todo check the callers expectations! */
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
*ppapwszEnviron = g_Sandbox.wenviron;
return 0;
}
@@ -3521,6 +3741,7 @@ static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExA(LPCSTR pszFilename, HAND
PKWDYNLOAD pDynLoad;
PKWMODULE pMod;
int rc;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
/*
* Deal with a couple of extremely unlikely special cases right away.
@@ -3668,6 +3889,7 @@ static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryW(LPCWSTR pwszFilename)
static BOOL WINAPI kwSandbox_Kernel32_FreeLibrary(HMODULE hmod)
{
/* Ignored, we like to keep everything loaded. */
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
return TRUE;
}
@@ -3677,6 +3899,7 @@ static HMODULE WINAPI kwSandbox_Kernel32_GetModuleHandleA(LPCSTR pszModule)
{
KSIZE i;
KSIZE cchModule;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
/*
* The executable.
@@ -3707,6 +3930,7 @@ static HMODULE WINAPI kwSandbox_Kernel32_GetModuleHandleW(LPCWSTR pwszModule)
{
KSIZE i;
KSIZE cwcModule;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
/*
* The executable.
@@ -3735,7 +3959,11 @@ static HMODULE WINAPI kwSandbox_Kernel32_GetModuleHandleW(LPCWSTR pwszModule)
/** Used to debug dynamically resolved procedures. */
static UINT WINAPI kwSandbox_BreakIntoDebugger(void *pv1, void *pv2, void *pv3, void *pv4)
{
+#ifdef _MSC_VER
+ __debugbreak();
+#else
KWFS_TODO();
+#endif
return -1;
}
@@ -3744,11 +3972,13 @@ static UINT WINAPI kwSandbox_BreakIntoDebugger(void *pv1, void *pv2, void *pv3,
static FARPROC WINAPI kwSandbox_Kernel32_GetProcAddress(HMODULE hmod, LPCSTR pszProc)
{
KSIZE i;
+ PKWMODULE pMod;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
/*
* Try locate the module.
*/
- PKWMODULE pMod = kwToolLocateModuleByHandle(g_Sandbox.pTool, hmod);
+ pMod = kwToolLocateModuleByHandle(g_Sandbox.pTool, hmod);
if (pMod)
{
KLDRADDR uValue;
@@ -3794,7 +4024,10 @@ static FARPROC WINAPI kwSandbox_Kernel32_GetProcAddress(HMODULE hmod, LPCSTR psz
/** Kernel32 - GetModuleFileNameA() */
static DWORD WINAPI kwSandbox_Kernel32_GetModuleFileNameA(HMODULE hmod, LPSTR pszFilename, DWORD cbFilename)
{
- PKWMODULE pMod = kwToolLocateModuleByHandle(g_Sandbox.pTool, hmod);
+ PKWMODULE pMod;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ pMod = kwToolLocateModuleByHandle(g_Sandbox.pTool, hmod);
if (pMod != NULL)
{
DWORD cbRet = kwStrCopyStyle1(pMod->pszPath, pszFilename, cbFilename);
@@ -3809,7 +4042,10 @@ static DWORD WINAPI kwSandbox_Kernel32_GetModuleFileNameA(HMODULE hmod, LPSTR ps
/** Kernel32 - GetModuleFileNameW() */
static DWORD WINAPI kwSandbox_Kernel32_GetModuleFileNameW(HMODULE hmod, LPWSTR pwszFilename, DWORD cbFilename)
{
- PKWMODULE pMod = kwToolLocateModuleByHandle(g_Sandbox.pTool, hmod);
+ PKWMODULE pMod;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ pMod = kwToolLocateModuleByHandle(g_Sandbox.pTool, hmod);
if (pMod)
{
DWORD cwcRet = kwUtf16CopyStyle1(pMod->pwszPath, pwszFilename, cbFilename);
@@ -4302,6 +4538,7 @@ static PKFSWCACHEDFILE kwFsObjCacheNewFile(PKFSOBJ pFsObj)
MY_OBJECT_ATTRIBUTES ObjAttr;
MY_UNICODE_STRING UniStr;
MY_NTSTATUS rcNt;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
/*
* Open the file relative to the parent directory.
@@ -4474,7 +4711,10 @@ static HANDLE WINAPI kwSandbox_Kernel32_CreateFileA(LPCSTR pszFilename, DWORD dw
if (kwFsIsCachableExtensionA(pszExt, K_FALSE /*fAttrQuery*/))
{
KFSLOOKUPERROR enmError;
- PKFSOBJ pFsObj = kFsCacheLookupNoMissingA(g_pFsCache, pszFilename, &enmError);
+ PKFSOBJ pFsObj;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ pFsObj = kFsCacheLookupNoMissingA(g_pFsCache, pszFilename, &enmError);
if (pFsObj)
{
KBOOL fRc = kwFsObjCacheCreateFile(pFsObj, dwDesiredAccess, pSecAttrs && pSecAttrs->bInheritHandle,
@@ -4553,7 +4793,7 @@ static HANDLE WINAPI kwSandbox_Kernel32_CreateFileW(LPCWSTR pwszFilename, DWORD
{
if (kwFsIsCachablePathExtensionW(pwszFilename, K_FALSE /*fAttrQuery*/))
{
- /** @todo rewrite to pure UTF-16. */
+ /** @todo rewrite in pure UTF-16. */
char szTmp[2048];
KSIZE cch = kwUtf16ToStr(pwszFilename, szTmp, sizeof(szTmp));
if (cch < sizeof(szTmp))
@@ -4584,6 +4824,7 @@ static HANDLE WINAPI kwSandbox_Kernel32_CreateFileW(LPCWSTR pwszFilename, DWORD
static DWORD WINAPI kwSandbox_Kernel32_SetFilePointer(HANDLE hFile, LONG cbMove, PLONG pcbMoveHi, DWORD dwMoveMethod)
{
KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
if (idxHandle < g_Sandbox.cHandles)
{
PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
@@ -4664,6 +4905,7 @@ static BOOL WINAPI kwSandbox_Kernel32_SetFilePointerEx(HANDLE hFile, LARGE_INTEG
DWORD dwMoveMethod)
{
KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
if (idxHandle < g_Sandbox.cHandles)
{
PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
@@ -4743,6 +4985,7 @@ static BOOL WINAPI kwSandbox_Kernel32_ReadFile(HANDLE hFile, LPVOID pvBuffer, DW
LPOVERLAPPED pOverlapped)
{
KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
if (idxHandle < g_Sandbox.cHandles)
{
PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
@@ -4858,6 +5101,7 @@ static BOOL WINAPI kwSandbox_Kernel32_ReadFileEx(HANDLE hFile, LPVOID pvBuffer,
LPOVERLAPPED_COMPLETION_ROUTINE pfnCompletionRoutine)
{
KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
if (idxHandle < g_Sandbox.cHandles)
{
PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
@@ -4934,6 +5178,7 @@ static BOOL WINAPI kwSandbox_Kernel32_WriteFile(HANDLE hFile, LPCVOID pvBuffer,
LPOVERLAPPED pOverlapped)
{
KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
if (idxHandle < g_Sandbox.cHandles)
{
PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
@@ -5012,6 +5257,23 @@ static BOOL WINAPI kwSandbox_Kernel32_WriteFile(HANDLE hFile, LPCVOID pvBuffer,
}
}
+#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
+ /*
+ * Check for stdout and stderr.
+ */
+ if ( g_Sandbox.StdErr.hOutput == hFile
+ || g_Sandbox.StdOut.hOutput == hFile)
+ {
+ PKWCONSOLEOUTPUTLINE pLineBuf = g_Sandbox.StdErr.hOutput == hFile ? &g_Sandbox.StdErr : &g_Sandbox.StdOut;
+ if (pLineBuf->fIsConsole)
+ {
+ kwSandboxConsoleWriteA(&g_Sandbox, pLineBuf, (const char *)pvBuffer, cbToWrite);
+ KWFS_LOG(("WriteFile(console) -> TRUE\n", hFile));
+ return TRUE;
+ }
+ }
+#endif
+
KWFS_LOG(("WriteFile(%p)\n", hFile));
return WriteFile(hFile, pvBuffer, cbToWrite, pcbActuallyWritten, pOverlapped);
}
@@ -5022,6 +5284,7 @@ static BOOL WINAPI kwSandbox_Kernel32_WriteFileEx(HANDLE hFile, LPCVOID pvBuffer
LPOVERLAPPED_COMPLETION_ROUTINE pfnCompletionRoutine)
{
KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
if (idxHandle < g_Sandbox.cHandles)
{
PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
@@ -5040,6 +5303,7 @@ static BOOL WINAPI kwSandbox_Kernel32_WriteFileEx(HANDLE hFile, LPCVOID pvBuffer
static BOOL WINAPI kwSandbox_Kernel32_SetEndOfFile(HANDLE hFile)
{
KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
if (idxHandle < g_Sandbox.cHandles)
{
PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
@@ -5086,6 +5350,7 @@ static BOOL WINAPI kwSandbox_Kernel32_SetEndOfFile(HANDLE hFile)
static BOOL WINAPI kwSandbox_Kernel32_GetFileType(HANDLE hFile)
{
KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
if (idxHandle < g_Sandbox.cHandles)
{
PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
@@ -5113,6 +5378,7 @@ static BOOL WINAPI kwSandbox_Kernel32_GetFileType(HANDLE hFile)
static DWORD WINAPI kwSandbox_Kernel32_GetFileSize(HANDLE hFile, LPDWORD pcbHighDword)
{
KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
if (idxHandle < g_Sandbox.cHandles)
{
PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
@@ -5148,6 +5414,7 @@ static DWORD WINAPI kwSandbox_Kernel32_GetFileSize(HANDLE hFile, LPDWORD pcbHigh
static BOOL WINAPI kwSandbox_Kernel32_GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER pcbFile)
{
KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
if (idxHandle < g_Sandbox.cHandles)
{
PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
@@ -5184,6 +5451,7 @@ static HANDLE WINAPI kwSandbox_Kernel32_CreateFileMappingW(HANDLE hFile, LPSECUR
DWORD dwMaximumSizeLow, LPCWSTR pwszName)
{
KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
if (idxHandle < g_Sandbox.cHandles)
{
PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
@@ -5223,6 +5491,7 @@ static HANDLE WINAPI kwSandbox_Kernel32_MapViewOfFile(HANDLE hSection, DWORD dwD
DWORD offFileHigh, DWORD offFileLow, SIZE_T cbToMap)
{
KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hSection);
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
if (idxHandle < g_Sandbox.cHandles)
{
PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
@@ -5308,6 +5577,7 @@ static BOOL WINAPI kwSandbox_Kernel32_UnmapViewOfFile(LPCVOID pvBase)
{
/* Is this one of our temporary mappings? */
PKWFSTEMPFILE pCur = g_Sandbox.pTempFileHead;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
while (pCur)
{
if ( pCur->cMappings > 0
@@ -5334,6 +5604,7 @@ static BOOL WINAPI kwSandbox_Kernel32_CloseHandle(HANDLE hObject)
{
BOOL fRet;
KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hObject);
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
if ( idxHandle < g_Sandbox.cHandles
&& g_Sandbox.papHandles[idxHandle] != NULL)
{
@@ -5373,7 +5644,10 @@ static DWORD WINAPI kwSandbox_Kernel32_GetFileAttributesA(LPCSTR pszFilename)
if (kwFsIsCachableExtensionA(pszExt, K_TRUE /*fAttrQuery*/))
{
KFSLOOKUPERROR enmError;
- PKFSOBJ pFsObj = kFsCacheLookupNoMissingA(g_pFsCache, pszFilename, &enmError);
+ PKFSOBJ pFsObj;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ pFsObj = kFsCacheLookupNoMissingA(g_pFsCache, pszFilename, &enmError);
if (pFsObj)
{
kHlpAssert(pFsObj->fHaveStats);
@@ -5403,7 +5677,10 @@ static DWORD WINAPI kwSandbox_Kernel32_GetFileAttributesW(LPCWSTR pwszFilename)
if (kwFsIsCachablePathExtensionW(pwszFilename, K_TRUE /*fAttrQuery*/))
{
KFSLOOKUPERROR enmError;
- PKFSOBJ pFsObj = kFsCacheLookupNoMissingW(g_pFsCache, pwszFilename, &enmError);
+ PKFSOBJ pFsObj;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ pFsObj = kFsCacheLookupNoMissingW(g_pFsCache, pwszFilename, &enmError);
if (pFsObj)
{
kHlpAssert(pFsObj->fHaveStats);
@@ -5435,7 +5712,10 @@ static DWORD WINAPI kwSandbox_Kernel32_GetShortPathNameW(LPCWSTR pwszLongPath, L
if (kwFsIsCachablePathExtensionW(pwszLongPath, K_TRUE /*fAttrQuery*/))
{
KFSLOOKUPERROR enmError;
- PKFSOBJ pObj = kFsCacheLookupW(g_pFsCache, pwszLongPath, &enmError);
+ PKFSOBJ pObj;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ pObj = kFsCacheLookupW(g_pFsCache, pwszLongPath, &enmError);
if (pObj)
{
if (pObj->bObjType != KFSOBJ_TYPE_MISSING)
@@ -5487,6 +5767,7 @@ static BOOL WINAPI kwSandbox_Kernel32_DeleteFileW(LPCWSTR pwszFilename)
if ( g_Sandbox.pTool->u.Sandboxed.enmHint == KWTOOLHINT_VISUAL_CPP_CL
&& kwFsIsClTempFileW(pwszFilename))
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
KWFS_LOG(("DeleteFileW(%s) -> TRUE [temp]\n", pwszFilename));
fRc = TRUE;
}
@@ -5501,6 +5782,463 @@ static BOOL WINAPI kwSandbox_Kernel32_DeleteFileW(LPCWSTR pwszFilename)
+#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
+
+/*
+ *
+ * Console output buffering.
+ * Console output buffering.
+ * Console output buffering.
+ *
+ */
+
+
+/**
+ * Write a wide char string to the console.
+ *
+ * @param pSandbox The sandbox which output buffer to flush.
+ */
+static void kwSandboxConsoleWriteIt(PKWSANDBOX pSandbox, wchar_t const *pwcBuf, KU32 cwcToWrite)
+{
+ if (cwcToWrite > 0)
+ {
+ DWORD cwcWritten = 0;
+ if (WriteConsoleW(pSandbox->Combined.hOutput, pwcBuf, cwcToWrite, &cwcWritten, NULL))
+ {
+ if (cwcWritten == cwcToWrite)
+ { /* likely */ }
+ else
+ {
+ DWORD off = 0;
+ do
+ {
+ off += cwcWritten;
+ cwcWritten = 0;
+ }
+ while ( off < cwcToWrite
+ && WriteConsoleW(pSandbox->Combined.hOutput, &pwcBuf[off], cwcToWrite - off, &cwcWritten, NULL));
+ kHlpAssert(off == cwcWritten);
+ }
+ }
+ else
+ kHlpAssertFailed();
+ pSandbox->Combined.cFlushes++;
+ }
+}
+
+
+/**
+ * Flushes the combined console output buffer.
+ *
+ * @param pSandbox The sandbox which output buffer to flush.
+ */
+static void kwSandboxConsoleFlushCombined(PKWSANDBOX pSandbox)
+{
+ if (pSandbox->Combined.cwcBuf > 0)
+ {
+ kwSandboxConsoleWriteIt(pSandbox, pSandbox->Combined.wszBuf, pSandbox->Combined.cwcBuf);
+ pSandbox->Combined.cwcBuf = 0;
+ }
+}
+
+
+/**
+ * For handling combined buffer overflow cases line by line.
+ *
+ * @param pSandbox The sandbox.
+ * @param pwcBuf What to add to the combined buffer. Usually a
+ * line, unless we're really low on buffer space.
+ * @param cwcBuf The length of what to add.
+ * @param fBrokenLine Whether this is a broken line.
+ */
+static void kwSandboxConsoleAddToCombined(PKWSANDBOX pSandbox, wchar_t const *pwcBuf, KU32 cwcBuf, KBOOL fBrokenLine)
+{
+ if (fBrokenLine)
+ kwSandboxConsoleFlushCombined(pSandbox);
+ if (pSandbox->Combined.cwcBuf + cwcBuf > K_ELEMENTS(pSandbox->Combined.wszBuf))
+ {
+ kwSandboxConsoleFlushCombined(pSandbox);
+ kwSandboxConsoleWriteIt(pSandbox, pwcBuf, cwcBuf);
+ }
+ else
+ {
+ memcpy(&pSandbox->Combined.wszBuf[pSandbox->Combined.cwcBuf], pwcBuf, cwcBuf * sizeof(wchar_t));
+ pSandbox->Combined.cwcBuf += cwcBuf;
+ }
+}
+
+
+/**
+ * Called to final flush a line buffer via the combined buffer (if applicable).
+ *
+ * @param pSandbox The sandbox.
+ * @param pLineBuf The line buffer.
+ */
+static void kwSandboxConsoleFinalFlushLineBuf(PKWSANDBOX pSandbox, PKWCONSOLEOUTPUTLINE pLineBuf)
+{
+ if (pLineBuf->cwcBuf > 0)
+ {
+ if (pLineBuf->fIsConsole)
+ {
+ if (pLineBuf->cwcBuf < pLineBuf->cwcBufAlloc)
+ {
+ pLineBuf->pwcBuf[pLineBuf->cwcBuf++] = '\n';
+ kwSandboxConsoleAddToCombined(pSandbox, pLineBuf->pwcBuf, pLineBuf->cwcBuf, K_FALSE /*fBrokenLine*/);
+ }
+ else
+ {
+ kwSandboxConsoleAddToCombined(pSandbox, pLineBuf->pwcBuf, pLineBuf->cwcBuf, K_TRUE /*fBrokenLine*/);
+ kwSandboxConsoleAddToCombined(pSandbox, L"\n", 1, K_TRUE /*fBrokenLine*/);
+ }
+ pLineBuf->cwcBuf = 0;
+ }
+ else
+ {
+ kHlpAssertFailed();
+ }
+ }
+}
+
+
+/**
+ * Called at the end of sandboxed execution to flush both stream buffers.
+ *
+ * @param pSandbox The sandbox.
+ */
+static void kwSandboxConsoleFlushAll(PKWSANDBOX pSandbox)
+{
+ /*
+ * First do the cl.exe source file supression trick, if applicable.
+ */
+ if ( pSandbox->Combined.cwcBuf >= 3
+ && pSandbox->StdOut.cwcBuf == 0
+ && pSandbox->StdErr.cwcBuf == 0
+ && pSandbox->Combined.cFlushes == 0
+ && pSandbox->pTool->u.Sandboxed.enmHint == KWTOOLHINT_VISUAL_CPP_CL)
+ {
+ KI32 off = pSandbox->Combined.cwcBuf - 1;
+ if (pSandbox->Combined.wszBuf[off] == '\n')
+ {
+ KBOOL fOk = K_TRUE;
+ while (off-- > 0)
+ {
+ wchar_t const wc = pSandbox->Combined.wszBuf[off];
+ if (iswalnum(wc) || wc == '.' || wc == ' ' || wc == '_' || wc == '-')
+ { /* likely */ }
+ else
+ {
+ fOk = K_FALSE;
+ break;
+ }
+ }
+ if (fOk)
+ {
+ pSandbox->Combined.cwcBuf = 0;
+ return;
+ }
+ }
+ }
+
+ /*
+ * Flush the two line buffer, the the combined buffer.
+ */
+ kwSandboxConsoleFinalFlushLineBuf(pSandbox, &pSandbox->StdErr);
+ kwSandboxConsoleFinalFlushLineBuf(pSandbox, &pSandbox->StdOut);
+ kwSandboxConsoleFlushCombined(pSandbox);
+}
+
+
+/**
+ * Writes a string to the given output stream.
+ *
+ * @param pSandbox The sandbox.
+ * @param pLineBuf The line buffer for the output stream.
+ * @param pwcBuffer The buffer to write.
+ * @param cwcToWrite The number of wchar_t's in the buffer.
+ */
+static void kwSandboxConsoleWriteW(PKWSANDBOX pSandbox, PKWCONSOLEOUTPUTLINE pLineBuf, wchar_t const *pwcBuffer, KU32 cwcToWrite)
+{
+ if (cwcToWrite > 0)
+ {
+ /*
+ * First, find the start of the last incomplete line so we can figure
+ * out how much line buffering we need to do.
+ */
+ KU32 cchLastIncompleteLine;
+ KU32 offLastIncompleteLine = cwcToWrite;
+ while ( offLastIncompleteLine > 0
+ && pwcBuffer[offLastIncompleteLine - 1] != '\n')
+ offLastIncompleteLine--;
+ cchLastIncompleteLine = cwcToWrite - offLastIncompleteLine;
+
+ /* Was there anything to line buffer? */
+ if (offLastIncompleteLine < cwcToWrite)
+ {
+ /* Need to grow the line buffer? */
+ KU32 cwcNeeded = offLastIncompleteLine != 0 ? offLastIncompleteLine : cchLastIncompleteLine + pLineBuf->cwcBuf;
+ if (cwcNeeded > pLineBuf->cwcBufAlloc)
+ {
+ void *pvNew;
+ KU32 cwcNew = !pLineBuf->cwcBufAlloc ? 1024 : pLineBuf->cwcBufAlloc * 2;
+ while (cwcNew < cwcNeeded)
+ cwcNew *= 2;
+ pvNew = kHlpRealloc(pLineBuf->pwcBuf, cwcNew * sizeof(wchar_t));
+ if (pvNew)
+ {
+ pLineBuf->pwcBuf = (wchar_t *)pvNew;
+ pLineBuf->cwcBufAlloc = cwcNew;
+ }
+ else
+ {
+ pvNew = kHlpRealloc(pLineBuf->pwcBuf, cwcNeeded * sizeof(wchar_t));
+ if (pvNew)
+ {
+ pLineBuf->pwcBuf = (wchar_t *)pvNew;
+ pLineBuf->cwcBufAlloc = cwcNeeded;
+ }
+ else
+ {
+ /* This isn't perfect, but it will have to do for now. */
+ if (pLineBuf->cwcBuf > 0)
+ {
+ kwSandboxConsoleAddToCombined(pSandbox, pLineBuf->pwcBuf, pLineBuf->cwcBuf, K_TRUE /*fBrokenLine*/);
+ pLineBuf->cwcBuf = 0;
+ }
+ kwSandboxConsoleAddToCombined(pSandbox, pwcBuffer, cwcToWrite, K_TRUE /*fBrokenLine*/);
+ return;
+ }
+ }
+ }
+
+ /*
+ * Handle the case where we only add to the line buffer.
+ */
+ if (offLastIncompleteLine == 0)
+ {
+ memcpy(&pLineBuf->pwcBuf[pLineBuf->cwcBuf], pwcBuffer, cwcToWrite * sizeof(wchar_t));
+ pLineBuf->cwcBuf += cwcToWrite;
+ return;
+ }
+ }
+
+ /*
+ * If there is sufficient combined buffer to handle this request, this are rather simple.
+ */
+ if (pLineBuf->cwcBuf + cchLastIncompleteLine <= K_ELEMENTS(pSandbox->Combined.wszBuf))
+ {
+ if (pLineBuf->cwcBuf > 0)
+ {
+ memcpy(&pSandbox->Combined.wszBuf[pSandbox->Combined.cwcBuf],
+ pLineBuf->pwcBuf, pLineBuf->cwcBuf * sizeof(wchar_t));
+ pSandbox->Combined.cwcBuf += pLineBuf->cwcBuf;
+ pLineBuf->cwcBuf = 0;
+ }
+
+ memcpy(&pSandbox->Combined.wszBuf[pSandbox->Combined.cwcBuf],
+ pwcBuffer, offLastIncompleteLine * sizeof(wchar_t));
+ pSandbox->Combined.cwcBuf += offLastIncompleteLine;
+ }
+ else
+ {
+ /*
+ * Do line-by-line processing of the input, flusing the combined buffer
+ * when it becomes necessary. We may have to write lines
+ */
+ KU32 off = 0;
+ KU32 offNextLine = 0;
+
+ /* If there is buffered chars, we handle the first line outside the
+ main loop. We must try our best outputting it as a complete line. */
+ if (pLineBuf->cwcBuf > 0)
+ {
+ while (offNextLine < cwcToWrite && pwcBuffer[offNextLine] != '\n')
+ offNextLine++;
+ offNextLine++;
+ kHlpAssert(offNextLine <= offLastIncompleteLine);
+
+ if (pLineBuf->cwcBuf + offNextLine + pSandbox->Combined.cwcBuf <= K_ELEMENTS(pSandbox->Combined.wszBuf))
+ {
+ memcpy(&pSandbox->Combined.wszBuf[pSandbox->Combined.cwcBuf],
+ pLineBuf->pwcBuf, pLineBuf->cwcBuf * sizeof(wchar_t));
+ pSandbox->Combined.cwcBuf += pLineBuf->cwcBuf;
+ pLineBuf->cwcBuf = 0;
+
+ memcpy(&pSandbox->Combined.wszBuf[pSandbox->Combined.cwcBuf], pwcBuffer, offNextLine * sizeof(wchar_t));
+ pSandbox->Combined.cwcBuf += offNextLine;
+ }
+ else
+ {
+ KU32 cwcLeft = pLineBuf->cwcBufAlloc - pLineBuf->cwcBuf;
+ if (cwcLeft > 0)
+ {
+ KU32 cwcCopy = K_MIN(cwcLeft, offNextLine);
+ memcpy(&pLineBuf->pwcBuf[pLineBuf->cwcBuf], pwcBuffer, cwcCopy * sizeof(wchar_t));
+ pLineBuf->cwcBuf += cwcCopy;
+ off += cwcCopy;
+ }
+ if (pLineBuf->cwcBuf > 0)
+ {
+ kwSandboxConsoleAddToCombined(pSandbox, pLineBuf->pwcBuf, pLineBuf->cwcBuf, K_TRUE /*fBrokenLine*/);
+ pLineBuf->cwcBuf = 0;
+ }
+ if (off < offNextLine)
+ kwSandboxConsoleAddToCombined(pSandbox, &pwcBuffer[off], offNextLine - off, K_TRUE /*fBrokenLine*/);
+ }
+ off = offNextLine;
+ }
+
+ /* Deal with the remaining lines */
+ while (off < offLastIncompleteLine)
+ {
+ while (offNextLine < offLastIncompleteLine && pwcBuffer[offNextLine] != '\n')
+ offNextLine++;
+ offNextLine++;
+ kHlpAssert(offNextLine <= offLastIncompleteLine);
+ kwSandboxConsoleAddToCombined(pSandbox, &pwcBuffer[off], offNextLine - off, K_FALSE /*fBrokenLine*/);
+ off = offNextLine;
+ }
+ }
+
+ /*
+ * Buffer any remaining incomplete line chars.
+ */
+ if (offLastIncompleteLine < cwcToWrite)
+ {
+ memcpy(&pLineBuf->pwcBuf[0], &pwcBuffer[offLastIncompleteLine], cchLastIncompleteLine * sizeof(wchar_t));
+ pLineBuf->cwcBuf = cchLastIncompleteLine;
+ }
+ }
+}
+
+
+/**
+ * Worker for WriteConsoleA and WriteFile.
+ *
+ * @param pSandbox The sandbox.
+ * @param pLineBuf The line buffer.
+ * @param pchBuffer What to write.
+ * @param cchToWrite How much to write.
+ */
+static void kwSandboxConsoleWriteA(PKWSANDBOX pSandbox, PKWCONSOLEOUTPUTLINE pLineBuf, const char *pchBuffer, KU32 cchToWrite)
+{
+ /*
+ * Convert it to wide char and use the 'W' to do the work.
+ */
+ int cwcRet;
+ KU32 cwcBuf = cchToWrite * 2 + 1;
+ wchar_t *pwcBufFree = NULL;
+ wchar_t *pwcBuf;
+
+ if (cwcBuf <= 4096)
+ pwcBuf = alloca(cwcBuf * sizeof(wchar_t));
+ else
+ pwcBuf = pwcBufFree = kHlpAlloc(cwcBuf * sizeof(wchar_t));
+
+ cwcRet = MultiByteToWideChar(pSandbox->Combined.uCodepage, 0/*dwFlags*/, pchBuffer, cchToWrite, pwcBuf, cwcBuf);
+ if (cwcRet > 0)
+ kwSandboxConsoleWriteW(pSandbox, pLineBuf, pwcBuf, cwcRet);
+ else
+ {
+ DWORD cchWritten;
+ kHlpAssertFailed();
+
+ /* Flush the line buffer and combined buffer before calling WriteConsoleA. */
+ if (pLineBuf->cwcBuf > 0)
+ {
+ kwSandboxConsoleAddToCombined(pSandbox, pLineBuf->pwcBuf, pLineBuf->cwcBuf, K_TRUE /*fBroken*/);
+ pLineBuf->cwcBuf = 0;
+ }
+ kwSandboxConsoleFlushCombined(pSandbox);
+
+ if (WriteConsoleA(pLineBuf->hBackup, pchBuffer, cchToWrite, &cchWritten, NULL /*pvReserved*/))
+ {
+ if (cchWritten >= cchToWrite)
+ { /* likely */ }
+ else
+ {
+ KU32 off = 0;
+ do
+ {
+ off += cchWritten;
+ cchWritten = 0;
+ } while ( off < cchToWrite
+ && WriteConsoleA(pLineBuf->hBackup, &pchBuffer[off], cchToWrite - off, &cchWritten, NULL));
+ }
+ }
+ }
+
+ if (pwcBufFree)
+ kHlpFree(pwcBufFree);
+}
+
+
+/** Kernel32 - WriteConsoleA */
+BOOL WINAPI kwSandbox_Kernel32_WriteConsoleA(HANDLE hConOutput, CONST VOID *pvBuffer, DWORD cbToWrite, PDWORD pcbWritten,
+ PVOID pvReserved)
+{
+ BOOL fRc;
+ PKWCONSOLEOUTPUTLINE pLineBuf;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ if (hConOutput == g_Sandbox.StdErr.hOutput)
+ pLineBuf = &g_Sandbox.StdErr;
+ else
+ pLineBuf = &g_Sandbox.StdOut;
+ if (pLineBuf->fIsConsole)
+ {
+ kwSandboxConsoleWriteA(&g_Sandbox, pLineBuf, (char const *)pvBuffer, cbToWrite);
+
+ KWFS_LOG(("WriteConsoleA: %p, %p LB %#x (%*.*s), %p, %p -> TRUE [cached]\n",
+ hConOutput, pvBuffer, cbToWrite, cbToWrite, cbToWrite, pvBuffer, pcbWritten, pvReserved));
+ if (pcbWritten)
+ *pcbWritten = cbToWrite;
+ fRc = TRUE;
+ }
+ else
+ {
+ fRc = WriteConsoleA(hConOutput, pvBuffer, cbToWrite, pcbWritten, pvReserved);
+ KWFS_LOG(("WriteConsoleA: %p, %p LB %#x (%*.*s), %p, %p -> %d !fallback!\n",
+ hConOutput, pvBuffer, cbToWrite, cbToWrite, cbToWrite, pvBuffer, pcbWritten, pvReserved, fRc));
+ }
+ return fRc;
+}
+
+
+/** Kernel32 - WriteConsoleW */
+BOOL WINAPI kwSandbox_Kernel32_WriteConsoleW(HANDLE hConOutput, CONST VOID *pvBuffer, DWORD cwcToWrite, PDWORD pcwcWritten,
+ PVOID pvReserved)
+{
+ BOOL fRc;
+ PKWCONSOLEOUTPUTLINE pLineBuf;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ if (hConOutput == g_Sandbox.StdErr.hOutput)
+ pLineBuf = &g_Sandbox.StdErr;
+ else
+ pLineBuf = &g_Sandbox.StdOut;
+ if (pLineBuf->fIsConsole)
+ {
+ kwSandboxConsoleWriteW(&g_Sandbox, pLineBuf, (wchar_t const *)pvBuffer, cwcToWrite);
+
+ KWFS_LOG(("WriteConsoleW: %p, %p LB %#x (%*.*ls), %p, %p -> TRUE [cached]\n",
+ hConOutput, pvBuffer, cwcToWrite, cwcToWrite, cwcToWrite, pvBuffer, pcwcWritten, pvReserved));
+ if (pcwcWritten)
+ *pcwcWritten = cwcToWrite;
+ fRc = TRUE;
+ }
+ else
+ {
+ fRc = WriteConsoleW(hConOutput, pvBuffer, cwcToWrite, pcwcWritten, pvReserved);
+ KWFS_LOG(("WriteConsoleW: %p, %p LB %#x (%*.*ls), %p, %p -> %d !fallback!\n",
+ hConOutput, pvBuffer, cwcToWrite, cwcToWrite, cwcToWrite, pvBuffer, pcwcWritten, pvReserved, fRc));
+ }
+ return fRc;
+}
+
+#endif /* WITH_CONSOLE_OUTPUT_BUFFERING */
+
+
+
/*
*
* Virtual memory leak prevension.
@@ -5518,7 +6256,10 @@ static PVOID WINAPI kwSandbox_Kernel32_VirtualAlloc(PVOID pvAddr, SIZE_T cb, DWO
if ( g_Sandbox.pTool->u.Sandboxed.enmHint == KWTOOLHINT_VISUAL_CPP_CL
&& pvMem)
{
- PKWVIRTALLOC pTracker = g_Sandbox.pVirtualAllocHead;
+ PKWVIRTALLOC pTracker;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ pTracker = g_Sandbox.pVirtualAllocHead;
while ( pTracker
&& (KUPTR)pvMem - (KUPTR)pTracker->pvAlloc >= pTracker->cbAlloc)
pTracker = pTracker->pNext;
@@ -5547,6 +6288,7 @@ static BOOL WINAPI kwSandbox_Kernel32_VirtualFree(PVOID pvAddr, SIZE_T cb, DWORD
KW_LOG(("VirtualFree: pvAddr=%p cb=%p type=%#x -> %d\n", pvAddr, cb, dwFreeType, fRc));
if (g_Sandbox.pTool->u.Sandboxed.enmHint == KWTOOLHINT_VISUAL_CPP_CL)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
if (dwFreeType & MEM_RELEASE)
{
PKWVIRTALLOC pTracker = g_Sandbox.pVirtualAllocHead;
@@ -5576,6 +6318,66 @@ static BOOL WINAPI kwSandbox_Kernel32_VirtualFree(PVOID pvAddr, SIZE_T cb, DWORD
}
+/** Kernel32 - HeapCreate / NtDll - RTlCreateHeap */
+HANDLE WINAPI kwSandbox_Kernel32_HeapCreate(DWORD fOptions, SIZE_T cbInitial, SIZE_T cbMax)
+{
+ HANDLE hHeap;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ hHeap = HeapCreate(fOptions, cbInitial, cbMax);
+ if (hHeap != NULL)
+ {
+ DWORD dwErr = GetLastError();
+ PKWHEAP pTracker = (PKWHEAP)kHlpAlloc(sizeof(*pTracker));
+ if (pTracker)
+ {
+ pTracker->hHeap = hHeap;
+ pTracker->pNext = g_Sandbox.pHeapHead;
+ g_Sandbox.pHeapHead = pTracker;
+ }
+
+ SetLastError(dwErr);
+ }
+ return hHeap;
+
+}
+
+
+/** Kernel32 - HeapDestroy / NtDll - RTlDestroyHeap */
+BOOL WINAPI kwSandbox_Kernel32_HeapDestroy(HANDLE hHeap)
+{
+ BOOL fRc = HeapDestroy(hHeap);
+ KW_LOG(("HeapDestroy: hHeap=%p -> %d\n", hHeap, fRc));
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+ if (fRc)
+ {
+ PKWHEAP pTracker = g_Sandbox.pHeapHead;
+ if (pTracker)
+ {
+ if (pTracker->hHeap == hHeap)
+ g_Sandbox.pHeapHead = pTracker->pNext;
+ else
+ {
+ PKWHEAP pPrev;
+ do
+ {
+ pPrev = pTracker;
+ pTracker = pTracker->pNext;
+ } while (pTracker && pTracker->hHeap == hHeap);
+ if (pTracker)
+ pPrev->pNext = pTracker->pNext;
+ }
+ if (pTracker)
+ kHlpFree(pTracker);
+ else
+ KW_LOG(("HeapDestroy: pvAddr=%p not found!\n", hHeap));
+ }
+ }
+
+ return fRc;
+}
+
+
/*
*
@@ -5600,6 +6402,7 @@ DWORD WINAPI kwSandbox_Kernel32_FlsAlloc(PFLS_CALLBACK_FUNCTION pfnCallback)
PKWLOCALSTORAGE pTracker = (PKWLOCALSTORAGE)kHlpAlloc(sizeof(*pTracker));
if (pTracker)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
pTracker->idx = idxFls;
pTracker->pNext = g_Sandbox.pFlsAllocHead;
g_Sandbox.pFlsAllocHead = pTracker;
@@ -5616,7 +6419,10 @@ BOOL WINAPI kwSandbox_Kernel32_FlsFree(DWORD idxFls)
KW_LOG(("FlsFree(%#x) -> %d\n", idxFls, fRc));
if (fRc)
{
- PKWLOCALSTORAGE pTracker = g_Sandbox.pFlsAllocHead;
+ PKWLOCALSTORAGE pTracker;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+
+ pTracker = g_Sandbox.pFlsAllocHead;
if (pTracker)
{
if (pTracker->idx == idxFls)
@@ -5679,6 +6485,7 @@ static BOOL WINAPI kwSandbox_Advapi32_CryptCreateHash(HCRYPTPROV hProv, ALG_ID i
PKWHASHMD5 pHash = (PKWHASHMD5)kHlpAllocZ(sizeof(*pHash));
if (pHash)
{
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
pHash->uMagic = KWHASHMD5_MAGIC;
pHash->cbHashed = 0;
pHash->fGoneBad = K_FALSE;
@@ -5722,6 +6529,7 @@ static BOOL WINAPI kwSandbox_Advapi32_CryptHashData(HCRYPTHASH hHash, CONST BYTE
{
BOOL fRc;
PKWHASHMD5 pHash = g_Sandbox.pHashHead;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
while (pHash && (KUPTR)pHash != hHash)
pHash = pHash->pNext;
KWCRYPT_LOG(("CryptHashData(hHash=%p/%p, pbData=%p, cbData=%#x, dwFlags=%#x)\n",
@@ -5837,6 +6645,7 @@ static BOOL WINAPI kwSandbox_Advapi32_CryptGetHashParam(HCRYPTHASH hHash, DWORD
{
BOOL fRc;
PKWHASHMD5 pHash = g_Sandbox.pHashHead;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
while (pHash && (KUPTR)pHash != hHash)
pHash = pHash->pNext;
if (pHash)
@@ -5994,6 +6803,7 @@ static BOOL WINAPI kwSandbox_Advapi32_CryptDestroyHash(HCRYPTHASH hHash)
BOOL fRc;
PKWHASHMD5 pPrev = NULL;
PKWHASHMD5 pHash = g_Sandbox.pHashHead;
+ kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
while (pHash && (KUPTR)pHash != hHash)
{
pPrev = pHash;
@@ -6126,9 +6936,15 @@ KWREPLACEMENTFUNCTION const g_aSandboxReplacements[] =
{ TUPLE("DeleteFileW"), NULL, (KUPTR)kwSandbox_Kernel32_DeleteFileW },
#endif
+ { TUPLE("WriteConsoleA"), NULL, (KUPTR)kwSandbox_Kernel32_WriteConsoleA },
+ { TUPLE("WriteConsoleW"), NULL, (KUPTR)kwSandbox_Kernel32_WriteConsoleW },
+
{ TUPLE("VirtualAlloc"), NULL, (KUPTR)kwSandbox_Kernel32_VirtualAlloc },
{ TUPLE("VirtualFree"), NULL, (KUPTR)kwSandbox_Kernel32_VirtualFree },
+ { TUPLE("HeapCreate"), NULL, (KUPTR)kwSandbox_Kernel32_HeapCreate, K_TRUE /*fOnlyExe*/ },
+ { TUPLE("HeapDestroy"), NULL, (KUPTR)kwSandbox_Kernel32_HeapDestroy, K_TRUE /*fOnlyExe*/ },
+
{ TUPLE("FlsAlloc"), NULL, (KUPTR)kwSandbox_Kernel32_FlsAlloc },
{ TUPLE("FlsFree"), NULL, (KUPTR)kwSandbox_Kernel32_FlsFree },
@@ -6151,6 +6967,10 @@ KWREPLACEMENTFUNCTION const g_aSandboxReplacements[] =
{ TUPLE("_amsg_exit"), NULL, (KUPTR)kwSandbox_msvcrt__amsg_exit },
{ TUPLE("terminate"), NULL, (KUPTR)kwSandbox_msvcrt_terminate },
+ { TUPLE("onexit"), NULL, (KUPTR)kwSandbox_msvcrt__onexit, K_TRUE /*fOnlyExe*/ },
+ { TUPLE("_onexit"), NULL, (KUPTR)kwSandbox_msvcrt__onexit, K_TRUE /*fOnlyExe*/ },
+ { TUPLE("atexit"), NULL, (KUPTR)kwSandbox_msvcrt_atexit, K_TRUE /*fOnlyExe*/ },
+
{ TUPLE("_beginthread"), NULL, (KUPTR)kwSandbox_msvcrt__beginthread },
{ TUPLE("_beginthreadex"), NULL, (KUPTR)kwSandbox_msvcrt__beginthreadex },
@@ -6240,6 +7060,9 @@ KWREPLACEMENTFUNCTION const g_aSandboxNativeReplacements[] =
#endif
{ TUPLE("SetConsoleCtrlHandler"), NULL, (KUPTR)kwSandbox_Kernel32_SetConsoleCtrlHandler },
+ { TUPLE("WriteConsoleA"), NULL, (KUPTR)kwSandbox_Kernel32_WriteConsoleA },
+ { TUPLE("WriteConsoleW"), NULL, (KUPTR)kwSandbox_Kernel32_WriteConsoleW },
+
#ifdef WITH_HASH_MD5_CACHE
{ TUPLE("CryptCreateHash"), NULL, (KUPTR)kwSandbox_Advapi32_CryptCreateHash },
{ TUPLE("CryptHashData"), NULL, (KUPTR)kwSandbox_Advapi32_CryptHashData },
@@ -6552,6 +7375,12 @@ static int kwSandboxInit(PKWSANDBOX pSandbox, PKWTOOL pTool,
pSandbox->idMainThread = GetCurrentThreadId();
pSandbox->pgmptr = (char *)pTool->pszPath;
pSandbox->wpgmptr = (wchar_t *)pTool->pwszPath;
+#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
+ pSandbox->StdOut.cwcBuf = 0;
+ pSandbox->StdErr.cwcBuf = 0;
+ pSandbox->Combined.cwcBuf = 0;
+ pSandbox->Combined.cFlushes = 0;
+#endif
pSandbox->cArgs = cArgs;
pSandbox->papszArgs = (char **)papszArgs;
pSandbox->pszCmdLine = kwSandboxInitCmdLineFromArgv(cArgs, papszArgs, fWatcomBrainDamange, &cbCmdLine);
@@ -6652,13 +7481,40 @@ static void kwSandboxCleanupLate(PKWSANDBOX pSandbox)
{
PROCESS_MEMORY_COUNTERS MemInfo;
PKWVIRTALLOC pTracker;
+ PKWHEAP pHeap;
PKWLOCALSTORAGE pLocalStorage;
#ifdef WITH_HASH_MD5_CACHE
PKWHASHMD5 pHash;
#endif
#ifdef WITH_TEMP_MEMORY_FILES
PKWFSTEMPFILE pTempFile;
+#endif
+ PKWEXITCALLACK pExitCallback;
+
+ /* Do exit callback first. */
+ pExitCallback = g_Sandbox.pExitCallbackHead;
+ g_Sandbox.pExitCallbackHead = NULL;
+ while (pExitCallback)
+ {
+ PKWEXITCALLACK pNext = pExitCallback->pNext;
+ KW_LOG(("kwSandboxCleanupLate: calling %p %sexit handler\n",
+ pExitCallback->pfnCallback, pExitCallback->fAtExit ? "at" : "_on"));
+ __try
+ {
+ pExitCallback->pfnCallback();
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ KW_LOG(("kwSandboxCleanupLate: %sexit handler %p threw an exception!\n",
+ pExitCallback->fAtExit ? "at" : "_on", pExitCallback->pfnCallback));
+ kHlpAssertFailed();
+ }
+ kHlpFree(pExitCallback);
+ pExitCallback = pNext;
+ }
+
+#ifdef WITH_TEMP_MEMORY_FILES
/* The temporary files aren't externally visible, they're all in memory. */
pTempFile = pSandbox->pTempFileHead;
pSandbox->pTempFileHead = NULL;
@@ -6688,6 +7544,17 @@ static void kwSandboxCleanupLate(PKWSANDBOX pSandbox)
pTracker = pNext;
}
+ /* Free left behind HeapCreate leaks. */
+ pHeap = g_Sandbox.pHeapHead;
+ g_Sandbox.pHeapHead = NULL;
+ while (pHeap != NULL)
+ {
+ PKWHEAP pNext = pHeap->pNext;
+ KW_LOG(("Freeing HeapCreate leak %p\n", pHeap->hHeap));
+ HeapDestroy(pHeap->hHeap);
+ pHeap = pNext;
+ }
+
/* Free left behind FlsAlloc leaks. */
pLocalStorage = g_Sandbox.pFlsAllocHead;
g_Sandbox.pFlsAllocHead = NULL;
@@ -6884,7 +7751,13 @@ static int kwSandboxExec(PKWSANDBOX pSandbox, PKWTOOL pTool, KU32 cArgs, const c
else
rcExit = 42 + 4;
- /* Clean up essential bits only, the rest is done after we've replied to kmk. */
+ /*
+ * Flush and clean up the essential bits only, postpone whatever we
+ * can till after we've replied to kmk.
+ */
+#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
+ kwSandboxConsoleFlushAll(&g_Sandbox);
+#endif
kwSandboxCleanup(&g_Sandbox);
}
else
@@ -7375,6 +8248,11 @@ int main(int argc, char **argv)
#if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_X86)
PVOID pvVecXcptHandler = AddVectoredExceptionHandler(0 /*called last*/, kwSandboxVecXcptEmulateChained);
#endif
+#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
+ HANDLE hCurProc = GetCurrentProcess();
+ PPEB pPeb = kwSandboxGetProcessEnvironmentBlock();
+ PMY_RTL_USER_PROCESS_PARAMETERS pProcessParams = (PMY_RTL_USER_PROCESS_PARAMETERS)pPeb->ProcessParameters;
+#endif
/*
* Register our Control-C and Control-Break handlers.
@@ -7399,6 +8277,40 @@ int main(int argc, char **argv)
if (pszTmp && *pszTmp != '\0')
kFsCacheSetupCustomRevisionForTree(g_pFsCache, kFsCacheLookupA(g_pFsCache, pszTmp, &enmIgnored));
+#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
+ /*
+ * Get and duplicate the console handles.
+ */
+ g_Sandbox.StdOut.hOutput = pProcessParams->StandardOutput;
+ if (!DuplicateHandle(hCurProc, pProcessParams->StandardOutput, hCurProc, &g_Sandbox.StdOut.hBackup,
+ GENERIC_WRITE, FALSE /*fInherit*/, DUPLICATE_SAME_ACCESS))
+ kHlpAssertFailedStmt(g_Sandbox.StdOut.hBackup = pProcessParams->StandardOutput);
+ g_Sandbox.StdOut.fIsConsole = GetFileType(g_Sandbox.StdOut.hOutput) == FILE_TYPE_CHAR;
+
+ g_Sandbox.StdErr.hOutput = pProcessParams->StandardError;
+ if (!DuplicateHandle(hCurProc, pProcessParams->StandardError, hCurProc, &g_Sandbox.StdErr.hBackup,
+ GENERIC_WRITE, FALSE /*fInherit*/, DUPLICATE_SAME_ACCESS))
+ kHlpAssertFailedStmt(g_Sandbox.StdErr.hBackup = pProcessParams->StandardError);
+ g_Sandbox.StdErr.fIsConsole = GetFileType(g_Sandbox.StdErr.hOutput) == FILE_TYPE_CHAR;
+
+ if (g_Sandbox.StdErr.fIsConsole)
+ {
+ g_Sandbox.Combined.hOutput = g_Sandbox.StdErr.hBackup;
+ g_Sandbox.Combined.uCodepage = GetConsoleCP();
+ }
+ else if (g_Sandbox.StdOut.fIsConsole)
+ {
+ g_Sandbox.Combined.hOutput = g_Sandbox.StdOut.hBackup;
+ g_Sandbox.Combined.uCodepage = GetConsoleCP();
+ }
+ else
+ {
+ g_Sandbox.Combined.hOutput = INVALID_HANDLE_VALUE;
+ g_Sandbox.Combined.uCodepage = CP_ACP;
+ }
+#endif
+
+
/*
* Parse arguments.
*/
diff --git a/src/kmk/Makefile.kmk b/src/kmk/Makefile.kmk
index 80c5168..11fe58f 100644
--- a/src/kmk/Makefile.kmk
+++ b/src/kmk/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 2886 2016-09-06 14:31:46Z bird $
+# $Id: Makefile.kmk 2907 2016-09-09 22:33:26Z bird $
## @file
# Sub-makefile for kmk / GNU Make.
#
@@ -57,7 +57,7 @@ TEMPLATE_BIN-KMK_INCS = $(kmk_0_OUTDIR) . $(TEMPLATE_BIN-THREADED_INCS)
ifneq ($(KBUILD_TARGET),os2)
TEMPLATE_BIN-KMK_INCS += glob
endif
-TEMPLATE_BIN-KMK_LIBS = $(TEMPLATE_BIN-THREADED_LIBS) $(kmkmissing_1_TARGET) $(LIB_KUTIL)
+TEMPLATE_BIN-KMK_LIBS = $(LIB_KUTIL) $(TEMPLATE_BIN-THREADED_LIBS) $(kmkmissing_1_TARGET) $(LIB_KUTIL)
ifdef ELECTRIC_HEAP # for electric heap (see electric.c) - windows only.
ifeq ($(KBUILD_TARGET),win)
TEMPLATE_BIN-KMK_CFLAGS = $(TEMPLATE_BIN-THREADED_CFLAGS) /FI$(kmk_DEFPATH)/electric.h -DELECTRIC_HEAP=1
@@ -281,7 +281,7 @@ kmk_SOURCES += \
kmkbuiltin/printf.c \
kmkbuiltin/rm.c \
kmkbuiltin/rmdir.c \
- kmkbuiltin/kSubmit.c \
+ $(if-expr $(KBUILD_TARGET) == win,kmkbuiltin/kSubmit.c) \
kmkbuiltin/sleep.c \
kmkbuiltin/test.c
diff --git a/src/kmk/kmkbuiltin.h b/src/kmk/kmkbuiltin.h
index 04e964b..8c3a8a3 100644
--- a/src/kmk/kmkbuiltin.h
+++ b/src/kmk/kmkbuiltin.h
@@ -1,4 +1,4 @@
-/* $Id: kmkbuiltin.h 2846 2016-08-30 12:48:33Z bird $ */
+/* $Id: kmkbuiltin.h 2899 2016-09-09 09:03:57Z bird $ */
/** @file
* kMk Builtin command handling.
*/
@@ -36,6 +36,7 @@
#include "kbuild_version.h"
+struct child;
int kmk_builtin_command(const char *pszCmd, struct child *pChild, char ***ppapszArgvToSpawn, pid_t *pPidSpawned);
int kmk_builtin_command_parsed(int argc, char **argv, struct child *pChild, char ***ppapszArgvToSpawn, pid_t *pPidSpawned);
diff --git a/src/kmk/kmkbuiltin/cat.c b/src/kmk/kmkbuiltin/cat.c
index 2e4e7ed..d9fc0a2 100644
--- a/src/kmk/kmkbuiltin/cat.c
+++ b/src/kmk/kmkbuiltin/cat.c
@@ -80,6 +80,14 @@ __FBSDID("$FreeBSD: src/bin/cat/cat.c,v 1.32 2005/01/10 08:39:20 imp Exp $");
#include "kmkbuiltin.h"
+#ifdef KBUILD_OS_WINDOWS
+/* This is a trick to seriuosly speed up console output windows. */
+# undef write
+# define write maybe_con_write
+extern ssize_t maybe_con_write(int, void const *, size_t);
+#endif
+
+
int bflag, eflag, nflag, sflag, tflag, vflag;
/*int rval;*/
const char *filename;
@@ -119,6 +127,8 @@ kmk_builtin_cat(int argc, char *argv[], char **envp)
#ifdef kmk_builtin_cat /* kmk did this already. */
setlocale(LC_CTYPE, "");
+#else
+ fflush(stdout);
#endif
while ((ch = getopt_long(argc, argv, "benstuv", long_options, NULL)) != -1)
@@ -287,7 +297,7 @@ cook_cat(FILE *fp)
static int
raw_cat(int rfd)
{
- int off, wfd;
+ int off, wfd = fileno(stdout);
ssize_t nr, nw;
static size_t bsize;
static char *buf = NULL;
@@ -297,8 +307,8 @@ raw_cat(int rfd)
if (buf == NULL) {
if (fstat(wfd, &sbuf))
return err(1, "%s", filename);
-#ifdef _MSC_VER
- bsize = 1024;
+#ifdef KBUILD_OS_WINDOWS
+ bsize = 16384;
#else
bsize = MAX(sbuf.st_blksize, 1024);
#endif
diff --git a/src/kmk/kmkbuiltin/err.c b/src/kmk/kmkbuiltin/err.c
index 230b2fe..90d99e4 100644
--- a/src/kmk/kmkbuiltin/err.c
+++ b/src/kmk/kmkbuiltin/err.c
@@ -1,10 +1,10 @@
-/* $Id: err.c 2413 2010-09-11 17:43:04Z bird $ */
+/* $Id: err.c 2911 2016-09-10 11:16:59Z bird $ */
/** @file
* Override err.h so we get the program name right.
*/
/*
- * Copyright (c) 2005-2010 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ * Copyright (c) 2005-2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
*
* This file is part of kBuild.
*
@@ -33,6 +33,13 @@
#include <errno.h>
#include "err.h"
+#ifdef KBUILD_OS_WINDOWS
+/* This is a trick to speed up console output on windows. */
+# undef fwrite
+# define fwrite maybe_con_fwrite
+extern size_t maybe_con_fwrite(void const *, size_t, size_t, FILE *);
+#endif
+
/** The current program name. */
const char *g_progname = "kmk";
@@ -42,6 +49,34 @@ int err(int eval, const char *fmt, ...)
{
va_list args;
int error = errno;
+
+ /* stderr is unbuffered, so try format the whole message and print it in
+ one go so it won't be split by other output. */
+ char szMsg[4096];
+ int cchMsg = snprintf(szMsg, sizeof(szMsg), "%s: ", g_progname);
+ if (cchMsg < sizeof(szMsg) - 1 && cchMsg > 0)
+ {
+ int cchMsg2;
+ va_start(args, fmt);
+ cchMsg += cchMsg2 = vsnprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args);
+ va_end(args);
+
+ if ( cchMsg < sizeof(szMsg) - 1
+ && cchMsg2 >= 0)
+ {
+ cchMsg += cchMsg2 = snprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, ": %s\n", strerror(error));
+ if ( cchMsg < sizeof(szMsg) - 1
+ && cchMsg2 >= 0)
+ {
+ fwrite(szMsg, cchMsg, 1, stderr);
+ return eval;
+ }
+
+ }
+
+ }
+
+ /* fallback */
fprintf(stderr, "%s: ", g_progname);
va_start(args, fmt);
vfprintf(stderr, fmt, args);
@@ -55,6 +90,29 @@ int err(int eval, const char *fmt, ...)
int errx(int eval, const char *fmt, ...)
{
va_list args;
+
+ /* stderr is unbuffered, so try format the whole message and print it in
+ one go so it won't be split by other output. */
+ char szMsg[4096];
+ int cchMsg = snprintf(szMsg, sizeof(szMsg), "%s: ", g_progname);
+ if (cchMsg < sizeof(szMsg) - 1 && cchMsg > 0)
+ {
+ int cchMsg2;
+ va_start(args, fmt);
+ cchMsg += cchMsg2 = vsnprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args);
+ va_end(args);
+
+ if ( cchMsg < sizeof(szMsg) - 1
+ && cchMsg2 >= 0)
+ {
+ szMsg[cchMsg++] = '\n';
+ fwrite(szMsg, cchMsg, 1, stderr);
+ return eval;
+ }
+
+ }
+
+ /* fallback */
fprintf(stderr, "%s: ", g_progname);
va_start(args, fmt);
vfprintf(stderr, fmt, args);
@@ -68,6 +126,33 @@ void warn(const char *fmt, ...)
{
int error = errno;
va_list args;
+
+ /* stderr is unbuffered, so try format the whole message and print it in
+ one go so it won't be split by other output. */
+ char szMsg[4096];
+ int cchMsg = snprintf(szMsg, sizeof(szMsg), "%s: ", g_progname);
+ if (cchMsg < sizeof(szMsg) - 1 && cchMsg > 0)
+ {
+ int cchMsg2;
+ va_start(args, fmt);
+ cchMsg += cchMsg2 = vsnprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args);
+ va_end(args);
+
+ if ( cchMsg < sizeof(szMsg) - 1
+ && cchMsg2 >= 0)
+ {
+ cchMsg += cchMsg2 = snprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, ": %s\n", strerror(error));
+ if ( cchMsg < sizeof(szMsg) - 1
+ && cchMsg2 >= 0)
+ {
+ fwrite(szMsg, cchMsg, 1, stderr);
+ return;
+ }
+
+ }
+ }
+
+ /* fallback */
fprintf(stderr, "%s: ", g_progname);
va_start(args, fmt);
vfprintf(stderr, fmt, args);
@@ -78,6 +163,29 @@ void warn(const char *fmt, ...)
void warnx(const char *fmt, ...)
{
va_list args;
+
+ /* stderr is unbuffered, so try format the whole message and print it in
+ one go so it won't be split by other output. */
+ char szMsg[4096];
+ int cchMsg = snprintf(szMsg, sizeof(szMsg), "%s: ", g_progname);
+ if (cchMsg < sizeof(szMsg) - 1 && cchMsg > 0)
+ {
+ int cchMsg2;
+ va_start(args, fmt);
+ cchMsg += cchMsg2 = vsnprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args);
+ va_end(args);
+
+ if ( cchMsg < sizeof(szMsg) - 1
+ && cchMsg2 >= 0)
+ {
+ szMsg[cchMsg++] = '\n';
+ fwrite(szMsg, cchMsg, 1, stderr);
+ return;
+ }
+
+ }
+
+ /* fallback */
fprintf(stderr, "%s: ", g_progname);
va_start(args, fmt);
vfprintf(stderr, fmt, args);
diff --git a/src/kmk/kmkbuiltin/mscfakes.c b/src/kmk/kmkbuiltin/mscfakes.c
index b8e33c7..b820dd8 100644
--- a/src/kmk/kmkbuiltin/mscfakes.c
+++ b/src/kmk/kmkbuiltin/mscfakes.c
@@ -1,4 +1,4 @@
-/* $Id: mscfakes.c 2759 2015-01-28 16:14:00Z bird $ */
+/* $Id: mscfakes.c 2901 2016-09-09 15:10:24Z bird $ */
/** @file
* Fake Unix stuff for MSC.
*/
@@ -633,11 +633,11 @@ int vasprintf(char **strp, const char *fmt, va_list va)
#ifdef va_copy
va_copy(va2, va);
- rc = snprintf(psz, cb, fmt, va2);
+ rc = vsnprintf(psz, cb, fmt, va2);
va_end(vaCopy);
#else
va2 = va;
- rc = snprintf(psz, cb, fmt, va2);
+ rc = vsnprintf(psz, cb, fmt, va2);
#endif
if (rc < 0 || (size_t)rc < cb)
break;
diff --git a/src/kmk/kmkbuiltin/printf.c b/src/kmk/kmkbuiltin/printf.c
index 36150e2..a27824b 100644
--- a/src/kmk/kmkbuiltin/printf.c
+++ b/src/kmk/kmkbuiltin/printf.c
@@ -75,6 +75,13 @@ __RCSID("$NetBSD: printf.c,v 1.31 2005/03/22 23:55:46 dsl Exp $");
#include "../kmkbuiltin.h"
+#ifdef KBUILD_OS_WINDOWS
+/* This is a trick to speed up console output on windows. */
+# undef fwrite
+# define fwrite maybe_con_fwrite
+extern size_t maybe_con_fwrite(void const *, size_t, size_t, FILE *);
+#endif
+
#ifdef __GNUC__
#define ESCAPE '\e'
@@ -112,6 +119,7 @@ static char *mklong(const char *, int);
static void check_conversion(const char *, const char *);
static int usage(FILE *);
+static int flush_buffer(void);
static void b_count(int);
static void b_output(int);
static int wrap_putchar(int ch);
@@ -126,6 +134,10 @@ static int wrap_printf(const char *, ...);
#include "../../bin/sh/bltin/bltin.h"
#endif /* SHELL */
+/* Buffer the output because windows doesn't do line buffering of stdout. */
+static char g_achBuf[256];
+static size_t g_cchBuf;
+
#define PF(f, func) { \
if (fieldwidth != -1) { \
if (precision != -1) \
@@ -155,7 +167,7 @@ int kmk_builtin_printf(int argc, char *argv[], char **envp)
int rc;
int ch;
- /* kmk: reset getopt and set progname */
+ /* kmk: reset getopt, set progname and reset buffer. */
g_progname = argv[0];
opterr = 1;
optarg = NULL;
@@ -224,6 +236,7 @@ static int common_printf(int argc, char *argv[])
b_fmt = NULL;
rval = 0;
gargv = NULL;
+ g_cchBuf = 0;
format = *argv;
gargv = ++argv;
@@ -271,6 +284,7 @@ static int common_printf(int argc, char *argv[])
ch = *fmt;
if (!ch) {
+ flush_buffer();
warnx("missing format character");
return (1);
}
@@ -353,20 +367,25 @@ static int common_printf(int argc, char *argv[])
break;
}
default:
+ flush_buffer();
warnx("%s: invalid directive", start);
return 1;
}
*fmt++ = ch;
*fmt = nextch;
/* escape if a \c was encountered */
- if (rval & 0x100)
+ if (rval & 0x100) {
+ flush_buffer();
return rval & ~0x100;
+ }
}
} while (gargv != argv && *gargv);
+ flush_buffer();
return rval;
}
+
/* helper functions for conv_escape_str */
static void
@@ -407,36 +426,105 @@ static int wrap_putchar(int ch)
return ch;
}
#endif
- return putchar(ch);
+ /* Buffered output. */
+ if (g_cchBuf + 1 < sizeof(g_achBuf)) {
+ g_achBuf[g_cchBuf++] = ch;
+ } else {
+ int rc = flush_buffer();
+ g_achBuf[g_cchBuf++] = ch;
+ if (rc)
+ return -1;
+ }
+ return 0;
}
static int wrap_printf(const char * fmt, ...)
{
- int rc;
+ ssize_t cchRet;
va_list va;
+ char *pszTmp;
+ va_start(va, fmt);
+ cchRet = vasprintf(&pszTmp, fmt, va);
+ va_end(va);
+ if (cchRet >= 0) {
#ifndef kmk_builtin_printf
- if (g_o) {
- char *str;
-
- va_start(va, fmt);
- rc = vasprintf(&str, fmt, va);
- va_end(va);
- if (rc >= 0) {
- g_o = variable_buffer_output(g_o, str, rc);
- free(str);
+ if (g_o) {
+ g_o = variable_buffer_output(g_o, pszTmp, cchRet);
+ } else
+#endif
+ {
+ if (cchRet + g_cchBuf <= sizeof(g_achBuf)) {
+ /* We've got space in the buffer. */
+ memcpy(&g_achBuf[g_cchBuf], pszTmp, cchRet);
+ g_cchBuf += cchRet;
+ } else {
+ /* Try write out complete lines. */
+ const char *pszLeft = pszTmp;
+ ssize_t cchLeft = cchRet;
+
+ while (cchLeft > 0) {
+ const char *pchNewLine = strchr(pszLeft, '\n');
+ ssize_t cchLine = pchNewLine ? pchNewLine - pszLeft + 1 : cchLeft;
+ if (g_cchBuf + cchLine <= sizeof(g_achBuf)) {
+ memcpy(&g_achBuf[g_cchBuf], pszLeft, cchLine);
+ g_cchBuf += cchLine;
+ } else {
+ if (flush_buffer() < 0) {
+ return -1;
+ }
+ if (fwrite(pszLeft, cchLine, 1, stdout) < 1) {
+ return -1;
+ }
+ }
+ pszLeft += cchLine;
+ cchLeft -= cchLine;
+ }
+ }
}
- return rc;
+ free(pszTmp);
}
-#endif
+ return (int)cchRet;
+}
- va_start(va, fmt);
- rc = vprintf(fmt, va);
- va_end(va);
- return rc;
+/**
+ * Flushes the g_abBuf/g_cchBuf.
+ */
+static int flush_buffer(void)
+{
+ if (g_cchBuf > 0) {
+ ssize_t cchToWrite = g_cchBuf;
+ ssize_t cchWritten = fwrite(g_achBuf, 1, g_cchBuf, stdout);
+ g_cchBuf = 0;
+ if (cchWritten >= cchToWrite) {
+ /* likely */
+ } else {
+ ssize_t off = cchWritten;
+ if (cchWritten >= 0) {
+ off = cchWritten;
+ } else if (errno == EINTR) {
+ cchWritten = 0;
+ } else {
+ return -1;
+ }
+
+ while (off < cchToWrite) {
+ cchWritten = fwrite(&g_achBuf[off], 1, cchToWrite - off, stdout);
+ if (cchWritten > 0) {
+ off += cchWritten;
+ } else if (errno == EINTR) {
+ /* nothing */
+ } else {
+ return -1;
+ }
+ }
+ }
+ }
+ return 0;
}
+
/*
* Print SysV echo(1) style escape string
* Halts processing string if a \c escape is encountered.
diff --git a/src/kmk/kmkbuiltin/solfakes.c b/src/kmk/kmkbuiltin/solfakes.c
index 2f4b818..6996ab4 100644
--- a/src/kmk/kmkbuiltin/solfakes.c
+++ b/src/kmk/kmkbuiltin/solfakes.c
@@ -1,4 +1,4 @@
-/* $Id: solfakes.c 2413 2010-09-11 17:43:04Z bird $ */
+/* $Id: solfakes.c 2901 2016-09-09 15:10:24Z bird $ */
/** @file
* Fake Unix stuff for Solaris.
*/
@@ -63,11 +63,11 @@ int vasprintf(char **strp, const char *fmt, va_list va)
#ifdef va_copy
va_copy(va2, va);
- rc = snprintf(psz, cb, fmt, va2);
+ rc = vsnprintf(psz, cb, fmt, va2);
va_end(va2);
#else
va2 = va;
- rc = snprintf(psz, cb, fmt, va2);
+ rc = vsnprintf(psz, cb, fmt, va2);
#endif
if (rc < 0 || (size_t)rc < cb)
break;
diff --git a/src/kmk/main.c b/src/kmk/main.c
index 2b45d9d..b648f42 100644
--- a/src/kmk/main.c
+++ b/src/kmk/main.c
@@ -1375,9 +1375,9 @@ main (int argc, char **argv, char **envp)
char *unix_path = NULL;
char *windows32_path = NULL;
-#ifndef ELECTRIC_HEAP /* Drop this because it prevents JIT debugging. */
+# ifndef ELECTRIC_HEAP /* Drop this because it prevents JIT debugging. */
SetUnhandledExceptionFilter(handle_runtime_exceptions);
-#endif /* !ELECTRIC_HEAP */
+# endif /* !ELECTRIC_HEAP */
/* start off assuming we have no shell */
unixy_shell = 0;
diff --git a/src/kmk/misc.c b/src/kmk/misc.c
index a70a222..a22759b 100644
--- a/src/kmk/misc.c
+++ b/src/kmk/misc.c
@@ -291,6 +291,30 @@ message (prefix, fmt, va_alist)
if (fmt != 0)
{
+#ifdef KBUILD_OS_WINDOWS
+ char szMsg[16384];
+ int cchMsg = 0;
+ int cchUser;
+ if (prefix)
+ {
+ if (makelevel == 0)
+ cchMsg = snprintf (szMsg, sizeof(szMsg), "%s: ", program);
+ else
+ cchMsg = snprintf (szMsg, sizeof(szMsg), "%s[%u]: ", program, makelevel);
+ }
+ VA_START (args, fmt);
+ cchMsg += cchUser = vsnprintf (&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args);
+ VA_END (args);
+ if ( cchMsg < sizeof(szMsg)
+ && cchUser >= 0)
+ {
+ extern size_t maybe_con_fwrite(void const *, size_t, size_t, FILE *);
+ szMsg[cchMsg++] = '\n';
+ maybe_con_fwrite(szMsg, cchMsg, 1, stdout);
+ }
+ else
+ {
+#endif
if (prefix)
{
if (makelevel == 0)
@@ -302,6 +326,9 @@ message (prefix, fmt, va_alist)
VA_PRINTF (stdout, fmt, args);
VA_END (args);
putchar ('\n');
+#ifdef KBUILD_OS_WINDOWS
+ }
+#endif
}
fflush (stdout);
@@ -322,9 +349,36 @@ error (flocp, fmt, va_alist)
#if USE_VARIADIC
va_list args;
#endif
+#ifdef KMK
+ char szMsg[16384];
+ int cchMsg = 0;
+ int cchUser;
+#endif
log_working_directory (1);
+#ifdef KMK /* Try avoid getting the error split by child output. */
+ if (flocp && flocp->filenm)
+ cchMsg = snprintf (szMsg, sizeof(szMsg), "%s:%lu: ", flocp->filenm, flocp->lineno);
+ else if (makelevel == 0)
+ cchMsg = snprintf (szMsg, sizeof(szMsg), "%s: ", program);
+ else
+ cchMsg = snprintf (szMsg, sizeof(szMsg), "%s[%u]: ", program, makelevel);
+
+ VA_START (args, fmt);
+ cchMsg += cchUser = vsnprintf (&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args);
+ VA_END (args);
+ if ( cchMsg < sizeof(szMsg)
+ && cchUser >= 0)
+ {
+ extern size_t maybe_con_fwrite(void const *, size_t, size_t, FILE *);
+ szMsg[cchMsg++] = '\n';
+ maybe_con_fwrite(szMsg, cchMsg, 1, stderr);
+ }
+ else
+ {
+#endif /* KMK */
+
if (flocp && flocp->filenm)
fprintf (stderr, "%s:%lu: ", flocp->filenm, flocp->lineno);
else if (makelevel == 0)
@@ -337,6 +391,9 @@ error (flocp, fmt, va_alist)
VA_END (args);
putc ('\n', stderr);
+#ifdef KMK
+ }
+#endif
fflush (stderr);
}
@@ -355,9 +412,38 @@ fatal (flocp, fmt, va_alist)
#if USE_VARIADIC
va_list args;
#endif
+#ifdef KMK
+ char szMsg[16384];
+ int cchMsg = 0;
+ int cchUser;
+ const char *pszStop = _(". Stop.\n");
+ int cchStop = (int)strlen(pszStop);
+#endif
log_working_directory (1);
+#ifdef KMK /* Try avoid getting the error split by child output. */
+ if (flocp && flocp->filenm)
+ cchMsg = snprintf (szMsg, sizeof(szMsg), "%s:%lu: *** ", flocp->filenm, flocp->lineno);
+ else if (makelevel == 0)
+ cchMsg = snprintf (szMsg, sizeof(szMsg), "%s: *** ", program);
+ else
+ cchMsg = snprintf (szMsg, sizeof(szMsg), "%s[%u]: *** ", program, makelevel);
+
+ VA_START (args, fmt);
+ cchMsg += cchUser = vsnprintf (&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args);
+ VA_END (args);
+ if ( cchMsg + cchStop <= sizeof(szMsg)
+ && cchUser >= 0)
+ {
+ extern size_t maybe_con_fwrite(void const *, size_t, size_t, FILE *);
+ memcpy(&szMsg[cchMsg], pszStop, cchStop);
+ cchMsg += cchStop;
+ maybe_con_fwrite(szMsg, cchMsg, 1, stderr);
+ }
+ else
+ {
+#endif /* KMK */
if (flocp && flocp->filenm)
fprintf (stderr, "%s:%lu: *** ", flocp->filenm, flocp->lineno);
else if (makelevel == 0)
@@ -370,6 +456,9 @@ fatal (flocp, fmt, va_alist)
VA_END (args);
fputs (_(". Stop.\n"), stderr);
+#ifdef KMK
+ }
+#endif
die (2);
}
diff --git a/src/lib/Makefile.kmk b/src/lib/Makefile.kmk
index f4bac14..b5833c2 100644
--- a/src/lib/Makefile.kmk
+++ b/src/lib/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 2886 2016-09-06 14:31:46Z bird $
+# $Id: Makefile.kmk 2906 2016-09-09 22:15:57Z bird $
## @file
# Sub-makefile for various libraries and stuff.
#
@@ -38,8 +38,11 @@ kUtil_DEFS.win = __WIN__
kUtil_SOURCES = \
crc32.c \
md5.c \
+ maybe_con_write.c \
+ maybe_con_fwrite.c \
kbuild_version.c
kUtil_SOURCES.win = \
+ msc_buffered_printf.c \
nt_fullpath.c \
nt_fullpath_cached.c \
quote_argv.c \
diff --git a/src/lib/maybe_con_fwrite.c b/src/lib/maybe_con_fwrite.c
new file mode 100644
index 0000000..6448434
--- /dev/null
+++ b/src/lib/maybe_con_fwrite.c
@@ -0,0 +1,114 @@
+/* $Id: maybe_con_fwrite.c 2906 2016-09-09 22:15:57Z bird $ */
+/** @file
+ * maybe_con_write - Optimized console output on windows.
+ */
+
+/*
+ * Copyright (c) 2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#ifdef KBUILD_OS_WINDOWS
+# include <windows.h>
+#endif
+#include <errno.h>
+#include <stdio.h>
+#ifdef _MSC_VER
+# include <io.h>
+# include <conio.h>
+#endif
+
+
+
+/**
+ * Drop-in fwrite replacement for optimizing console output on windows.
+ *
+ *
+ * @returns Units written; 0 & errno on failure.
+ * @param pvBuf What to write.
+ * @param cbUnit How much to write in each unit.
+ * @param cUnits How many units to write.
+ * @param pFile The file to write to.
+ */
+size_t maybe_con_fwrite(void const *pvBuf, size_t cbUnit, size_t cUnits, FILE *pFile)
+{
+#ifdef KBUILD_OS_WINDOWS
+ /*
+ * If it's a TTY, do our own conversion to wide char and
+ * call WriteConsoleW directly.
+ */
+ if ( cbUnit > 0
+ && cUnits > 0
+ && (pFile == stdout || pFile == stderr))
+ {
+ int fd = fileno(pFile);
+ if (fd >= 0)
+ {
+ if (isatty(fd))
+ {
+ HANDLE hCon = (HANDLE)_get_osfhandle(fd);
+ if ( hCon != INVALID_HANDLE_VALUE
+ && hCon != NULL)
+ {
+ size_t cbToWrite = cbUnit * cUnits;
+ size_t cwcTmp = cbToWrite * 2 + 16;
+ wchar_t *pawcTmp = (wchar_t *)malloc(cwcTmp * sizeof(wchar_t));
+ if (pawcTmp)
+ {
+ int cwcToWrite;
+ static UINT s_uConsoleCp = 0;
+ if (s_uConsoleCp == 0)
+ s_uConsoleCp = GetConsoleCP();
+
+ cwcToWrite = MultiByteToWideChar(s_uConsoleCp, 0 /*dwFlags*/, pvBuf, (int)cbToWrite, pawcTmp, (int)(cwcTmp - 1));
+ if (cwcToWrite > 0)
+ {
+ int rc;
+ pawcTmp[cwcToWrite] = '\0';
+
+ /* Let the CRT do the rest. At least the Visual C++ 2010 CRT
+ sources indicates _cputws will do the right thing we want. */
+ fflush(pFile);
+ rc = _cputws(pawcTmp);
+ free(pawcTmp);
+ if (rc >= 0)
+ return cUnits;
+ return 0;
+ }
+ free(pawcTmp);
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ /*
+ * Semi regular write handling.
+ */
+ return fwrite(pvBuf, cbUnit, cUnits, pFile);
+}
diff --git a/src/lib/maybe_con_write.c b/src/lib/maybe_con_write.c
new file mode 100644
index 0000000..0b28a42
--- /dev/null
+++ b/src/lib/maybe_con_write.c
@@ -0,0 +1,116 @@
+/* $Id: maybe_con_write.c 2900 2016-09-09 14:42:06Z bird $ */
+/** @file
+ * maybe_con_write - Optimized console output on windows.
+ */
+
+/*
+ * Copyright (c) 2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#ifdef KBUILD_OS_WINDOWS
+# include <windows.h>
+#endif
+#include <errno.h>
+#ifdef _MSC_VER
+# include <io.h>
+# include <conio.h>
+typedef intptr_t ssize_t;
+typedef unsigned int to_write_t;
+#else
+# include <unistd.h>
+typedef size_t to_write_t;
+#endif
+
+
+/**
+ * Drop-in write replacement for optimizing console output on windows.
+ *
+ * @returns Number of bytes written, -1 + errno on failure.
+ * @param fd The file descript to write to.
+ * @param pvBuf What to write.
+ * @param cbToWrite How much to write.
+ */
+ssize_t maybe_con_write(int fd, void *pvBuf, size_t cbToWrite)
+{
+ ssize_t cbWritten;
+#ifdef KBUILD_OS_WINDOWS
+ /*
+ * If it's a TTY, do our own conversion to wide char and
+ * call WriteConsoleW directly.
+ */
+ if (cbToWrite > 0 && isatty(fd))
+ {
+ HANDLE hCon = (HANDLE)_get_osfhandle(fd);
+ if ( hCon != INVALID_HANDLE_VALUE
+ && hCon != NULL)
+ {
+ size_t cwcTmp = cbToWrite * 2 + 16;
+ wchar_t *pawcTmp = (wchar_t *)malloc(cwcTmp * sizeof(wchar_t));
+ if (pawcTmp)
+ {
+ int cwcToWrite;
+ static UINT s_uConsoleCp = 0;
+ if (s_uConsoleCp == 0)
+ s_uConsoleCp = GetConsoleCP();
+
+ cwcToWrite = MultiByteToWideChar(s_uConsoleCp, 0 /*dwFlags*/, pvBuf, (int)cbToWrite, pawcTmp, (int)(cwcTmp - 1));
+ if (cwcToWrite > 0)
+ {
+ /* Let the CRT do the rest. At least the Visual C++ 2010 CRT
+ sources indicates _cputws will do the right thing we want. */
+ pawcTmp[cwcToWrite] = '\0';
+ if (_cputws(pawcTmp) >= 0)
+ return cbToWrite;
+ return -1;
+ }
+ }
+ }
+ }
+#endif
+
+ /*
+ * Semi regular write handling.
+ */
+ cbWritten = write(fd, pvBuf, (to_write_t)cbToWrite);
+ if (cbWritten == cbToWrite)
+ { /* likely */ }
+ else if (cbWritten >= 0 || errno == EINTR)
+ {
+ if (cbWritten < 0)
+ cbWritten = 0;
+ while (cbWritten < (ssize_t)cbToWrite)
+ {
+ ssize_t cbThis = write(fd, (char *)pvBuf + cbWritten, (to_write_t)(cbToWrite - cbWritten));
+ if (cbThis >= 0)
+ cbWritten += cbThis;
+ else if (errno != EINTR)
+ return -1;
+ }
+ }
+ return cbWritten;
+}
diff --git a/src/lib/msc_buffered_printf.c b/src/lib/msc_buffered_printf.c
new file mode 100644
index 0000000..2638b4f
--- /dev/null
+++ b/src/lib/msc_buffered_printf.c
@@ -0,0 +1,254 @@
+/* $Id: msc_buffered_printf.c 2910 2016-09-10 00:57:29Z bird $ */
+/** @file
+ * printf, vprintf, fprintf, puts, fputs console optimizations for Windows/MSC.
+ */
+
+/*
+ * Copyright (c) 2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <Windows.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <io.h>
+#include <conio.h>
+#include <malloc.h>
+
+#undef printf
+#undef vprintf
+#undef fprintf
+#undef puts
+#undef fputs
+#pragma warning(disable: 4273) /* inconsistent dll linkage*/
+
+extern size_t maybe_con_fwrite(void const *pvBuf, size_t cbUnit, size_t cUnits, FILE *pFile);
+
+
+/**
+ * Replaces printf for MSC to speed up console output.
+ *
+ * @returns chars written on success, -1 and errno on failure.
+ * @param pszFormat The format string.
+ * @param ... Format arguments.
+ */
+__declspec(dllexport)
+int __cdecl printf(const char *pszFormat, ...)
+{
+ int cchRet;
+ va_list va;
+ va_start(va, pszFormat);
+ cchRet = vprintf(pszFormat, va);
+ va_end(va);
+ return cchRet;
+}
+
+
+/**
+ * Replaces vprintf for MSC to speed up console output.
+ *
+ * @returns chars written on success, -1 and errno on failure.
+ * @param pszFormat The format string.
+ * @param va Format arguments.
+ */
+__declspec(dllexport)
+int __cdecl vprintf(const char *pszFormat, va_list va)
+{
+ /*
+ * If it's a TTY, try format into a stack buffer and output using our
+ * console optimized fwrite wrapper.
+ */
+ if (*pszFormat != '\0')
+ {
+ int fd = fileno(stdout);
+ if (fd >= 0)
+ {
+ if (isatty(fd))
+ {
+ char *pszTmp = (char *)alloca(16384);
+ va_list va2 = va;
+ int cchRet = vsnprintf(pszTmp, 16384, pszFormat, va2);
+ if (cchRet < 16384 - 1)
+ return (int)maybe_con_fwrite(pszTmp, cchRet, 1, stdout);
+ }
+ }
+ }
+
+ /*
+ * Fallback.
+ */
+ return vfprintf(stdout, pszFormat, va);
+}
+
+
+/**
+ * Replaces fprintf for MSC to speed up console output.
+ *
+ * @returns chars written on success, -1 and errno on failure.
+ * @param pFile The output file/stream.
+ * @param pszFormat The format string.
+ * @param va Format arguments.
+ */
+__declspec(dllexport)
+int __cdecl fprintf(FILE *pFile, const char *pszFormat, ...)
+{
+ va_list va;
+ int cchRet;
+
+ /*
+ * If it's a TTY, try format into a stack buffer and output using our
+ * console optimized fwrite wrapper.
+ */
+ if (*pszFormat != '\0')
+ {
+ int fd = fileno(pFile);
+ if (fd >= 0)
+ {
+ if (isatty(fd))
+ {
+ char *pszTmp = (char *)alloca(16384);
+ if (pszTmp)
+ {
+ va_start(va, pszFormat);
+ cchRet = vsnprintf(pszTmp, 16384, pszFormat, va);
+ va_end(va);
+ if (cchRet < 16384 - 1)
+ return (int)maybe_con_fwrite(pszTmp, cchRet, 1, pFile);
+ }
+ }
+ }
+ }
+
+ /*
+ * Fallback.
+ */
+ va_start(va, pszFormat);
+ cchRet = vfprintf(pFile, pszFormat, va);
+ va_end(va);
+ return cchRet;
+}
+
+
+/**
+ * Replaces puts for MSC to speed up console output.
+ *
+ * @returns Units written; 0 & errno on failure.
+ * @param pszString The string to write. (newline is appended)
+ */
+__declspec(dllexport)
+int __cdecl puts(const char *pszString)
+{
+ size_t cchString = strlen(pszString);
+ size_t cch;
+
+ /*
+ * If it's a TTY, we convert it to a wide char string with a newline
+ * appended right here. Going thru maybe_con_fwrite is just extra
+ * buffering due to the added newline.
+ */
+ if (*pszString != '\0')
+ {
+ int fd = fileno(stdout);
+ if (fd >= 0)
+ {
+ if (isatty(fd))
+ {
+ HANDLE hCon = (HANDLE)_get_osfhandle(fd);
+ if ( hCon != INVALID_HANDLE_VALUE
+ && hCon != NULL)
+ {
+ /* We need to append a newline, so we can just as well do the conversion here. */
+ size_t cwcTmp = cchString * 2 + 16 + 2;
+ wchar_t *pawcTmp = (wchar_t *)malloc(cwcTmp * sizeof(wchar_t));
+ if (pawcTmp)
+ {
+ int cwcToWrite;
+ static UINT s_uConsoleCp = 0;
+ if (s_uConsoleCp == 0)
+ s_uConsoleCp = GetConsoleCP();
+
+ cwcToWrite = MultiByteToWideChar(s_uConsoleCp, 0 /*dwFlags*/, pszString, (int)cchString, pawcTmp,
+ (int)(cwcTmp - 2));
+ if (cwcToWrite > 0)
+ {
+ int rc;
+
+ pawcTmp[cwcToWrite++] = '\n';
+ pawcTmp[cwcToWrite] = '\0';
+
+ /* Let the CRT do the rest. At least the Visual C++ 2010 CRT
+ sources indicates _cputws will do the right thing we want. */
+ fflush(stdout);
+ rc = _cputws(pawcTmp);
+ free(pawcTmp);
+ return rc;
+ }
+ free(pawcTmp);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Fallback.
+ */
+ cch = fwrite(pszString, cchString, 1, stdout);
+ if (cch == cchString)
+ {
+ if (putc('\n', stdout) != EOF)
+ return 0;
+ }
+ return -1;
+}
+
+
+/**
+ * Replaces puts for MSC to speed up console output.
+ *
+ * @returns Units written; 0 & errno on failure.
+ * @param pszString The string to write (no newline added).
+ * @param pFile The output file.
+ */
+__declspec(dllexport)
+int __cdecl fputs(const char *pszString, FILE *pFile)
+{
+ size_t cchString = strlen(pszString);
+ size_t cch = maybe_con_fwrite(pszString, cchString, 1, pFile);
+ if (cch == cchString)
+ return 0;
+ return -1;
+}
+
+
+
+void * const __imp_printf = (void *)(uintptr_t)printf;
+void * const __imp_vprintf = (void *)(uintptr_t)vprintf;
+void * const __imp_fprintf = (void *)(uintptr_t)fprintf;
+void * const __imp_puts = (void *)(uintptr_t)puts;
+void * const __imp_fputs = (void *)(uintptr_t)fputs;
+
diff --git a/src/lib/nt/ntstuff.h b/src/lib/nt/ntstuff.h
index a784ebc..f9ed594 100644
--- a/src/lib/nt/ntstuff.h
+++ b/src/lib/nt/ntstuff.h
@@ -1,4 +1,4 @@
-/* $Id: ntstuff.h 2862 2016-09-02 02:39:56Z bird $ */
+/* $Id: ntstuff.h 2900 2016-09-09 14:42:06Z bird $ */
/** @file
* Definitions, types, prototypes and globals for NT.
*/
@@ -74,6 +74,59 @@ typedef struct MY_STRING
} MY_STRING;
typedef MY_STRING MY_ANSI_STRING;
+typedef struct MY_CURDIR
+{
+ UNICODE_STRING DosPath;
+ HANDLE Handle;
+} MY_CURDIR;
+typedef MY_CURDIR *PMY_CURDIR;
+
+typedef struct MY_RTL_DRIVE_LETTER_CURDIR
+{
+ USHORT Flags;
+ USHORT Length;
+ ULONG TimeStamp;
+ MY_ANSI_STRING DosPath;
+} MY_RTL_DRIVE_LETTER_CURDIR;
+typedef MY_RTL_DRIVE_LETTER_CURDIR *PRTL_DRIVE_LETTER_CURDIR;
+
+typedef struct MY_RTL_USER_PROCESS_PARAMETERS
+{
+ ULONG MaximumLength;
+ ULONG Length;
+ ULONG Flags;
+ ULONG DebugFlags;
+ HANDLE ConsoleHandle;
+ ULONG ConsoleFlags;
+ HANDLE StandardInput;
+ HANDLE StandardOutput;
+ HANDLE StandardError;
+ MY_CURDIR CurrentDirectory;
+ MY_UNICODE_STRING DllPath;
+ MY_UNICODE_STRING ImagePathName;
+ MY_UNICODE_STRING CommandLine;
+ PWSTR Environment;
+ ULONG StartingX;
+ ULONG StartingY;
+ ULONG CountX;
+ ULONG CountY;
+ ULONG CountCharsX;
+ ULONG CountCharsY;
+ ULONG FillAttribute;
+ ULONG WindowFlags;
+ ULONG ShowWindowFlags;
+ MY_UNICODE_STRING WindowTitle;
+ MY_UNICODE_STRING DesktopInfo;
+ MY_UNICODE_STRING ShellInfo;
+ MY_UNICODE_STRING RuntimeInfo;
+ MY_RTL_DRIVE_LETTER_CURDIR CurrentDirectories[0x20];
+ SIZE_T EnvironmentSize; /* >= Vista+ */
+ SIZE_T EnvironmentVersion; /* >= Windows 7. */
+ PVOID PackageDependencyData; /* >= Windows 8 or Windows 8.1. */
+ ULONG ProcessGroupId; /* >= Windows 8 or Windows 8.1. */
+} MY_RTL_USER_PROCESS_PARAMETERS;
+typedef MY_RTL_USER_PROCESS_PARAMETERS *PMY_RTL_USER_PROCESS_PARAMETERS;
+
typedef struct MY_OBJECT_ATTRIBUTES
{
ULONG Length;
diff --git a/src/sed/Makefile.kmk b/src/sed/Makefile.kmk
index 7a6bc2f..1fec22c 100644
--- a/src/sed/Makefile.kmk
+++ b/src/sed/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 2829 2016-08-15 10:52:09Z bird $
+# $Id: Makefile.kmk 2909 2016-09-09 22:54:17Z bird $
## @file
# Sub-Makefile for kmk_sed.
#
@@ -88,6 +88,8 @@ kmk_sed_SOURCES.win = \
lib/getline.c \
../lib/startuphacks-win.c
+kmk_sed_LIBS.win = $(LIB_KUTIL) # for stdout optimizations.
+
include $(FILE_KBUILD_SUB_FOOTER)
#
diff --git a/src/sed/lib/utils.c b/src/sed/lib/utils.c
index 647fd6d..0fe8671 100644
--- a/src/sed/lib/utils.c
+++ b/src/sed/lib/utils.c
@@ -37,6 +37,11 @@
#include "utils.h"
+#ifdef KBUILD_OS_WINDOWS /* bird: Way faster console output! */
+extern size_t maybe_con_fwrite(void const *, size_t, size_t, FILE *);
+# define fwrite maybe_con_fwrite
+#endif
+
const char *myname;
/* Store information about files opened with ck_fopen
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-virtualbox/kbuild.git
More information about the Pkg-virtualbox-commits
mailing list