Index: /trunk/Config.kmk
===================================================================
--- /trunk/Config.kmk	(revision 2837)
+++ /trunk/Config.kmk	(revision 2838)
@@ -385,5 +385,31 @@
 
 
-LIB_KDEP = $(PATH_OBJ)/kDep/$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBPREF)kDep$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBSUFF)
+#
+# Template for static threaded binaries (windows).
+#
+TEMPLATE_BIN-STATIC-THREADED = Threaded command line binary
+TEMPLATE_BIN-STATIC-THREADED_EXTENDS  = BIN-THREADED
+ifeq ($(filter-out win nt,$(KBUILD_TARGET)),)
+ TEMPLATE_BIN-STATIC-THREADED_CFLAGS  = $(filter-out -MD,$(TEMPLATE_BIN-THREADED_CFLAGS)) -MT
+ TEMPLATE_BIN-STATIC-THREADED_LIBS    = $(filter-out %/msvcrt.lib,$(TEMPLATE_BIN-THREADED_LIBS)) \
+ 	$(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/libcmt.lib \
+ 	$(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/libcpmt.lib
+else
+ TEMPLATE_BIN-STATIC-THREADED_CFLAGS  = $(TEMPLATE_BIN-THREADED_CFLAGS) -static
+ TEMPLATE_BIN-STATIC-THREADED_LDFLAGS = $(TEMPLATE_BIN-THREADED_LDFLAGS) -static
+endif
+
+#
+# Template for static threaded libraries.
+#
+TEMPLATE_LIB-STATIC-THREADED = Threaded command line library
+TEMPLATE_LIB-STATIC-THREADED_EXTENDS  = BIN-STATIC-THREADED
+TEMPLATE_LIB-STATIC-THREADED_INST     = lib/
+
+
+#
+# Library macros.
+#
+LIB_KDEP  = $(PATH_OBJ)/kDep/$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBPREF)kDep$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBSUFF)
 LIB_KUTIL = $(PATH_OBJ)/kUtil/$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBPREF)kUtil$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBSUFF)
 
Index: /trunk/src/kWorker/Makefile.kmk
===================================================================
--- /trunk/src/kWorker/Makefile.kmk	(revision 2837)
+++ /trunk/src/kWorker/Makefile.kmk	(revision 2838)
@@ -24,6 +24,4 @@
 #
 
-## @todo fixme!!!
-KBUILD_WITH_STATIC_MSVCRT = 1
 
 SUB_DEPTH = ../..
@@ -32,5 +30,5 @@
 
 PROGRAMS += kWorker
-kWorker_TEMPLATE = BIN
+kWorker_TEMPLATE = BIN-STATIC-THREADED
 kWorker_INCS = kStuff/include
 kWorker_DEFS.debug = K_STRICT
@@ -39,9 +37,8 @@
 kWorker_LIBS = \
 	$(kStuff_1_TARGET) \
-	$(LIB_KDEP) \
-	$(LIB_KUTIL)
+	$(kWorkerLib_1_TARGET)
 include $(KBUILD_PATH)/sdks/WINDDK71.kmk
 kWorker_LIBS.win = \
-	$(TEMPLATE_BIN_LIBS) \
+	$(TEMPLATE_BIN-STATIC-THREADED_LIBS) \
 	$(PATH_SDK_WINDDK71_LIB_WNET)/ntdll.lib
 kWorker_LDFLAGS.win = \
@@ -50,8 +47,27 @@
 
 #
+# Stuff from ../libs.  Need to rebuilt it with static CRT.
+#
+LIBRARIES += kWorkerLib
+kWorkerLib_TEMPLATE = LIB-STATIC-THREADED
+kWorkerLib_DEFPATH = ../lib # Need fix from r2837.
+kWorkerLib_DEFPATH := $(PATH_SUB_CURRENT)/../lib
+kWorkerLib_SOURCES = \
+	crc32.c \
+	md5.c
+kWorkerLib_SOURCES.win = \
+	nt_fullpath.c \
+	quoted_spawn.c \
+       nt/nthlpcore.c \
+       nt/nthlpfs.c \
+       nt/ntdir.c \
+       nt/ntstat.c \
+       nt/ntunlink.c
+
+#
 # kStuff library.
 #
 LIBRARIES += kStuff
-kStuff_TEMPLATE = LIB
+kStuff_TEMPLATE = LIB-STATIC-THREADED
 kStuff_DEFS.debug = K_STRICT
 kStuff_INCS = kStuff/include
Index: /trunk/src/kWorker/kWorker.c
===================================================================
--- /trunk/src/kWorker/kWorker.c	(revision 2837)
+++ /trunk/src/kWorker/kWorker.c	(revision 2838)
@@ -4922,10 +4922,11 @@
 #else
 // Skylake (W10/amd64, only stdandard MS defender):
-//     run 4: 32.67/1024 = 0x0 (0.031904296875)
-//     run 3: 32.77/1024 = 0x0 (0.032001953125)
-//     run 2: 34/1024 = 0x0 (0.033203125)
-//     run 1: 37/1024 = 0x0 (0.0361328125)
-//     kmk 1: 44/1024 = 0x0 (0.04296875)
-//     cmd 1: 48/1024 = 0x0 (0.046875)
+//     cmd 1:  48    /1024 = 0x0 (0.046875)        [for /l %i in (1,1,1024) do ...]
+//     kmk 1:  44    /1024 = 0x0 (0.04296875)      [all: ; 1024 x cl.exe]
+//     run 1:  37    /1024 = 0x0 (0.0361328125)    [just process creation gain]
+//     run 2:  34    /1024 = 0x0 (0.033203125)     [get file attribs]
+//     run 3:  32.77 /1024 = 0x0 (0.032001953125)  [read caching of headers]
+//     run 4:  32.67 /1024 = 0x0 (0.031904296875)  [loader tweaking]
+//     run 5:  29.144/1024 = 0x0 (0.0284609375)    [with temp files in memory]
 // Dell (W7/amd64, infected by mcafee):
 //     kmk 1: 285.278/1024 = 0x0 (0.278591796875)
Index: /trunk/src/lib/Makefile.kmk
===================================================================
--- /trunk/src/lib/Makefile.kmk	(revision 2837)
+++ /trunk/src/lib/Makefile.kmk	(revision 2838)
@@ -42,4 +42,5 @@
 kUtil_SOURCES.win = \
 	nt_fullpath.c \
+	quote_argv.c \
 	quoted_spawn.c \
        nt/nthlpcore.c \
Index: /trunk/src/lib/quote_argv.c
===================================================================
--- /trunk/src/lib/quote_argv.c	(revision 2838)
+++ /trunk/src/lib/quote_argv.c	(revision 2838)
@@ -0,0 +1,203 @@
+/* $Id$ */
+/** @file
+ * quote_argv - Correctly quote argv for spawn, windows specific.
+ */
+
+/*
+ * Copyright (c) 2007-2016 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * kBuild is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with kBuild.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "quote_argv.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifndef KBUILD_OS_WINDOWS
+# error "KBUILD_OS_WINDOWS not defined"
+#endif
+
+
+/**
+ * Checks if this is an Watcom option where we must just pass thru the string
+ * as-is.
+ *
+ * This is currnetly only used for -d (defining macros).
+ *
+ * @returns 1 if pass-thru, 0 if not.
+ * @param   pszArg          The argument to consider.
+ */
+static int isWatcomPassThruOption(const char *pszArg)
+{
+    char ch = *pszArg++;
+    if (ch != '-' && ch != '/')
+        return 0;
+    ch = *pszArg++;
+    switch (ch)
+    {
+        /* Example: -d+VAR="string-value" */
+        case 'd':
+            if (ch == '+')
+                ch = *pszArg++;
+            if (!isalpha(ch) && ch != '_')
+                return 0;
+            return 1;
+
+        default:
+            return 0;
+    }
+}
+
+
+/**
+ * Replaces arguments in need of quoting.
+ *
+ * For details on how MSC parses the command line, see "Parsing C Command-Line
+ * Arguments": http://msdn.microsoft.com/en-us/library/a1y7w461.aspx
+ *
+ * @param   argc                The argument count.
+ * @param   argv                The argument vector.
+ * @param   fWatcomBrainDamage  Set if we're catering for wcc, wcc386 or similar
+ *                              OpenWatcom tools.  They seem to follow some
+ *                              ancient or home made quoting convention.
+ * @param   fFreeOrLeak         Whether to free replaced argv members
+ *                              (non-zero), or just leak them (zero).  This
+ *                              depends on which argv you're working on.
+ *                              Suggest doing the latter if it's main()'s argv.
+ */
+void quote_argv(int argc, char **argv, int fWatcomBrainDamage, int fFreeOrLeak)
+{
+    int i;
+    for (i = 0; i < argc; i++)
+    {
+        char *const pszOrgOrg = argv[i];
+        const char *pszOrg    = pszOrgOrg;
+        size_t      cchOrg    = strlen(pszOrg);
+        const char *pszQuotes = (const char *)memchr(pszOrg, '"', cchOrg);
+        const char *pszProblem = NULL;
+        if (   pszQuotes
+            || cchOrg == 0
+            || (pszProblem = (const char *)memchr(pszOrg, ' ',  cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '\t', cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '\n', cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '\r', cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '&',  cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '>',  cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '<',  cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '|',  cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '%',  cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '\'', cchOrg)) != NULL
+            || (   !fWatcomBrainDamage
+                && (pszProblem = (const char *)memchr(pszOrg, '=',  cchOrg)) != NULL)
+            )
+        {
+            char   ch;
+            int    fComplicated = pszQuotes || (cchOrg > 0 && pszOrg[cchOrg - 1] == '\\');
+            size_t cchNew       = fComplicated ? cchOrg * 2 + 2 : cchOrg + 2;
+            char  *pszNew       = (char *)malloc(cchNew + 1 /*term*/ + 3 /*passthru hack*/);
+
+            argv[i] = pszNew;
+
+            /* Watcom does not grok stuff like "-i=c:\program files\watcom\h",
+               it think it's a source specification. In that case the quote
+               must follow the equal sign. */
+            if (fWatcomBrainDamage)
+            {
+                size_t cchUnquoted  = 0;
+                if (pszOrg[0] == '@') /* Response file quoting: @"file name.rsp" */
+                    cchUnquoted = 1;
+                else if (pszOrg[0] == '-' || pszOrg[0] == '/') /* Switch quoting. */
+                {
+                    if (isWatcomPassThruOption(pszOrg))
+                        cchUnquoted = strlen(pszOrg) + 1;
+                    else
+                    {
+                        const char *pszNeedQuoting = (const char *)memchr(pszOrg, '=', cchOrg); /* For -i=dir and similar. */
+                        if (   pszNeedQuoting == NULL
+                            || (uintptr_t)pszNeedQuoting > (uintptr_t)(pszProblem ? pszProblem : pszQuotes))
+                            pszNeedQuoting = pszProblem ? pszProblem : pszQuotes;
+                        else
+                            pszNeedQuoting++;
+                        cchUnquoted = pszNeedQuoting - pszOrg;
+                    }
+                }
+                if (cchUnquoted)
+                {
+                    memcpy(pszNew, pszOrg, cchUnquoted);
+                    pszNew += cchUnquoted;
+                    pszOrg += cchUnquoted;
+                    cchOrg -= cchUnquoted;
+                }
+            }
+
+            *pszNew++ = '"';
+            if (fComplicated)
+            {
+                while ((ch = *pszOrg++) != '\0')
+                {
+                    if (ch == '"')
+                    {
+                        *pszNew++ = '\\';
+                        *pszNew++ = '"';
+                    }
+                    else if (ch == '\\')
+                    {
+                        /* Backslashes are a bit complicated, they depends on
+                           whether a quotation mark follows them or not.  They
+                           only require escaping if one does. */
+                        unsigned cSlashes = 1;
+                        while ((ch = *pszOrg) == '\\')
+                        {
+                            pszOrg++;
+                            cSlashes++;
+                        }
+                        if (ch == '"' || ch == '\0') /* We put a " at the EOS. */
+                        {
+                            while (cSlashes-- > 0)
+                            {
+                                *pszNew++ = '\\';
+                                *pszNew++ = '\\';
+                            }
+                        }
+                        else
+                            while (cSlashes-- > 0)
+                                *pszNew++ = '\\';
+                    }
+                    else
+                        *pszNew++ = ch;
+                }
+            }
+            else
+            {
+                memcpy(pszNew, pszOrg, cchOrg);
+                pszNew += cchOrg;
+            }
+            *pszNew++ = '"';
+            *pszNew = '\0';
+
+            if (fFreeOrLeak)
+                free(pszOrgOrg);
+        }
+    }
+
+    /*for (i = 0; i < argc; i++) fprintf(stderr, "argv[%u]=%s;;\n", i, argv[i]);*/
+}
+
Index: /trunk/src/lib/quote_argv.h
===================================================================
--- /trunk/src/lib/quote_argv.h	(revision 2838)
+++ /trunk/src/lib/quote_argv.h	(revision 2838)
@@ -0,0 +1,34 @@
+/* $Id$ */
+/** @file
+ * quote_argv - Correctly quote argv for spawn, windows specific.
+ */
+
+/*
+ * Copyright (c) 2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * kBuild is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with kBuild.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+
+#ifndef ___quote_argv_h___
+#define ___quote_argv_h___
+
+#include "mytypes.h"
+extern void quote_argv(int argc, char **argv, int fWatcomBrainDamage, int fFreeOrLeak);
+
+#endif
+
