Index: trunk/src/emx/include/emx/startup.h
===================================================================
--- trunk/src/emx/include/emx/startup.h	(revision 1675)
+++ trunk/src/emx/include/emx/startup.h	(revision 1676)
@@ -8,8 +8,29 @@
 #endif
 
-extern int  _CRT_init (void);
-extern void _CRT_term (void);
-extern void __ctordtorInit (void);
-extern void __ctordtorTerm (void);
+extern int  _CRT_init(void);
+extern void _CRT_term(void);
+extern void __ctordtorInit(void);
+extern void __ctordtorTerm(void);
+
+extern void __ctordtorInit1(int *);
+extern void __ctordtorTerm1(int *);
+
+/** init and term vectors.
+ * @{
+ */
+/** Array of CRT init functions. */
+extern int __crtinit1__;
+/** Array of CRT exit functions. */
+extern int __crtexit1__;
+/** Array of exception handlers something. */
+extern int __eh_init__;
+/** Array of exception handlers something. */
+extern int __eh_term__;
+/** Array of constructors. */
+extern int __CTOR_LIST__;
+/** Array of destructors. */
+extern int __DTOR_LIST__;
+/** @} */
+
 
 /* argv[i][-1] contains some flag bits: */
Index: trunk/src/emx/include/os2emx.h
===================================================================
--- trunk/src/emx/include/os2emx.h	(revision 1675)
+++ trunk/src/emx/include/os2emx.h	(revision 1676)
@@ -13529,4 +13529,16 @@
 APIRET APIENTRY DosCloseEventSemEx(HEV hev);
 
+/**
+ * Extended DosLoadModule() which will make sure the loaded module is
+ * loaded in a forked process.
+ */
+APIRET APIENTRY DosLoadModuleEx(PSZ pszObject, ULONG cbObject, PCSZ pszModule, PHMODULE phmod);
+
+/**
+ * Free module loaded using the extended APIs.
+ */
+APIRET APIENTRY DosFreeModuleEx(HMODULE hmod);
+
+
 #ifdef INCL_EXAPIS_MAPPINGS
 
@@ -13542,4 +13554,7 @@
 #define DosCloseEventSem(a)        DosCloseEventSemEx((a))
 
+#define DosLoadModule(a,b,c,d)     DosLoadModuleEx(a,b,c,d)
+#define DosFreeModule(a)           DosFreeModuleEx(a)
+
 #endif /* INCL_EXAPIS_MAPPINGS */
 
Index: trunk/src/emx/include/sys/fmutex.h
===================================================================
--- trunk/src/emx/include/sys/fmutex.h	(revision 1675)
+++ trunk/src/emx/include/sys/fmutex.h	(revision 1676)
@@ -100,4 +100,15 @@
 }
 
+/**
+ * Release a semaphore in the child process after the
+ * semaphore was locked for the forking the parent.
+ *
+ * @param   pSem    Semaphore to unlock.
+ */
+static __inline__ void _fmutex_release_fork(_fmutex *pSem)
+{
+    pSem->fs = _FMS_AVAILABLE;
+    pSem->Owner = 0;
+}
 
 unsigned _fmutex_create (_fmutex *, unsigned);
Index: trunk/src/emx/src/lib/libc.def
===================================================================
--- trunk/src/emx/src/lib/libc.def	(revision 1675)
+++ trunk/src/emx/src/lib/libc.def	(revision 1676)
@@ -1273,2 +1273,4 @@
     "_warnc" @1291
     ; new stuff
+    "DosLoadModuleEx" @1292
+    "DosFreeModuleEx" @1293
Index: trunk/src/emx/src/lib/malloc/initr.c
===================================================================
--- trunk/src/emx/src/lib/malloc/initr.c	(revision 1675)
+++ trunk/src/emx/src/lib/malloc/initr.c	(revision 1676)
@@ -167,9 +167,9 @@
         LIBCLOG_MSG("Unlocking the heaps.\n");
         if (_um_tiled_heap)
-            _um_heap_unlock(_um_tiled_heap);
+            _fmutex_release_fork(&_um_tiled_heap->fsem);
         if (_um_high_heap)
-            _um_heap_unlock(_um_high_heap);
+            _fmutex_release_fork(&_um_high_heap->fsem);
         if (_um_low_heap)
-            _um_heap_unlock(_um_low_heap);
+            _fmutex_release_fork(&_um_low_heap->fsem);
         gfForkCleanupDone = 1;
     }
Index: trunk/src/emx/src/lib/startup/cleanup.c
===================================================================
--- trunk/src/emx/src/lib/startup/cleanup.c	(revision 1675)
+++ trunk/src/emx/src/lib/startup/cleanup.c	(revision 1676)
@@ -2,8 +2,5 @@
 
 #include <stdio.h>
-#include <emx\startup.h>
-
-extern int __crtexit1__;
-extern void __ctordtorTerm1 (int *ptr);
+#include <emx/startup.h>
 
 void _CRT_term (void)
Index: trunk/src/emx/src/lib/startup/ctor1.c
===================================================================
--- trunk/src/emx/src/lib/startup/ctor1.c	(revision 1675)
+++ trunk/src/emx/src/lib/startup/ctor1.c	(revision 1676)
@@ -2,6 +2,6 @@
 
 #include <stdlib.h>
+#include <emx/startup.h>
 
-void __ctordtorInit1 (int *ptr);
 void __ctordtorInit1 (int *ptr)
 {
Index: trunk/src/emx/src/lib/startup/startup.c
===================================================================
--- trunk/src/emx/src/lib/startup/startup.c	(revision 1675)
+++ trunk/src/emx/src/lib/startup/startup.c	(revision 1676)
@@ -11,7 +11,4 @@
 #define __LIBC_LOG_GROUP    __LIBC_LOG_GRP_INITTERM
 #include <InnoTekLIBC/logstrict.h>
-
-extern int __crtinit1__;
-extern void __ctordtorInit1 (int *ptr);
 
 
Index: trunk/src/emx/src/lib/sys/DosEx.c
===================================================================
--- trunk/src/emx/src/lib/sys/DosEx.c	(revision 1675)
+++ trunk/src/emx/src/lib/sys/DosEx.c	(revision 1676)
@@ -158,4 +158,5 @@
 static int  dosexForkPreEventCreate(PDOSEX pEntry);
 static int  dosexForkPreEventOpen(PDOSEX pEntry);
+static int  dosexForkPreLoadModule(PDOSEX pEntry);
 static int  dosexForkChild(__LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKOP enmOperation);
 static void dosexForkCleanup(void *pvArg, int rc, __LIBC_FORKCTX enmCtx);
@@ -192,5 +193,5 @@
  * @returns OS/2 error code on failure.
  */
-int  dosexRequestMutex(void)
+static int  dosexRequestMutex(void)
 {
     LIBCLOG_ENTER("\n");
@@ -227,5 +228,5 @@
  * Release mutex succesfully obtained by dosexRequestMutex().
  */
-void dosexReleaseMutex(void)
+static void dosexReleaseMutex(void)
 {
     LIBCLOG_ENTER("\n");
@@ -255,5 +256,5 @@
  * @remark  Caller owns mutex.
  */
-int dosexAllocPool(void)
+static int dosexAllocPool(void)
 {
     LIBCLOG_ENTER("\n");
@@ -495,5 +496,5 @@
  *
  */
-int dosexFreeEntry(DOSEXTYPE enmType, PDOSEX pCur, PDOSEX pPrev, PDOSEXHDR pPool)
+static int dosexFreeEntry(DOSEXTYPE enmType, PDOSEX pCur, PDOSEX pPrev, PDOSEXHDR pPool)
 {
     int         rc;
@@ -550,4 +551,16 @@
             break;
 
+        case DOSEX_TYPE_LOAD_MODULE:
+            rc = DosFreeModule(pCur->u.LoadModule.hmte);
+            if (rc && rc != ERROR_INVALID_HANDLE)
+                fUnlink = 0;
+            else
+            {
+                pCur->u.LoadModule.cLoads--;
+                if (pCur->u.LoadModule.cLoads > 0)
+                    fUnlink = 0;
+            }
+            break;
+
         default:
             rc = ERROR_INVALID_PARAMETER;
@@ -714,5 +727,5 @@
  * @param   pForkHandle     Pointer to the fork handle.
  */
-int     dosexForkOpExecParent(__LIBC_PFORKHANDLE pForkHandle)
+static int     dosexForkOpExecParent(__LIBC_PFORKHANDLE pForkHandle)
 {
     LIBCLOG_ENTER("pForkHandle=%p\n", (void *)pForkHandle);
@@ -833,5 +846,5 @@
  * @param   pForkHandle     Pointer to the fork handle.
  */
-int  dosexForkOpForkParent(__LIBC_PFORKHANDLE pForkHandle)
+static int  dosexForkOpForkParent(__LIBC_PFORKHANDLE pForkHandle)
 {
     LIBCLOG_ENTER("pForkHandle=%p\n", (void *)pForkHandle);
@@ -885,5 +898,5 @@
  * @param   cbArg           sizeof(DOSEXFORKCHILDALLOC).
  */
-int dosexForkChildAlloc(__LIBC_PFORKHANDLE pForkHandle, void *pvArg, size_t cbArg)
+static int dosexForkChildAlloc(__LIBC_PFORKHANDLE pForkHandle, void *pvArg, size_t cbArg)
 {
     LIBCLOG_ENTER("pForkHandle=%p pvArg=%p cbArg=%d\n", (void *)pForkHandle, pvArg, cbArg);
@@ -912,5 +925,5 @@
  * @param   cbArg           sizeof(PDOSEXHDR).
  */
-int dosexForkChildProcess(__LIBC_PFORKHANDLE pForkHandle, void *pvArg, size_t cbArg)
+static int dosexForkChildProcess(__LIBC_PFORKHANDLE pForkHandle, void *pvArg, size_t cbArg)
 {
     LIBCLOG_ENTER("pForkHandle=%p pvArg=%p:{%p} cbArg=%d\n", (void *)pForkHandle, pvArg, *(void **)pvArg, cbArg);
@@ -961,4 +974,10 @@
         if (rc)
             break;
+
+        /* Module loading. */
+        for (pEntry = pPool->apHeads[DOSEX_TYPE_LOAD_MODULE];   !rc && pEntry; pEntry = pEntry->pNext)
+            rc = dosexForkPreLoadModule(pEntry);
+        if (rc)
+            break;
     }
 
@@ -967,5 +986,5 @@
 
 /**
- * Allocates the memory described in the entry.
+ * Allocates the memory object described in the entry.
  *
  * @returns 0 on success.
@@ -973,5 +992,5 @@
  * @param   pEntry  Entry containing a memory allocation.
  */
-int dosexForkPreMemAlloc(PDOSEX pEntry)
+static int dosexForkPreMemAlloc(PDOSEX pEntry)
 {
     int rc;
@@ -986,5 +1005,5 @@
 
 /**
- * Allocates the memory described in the entry.
+ * Allocates the memory object described in the entry.
  *
  * @returns 0 on success.
@@ -992,5 +1011,5 @@
  * @param   pEntry  Entry containing a memory allocation.
  */
-int dosexForkPreMemOpen(PDOSEX pEntry)
+static int dosexForkPreMemOpen(PDOSEX pEntry)
 {
     unsigned    cOpens = pEntry->u.MemOpen.cOpens;
@@ -1007,5 +1026,5 @@
 
 /**
- * Allocates the memory described in the entry.
+ * Creates the mutex semaphore described in the entry.
  *
  * @returns 0 on success.
@@ -1013,5 +1032,5 @@
  * @param   pEntry  Entry containing a memory allocation.
  */
-int dosexForkPreMutexCreate(PDOSEX pEntry)
+static int dosexForkPreMutexCreate(PDOSEX pEntry)
 {
     int                 i;
@@ -1084,5 +1103,5 @@
 
 /**
- * Allocates the memory described in the entry.
+ * Opens the mutex semaphore described in the entry.
  *
  * @returns 0 on success.
@@ -1090,5 +1109,5 @@
  * @param   pEntry  Entry containing a memory allocation.
  */
-int dosexForkPreMutexOpen(PDOSEX pEntry)
+static int dosexForkPreMutexOpen(PDOSEX pEntry)
 {
     int cOpens = pEntry->u.MutexOpen.cOpens;
@@ -1105,5 +1124,5 @@
 
 /**
- * Allocates the memory described in the entry.
+ * Creates the event semaphore described in the entry.
  *
  * @returns 0 on success.
@@ -1111,5 +1130,5 @@
  * @param   pEntry  Entry containing a memory allocation.
  */
-int dosexForkPreEventCreate(PDOSEX pEntry)
+static int dosexForkPreEventCreate(PDOSEX pEntry)
 {
     int                 i;
@@ -1182,5 +1201,5 @@
 
 /**
- * Allocates the memory described in the entry.
+ * Opens the event semaphore described in the entry.
  *
  * @returns 0 on success.
@@ -1188,5 +1207,5 @@
  * @param   pEntry  Entry containing a memory allocation.
  */
-int dosexForkPreEventOpen(PDOSEX pEntry)
+static int dosexForkPreEventOpen(PDOSEX pEntry)
 {
     int cOpens = pEntry->u.EventOpen.cOpens;
@@ -1195,4 +1214,42 @@
         int rc = DosOpenEventSem(NULL, &pEntry->u.EventOpen.hev);
         LIBC_ASSERTM(!rc, "DosOpenEventSem(,%#lx) -> rc=%d\n", pEntry->u.EventOpen.hev, rc);
+        if (rc)
+            return -__libc_native2errno(rc);
+    }
+    return 0;
+}
+
+
+/**
+ * Loads the module described in the entry.
+ *
+ * @returns 0 on success.
+ * @returns -errno on failure.
+ * @param   pEntry  Entry containing a memory allocation.
+ */
+static int dosexForkPreLoadModule(PDOSEX pEntry)
+{
+    char    szName[CCHMAXPATH];
+    int     cLoads = pEntry->u.LoadModule.cLoads;
+
+    /*
+     * Figure out the name first.
+     */
+    int     rc = DosQueryModuleName(pEntry->u.LoadModule.hmte, sizeof(szName), szName);
+    if (rc)
+    {
+        LIBC_ASSERTM(!rc, "DosQueryModuleName(%#lx,%d,%p) -> rc=%d \n", pEntry->u.LoadModule.hmte, sizeof(szName), szName, rc);
+        if (rc)
+            return -__libc_native2errno(rc);
+    }
+
+    /*
+     * Perform the loads.
+     */
+    while (cLoads-- > 0)
+    {
+        HMODULE hmod = 0;
+        rc = DosLoadModule(NULL, 0, (PCSZ)szName, &hmod);
+        LIBC_ASSERTM(!rc, "DosLoadModule(,,'%s',) -> rc=%d (hmte=%#lx)\n", szName, rc, pEntry->u.LoadModule.hmte);
         if (rc)
             return -__libc_native2errno(rc);
@@ -1264,3 +1321,2 @@
 }
 
-
Index: trunk/src/emx/src/lib/sys/DosEx.h
===================================================================
--- trunk/src/emx/src/lib/sys/DosEx.h	(revision 1675)
+++ trunk/src/emx/src/lib/sys/DosEx.h	(revision 1676)
@@ -49,4 +49,6 @@
     /** Event open. */
     DOSEX_TYPE_EVENT_OPEN,
+    /** Load module. */
+    DOSEX_TYPE_LOAD_MODULE,
     /** Max type (exclusive). */
     DOSEX_TYPE_MAX
@@ -69,5 +71,5 @@
     {
         /** Search key.
-         * We assume that sizeof(unsigned) == sizeof(PVOID) == sizeof(HMTX) == sizeof(HEV).
+         * We assume that sizeof(unsigned) == sizeof(PVOID) == sizeof(HMTX) == sizeof(HEV) == sizeof(HMODULE).
          */
         unsigned        uKey;
@@ -151,4 +153,15 @@
             unsigned    cOpens;
         }   EventOpen;
+
+        /**
+         * Loaded module.
+         */
+        struct
+        {
+            /** Module handle. */
+            HMODULE     hmte;
+            /** Load count. */
+            unsigned    cLoads;
+        }   LoadModule;
     }       u;
 } DOSEX;
Index: trunk/src/emx/src/lib/sys/DosFreeModuleEx.c
===================================================================
--- trunk/src/emx/src/lib/sys/DosFreeModuleEx.c	(revision 1676)
+++ trunk/src/emx/src/lib/sys/DosFreeModuleEx.c	(revision 1676)
@@ -0,0 +1,66 @@
+/* $Id$ */
+/** @file
+ *
+ * DosFreeModuleEx.
+ *
+ * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This file is part of InnoTek LIBC.
+ *
+ * InnoTek LIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * InnoTek LIBC 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with InnoTek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "libc-alias.h"
+#define INCL_ERRORS
+#define INCL_DOSMODULEMGR
+#define INCL_FSMACROS
+#define INCL_EXAPIS
+#include <os2emx.h>
+#define __LIBC_LOG_GROUP    __LIBC_LOG_GRP_DOSEX
+#include <InnoTekLIBC/logstrict.h>
+#include "DosEx.h"
+
+
+/**
+ * Free module loaded using the extended APIs.
+ */
+APIRET APIENTRY DosFreeModuleEx(HMODULE hmod)
+{
+    LIBCLOG_ENTER("hmod=%lx\n", hmod);
+    int         rc;
+    FS_VAR();
+
+    /*
+     * Validate input.
+     */
+    if (!hmod)
+        LIBCLOG_RETURN_INT(ERROR_INVALID_HANDLE);
+
+    /*
+     * Free module.
+     */
+    FS_SAVE_LOAD();
+    rc = __libc_dosexFree(DOSEX_TYPE_LOAD_MODULE, (unsigned)hmod);
+    if (rc == -1)
+        rc = DosFreeModule(hmod);
+    FS_RESTORE();
+    LIBCLOG_RETURN_INT(rc);
+}
+
Index: trunk/src/emx/src/lib/sys/DosLoadModuleEx.c
===================================================================
--- trunk/src/emx/src/lib/sys/DosLoadModuleEx.c	(revision 1676)
+++ trunk/src/emx/src/lib/sys/DosLoadModuleEx.c	(revision 1676)
@@ -0,0 +1,99 @@
+/* $Id$ */
+/** @file
+ *
+ * DosCreateEventSemEx.
+ *
+ * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This file is part of InnoTek LIBC.
+ *
+ * InnoTek LIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * InnoTek LIBC 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with InnoTek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "libc-alias.h"
+#define INCL_ERRORS
+#define INCL_DOSMODULEMGR
+#define INCL_FSMACROS
+#define INCL_EXAPIS
+#include <os2emx.h>
+#define __LIBC_LOG_GROUP    __LIBC_LOG_GRP_DOSEX
+#include <InnoTekLIBC/logstrict.h>
+#include "DosEx.h"
+
+
+/**
+ * Extended DosLoadModule() which will make sure the loaded module is
+ * loaded in a forked process.
+ */
+APIRET APIENTRY DosLoadModuleEx(PSZ pszObject, ULONG cbObject, PCSZ pszModule, PHMODULE phmod)
+{
+    LIBCLOG_ENTER("pszObject=%p cbObject=%ld pszModule=%p:{'%s'} phmod=%p\n", pszObject, cbObject, (void *)pszModule, pszModule, (void *)phmod);
+    DOSEXTYPE   enmType;
+    PDOSEX      pDosEx;
+    HMODULE     hmte;
+    int         rc;
+    FS_VAR();
+
+    /*
+     * Create the semaphore.
+     */
+    FS_SAVE_LOAD();
+    rc = DosLoadModule(pszObject, cbObject, pszModule, phmod);
+    if (rc)
+    {
+        FS_RESTORE();
+        LIBCLOG_RETURN_INT(rc);
+    }
+
+    /*
+     * Check if already loaded.
+     */
+    hmte = *phmod;
+    pDosEx = __libc_dosexFind(DOSEX_TYPE_LOAD_MODULE, (unsigned)hmte);
+    if (pDosEx)
+    {
+        pDosEx->u.LoadModule.cLoads++;
+        __libc_dosexRelease(pDosEx);
+    }
+    else
+    {
+        /*
+         * Allocate record.
+         */
+        enmType = DOSEX_TYPE_LOAD_MODULE;
+        pDosEx = __libc_dosexAlloc(enmType);
+        if (!pDosEx)
+        {
+            DosFreeModule(hmte);
+            FS_RESTORE();
+            LIBCLOG_RETURN_INT(ERROR_NOT_ENOUGH_MEMORY);
+        }
+
+        /*
+         * Initialize record.
+         */
+        pDosEx->u.LoadModule.hmte   = hmte;
+        pDosEx->u.LoadModule.cLoads = 1;
+    }
+
+    FS_RESTORE();
+    LIBCLOG_RETURN_MSG(0, "ret 0 *phmod=%#lx\n", hmte);
+}
+
Index: trunk/src/emx/src/lib/sys/b_ldrClose.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_ldrClose.c	(revision 1675)
+++ trunk/src/emx/src/lib/sys/b_ldrClose.c	(revision 1676)
@@ -31,4 +31,5 @@
 #include "libc-alias.h"
 #define INCL_BASE
+#define INCL_EXAPIS
 #define INCL_FSMACROS
 #include <os2emx.h>
@@ -50,5 +51,5 @@
     FS_VAR();
     FS_SAVE_LOAD();
-    int rc = DosFreeModule((HMODULE)pvModule);
+    int rc = DosFreeModuleEx((HMODULE)pvModule);
     FS_RESTORE();
     LIBCLOG_RETURN_INT(rc);
Index: trunk/src/emx/src/lib/sys/b_ldrOpen.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_ldrOpen.c	(revision 1675)
+++ trunk/src/emx/src/lib/sys/b_ldrOpen.c	(revision 1676)
@@ -32,4 +32,5 @@
 #define INCL_BASE
 #define INCL_FSMACROS
+#define INCL_EXAPIS
 #include <os2emx.h>
 #include <InnoTekLIBC/backend.h>
@@ -55,5 +56,5 @@
     FS_VAR();
     FS_SAVE_LOAD();
-    int rc = DosLoadModule((PSZ)pszError, cchError, (PCSZ)pszLibrary, &hmod);
+    int rc = DosLoadModuleEx((PSZ)pszError, cchError, (PCSZ)pszLibrary, &hmod);
     FS_RESTORE();
     if (!rc)
