Index: /trunk/src/kWorker/kWorker.c
===================================================================
--- /trunk/src/kWorker/kWorker.c	(revision 2875)
+++ /trunk/src/kWorker/kWorker.c	(revision 2876)
@@ -195,13 +195,4 @@
     PKWDYNLOAD          pNext;
 
-    /** The normalized path to the image. */
-    const char         *pszPath;
-    /** The module name (within pszPath). */
-    const char         *pszModName;
-    /** UTF-16 version of pszPath. */
-    const wchar_t      *pwszPath;
-    /** The hash of the path. */
-    KU32                uHashPath;
-
     /** The module handle we present to the application.
      * This is the LoadLibraryEx return value for special modules and the
@@ -211,4 +202,9 @@
     /** The module for non-special resource stuff, NULL if special. */
     PKWMODULE           pMod;
+
+    /** The length of the LoadLibary filename. */
+    KSIZE               cchRequest;
+    /** The LoadLibrary filename. */
+    char                szRequest[1];
 } KWDYNLOAD;
 
@@ -381,4 +377,6 @@
         struct
         {
+            /** The main entry point. */
+            KUPTR       uMainAddr;
             /** The executable. */
             PKWMODULE   pExe;
@@ -386,4 +384,9 @@
              * These will be kept loaded till the tool is destroyed (if we ever do that). */
             PKWDYNLOAD  pDynLoadHead;
+            /** Module array sorted by hOurMod. */
+            PKWMODULE  *papModules;
+            /** Number of entries in papModules. */
+            KU32        cModules;
+
             /** Tool hint (for hacks and such). */
             KWTOOLHINT  enmHint;
@@ -1655,5 +1658,8 @@
     KSIZE const cchName = kHlpStrLen(pszName);
     char        szPath[1024];
+    char       *psz;
     PKWMODULE   pMod = NULL;
+    KBOOL       fNeedSuffix = *kHlpGetExt(pszName) == '\0' && kHlpGetFilename(pszName) == pszName;
+    KSIZE       cchSuffix   = fNeedSuffix ? 4 : 0;
 
 
@@ -1661,7 +1667,10 @@
     if (pMod == NULL && pImporter != NULL)
     {
-        if (pImporter->offFilename + cchName >= sizeof(szPath))
+        if (pImporter->offFilename + cchName + cchSuffix >= sizeof(szPath))
             return KERR_BUFFER_OVERFLOW;
-        kHlpMemCopy(kHlpMemPCopy(szPath, pImporter->pszPath, pImporter->offFilename), pszName, cchName + 1);
+
+        psz = (char *)kHlpMemPCopy(kHlpMemPCopy(szPath, pImporter->pszPath, pImporter->offFilename), pszName, cchName + 1);
+        if (fNeedSuffix)
+            kHlpMemCopy(psz - 1, ".dll", sizeof(".dll"));
         pMod = kwLdrModuleTryLoadDll(szPath, KWLOCATION_IMPORTER_DIR, pExe);
     }
@@ -1670,7 +1679,9 @@
     if (pMod == NULL && pExe != NULL && pExe != pImporter)
     {
-        if (pExe->offFilename + cchName >= sizeof(szPath))
+        if (pExe->offFilename + cchName + cchSuffix >= sizeof(szPath))
             return KERR_BUFFER_OVERFLOW;
-        kHlpMemCopy(kHlpMemPCopy(szPath, pExe->pszPath, pExe->offFilename), pszName, cchName + 1);
+        psz = (char *)kHlpMemPCopy(kHlpMemPCopy(szPath, pExe->pszPath, pExe->offFilename), pszName, cchName + 1);
+        if (fNeedSuffix)
+            kHlpMemCopy(psz - 1, ".dll", sizeof(".dll"));
         pMod = kwLdrModuleTryLoadDll(szPath, KWLOCATION_EXE_DIR, pExe);
     }
@@ -1681,8 +1692,10 @@
         UINT cchDir = GetSystemDirectoryA(szPath, sizeof(szPath));
         if (   cchDir <= 2
-            || cchDir + 1 + cchName >= sizeof(szPath))
+            || cchDir + 1 + cchName + cchSuffix >= sizeof(szPath))
             return KERR_BUFFER_OVERFLOW;
         szPath[cchDir++] = '\\';
-        kHlpMemCopy(&szPath[cchDir], pszName, cchName + 1);
+        psz = (char *)kHlpMemPCopy(&szPath[cchDir], pszName, cchName + 1);
+        if (fNeedSuffix)
+            kHlpMemCopy(psz - 1, ".dll", sizeof(".dll"));
         pMod = kwLdrModuleTryLoadDll(szPath, KWLOCATION_SYSTEM32, pExe);
     }
@@ -1769,4 +1782,188 @@
 
 
+/**
+ * Looks up a module handle for a tool.
+ *
+ * @returns Referenced loader module on success, NULL on if not found.
+ * @param   pTool               The tool.
+ * @param   hmod                The module handle.
+ */
+static PKWMODULE kwToolLocateModuleByHandle(PKWTOOL pTool, HMODULE hmod)
+{
+    KUPTR const     uHMod = (KUPTR)hmod;
+    PKWMODULE      *papMods;
+    KU32            iEnd;
+    KU32            i;
+    PKWDYNLOAD      pDynLoad;
+
+    /* The executable. */
+    if (   hmod == NULL
+        || pTool->u.Sandboxed.pExe->hOurMod == hmod)
+        return kwLdrModuleRetain(pTool->u.Sandboxed.pExe);
+
+    /*
+     * Binary lookup using the module table.
+     */
+    papMods = pTool->u.Sandboxed.papModules;
+    iEnd    = pTool->u.Sandboxed.cModules;
+    if (iEnd)
+    {
+        KU32 iStart  = 0;
+        i = iEnd / 2;
+        for (;;)
+        {
+            KUPTR const uHModThis = (KUPTR)papMods[i]->hOurMod;
+            if (uHMod < uHModThis)
+            {
+                iEnd = i--;
+                if (iStart <= i)
+                { }
+                else
+                    break;
+            }
+            else if (uHMod != uHModThis)
+            {
+                iStart = ++i;
+                if (i < iEnd)
+                { }
+                else
+                    break;
+            }
+            else
+                return kwLdrModuleRetain(papMods[i]);
+
+            i = iStart + (iEnd - iStart) / 2;
+        }
+
+#ifndef NDEBUG
+        iStart = pTool->u.Sandboxed.cModules;
+        while (--iStart > 0)
+            kHlpAssert((KUPTR)papMods[iStart]->hOurMod != uHMod);
+        kHlpAssert(i == 0 || (KUPTR)papMods[i - 1]->hOurMod < uHMod);
+        kHlpAssert(i == pTool->u.Sandboxed.cModules || (KUPTR)papMods[i]->hOurMod > uHMod);
+#endif
+    }
+
+    /*
+     * Dynamically loaded images.
+     */
+    for (pDynLoad = pTool->u.Sandboxed.pDynLoadHead; pDynLoad != NULL; pDynLoad = pDynLoad->pNext)
+        if (pDynLoad->hmod == hmod)
+        {
+            if (pDynLoad->pMod)
+                return kwLdrModuleRetain(pDynLoad->pMod);
+            KWFS_TODO();
+            return NULL;
+        }
+
+    return NULL;
+}
+
+/**
+ * Adds the given module to the tool import table.
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param   pTool               The tool.
+ * @param   pMod                The module.
+ */
+static int kwToolAddModule(PKWTOOL pTool, PKWMODULE pMod)
+{
+    /*
+     * Binary lookup. Locating the right slot for it, return if already there.
+     */
+    KUPTR const     uHMod   = (KUPTR)pMod->hOurMod;
+    PKWMODULE      *papMods = pTool->u.Sandboxed.papModules;
+    KU32            iEnd    = pTool->u.Sandboxed.cModules;
+    KU32            i;
+    if (iEnd)
+    {
+        KU32        iStart  = 0;
+        i = iEnd / 2;
+        for (;;)
+        {
+            KUPTR const uHModThis = (KUPTR)papMods[i]->hOurMod;
+            if (uHMod < uHModThis)
+            {
+                iEnd = i;
+                if (iStart < i)
+                { }
+                else
+                    break;
+            }
+            else if (uHMod != uHModThis)
+            {
+                iStart = ++i;
+                if (i < iEnd)
+                { }
+                else
+                    break;
+            }
+            else
+            {
+                /* Already there in the table. */
+                return 0;
+            }
+
+            i = iStart + (iEnd - iStart) / 2;
+        }
+#ifndef NDEBUG
+        iStart = pTool->u.Sandboxed.cModules;
+        while (--iStart > 0)
+        {
+            kHlpAssert(papMods[iStart] != pMod);
+            kHlpAssert((KUPTR)papMods[iStart]->hOurMod != uHMod);
+        }
+        kHlpAssert(i == 0 || (KUPTR)papMods[i - 1]->hOurMod < uHMod);
+        kHlpAssert(i == pTool->u.Sandboxed.cModules || (KUPTR)papMods[i]->hOurMod > uHMod);
+#endif
+    }
+    else
+        i = 0;
+
+    /*
+     * Grow the table?
+     */
+    if ((pTool->u.Sandboxed.cModules % 16) == 0)
+    {
+        void *pvNew = kHlpRealloc(papMods, sizeof(papMods[0]) * (pTool->u.Sandboxed.cModules + 16));
+        if (!pvNew)
+            return KERR_NO_MEMORY;
+        pTool->u.Sandboxed.papModules = papMods = (PKWMODULE *)pvNew;
+    }
+
+    /* Insert it. */
+    if (i != pTool->u.Sandboxed.cModules)
+        kHlpMemMove(&papMods[i + 1], &papMods[i], (pTool->u.Sandboxed.cModules - i) * sizeof(papMods[0]));
+    papMods[i] = kwLdrModuleRetain(pMod);
+    pTool->u.Sandboxed.cModules++;
+    KW_LOG(("kwToolAddModule: %u modules after adding %p=%s\n", pTool->u.Sandboxed.cModules, uHMod, pMod->pszPath));
+    return 0;
+}
+
+
+/**
+ * Adds the given module and all its imports to the
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param   pTool               The tool.
+ * @param   pMod                The module.
+ */
+static int kwToolAddModuleAndImports(PKWTOOL pTool, PKWMODULE pMod)
+{
+    int rc = kwToolAddModule(pTool, pMod);
+    if (!pMod->fNative && rc == 0)
+    {
+        KSIZE iImp = pMod->u.Manual.cImpMods;
+        while (iImp-- > 0)
+        {
+            rc = kwToolAddModuleAndImports(pTool, pMod->u.Manual.apImpMods[iImp]);
+            if (rc == 0)
+            { }
+            else
+                break;
+        }
+    }
+    return 0;
+}
 
 
@@ -1800,10 +1997,25 @@
         pTool->enmType = KWTOOLTYPE_SANDBOXED;
         pTool->u.Sandboxed.pExe = kwLdrModuleCreateNonNative(pTool->pszPath, kwStrHash(pTool->pszPath), K_TRUE /*fExe*/, NULL);
-        if (!pTool->u.Sandboxed.pExe)
+        if (pTool->u.Sandboxed.pExe)
+        {
+            int rc = kwLdrModuleQueryMainEntrypoint(pTool->u.Sandboxed.pExe, &pTool->u.Sandboxed.uMainAddr);
+            if (rc == 0)
+            {
+                if (kHlpStrICompAscii(pToolFsObj->pszName, "cl.exe") == 0)
+                    pTool->u.Sandboxed.enmHint = KWTOOLHINT_VISUAL_CPP_CL;
+                else
+                    pTool->u.Sandboxed.enmHint = KWTOOLHINT_NONE;
+                kwToolAddModuleAndImports(pTool, pTool->u.Sandboxed.pExe);
+            }
+            else
+            {
+                kwErrPrintf("Failed to get entrypoint for '%s': %u\n", pTool->pszPath, rc);
+                kwLdrModuleRelease(pTool->u.Sandboxed.pExe);
+                pTool->u.Sandboxed.pExe = NULL;
+                pTool->enmType = KWTOOLTYPE_EXEC;
+            }
+        }
+        else
             pTool->enmType = KWTOOLTYPE_EXEC;
-        else if (kHlpStrICompAscii(pToolFsObj->pszName, "cl.exe") == 0)
-            pTool->u.Sandboxed.enmHint = KWTOOLHINT_VISUAL_CPP_CL;
-        else
-            pTool->u.Sandboxed.enmHint = KWTOOLHINT_NONE;
 
         kFsCacheObjRelease(g_pFsCache, pToolFsObj);
@@ -2005,6 +2217,6 @@
  */
 
-/** ExitProcess replacement.  */
-static void WINAPI kwSandbox_Kernel32_ExitProcess(UINT uExitCode)
+/** Common worker for ExitProcess(), exit() and friends.  */
+static void WINAPI kwSandboxDoExit(int uExitCode)
 {
     if (g_Sandbox.idMainThread == GetCurrentThreadId())
@@ -2026,8 +2238,16 @@
 
 /** ExitProcess replacement.  */
+static void WINAPI kwSandbox_Kernel32_ExitProcess(UINT uExitCode)
+{
+    KW_LOG(("kwSandbox_Kernel32_ExitProcess: %u\n", uExitCode));
+    kwSandboxDoExit((int)uExitCode);
+}
+
+
+/** ExitProcess replacement.  */
 static BOOL WINAPI kwSandbox_Kernel32_TerminateProcess(HANDLE hProcess, UINT uExitCode)
 {
     if (hProcess == GetCurrentProcess())
-        kwSandbox_Kernel32_ExitProcess(uExitCode);
+        kwSandboxDoExit(uExitCode);
     KWFS_TODO();
     return TerminateProcess(hProcess, uExitCode);
@@ -2039,5 +2259,5 @@
 {
     KW_LOG(("kwSandbox_msvcrt_exit: %d\n", rcExitCode));
-    kwSandbox_Kernel32_ExitProcess(rcExitCode);
+    kwSandboxDoExit(rcExitCode);
 }
 
@@ -2048,5 +2268,5 @@
     /* Quick. */
     KW_LOG(("kwSandbox_msvcrt__exit %d\n", rcExitCode));
-    kwSandbox_Kernel32_ExitProcess(rcExitCode);
+    kwSandboxDoExit(rcExitCode);
 }
 
@@ -2056,5 +2276,5 @@
 {
     KW_LOG(("kwSandbox_msvcrt__cexit: %d\n", rcExitCode));
-    kwSandbox_Kernel32_ExitProcess(rcExitCode);
+    kwSandboxDoExit(rcExitCode);
 }
 
@@ -2064,5 +2284,5 @@
 {
     KW_LOG(("kwSandbox_msvcrt__c_exit: %d\n", rcExitCode));
-    kwSandbox_Kernel32_ExitProcess(rcExitCode);
+    kwSandboxDoExit(rcExitCode);
 }
 
@@ -2072,5 +2292,5 @@
 {
     KW_LOG(("\nRuntime error #%u!\n", iMsgNo));
-    kwSandbox_Kernel32_ExitProcess(255);
+    kwSandboxDoExit(255);
 }
 
@@ -2080,5 +2300,5 @@
 {
     KW_LOG(("\nRuntime - terminate!\n"));
-    kwSandbox_Kernel32_ExitProcess(254);
+    kwSandboxDoExit(254);
 }
 
@@ -2408,71 +2628,41 @@
  * Kernel32 - LoadLibraryExA() worker that loads resource files and such.
  */
-static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExA_Resource(LPCSTR pszFilename, HANDLE hFile, DWORD fFlags)
+static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExA_Resource(PKWDYNLOAD pDynLoad, DWORD fFlags)
+{
+    /* Load it first. */
+    HMODULE hmod = LoadLibraryExA(pDynLoad->szRequest, NULL /*hFile*/, fFlags);
+    if (hmod)
+    {
+        pDynLoad->hmod = hmod;
+        pDynLoad->pMod = NULL; /* indicates special  */
+
+        pDynLoad->pNext = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead;
+        g_Sandbox.pTool->u.Sandboxed.pDynLoadHead = pDynLoad;
+        KW_LOG(("LoadLibraryExA(%s,,[resource]) -> %p\n", pDynLoad->szRequest, pDynLoad->hmod));
+    }
+    else
+        kHlpFree(pDynLoad);
+    return hmod;
+}
+
+
+/**
+ * Kernel32 - LoadLibraryExA() worker that deals with the api-ms-xxx modules.
+ */
+static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExA_VirtualApiModule(PKWDYNLOAD pDynLoad, DWORD fFlags)
 {
     HMODULE     hmod;
-    PKWDYNLOAD  pDynLoad;
+    PKWMODULE   pMod;
     KU32        uHashPath;
-    char        szNormPath[4096];
-
-    /* Normalize the path. */
-    int rc = kwPathNormalize(pszFilename, szNormPath, sizeof(szNormPath));
-    if (rc != 0)
-    {
-        KWFS_TODO();
-        return LoadLibraryExA(pszFilename, hFile, fFlags);
-    }
-
-    /* Try look it up. */
-    uHashPath = kwStrHash(szNormPath);
-    for (pDynLoad = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead; pDynLoad != NULL; pDynLoad = pDynLoad->pNext)
-        if (   pDynLoad->uHashPath == uHashPath
-            && kHlpStrComp(pDynLoad->pszPath, szNormPath) == 0)
-        {
-            if (pDynLoad->pMod == NULL)
-                return pDynLoad->hmod;
-            KWFS_TODO();
-        }
-
-    /* Then try load it. */
-    hmod = LoadLibraryExA(szNormPath, hFile, fFlags);
-    if (hmod)
-    {
-        KSIZE cbNormPath = kHlpStrLen(szNormPath) + 1;
-        pDynLoad = (PKWDYNLOAD)kHlpAlloc(sizeof(*pDynLoad) + cbNormPath + cbNormPath * 2 * sizeof(wchar_t));
-        if (pDynLoad)
-        {
-            pDynLoad->pszPath           = (char *)kHlpMemCopy(pDynLoad + 1, szNormPath, cbNormPath);
-            pDynLoad->pwszPath          = (wchar_t *)(pDynLoad->pszPath + cbNormPath + (cbNormPath & 1));
-            kwStrToUtf16(pDynLoad->pszPath, (wchar_t *)pDynLoad->pwszPath, cbNormPath * 2);
-            pDynLoad->pszModName        = kHlpGetFilename(pDynLoad->pszPath);
-            pDynLoad->uHashPath         = uHashPath;
-            pDynLoad->pMod              = NULL; /* indicates special  */
-            pDynLoad->hmod              = hmod;
-
-            pDynLoad->pNext = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead;
-            g_Sandbox.pTool->u.Sandboxed.pDynLoadHead = pDynLoad;
-        }
-        else
-            KWFS_TODO();
-    }
-    return hmod;
-}
-
-
-/**
- * Kernel32 - LoadLibraryExA() worker that deals with the api-ms-xxx modules.
- */
-static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExA_VirtualApiModule(LPCSTR pszFilename, HANDLE hFile, DWORD fFlags)
-{
-    HMODULE     hmod;
-    PKWDYNLOAD  pDynLoad;
-    KU32        uHashPath;
+    KSIZE       idxHash;
     char        szNormPath[256];
-    KSIZE       cbFilename = kHlpStrLen(pszFilename) + 1;
-
-    /* Lower case it. */
+    KSIZE       cbFilename = kHlpStrLen(pDynLoad->szRequest) + 1;
+
+    /*
+     * Lower case it.
+     */
     if (cbFilename <= sizeof(szNormPath))
     {
-        kHlpMemCopy(szNormPath, pszFilename, cbFilename);
+        kHlpMemCopy(szNormPath, pDynLoad->szRequest, cbFilename);
         _strlwr(szNormPath);
     }
@@ -2483,17 +2673,35 @@
     }
 
-    /* Try look it up. */
+    /*
+     * Check if it has already been loaded so we don't create an unnecessary
+     * loader module for it.
+     */
     uHashPath = kwStrHash(szNormPath);
-    for (pDynLoad = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead; pDynLoad != NULL; pDynLoad = pDynLoad->pNext)
-        if (   pDynLoad->uHashPath == uHashPath
-            && kHlpStrComp(pDynLoad->pszPath, szNormPath) == 0)
-        {
-            if (pDynLoad->pMod != NULL)
+    idxHash   = uHashPath % K_ELEMENTS(g_apModules);
+    pMod      = g_apModules[idxHash];
+    if (pMod)
+    {
+        do
+        {
+            if (   pMod->uHashPath == uHashPath
+                && kHlpStrComp(pMod->pszPath, szNormPath) == 0)
+            {
+                pDynLoad->pMod = kwLdrModuleRetain(pMod);
+                pDynLoad->hmod = pMod->hOurMod;
+
+                pDynLoad->pNext = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead;
+                g_Sandbox.pTool->u.Sandboxed.pDynLoadHead = pDynLoad;
+                KW_LOG(("LoadLibraryExA(%s,,) -> %p [already loaded]\n", pDynLoad->szRequest, pDynLoad->hmod));
                 return pDynLoad->hmod;
-            KWFS_TODO();
-        }
-
-    /* Then try load it and make a kLdr module for it. */
-    hmod = LoadLibraryExA(szNormPath, hFile, fFlags);
+            }
+            pMod = pMod->pNext;
+        } while (pMod);
+    }
+
+
+    /*
+     * Try load it and make a kLdr module for it.
+     */
+    hmod = LoadLibraryExA(szNormPath, NULL /*hFile*/, fFlags);
     if (hmod)
     {
@@ -2506,17 +2714,15 @@
             if (pMod)
             {
+                kwToolAddModuleAndImports(g_Sandbox.pTool, pMod);
+
                 pDynLoad = (PKWDYNLOAD)kHlpAlloc(sizeof(*pDynLoad) + cbFilename + cbFilename * sizeof(wchar_t));
                 if (pDynLoad)
                 {
-                    pDynLoad->pwszPath      = (wchar_t *)(pDynLoad + 1);
-                    kwStrToUtf16(szNormPath, (wchar_t *)pDynLoad->pwszPath, cbFilename);
-                    pDynLoad->pszPath       = (char *)kHlpMemCopy((char *)&pDynLoad->pwszPath[cbFilename], szNormPath, cbFilename);
-                    pDynLoad->pszModName    = pDynLoad->pszPath;
-                    pDynLoad->uHashPath     = uHashPath;
-                    pDynLoad->pMod          = pMod;
-                    pDynLoad->hmod          = hmod;
+                    pDynLoad->pMod = pMod;
+                    pDynLoad->hmod = hmod;
 
                     pDynLoad->pNext = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead;
                     g_Sandbox.pTool->u.Sandboxed.pDynLoadHead = pDynLoad;
+                    KW_LOG(("LoadLibraryExA(%s,,) -> %p\n", pDynLoad->szRequest, pDynLoad->hmod));
                     return hmod;
                 }
@@ -2530,4 +2736,5 @@
             KWFS_TODO();
     }
+    kHlpFree(pDynLoad);
     return hmod;
 }
@@ -2537,13 +2744,55 @@
 static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExA(LPCSTR pszFilename, HANDLE hFile, DWORD fFlags)
 {
+    KSIZE       cchFilename = kHlpStrLen(pszFilename);
     PKWDYNLOAD  pDynLoad;
     PKWMODULE   pMod;
     int         rc;
 
-    if (   (fFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)
-        || (hFile != NULL && hFile != INVALID_HANDLE_VALUE) )
+    /*
+     * Deal with a couple of extremely unlikely special cases right away.
+     */
+    if (   !(fFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)
+        && (hFile == NULL || hFile == INVALID_HANDLE_VALUE) )
+    { /* likely */ }
+    else
     {
         KWFS_TODO();
         return LoadLibraryExA(pszFilename, hFile, fFlags);
+    }
+
+    /*
+     * Check if we've already got a dynload entry for this one.
+     */
+    for (pDynLoad = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead; pDynLoad; pDynLoad = pDynLoad->pNext)
+        if (   pDynLoad->cchRequest == cchFilename
+            && kHlpMemComp(pDynLoad->szRequest, pszFilename, cchFilename) == 0)
+        {
+            if (pDynLoad->pMod)
+                rc = kwLdrModuleInitTree(pDynLoad->pMod);
+            else
+                rc = 0;
+            if (rc == 0)
+            {
+                KW_LOG(("LoadLibraryExA(%s,,) -> %p [cached]\n", pszFilename, pDynLoad->hmod));
+                return pDynLoad->hmod;
+            }
+            SetLastError(ERROR_DLL_INIT_FAILED);
+            return NULL;
+        }
+
+    /*
+     * Allocate a dynload entry for the request.
+     */
+    pDynLoad = (PKWDYNLOAD)kHlpAlloc(sizeof(*pDynLoad) + cchFilename + 1);
+    if (pDynLoad)
+    {
+        pDynLoad->cchRequest = cchFilename;
+        kHlpMemCopy(pDynLoad->szRequest, pszFilename, cchFilename + 1);
+    }
+    else
+    {
+        KW_LOG(("LoadLibraryExA: Out of memory!\n"));
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return NULL;
     }
 
@@ -2554,14 +2803,12 @@
                   | LOAD_LIBRARY_AS_DATAFILE
                   | LOAD_LIBRARY_AS_IMAGE_RESOURCE) )
-    {
-        /* currently, only deal with those that has a path. */
-        if (kHlpIsFilenameOnly(pszFilename))
-        {
-            KWFS_TODO();
-            return LoadLibraryExA(pszFilename, hFile, fFlags);
-        }
-
-        return kwSandbox_Kernel32_LoadLibraryExA_Resource(pszFilename, hFile, fFlags);
-    }
+        return kwSandbox_Kernel32_LoadLibraryExA_Resource(pDynLoad, fFlags);
+
+    /*
+     * Special case: api-ms-win-core-synch-l1-2-0 and friends (32-bit yasm, built with VS2015).
+     */
+    if (   strnicmp(pszFilename, TUPLE("api-ms-")) == 0
+        && kHlpIsFilenameOnly(pszFilename))
+        return kwSandbox_Kernel32_LoadLibraryExA_VirtualApiModule(pDynLoad, fFlags);
 
     /*
@@ -2571,50 +2818,40 @@
     if (!kHlpIsFilenameOnly(pszFilename))
         pMod = kwLdrModuleTryLoadDll(pszFilename, KWLOCATION_UNKNOWN, g_Sandbox.pTool->u.Sandboxed.pExe);
-    /* Special case: api-ms-win-core-synch-l1-2-0 and friends (32-bit yasm, built with VS2015). */
-    else if (strnicmp(pszFilename, TUPLE("api-ms-")) == 0)
-        return kwSandbox_Kernel32_LoadLibraryExA_VirtualApiModule(pszFilename, hFile, fFlags);
     else
     {
-        KWFS_TODO();
         rc = kwLdrModuleResolveAndLookup(pszFilename, g_Sandbox.pTool->u.Sandboxed.pExe, NULL /*pImporter*/, &pMod);
         if (rc != 0)
             pMod = NULL;
     }
-    if (!pMod)
+    if (pMod)
+    {
+        /* Enter it into the tool module table and dynamic link request cache. */
+        kwToolAddModuleAndImports(g_Sandbox.pTool, pMod);
+
+        pDynLoad->pMod = pMod;
+        pDynLoad->hmod = pMod->hOurMod;
+
+        pDynLoad->pNext = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead;
+        g_Sandbox.pTool->u.Sandboxed.pDynLoadHead = pDynLoad;
+
+        /*
+         * Make sure it's initialized (need to link it first since DllMain may
+         * use loader APIs).
+         */
+        rc = kwLdrModuleInitTree(pMod);
+        if (rc == 0)
+        {
+            KW_LOG(("LoadLibraryExA(%s,,) -> %p\n", pszFilename, pDynLoad->hmod));
+            return pDynLoad->hmod;
+        }
+
+        SetLastError(ERROR_DLL_INIT_FAILED);
+    }
+    else
     {
         KWFS_TODO();
+        kHlpFree(pDynLoad);
         SetLastError(ERROR_MOD_NOT_FOUND);
-        return NULL;
-    }
-
-    /*
-     * Make sure it's initialized.
-     */
-    rc = kwLdrModuleInitTree(pMod);
-    if (rc == 0)
-    {
-        /*
-         * Create an dynamic loading entry for it.
-         */
-        pDynLoad = (PKWDYNLOAD)kHlpAlloc(sizeof(*pDynLoad));
-        if (pDynLoad)
-        {
-            pDynLoad->pszPath           = pMod->pszPath;
-            pDynLoad->pwszPath          = pMod->pwszPath;
-            pDynLoad->pszModName        = kHlpGetFilename(pDynLoad->pszPath);
-            pDynLoad->uHashPath         = pMod->uHashPath;
-            pDynLoad->pMod              = pMod;
-            pDynLoad->hmod              = pMod->hOurMod;
-
-            pDynLoad->pNext = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead;
-            g_Sandbox.pTool->u.Sandboxed.pDynLoadHead = pDynLoad;
-
-            return pDynLoad->hmod;
-        }
-    }
-
-    KWFS_TODO();
-    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-    kwLdrModuleRelease(pMod);
+    }
     return NULL;
 }
@@ -2722,27 +2959,4 @@
 
 
-static PKWMODULE kwSandboxLocateModuleByHandle(PKWSANDBOX pSandbox, HMODULE hmod)
-{
-    PKWDYNLOAD pDynLoad;
-
-    /* The executable. */
-    if (   hmod == NULL
-        || pSandbox->pTool->u.Sandboxed.pExe->hOurMod == hmod)
-        return kwLdrModuleRetain(pSandbox->pTool->u.Sandboxed.pExe);
-
-    /* Dynamically loaded images. */
-    for (pDynLoad = pSandbox->pTool->u.Sandboxed.pDynLoadHead; pDynLoad != NULL; pDynLoad = pDynLoad->pNext)
-        if (pDynLoad->hmod == hmod)
-        {
-            if (pDynLoad->pMod)
-                return kwLdrModuleRetain(pDynLoad->pMod);
-            KWFS_TODO();
-            return NULL;
-        }
-
-    return NULL;
-}
-
-
 /** Used to debug dynamically resolved procedures. */
 static UINT WINAPI kwSandbox_BreakIntoDebugger(void *pv1, void *pv2, void *pv3, void *pv4)
@@ -2761,5 +2975,5 @@
      * Try locate the module.
      */
-    PKWMODULE pMod = kwSandboxLocateModuleByHandle(&g_Sandbox, hmod);
+    PKWMODULE pMod = kwToolLocateModuleByHandle(g_Sandbox.pTool, hmod);
     if (pMod)
     {
@@ -2807,5 +3021,5 @@
 static DWORD WINAPI kwSandbox_Kernel32_GetModuleFileNameA(HMODULE hmod, LPSTR pszFilename, DWORD cbFilename)
 {
-    PKWMODULE pMod = kwSandboxLocateModuleByHandle(&g_Sandbox, hmod);
+    PKWMODULE pMod = kwToolLocateModuleByHandle(g_Sandbox.pTool, hmod);
     if (pMod != NULL)
     {
@@ -2822,5 +3036,5 @@
 static DWORD WINAPI kwSandbox_Kernel32_GetModuleFileNameW(HMODULE hmod, LPWSTR pwszFilename, DWORD cbFilename)
 {
-    PKWMODULE pMod = kwSandboxLocateModuleByHandle(&g_Sandbox, hmod);
+    PKWMODULE pMod = kwToolLocateModuleByHandle(g_Sandbox.pTool, hmod);
     if (pMod)
     {
@@ -5100,65 +5314,58 @@
              * Call the main function.
              */
-            KUPTR uAddrMain;
-            rc = kwLdrModuleQueryMainEntrypoint(pTool->u.Sandboxed.pExe, &uAddrMain);
-            if (rc == 0)
-            {
 #if K_ARCH == K_ARCH_AMD64
-                int (*pfnWin64Entrypoint)(void *pvPeb, void *, void *, void *);
+            int (*pfnWin64Entrypoint)(void *pvPeb, void *, void *, void *);
 #elif K_ARCH == K_ARCH_X86_32
-                int (__cdecl *pfnWin32Entrypoint)(void *pvPeb);
+            int (__cdecl *pfnWin32Entrypoint)(void *pvPeb);
 #else
 # error "Port me!"
 #endif
 
-                /* Save the NT TIB first (should do that here, not in some other function). */
-                PNT_TIB pTib = (PNT_TIB)NtCurrentTeb();
-                pSandbox->TibMainThread = *pTib;
-
-                /* Make the call in a guarded fashion. */
+            /* Save the NT TIB first (should do that here, not in some other function). */
+            PNT_TIB pTib = (PNT_TIB)NtCurrentTeb();
+            pSandbox->TibMainThread = *pTib;
+
+            /* Make the call in a guarded fashion. */
 #if K_ARCH == K_ARCH_AMD64
-                /* AMD64 */
-                *(KUPTR *)&pfnWin64Entrypoint = uAddrMain;
-                __try
+            /* AMD64 */
+            *(KUPTR *)&pfnWin64Entrypoint = pTool->u.Sandboxed.uMainAddr;
+            __try
+            {
+                pSandbox->pOutXcptListHead = pTib->ExceptionList;
+                if (setjmp(pSandbox->JmpBuf) == 0)
                 {
-                    pSandbox->pOutXcptListHead = pTib->ExceptionList;
-                    if (setjmp(pSandbox->JmpBuf) == 0)
-                    {
-                        *(KU64*)(pSandbox->JmpBuf) = 0; /** @todo find other way to prevent longjmp from doing unwind! */
-                        pSandbox->fRunning = K_TRUE;
-                        rcExit = pfnWin64Entrypoint(kwSandboxGetProcessEnvironmentBlock(), NULL, NULL, NULL);
-                        pSandbox->fRunning = K_FALSE;
-                    }
-                    else
-                        rcExit = pSandbox->rcExitCode;
+                    *(KU64*)(pSandbox->JmpBuf) = 0; /** @todo find other way to prevent longjmp from doing unwind! */
+                    pSandbox->fRunning = K_TRUE;
+                    rcExit = pfnWin64Entrypoint(kwSandboxGetProcessEnvironmentBlock(), NULL, NULL, NULL);
+                    pSandbox->fRunning = K_FALSE;
                 }
+                else
+                    rcExit = pSandbox->rcExitCode;
+            }
 #elif K_ARCH == K_ARCH_X86_32
-                /* x86 (see _tmainCRTStartup) */
-                *(KUPTR *)&pfnWin32Entrypoint = uAddrMain;
-                __try
+            /* x86 (see _tmainCRTStartup) */
+            *(KUPTR *)&pfnWin32Entrypoint = pTool->u.Sandboxed.uMainAddr;
+            __try
+            {
+                pSandbox->pOutXcptListHead = pTib->ExceptionList;
+                if (setjmp(pSandbox->JmpBuf) == 0)
                 {
-                    pSandbox->pOutXcptListHead = pTib->ExceptionList;
-                    if (setjmp(pSandbox->JmpBuf) == 0)
-                    {
-                        //*(KU64*)(pSandbox->JmpBuf) = 0; /** @todo find other way to prevent longjmp from doing unwind! */
-                        pSandbox->fRunning = K_TRUE;
-                        rcExit = pfnWin32Entrypoint(kwSandboxGetProcessEnvironmentBlock());
-                        pSandbox->fRunning = K_FALSE;
-                    }
-                    else
-                        rcExit = pSandbox->rcExitCode;
+                    //*(KU64*)(pSandbox->JmpBuf) = 0; /** @todo find other way to prevent longjmp from doing unwind! */
+                    pSandbox->fRunning = K_TRUE;
+                    rcExit = pfnWin32Entrypoint(kwSandboxGetProcessEnvironmentBlock());
+                    pSandbox->fRunning = K_FALSE;
                 }
+                else
+                    rcExit = pSandbox->rcExitCode;
+            }
 #endif
-                __except (EXCEPTION_EXECUTE_HANDLER)
-                {
-                    rcExit = 512;
-                }
-                pSandbox->fRunning = K_FALSE;
-
-                /* Now, restore the NT TIB. */
-                *pTib = pSandbox->TibMainThread;
-            }
-            else
-                rcExit = 42 + 5;
+            __except (EXCEPTION_EXECUTE_HANDLER)
+            {
+                rcExit = 512;
+            }
+            pSandbox->fRunning = K_FALSE;
+
+            /* Now, restore the NT TIB. */
+            *pTib = pSandbox->TibMainThread;
         }
         else
@@ -5331,5 +5538,5 @@
 
                     /* Environment variable count. */
-                    if (sizeof(KU32) < cbMsg)
+                    if (cbMsg > sizeof(KU32))
                     {
                         KU32    cEnvVars;
@@ -5354,18 +5561,15 @@
                                     else
                                     {
-                                        if (   cbTmp == cbMsg
-                                            && i + 1 == cEnvVars)
-                                            cbMsg = 0;
-                                        else
-                                            cbMsg = KSIZE_MAX;
+                                        cbMsg = 0;
                                         break;
                                     }
                                 }
                                 papszEnvVars[cEnvVars] = 0;
-                                if (cbMsg != KSIZE_MAX)
+                                if (cbMsg >= sizeof(KU8))
                                 {
+                                    KBOOL fWatcomBrainDamange = *pszMsg++;
+                                    cbMsg--;
                                     if (cbMsg == 0)
                                     {
-                                        KBOOL fWatcomBrainDamange = K_FALSE; /** @todo fix fWatcomBrainDamange */
                                         /*
                                          * The next step.
@@ -5504,4 +5708,5 @@
     const char *pszCwd = getcwd(szCwd, sizeof(szCwd));
     KU32        cEnvVars;
+    KBOOL       fWatcomBrainDamange = K_FALSE;
 
     /*
@@ -5529,4 +5734,13 @@
         }
 
+        /* Optional watcom flag directory change. */
+        if (   i < argc
+            && (   strcmp(argv[i], "--wcc-brain-damage") == 0
+                || strcmp(argv[i], "--watcom-brain-damage") == 0) )
+        {
+            fWatcomBrainDamange = K_TRUE;
+            i++;
+        }
+
         /* Check for '--'. */
         if (i >= argc)
@@ -5554,6 +5768,7 @@
     {
         rcExit = kSubmitHandleJobUnpacked(argv[i], pszCwd,
-                                          argc - i, &argv[i], K_FALSE /* fWatcomBrainDamange*/,
+                                          argc - i, &argv[i], fWatcomBrainDamange,
                                           cEnvVars, environ);
+        KW_LOG(("rcExit=%d\n", rcExit));
     }
 
Index: /trunk/src/kmk/kmkbuiltin/kSubmit.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin/kSubmit.c	(revision 2875)
+++ /trunk/src/kmk/kmkbuiltin/kSubmit.c	(revision 2876)
@@ -569,12 +569,13 @@
  *
  * @returns Pointer to the message.
- * @param   pszExecutable   The executable to run.
- * @param   papszArgs       The argument vector.
- * @param   papszEnvVars    The environment vector.
- * @param   pszCwd          The current directory.
- * @param   pcbMsg          Where to return the message length.
+ * @param   pszExecutable       The executable to run.
+ * @param   papszArgs           The argument vector.
+ * @param   papszEnvVars        The environment vector.
+ * @param   pszCwd              The current directory.
+ * @param   fWatcomBrainDamage  The wcc/wcc386 workaround.
+ * @param   pcbMsg              Where to return the message length.
  */
 static void *kSubmitComposeJobMessage(const char *pszExecutable, char **papszArgs, char **papszEnvVars,
-                                      const char *pszCwd, uint32_t *pcbMsg)
+                                      const char *pszCwd, int fWatcomBrainDamage, uint32_t *pcbMsg)
 {
     size_t   cbTmp;
@@ -610,4 +611,5 @@
     cEnvVars = i;
 
+    cbMsg += 1;
 
     /*
@@ -649,4 +651,6 @@
     }
     assert(i == cEnvVars);
+
+    *pbCursor++ = fWatcomBrainDamage != 0;
 
     assert(pbCursor - pbMsg == (size_t)cbMsg);
@@ -1544,5 +1548,6 @@
     {
         uint32_t        cbMsg;
-        void           *pvMsg   = kSubmitComposeJobMessage(pszExecutable, &argv[iArg], papszEnv, szCwd, &cbMsg);
+        void           *pvMsg   = kSubmitComposeJobMessage(pszExecutable, &argv[iArg], papszEnv, szCwd,
+                                                           fWatcomBrainDamage, &cbMsg);
         PWORKERINSTANCE pWorker = kSubmitSelectWorkSpawnNewIfNecessary(cBitsWorker, cVerbosity);
         if (pWorker)
