Index: /trunk/kStuff/include/k/kHlpAssert.h
===================================================================
--- /trunk/kStuff/include/k/kHlpAssert.h	(revision 3543)
+++ /trunk/kStuff/include/k/kHlpAssert.h	(revision 3543)
@@ -0,0 +1,141 @@
+/* $Id$ */
+/** @file
+ * kHlpAssert - Assertion Macros.
+ */
+
+/*
+ * Copyright (c) 2006-2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kStuff.
+ *
+ * kStuff 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.
+ *
+ * kStuff 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 kStuff; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ___kHlpAssert_h___
+#define ___kHlpAssert_h___
+
+#include <k/kHlpDefs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup   grp_kHlpAssert - Assertion Macros
+ * @addtogroup grp_kHlp
+ * @{ */
+
+/** @def K_STRICT
+ * Assertions are enabled when K_STRICT is \#defined. */
+
+/** @def kHlpAssertBreakpoint
+ * Emits a breakpoint instruction or somehow triggers a debugger breakpoint.
+ */
+#ifdef _MSC_VER
+# define kHlpAssertBreakpoint() do { __debugbreak(); } while (0)
+#elif defined(__GNUC__)
+# define kHlpAssertBreakpoint() do { __asm__ __volatile__ ("int3"); } while (0)
+#else
+# error "Port Me"
+#endif
+
+#ifdef K_STRICT
+
+# define kHlpAssert(expr) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, __FUNCTION__); \
+            kHlpAssertBreakpoint(); \
+        }
+    } while (0)
+
+# define kHlpAssertReturn(expr, rcRet) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, __FUNCTION__); \
+            kHlpAssertBreakpoint(); \
+            return (rcRet); \
+        }
+    } while (0)
+
+# define kHlpAssertMsg(expr, msg) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, __FUNCTION__); \
+            kHlpAssertMsg2 msg; \
+            kHlpAssertBreakpoint(); \
+        }
+    } while (0)
+
+# define kHlpAssertMsgReturn(expr, msg, rcRet) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, __FUNCTION__); \
+            kHlpAssertMsg2 msg; \
+            kHlpAssertBreakpoint(); \
+            return (rcRet); \
+        }
+    } while (0)
+
+#else   /* !K_STRICT */
+# define kHlpAssert(expr)                       do { } while (0)
+# define kHlpAssertReturn(expr, rcRet)          do { if (!(expr)) return (rcRet); } while (0)
+# define kHlpAssertMsg(expr, msg)               do { } while (0)
+# define kHlpAssertMsgReturn(expr, msg, rcRet)  do { if (!(expr)) return (rcRet); } while (0)
+#endif  /* !K_STRICT */
+
+#define kHlpAssertPtr(ptr)                      kHlpAssertMsg(K_VALID_PTR(ptr), ("%s = %p\n", #ptr, (ptr)))
+#define kHlpAssertPtrReturn(ptr, rcRet)         kHlpAssertMsgReturn(K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)), (rcRet))
+#define kHlpAssertPtrNull(ptr)                  kHlpAssertMsg(!(ptr) || K_VALID_PTR(ptr), ("%s = %p\n", #ptr, (ptr)))
+#define kHlpAssertPtrNullReturn(ptr, rcRet)     kHlpAssertMsgReturn(!(ptr) || K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)), (rcRet))
+#define kHlpAssertRC(rc)                        kHlpAssertMsg((rc) == 0, ("%s = %d\n", #rc, (rc)))
+#define kHlpAssertRCReturn(rc, rcRet)           kHlpAssertMsgReturn((rc) == 0, ("%s = %d -> %d\n", #rc, (rc), (rcRet)), (rcRet))
+#define kHlpAssertFailed()                      kHlpAssert(0)
+#define kHlpAssertFailedReturn(rcRet)           kHlpAssertReturn(0, (rcRet))
+#define kHlpAssertMsgFailed(msg)                kHlpAssertMsg(0, msg)
+#define kHlpAssertMsgFailedReturn(msg, rcRet)   kHlpAssertMsgReturn(0, msg, (rcRet))
+
+/**
+ * Helper function that displays the first part of the assertion message.
+ *
+ * @param   pszExpr         The expression.
+ * @param   pszFile         The file name.
+ * @param   iLine           The line number is the file.
+ * @param   pszFunction     The function name.
+ * @internal
+ */
+KHLP_DECL(void) kHlpAssertMsg1(const char *pszExpr, const char *pszFile, unsigned iLine, const char *pszFunction);
+
+/**
+ * Helper function that displays custom assert message.
+ *
+ * @param   pszFormat       Format string that get passed to vprintf.
+ * @param   ...             Format arguments.
+ * @internal
+ */
+KHLP_DECL(void) kHlpAssertMsg2(const char *pszFormat, ...);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /trunk/kStuff/include/k/kHlpDefs.h
===================================================================
--- /trunk/kStuff/include/k/kHlpDefs.h	(revision 3543)
+++ /trunk/kStuff/include/k/kHlpDefs.h	(revision 3543)
@@ -0,0 +1,51 @@
+/* $Id$ */
+/** @file
+ * kHlpDefs - Helper Definitions.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kStuff.
+ *
+ * kStuff 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.
+ *
+ * kStuff 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 kStuff; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ___k_kHlpDefs_h___
+#define ___k_kHlpDefs_h___
+
+#include <k/kDefs.h>
+
+/** @defgroup grp_kHlpDefs - Definitions
+ * @addtogroup grp_kHlp
+ * @{ */
+
+/** @def KHLP_DECL
+ * Declares a kHlp function according to build context.
+ * @param type          The return type.
+ */
+#if defined(KHLP_BUILDING_DYNAMIC)
+# define KHLP_DECL(type)    K_DECL_EXPORT(type)
+#elif defined(KHLP_BUILT_DYNAMIC)
+# define KHLP_DECL(type)    K_DECL_IMPORT(type)
+#else
+# define KHLP_DECL(type)    type
+#endif
+
+/** @} */
+
+#endif
+
Index: /trunk/kStuff/include/k/kMagics.h
===================================================================
--- /trunk/kStuff/include/k/kMagics.h	(revision 3543)
+++ /trunk/kStuff/include/k/kMagics.h	(revision 3543)
@@ -0,0 +1,37 @@
+/* $Id$ */
+/** @file
+ * kMagics - Various Magic Constants.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kStuff.
+ *
+ * kStuff 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.
+ *
+ * kStuff 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 kStuff; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifndef ___k_kMagics_h___
+#define ___k_kMagics_h___
+
+/** The magic for KRDR::u32Magic. (Katsu Aki (Katsuaki Nakamura))
+ * @ingroup grp_kDbgAll */
+#define KRDR_MAGIC   0x19610919
+
+
+#endif
+
Index: /trunk/kStuff/include/k/kRdr.h
===================================================================
--- /trunk/kStuff/include/k/kRdr.h	(revision 3542)
+++ /trunk/kStuff/include/k/kRdr.h	(revision 3543)
@@ -29,9 +29,5 @@
 
 #include <k/kDefs.h>
-#ifndef ___k_kLdr___
-/* avoid dragging in kLdr.h */
-typedef enum KLDRPROT { KLDRPROT_32BIT_HACK = 0x7fffffff } KLDRPROT;
-typedef const struct KLDRSEG *PCKLDRSEG;
-#endif
+#include <k/kTypes.h>
 
 #ifdef __cplusplus
@@ -43,87 +39,13 @@
  * @{ */
 
-/** Pointer to a file provider instance core. */
+/** Pointer to a file provider instance. */
 typedef struct KRDR *PKRDR;
-/** Pointer to a file provider instance core pointer. */
+/** Pointer to a file provider instance pointer. */
 typedef struct KRDR **PPKRDR;
-
-/**
- * File provider instance operations.
- */
-typedef struct KRDROPS
-{
-    /** The name of this file provider. */
-    const char *pszName;
-    /** Pointer to the next file provider. */
-    const struct KRDROPS *pNext;
-
-    /** Try create a new file provider instance.
-     *
-     * @returns 0 on success, OS specific error code on failure.
-     * @param   ppRdr       Where to store the file provider instance.
-     * @param   pszFilename The filename to open.
-     */
-    int     (* pfnCreate)(  PPKRDR ppRdr, const char *pszFilename);
-    /** Destroy the file provider instance.
-     *
-     * @returns 0 on success, OS specific error code on failure.
-     *          On failure, the file provider instance will be in an indeterminate state - don't touch it!
-     * @param   pRdr        The file provider instance.
-     */
-    int     (* pfnDestroy)( PKRDR pRdr);
-    /** @copydoc kRdrRead */
-    int     (* pfnRead)(    PKRDR pRdr, void *pvBuf, size_t cb, KLDRFOFF off);
-    /** @copydoc kRdrAllMap */
-    int     (* pfnAllMap)(  PKRDR pRdr, const void **ppvBits);
-    /** @copydoc kRdrAllUnmap */
-    int     (* pfnAllUnmap)(PKRDR pRdr, const void *pvBits);
-    /** @copydoc kRdrSize */
-    KFOFF   (* pfnSize)(    PKRDR pRdr);
-    /** @copydoc kRdrTell */
-    KFOFF   (* pfnTell)(    PKRDR pRdr);
-    /** @copydoc kRdrName */
-    const char * (* pfnName)(PKRDR pRdr);
-    /** @copydoc kRdrPageSize */
-    KSIZE   (* pfnPageSize)(PKRDR pRdr);
-    /** @copydoc kRdrMap */
-    int     (* pfnMap)(     PKRDR pRdr, void **ppvBase, KU32 cSegments, PCKLDRSEG paSegments, unsigned fFixed);
-    /** @copydoc kRdrRefresh */
-    int     (* pfnRefresh)( PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments);
-    /** @copydoc kRdrProtect */
-    int     (* pfnProtect)( PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments, unsigned fUnprotectOrProtect);
-    /** @copydoc kRdrUnmap */
-    int     (* pfnUnmap)(   PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments);
-    /** @copydoc kRdrDone */
-    void    (* pfnDone)(    PKRDR pRdr);
-    /** The usual non-zero dummy that makes sure we've initialized all members. */
-    KU32    u32Dummy;
-} KRDROPS;
-/** Pointer to file provider operations. */
-typedef KRDROPS *PKRDROPS;
-/** Pointer to const file provider operations. */
-typedef const KRDROPS *PCKRDROPS;
-
-
-/**
- * File provider instance core.
- */
-typedef struct KRDR
-{
-    /** Magic number (KLDRRDR_MAGIC). */
-    KU32        u32Magic;
-    /** Pointer to the file provider operations. */
-    PCKRDROPS   pOps;
-} KRDR;
-
-/** The magic for KRDR::u32Magic. (Katsu Aki (Katsuaki Nakamura)) */
-#define KRDR_MAGIC   0x19610919
-
-void    kRdrAddProvider(PKRDROPS pAdd);
 
 int     kRdrOpen(PPKRDR ppRdr, const char *pszFilename);
 int     kRdrOpenBuffered(PPKRDR ppRdr, const char *pszFilename);
-
 int     kRdrClose(   PKRDR pRdr);
-int     kRdrRead(    PKRDR pRdr, void *pvBuf, size_t cb, KLDRFOFF off);
+int     kRdrRead(    PKRDR pRdr, void *pvBuf, KSIZE cb, KFOFF off);
 int     kRdrAllMap(  PKRDR pRdr, const void **ppvBits);
 int     kRdrAllUnmap(PKRDR pRdr, const void *pvBits);
@@ -132,10 +54,11 @@
 const char *kRdrName(PKRDR pRdr);
 KIPTR   kRdrNativeFH(PKRDR pRdr);
-
 KSIZE   kRdrPageSize(PKRDR pRdr);
+#ifndef ___k_kLdr___
 int     kRdrMap(     PKRDR pRdr, void **ppvBase, KU32 cSegments, PCKLDRSEG paSegments, unsigned fFixed);
 int     kRdrRefresh( PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments);
 int     kRdrProtect( PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments, unsigned fUnprotectOrProtect);
 int     kRdrUnmap(   PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments);
+#endif /* !___k_kLdr___ */
 void    kRdrDone(    PKRDR pRdr);
 
Index: /trunk/kStuff/include/k/kRdrAll.h
===================================================================
--- /trunk/kStuff/include/k/kRdrAll.h	(revision 3543)
+++ /trunk/kStuff/include/k/kRdrAll.h	(revision 3543)
@@ -0,0 +1,123 @@
+/* $Id$ */
+/** @file
+ * kRdr - The File Provider, All Dependencies Included.
+ */
+
+/*
+ * Copyright (c) 2006-2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kStuff.
+ *
+ * kStuff 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.
+ *
+ * kStuff 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 kStuff; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ___kRdrAll_h___
+#define ___kRdrAll_h___
+
+#include <k/kDefs.h>
+#include "../kLdr/kLdr.h" //later - <k/kLdr.h>
+#include <k/kRdr.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** @defgroup grp_kRdrAll   All
+ * @addtogroup grp_kRdr
+ * @{
+ */
+
+/**
+ * File provider instance operations.
+ */
+typedef struct KRDROPS
+{
+    /** The name of this file provider. */
+    const char *pszName;
+    /** Pointer to the next file provider. */
+    const struct KRDROPS *pNext;
+
+    /** Try create a new file provider instance.
+     *
+     * @returns 0 on success, OS specific error code on failure.
+     * @param   ppRdr       Where to store the file provider instance.
+     * @param   pszFilename The filename to open.
+     */
+    int     (* pfnCreate)(  PPKRDR ppRdr, const char *pszFilename);
+    /** Destroy the file provider instance.
+     *
+     * @returns 0 on success, OS specific error code on failure.
+     *          On failure, the file provider instance will be in an indeterminate state - don't touch it!
+     * @param   pRdr        The file provider instance.
+     */
+    int     (* pfnDestroy)( PKRDR pRdr);
+    /** @copydoc kRdrRead */
+    int     (* pfnRead)(    PKRDR pRdr, void *pvBuf, size_t cb, KFOFF off);
+    /** @copydoc kRdrAllMap */
+    int     (* pfnAllMap)(  PKRDR pRdr, const void **ppvBits);
+    /** @copydoc kRdrAllUnmap */
+    int     (* pfnAllUnmap)(PKRDR pRdr, const void *pvBits);
+    /** @copydoc kRdrSize */
+    KFOFF   (* pfnSize)(    PKRDR pRdr);
+    /** @copydoc kRdrTell */
+    KFOFF   (* pfnTell)(    PKRDR pRdr);
+    /** @copydoc kRdrName */
+    const char * (* pfnName)(PKRDR pRdr);
+    /** @copydoc kRdrNativeFH */
+    KIPTR  (* pfnNativeFH)(PKRDR pRdr);
+    /** @copydoc kRdrPageSize */
+    KSIZE   (* pfnPageSize)(PKRDR pRdr);
+    /** @copydoc kRdrMap */
+    int     (* pfnMap)(     PKRDR pRdr, void **ppvBase, KU32 cSegments, PCKLDRSEG paSegments, unsigned fFixed);
+    /** @copydoc kRdrRefresh */
+    int     (* pfnRefresh)( PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments);
+    /** @copydoc kRdrProtect */
+    int     (* pfnProtect)( PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments, unsigned fUnprotectOrProtect);
+    /** @copydoc kRdrUnmap */
+    int     (* pfnUnmap)(   PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments);
+    /** @copydoc kRdrDone */
+    void    (* pfnDone)(    PKRDR pRdr);
+    /** The usual non-zero dummy that makes sure we've initialized all members. */
+    KU32    u32Dummy;
+} KRDROPS;
+/** Pointer to file provider operations. */
+typedef KRDROPS *PKRDROPS;
+/** Pointer to const file provider operations. */
+typedef const KRDROPS *PCKRDROPS;
+
+
+/**
+ * File provider instance core.
+ */
+typedef struct KRDR
+{
+    /** Magic number (KRDR_MAGIC). */
+    KU32        u32Magic;
+    /** Pointer to the file provider operations. */
+    PCKRDROPS   pOps;
+} KRDR;
+
+void    kRdrAddProvider(PKRDROPS pAdd);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: /trunk/kStuff/kDbg/kDbgModule.cpp
===================================================================
--- /trunk/kStuff/kDbg/kDbgModule.cpp	(revision 3542)
+++ /trunk/kStuff/kDbg/kDbgModule.cpp	(revision 3543)
@@ -6,5 +6,4 @@
 /*
  * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
- *
  *
  * This file is part of kStuff.
@@ -31,5 +30,5 @@
 *   Header Files                                                               *
 *******************************************************************************/
-#include <k/kDbg.h>
+#include <k/kDbgAll.h>
 #include <k/kErrors.h>
 #include <string.h>
Index: /trunk/kStuff/kLdr/kLdrRdr.c
===================================================================
--- /trunk/kStuff/kLdr/kLdrRdr.c	(revision 3542)
+++ /trunk/kStuff/kLdr/kLdrRdr.c	(revision 3543)
@@ -29,5 +29,5 @@
 *   Header Files                                                               *
 *******************************************************************************/
-#include <kLdr.h>
+#include <k/kRdr.h>
 #include "kLdrInternal.h"
 
Index: /trunk/kStuff/kRdr/Makefile.kmk
===================================================================
--- /trunk/kStuff/kRdr/Makefile.kmk	(revision 3543)
+++ /trunk/kStuff/kRdr/Makefile.kmk	(revision 3543)
@@ -0,0 +1,43 @@
+# $Id$
+## @file
+# kRdr - The File Provider.
+#
+
+#
+# Copyright (c) 2006-2007 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kStuff.
+#
+# kStuff 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.
+#
+# kStuff 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 kStuff; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+
+DEPTH = ../..
+include $(PATH_KBUILD)/header.kmk
+
+#
+# kRdrStatic - The file provider module.
+#
+LIBRARIES += kRdrStatic
+kRdrStatic_TEMPLATE = kStuffLIB
+kRdrStatic_DEFS = KDBG_BUILDING
+kRdrStatic_INCS = ../kLdr
+kRdrStatic_SOURCES = \
+	kRdr.c \
+	kRdrFile.c
+
+# Generate the rules
+include $(PATH_KBUILD)/footer.kmk
+
Index: /trunk/kStuff/kRdr/kRdr.c
===================================================================
--- /trunk/kStuff/kRdr/kRdr.c	(revision 3543)
+++ /trunk/kStuff/kRdr/kRdr.c	(revision 3543)
@@ -0,0 +1,280 @@
+/* $Id$ */
+/** @file
+ * kRdr - The File Provider.
+ */
+
+/*
+ * Copyright (c) 2006-2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kStuff.
+ *
+ * kStuff 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.
+ *
+ * kStuff 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 kStuff; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kRdrAll.h>
+#include <k/kErrors.h>
+#include "kRdrInternal.h"
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** The list of file providers. */
+static PCKRDROPS g_pRdrHead = &g_kRdrFileOps;
+
+
+/**
+ * Adds a new file provider.
+ *
+ * @param   pAdd        The new file provider.
+ */
+void kRdrAddProvider(PKRDROPS pAdd)
+{
+    pAdd->pNext = g_pRdrHead;
+    g_pRdrHead = pAdd;
+}
+
+
+/**
+ * Tries to opens a file.
+ *
+ * @returns 0 on success, OS status code on failure.
+ * @param   ppRdr           Where to store the file provider instance.
+ * @param   pszFilename     The filename.
+ */
+int kRdrOpen(PPKRDR ppRdr, const char *pszFilename)
+{
+    int             rc = -1;
+    PCKRDROPS    pCur;
+    for (pCur = g_pRdrHead; pCur; pCur = pCur->pNext)
+    {
+        rc = pCur->pfnCreate(ppRdr, pszFilename);
+        if (!rc)
+            return 0;
+    }
+    return rc;
+}
+
+
+/**
+ * Closes the file.
+ *
+ * @returns 0 on success, OS specific error code on failure.
+ *          On failure, the file provider instance will be in an indeterminate state - don't touch it!
+ * @param   pRdr        The file provider instance.
+ */
+int kRdrClose(PKRDR pRdr)
+{
+    KRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnDestroy(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.
+ */
+int kRdrRead(PKRDR pRdr, void *pvBuf, KSIZE cb, KFOFF off)
+{
+    KRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnRead(pRdr, pvBuf, cb, 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.
+ */
+int kRdrAllMap(PKRDR pRdr, const void **ppvBits)
+{
+    KRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnAllMap(pRdr, ppvBits);
+}
+
+
+/** Unmap a file bits mapping obtained by KRDROPS::pfnAllMap.
+ *
+ * @returns 0 on success, OS specific error code on failure.
+ * @param   pRdr        The file provider instance.
+ * @param   pvBits      The mapping address.
+ */
+int kRdrAllUnmap(PKRDR pRdr, const void *pvBits)
+{
+    KRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnAllUnmap(pRdr, pvBits);
+}
+
+
+/** Get the file size.
+ *
+ * @returns The file size. Returns -1 on failure.
+ * @param   pRdr        The file provider instance.
+ */
+KFOFF kRdrSize(PKRDR pRdr)
+{
+    KRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnSize(pRdr);
+}
+
+
+/** Get the file pointer offset.
+ *
+ * @returns The file pointer offset. Returns -1 on failure.
+ * @param   pRdr        The file provider instance.
+ */
+KFOFF kRdrTell(PKRDR pRdr)
+{
+    KRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnTell(pRdr);
+}
+
+
+/** Get the file name.
+ *
+ * @returns The file name. Returns NULL on failure.
+ * @param   pRdr        The file provider instance.
+ */
+const char *kRdrName(PKRDR pRdr)
+{
+    KRDR_VALIDATE_EX(pRdr, NULL);
+    return pRdr->pOps->pfnName(pRdr);
+}
+
+
+/** Get the native file handle if possible.
+ *
+ * @returns The native file handle. Returns -1 if not available.
+ * @param   pRdr        The file provider instance.
+ */
+KIPTR kRdrNativeFH(PKRDR pRdr)
+{
+    KRDR_VALIDATE_EX(pRdr, -1);
+    return pRdr->pOps->pfnNativeFH(pRdr);
+}
+
+
+/**
+ * Gets the page size used when mapping sections of the file.
+ *
+ * @returns The page size.
+ * @param   pRdr        The file provider instance.
+ */
+KSIZE kRdrPageSize(PKRDR pRdr)
+{
+    KRDR_VALIDATE_EX(pRdr, 0x10000);
+    return pRdr->pOps->pfnPageSize(pRdr);
+}
+
+
+/**
+ * Maps the segments of a image into memory.
+ *
+ * The file reader will be using the RVA member of each segment to figure out where
+ * it goes relative to the image base address.
+ *
+ * @returns 0 on success, OS specific error code on failure.
+ * @param   pRdr        The file provider instance.
+ * @param   ppvBase     On input when fFixed is set, this contains the base address of the mapping.
+ *                      On output this contains the base of the image mapping.
+ * @param   cSegments   The number of segments in the array pointed to by paSegments.
+ * @param   paSegments  The segments thats going to be mapped.
+ * @param   fFixed      If set, the address at *ppvBase should be the base address of the mapping.
+ */
+int kRdrMap(PKRDR pRdr, void **ppvBase, KU32 cSegments, PCKLDRSEG paSegments, unsigned fFixed)
+{
+    KRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnMap(pRdr, ppvBase, cSegments, paSegments, fFixed);
+}
+
+
+/**
+ * Reloads dirty pages in mapped image.
+ *
+ * @returns 0 on success, OS specific error code on failure.
+ * @param   pRdr        The file provider instance.
+ * @param   pvBase      The base address of the image mapping.
+ * @param   cSegments   The number of segments in the array pointed to by paSegments.
+ * @param   paSegments  The segments thats going to be mapped.
+ */
+int kRdrRefresh(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments)
+{
+    KRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnRefresh(pRdr, pvBase, cSegments, paSegments);
+}
+
+
+/**
+ * Protects or unprotects an image mapping.
+ *
+ * This is typically used for getting write access to read or execute only
+ * pages while applying fixups.
+ *
+ * @returns 0 on success, OS specific error code on failure.
+ * @param   pRdr        The file provider instance.
+ * @param   pvBase      The base address of the image mapping.
+ * @param   cSegments   The number of segments in the array pointed to by paSegments.
+ * @param   paSegments  The segments thats going to be mapped.
+ * @param   fUnprotectOrProtect     When set the all mapped segments are made writable.
+ *                                  When clean the segment protection is restored.
+ */
+int kRdrProtect(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments, unsigned fUnprotectOrProtect)
+{
+    KRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnProtect(pRdr, pvBase, cSegments, paSegments, fUnprotectOrProtect);
+}
+
+
+/**
+ * Unmaps a image mapping.
+ *
+ * @returns 0 on success, OS specific error code on failure.
+ * @param   pRdr        The file provider instance.
+ * @param   pvBase      The base address of the image mapping.
+ * @param   cSegments   The number of segments in the array pointed to by paSegments.
+ * @param   paSegments  The segments thats going to be mapped.
+ */
+int kRdrUnmap(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments)
+{
+    KRDR_VALIDATE(pRdr);
+    return pRdr->pOps->pfnUnmap(pRdr, pvBase, cSegments, paSegments);
+}
+
+
+/**
+ * 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 kRdrDone(PKRDR pRdr)
+{
+    KRDR_VALIDATE_VOID(pRdr);
+    pRdr->pOps->pfnDone(pRdr);
+}
+
Index: /trunk/kStuff/kRdr/kRdrFile.c
===================================================================
--- /trunk/kStuff/kRdr/kRdrFile.c	(revision 3543)
+++ /trunk/kStuff/kRdr/kRdrFile.c	(revision 3543)
@@ -0,0 +1,1181 @@
+/* $Id$ */
+/** @file
+ *
+ * kLdr - The Dynamic Loader, file abstraction.
+ *
+ * Copyright (c) 2006 knut st. osmundsen <bird-kbuild-src@anduin.net>
+ *
+ *
+ * This file is part of kLdr.
+ *
+ * kLdr is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * kLdr is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with kLdr; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#ifdef __OS2__
+# define INCL_ERRORS
+# define INCL_BASE
+# include <os2.h>
+
+#elif defined(__WIN32__) || defined(__WIN64__) || defined(__WIN__)
+# define WIN32_NO_STATUS
+# include <Windows.h>
+# ifndef __WIN__
+#  define __WIN__
+# endif
+# include <ntsecapi.h>
+# include <ntstatus.h>
+
+  /** @todo find a non-conflicting header with NTSTATUS, NTAPI, ++ */
+  typedef LONG NTSTATUS;
+  #define NT_SUCCESS(x) ((x)>=0)
+
+  typedef struct _OBJECT_ATTRIBUTES
+  {
+      ULONG   Length;
+      HANDLE  RootDirectory;
+      PUNICODE_STRING ObjectName;
+      ULONG   Attributes;
+      PVOID   SecurityDescriptor;
+      PVOID   SecurityQualityOfService;
+  } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
+
+  typedef enum _SECTION_INHERIT
+  {
+      ViewShare = 1,
+      ViewUnmap = 2
+  } SECTION_INHERIT;
+
+# define NTOSAPI __declspec(dllimport)
+# define NtCurrentProcess() GetCurrentProcess()
+
+# ifndef MEM_DOS_LIM
+#  define MEM_DOS_LIM 0x40000000UL
+# endif
+
+  NTOSAPI
+  NTSTATUS
+  NTAPI
+  NtCreateSection(
+      OUT PHANDLE SectionHandle,
+      IN ACCESS_MASK DesiredAccess,
+      IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+      IN PLARGE_INTEGER SectionSize OPTIONAL,
+      IN ULONG Protect,
+      IN ULONG Attributes,
+      IN HANDLE FileHandle OPTIONAL
+  );
+
+  NTOSAPI
+  NTSTATUS
+  NTAPI
+  NtMapViewOfSection(
+      IN HANDLE SectionHandle,
+      IN HANDLE ProcessHandle,
+      IN OUT PVOID *BaseAddress,
+      IN ULONG ZeroBits,
+      IN ULONG CommitSize,
+      IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
+      IN OUT PSIZE_T ViewSize,
+      IN SECTION_INHERIT InheritDisposition,
+      IN ULONG AllocationType,
+      IN ULONG Protect
+  );
+
+  NTOSAPI
+  NTSTATUS
+  NTAPI
+  NtUnmapViewOfSection(
+      IN HANDLE ProcessHandle,
+      IN PVOID BaseAddress
+  );
+
+  NTOSAPI
+  NTSTATUS
+  NTAPI
+  NtClose(
+      IN HANDLE Handle
+  );
+
+  NTOSAPI
+  NTSTATUS
+  NTAPI
+  ZwProtectVirtualMemory(
+      IN HANDLE ProcessHandle,
+      IN OUT PVOID *BaseAddress,
+      IN OUT PULONG ProtectSize,
+      IN ULONG NewProtect,
+      OUT PULONG OldProtect
+  );
+# define NtProtectVirtualMemory ZwProtectVirtualMemory
+
+  NTOSAPI
+  NTSTATUS
+  NTAPI
+  NtAllocateVirtualMemory(
+      IN HANDLE ProcessHandle,
+      IN OUT PVOID *BaseAddress,
+      IN ULONG ZeroBits,
+      IN OUT PULONG AllocationSize,
+      IN ULONG AllocationType,
+      IN ULONG Protect
+  );
+
+  NTOSAPI
+  NTSTATUS
+  NTAPI
+  NtFreeVirtualMemory(
+      IN HANDLE ProcessHandle,
+      IN OUT PVOID *BaseAddress,
+      IN OUT PULONG FreeSize,
+      IN ULONG FreeType
+  );
+
+#else
+# error "port me"
+#endif
+
+#include <kLdr.h>
+#include "kLdrHlp.h"
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** @def KLDRRDRFILE_STRICT
+ * Define KLDRRDRFILE_STRICT to enabled strict checks in KLDRRDRFILE. */
+#define KLDRRDRFILE_STRICT 1
+
+/** @def KLDRRDRFILE_ASSERT
+ * Assert that an expression is true when KLDRRDRFILE_STRICT is defined.
+ */
+#ifdef KLDRRDRFILE_STRICT
+# define KLDRRDRFILE_ASSERT(expr)  kldrHlpAssert(expr)
+#else
+# define KLDRRDRFILE_ASSERT(expr)  do {} while (0)
+#endif
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Prepared stuff.
+ */
+typedef struct KLDRRDRFILEPREP
+{
+    /** The address of the prepared region. */
+    void           *pv;
+    /** The size of the prepared region. */
+    size_t          cb;
+#if defined(__WIN__) || defined(__NT__)
+    /** Handle to the section created to map the file. */
+    HANDLE          hSection;
+#endif
+} KLDRRDRFILEPREP, *PKLDRRDRFILEPREP;
+
+/**
+ * The file provier instance for native files.
+ */
+typedef struct KLDRRDRFILE
+{
+    /** The file reader vtable. */
+    KLDRRDR             Core;
+    /** The file handle. */
+#ifdef __OS2__
+    HFILE               File;
+#elif defined(__WIN__) || defined(__NT__)
+    HANDLE              File;
+#else
+# error "Port me!"
+#endif
+    /** The current file offset. */
+    KLDRFOFF            off;
+    /** The file size. */
+    KLDRFOFF            cb;
+    /** Array where we stuff the mapping area data. */
+    KLDRRDRFILEPREP     aPreps[4];
+    /** The number of current preps. */
+    uint32_t            cPreps;
+    /** Number of mapping references. */
+    int32_t             cMappings;
+    /** The memory mapping. */
+    void               *pvMapping;
+    /** The filename. */
+    char                szFilename[1];
+} KLDRRDRFILE, *PKLDRRDRFILE;
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static void     kldrRdrFileDone(PKLDRRDR pRdr);
+static int      kldrRdrFileUnmap(PKLDRRDR pRdr, void *pvBase, uint32_t cSegments, PCKLDRSEG paSegments);
+static int      kldrRdrFileGenericUnmap(PKLDRRDR pRdr, PKLDRRDRFILEPREP pPrep, uint32_t cSegments, PCKLDRSEG paSegments);
+static int      kldrRdrFileProtect(PKLDRRDR pRdr, void *pvBase, uint32_t cSegments, PCKLDRSEG paSegments, unsigned fUnprotectOrProtect);
+static int      kldrRdrFileGenericProtect(PKLDRRDR pRdr, PKLDRRDRFILEPREP pPrep, uint32_t cSegments, PCKLDRSEG paSegments, unsigned fUnprotectOrProtect);
+static int      kldrRdrFileRefresh(PKLDRRDR pRdr, void *pvBase, uint32_t cSegments, PCKLDRSEG paSegments);
+static int      kldrRdrFileGenericRefresh(PKLDRRDR pRdr, PKLDRRDRFILEPREP pPrep, uint32_t cSegments, PCKLDRSEG paSegments);
+static int      kldrRdrFileMap(PKLDRRDR pRdr, void **ppvBase, uint32_t cSegments, PCKLDRSEG paSegments, unsigned fFixed);
+static int      kldrRdrFileGenericMap(PKLDRRDR pRdr, PKLDRRDRFILEPREP pPrep, uint32_t cSegments, PCKLDRSEG paSegments, unsigned fFixed);
+static size_t   kldrRdrFilePageSize(PKLDRRDR pRdr);
+static const char *kldrRdrFileName(PKLDRRDR pRdr);
+static KLDRFOFF kldrRdrFileTell(PKLDRRDR pRdr);
+static KLDRFOFF kldrRdrFileSize(PKLDRRDR pRdr);
+static int      kldrRdrFileAllUnmap(PKLDRRDR pRdr, const void *pvBits);
+static int      kldrRdrFileAllMap(PKLDRRDR pRdr, const void **ppvBits);
+static int      kldrRdrFileRead(PKLDRRDR pRdr, void *pvBuf, size_t cb, KLDRFOFF off);
+static int      kldrRdrFileDestroy(PKLDRRDR pRdr);
+static int      kldrRdrFileCreate(PPKLDRRDR ppRdr, const char *pszFilename);
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** Native file provider operations. */
+const KLDRRDROPS g_kLdrRdrFileOps =
+{
+    "native file",
+    NULL,
+    kldrRdrFileCreate,
+    kldrRdrFileDestroy,
+    kldrRdrFileRead,
+    kldrRdrFileAllMap,
+    kldrRdrFileAllUnmap,
+    kldrRdrFileSize,
+    kldrRdrFileTell,
+    kldrRdrFileName,
+    kldrRdrFilePageSize,
+    kldrRdrFileMap,
+    kldrRdrFileRefresh,
+    kldrRdrFileProtect,
+    kldrRdrFileUnmap,
+    kldrRdrFileDone,
+    42
+};
+
+
+#if defined(__WIN__) || defined(__NT__)
+/**
+ * Converts a kLdr segment protection to NT protection for a mapping.
+ *
+ * @returns Nt page protection.
+ * @param   enmProt     kLdr protection.
+ */
+static ULONG kldrRdrFileGetNtMapProt(KLDRPROT enmProt)
+{
+    switch (enmProt)
+    {
+        case KLDRPROT_NOACCESS:             return PAGE_NOACCESS;
+        case KLDRPROT_READONLY:             return PAGE_READONLY;
+        case KLDRPROT_READWRITE:            return PAGE_READWRITE;
+        case KLDRPROT_WRITECOPY:            return PAGE_WRITECOPY;
+        case KLDRPROT_EXECUTE:              return PAGE_EXECUTE;
+        case KLDRPROT_EXECUTE_READ:         return PAGE_EXECUTE_READ;
+        case KLDRPROT_EXECUTE_READWRITE:    return PAGE_EXECUTE_READWRITE;
+        case KLDRPROT_EXECUTE_WRITECOPY:    return PAGE_EXECUTE_WRITECOPY;
+        default:                            return ~(ULONG)0;
+    }
+}
+
+
+/**
+ * Converts a kLdr segment protection to NT protection for a allocation.
+ *
+ * @returns Nt page protection.
+ * @param   enmProt     kLdr protection.
+ */
+static ULONG kldrRdrFileGetNtAllocProt(KLDRPROT enmProt)
+{
+    switch (enmProt)
+    {
+        case KLDRPROT_NOACCESS:             return PAGE_NOACCESS;
+        case KLDRPROT_READONLY:             return PAGE_READONLY;
+        case KLDRPROT_WRITECOPY:
+        case KLDRPROT_READWRITE:            return PAGE_READWRITE;
+        case KLDRPROT_EXECUTE:              return PAGE_EXECUTE;
+        case KLDRPROT_EXECUTE_READ:         return PAGE_EXECUTE_READ;
+        case KLDRPROT_EXECUTE_WRITECOPY:
+        case KLDRPROT_EXECUTE_READWRITE:    return PAGE_EXECUTE_READWRITE;
+        default:                            return ~(ULONG)0;
+    }
+}
+#endif
+
+
+/** @copydoc KLDRRDR::pfnDone */
+static void     kldrRdrFileDone(PKLDRRDR pRdr)
+{
+}
+
+
+/**
+ * Finds a prepared mapping region.
+ *
+ * @returns Pointer to the aPrep entry.
+ * @param   pFile   The instance data.
+ * @param   pv      The base of the region.
+ */
+static PKLDRRDRFILEPREP kldrRdrFileFindPrepExact(PKLDRRDRFILE pFile, void *pv)
+{
+    int32_t i = pFile->cPreps;
+    while (i-- > 0)
+        if (pFile->aPreps[i].pv == pv)
+            return &pFile->aPreps[i];
+    return NULL;
+}
+
+
+/** @copydoc KLDRRDR::pfnUnmap */
+static int      kldrRdrFileUnmap(PKLDRRDR pRdr, void *pvBase, uint32_t cSegments, PCKLDRSEG paSegments)
+{
+    PKLDRRDRFILE        pRdrFile = (PKLDRRDRFILE)pRdr;
+    PKLDRRDRFILEPREP    pPrep = kldrRdrFileFindPrepExact(pRdrFile, pvBase);
+    int                 rc;
+    if (!pPrep)
+        return KLDR_ERR_INVALID_PARAMETER;
+
+#if defined(__WIN__) || defined(__NT__)
+    if (pPrep->hSection != NULL)
+    {
+        /** @todo implement me. */
+        return -1;
+    }
+#endif
+
+    rc = kldrRdrFileGenericUnmap(pRdr, pPrep, cSegments, paSegments);
+
+    /* remove the mapping data on success. */
+    if (!rc)
+    {
+        pRdrFile->cPreps--;
+        if (pPrep != &pRdrFile->aPreps[pRdrFile->cPreps])
+            *pPrep = pRdrFile->aPreps[pRdrFile->cPreps];
+    }
+    return rc;
+}
+
+
+/** Generic implementation of kldrRdrFileUnmap. */
+static int kldrRdrFileGenericUnmap(PKLDRRDR pRdr, PKLDRRDRFILEPREP pPrep, uint32_t cSegments, PCKLDRSEG paSegments)
+{
+    kldrRdrFileGenericProtect(pRdr, pPrep, cSegments, paSegments, 1 /* unprotect */);
+    return kldrHlpPageFree(pPrep->pv, pPrep->cb);
+}
+
+
+/** @copydoc KLDRRDR::pfnProtect */
+static int      kldrRdrFileProtect(PKLDRRDR pRdr, void *pvBase, uint32_t cSegments, PCKLDRSEG paSegments, unsigned fUnprotectOrProtect)
+{
+    PKLDRRDRFILE        pRdrFile = (PKLDRRDRFILE)pRdr;
+    PKLDRRDRFILEPREP    pPrep = kldrRdrFileFindPrepExact(pRdrFile, pvBase);
+    if (!pPrep)
+        return KLDR_ERR_INVALID_PARAMETER;
+
+#if defined(__WIN__) || defined(__NT__)
+    if (pPrep->hSection != NULL)
+    {
+        /** @todo implement me. */
+        return -1;
+    }
+#endif
+
+    return kldrRdrFileGenericProtect(pRdr, pPrep, cSegments, paSegments, fUnprotectOrProtect);
+}
+
+
+/** Generic implementation of kldrRdrFileProtect. */
+static int kldrRdrFileGenericProtect(PKLDRRDR pRdr, PKLDRRDRFILEPREP pPrep, uint32_t cSegments, PCKLDRSEG paSegments, unsigned fUnprotectOrProtect)
+{
+    uint32_t i;
+
+    /*
+     * Iterate the segments and apply memory protection changes.
+     */
+    for (i = 0; i < cSegments; i++)
+    {
+        int rc;
+        void *pv;
+        KLDRPROT enmProt;
+
+        if (paSegments[i].RVA == NIL_KLDRADDR)
+            continue;
+
+        /* calc new protection. */
+        enmProt = paSegments[i].enmProt;
+        if (fUnprotectOrProtect)
+        {
+            switch (enmProt)
+            {
+                case KLDRPROT_NOACCESS:
+                case KLDRPROT_READONLY:
+                case KLDRPROT_READWRITE:
+                case KLDRPROT_WRITECOPY:
+                    enmProt = KLDRPROT_READWRITE;
+                    break;
+                case KLDRPROT_EXECUTE:
+                case KLDRPROT_EXECUTE_READ:
+                case KLDRPROT_EXECUTE_READWRITE:
+                case KLDRPROT_EXECUTE_WRITECOPY:
+                    enmProt = KLDRPROT_EXECUTE_READWRITE;
+                    break;
+                default:
+                    KLDRRDRFILE_ASSERT(!"bad enmProt");
+                    return -1;
+            }
+        }
+        else
+        {
+            /* copy on write -> normal write. */
+            if (enmProt == KLDRPROT_EXECUTE_WRITECOPY)
+                enmProt = KLDRPROT_EXECUTE_READWRITE;
+            else if (enmProt == KLDRPROT_WRITECOPY)
+                enmProt = KLDRPROT_READWRITE;
+        }
+
+        pv = (uint8_t *)pPrep->pv + paSegments[i].RVA;
+
+        rc = kldrHlpPageProtect(pv, paSegments[i].cbMapped, enmProt);
+        if (rc)
+            break;
+    }
+
+    return 0;
+}
+
+
+/** @copydoc KLDRRDR::pfnRefresh */
+static int      kldrRdrFileRefresh(PKLDRRDR pRdr, void *pvBase, uint32_t cSegments, PCKLDRSEG paSegments)
+{
+    PKLDRRDRFILE        pRdrFile = (PKLDRRDRFILE)pRdr;
+    PKLDRRDRFILEPREP    pPrep = kldrRdrFileFindPrepExact(pRdrFile, pvBase);
+    if (!pPrep)
+        return KLDR_ERR_INVALID_PARAMETER;
+
+#if defined(__WIN__) || defined(__NT__)
+    if (pPrep->hSection != NULL)
+    {
+        /** @todo implement me. */
+        return -1;
+    }
+#endif
+
+    return kldrRdrFileGenericRefresh(pRdr, pPrep, cSegments, paSegments);
+}
+
+
+/** Generic implementation of kldrRdrFileRefresh. */
+static int      kldrRdrFileGenericRefresh(PKLDRRDR pRdr, PKLDRRDRFILEPREP pPrep, uint32_t cSegments, PCKLDRSEG paSegments)
+{
+    int rc;
+    int rc2;
+    uint32_t i;
+
+    /*
+     * Make everything writable again.
+     */
+    rc = kldrRdrFileGenericProtect(pRdr, pPrep, cSegments, paSegments, 1 /* unprotect */);
+    if (rc)
+    {
+        kldrRdrFileGenericProtect(pRdr, pPrep, cSegments, paSegments, 0 /* protect */);
+        return rc;
+    }
+
+    /*
+     * Clear everything.
+     */
+    /** @todo only zero the areas not covered by raw file bits. */
+    kLdrHlpMemSet(pPrep->pv, 0, pPrep->cb);
+
+    /*
+     * Reload all the segments.
+     * We could possibly skip some segments, but we currently have
+     * no generic way of figuring out which at the moment.
+     */
+    for (i = 0; i < cSegments; i++)
+    {
+        void *pv;
+
+        if (    paSegments[i].RVA == NIL_KLDRADDR
+            ||  paSegments[i].cbFile <= 0)
+            continue;
+
+        pv = (uint8_t *)pPrep->pv + paSegments[i].RVA;
+        rc = pRdr->pOps->pfnRead(pRdr, pv, paSegments[i].cbFile, paSegments[i].offFile);
+        if (rc)
+            break;
+    }
+
+    /*
+     * Protect the bits again.
+     */
+    rc2 = kldrRdrFileGenericProtect(pRdr, pPrep, cSegments, paSegments, 0 /* protect */);
+    if (rc2 && rc)
+        rc = rc2;
+
+    return rc;
+}
+
+
+/** @copydoc KLDRRDR::pfnMap */
+static int      kldrRdrFileMap(PKLDRRDR pRdr, void **ppvBase, uint32_t cSegments, PCKLDRSEG paSegments, unsigned fFixed)
+{
+    PKLDRRDRFILE        pRdrFile = (PKLDRRDRFILE)pRdr;
+    PKLDRRDRFILEPREP    pPrep = &pRdrFile->aPreps[pRdrFile->cPreps];
+    KLDRSIZE            cbTotal;
+    const size_t        cbPage = pRdr->pOps->pfnPageSize(pRdr);
+    int                 rc;
+    uint32_t            i;
+
+    if (pRdrFile->cPreps >= KLDR_ELEMENTS(pRdrFile->aPreps))
+        return KLDR_ERR_TOO_MANY_MAPPINGS;
+
+    /*
+     * Calc the total mapping space needed.
+     */
+    cbTotal = 0;
+    for (i = 0; i < cSegments; i++)
+    {
+        KLDRSIZE uRVASegmentEnd;
+        if (paSegments[i].RVA == NIL_KLDRADDR)
+            continue;
+        uRVASegmentEnd = paSegments[i].RVA + paSegments[i].cbMapped;
+        if (cbTotal < uRVASegmentEnd)
+            cbTotal = uRVASegmentEnd;
+    }
+    pPrep->cb = (size_t)cbTotal;
+    if (pPrep->cb != cbTotal)
+        return KLDR_ERR_ADDRESS_OVERFLOW;
+    pPrep->cb = (pPrep->cb + (cbPage - 1)) & ~(cbPage- 1);
+
+#if defined(__WIN__) || defined(__NT__)
+    /*
+     * The NT memory mapped file API sucks in a lot of ways. Unless you're actually
+     * trying to map a PE image and the kernel can parse the file for it self, the
+     * API just isn't up to scratch.
+     *
+     * Problems:
+     *      1. Reserving memory for the views is risky because you can't reserve and
+     *         map into the reserved space. So, other threads might grab the memory
+     *         before we get to it.
+     *      2. The page aligning of file offsets makes it impossible to map most
+     *         executable images since these are commonly sector aligned.
+     *      3. When mapping a read+execute file, its not possible to create section
+     *         larger than the file since the section size is bound to the data file
+     *         size. This wouldn't have been such a problem if it was possible to
+     *         map views beyond the section restriction, i.e. have a file size and
+     *         view size.
+     *      4. Only x86 can map views at page granularity it seems, and that only
+     *         using an undocument flag. The default granularity is 64KB.
+     *      5. There is more crappyness here...
+     *
+     * So, first we'll have to check if we can the file using the crappy NT APIs.
+     * Chances are we can't.
+     */
+    for (i = 0; i < cSegments; i++)
+    {
+        if (paSegments[i].RVA == NIL_KLDRADDR)
+            continue;
+
+        /* The file backing of the segments must be page aligned. */
+        if (    paSegments[i].cbFile > 0
+            &&  paSegments[i].offFile & (cbPage - 1))
+            break;
+
+        /* Only page alignment gaps between the file size and the mapping size. */
+        if (    paSegments[i].cbFile > 0
+            &&  (paSegments[i].cbFile & ~(cbPage - 1)) != (paSegments[i].cbMapped & ~(cbPage - 1)) )
+            break;
+
+        /* The mapping addresses of the segments must be page aligned.
+         * Non-x86 will probably require 64KB alignment here. */
+        if (paSegments[i].RVA & (cbPage - 1))
+            break;
+
+        /* If we do have to allocate the segment it's RVA must be 64KB aligned. */
+        if (    paSegments[i].cbFile > 0
+            &&  (paSegments[i].RVA & 0xffff))
+            break;
+    }
+    /** @todo if this is a PE image, we might just try a SEC_IMAGE mapping. It'll work if the host and image machines matches. */
+    if (i == cSegments)
+    {
+        /* WOW! it may work out! Incredible! */
+        SIZE_T          ViewSize;
+        LARGE_INTEGER   SectionOffset;
+        LARGE_INTEGER   MaxiumSize;
+        NTSTATUS        Status;
+        PVOID           pv;
+
+        MaxiumSize.QuadPart = pRdr->pOps->pfnSize(pRdr);
+        if (MaxiumSize.QuadPart > (LONGLONG)cbTotal)
+            MaxiumSize.QuadPart = cbTotal;
+
+        Status = NtCreateSection(&pPrep->hSection,
+                                 SECTION_MAP_EXECUTE | SECTION_MAP_READ,    /* desired access */
+                                 NULL,                                      /* object attributes */
+                                 &MaxiumSize,
+                                 PAGE_EXECUTE_WRITECOPY,                    /* page attributes */
+                                 SEC_COMMIT,                                /* section attributes */
+                                 pRdrFile->File);
+        if (!NT_SUCCESS(Status))
+            return (int)Status;
+
+        /*
+         * Determin the base address.
+         */
+        if (fFixed)
+            pPrep->pv = *ppvBase;
+        else
+        {
+            pv = NULL;
+            ViewSize = (size_t)cbTotal;
+
+            Status = NtAllocateVirtualMemory(NtCurrentProcess(),
+                                             &pv,
+                                             0,                             /* ZeroBits */
+                                             &ViewSize,
+                                             MEM_RESERVE,
+                                             PAGE_READONLY);
+            if (NT_SUCCESS(Status))
+            {
+                pPrep->pv = *ppvBase = pv;
+                ViewSize = 0;
+                Status = NtFreeVirtualMemory(NtCurrentProcess(), &pv, &ViewSize, MEM_RELEASE);
+            }
+            if (!NT_SUCCESS(Status))
+            {
+                NtClose(pPrep->hSection);
+                return Status;
+            }
+        }
+
+        /*
+         * Map the segments.
+         */
+        for (i = 0; i < cSegments; i++)
+        {
+            ULONG fPageProt;
+
+            if (paSegments[i].RVA == NIL_KLDRADDR)
+                continue;
+
+            pv = (uint8_t *)pPrep->pv + paSegments[i].RVA;
+            if (paSegments[i].cbFile > 0)
+            {
+                SectionOffset.QuadPart = paSegments[i].offFile;
+                ViewSize = paSegments[i].cbFile;
+                fPageProt = kldrRdrFileGetNtMapProt(paSegments[i].enmProt);
+                /* STATUS_MAPPED_ALIGNMENT
+                   STATUS_CONFLICTING_ADDRESSES
+                   STATUS_INVALID_VIEW_SIZE */
+                Status = NtMapViewOfSection(pPrep->hSection, NtCurrentProcess(),
+                                            &pv,
+                                            0,                                  /* ZeroBits */
+                                            0,                                  /* CommitSize */
+                                            &SectionOffset,                     /* SectionOffset */
+                                            &ViewSize,
+                                            ViewUnmap,
+                                            MEM_DOS_LIM,                        /* AllocationType */
+                                            fPageProt);
+                /* do we have to zero anything? */
+                if (    NT_SUCCESS(Status)
+                    &&  0/*later*/)
+                {
+                    /*ULONG OldPageProt = 0;
+                      NtProtectVirtualMemory(NtCurrentProcess(), &pv, &ViewSize, , */
+                }
+            }
+            else
+            {
+                ViewSize = paSegments[i].cbMapped;
+                fPageProt = kldrRdrFileGetNtAllocProt(paSegments[i].enmProt);
+                Status = NtAllocateVirtualMemory(NtCurrentProcess(),
+                                                 &pv,
+                                                 0,                             /* ZeroBits */
+                                                 &ViewSize,
+                                                 MEM_COMMIT,
+                                                 fPageProt);
+            }
+            if (!NT_SUCCESS(Status))
+                break;
+        }
+
+        /*
+         * On success, commit the mapping and return.
+         */
+        if (NT_SUCCESS(Status))
+        {
+            pRdrFile->cPreps++;
+            return 0;
+        }
+
+        /* bail out and fall back on the generic code. */
+        while (i-- > 0)
+        {
+            PVOID pv;
+
+            if (paSegments[i].RVA == NIL_KLDRADDR)
+                continue;
+
+            pv = (uint8_t *)pPrep->pv + paSegments[i].RVA;
+            if (paSegments[i].cbFile > 0)
+                NtUnmapViewOfSection(NtCurrentProcess(), pv);
+            else
+                NtFreeVirtualMemory(NtCurrentProcess(), &pv, NULL, MEM_RELEASE);
+        }
+        NtClose(pPrep->hSection);
+    }
+    /* else: fall back to the generic code */
+    pPrep->hSection = NULL;
+#endif
+
+    /*
+     * Use the generic map emulation.
+     */
+    pPrep->pv = fFixed ? *ppvBase : NULL;
+    rc = kldrRdrFileGenericMap(pRdr, pPrep, cSegments, paSegments, fFixed);
+    if (!rc)
+    {
+        *ppvBase = pPrep->pv;
+        pRdrFile->cPreps++;
+    }
+
+    return rc;
+}
+
+
+/** Generic implementation of kldrRdrFileMap. */
+static int  kldrRdrFileGenericMap(PKLDRRDR pRdr, PKLDRRDRFILEPREP pPrep, uint32_t cSegments, PCKLDRSEG paSegments, unsigned fFixed)
+{
+    int rc;
+    uint32_t i;
+
+    /*
+     * Generic mapping code using kldrHlpPageAlloc(), kldrHlpPageFree() and kldrHlpPageProtect().
+     */
+    rc = kldrHlpPageAlloc(&pPrep->pv, pPrep->cb, KLDRPROT_EXECUTE_READWRITE, fFixed);
+    if (rc)
+        return rc;
+
+    /*
+     * Load the data.
+     */
+    for (i = 0; i < cSegments; i++)
+    {
+        void *pv;
+
+        if (    paSegments[i].RVA == NIL_KLDRADDR
+            ||  paSegments[i].cbFile <= 0)
+            continue;
+
+        pv = (uint8_t *)pPrep->pv + paSegments[i].RVA;
+        rc = pRdr->pOps->pfnRead(pRdr, pv, paSegments[i].cbFile, paSegments[i].offFile);
+        if (rc)
+            break;
+    }
+
+    /*
+     * Set segment protection.
+     */
+    if (!rc)
+    {
+        rc = kldrRdrFileGenericProtect(pRdr, pPrep, cSegments, paSegments, 0 /* protect */);
+        if (!rc)
+            return 0;
+        kldrRdrFileGenericProtect(pRdr, pPrep, cSegments, paSegments, 1 /* unprotect */);
+    }
+
+    /* bailout */
+    kldrHlpPageFree(pPrep->pv, pPrep->cb);
+    return rc;
+}
+
+
+/** @copydoc KLDRRDR::pfnPageSize */
+static size_t   kldrRdrFilePageSize(PKLDRRDR pRdr)
+{
+#ifdef __OS2__
+    /* The page size on OS/2 wont change anytime soon. :-) */
+    return 0x1000;
+
+#elif defined(__WIN__)
+    SYSTEM_INFO SysInfo;
+    GetSystemInfo(&SysInfo);
+    return SysInfo.dwPageSize;
+    /*return SysInfo.dwAllocationGranularity;*/
+#else
+# error "port me"
+#endif
+}
+
+
+/** @copydoc KLDRRDR::pfnName */
+static const char *kldrRdrFileName(PKLDRRDR pRdr)
+{
+    PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
+    return &pRdrFile->szFilename[0];
+}
+
+
+/** @copydoc KLDRRDR::pfnTell */
+static KLDRFOFF kldrRdrFileTell(PKLDRRDR pRdr)
+{
+    PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
+
+    /*
+     * If the offset is undefined, try figure out what it is.
+     */
+    if (pRdrFile->off == -1)
+    {
+#ifdef __OS2__
+        ULONG ulNew;
+        APIRET rc = DosSetFilePtr(pRdrFile->File, 0, FILE_CURRENT, &ulNew);
+        if (rc)
+            return -1;
+        pRdrFile->off = ulNew;
+
+#elif defined(__WIN__)
+        LONG offHigh = 0;
+        LONG offLow;
+        int rc;
+
+        SetLastError(0);
+        offLow = SetFilePointer(pRdrFile->File, 0, &offHigh, FILE_CURRENT);
+        rc = GetLastError();
+        if (rc)
+            return -1;
+        pRdrFile->off = ((KLDRFOFF)offHigh << 32) | offLow;
+
+#else
+# error "port me."
+#endif
+    }
+    return pRdrFile->off;
+}
+
+
+/** @copydoc KLDRRDR::pfnSize */
+static KLDRFOFF kldrRdrFileSize(PKLDRRDR pRdr)
+{
+    PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
+    return pRdrFile->cb;
+}
+
+
+/** @copydoc KLDRRDR::pfnAllUnmap */
+static int kldrRdrFileAllUnmap(PKLDRRDR pRdr, const void *pvBits)
+{
+    PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
+
+    /* check for underflow */
+    if (pRdrFile->cMappings <= 0)
+#if defined(__OS2__) || defined(__WIN__)
+        return ERROR_INVALID_PARAMETER;
+#else
+# error "port me"
+#endif
+
+    /* decrement usage counter, free mapping if no longer in use. */
+    if (!--pRdrFile->cMappings)
+    {
+        kldrHlpFree(pRdrFile->pvMapping);
+        pRdrFile->pvMapping = NULL;
+    }
+
+    return 0;
+}
+
+
+/** @copydoc KLDRRDR::pfnAllMap */
+static int kldrRdrFileAllMap(PKLDRRDR pRdr, const void **ppvBits)
+{
+    PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
+
+    /*
+     * Do we need to map it?
+     */
+    if (!pRdrFile->pvMapping)
+    {
+        int rc;
+        KLDRFOFF cb = pRdrFile->Core.pOps->pfnSize(pRdr);
+
+        pRdrFile->pvMapping = kldrHlpAlloc(cb);
+        if (!pRdrFile->pvMapping)
+#if defined(__OS2__) || defined(__WIN__)
+            return ERROR_NOT_ENOUGH_MEMORY;
+#else
+# error "port me"
+#endif
+        rc = pRdrFile->Core.pOps->pfnRead(pRdr, pRdrFile->pvMapping, cb, 0);
+        if (rc)
+        {
+            kldrHlpFree(pRdrFile->pvMapping);
+            pRdrFile->pvMapping = NULL;
+            return rc;
+        }
+        pRdrFile->cMappings = 0;
+    }
+
+    *ppvBits = pRdrFile->pvMapping;
+    pRdrFile->cMappings++;
+    return 0;
+}
+
+
+/** @copydoc KLDRRDR::pfnRead */
+static int kldrRdrFileRead(PKLDRRDR pRdr, void *pvBuf, size_t cb, KLDRFOFF off)
+{
+    PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
+
+    /*
+     * Do a seek if needed.
+     */
+    if (pRdrFile->off != off)
+    {
+#ifdef __OS2__
+        ULONG ulNew;
+        APIRET rc;
+
+        rc = DosSetFilePtr(pRdrFile->File, off, FILE_BEGIN, &ulNew);
+        if (rc)
+        {
+            pRdrFile->off = -1;
+            return rc;
+        }
+
+#elif defined(__WIN__)
+        LONG offHigh;
+        LONG offLow;
+
+        offHigh = sizeof(KLDRFOFF) == 4 ? 0 : (off >> 32);
+        offLow = SetFilePointer(pRdrFile->File, (LONG)off, &offHigh, FILE_BEGIN);
+        if (    offLow != (LONG)off
+            ||  offHigh != (LONG)(sizeof(KLDRFOFF) == 4 ? 0 : (off >> 32)))
+        {
+            int rc = GetLastError();
+            if (!rc)
+                rc = ERROR_GEN_FAILURE;
+            pRdrFile->off = -1;
+            return rc;
+        }
+
+#else
+# error "port me."
+#endif
+    }
+
+    /*
+     * Do the read.
+     */
+#ifdef __OS2__
+    {
+    ULONG cbRead = 0;
+    APIRET rc = DosRead(pRdrFile->File, pvBuf, cb, &cbRead);
+    if (rc)
+    {
+        pRdrFile->off = -1;
+        return rc;
+    }
+    if (cbRead != cb)
+    {
+        pRdrFile->off = -1;
+        return ERROR_GEN_FAILURE;
+    }
+    }
+
+#elif defined(__WIN__)
+    {
+    DWORD cbRead = 0;
+    if (!ReadFile(pRdrFile->File, pvBuf, cb, &cbRead, NULL))
+    {
+        int rc = GetLastError();
+        if (!rc)
+            rc = ERROR_GEN_FAILURE;
+        pRdrFile->off = -1;
+        return rc;
+    }
+    if (cbRead != cb)
+    {
+        pRdrFile->off = -1;
+        return ERROR_GEN_FAILURE;
+    }
+    }
+
+#else
+# error "port me."
+#endif
+
+    pRdrFile->off = off + cb;
+    return 0;
+}
+
+
+/** @copydoc KLDRRDR::pfnDestroy */
+static int kldrRdrFileDestroy(PKLDRRDR pRdr)
+{
+    PKLDRRDRFILE    pRdrFile = (PKLDRRDRFILE)pRdr;
+    int             rc;
+#ifdef __OS2__
+    rc = DosClose(pRdrFile->File);
+
+#elif defined(__WIN__)
+    rc = 0;
+    if (!CloseHandle(pRdrFile->File))
+        rc = GetLastError();
+
+#else
+# error "port me"
+#endif
+
+    if (pRdrFile->pvMapping)
+    {
+        kldrHlpFree(pRdrFile->pvMapping);
+        pRdrFile->pvMapping = NULL;
+    }
+
+    kldrHlpFree(pRdr);
+    return rc;
+}
+
+
+/** @copydoc KLDRRDROPS::pfnCreate */
+static int kldrRdrFileCreate(PPKLDRRDR ppRdr, const char *pszFilename)
+{
+    size_t          cchFilename;
+    PKLDRRDRFILE    pRdrFile;
+
+    /*
+     * Open the file and determin its size.
+     */
+#ifdef __OS2__
+    ULONG           ulAction = 0;
+    FILESTATUS3     Info;
+    APIRET          rc;
+    HFILE           File = 0;
+    KLDRFOFF        cb;
+    char            szFilename[CCHMAXPATH];
+
+    if ((uintptr_t)pszFilename >= 0x20000000)
+    {
+        char *psz;
+        cchFilename = kLdrHlpStrLen(szFilename);
+        psz = (char *)kLdrHlpAllocA(cchFilename + 1);
+        kLdrHlpMemCopy(psz, pszFilename, cchFilename + 1);
+        pszFilename = psz;
+    }
+    rc = DosOpen((PCSZ)pszFilename, &File, &ulAction, 0, FILE_NORMAL,
+                 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
+                 OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY | OPEN_FLAGS_RANDOMSEQUENTIAL,
+                 NULL);
+    if (rc)
+        return rc;
+
+    rc = DosQueryPathInfo((PCSZ)pszFilename, FIL_QUERYFULLNAME, szFilename, sizeof(szFilename));
+    if (rc)
+    {
+        DosClose(File);
+        return rc;
+    }
+
+    rc = DosQueryFileInfo(File, FIL_STANDARD, &Info, sizeof(Info));
+    if (rc)
+    {
+        DosClose(File);
+        return rc;
+    }
+    cb = Info.cbFile;
+
+#elif defined(__WIN__)
+    SECURITY_ATTRIBUTES SecAttr;
+    DWORD               High;
+    DWORD               Low;
+    int                 rc;
+    HANDLE              File;
+    KLDRFOFF            cb;
+    char                szFilename[MAX_PATH];
+
+    SecAttr.bInheritHandle = FALSE;
+    SecAttr.lpSecurityDescriptor = NULL;
+    SecAttr.nLength = 0;
+    File = CreateFile(pszFilename, GENERIC_READ | GENERIC_EXECUTE, FILE_SHARE_READ, &SecAttr, OPEN_EXISTING, 0, NULL);
+    if (File == INVALID_HANDLE_VALUE)
+        return GetLastError();
+
+    if (!GetFullPathName(pszFilename, sizeof(szFilename), szFilename, NULL))
+    {
+        rc = GetLastError();
+        CloseHandle(File);
+        return rc;
+    }
+
+    SetLastError(0);
+    Low = GetFileSize(File, &High);
+    rc = GetLastError();
+    if (rc)
+    {
+        CloseHandle(File);
+        return rc;
+    }
+    if (sizeof(KLDRFOFF) == 4)
+        cb = High ? 0x7fffffff : Low;
+    else
+        cb = ((KLDRFOFF)High << 32) | Low;
+
+#else
+# error "port me"
+#endif
+
+
+    /*
+     * Allocate the reader instance.
+     */
+    cchFilename = kLdrHlpStrLen(szFilename);
+    pRdrFile = (PKLDRRDRFILE)kldrHlpAlloc(sizeof(*pRdrFile) + cchFilename);
+    if (!pRdrFile)
+#if defined(__OS2__)
+    {
+        DosClose(File);
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
+#elif defined(__WIN__)
+    {
+        CloseHandle(File);
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
+#else
+# error "port me"
+#endif
+
+    /*
+     * Initialize it and return successfully.
+     */
+    pRdrFile->Core.u32Magic = KLDRRDR_MAGIC;
+    pRdrFile->Core.pOps = &g_kLdrRdrFileOps;
+    pRdrFile->File = File;
+    pRdrFile->cb = cb;
+    pRdrFile->off = 0;
+    pRdrFile->cMappings = 0;
+    pRdrFile->cPreps = 0;
+    kLdrHlpMemCopy(&pRdrFile->szFilename[0], szFilename, cchFilename + 1);
+
+    *ppRdr = &pRdrFile->Core;
+    return 0;
+}
+
Index: /trunk/kStuff/kRdr/kRdrInternal.h
===================================================================
--- /trunk/kStuff/kRdr/kRdrInternal.h	(revision 3543)
+++ /trunk/kStuff/kRdr/kRdrInternal.h	(revision 3543)
@@ -0,0 +1,114 @@
+/* $Id$ */
+/** @file
+ * kRdr - Internal Header.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kStuff.
+ *
+ * kStuff 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.
+ *
+ * kStuff 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 kStuff; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ___kRdrInternal_h__
+#define ___kRdrInternal_h__
+
+#include <k/kHlpAssert.h>
+#include <k/kMagics.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup grp_kRdrInternal - Internals
+ * @addtogroup grp_kRdr
+ * @internal
+ * @{ */
+
+/** @def KRDR_STRICT
+ * If defined the kRdr assertions and other runtime checks will be enabled. */
+#ifdef K_ALL_STRICT
+# undef KRDR_STRICT
+# define KRDR_STRICT
+#endif
+
+/** @name Our Assert macros
+ * @{ */
+#ifdef KRDR_STRICT
+# define kRdrAssert(expr)                       kHlpAssert(expr)
+# define kRdrAssertReturn(expr, rcRet)          kHlpAssertReturn(expr, rcRet)
+# define kRdrAssertMsg(expr, msg)               kHlpAssertMsg(expr, msg)
+# define kRdrAssertMsgReturn(expr, msg, rcRet)  kHlpAssertMsgReturn(expr, msg, rcRet)
+#else   /* !KRDR_STRICT */
+# define kRdrAssert(expr)                       do { } while (0)
+# define kRdrAssertReturn(expr, rcRet)          do { if (!(expr)) return (rcRet); } while (0)
+# define kRdrAssertMsg(expr, msg)               do { } while (0)
+# define kRdrAssertMsgReturn(expr, msg, rcRet)  do { if (!(expr)) return (rcRet); } while (0)
+#endif  /* !KRDR_STRICT */
+
+#define kRdrAssertPtr(ptr)                      kRdrAssertMsg(K_VALID_PTR(ptr), ("%s = %p\n", #ptr, (ptr)))
+#define kRdrAssertPtrReturn(ptr, rcRet)         kRdrAssertMsgReturn(K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)), (rcRet))
+#define kRdrAssertPtrNull(ptr)                  kRdrAssertMsg(!(ptr) || K_VALID_PTR(ptr), ("%s = %p\n", #ptr, (ptr)))
+#define kRdrAssertPtrNullReturn(ptr, rcRet)     kRdrAssertMsgReturn(!(ptr) || K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)), (rcRet))
+#define kRdrAssertRC(rc)                        kRdrAssertMsg((rc) == 0, ("%s = %d\n", #rc, (rc)))
+#define kRdrAssertRCReturn(rc, rcRet)           kRdrAssertMsgReturn((rc) == 0, ("%s = %d -> %d\n", #rc, (rc), (rcRet)), (rcRet))
+#define kRdrAssertFailed()                      kRdrAssert(0)
+#define kRdrAssertFailedReturn(rcRet)           kRdrAssertReturn(0, (rcRet))
+#define kRdrAssertMsgFailed(msg)                kRdrAssertMsg(0, msg)
+#define kRdrAssertMsgFailedReturn(msg, rcRet)   kRdrAssertMsgReturn(0, msg, (rcRet))
+/** @} */
+
+/** Return / crash validation of a reader argument. */
+#define KRDR_VALIDATE_EX(pRdr, rc) \
+    do  { \
+        if (    (pRdr)->u32Magic != KRDR_MAGIC \
+            ||  (pRdr)->pOps == NULL \
+           )\
+        { \
+            return (rc); \
+        } \
+    } while (0)
+
+/** Return / crash validation of a reader argument. */
+#define KRDR_VALIDATE(pRdr) \
+    KRDR_VALIDATE_EX(pRdr, KERR_INVALID_PARAMETER)
+
+/** Return / crash validation of a reader argument. */
+#define KRDR_VALIDATE_VOID(pRdr) \
+    do  { \
+        if (    (pRdr)->u32Magic != KRDR_MAGIC \
+            ||  (pRdr)->pOps == NULL \
+           )\
+        { \
+            return; \
+        } \
+    } while (0)
+
+
+/** @name Built-in Providers
+ * @{ */
+extern const KRDROPS g_kRdrFileOps;
+/** @} */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
