Index: /trunk/kLdr/kLdr.h
===================================================================
--- /trunk/kLdr/kLdr.h	(revision 2855)
+++ /trunk/kLdr/kLdr.h	(revision 2856)
@@ -136,113 +136,31 @@
      */
     int     (* pfnDestroy)( PKLDRRDR pRdr);
-    /** Read bits from the file.
-     *
-     * @returns 0 on success, OS specific error code on failure.
-     * @param   pRdr        The file provider instance.
-     * @param   pvBuf       Where to put the bits.
-     * @param   cb          The number of bytes to read.
-     * @param   off         Where to start reading.
-     */
+    /** @copydoc kLdrRdrRead */
     int     (* pfnRead)(    PKLDRRDR pRdr, void *pvBuf, size_t cb, off_t off);
-    /** Map all the file bits into memory (read only).
-     *
-     * @returns 0 on success, OS specific error code on failure.
-     * @param   pRdr        The file provider instance.
-     * @param   ppvBits     Where to store the address of the mapping.
-     *                      The size can be obtained using pfnSize.
-     */
+    /** @copydoc kLdrRdrAllMap */
     int     (* pfnAllMap)(  PKLDRRDR pRdr, const void **ppvBits);
-    /** Unmap a file bits mapping obtained by KLDRRDROPS::pfnAllMap.
-     *
-     * @returns 0 on success, OS specific error code on failure.
-     * @param   pRdr        The file provider instance.
-     * @param   pvBits      The mapping address.
-     */
+    /** @copydoc kLdrRdrAllUnmap */
     int     (* pfnAllUnmap)(PKLDRRDR pRdr, const void *pvBits);
-    /** Get the file size.
-     *
-     * @returns The file size. Returns -1 on failure.
-     * @param   pRdr        The file provider instance.
-     */
+    /** @copydoc kLdrRdrSize */
     off_t   (* pfnSize)(    PKLDRRDR pRdr);
-    /** Get the file pointer offset.
-     *
-     * @returns The file pointer offset. Returns -1 on failure.
-     * @param   pRdr        The file provider instance.
-     */
+    /** @copydoc kLdrRdrTell */
     off_t   (* pfnTell)(    PKLDRRDR pRdr);
-    /** Get the file name.
-     *
-     * @returns The file size. Returns -1 on failure.
-     * @param   pRdr        The file provider instance.
-     */
+    /** @copydoc kLdrRdrName */
     const char * (* pfnName)(PKLDRRDR pRdr);
-    /**
-     * Prepares a memory region to map file sections into.
-     *
-     * @returns 0 on success, OS specific error code on failure.
-     * @param   pRdr        The file provider instance.
-     * @param   ppv         If fFixed is set, *ppv contains the memory location which
-     *                      the region should be based at. If fFixed is clear the OS
-     *                      is free to choose the location.
-     *                      On successful return *ppv contains address of the prepared
-     *                      memory region.
-     * @param   cb          The size of the memory region to prepare.
-     * @param   fFixed      When set *ppv will contain the desired region address.
-     *
-     */
+    /** @copydoc kLdrRdrPageSize */
+    size_t  (* pfnPageSize)(PKLDRRDR pRdr);
+    /** @copydoc kLdrRdrPrepare */
     int     (* pfnPrepare)(PKLDRRDR pRdr, void **ppv, size_t cb, unsigned fFixed);
-    /**
-     * Maps a section of the file into the memory region reserved by pfnPrepare.
-     *
-     * @returns 0 on success, OS specific error code on failure.
-     * @param   pRdr        The file provider instance.
-     * @param   pv          The address in the prepared region.
-     * @param   cb          The size of the memory mapping.
-     * @param   enmProt     The desired memory protection.
-     * @param   offFile     The start of the raw file bytes.
-     * @param   cbFile      The number of raw file bytes. This must be less or equal to cb.
-     */
+    /** @copydoc kLdrRdrMap */
     int     (* pfnMap)(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt, off_t offFile, size_t cbFile);
-    /**
-     * Changes the page protection of a section mapped using pfnMap.
-     *
-     * This is typically used for applying fixups and similar.
-     *
-     * @returns 0 on success, OS specific error code on failure.
-     * @param   pRdr        The file provider instance.
-     * @param   pv          The address passed to pfnMap.
-     * @param   cb          The size passed to pfnMap.
-     * @param   enmProt     The desired memory protection.
-     */
+    /** @copydoc kLdrRdrRefreshMap */
+    int     (* pfnRefreshMap)(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt, off_t offFile, size_t cbFile);
+    /** @copydoc kLdrRdrProtect */
     int     (* pfnProtect)(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt);
-    /**
-     * Unmaps a section of the file previously mapped using pfnMap.
-     *
-     * @returns 0 on success, OS specific error code on failure.
-     * @param   pRdr        The file provider instance.
-     * @param   pv          The address passed to pfnMap.
-     * @param   cb          The size passed to pfnMap.
-     */
+    /** @copydoc kLdrRdrUnmap */
     int     (* pfnUnmap)(PKLDRRDR pRdr, void *pv, size_t cb);
-    /**
-     * Releases the memory region prepared by pfnPrepare().
-     *
-     * Before calling this function, all sections mapped by pfnMap must first be unmapped by calling pfnUnmap.
-     *
-     * @returns 0 on success, OS specific error code on failure.
-     * @param   pRdr        The file provider instance.
-     * @param   pv          The address of the prepared region.
-     * @param   cb          The size of the prepared region.
-     */
+    /** @copydoc kLdrRdrUnprepare */
     int     (* pfnUnprepare)(PKLDRRDR pRdr, void *pv, size_t cb);
-    /**
-     * We're done reading from the file but would like to keep file mappings.
-     *
-     * If the OS support closing the file handle while the file is mapped,
-     * the reader should do so.
-     *
-     * @param   pRdr        The file provider instance.
-     */
+    /** @copydoc kLdrRdrDone */
     void    (* pfnDone)(PKLDRRDR pRdr);
     /** The usual non-zero dummy that makes sure we've initialized all members. */
@@ -260,7 +178,12 @@
 typedef struct KLDRRDR
 {
+    /** Magic number (KLDRRDR_MAGIC). */
+    uint32_t     u32Magic;
     /** Pointer to the file provider operations. */
     PCKLDRRDROPS pOps;
 } KLDRRDR;
+
+/** The magic for KLDRRDR::u32Magic. (Katsu Aki (Katsuaki Nakamura)) */
+#define KLDRRDR_MAGIC   0x19610919
 
 void    kLdrRdrAddProvider(PKLDRRDROPS pAdd);
@@ -274,4 +197,12 @@
 off_t   kLdrRdrTell(    PKLDRRDR pRdr);
 const char *kLdrRdrName(PKLDRRDR pRdr);
+size_t  kLdrRdrPageSize(PKLDRRDR pRdr);
+int     kLdrRdrPrepare( PKLDRRDR pRdr, void **ppv, size_t cb, unsigned fFixed);
+int     kLdrRdrMap(     PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt, off_t offFile, size_t cbFile);
+int     kLdrRdrRefreshMap(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt, off_t offFile, size_t cbFile);
+int     kLdrRdrProtect( PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt);
+int     kLdrRdrUnmap(   PKLDRRDR pRdr, void *pv, size_t cb);
+int     kLdrRdrUnprepare(PKLDRRDR pRdr, void *pv, size_t cb);
+void    kLdrRdrDone(    PKLDRRDR pRdr);
 
 /** @} */
@@ -399,4 +330,6 @@
     /** The usual invalid enum value. */
     KLDRDBGINFOTYPE_INVALID = 0,
+    /** Unknown debug info format. */
+    KLDRDBGINFOTYPE_UNKNOWN,
     /** Stabs. */
     KLDRDBGINFOTYPE_STABS,
@@ -456,14 +389,22 @@
     /** The size of the segment. */
     KLDRSIZE        cb;
-    /** The required segment alignment. */
+    /** The required segment alignment.
+     * The to 0 if the segment isn't supposed to be mapped. */
     KLDRADDR        Alignment;
     /** The link address.
-     * Set to NIL_KLDRADDR if the segment isn't supposed to be mapped. */
+     * Set to NIL_KLDRADDR if the segment isn't supposed to be
+     * mapped or if the image doesn't have link addresses. */
     KLDRADDR        LinkAddress;
-    /** The address the segment was mapped at by kLdrModMap().
-     * Set to NIL_KLDRADDR if not mapped. */
-    KLDRADDR        MapAddress;
     /** The segment protection. */
     KLDRPROT        enmProt;
+    /** The address the segment was mapped at by kLdrModMap().
+     * Set to 0 if not mapped. */
+    uintptr_t       MapAddress;
+    /** File offset of the segment.
+     * Set to -1 if no file backing (like BSS). */
+    off_t           offFile;
+    /** Size of the file bits of the segment.
+     * Set to -1 if no file backing (like BSS). */
+    off_t           cbFile;
 } KLDRSEG;
 /** Pointer to a loader segment. */
@@ -563,5 +504,5 @@
 typedef struct KLDRMOD
 {
-    /** Magic number. */
+    /** Magic number (KLDRMOD_MAGIC). */
     uint32_t            u32Magic;
     /** The format of this module. */
@@ -696,16 +637,20 @@
  *
  * @param   pMod        The module.
+ * @param   iDbgInfo    The debug info ordinal number / id.
  * @param   enmType     The debug info type.
- * @param   iDbgInfo    The debug info ordinal number / id.
+ * @param   iMajorVer   The major version number of the debug info format. -1 if unknow - implies invalid iMinorVer.
+ * @param   iMinorVer   The minor version number of the debug info format. -1 when iMajorVer is -1.
  * @param   offFile     The file offset *if* this type has one specific location in the executable image file.
  *                      This is -1 if there isn't any specific file location.
- * @param   cbFile      The file size.
- *                      This is 0 if there isn't any specific file location.
+ * @param   LinkAddress The link address of the debug info if it's loadable. NIL_KLDRADDR if not loadable.
+ * @param   cb          The size of the debug information. -1 is used if this isn't applicable.
  * @param   pszExtFile  This points to the name of an external file containing the debug info.
  *                      This is NULL if there isn't any external file.
  * @param   pvUser      The user parameter specified to kLdrModEnumDbgInfo.
  */
-typedef int FNKLDRENUMDBG(PKLDRMOD pMod, KLDRDBGINFOTYPE enmType, uint32_t iDbgInfo, off_t offFile, off_t cbFile,
-                          const char *pszExtFile, void *pvUser);
+typedef int FNKLDRENUMDBG(PKLDRMOD pMod, uint32_t iDbgInfo, KLDRDBGINFOTYPE enmType, int16_t iMajorVer, int16_t iMinorVer,
+                          off_t offFile, KLDRADDR LinkAddress, off_t cb, const char *pszExtFile, void *pvUser);
+/** Pointer to a debug info enumberator callback. */
+typedef FNKLDRENUMDBG *PFNKLDRENUMDBG;
 
 int     kLdrModOpen(const char *pszFilename, PPKLDRMOD ppMod);
@@ -724,6 +669,4 @@
 int     kLdrModGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo);
 int     kLdrModQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress);
-/** Pointer to a debug info enumberator callback. */
-typedef FNKLDRENUMDBG *PFNKLDRENUMDBG;
 int     kLdrModEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser);
 int     kLdrModHasDbgInfo(PKLDRMOD pMod, const void *pvBits);
@@ -737,12 +680,12 @@
 int     kLdrModReload(PKLDRMOD pMod);
 int     kLdrModFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
-int     kLdrModCallInit(PKLDRMOD pMod);
-int     kLdrModCallTerm(PKLDRMOD pMod);
-int     kLdrModCallThread(PKLDRMOD pMod, unsigned fAttachingOrDetaching);
+int     kLdrModCallInit(PKLDRMOD pMod, uintptr_t uHandle);
+int     kLdrModCallTerm(PKLDRMOD pMod, uintptr_t uHandle);
+int     kLdrModCallThread(PKLDRMOD pMod, uintptr_t uHandle, unsigned fAttachingOrDetaching);
 /** @} */
 
 /** @name Operations On The Externally Managed Mappings
  * @{ */
-size_t  kLdrModSize(PKLDRMOD pMod);
+KLDRADDR kLdrModSize(PKLDRMOD pMod);
 int     kLdrModGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
 int     kLdrModRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
@@ -818,11 +761,11 @@
     int (* pfnFixupMapping)(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
     /** @copydoc kLdrModCallInit */
-    int (* pfnCallInit)(PKLDRMOD pMod);
+    int (* pfnCallInit)(PKLDRMOD pMod, uintptr_t uHandle);
     /** @copydoc kLdrModCallTerm */
-    int (* pfnCallTerm)(PKLDRMOD pMod);
+    int (* pfnCallTerm)(PKLDRMOD pMod, uintptr_t uHandle);
     /** @copydoc kLdrModCallThread */
-    int (* pfnCallThread)(PKLDRMOD pMod, unsigned fAttachingOrDetaching);
+    int (* pfnCallThread)(PKLDRMOD pMod, uintptr_t uHandle, unsigned fAttachingOrDetaching);
     /** @copydoc kLdrModSize */
-    size_t (* pfnSize)(PKLDRMOD pMod);
+    KLDRADDR (* pfnSize)(PKLDRMOD pMod);
     /** @copydoc kLdrModGetBits */
     int (* pfnGetBits)(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
@@ -1052,4 +995,12 @@
 /** A forwarder chain was too long. */
 #define KLDR_ERR_TOO_LONG_FORWARDER_CHAIN                   (KLDR_ERR_BASE + 51)
+/** The module has no debug info. */
+#define KLDR_ERR_NO_DEBUG_INFO                              (KLDR_ERR_BASE + 52)
+/** The module is already mapped.
+ * kLdrModMap() can only be called once (without kLdrModUnmap() in between). */
+#define KLDR_ERR_ALREADY_MAPPED                             (KLDR_ERR_BASE + 53)
+/** The module was not mapped.
+ * kLdrModUnmap() should not called without being preceeded by a kLdrModMap(). */
+#define KLDR_ERR_NOT_MAPPED                                 (KLDR_ERR_BASE + 54)
 
 /** @name kLdrModPE status codes
Index: /trunk/kLdr/kLdrDyldMod.c
===================================================================
--- /trunk/kLdr/kLdrDyldMod.c	(revision 2855)
+++ /trunk/kLdr/kLdrDyldMod.c	(revision 2856)
@@ -1002,5 +1002,5 @@
     KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_INITIALIZING);
 
-    rc = kLdrModCallInit(pMod->pMod);
+    rc = kLdrModCallInit(pMod->pMod, (uintptr_t)pMod->hMod);
     if (!rc)
         pMod->enmState = KLDRSTATE_GOOD;
@@ -1023,5 +1023,5 @@
     KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_TERMINATING);
 
-    kLdrModCallTerm(pMod->pMod);
+    kLdrModCallTerm(pMod->pMod, (uintptr_t)pMod->hMod);
     pMod->enmState = KLDRSTATE_PENDING_GC;
 }
@@ -1038,5 +1038,5 @@
     KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_GOOD);
 
-    return kLdrModCallThread(pMod->pMod, 1 /* attach */);
+    return kLdrModCallThread(pMod->pMod, (uintptr_t)pMod->hMod, 1 /* attach */);
 }
 
@@ -1052,5 +1052,5 @@
     KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_GOOD);
 
-    kLdrModCallThread(pMod->pMod, 0 /* detach */);
+    kLdrModCallThread(pMod->pMod, (uintptr_t)pMod->hMod, 0 /* detach */);
 }
 
Index: /trunk/kLdr/kLdrMod.c
===================================================================
--- /trunk/kLdr/kLdrMod.c	(revision 2855)
+++ /trunk/kLdr/kLdrMod.c	(revision 2856)
@@ -538,9 +538,10 @@
  * @returns 0 on success or no init function, non-zero on init function failure or invalid pMod.
  * @param   pMod            The module.
- */
-int     kLdrModCallInit(PKLDRMOD pMod)
-{
-    KLDRMOD_VALIDATE(pMod);
-    return pMod->pOps->pfnCallInit(pMod);
+ * @param   uHandle         The module handle to use if any of the init functions requires the module handle.
+ */
+int     kLdrModCallInit(PKLDRMOD pMod, uintptr_t uHandle)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnCallInit(pMod, uHandle);
 }
 
@@ -551,11 +552,12 @@
  * @returns 0 on success or no term function, non-zero on invalid pMod.
  * @param   pMod            The module.
+ * @param   uHandle         The module handle to use if any of the term functions requires the module handle.
  *
  * @remark  Termination function failure will be ignored by the module interpreter.
  */
-int     kLdrModCallTerm(PKLDRMOD pMod)
-{
-    KLDRMOD_VALIDATE(pMod);
-    return pMod->pOps->pfnCallTerm(pMod);
+int     kLdrModCallTerm(PKLDRMOD pMod, uintptr_t uHandle)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnCallTerm(pMod, uHandle);
 }
 
@@ -564,14 +566,18 @@
  * Call the thread attach or detach function of a mapped module (if any).
  *
+ * Any per-thread TLS initialization/termination will have to be done at this time too.
+ *
  * @returns 0 on success or no attach/detach function, non-zero on attach failure or invalid pMod.
  * @param   pMod            The module.
+ * @param   uHandle         The module handle to use if any of the thread attach/detach functions
+ *                          requires the module handle.
  *
  * @remark  Detach function failure will be ignored by the module interpreter.
  */
-int     kLdrModCallThread(PKLDRMOD pMod, unsigned fAttachingOrDetaching)
+int     kLdrModCallThread(PKLDRMOD pMod, uintptr_t uHandle, unsigned fAttachingOrDetaching)
 {
     KLDRMOD_VALIDATE(pMod);
     KLDRHLP_VALIDATE_FLAGS(fAttachingOrDetaching, 1);
-    return pMod->pOps->pfnCallThread(pMod, fAttachingOrDetaching);
+    return pMod->pOps->pfnCallThread(pMod, uHandle, fAttachingOrDetaching);
 }
 
@@ -583,5 +589,5 @@
  * @param   pMod            The module.
  */
-size_t  kLdrModSize(PKLDRMOD pMod)
+KLDRADDR kLdrModSize(PKLDRMOD pMod)
 {
     KLDRMOD_VALIDATE_EX(pMod, 0);
Index: /trunk/kLdr/kLdrModPE.c
===================================================================
--- /trunk/kLdr/kLdrModPE.c	(revision 2855)
+++ /trunk/kLdr/kLdrModPE.c	(revision 2856)
@@ -33,4 +33,5 @@
 #include "kLdrInternal.h"
 #include "kLdrModPE.h"
+
 
 /*******************************************************************************
@@ -73,8 +74,8 @@
     /** Pointer to the RDR mapping of the raw file bits. NULL if not mapped. */
     const void             *pvBits;
-    /** Whether we've mapped the image or not. */
-    uint32_t                fMapped : 1;
+    /** Pointer to the user mapping. */
+    const void             *pvMapping;
     /** Reserved flags. */
-    uint32_t                f31Reserved;
+    uint32_t                f32Reserved;
     /** The number of imported modules.
      * If ~(uint32_t)0 this hasn't been determined yet. */
@@ -100,4 +101,12 @@
                                    PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser, PKLDRADDR puValue, uint32_t *pfKind);
 static int32_t kldrModPENumberOfImports(PKLDRMOD pMod, const void *pvBits);
+static int kldrModPEUnprotect(PKLDRMODPE pModPE, const void *pvMapping);
+static int kldrModPEProtect(PKLDRMODPE pModPE, const void *pvMapping);
+static int kldrModPEDoFixups(PKLDRMODPE pModPE, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress);
+static int kldrModPEDoImports(PKLDRMODPE pModPE, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
+static int kldrModPEDoCallDLL(PKLDRMODPE pModPE, unsigned uOp, uintptr_t uHandle);
+static int kldrModPEDoCallTLS(PKLDRMODPE pModPE, unsigned uOp, uintptr_t uHandle);
+static int kldrModPERelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
+                                 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
 
 
@@ -221,6 +230,5 @@
     pModPE->pMod = pMod;
     pModPE->pvBits = NULL;
-    pModPE->fMapped = 0;
-    pModPE->f31Reserved = 0;
+    pModPE->f32Reserved = 0;
     pModPE->cImportModules = ~(uint32_t)0;
     pModPE->offHdrs = offNewHdr >= 0 ? offNewHdr : 0;
@@ -473,4 +481,36 @@
 
 /**
+ * Performs the mapping of the image.
+ *
+ * This can be used to do the internal mapping as well as the
+ * user requested mapping. fForReal indicates which is desired.
+ *
+ * @returns 0 on success, non-zero OS or kLdr status code on failure.
+ * @param   pModPE          The interpreter module instance
+ * @param   fForReal        If set, do the user mapping. if clear, do the internal mapping.
+ */
+static int kldrModPEDoMap(PKLDRMODPE pModPE, unsigned fForReal)
+{
+    return -1;
+}
+
+
+/**
+ * Unmaps a image mapping.
+ *
+ * This can be used to do the internal mapping as well as the
+ * user requested mapping. fForReal indicates which is desired.
+ *
+ * @returns 0 on success, non-zero OS or kLdr status code on failure.
+ * @param   pModPE          The interpreter module instance
+ * @param   fForReal        If set, unmap the user mapping. if clear, unmap the internal mapping.
+ */
+static int kldrModPEDoUnmap(PKLDRMODPE pModPE, unsigned fForReal)
+{
+    return -1;
+}
+
+
+/**
  * Gets usable bits and the right base address.
  *
@@ -505,6 +545,6 @@
     if (!*ppvBits)
     {
-        if (pModPE->fMapped)
-            *ppvBits = (void *)(uintptr_t)pModPE->pMod->aSegments[0].MapAddress;
+        if (pModPE->pvMapping)
+            *ppvBits = pModPE->pvMapping;
         else if (pModPE->pvBits)
             *ppvBits = pModPE->pvBits;
@@ -888,5 +928,5 @@
         /*
          * We'll have to walk the import descriptors to figure out their number.
-         * First, make sure we've got mapped bits and resolve any base address aliases.
+         * First, make sure we've got mapped bits.
          */
         if (kldrModPEBitsAndBaseAddress(pModPE, &pvBits, NULL))
@@ -931,8 +971,14 @@
     int rc;
 
+    /*
+     * Resolve base address alias if any.
+     */
     rc = kldrModPEBitsAndBaseAddress(pModPE, NULL, &BaseAddress);
     if (rc)
         return rc;
 
+    /*
+     * Convert the address from the header.
+     */
     *pMainEPAddress = pModPE->Hdrs.OptionalHeader.AddressOfEntryPoint
         ? BaseAddress + pModPE->Hdrs.OptionalHeader.AddressOfEntryPoint
@@ -943,32 +989,376 @@
 
 /** @copydoc kLdrModEnumDbgInfo */
-int (* pfnEnumDbgInfo)(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser);
+static int kldrModPEEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser)
+{
+    PKLDRMODPE                      pModPE = (PKLDRMODPE)pMod->pvData;
+    const IMAGE_DEBUG_DIRECTORY    *pDbgDir;
+    uint32_t                        iDbgInfo;
+    uint32_t                        cb;
+    int                             rc;
+
+    /*
+     * Check that there is a debug directory first.
+     */
+    cb = pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+    if (    cb < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */
+        ||  !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)
+        return 0;
+
+    /*
+     * Make sure we've got mapped bits.
+     */
+    rc = kldrModPEBitsAndBaseAddress(pModPE, &pvBits, NULL);
+    if (rc)
+        return rc;
+
+    /*
+     * Enumerate the debug directory.
+     */
+    pDbgDir = KLDRMODPE_RVA2TYPE(pvBits,
+                                 pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,
+                                 const IMAGE_DEBUG_DIRECTORY *);
+    for (iDbgInfo = 0;; iDbgInfo++, pDbgDir++, cb -= sizeof(IMAGE_DEBUG_DIRECTORY))
+    {
+        KLDRDBGINFOTYPE     enmDbgInfoType;
+
+        /* convert the type. */
+        switch (pDbgDir->Type)
+        {
+            case IMAGE_DEBUG_TYPE_UNKNOWN:
+            case IMAGE_DEBUG_TYPE_FPO:
+            case IMAGE_DEBUG_TYPE_COFF: //stabs dialect??
+            case IMAGE_DEBUG_TYPE_MISC:
+            case IMAGE_DEBUG_TYPE_EXCEPTION:
+            case IMAGE_DEBUG_TYPE_FIXUP:
+            case IMAGE_DEBUG_TYPE_BORLAND:
+            default:
+                enmDbgInfoType = KLDRDBGINFOTYPE_UNKNOWN;
+                break;
+            case IMAGE_DEBUG_TYPE_CODEVIEW:
+                enmDbgInfoType = KLDRDBGINFOTYPE_CODEVIEW;
+                break;
+        }
+
+        rc = pfnCallback(pMod, iDbgInfo,
+                         enmDbgInfoType, pDbgDir->MajorVersion, pDbgDir->MinorVersion,
+                         pDbgDir->PointerToRawData ? pDbgDir->PointerToRawData : -1,
+                         pDbgDir->AddressOfRawData ? pDbgDir->AddressOfRawData : NIL_KLDRADDR,
+                         pDbgDir->SizeOfData,
+                         NULL,
+                         pvUser);
+        if (rc)
+            break;
+
+        /* next */
+        if (cb <= sizeof(IMAGE_DEBUG_DIRECTORY))
+            break;
+    }
+
+    return rc;
+}
+
 
 /** @copydoc kLdrModHasDbgInfo */
-int (* pfnHasDbgInfo)(PKLDRMOD pMod, const void *pvBits);
+static int kldrModPEHasDbgInfo(PKLDRMOD pMod, const void *pvBits)
+{
+    PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData;
+
+    /*
+     * Base this entirely on the presence of a debug directory.
+     */
+    if (    pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size
+            < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */
+        ||  !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)
+        return KLDR_ERR_NO_DEBUG_INFO;
+    return 0;
+}
+
+
 /** @copydoc kLdrModMap */
-int (* pfnMap)(PKLDRMOD pMod);
+static int kldrModPEMap(PKLDRMOD pMod)
+{
+    PKLDRMODPE  pModPE = (PKLDRMODPE)pMod->pvData;
+    int         rc;
+
+    /*
+     * Already mapped?
+     */
+    if (pModPE->pvMapping)
+        return KLDR_ERR_ALREADY_MAPPED;
+
+    /*
+     * We've got a common worker which does this.
+     */
+    rc = kldrModPEDoMap(pModPE, 1 /* the real thing */);
+    if (rc)
+        return rc;
+    KLDRMODPE_ASSERT(pModPE->pvMapping);
+    return 0;
+}
+
+
 /** @copydoc kLdrModUnmap */
-int (* pfnUnmap)(PKLDRMOD pMod);
+static int kldrModPEUnmap(PKLDRMOD pMod)
+{
+    PKLDRMODPE  pModPE = (PKLDRMODPE)pMod->pvData;
+    int         rc;
+
+    /*
+     * Mapped?
+     */
+    if (!pModPE->pvMapping)
+        return KLDR_ERR_NOT_MAPPED;
+
+    /*
+     * We've got a common worker which does this.
+     */
+    rc = kldrModPEDoMap(pModPE, 1 /* the real thing */);
+    if (rc)
+        return rc;
+    KLDRMODPE_ASSERT(pModPE->pvMapping);
+    return 0;
+
+}
+
+
 /** @copydoc kLdrModAllocTLS */
-int (* pfnAllocTLS)(PKLDRMOD pMod);
+static int kldrModPEAllocTLS(PKLDRMOD pMod)
+{
+    PKLDRMODPE  pModPE = (PKLDRMODPE)pMod->pvData;
+
+    /*
+     * Mapped?
+     */
+    if (!pModPE->pvMapping)
+        return KLDR_ERR_NOT_MAPPED;
+
+    /*
+     * If no TLS directory then there is nothing to do.
+     */
+    if (    !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size
+        ||  !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress)
+        return 0;
+    /** @todo implement TLS. */
+    return -1;
+}
+
+
 /** @copydoc kLdrModFreeTLS */
-void (* pfnFreeTLS)(PKLDRMOD pMod);
+static void kldrModPEFreeTLS(PKLDRMOD pMod)
+{
+    PKLDRMODPE  pModPE = (PKLDRMODPE)pMod->pvData;
+
+    /*
+     * Mapped?
+     */
+    if (!pModPE->pvMapping)
+        return;
+
+    /*
+     * If no TLS directory then there is nothing to do.
+     */
+    if (    !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size
+        ||  !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress)
+        return;
+    /** @todo implement TLS. */
+    return;
+}
+
+
 /** @copydoc kLdrModReload */
-int (* pfnReload)(PKLDRMOD pMod);
+static int kldrModPEReload(PKLDRMOD pMod)
+{
+    PKLDRMODPE      pModPE = (PKLDRMODPE)pMod->pvData;
+    uint32_t        i;
+    int             rc;
+    const size_t    cbPage = kLdrRdrPageSize(pMod->pRdr);
+
+    /*
+     * Mapped?
+     */
+    if (!pModPE->pvMapping)
+        return KLDR_ERR_NOT_MAPPED;
+
+    /*
+     * Iterate the objects and ask the file provider to undo all the changes.
+     */
+    for (i = rc = 0; !rc && i < pMod->cSegments; i++)
+        rc = kLdrRdrRefreshMap(pMod->pRdr,
+                               (void *)pMod->aSegments[i].MapAddress,
+                               (size_t)pMod->aSegments[i].cb,
+                               pMod->aSegments[i].enmProt,
+                               pMod->aSegments[i].offFile,
+                               pMod->aSegments[i].cbFile);
+
+    return rc;
+}
+
+
 /** @copydoc kLdrModFixupMapping */
-int (* pfnFixupMapping)(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
+static int kldrModPEFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData;
+    int rc, rc2;
+
+    /*
+     * Mapped?
+     */
+    if (!pModPE->pvMapping)
+        return KLDR_ERR_NOT_MAPPED;
+
+    /*
+     * Before doing anything we'll have to make all pages writable.
+     */
+    rc = kldrModPEUnprotect(pModPE, pModPE->pvMapping);
+    if (rc)
+        return rc;
+
+    /*
+     * Do we need to apply base relocations?
+     */
+    if (pModPE->Hdrs.OptionalHeader.ImageBase != (uintptr_t)pModPE->pvMapping)
+        rc = kldrModPEDoFixups(pModPE, (void *)pModPE->pvMapping, (uintptr_t)pModPE->pvMapping,
+                               pModPE->Hdrs.OptionalHeader.ImageBase);
+
+    /*
+     * Resolve imports.
+     */
+    if (!rc)
+        rc = kldrModPEDoImports(pModPE, (void *)pModPE->pvMapping, pfnGetImport, pvUser);
+
+    /*
+     * Restore protection.
+     */
+    rc2 = kldrModPEProtect(pModPE, pModPE->pvMapping);
+    if (!rc && rc2)
+        rc = rc2;
+    return rc;
+}
+
+
 /** @copydoc kLdrModCallInit */
-int (* pfnCallInit)(PKLDRMOD pMod);
+static int kldrModPECallInit(PKLDRMOD pMod, uintptr_t uHandle)
+{
+    PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData;
+    int rc;
+
+    /*
+     * Mapped?
+     */
+    if (!pModPE->pvMapping)
+        return KLDR_ERR_NOT_MAPPED;
+
+    /*
+     * Do TLS callbacks first and then call the init/term function if it's a DLL.
+     */
+    rc = kldrModPEDoCallTLS(pModPE, DLL_PROCESS_ATTACH, uHandle);
+    if (    !rc
+        &&  (pModPE->Hdrs.FileHeader.Characteristics & IMAGE_FILE_DLL))
+    {
+        rc = kldrModPEDoCallDLL(pModPE, DLL_PROCESS_ATTACH, uHandle);
+        if (rc)
+            kldrModPEDoCallTLS(pModPE, DLL_PROCESS_DETACH, uHandle);
+    }
+
+    return rc;
+}
+
+
 /** @copydoc kLdrModCallTerm */
-int (* pfnCallTerm)(PKLDRMOD pMod);
+static int kldrModPECallTerm(PKLDRMOD pMod, uintptr_t uHandle)
+{
+    PKLDRMODPE  pModPE = (PKLDRMODPE)pMod->pvData;
+
+    /*
+     * Mapped?
+     */
+    if (!pModPE->pvMapping)
+        return KLDR_ERR_NOT_MAPPED;
+
+    /*
+     * Do TLS callbacks first.
+     */
+    kldrModPEDoCallTLS(pModPE, DLL_PROCESS_DETACH, uHandle);
+    if (pModPE->Hdrs.FileHeader.Characteristics & IMAGE_FILE_DLL)
+        kldrModPEDoCallDLL(pModPE, DLL_PROCESS_DETACH, uHandle);
+
+    return 0;
+}
+
+
 /** @copydoc kLdrModCallThread */
-int (* pfnCallThread)(PKLDRMOD pMod, unsigned fAttachingOrDetaching);
+static int kldrModPECallThread(PKLDRMOD pMod, uintptr_t uHandle, unsigned fAttachingOrDetaching)
+{
+    PKLDRMODPE  pModPE = (PKLDRMODPE)pMod->pvData;
+    unsigned    uOp = fAttachingOrDetaching ? DLL_THREAD_ATTACH : DLL_THREAD_DETACH;
+    int         rc;
+
+    /*
+     * Do TLS callbacks first and then call the init/term function if it's a DLL.
+     */
+    rc = kldrModPEDoCallTLS(pModPE, uOp, uHandle);
+    if (!fAttachingOrDetaching)
+        rc = 0;
+    if (    !rc
+        &&  (pModPE->Hdrs.FileHeader.Characteristics & IMAGE_FILE_DLL))
+    {
+        rc = kldrModPEDoCallDLL(pModPE, uOp, uHandle);
+        if (!fAttachingOrDetaching)
+            rc = 0;
+        if (rc)
+            kldrModPEDoCallTLS(pModPE, uOp, uHandle);
+    }
+
+    return rc;
+}
+
+
 /** @copydoc kLdrModSize */
-size_t (* pfnSize)(PKLDRMOD pMod);
+static KLDRADDR kldrModPESize(PKLDRMOD pMod)
+{
+    PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData;
+    return pModPE->Hdrs.OptionalHeader.SizeOfImage;
+}
+
+
 /** @copydoc kLdrModGetBits */
-int (* pfnGetBits)(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
+static int kldrModPEGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    PKLDRMODPE  pModPE = (PKLDRMODPE)pMod->pvData;
+    uint32_t    i;
+    int         rc;
+
+    /*
+     * Iterate the segments and read the data within them.
+     */
+    for (i = 0; i < pMod->cSegments; i++)
+    {
+        /// @todo
+        rc = 0;
+    }
+
+    /*
+     * Perform relocations.
+     */
+    return kldrModPERelocateBits(pMod, pvBits, BaseAddress, pModPE->Hdrs.OptionalHeader.ImageBase, pfnGetImport, pvUser);
+
+}
+
+
 /** @copydoc kLdrModRelocateBits */
-int (* pfnRelocateBits)(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
-                        PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
-
+static int kldrModPERelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
+                                 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData;
+    int rc;
+
+    /*
+     * Call workers to do the jobs.
+     */
+    rc = kldrModPEDoFixups(pModPE, pvBits, NewBaseAddress, OldBaseAddress);
+    if (!rc)
+        rc = kldrModPEDoImports(pModPE, pvBits, pfnGetImport, pvUser);
+
+    return rc;
+}
+
Index: /trunk/kLdr/kLdrModPE.h
===================================================================
--- /trunk/kLdr/kLdrModPE.h	(revision 2855)
+++ /trunk/kLdr/kLdrModPE.h	(revision 2856)
@@ -152,4 +152,11 @@
 #define  IMAGE_ORDINAL64(ord)  ((ord) &  0xffff)
 #define  IMAGE_SNAP_BY_ORDINAL64(ord)  (!!((ord) & IMAGE_ORDINAL_FLAG64))
+
+
+/* dll/tls entry points argument */
+#define DLL_PROCESS_DETACH      0
+#define DLL_PROCESS_ATTACH      1
+#define DLL_THREAD_ATTACH       2
+#define DLL_THREAD_DETACH       3
 
 
@@ -412,4 +419,49 @@
 typedef IMAGE_LOAD_CONFIG_DIRECTORY64 *PIMAGE_LOAD_CONFIG_DIRECTORY64;
 
+typedef struct _IMAGE_DEBUG_DIRECTORY
+{
+    uint32_t  Characteristics;
+	uint32_t  TimeDateStamp;
+    uint16_t  MajorVersion;
+    uint16_t  MinorVersion;
+    uint32_t  Type;
+    uint32_t  SizeOfData;
+    uint32_t  AddressOfRawData;
+    uint32_t  PointerToRawData;
+} IMAGE_DEBUG_DIRECTORY;
+typedef IMAGE_DEBUG_DIRECTORY *PIMAGE_DEBUG_DIRECTORY;
+
+#define IMAGE_DEBUG_TYPE_UNKNOWN  0
+#define IMAGE_DEBUG_TYPE_COFF 1
+#define IMAGE_DEBUG_TYPE_CODEVIEW 2 /* 4.0 */
+#define IMAGE_DEBUG_TYPE_FPO 3 /* FPO = frame pointer omission */
+#define IMAGE_DEBUG_TYPE_MISC 4
+#define IMAGE_DEBUG_TYPE_EXCEPTION 5
+#define IMAGE_DEBUG_TYPE_FIXUP 6
+#define IMAGE_DEBUG_TYPE_BORLAND 9
+
+typedef struct _IMAGE_TLS_DIRECTORY32
+{
+    uint32_t  StartAddressOfRawData;
+    uint32_t  EndAddressOfRawData;
+    uint32_t  AddressOfIndex;
+    uint32_t  AddressOfCallBacks;
+    uint32_t  SizeOfZeroFill;
+    uint32_t  Characteristics;
+} IMAGE_TLS_DIRECTORY32;
+typedef IMAGE_TLS_DIRECTORY32 *PIMAGE_TLS_DIRECTORY32;
+
+typedef struct _IMAGE_TLS_DIRECTORY64
+{
+    uint64_t  StartAddressOfRawData;
+    uint64_t  EndAddressOfRawData;
+    uint64_t  AddressOfIndex;
+    uint64_t  AddressOfCallBacks;
+    uint32_t  SizeOfZeroFill;
+    uint32_t  Characteristics;
+} IMAGE_TLS_DIRECTORY64;
+typedef IMAGE_TLS_DIRECTORY64 *PIMAGE_TLS_DIRECTORY64;
+
+
 #pragma pack()
 
Index: /trunk/kLdr/kLdrRdr.c
===================================================================
--- /trunk/kLdr/kLdrRdr.c	(revision 2855)
+++ /trunk/kLdr/kLdrRdr.c	(revision 2856)
@@ -31,4 +31,48 @@
 #include <kLdr.h>
 #include "kLdrInternal.h"
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** @def KLDRRDR_STRICT
+ * Define KLDRRDR_STRICT to enabled strict checks in KLDRMOD. */
+#define KLDRRDR_STRICT 1
+
+/** @def KLDRRDR_ASSERT
+ * Assert that an expression is true when KLDR_STRICT is defined.
+ */
+#ifdef KLDRRDR_STRICT
+# define KLDRRDR_ASSERT(expr)  kldrHlpAssert(expr)
+#else
+# define KLDRRDR_ASSERT(expr)  do {} while (0)
+#endif
+
+/** Return / crash validation of a reader argument. */
+#define KLDRRDR_VALIDATE_EX(pRdr, rc) \
+    do  { \
+        if (    (pRdr)->u32Magic != KLDRRDR_MAGIC \
+            ||  (pRdr)->pOps == NULL \
+           )\
+        { \
+            return (rc); \
+        } \
+    } while (0)
+
+/** Return / crash validation of a reader argument. */
+#define KLDRRDR_VALIDATE(pRdr) \
+    KLDRRDR_VALIDATE_EX(pRdr, KLDR_ERR_INVALID_PARAMETER)
+
+/** Return / crash validation of a reader argument. */
+#define KLDRRDR_VALIDATE_VOID(pRdr) \
+    do  { \
+        if (    (pRdr)->u32Magic != KLDRRDR_MAGIC \
+            ||  (pRdr)->pOps == NULL \
+           )\
+        { \
+            return; \
+        } \
+    } while (0)
+
 
 
@@ -82,4 +126,5 @@
 int kLdrRdrClose(PKLDRRDR pRdr)
 {
+    KLDRRDR_VALIDATE(pRdr);
     return pRdr->pOps->pfnDestroy(pRdr);
 }
@@ -96,4 +141,5 @@
 int kLdrRdrRead(PKLDRRDR pRdr, void *pvBuf, size_t cb, off_t off)
 {
+    KLDRRDR_VALIDATE(pRdr);
     return pRdr->pOps->pfnRead(pRdr, pvBuf, cb, off);
 }
@@ -109,4 +155,5 @@
 int kLdrRdrAllMap(PKLDRRDR pRdr, const void **ppvBits)
 {
+    KLDRRDR_VALIDATE(pRdr);
     return pRdr->pOps->pfnAllMap(pRdr, ppvBits);
 }
@@ -121,4 +168,5 @@
 int kLdrRdrAllUnmap(PKLDRRDR pRdr, const void *pvBits)
 {
+    KLDRRDR_VALIDATE(pRdr);
     return pRdr->pOps->pfnAllUnmap(pRdr, pvBits);
 }
@@ -132,4 +180,5 @@
 off_t kLdrRdrSize(PKLDRRDR pRdr)
 {
+    KLDRRDR_VALIDATE(pRdr);
     return pRdr->pOps->pfnSize(pRdr);
 }
@@ -143,4 +192,5 @@
 off_t kLdrRdrTell(PKLDRRDR pRdr)
 {
+    KLDRRDR_VALIDATE(pRdr);
     return pRdr->pOps->pfnTell(pRdr);
 }
@@ -149,11 +199,146 @@
 /** Get the file name.
  *
- * @returns The file size. Returns -1 on failure.
+ * @returns The file name. Returns NULL on failure.
  * @param   pRdr        The file provider instance.
  */
 const char *kLdrRdrName(PKLDRRDR pRdr)
 {
+    KLDRRDR_VALIDATE_EX(pRdr, NULL);
     return pRdr->pOps->pfnName(pRdr);
 }
 
 
+/**
+ * Gets the page size used when mapping sections of the file.
+ *
+ * @returns The page size.
+ * @param   pRdr        The file provider instance.
+ */
+size_t  kLdrRdrPageSize(PKLDRRDR pRdr)
+{
+    KLDRRDR_VALIDATE_EX(pRdr, 0x10000);
+    return pRdr->pOps->pfnPageSize(pRdr);
+}
+
+
+/**
+ * Prepares a memory region to map file sections into.
+ *
+ * @returns 0 on success, OS specific error code on failure.
+ * @param   pRdr        The file provider instance.
+ * @param   ppv         If fFixed is set, *ppv contains the memory location which
+ *                      the region should be based at. If fFixed is clear the OS
+ *                      is free to choose the location.
+ *                      On successful return *ppv contains address of the prepared
+ *                      memory region.
+ * @param   cb          The size of the memory region to prepare.
+ * @param   fFixed      When set *ppv will contain the desired region address.
+ *
+ */
+int kLdrRdrPrepare(PKLDRRDR pRdr, void **ppv, size_t cb, unsigned fFixed)
+{
+    KLDRRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnPrepare(pRdr, ppv, cb, fFixed);
+}
+
+
+/**
+ * Maps a section of the file into the memory region reserved by pfnPrepare.
+ *
+ * @returns 0 on success, OS specific error code on failure.
+ * @param   pRdr        The file provider instance.
+ * @param   pv          The address in the prepared region.
+ * @param   cb          The size of the memory mapping.
+ * @param   enmProt     The desired memory protection.
+ * @param   offFile     The start of the raw file bytes.
+ * @param   cbFile      The number of raw file bytes. This must be less or equal to cb.
+ */
+int kLdrRdrMap(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt, off_t offFile, size_t cbFile)
+{
+    KLDRRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnMap(pRdr, pv, cb, enmProt, offFile, cbFile);
+}
+
+
+/**
+ * Reloads dirty pages in mapped section.
+ *
+ * @returns 0 on success, OS specific error code on failure.
+ * @param   pRdr        The file provider instance.
+ * @param   pv          The address in the prepared region.
+ * @param   cb          The size of the memory mapping.
+ * @param   enmProt     The desired memory protection.
+ * @param   offFile     The start of the raw file bytes.
+ * @param   cbFile      The number of raw file bytes. This must be less or equal to cb.
+ */
+int kLdrRdrRefreshMap(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt, off_t offFile, size_t cbFile)
+{
+    KLDRRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnRefreshMap(pRdr, pv, cb, enmProt, offFile, cbFile);
+}
+
+
+/**
+ * Changes the page protection of a section mapped using pfnMap.
+ *
+ * This is typically used for applying fixups and similar.
+ *
+ * @returns 0 on success, OS specific error code on failure.
+ * @param   pRdr        The file provider instance.
+ * @param   pv          The address passed to pfnMap.
+ * @param   cb          The size passed to pfnMap.
+ * @param   enmProt     The desired memory protection.
+ */
+int kLdrRdrProtect(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt)
+{
+    KLDRRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnProtect(pRdr, pv, cb, enmProt);
+}
+
+
+/**
+ * Unmaps a section of the file previously mapped using pfnMap.
+ *
+ * @returns 0 on success, OS specific error code on failure.
+ * @param   pRdr        The file provider instance.
+ * @param   pv          The address passed to pfnMap.
+ * @param   cb          The size passed to pfnMap.
+ */
+int kLdrRdrUnmap(PKLDRRDR pRdr, void *pv, size_t cb)
+{
+    KLDRRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnUnmap(pRdr, pv, cb);
+}
+
+
+/**
+ * Releases the memory region prepared by pfnPrepare().
+ *
+ * Before calling this function, all sections mapped by pfnMap must first be unmapped by calling pfnUnmap.
+ *
+ * @returns 0 on success, OS specific error code on failure.
+ * @param   pRdr        The file provider instance.
+ * @param   pv          The address of the prepared region.
+ * @param   cb          The size of the prepared region.
+ */
+int kLdrRdrUnprepare(PKLDRRDR pRdr, void *pv, size_t cb)
+{
+    KLDRRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnUnprepare(pRdr, pv, cb);
+}
+
+
+/**
+ * We're done reading from the file but would like to keep file mappings.
+ *
+ * If the OS support closing the file handle while the file is mapped,
+ * the reader should do so.
+ *
+ * @param   pRdr        The file provider instance.
+ */
+void kLdrRdrDone(PKLDRRDR pRdr)
+{
+    KLDRRDR_VALIDATE_VOID(pRdr);
+    pRdr->pOps->pfnDone(pRdr);
+}
+
