Index: /trunk/src/kmk/kmkbuiltin.h
===================================================================
--- /trunk/src/kmk/kmkbuiltin.h	(revision 3194)
+++ /trunk/src/kmk/kmkbuiltin.h	(revision 3195)
@@ -89,4 +89,8 @@
     /** The KMK output synchronizer.   */
     struct output *pOut;
+#if defined(KBUILD_OS_WINDOWS) && !defined(KMK_BUILTIN_STANDALONE)
+    /** Pointer to the worker thread, if we're on one. */
+    void *pvWorker;
+#endif
 } KMKBUILTINCTX;
 /** Pointer to kmk built-in command execution context. */
Index: /trunk/src/kmk/kmkbuiltin/redirect.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin/redirect.c	(revision 3194)
+++ /trunk/src/kmk/kmkbuiltin/redirect.c	(revision 3195)
@@ -92,4 +92,8 @@
 #  define LIBPATHSTRICT 3
 # endif
+#endif
+
+#ifndef KMK_BUILTIN_STANDALONE
+extern void kmk_cache_exec_image_a(const char *); /* imagecache.c */
 #endif
 
@@ -596,4 +600,72 @@
 
 /**
+ * Registers the child process with a care provider or waits on it to complete.
+ *
+ * @returns 0 or non-zero success indicator or child exit code, depending on
+ *          the value pfIsChildExitCode points to.
+ * @param   pCtx                The command execution context.
+ * @param   hProcess            The child process handle.
+ * @param   cVerbosity          The verbosity level.
+ * @param   pPidSpawned         Where to return the PID of the spawned child
+ *                              when we're inside KMK and we're return without
+ *                              waiting.
+ * @param   pfIsChildExitCode   Where to indicate whether the return exit code
+ *                              is from the child or from our setup efforts.
+ */
+static int kRedirectPostnatalCareOnWindows(PKMKBUILTINCTX pCtx, HANDLE hProcess, unsigned cVerbosity,
+                                           pid_t *pPidSpawned, KBOOL *pfIsChildExitCode)
+{
+    int   rcExit;
+    DWORD dwTmp;
+
+# ifndef KMK_BUILTIN_STANDALONE
+    /*
+     * Try register the child with a childcare provider, i.e. winchildren.c
+     * or sub_proc.c.
+     */
+#  ifndef CONFIG_NEW_WIN_CHILDREN
+    if (process_kmk_register_redirect(hProcess, pPidSpawned) == 0)
+#  else
+    if (   pPidSpawned
+        && MkWinChildCreateRedirect((intptr_t)hProcess, pPidSpawned) == 0)
+#  endif
+    {
+        if (cVerbosity > 0)
+            warnx(pCtx, "debug: spawned %d", *pPidSpawned);
+        *pfIsChildExitCode = K_FALSE;
+        return 0;
+    }
+#  ifndef CONFIG_NEW_WIN_CHILDREN
+    warn(pCtx, "sub_proc is out of slots, waiting for child...");
+#  else
+    if (pPidSpawned)
+        warn(pCtx, "MkWinChildCreateRedirect failed...");
+#  endif
+# endif
+
+    /*
+     * Either the provider is outbooked or we're not in a context (like
+     * standalone) where we get help with waiting and must to it ourselves
+     */
+    dwTmp = WaitForSingleObject(hProcess, INFINITE);
+    if (dwTmp != WAIT_OBJECT_0)
+        warnx(pCtx, "WaitForSingleObject failed: %#x\n", dwTmp);
+
+    if (GetExitCodeProcess(hProcess, &dwTmp))
+        rcExit = (int)dwTmp;
+    else
+    {
+        warnx(pCtx, "GetExitCodeProcess failed: %u\n", GetLastError());
+        TerminateProcess(hProcess, 127);
+        rcExit = 127;
+    }
+
+    CloseHandle(hProcess);
+    *pfIsChildExitCode = K_TRUE;
+    return rcExit;
+}
+
+
+/**
  * Tries to locate the executable image.
  *
@@ -665,4 +737,51 @@
 
    return pszExecutable;
+}
+
+
+/**
+ * Turns the orders into input for nt_child_inject_standard_handles and
+ * winchildren.c
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param   pCtx                The command execution context.
+ * @param   cOrders             Number of file operation orders.
+ * @param   paOrders            The file operation orders.
+ * @param   pafReplace          Replace (TRUE) or leave alone (FALSE) indicator
+ *                              for each of the starndard handles.
+ * @param   pahChild            Array of standard handles for injecting into the
+ *                              child.  Parallel to pafReplace.
+ */
+static int kRedirectOrderToWindowsHandles(PKMKBUILTINCTX pCtx, unsigned cOrders, REDIRECTORDERS *paOrders,
+                                          BOOL pafReplace[3], HANDLE pahChild[3])
+{
+    int i;
+    for (i = 0; i < (int)cOrders; i++)
+    {
+        int fdTarget = paOrders[i].fdTarget;
+        assert(fdTarget >= 0 && fdTarget < 3);
+        switch (paOrders[i].enmOrder)
+        {
+            case kRedirectOrder_Open:
+                if (   (paOrders[i].fOpen & O_APPEND)
+                    && lseek(paOrders[i].fdSource, 0, SEEK_END) < 0)
+                    return err(pCtx, 10, "lseek-to-end failed on %d (for %d)", paOrders[i].fdSource, fdTarget);
+                /* fall thru */
+            case kRedirectOrder_Dup:
+                pahChild[fdTarget] = (HANDLE)_get_osfhandle(paOrders[i].fdSource);
+                if (pahChild[fdTarget] == NULL || pahChild[fdTarget] == INVALID_HANDLE_VALUE)
+                    return err(pCtx, 10, "_get_osfhandle failed on %d (for %d)", paOrders[i].fdSource, fdTarget);
+                break;
+
+            case kRedirectOrder_Close:
+                pahChild[fdTarget] = NULL;
+                break;
+
+            default:
+                assert(0);
+        }
+        pafReplace[fdTarget] = TRUE;
+    }
+    return 0;
 }
 
@@ -774,4 +893,7 @@
                 CloseHandle(ProcInfo.hThread);
                 *phProcess = ProcInfo.hProcess;
+# ifndef KMK_BUILTIN_STANDALONE
+                kmk_cache_exec_image_a(pszExecutable);
+# endif
                 rc = 0;
             }
@@ -789,28 +911,5 @@
             BOOL   afReplace[3] = { FALSE, FALSE, FALSE };
             HANDLE ahChild[3]   = { NULL,  NULL,  NULL  };
-            rc = 0;
-            for (i = 0; i < (int)cOrders; i++)
-            {
-                int fdTarget = paOrders[i].fdTarget;
-                assert(fdTarget >= 0 && fdTarget < 3);
-                switch (paOrders[i].enmOrder)
-                {
-                    case kRedirectOrder_Open:
-                        if (   (paOrders[i].fOpen & O_APPEND)
-                            && lseek(paOrders[i].fdSource, 0, SEEK_END) < 0)
-                            rc = err(pCtx, 10, "lseek-to-end failed on %d (for %d)", paOrders[i].fdSource, fdTarget);
-                    case kRedirectOrder_Dup:
-                        ahChild[fdTarget] = (HANDLE)_get_osfhandle(paOrders[i].fdSource);
-                        if (ahChild[fdTarget] == NULL || ahChild[fdTarget] == INVALID_HANDLE_VALUE)
-                            rc = err(pCtx, 10, "_get_osfhandle failed on %d (for %d)", paOrders[i].fdSource, fdTarget);
-                        break;
-                    case kRedirectOrder_Close:
-                        ahChild[fdTarget] = NULL;
-                        break;
-                    default:
-                        assert(0);
-                }
-                afReplace[fdTarget] = TRUE;
-            }
+            rc = kRedirectOrderToWindowsHandles(pCtx, cOrders, paOrders, afReplace, ahChild);
             if (rc == 0)
             {
@@ -835,4 +934,7 @@
                     CloseHandle(ProcInfo.hThread);
                     *phProcess = ProcInfo.hProcess;
+# ifndef KMK_BUILTIN_STANDALONE
+                    kmk_cache_exec_image_a(pszExecutable);
+# endif
                     rc = 0;
                 }
@@ -848,4 +950,38 @@
     return rc;
 }
+
+# if !defined(KMK_BUILTIN_STANDALONE) && defined(CONFIG_NEW_WIN_CHILDREN)
+/**
+ * Pass the problem on to winchildren.c when we're on one of its workers.
+ *
+ * @returns 0 on success, non-zero on failure to create.
+ * @param   pCtx                The command execution context.
+ * @param   pszExecutable       The child process executable.
+ * @param   cArgs               Number of arguments.
+ * @param   papszArgs           The child argument vector.
+ * @param   papszEnvVars        The child environment vector.
+ * @param   pszCwd              The current working directory of the child.
+ * @param   cOrders             Number of file operation orders.
+ * @param   paOrders            The file operation orders.
+ * @param   phProcess           Where to return process handle.
+ * @param   pfIsChildExitCode   Where to indicate whether the return exit code
+ *                              is from the child or from our setup efforts.
+ */
+static int kRedirectExecProcessWithinOnWorker(PKMKBUILTINCTX pCtx, const char *pszExecutable, int cArgs, char **papszArgs,
+                                              char **papszEnvVars, const char *pszCwd, unsigned cOrders,
+                                              REDIRECTORDERS *paOrders, KBOOL *pfIsChildExitCode)
+{
+    BOOL   afReplace[3] = { FALSE, FALSE, FALSE };
+    HANDLE ahChild[3]   = { NULL,  NULL,  NULL  };
+    int rc = kRedirectOrderToWindowsHandles(pCtx, cOrders, paOrders, afReplace, ahChild);
+    if (rc == 0)
+    {
+        rc = MkWinChildBuiltInExecChild(pCtx->pvWorker, pszExecutable, papszArgs, TRUE /*fQuotedArgv*/,
+                                        papszEnvVars, pszCwd, afReplace, ahChild);
+        *pfIsChildExitCode = K_TRUE;
+    }
+    return rc;
+}
+# endif /* !KMK_BUILTIN_STANDALONE */
 
 #endif /* KBUILD_OS_WINDOWS */
@@ -964,46 +1100,19 @@
 # ifdef KBUILD_OS_WINDOWS
                 /* Windows is slightly complicated due to handles and winchildren.c. */
-                HANDLE hProcess = INVALID_HANDLE_VALUE;
-                rcExit = kRedirectCreateProcessWindows(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars,
-                                                       pszSavedCwd ? pszCwd : NULL, cOrders, paOrders, &hProcess);
-                if (rcExit == 0)
-                {
-#  ifndef CONFIG_NEW_WIN_CHILDREN
-                    if (process_kmk_register_redirect(hProcess, pPidSpawned) == 0)
-#  else
-                    if (   pPidSpawned
-                        && MkWinChildCreateRedirect((intptr_t)hProcess, pPidSpawned) == 0)
+                if (pPidSpawned)
+                    *pPidSpawned = 0;
+#  ifdef CONFIG_NEW_WIN_CHILDREN
+                if (pCtx->pvWorker && !pPidSpawned)
+                    rcExit = kRedirectExecProcessWithinOnWorker(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars,
+                                                                pszSavedCwd ? pszCwd : NULL, cOrders, paOrders,
+                                                                pfIsChildExitCode);
+                else
 #  endif
-                    {
-                        if (cVerbosity > 0)
-                            warnx(pCtx, "debug: spawned %d", *pPidSpawned);
-                    }
-                    else
-                    {
-                        DWORD dwTmp;
-#  ifndef CONFIG_NEW_WIN_CHILDREN
-                        warn(pCtx, "sub_proc is out of slots, waiting for child...");
-#  else
-                        if (pPidSpawned)
-                            warn(pCtx, "MkWinChildCreateRedirect failed...");
-#  endif
-                        dwTmp = WaitForSingleObject(hProcess, INFINITE);
-                        if (dwTmp != WAIT_OBJECT_0)
-                            warnx(pCtx, "WaitForSingleObject failed: %#x\n", dwTmp);
-
-                        if (GetExitCodeProcess(hProcess, &dwTmp))
-                            rcExit = (int)dwTmp;
-                        else
-                        {
-                            warnx(pCtx, "GetExitCodeProcess failed: %u\n", GetLastError());
-                            TerminateProcess(hProcess, 127);
-                            rcExit = 127;
-                        }
-
-                        CloseHandle(hProcess);
-                        if (pPidSpawned)
-                            *pPidSpawned = 0;
-                        *pfIsChildExitCode = K_TRUE;
-                    }
+                {
+                    HANDLE hProcess = INVALID_HANDLE_VALUE;
+                    rcExit = kRedirectCreateProcessWindows(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars,
+                                                           pszSavedCwd ? pszCwd : NULL, cOrders, paOrders, &hProcess);
+                    if (rcExit == 0)
+                        rcExit = kRedirectPostnatalCareOnWindows(pCtx, hProcess, cVerbosity, pPidSpawned, pfIsChildExitCode);
                 }
 
@@ -1052,5 +1161,8 @@
                     dwWait = 11;
                     if (GetExitCodeProcess(hProcess, &dwWait))
+                    {
+                        *pfIsChildExitCode = K_TRUE;
                         rcExit = dwWait;
+                    }
                     else
                         rcExit = errx(pCtx, 11, "GetExitCodeProcess(%s) failed: %u", pszExecutable, GetLastError());
Index: /trunk/src/kmk/output.c
===================================================================
--- /trunk/src/kmk/output.c	(revision 3194)
+++ /trunk/src/kmk/output.c	(revision 3195)
@@ -126,8 +126,28 @@
             fflush(prevdst);
           prevdst = dst;
-# ifdef KBUILD_OS_WINDOWS
+# if 0 /* for debugging */
+          while (len > 0)
+            {
+              const char *nl = (const char *)memchr (src, '\n', len);
+              size_t line_len = nl ? nl - (const char *)src + 1 : len;
+              char *tmp = (char *)xmalloc (2 + line_len + 1);
+              tmp[0] = '>';
+              tmp[1] = ' ';
+              memcpy (&tmp[2], src, line_len);
+#  ifdef KBUILD_OS_WINDOWS
+              maybe_con_fwrite (tmp, 2 + line_len, 1, dst);
+#  else
+              fwrite (tmp, 2 + line_len, 1, dst);
+#  endif
+              free (tmp);
+              src  = (const char *)src + line_len;
+              len -= line_len;
+            }
+#else
+#  ifdef KBUILD_OS_WINDOWS
           maybe_con_fwrite (src, len, 1, dst);
-# else
+#  else
           fwrite (src, len, 1, dst);
+#  endif
 # endif
         }
Index: /trunk/src/kmk/w32/imagecache.c
===================================================================
--- /trunk/src/kmk/w32/imagecache.c	(revision 3194)
+++ /trunk/src/kmk/w32/imagecache.c	(revision 3195)
@@ -26,7 +26,7 @@
 /* No GNU coding style here! */
 
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
 #include "makeint.h"
 
@@ -34,7 +34,7 @@
 
 
-/*******************************************************************************
-*   Structures and Typedefs                                                    *
-*******************************************************************************/
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
 typedef struct EXECCACHEENTRY
 {
@@ -42,21 +42,26 @@
     unsigned                uHash;
     /** The name length. */
-    unsigned                cchName;
+    unsigned                cwcName;
     /** Pointer to the next name with the same hash. */
     struct EXECCACHEENTRY  *pNext;
     /** When it was last referenced. */
     unsigned                uLastRef;
-    /** The module handle. */
+    /** The module handle, LOAD_LIBRARY_AS_DATAFILE. */
     HMODULE                 hmod1;
-    /** The module handle. */
+    /** The module handle, DONT_RESOLVE_DLL_REFERENCES. */
     HMODULE                 hmod2;
     /** The executable path. */
-    char                    szName[1];
+    wchar_t                 wszName[1];
 } EXECCACHEENTRY;
 typedef EXECCACHEENTRY *PEXECCACHEENTRY;
 
-/*******************************************************************************
-*   Global Variables                                                           *
-*******************************************************************************/
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** Critical section serializing all access. */
+static CRITICAL_SECTION g_CritSect;
+/** Set if initialized. */
+static int volatile     g_fInitialized = 0;
 /** The number of cached images. */
 static unsigned         g_cCached;
@@ -69,4 +74,18 @@
 /** The hash table. */
 static PEXECCACHEENTRY  g_apHashTab[EXECCACHE_HASHTAB_SIZE];
+
+
+/** A sleepy approach to do-once. */
+static void kmk_cache_lazy_init(void)
+{
+    if (_InterlockedCompareExchange(&g_fInitialized, -1, 0) == 0)
+    {
+        InitializeCriticalSection(&g_CritSect);
+        _InterlockedExchange(&g_fInitialized, 1);
+    }
+    else
+        while (g_fInitialized != 1)
+            Sleep(1);
+}
 
 
@@ -83,34 +102,51 @@
    elsewhere. */
 
-static unsigned execcache_calc_hash(const char *psz, unsigned *pcch)
-{
-    unsigned char  *puch = (unsigned char *)psz;
-    unsigned        hash = 0;
-    int             ch;
-
-    while ((ch = *puch++))
+static unsigned execcache_calc_hash(const wchar_t *pwsz, size_t *pcch)
+{
+    wchar_t const  * const pwszStart = pwsz;
+    unsigned               hash = 0;
+    int                    ch;
+
+    while ((ch = *pwsz++) != L'\0')
         hash = ch + (hash << 6) + (hash << 16) - hash;
 
-    *pcch = (unsigned)(puch - psz - 1);
+    *pcch = (size_t)(pwsz - pwszStart - 1);
     return hash;
 }
 
-
-extern void kmk_cache_exec_image(const char *pszExec)
-{
-    /*
-     * Lookup the name.
-     */
-    unsigned            cchName;
-    const unsigned      uHash = execcache_calc_hash(pszExec, &cchName);
+/**
+ * Caches two memory mappings of the specified image so that it isn't flushed
+ * from the kernel's cache mananger.
+ *
+ * Not sure exactly how much this actually helps, but whatever...
+ *
+ * @param   pwszExec    The executable.
+ */
+extern void kmk_cache_exec_image_w(const wchar_t *pwszExec)
+{
+    /*
+     * Prepare name lookup and to lazy init.
+     */
+    size_t              cwcName;
+    const unsigned      uHash = execcache_calc_hash(pwszExec, &cwcName);
     PEXECCACHEENTRY    *ppCur = &g_apHashTab[uHash % EXECCACHE_HASHTAB_SIZE];
-    PEXECCACHEENTRY     pCur  = *ppCur;
+    PEXECCACHEENTRY     pCur;
+
+    if (g_fInitialized != 1)
+        kmk_cache_lazy_init();
+
+    /*
+     * Do the lookup.
+     */
+    EnterCriticalSection(&g_CritSect);
+    pCur = *ppCur;
     while (pCur)
     {
         if (   pCur->uHash   == uHash
-            && pCur->cchName == cchName
-            && !memcmp(pCur->szName, pszExec, cchName))
+            && pCur->cwcName == cwcName
+            && !memcmp(pCur->wszName, pwszExec, cwcName * sizeof(wchar_t)))
         {
             pCur->uLastRef = ++g_uNow;
+            LeaveCriticalSection(&g_CritSect);
             return;
         }
@@ -118,22 +154,66 @@
         pCur = pCur->pNext;
     }
+    LeaveCriticalSection(&g_CritSect);
 
     /*
      * Not found, create a new entry.
      */
-    pCur = xmalloc(sizeof(*pCur) + cchName);
+    pCur = xmalloc(sizeof(*pCur) + cwcName * sizeof(wchar_t));
     pCur->uHash    = uHash;
-    pCur->cchName  = cchName;
+    pCur->cwcName  = (unsigned)cwcName;
     pCur->pNext    = NULL;
     pCur->uLastRef = ++g_uNow;
-    memcpy(pCur->szName, pszExec, cchName + 1);
-    pCur->hmod1 = LoadLibraryEx(pszExec, NULL, LOAD_LIBRARY_AS_DATAFILE);
+    memcpy(pCur->wszName, pwszExec, (cwcName + 1) * sizeof(wchar_t));
+    pCur->hmod1 = LoadLibraryExW(pwszExec, NULL, LOAD_LIBRARY_AS_DATAFILE);
     if (pCur->hmod1 != NULL)
-        pCur->hmod2 = LoadLibraryEx(pszExec, NULL, DONT_RESOLVE_DLL_REFERENCES);
+        pCur->hmod2 = LoadLibraryExW(pwszExec, NULL, DONT_RESOLVE_DLL_REFERENCES);
     else
         pCur->hmod2 = NULL;
 
-    *ppCur = pCur;
-    g_cCached++;
-}
-
+    /*
+     * Insert it.
+     * Take into account that we might've been racing other threads,
+     * fortunately we don't evict anything from the cache.
+     */
+    EnterCriticalSection(&g_CritSect);
+    if (*ppCur != NULL)
+    {
+        /* Find new end of chain and check for duplicate. */
+        PEXECCACHEENTRY pCur2 = *ppCur;
+        while (pCur2)
+        {
+            if (   pCur->uHash   == uHash
+                && pCur->cwcName == cwcName
+                && !memcmp(pCur->wszName, pwszExec, cwcName * sizeof(wchar_t)))
+                break;
+            ppCur = &pCur->pNext;
+            pCur = pCur->pNext;
+        }
+
+    }
+    if (*ppCur == NULL)
+    {
+        *ppCur = pCur;
+        g_cCached++;
+        LeaveCriticalSection(&g_CritSect);
+    }
+    else
+    {
+        LeaveCriticalSection(&g_CritSect);
+
+        if (pCur->hmod1 != NULL)
+            FreeLibrary(pCur->hmod1);
+        if (pCur->hmod2 != NULL)
+            FreeLibrary(pCur->hmod2);
+        free(pCur);
+    }
+}
+
+extern void kmk_cache_exec_image_a(const char *pszExec)
+{
+    wchar_t wszExec[260];
+    int cwc = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszExec, strlen(pszExec) + 1, wszExec, 260);
+    if (cwc > 0)
+        kmk_cache_exec_image_w(wszExec);
+}
+
Index: /trunk/src/kmk/w32/subproc/sub_proc.c
===================================================================
--- /trunk/src/kmk/w32/subproc/sub_proc.c	(revision 3194)
+++ /trunk/src/kmk/w32/subproc/sub_proc.c	(revision 3195)
@@ -40,5 +40,5 @@
 # include <assert.h>
 # include "kmkbuiltin.h"
-extern void kmk_cache_exec_image(const char *); /* imagecache.c */
+extern void kmk_cache_exec_image_a(const char *); /* imagecache.c */
 #endif
 
@@ -844,9 +844,9 @@
 #ifdef KMK
 		if (exec_fname[0])
-			kmk_cache_exec_image(exec_fname);
+			kmk_cache_exec_image_a(exec_fname);
 		else if (exec_path)
-			kmk_cache_exec_image(exec_path);
+			kmk_cache_exec_image_a(exec_path);
 		else if (argv[0])
-			kmk_cache_exec_image(argv[0]);
+			kmk_cache_exec_image_a(argv[0]);
 
 		switch (process_priority) {
Index: /trunk/src/kmk/w32/winchildren.c
===================================================================
--- /trunk/src/kmk/w32/winchildren.c	(revision 3194)
+++ /trunk/src/kmk/w32/winchildren.c	(revision 3195)
@@ -101,4 +101,8 @@
 
 #include "nt/nt_child_inject_standard_handles.h"
+
+#ifndef KMK_BUILTIN_STANDALONE
+extern void kmk_cache_exec_image_w(const wchar_t *); /* imagecache.c */
+#endif
 
 
@@ -805,4 +809,5 @@
  * Commmon worker for waiting on a child process and retrieving the exit code.
  *
+ * @returns Child exit code.
  * @param   pWorker             The worker.
  * @param   pChild              The child.
@@ -812,6 +817,6 @@
  *                              associated with the worker.
  */
-static void mkWinChildcareWorkerWaitForProcess(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild, HANDLE hProcess,
-                                               WCHAR const *pwszJob, BOOL fCatchOutput)
+static int mkWinChildcareWorkerWaitForProcess(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild, HANDLE hProcess,
+                                              WCHAR const *pwszJob, BOOL fCatchOutput)
 {
     DWORD const msStart = GetTickCount();
@@ -850,5 +855,5 @@
                     mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdErr, TRUE /*fFlushing*/);
                 }
-                return;
+                return dwExitCode;
             }
         }
@@ -891,5 +896,5 @@
         if (pChild->iExitCode == 0)
             pChild->iExitCode = -4242;
-        return;
+        return pChild->iExitCode;
     }
 }
@@ -930,12 +935,12 @@
  * @param   pwszzEnvironment    The enviornment block.
  */
-static int mkWinChildcareWorkerCreateProcess(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild, WCHAR const *pwszImageName,
-                                             WCHAR const *pwszCommandLine, WCHAR const *pwszzEnvironment)
+static int mkWinChildcareWorkerCreateProcess(PWINCHILDCAREWORKER pWorker, WCHAR const *pwszImageName,
+                                             WCHAR const *pwszCommandLine, WCHAR const *pwszzEnvironment, WCHAR const *pwszCwd,
+                                             BOOL pafReplace[3], HANDLE pahChild[3], BOOL fCatchOutput, HANDLE *phProcess)
 {
     PROCESS_INFORMATION ProcInfo;
     STARTUPINFOW        StartupInfo;
     DWORD               fFlags       = CREATE_UNICODE_ENVIRONMENT;
-    BOOL const          fHaveHandles = pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE
-                                    || pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE;
+    BOOL const          fHaveHandles = pafReplace[0] | pafReplace[1] | pafReplace[2];
     BOOL                fRet;
     DWORD               dwErr;
@@ -965,5 +970,5 @@
     StartupInfo.cbReserved2 = 0;
     if (   !fHaveHandles
-        && !pChild->u.Process.fCatchOutput)
+        && !fCatchOutput)
         StartupInfo.dwFlags &= ~STARTF_USESTDHANDLES;
     else
@@ -999,5 +1004,5 @@
 
     fRet = CreateProcessW((WCHAR *)pwszImageName, (WCHAR *)pwszCommandLine, NULL /*pProcSecAttr*/, NULL /*pThreadSecAttr*/,
-                          FALSE /*fInheritHandles*/, fFlags, (WCHAR *)pwszzEnvironment, NULL /*pwsz*/, &StartupInfo, &ProcInfo);
+                          FALSE /*fInheritHandles*/, fFlags, (WCHAR *)pwszzEnvironment, pwszCwd, &StartupInfo, &ProcInfo);
     dwErr = GetLastError();
 
@@ -1006,9 +1011,9 @@
 #endif
     if (fRet)
-        pChild->u.Process.hProcess = ProcInfo.hProcess;
+        *phProcess = ProcInfo.hProcess;
     else
     {
         fprintf(stderr, "CreateProcess(%ls) failed: %u\n", pwszImageName, dwErr);
-        return pChild->iExitCode = (int)dwErr;
+        return (int)dwErr;
     }
 
@@ -1022,28 +1027,21 @@
          * First do handle inhertiance as that's the most complicated.
          */
-        if (fHaveHandles || pChild->u.Process.fCatchOutput)
-        {
-            char    szErrMsg[128];
-            BOOL    afReplace[3];
-            HANDLE  ahChild[3];
-
-            afReplace[0] = FALSE;
-            ahChild[0]   = INVALID_HANDLE_VALUE;
-            if (fHaveHandles)
-            {
-                afReplace[1] = pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE;
-                ahChild[1]   = pChild->u.Process.hStdOut;
-                afReplace[2] = pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE;
-                ahChild[2]   = pChild->u.Process.hStdErr;
-            }
-            else
-            {
-                afReplace[1] = TRUE;
-                ahChild[1]   = pWorker->StdOut.hPipeChild;
-                afReplace[2] = TRUE;
-                ahChild[2]   = pWorker->StdErr.hPipeChild;
-            }
-
-            dwErr = nt_child_inject_standard_handles(ProcInfo.hProcess, afReplace, ahChild, szErrMsg, sizeof(szErrMsg));
+        if (fHaveHandles || fCatchOutput)
+        {
+            char szErrMsg[128];
+            if (fCatchOutput)
+            {
+                if (!pafReplace[1])
+                {
+                    pafReplace[1] = TRUE;
+                    pahChild[1]   = pWorker->StdOut.hPipeChild;
+                }
+                if (!pafReplace[2])
+                {
+                    pafReplace[2] = TRUE;
+                    pahChild[2]   = pWorker->StdErr.hPipeChild;
+                }
+            }
+            dwErr = nt_child_inject_standard_handles(ProcInfo.hProcess, pafReplace, pahChild, szErrMsg, sizeof(szErrMsg));
             if (dwErr != 0)
                 fprintf(stderr, "%s\n", szErrMsg);
@@ -1094,8 +1092,76 @@
 
     /*
-     * Close unnecessary handles.
-     */
-    mkWinChildcareWorkerCloseStandardHandles(pChild);
+     * Close unnecessary handles and cache the image.
+     */
     CloseHandle(ProcInfo.hThread);
+    kmk_cache_exec_image_w(pwszImageName);
+    return 0;
+}
+
+/**
+ * Converts a argument vector that has already been quoted correctly.
+ *
+ * The argument vector is typically the result of quote_argv().
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param   papszArgs           The argument vector to convert.
+ * @param   ppwszCommandLine    Where to return the command line.
+ */
+static int mkWinChildcareWorkerConvertQuotedArgvToCommandline(char **papszArgs, WCHAR **ppwszCommandLine)
+{
+    WCHAR   *pwszCmdLine;
+    WCHAR   *pwszDst;
+
+    /*
+     * Calc length the converted length.
+     */
+    unsigned cwcNeeded = 1;
+    unsigned i = 0;
+    const char *pszSrc;
+    while ((pszSrc = papszArgs[i]) != NULL)
+    {
+        int cwcThis = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszSrc, -1, NULL, 0);
+        if (cwcThis > 0 || *pszSrc == '\0')
+            cwcNeeded += cwcThis + 1;
+        else
+        {
+            DWORD dwErr = GetLastError();
+            fprintf(stderr, _("MultiByteToWideChar failed to convert argv[%u] (%s): %u\n"), i, pszSrc, dwErr);
+            return dwErr;
+        }
+        i++;
+    }
+
+    /*
+     * Allocate and do the conversion.
+     */
+    pwszCmdLine = pwszDst = (WCHAR *)xmalloc(cwcNeeded * sizeof(WCHAR));
+    i = 0;
+    while ((pszSrc = papszArgs[i]) != NULL)
+    {
+        int cwcThis;
+        if (i > 0)
+        {
+            *pwszDst++ = ' ';
+            cwcNeeded--;
+        }
+
+        cwcThis = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszSrc, -1, pwszDst, cwcNeeded);
+        if (!cwcThis && *pszSrc != '\0')
+        {
+            DWORD dwErr = GetLastError();
+            fprintf(stderr, _("MultiByteToWideChar failed to convert argv[%u] (%s): %u\n"), i, pszSrc, dwErr);
+            free(pwszCmdLine);
+            return dwErr;
+        }
+        if (cwcThis > 0 && pwszDst[cwcThis - 1] == '\0')
+            cwcThis--;
+        pwszDst += cwcThis;
+        cwcNeeded -= cwcThis;
+        i++;
+    }
+    *pwszDst++ = '\0';
+
+    *ppwszCommandLine = pwszCmdLine;
     return 0;
 }
@@ -1707,5 +1773,4 @@
         {
             fprintf(stderr, "%s: not found!\n", pszArg0);
-//__debugbreak();
             dwErr = ERROR_FILE_NOT_FOUND;
         }
@@ -1920,5 +1985,10 @@
         if (rc == 0)
         {
-            rc = mkWinChildcareWorkerCreateProcess(pWorker, pChild, pwszImageName, pwszCommandLine, pwszzEnvironment);
+            BOOL afReplace[3] = { FALSE, pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE, pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE };
+            HANDLE ahChild[3] = { INVALID_HANDLE_VALUE, pChild->u.Process.hStdOut, pChild->u.Process.hStdErr };
+            rc = mkWinChildcareWorkerCreateProcess(pWorker, pwszImageName, pwszCommandLine, pwszzEnvironment,
+                                                   NULL /*pwszCwd*/, afReplace, ahChild, pChild->u.Process.fCatchOutput,
+                                                   &pChild->u.Process.hProcess);
+            mkWinChildcareWorkerCloseStandardHandles(pChild);
             if (rc == 0)
             {
@@ -1958,5 +2028,10 @@
 {
     PCKMKBUILTINENTRY pBuiltIn = pChild->u.BuiltIn.pBuiltIn;
-    KMKBUILTINCTX Ctx = { pBuiltIn->uName.s.sz, pChild->pMkChild ? &pChild->pMkChild->output : NULL };
+    KMKBUILTINCTX Ctx =
+    {
+        pBuiltIn->uName.s.sz,
+        pChild->pMkChild ? &pChild->pMkChild->output : NULL,
+        pWorker,
+    };
     if (pBuiltIn->uFnSignature == FN_SIG_MAIN)
         pChild->iExitCode = pBuiltIn->u.pfnMain(pChild->u.BuiltIn.cArgs, pChild->u.BuiltIn.papszArgs,
@@ -1964,5 +2039,5 @@
     else if (pBuiltIn->uFnSignature == FN_SIG_MAIN_SPAWNS)
         pChild->iExitCode = pBuiltIn->u.pfnMainSpawns(pChild->u.BuiltIn.cArgs, pChild->u.BuiltIn.papszArgs,
-                                                      pChild->u.BuiltIn.papszEnv, &Ctx, pChild->pMkChild, NULL);
+                                                      pChild->u.BuiltIn.papszEnv, &Ctx, pChild->pMkChild, NULL /*pPid*/);
     else
     {
@@ -2115,4 +2190,5 @@
                 PWINCHILD pTailExpect;
 
+                pWorker->pCurChild = pChild;
                 switch (pChild->enmType)
                 {
@@ -2137,4 +2213,5 @@
                         assert(0);
                 }
+                pWorker->pCurChild = NULL;
 
                 /*
@@ -2821,4 +2898,105 @@
 }
 
+
+/**
+ * New interface used by redirect.c for spawning and waitin on a child.
+ *
+ * This interface is only used when kmk_builtin_redirect is already running on
+ * a worker thread.
+ *
+ * @returns exit status.
+ * @param   pvWorker        The worker instance.
+ * @param   pszExecutable   The executable image to run.
+ * @param   papszArgs       Argument vector.
+ * @param   fQuotedArgv     Whether the argument vector is already quoted and
+ *                          just need some space to be turned into a command
+ *                          line.
+ * @param   papszEnvVars    Environment vector.
+ * @param   pszCwd          The working directory of the child.  Optional.
+ * @param   pafReplace      Which standard handles to replace. Maybe modified!
+ * @param   pahReplace      The replacement handles.  Maybe modified!
+ *
+ */
+int MkWinChildBuiltInExecChild(void *pvWorker, const char *pszExecutable, char **papszArgs, BOOL fQuotedArgv,
+                               char **papszEnvVars, const char *pszCwd, BOOL pafReplace[3], HANDLE pahReplace[3])
+{
+    PWINCHILDCAREWORKER pWorker = (PWINCHILDCAREWORKER)pvWorker;
+    WCHAR              *pwszSearchPath   = NULL;
+    WCHAR              *pwszzEnvironment = NULL;
+    WCHAR              *pwszCommandLine  = NULL;
+    WCHAR              *pwszImageName    = NULL;
+    WCHAR              *pwszCwd          = NULL;
+    BOOL                fNeedShell       = FALSE;
+    int                 rc;
+    assert(pWorker->uMagic == WINCHILDCAREWORKER_MAGIC);
+    assert(pWorker->pCurChild != NULL && pWorker->pCurChild->uMagic == WINCHILD_MAGIC);
+
+    /*
+     * Convert the CWD first since it's optional and we don't need to clean
+     * up anything here if it fails.
+     */
+    if (pszCwd)
+    {
+        size_t cchCwd = strlen(pszCwd);
+        int    cwcCwd = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszCwd, cchCwd + 1, NULL, 0);
+        pwszCwd = xmalloc((cwcCwd + 1) * sizeof(WCHAR)); /* (+1 in case cwcCwd is 0) */
+        cwcCwd = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszCwd, cchCwd + 1, pwszCwd, cwcCwd + 1);
+        if (!cwcCwd)
+        {
+            rc = GetLastError();
+            fprintf(stderr, _("MultiByteToWideChar failed to convert CWD (%s): %u\n"), pszCwd, (unsigned)rc);
+            return rc;
+        }
+    }
+
+    /*
+     * Before we search for the image, we convert the environment so we don't
+     * have to traverse it twice to find the PATH.
+     */
+    rc = mkWinChildcareWorkerConvertEnvironment(papszEnvVars ? papszEnvVars : environ, 0/*cbEnvStrings*/,
+                                                &pwszzEnvironment, &pwszSearchPath);
+    /*
+     * Find the executable and maybe checking if it's a shell script, then
+     * convert it to a command line.
+     */
+    if (rc == 0)
+        rc = mkWinChildcareWorkerFindImage(pszExecutable, pwszSearchPath, pwszzEnvironment,
+                                           NULL /*pszNull*/, &pwszImageName, &fNeedShell);
+    if (rc == 0)
+    {
+        assert(!fNeedShell);
+        if (!fQuotedArgv)
+            rc = mkWinChildcareWorkerConvertCommandline(papszArgs, 0 /*fFlags*/, &pwszCommandLine);
+        else
+            rc = mkWinChildcareWorkerConvertQuotedArgvToCommandline(papszArgs, &pwszCommandLine);
+
+        /*
+         * Create the child process.
+         */
+        if (rc == 0)
+        {
+            HANDLE hProcess;
+            rc = mkWinChildcareWorkerCreateProcess(pWorker, pwszImageName, pwszCommandLine, pwszzEnvironment,
+                                                   pwszCwd, pafReplace, pahReplace, TRUE /*fCatchOutput*/, &hProcess);
+            if (rc == 0)
+            {
+                /*
+                 * Wait for the child to complete.
+                 */
+                rc = mkWinChildcareWorkerWaitForProcess(pWorker, pWorker->pCurChild, hProcess, pwszImageName,
+                                                        TRUE /*fCatchOutput*/);
+                CloseHandle(hProcess);
+            }
+        }
+    }
+
+    free(pwszCwd);
+    free(pwszCommandLine);
+    free(pwszImageName);
+    free(pwszzEnvironment);
+
+    return rc;
+}
+
 #endif /* CONFIG_NEW_WIN_CHILDREN */
 
Index: /trunk/src/kmk/w32/winchildren.h
===================================================================
--- /trunk/src/kmk/w32/winchildren.h	(revision 3194)
+++ /trunk/src/kmk/w32/winchildren.h	(revision 3195)
@@ -41,4 +41,8 @@
 int     MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, pid_t *pPid);
 int     MkWinChildCreateRedirect(intptr_t hProcess, pid_t *pPid);
+# ifdef DECLARE_HANDLE
+int     MkWinChildBuiltInExecChild(void *pvWorker, const char *pszExecutable, char **papszArgs, BOOL fQuotedArgv,
+                                   char **papszEnvVars, const char *pszCwd, BOOL pafReplace[3], HANDLE pahReplace[3]);
+# endif
 #endif
 int     MkWinChildKill(pid_t pid, int iSignal, struct child *pMkChild);
