[Pkg-virtualbox-commits] [kbuild] 01/03: Imported Upstream version 0.1.9998svn2888+dfsg

Gianfranco Costamagna locutusofborg at moszumanska.debian.org
Wed Sep 7 07:56:41 UTC 2016


This is an automated email from the git hooks/post-receive script.

locutusofborg pushed a commit to branch master
in repository kbuild.

commit 53abad24c9e154847053a8071b99ec97f0364d25
Author: Gianfranco Costamagna <locutusofborg at debian.org>
Date:   Wed Sep 7 08:09:20 2016 +0200

    Imported Upstream version 0.1.9998svn2888+dfsg
---
 Config.kmk                                         |   49 +-
 SlickEdit/kdev.e                                   |   70 +-
 kBuild/header.kmk                                  |   16 +-
 kBuild/tools/NASM.kmk                              |   29 +-
 kBuild/tools/OPENWATCOM.kmk                        |    4 +-
 kBuild/tools/VCC100AMD64.kmk                       |   17 +-
 kBuild/tools/VCC100X86.kmk                         |   17 +-
 kBuild/tools/YASM.kmk                              |   11 +-
 src/Makefile.kmk                                   |    6 +-
 src/kDepPre/Makefile.kmk                           |    4 +-
 src/kWorker/Makefile.kmk                           |  143 +
 src/kWorker/kWorker.c                              | 7451 ++++++++++++++++
 src/kWorker/tst-1-c1xx-xcpt.cpp                    |  345 +
 src/kmk/Makefile.kmk                               |   39 +-
 src/kmk/config.h.win                               |    3 +-
 src/kmk/dir-nt-bird.c                              |  587 ++
 src/kmk/dir.c                                      |   21 +
 src/kmk/function.c                                 |   41 +
 src/kmk/incdep.c                                   |   70 +-
 src/kmk/job.c                                      |   30 +-
 src/kmk/kbuild.c                                   |   93 +-
 src/kmk/kmk_cc_exec.c                              |    4 +-
 src/kmk/kmkbuiltin.c                               |   24 +-
 src/kmk/kmkbuiltin.h                               |   23 +-
 src/kmk/kmkbuiltin/kDepIDB.c                       |    8 +-
 src/kmk/kmkbuiltin/kDepObj.c                       |   10 +-
 src/kmk/kmkbuiltin/kSubmit.c                       | 1594 ++++
 src/kmk/kmkbuiltin/kbuild_version.c                |   60 -
 src/kmk/kmkbuiltin/redirect.c                      |  187 +-
 src/kmk/main.c                                     |    5 +-
 src/kmk/make.h                                     |    6 +
 src/kmk/read.c                                     |    4 +
 src/kmk/remake.c                                   |    5 +
 src/kmk/w32/Makefile.kmk                           |   37 -
 src/kmk/w32/Makefile.kup                           |    0
 src/kmk/w32/include/sub_proc.h                     |    5 +
 src/kmk/w32/pathstuff.c                            |    9 +-
 src/kmk/w32/subproc/Makefile.kup                   |    0
 src/kmk/w32/subproc/sub_proc.c                     |  105 +-
 src/lib/Makefile.kmk                               |   15 +-
 src/lib/kDep.c                                     |   52 +-
 src/lib/kDep.h                                     |   34 +-
 src/lib/kStuff/Config.kmk                          |  138 +
 src/lib/kStuff/Copyright                           |   25 +
 src/lib/kStuff/Makefile.kmk                        |   55 +
 src/lib/kStuff/include/k/kAvlTmpl/kAvlBase.h       |  626 ++
 src/lib/kStuff/include/k/kAvlTmpl/kAvlDestroy.h    |  129 +
 src/lib/kStuff/include/k/kAvlTmpl/kAvlDoWithAll.h  |  166 +
 src/lib/kStuff/include/k/kAvlTmpl/kAvlEnum.h       |  187 +
 src/lib/kStuff/include/k/kAvlTmpl/kAvlGet.h        |   89 +
 src/lib/kStuff/include/k/kAvlTmpl/kAvlGetBestFit.h |  112 +
 .../kStuff/include/k/kAvlTmpl/kAvlGetWithParent.h  |   65 +
 src/lib/kStuff/include/k/kAvlTmpl/kAvlRemove2.h    |  133 +
 .../kStuff/include/k/kAvlTmpl/kAvlRemoveBestFit.h  |   70 +
 src/lib/kStuff/include/k/kAvlTmpl/kAvlUndef.h      |   79 +
 src/lib/kStuff/include/k/kAvlU32.h                 |   66 +
 src/lib/kStuff/include/k/kAvloU32.h                |   75 +
 src/lib/kStuff/include/k/kAvlrU32.h                |   71 +
 src/lib/kStuff/include/k/kCpu.h                    |   68 +
 src/lib/kStuff/include/k/kCpus.h                   |  157 +
 src/lib/kStuff/include/k/kDbg.h                    |  243 +
 src/lib/kStuff/include/k/kDbgAll.h                 |  168 +
 src/lib/kStuff/include/k/kDbgBase.h                |  248 +
 src/lib/{ => kStuff/include}/k/kDefs.h             |   96 +-
 src/lib/kStuff/include/k/kErr.h                    |   68 +
 src/lib/kStuff/include/k/kErrors.h                 |  327 +
 src/lib/kStuff/include/k/kHlp.h                    |   53 +
 src/lib/kStuff/include/k/kHlpAlloc.h               |   78 +
 src/lib/kStuff/include/k/kHlpAssert.h              |  258 +
 src/lib/kStuff/include/k/kHlpDefs.h                |   55 +
 src/lib/kStuff/include/k/kHlpEnv.h                 |   55 +
 src/lib/kStuff/include/k/kHlpPath.h                |   57 +
 src/lib/kStuff/include/k/kHlpProcess.h             |   54 +
 src/lib/kStuff/include/k/kHlpSem.h                 |   54 +
 src/lib/kStuff/include/k/kHlpString.h              |  156 +
 src/lib/kStuff/include/k/kHlpSys.h                 |   79 +
 src/lib/kStuff/include/k/kHlpThread.h              |   55 +
 src/lib/kStuff/include/k/kLdr.h                    |  957 ++
 src/lib/kStuff/include/k/kLdrFmts/lx.h             |  485 +
 src/lib/kStuff/include/k/kLdrFmts/mach-o.h         |  997 +++
 src/lib/kStuff/include/k/kLdrFmts/mz.h             |   70 +
 src/lib/{ => kStuff/include}/k/kLdrFmts/pe.h       |   29 +-
 src/lib/kStuff/include/k/kMagics.h                 |   43 +
 src/lib/kStuff/include/k/kRbTmpl/kRbAssert.h       |  136 +
 src/lib/kStuff/include/k/kRbTmpl/kRbBase.h         |  609 ++
 src/lib/kStuff/include/k/kRbTmpl/kRbDestroy.h      |  129 +
 src/lib/kStuff/include/k/kRbTmpl/kRbDoWithAll.h    |  166 +
 src/lib/kStuff/include/k/kRbTmpl/kRbEnum.h         |  187 +
 src/lib/kStuff/include/k/kRbTmpl/kRbGet.h          |   89 +
 src/lib/kStuff/include/k/kRbTmpl/kRbGetBestFit.h   |  112 +
 .../kStuff/include/k/kRbTmpl/kRbGetWithParent.h    |   65 +
 src/lib/kStuff/include/k/kRbTmpl/kRbRemove2.h      |  133 +
 .../kStuff/include/k/kRbTmpl/kRbRemoveBestFit.h    |   70 +
 src/lib/kStuff/include/k/kRbTmpl/kRbUndef.h        |   79 +
 src/lib/kStuff/include/k/kRbU32.h                  |   68 +
 src/lib/kStuff/include/k/kRdr.h                    |   86 +
 src/lib/kStuff/include/k/kRdrAll.h                 |  127 +
 src/lib/{ => kStuff/include}/k/kTypes.h            |   42 +-
 src/lib/kStuff/kCpu/Makefile.kmk                   |   42 +
 src/lib/kStuff/kCpu/kCpuCompare.c                  |  131 +
 src/lib/kStuff/kCpu/kCpuGetArchAndCpu.c            |   57 +
 src/lib/kStuff/kDbg/Makefile.kmk                   |   73 +
 src/lib/kStuff/kDbg/kDbgDump.cpp                   |  174 +
 src/lib/kStuff/kDbg/kDbgHlp.h                      |  306 +
 src/lib/kStuff/kDbg/kDbgHlpCrt.cpp                 |  239 +
 src/lib/kStuff/kDbg/kDbgInternal.h                 |  137 +
 src/lib/kStuff/kDbg/kDbgLine.cpp                   |   78 +
 src/lib/kStuff/kDbg/kDbgModLdr.cpp                 |  109 +
 src/lib/kStuff/kDbg/kDbgModPE.cpp                  |  384 +
 src/lib/kStuff/kDbg/kDbgModWinDbgHelp.cpp          |  724 ++
 src/lib/kStuff/kDbg/kDbgModule.cpp                 |  440 +
 src/lib/kStuff/kDbg/kDbgSpace.cpp                  |  192 +
 src/lib/kStuff/kDbg/kDbgSymbol.cpp                 |   78 +
 src/lib/kStuff/kErr/Makefile.kmk                   |   61 +
 src/lib/kStuff/kErr/kErrName.c                     |   57 +
 src/lib/kStuff/kHlp/Bare/Makefile.kup              |    0
 src/lib/kStuff/kHlp/Bare/kHlpBare-gcc.c            |  223 +
 src/lib/kStuff/kHlp/Bare/kHlpBareAssert.c          |  138 +
 src/lib/kStuff/kHlp/Bare/kHlpBareEnv.c             |  102 +
 src/lib/kStuff/kHlp/Bare/kHlpBareHeap.c            |  763 ++
 src/lib/kStuff/kHlp/Bare/kHlpBareProcess.c         |   85 +
 src/lib/kStuff/kHlp/Bare/kHlpBareThread.c          |   93 +
 src/lib/kStuff/kHlp/Bare/kHlpSys-darwin.c          |  345 +
 src/lib/kStuff/kHlp/CRT/kHlpCRTAlloc.cpp           |   78 +
 src/lib/kStuff/kHlp/CRT/kHlpCRTEnv.cpp             |   56 +
 src/lib/kStuff/kHlp/CRT/kHlpCRTString.cpp          |  164 +
 src/lib/kStuff/kHlp/Generic/kHlpGetEnvUZ.c         |  108 +
 src/lib/kStuff/kHlp/Generic/kHlpGetExt.c           |   78 +
 src/lib/kStuff/kHlp/Generic/kHlpGetFilename.c      |   72 +
 src/lib/kStuff/kHlp/Generic/kHlpInt2Ascii.c        |   83 +
 src/lib/kStuff/kHlp/Generic/kHlpIsFilenameOnly.c   |   61 +
 src/lib/kStuff/kHlp/Generic/kHlpMemChr.c           |   51 +
 src/lib/kStuff/kHlp/Generic/kHlpMemComp.c          |   71 +
 src/lib/kStuff/kHlp/Generic/kHlpMemCopy.c          |   69 +
 src/lib/kStuff/kHlp/Generic/kHlpMemICompAscii.c    |   80 +
 src/lib/kStuff/kHlp/Generic/kHlpMemMove.c          |  100 +
 src/lib/kStuff/kHlp/Generic/kHlpMemPComp.c         |   71 +
 src/lib/kStuff/kHlp/Generic/kHlpMemPCopy.c         |   69 +
 src/lib/kStuff/kHlp/Generic/kHlpMemPMove.c         |   99 +
 src/lib/kStuff/kHlp/Generic/kHlpMemPSet.c          |   77 +
 src/lib/kStuff/kHlp/Generic/kHlpMemSet.c           |   76 +
 src/lib/kStuff/kHlp/Generic/kHlpPage.c             |  371 +
 src/lib/kStuff/kHlp/Generic/kHlpStrCat.c           |   52 +
 src/lib/kStuff/kHlp/Generic/kHlpStrChr.c           |   56 +
 src/lib/kStuff/kHlp/Generic/kHlpStrComp.c          |   52 +
 src/lib/kStuff/kHlp/Generic/kHlpStrCopy.c          |   46 +
 src/lib/kStuff/kHlp/Generic/kHlpStrICompAscii.c    |   58 +
 src/lib/kStuff/kHlp/Generic/kHlpStrIPCompAscii.c   |   59 +
 src/lib/kStuff/kHlp/Generic/kHlpStrLen.c           |   44 +
 src/lib/kStuff/kHlp/Generic/kHlpStrNCat.c          |   55 +
 src/lib/kStuff/kHlp/Generic/kHlpStrNComp.c         |   52 +
 src/lib/kStuff/kHlp/Generic/kHlpStrNICompAscii.c   |   59 +
 src/lib/kStuff/kHlp/Generic/kHlpStrNIPCompAscii.c  |   61 +
 src/lib/kStuff/kHlp/Generic/kHlpStrNLen.c          |   44 +
 src/lib/kStuff/kHlp/Generic/kHlpStrNPCat.c         |   54 +
 src/lib/kStuff/kHlp/Generic/kHlpStrNPComp.c        |   53 +
 src/lib/kStuff/kHlp/Generic/kHlpStrPCat.c          |   51 +
 src/lib/kStuff/kHlp/Generic/kHlpStrPComp.c         |   53 +
 src/lib/kStuff/kHlp/Generic/kHlpStrPCopy.c         |   45 +
 src/lib/kStuff/kHlp/Generic/kHlpStrRChr.c          |   59 +
 src/lib/kStuff/kHlp/Makefile.kmk                   |  126 +
 src/lib/kStuff/kLdr/Doxyfile                       | 1252 +++
 src/lib/kStuff/kLdr/Makefile.kmk                   |  224 +
 src/lib/kStuff/kLdr/kLdr-os2.c                     |   66 +
 src/lib/kStuff/kLdr/kLdr-os2.def                   |  115 +
 src/lib/kStuff/kLdr/kLdr-win.c                     |   77 +
 src/lib/kStuff/kLdr/kLdr-win.def                   |  113 +
 src/lib/kStuff/kLdr/kLdr.c                         |  145 +
 src/lib/kStuff/kLdr/kLdrA-os2.asm                  |   66 +
 src/lib/kStuff/kLdr/kLdrDyld.c                     | 1509 ++++
 src/lib/kStuff/kLdr/kLdrDyldFind.c                 | 1086 +++
 src/lib/kStuff/kLdr/kLdrDyldMod.c                  | 1300 +++
 src/lib/kStuff/kLdr/kLdrDyldOS.c                   |  133 +
 src/lib/kStuff/kLdr/kLdrDyldSem.c                  |  198 +
 src/lib/kStuff/kLdr/kLdrExeStub-os2.asm            |   72 +
 src/lib/kStuff/kLdr/kLdrExeStub-os2.c              |   59 +
 src/lib/kStuff/kLdr/kLdrExeStub-os2A.asm           |   41 +
 src/lib/kStuff/kLdr/kLdrExeStub-win.c              |   62 +
 src/lib/kStuff/kLdr/kLdrHlp.h                      |    9 +
 src/lib/kStuff/kLdr/kLdrInternal.h                 |  461 +
 src/lib/kStuff/kLdr/kLdrMod.c                      |  914 ++
 src/lib/kStuff/kLdr/kLdrModLX.c                    | 2698 ++++++
 src/lib/kStuff/kLdr/kLdrModMachO.c                 | 3718 ++++++++
 src/lib/kStuff/kLdr/kLdrModNative.c                | 1167 +++
 src/lib/kStuff/kLdr/kLdrModPE.c                    | 2044 +++++
 src/lib/kStuff/kLdr/testcase/Makefile.kmk          |  305 +
 src/lib/kStuff/kLdr/testcase/bin/tst-3.dll.win.x86 |  Bin 0 -> 3072 bytes
 .../kStuff/kLdr/testcase/bin/tst-3.rel.darwin.x86  |  Bin 0 -> 2800 bytes
 src/lib/kStuff/kLdr/testcase/tst-0-a.c             |   10 +
 src/lib/kStuff/kLdr/testcase/tst-0-b.c             |   10 +
 src/lib/kStuff/kLdr/testcase/tst-0-c.c             |   10 +
 src/lib/kStuff/kLdr/testcase/tst-0-d.c             |    8 +
 src/lib/kStuff/kLdr/testcase/tst-0-driver.c        |  502 ++
 src/lib/kStuff/kLdr/testcase/tst-0.c               |   13 +
 src/lib/kStuff/kLdr/testcase/tst-1-a.c             |   10 +
 src/lib/kStuff/kLdr/testcase/tst-1-b.c             |   10 +
 src/lib/kStuff/kLdr/testcase/tst-1-c.c             |   10 +
 src/lib/kStuff/kLdr/testcase/tst-1-d.c             |    8 +
 src/lib/kStuff/kLdr/testcase/tst-1.c               |   15 +
 src/lib/kStuff/kLdr/testcase/tst-2-a.c             |    8 +
 src/lib/kStuff/kLdr/testcase/tst-2-b.c             |   10 +
 src/lib/kStuff/kLdr/testcase/tst-2-c.c             |   10 +
 src/lib/kStuff/kLdr/testcase/tst-2-d.c             |   10 +
 src/lib/kStuff/kLdr/testcase/tst-2.c               |   16 +
 src/lib/kStuff/kLdr/testcase/tst-3-driver.c        |  216 +
 src/lib/kStuff/kLdr/testcase/tst-3-ext.c           |   39 +
 src/lib/kStuff/kLdr/testcase/tst-3-imp-os2.def     |   34 +
 src/lib/kStuff/kLdr/testcase/tst-3-imp-win.def     |   34 +
 src/lib/kStuff/kLdr/testcase/tst-3.c               |   78 +
 src/lib/kStuff/kLdr/testcase/tst.h                 |   57 +
 src/lib/kStuff/kLdr/testcase/tstDllMain.c          |  192 +
 .../kStuff/kLdr/testcase/tstDllMainStub-os2.asm    |   40 +
 src/lib/kStuff/kLdr/testcase/tstDllMainStub.c      |   76 +
 .../kStuff/kLdr/testcase/tstExeMainStub-os2.asm    |   40 +
 src/lib/kStuff/kLdr/testcase/tstExeMainStub.c      |   93 +
 src/lib/kStuff/kLdr/tg/KLDRSTATE.gif               |  Bin 0 -> 14294 bytes
 src/lib/kStuff/kLdr/tg/KLDRSTATE.txvstc            |  529 ++
 src/lib/kStuff/kLdr/tg/default.txvpck              |    8 +
 src/lib/kStuff/kLdr/tg/kLdr.tpr                    |   23 +
 src/lib/kStuff/kLdr/tg/kLdr.tws                    |    2 +
 src/lib/kStuff/kLdr/tstkLdrHeap.c                  |  223 +
 src/lib/kStuff/kLdr/tstkLdrMod.c                   |  629 ++
 src/lib/kStuff/kProfiler2/Makefile.kmk             |  237 +
 src/lib/kStuff/kProfiler2/dllmain-win.cpp          |   75 +
 src/lib/kStuff/kProfiler2/kPrf2-win-amd64.def      |   37 +
 src/lib/kStuff/kProfiler2/kPrf2-win-x86.def        |   36 +
 src/lib/kStuff/kProfiler2/kPrf2Read.cpp            |  503 ++
 src/lib/kStuff/kProfiler2/kPrf2WinApi-dumpbin.sed  |   96 +
 src/lib/kStuff/kProfiler2/kPrf2WinApi-gencode.sed  |  120 +
 src/lib/kStuff/kProfiler2/kPrf2WinApi-genimp.sed   |   55 +
 src/lib/kStuff/kProfiler2/kPrf2WinApi-pre.sed      |  117 +
 src/lib/kStuff/kProfiler2/kPrf2WinApiWrapperHlp.c  |   53 +
 src/lib/kStuff/kProfiler2/kPrf2WinApiWrapperHlp.h  |   41 +
 .../kProfiler2/kPrf2WinApiWrappers-kernel32.h      | 9360 ++++++++++++++++++++
 src/lib/kStuff/kProfiler2/kPrf2WinApiWrappers.c    |  123 +
 .../kProfiler2/kPrf2WinApiWrappersImp-amd64.def    |  854 ++
 .../kProfiler2/kPrf2WinApiWrappersImp-x86.def      | 1682 ++++
 src/lib/kStuff/kProfiler2/kPrfReader.h             |   45 +
 src/lib/kStuff/kProfiler2/kProfileR3.cpp           | 1666 ++++
 src/lib/kStuff/kProfiler2/kProfileR3.h             |   39 +
 src/lib/kStuff/kProfiler2/prfamd64msc.asm          |  474 +
 src/lib/kStuff/kProfiler2/prfcore.cpp.h            |  657 ++
 src/lib/kStuff/kProfiler2/prfcore.h.h              |  381 +
 src/lib/kStuff/kProfiler2/prfcorefunction.cpp.h    |  127 +
 src/lib/kStuff/kProfiler2/prfcoreinit.cpp.h        |  191 +
 src/lib/kStuff/kProfiler2/prfcoremodseg.cpp.h      |  197 +
 src/lib/kStuff/kProfiler2/prfcorepost.cpp.h        |   41 +
 src/lib/kStuff/kProfiler2/prfcorepre.cpp.h         |  202 +
 src/lib/kStuff/kProfiler2/prfcorereloc.cpp.h       |   47 +
 src/lib/kStuff/kProfiler2/prfcoreterm.cpp.h        |  142 +
 src/lib/kStuff/kProfiler2/prfreader.cpp.h          | 1602 ++++
 src/lib/kStuff/kProfiler2/prfx86msc.asm            |  393 +
 src/lib/kStuff/kProfiler2/tst.c                    |   48 +
 src/lib/kStuff/kProfiler2/tstlongjmp.c             |   62 +
 src/lib/kStuff/kRdr/Makefile.kmk                   |   48 +
 src/lib/kStuff/kRdr/kRdr.cpp                       |  281 +
 src/lib/kStuff/kRdr/kRdrBuffered.cpp               |  750 ++
 src/lib/kStuff/kRdr/kRdrFile.cpp                   | 1308 +++
 src/lib/kStuff/kRdr/kRdrInternal.h                 |  122 +
 src/lib/kbuild_version.c                           |   64 +
 src/lib/kbuild_version.h                           |   37 +
 src/lib/mytypes.h                                  |   37 +-
 src/lib/nt/kFsCache.c                              | 4055 +++++++++
 src/lib/nt/kFsCache.h                              |  488 +
 src/lib/nt/nthlp.h                                 |   11 +-
 src/lib/nt/nthlpcore.c                             |   16 +-
 src/lib/nt/ntstat.c                                |  188 +-
 src/lib/nt/ntstat.h                                |   12 +-
 src/lib/nt/ntstuff.h                               |   79 +-
 src/lib/nt_fullpath.c                              |    5 +-
 src/lib/{mytypes.h => nt_fullpath.h}               |   29 +-
 src/lib/nt_fullpath_cached.c                       |  136 +
 src/lib/quote_argv.c                               |  209 +
 src/lib/quote_argv.h                               |   39 +
 src/lib/quoted_spawn.c                             |   34 +-
 src/lib/quoted_spawn.h                             |   33 +-
 src/lib/restartable-syscall-wrappers.c             |   33 +-
 src/lib/wrapper.c                                  |   36 +-
 src/sed/Makefile.kmk                               |    8 +-
 279 files changed, 76187 insertions(+), 652 deletions(-)

diff --git a/Config.kmk b/Config.kmk
index 0e21f44..176a1b6 100644
--- a/Config.kmk
+++ b/Config.kmk
@@ -1,4 +1,4 @@
-# $Id: Config.kmk 2814 2016-04-15 09:10:48Z bird $
+# $Id: Config.kmk 2870 2016-09-04 13:52:39Z bird $
 ## @file
 # Build Configuration.
 #
@@ -48,12 +48,21 @@ ifneq ($(wildcard $(PATH_ROOT)/SvnInfo.kmk),)
 KBUILD_SVN_INFO_KMK := $(PATH_ROOT)/SvnInfo.kmk
 KBUILD_SVN_INFO_DEP := $(KBUILD_SVN_INFO_KMK)
 
-else ifneq ($(wildcard $(PATH_ROOT)/.svn/entries $(PATH_ROOT)/../.svn/entries),)
+else ifneq ($(wildcard $(PATH_ROOT)/.svn/ $(PATH_ROOT)/../.svn/),)
 # Generate from svn info
 KBUILD_SVN_INFO_KMK := $(PATH_OBJ)/SvnInfo.kmk
 KBUILD_SVN_INFO_DEP := $(KBUILD_SVN_INFO_KMK)
 
-$(PATH_OBJ)/SvnInfo.ts +| $(KBUILD_SVN_INFO_KMK): $(wildcard $(PATH_ROOT)/.svn $(PATH_ROOT)/.svn/entries $(PATH_ROOT)/.svn/all-wcprops $(PATH_ROOT)/.svn/format $(PATH_ROOT)/.svn/props $(PATH_ROOT)/.svn/prop-base )
+$(PATH_OBJ)/SvnInfo.ts +| $(KBUILD_SVN_INFO_KMK): $(wildcard $(addprefix $(PATH_ROOT)/.svn/ $(PATH_ROOT)/../.svn/,\
+		. \
+		pristine \
+		wc.db \
+		tmp \
+		entries \
+		all-wcprops \
+		format \
+		props \
+		prop-base ) )
 	$(call MSG_GENERATE,,$(KBUILD_SVN_INFO_KMK))
 	@$(RM) -f $@ $@.tmp
 	@$(MKDIR) -p $(@D)
@@ -198,7 +207,9 @@ TEMPLATE_DOC_GID    ?= $(firstword $(MY_INST_DOC_GID)  $(MY_INST_GID))
 #
 TEMPLATE_BIN = Command line binary
 
-TEMPLATE_BIN_INCS               = $(PATH_ROOT)/src/lib
+TEMPLATE_BIN_INCS               = \
+	$(PATH_ROOT)/src/lib \
+	$(PATH_ROOT)/src/lib/kStuff/include
 TEMPLATE_BIN_DEFS.profile       = NDEBUG
 TEMPLATE_BIN_DEFS.release       = NDEBUG
 if defined(NIX_INSTALL_DIR) && !defined(KBUILD_BOOTSTRAP)
@@ -280,7 +291,7 @@ ifeq ($(filter-out win nt,$(KBUILD_TARGET)),)
 	. \
 	$(PATH_GNUMAKE_SRC)/w32/include \
 	$(PATH_GNUMAKE_SRC)/glob
- TEMPLATE_BIN_LDFLAGS           = /SUBSYSTEM:console /INCREMENTAL:no /NOD /DEBUG /OPT:REF /OPT:ICF
+ TEMPLATE_BIN_LDFLAGS           = /SUBSYSTEM:console /INCREMENTAL:no /NOD /DEBUG /OPT:REF /OPT:ICF /LargeAddressAware
  ifeq ($(KBUILD_TYPE),profile)
   TEMPLATE_BIN_SDKS             = WINPSDKINCS
   TEMPLATE_BIN_CFLAGS          += -MT
@@ -375,6 +386,32 @@ TEMPLATE_LIB_INST    = lib/
 TEMPLATE_LIB_TOOL    = $(TEMPLATE_BIN_TOOL)
 
 
-LIB_KDEP = $(PATH_OBJ)/kDep/$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBPREF)kDep$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBSUFF)
+#
+# Template for static threaded binaries (windows).
+#
+TEMPLATE_BIN-STATIC-THREADED = Threaded command line binary
+TEMPLATE_BIN-STATIC-THREADED_EXTENDS  = BIN-THREADED
+ifeq ($(filter-out win nt,$(KBUILD_TARGET)),)
+ TEMPLATE_BIN-STATIC-THREADED_CFLAGS  = $(filter-out -MD,$(TEMPLATE_BIN-THREADED_CFLAGS)) -MT
+ TEMPLATE_BIN-STATIC-THREADED_LIBS    = $(filter-out %/msvcrt.lib,$(TEMPLATE_BIN-THREADED_LIBS)) \
+ 	$(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/libcmt.lib \
+ 	$(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/libcpmt.lib
+else
+ TEMPLATE_BIN-STATIC-THREADED_CFLAGS  = $(TEMPLATE_BIN-THREADED_CFLAGS) -static
+ TEMPLATE_BIN-STATIC-THREADED_LDFLAGS = $(TEMPLATE_BIN-THREADED_LDFLAGS) -static
+endif
+
+#
+# Template for static threaded libraries.
+#
+TEMPLATE_LIB-STATIC-THREADED = Threaded command line library
+TEMPLATE_LIB-STATIC-THREADED_EXTENDS  = BIN-STATIC-THREADED
+TEMPLATE_LIB-STATIC-THREADED_INST     = lib/
+
+
+#
+# Library macros.
+#
+LIB_KDEP  = $(PATH_OBJ)/kDep/$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBPREF)kDep$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBSUFF)
 LIB_KUTIL = $(PATH_OBJ)/kUtil/$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBPREF)kUtil$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBSUFF)
 
diff --git a/SlickEdit/kdev.e b/SlickEdit/kdev.e
index b806428..5e883ae 100644
--- a/SlickEdit/kdev.e
+++ b/SlickEdit/kdev.e
@@ -1,4 +1,4 @@
-/* $Id: kdev.e 2785 2015-07-11 14:58:52Z bird $  -*- tab-width: 4 c-indent-level: 4 -*- */
+/* $Id: kdev.e 2826 2016-08-14 13:58:02Z bird $  -*- tab-width: 4 c-indent-level: 4 -*- */
 /** @file
  * Visual SlickEdit Documentation Macros.
  */
@@ -190,9 +190,9 @@ static boolean k_commentconfig(_str &sLeft, _str &sRight, int &iColumn, _str sEx
     if (sLexer)
     {
         /* multiline */
-#if __VERSION__>=14.0
-        _str aComments[];
-        GetComments(aComments, "mlcomment", sLexer)
+#if __VERSION__ >= 14.0
+        _str aComments[] = null;
+        GetComments(aComments, "mlcomment", sLexer);
         for (i = 0; i < aComments._length(); i++)
             if (!pos("documentation", aComments[i]) > 0)
             {
@@ -214,7 +214,7 @@ static boolean k_commentconfig(_str &sLeft, _str &sRight, int &iColumn, _str sEx
         }
 
         /* failed, try single line. */
-#if __VERSION__>=14.0
+#if __VERSION__ >= 14.0
         GetComments(aComments, "linecomment", sLexer)
         for (i = 0; i < aComments._length(); i++)
             if (!pos("documentation", aComments[i]) > 0)
@@ -3638,15 +3638,17 @@ _command void kdev_load_settings()
                      | VSCODEHELPFLAG_RESERVED_ON \
                      | VSCODEHELPFLAG_MOUSE_OVER_INFO \
                      | VSCODEHELPFLAG_AUTO_LIST_VALUES \
-                     | VSCODEHELPFLAG_FIND_TAG_PREFERS_DEFINITION \
-                     | VSCODEHELPFLAG_FIND_TAG_PREFERS_ALTERNATE \
                      | VSCODEHELPFLAG_HIGHLIGHT_TAGS \
+                     | VSCODEHELPFLAG_FIND_TAG_PREFERS_ALTERNATE \
                      ;
     fNewCodeHelp &= ~(  VSCODEHELPFLAG_SPACE_COMPLETION \
                       | VSCODEHELPFLAG_AUTO_SYNTAX_HELP \
                       | VSCODEHELPFLAG_NO_SPACE_AFTER_COMMA \
                       | VSCODEHELPFLAG_STRICT_LIST_SELECT \
                       | VSCODEHELPFLAG_AUTO_LIST_VALUES \
+                      | VSCODEHELPFLAG_FIND_TAG_PREFERS_DECLARATION \
+                      | VSCODEHELPFLAG_FIND_TAG_PREFERS_DEFINITION \
+                      | VSCODEHELPFLAG_FIND_TAG_HIDE_OPTIONS \
                      );
     def_codehelp_flags = fNewCodeHelp;
     foreach (sLangId in aMyLangIds)
@@ -3666,6 +3668,60 @@ _command void kdev_load_settings()
     message("Please restart SlickEdit.")
 }
 
+
+static int kfile_to_array(_str sFile, _str (&asLines)[])
+{
+    asLines._makeempty();
+
+    int idTempView = 0;
+    int idOrgView  = 0;
+    int rc = _open_temp_view(sFile, idTempView, idOrgView);
+    if (!rc)
+    {
+        _GoToROffset(0); /* top of the file. */
+
+        int i = 0;
+        do
+        {
+            _str sLine = '';
+            get_line(sLine);
+            asLines[i] = sLine;
+            i += 1;
+        } while (down() == 0);
+
+        _delete_temp_view(idTempView);
+        activate_window(idOrgView);
+    }
+    return rc;
+}
+
+
+_command void kload_files(_str sFile = "file-not-specified.lst")
+{
+    _str sFileDir = absolute(_strip_filename(sFile, 'NE'));
+    _str aFiles[];
+    int  rc = kfile_to_array(sFile, asFiles);
+    if (rc == 0)
+    {
+        _str sFile;
+        int i;
+        for (i = 0; i < asFiles._length(); i++)
+        {
+            _str sFile = strip(asFiles[i]);
+            if (length(sFile) > 0)
+            {
+                sAbsFile = absolute(sFile, sFileDir);
+                message("Loading \"" :+ sAbsFile :+ "\"...");
+                //say("sAbsFile=" :+ sAbsFile);
+                edit(sAbsFile);
+            }
+        }
+    }
+    else
+        message("_GetFileContents failed: " :+ rc);
+}
+
+
 /**
  * Module initiation.
  */
diff --git a/kBuild/header.kmk b/kBuild/header.kmk
index 44ce7c2..63ff90d 100644
--- a/kBuild/header.kmk
+++ b/kBuild/header.kmk
@@ -1,4 +1,4 @@
-# $Id: header.kmk 2813 2016-03-13 12:56:18Z bird $
+# $Id: header.kmk 2887 2016-09-06 14:33:15Z bird $
 ## @file
 # kBuild - File included at top of a makefile.
 #
@@ -79,7 +79,7 @@ endif
 # The revision in which this file was last modified.
 # This can be useful when using development versions of kBuild.
 #
-KMK_REVISION := $(patsubst %:,,  $Rev: 2813 $  )
+KMK_REVISION := $(patsubst %:,,  $Rev: 2887 $  )
 
 
 #
@@ -1608,6 +1608,18 @@ ifn1of ($(KBUILD_TYPE), $(KBUILD_BLD_TYPES))
 endif
 
 
+#
+# Mark the output and temporary directories as volatile on windows.
+#
+# This automatically means the directories not listed here are considered
+# static and won't be invalidated once we start running compile jobs.
+#
+ifeq ($(KBUILD_HOST),win)
+ if $(KBUILD_KMK_REVISION) >= 2886
+   $(dircache-ctl volatile, $(PATH_OUT_BASE), $(PATH_OUT), $(TEMP), $(TMP), $(TMPDIR), $(TMP))
+ endif
+endif
+
 
 ifdef KBUILD_PROFILE_SELF
  $(evalcall def_profile_self, end of header.kmk)
diff --git a/kBuild/tools/NASM.kmk b/kBuild/tools/NASM.kmk
index 5dcda22..c4941c9 100644
--- a/kBuild/tools/NASM.kmk
+++ b/kBuild/tools/NASM.kmk
@@ -1,4 +1,4 @@
-# $Id: NASM.kmk 2808 2016-01-30 15:13:32Z bird $
+# $Id: NASM.kmk 2873 2016-09-04 19:13:12Z bird $
 ## @file
 # kBuild Tool Config - Netwide Assembler v0.98+.
 #
@@ -50,6 +50,13 @@ else
  TOOL_NASM_AS ?= nasm$(HOSTSUFF_EXE)
 endif
 
+# kSubmit
+ifdef TOOL_NASM_USE_KSUBMIT
+ ifeq ($(KBUILD_HOST),win)
+  TOOL_NASM_KSUBMIT ?= kmk_builtin_kSubmit $1 --
+ endif
+endif
+
 # General Properties used by kBuild
 TOOL_NASM_ASFLAGS ?=
 
@@ -71,16 +78,30 @@ TOOL_NASM_COMPILE_AS_OUTPUT = $(outbase).lst
 TOOL_NASM_COMPILE_AS_DEPEND =
 TOOL_NASM_COMPILE_AS_DEPORD =
 define TOOL_NASM_COMPILE_AS_CMDS
-	$(QUIET)$(TOOL_NASM_AS)\
+ifdef TOOL_NASM_KSUBMIT
+	$(QUIET)$(call TOOL_NASM_KSUBMIT, -C $(PATH_OUT_BASE)) $(TOOL_NASM_AS)\
 		$(flags) $(addsuffix /,$(addprefix -i, $(incs))) $(addprefix -D, $(defs))\
 		-l $(outbase).lst\
 		-o $(obj)\
 		$(abspath $(source))
-	$(QUIET)$(REDIRECT) -C $(PATH_OUT_BASE) -wo $(dep) -- $(TOOL_NASM_AS) -DKBUILD_GENERATING_MAKEFILE_DEPENDENCIES\
+	$(QUIET)$(call TOOL_NASM_KSUBMIT, -C $(PATH_OUT_BASE)) $(TOOL_NASM_AS) -DKBUILD_GENERATING_MAKEFILE_DEPENDENCIES\
 		$(flags) $(addsuffix /,$(addprefix -i, $(incs))) $(addprefix -D, $(defs))\
 		-l $(outbase).lst\
 		-o $(obj)\
 		$(abspath $(source)) \
-		-M -MP
+		-MF "$(dep)" -MP
+else
+	$(QUIET)$(REDIRECT) -C $(PATH_OUT_BASE) $(TOOL_NASM_AS)\
+		$(flags) $(addsuffix /,$(addprefix -i, $(incs))) $(addprefix -D, $(defs))\
+		-l $(outbase).lst\
+		-o $(obj)\
+		$(abspath $(source))
+	$(QUIET)$(REDIRECT) -C $(PATH_OUT_BASE) -- $(TOOL_NASM_AS) -DKBUILD_GENERATING_MAKEFILE_DEPENDENCIES\
+		$(flags) $(addsuffix /,$(addprefix -i, $(incs))) $(addprefix -D, $(defs))\
+		-l $(outbase).lst\
+		-o $(obj)\
+		$(abspath $(source)) \
+		-MF "$(dep)" -MP
+endif
 endef
 
diff --git a/kBuild/tools/OPENWATCOM.kmk b/kBuild/tools/OPENWATCOM.kmk
index 26fb276..2b33a5b 100644
--- a/kBuild/tools/OPENWATCOM.kmk
+++ b/kBuild/tools/OPENWATCOM.kmk
@@ -1,4 +1,4 @@
-# $Id: OPENWATCOM.kmk 2750 2015-01-23 12:24:02Z bird $
+# $Id: OPENWATCOM.kmk 2882 2016-09-05 23:54:45Z bird $
 ## @file
 # kBuild Tool Config - Open Watcom v1.4 and later.
 #
@@ -107,7 +107,7 @@ ifneq ($(PATH_TOOL_OPENWATCOM),)
  	$2 --
  else
   PATH_TOOL_OPENWATCOM_BIN   = $(PATH_TOOL_OPENWATCOM)/binnt
-  TOOL_OPENWATCOM_ENV_SETUP ?= $(REDIRECT) \
+  TOOL_OPENWATCOM_ENV_SETUP ?= $(if-expr defined(TOOL_OPENWATCOM_USE_KSUBMIT),kmk_builtin_kSubmit --32-bit,$(REDIRECT)) \
  	-E 'PATH=$(PATH_TOOL_OPENWATCOM_BIN);$(PATH_TOOL_OPENWATCOM)/binw;$(PATH)' \
  	-E 'WATCOM=$(PATH_TOOL_OPENWATCOM)' \
  	-E 'EDPATH=$(PATH_TOOL_OPENWATCOM)/EDDAT' \
diff --git a/kBuild/tools/VCC100AMD64.kmk b/kBuild/tools/VCC100AMD64.kmk
index 4dca7c3..1239e64 100644
--- a/kBuild/tools/VCC100AMD64.kmk
+++ b/kBuild/tools/VCC100AMD64.kmk
@@ -1,10 +1,10 @@
-# $Id: VCC100AMD64.kmk 2795 2015-09-15 23:35:37Z bird $
+# $Id: VCC100AMD64.kmk 2870 2016-09-04 13:52:39Z bird $
 ## @file
 # kBuild Tool Config - Visual C++ 10.0 (aka Visual 2010 and MSC v16), targeting AMD64.
 #
 
 #
-# Copyright (c) 2004-2014 knut st. osmundsen <bird-kBuild-spam-xiv at anduin.net>
+# Copyright (c) 2004-2016 knut st. osmundsen <bird-kBuild-spam-xiv at anduin.net>
 #
 # This file is part of kBuild.
 #
@@ -74,6 +74,15 @@ TOOL_VCC100AMD64_DUMPBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/dumpb
 TOOL_VCC100AMD64_EDITBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/editbin.exe
 TOOL_VCC100AMD64_RC  ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,rc.exe,[Rr][Cc].[Ee][Xx][Ee],TOOL_VCC100_RC_CACHED)
 TOOL_VCC100AMD64_MT  ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,mt.exe,[Mm][Tt].[Ee][Xx][Ee],TOOL_VCC100_MT_CACHED)
+ifdef TOOL_VCC100AMD64_USE_KSUBMIT
+ ifeq ($(KBUILD_HOST),win)
+  ifneq ($(substr $(PATH_TOOL_VCC100AMD64_BIN),-9),x86_amd64)
+   TOOL_VCC100AMD64_KSUBMIT ?= kmk_builtin_kSubmit --64-bit --
+  else
+   TOOL_VCC100AMD64_KSUBMIT ?= kmk_builtin_kSubmit --32-bit --
+  endif
+ endif
+endif
 
 # The following in duplicated in VCC100.kmk and VCC100X86.kmk.
 TOOL_VCC100_FN_FIND_SDK_TOOL_SUB = $(eval $3 := $(firstword  \
@@ -163,7 +172,7 @@ else  # !KBUILD_USE_KOBJCACHE
 TOOL_VCC100AMD64_COMPILE_C_OUTPUT = $(call TOOL_VCC100AMD64_PDB, $(outbase)-obj,idb)
 TOOL_VCC100AMD64_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC100AMD64_PDB, $(outbase)-obj,pdb)
 define TOOL_VCC100AMD64_COMPILE_C_CMDS
-	$(QUIET)$(TOOL_VCC100AMD64_CC) -c\
+	$(QUIET)$(TOOL_VCC100AMD64_KSUBMIT) $(TOOL_VCC100AMD64_CC) -c\
 		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
 		-Fd$(outbase)-obj.pdb \
 		-FD\
@@ -211,7 +220,7 @@ else  # !KBUILD_USE_KOBJCACHE
 TOOL_VCC100AMD64_COMPILE_CXX_OUTPUT = $(call TOOL_VCC100AMD64_PDB, $(outbase)-obj,idb)
 TOOL_VCC100AMD64_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC100AMD64_PDB, $(outbase)-obj,pdb)
 define TOOL_VCC100AMD64_COMPILE_CXX_CMDS
-	$(QUIET)$(TOOL_VCC100AMD64_CXX) -c\
+	$(QUIET)$(TOOL_VCC100AMD64_KSUBMIT) $(TOOL_VCC100AMD64_CXX) -c\
 		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
 		-Fd$(outbase)-obj.pdb \
 		-FD\
diff --git a/kBuild/tools/VCC100X86.kmk b/kBuild/tools/VCC100X86.kmk
index 7168b0b..ed8d100 100644
--- a/kBuild/tools/VCC100X86.kmk
+++ b/kBuild/tools/VCC100X86.kmk
@@ -1,10 +1,10 @@
-# $Id: VCC100X86.kmk 2795 2015-09-15 23:35:37Z bird $
+# $Id: VCC100X86.kmk 2870 2016-09-04 13:52:39Z bird $
 ## @file
 # kBuild Tool Config - Visual C++ 10.0 (aka Visual 2010 and MSC v16), targeting x86.
 #
 
 #
-# Copyright (c) 2004-2014 knut st. osmundsen <bird-kBuild-spam-xiv at anduin.net>
+# Copyright (c) 2004-2016 knut st. osmundsen <bird-kBuild-spam-xiv at anduin.net>
 #
 # This file is part of kBuild.
 #
@@ -73,6 +73,11 @@ TOOL_VCC100X86_DUMPBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/dumpbin.e
 TOOL_VCC100X86_EDITBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/editbin.exe
 TOOL_VCC100X86_RC  ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,rc.exe,[Rr][Cc].[Ee][Xx][Ee],TOOL_VCC100_RC_CACHED)
 TOOL_VCC100X86_MT  ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,mt.exe,[Mm][Tt].[Ee][Xx][Ee],TOOL_VCC100_MT_CACHED)
+ifdef TOOL_VCC100X86_USE_KSUBMIT
+ ifeq ($(KBUILD_HOST),win)
+  TOOL_VCC100X86_KSUBMIT ?= kmk_builtin_kSubmit --32-bit --
+ endif
+endif
 
 # The following in duplicated in VCC100.kmk and VCC100X86.kmk.
 TOOL_VCC100_FN_FIND_SDK_TOOL_SUB = $(eval $3 := $(firstword  \
@@ -145,7 +150,7 @@ TOOL_VCC100X86_COMPILE_C_DEPORD =
 ifdef KBUILD_USE_KOBJCACHE
 TOOL_VCC100X86_COMPILE_C_USES_KOBJCACHE = 1
 TOOL_VCC100X86_COMPILE_C_OUTPUT = $(outbase).i
-TOOL_VCC100AMD64_COMPILE_C_OUTPUT_MAYBE =
+TOOL_VCC100X86_COMPILE_C_OUTPUT_MAYBE =
 define TOOL_VCC100X86_COMPILE_C_CMDS
 	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -O2 -r\
 		--make-dep-fix-case --make-dep-gen-stubs --make-dep-quiet --make-dep-file $(dep)\
@@ -164,7 +169,7 @@ else  # !KBUILD_USE_KOBJCACHE
 TOOL_VCC100X86_COMPILE_C_OUTPUT = $(call TOOL_VCC100X86_PDB, $(outbase)-obj,idb)
 TOOL_VCC100X86_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC100X86_PDB, $(outbase)-obj,pdb)
 define TOOL_VCC100X86_COMPILE_C_CMDS
-	$(QUIET)$(TOOL_VCC100X86_CC) -c\
+	$(QUIET)$(TOOL_VCC100X86_KSUBMIT) $(TOOL_VCC100X86_CC) -c\
 		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
 		-Fd$(outbase)-obj.pdb \
 		-FD\
@@ -193,7 +198,7 @@ TOOL_VCC100X86_COMPILE_CXX_DEPORD =
 ifdef KBUILD_USE_KOBJCACHE
 TOOL_VCC100X86_COMPILE_CXX_USES_KOBJCACHE = 1
 TOOL_VCC100X86_COMPILE_CXX_OUTPUT = $(outbase).ii
-TOOL_VCC100AMD64_COMPILE_CXX_OUTPUT_MAYBE =
+TOOL_VCC100X86_COMPILE_CXX_OUTPUT_MAYBE =
 define TOOL_VCC100X86_COMPILE_CXX_CMDS
 	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -O2 -r\
 		--make-dep-fix-case --make-dep-gen-stubs --make-dep-quiet --make-dep-file $(dep)\
@@ -212,7 +217,7 @@ else  # !KBUILD_USE_KOBJCACHE
 TOOL_VCC100X86_COMPILE_CXX_OUTPUT = $(call TOOL_VCC100X86_PDB, $(outbase)-obj,idb)
 TOOL_VCC100X86_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC100X86_PDB, $(outbase)-obj,pdb)
 define TOOL_VCC100X86_COMPILE_CXX_CMDS
-	$(QUIET)$(TOOL_VCC100X86_CXX) -c\
+	$(QUIET)$(TOOL_VCC100X86_KSUBMIT) $(TOOL_VCC100X86_CXX) -c\
 		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
 		-Fd$(outbase)-obj.pdb \
 		-FD\
diff --git a/kBuild/tools/YASM.kmk b/kBuild/tools/YASM.kmk
index 725402c..ed06adb 100644
--- a/kBuild/tools/YASM.kmk
+++ b/kBuild/tools/YASM.kmk
@@ -1,4 +1,4 @@
-# $Id: YASM.kmk 2750 2015-01-23 12:24:02Z bird $
+# $Id: YASM.kmk 2873 2016-09-04 19:13:12Z bird $
 ## @file
 # kBuild Tool Config - YASM 0.4.0 or later.
 #
@@ -49,6 +49,13 @@ else
  TOOL_YASM_AS ?= yasm$(HOSTSUFF_EXE)
 endif
 
+# kSubmit
+ifdef TOOL_YASM_USE_KSUBMIT
+ ifeq ($(KBUILD_HOST),win)
+  TOOL_YASM_KSUBMIT ?= kmk_builtin_kSubmit --
+ endif
+endif
+
 # General Properties used by kBuild
 TOOL_YASM_ASFLAGS ?=
 
@@ -71,7 +78,7 @@ TOOL_YASM_COMPILE_AS_OUTPUT_MAYBE = $(obj).map
 TOOL_YASM_COMPILE_AS_DEPEND =
 TOOL_YASM_COMPILE_AS_DEPORD =
 define TOOL_YASM_COMPILE_AS_CMDS
-	$(QUIET)$(TOOL_YASM_AS)\
+	$(QUIET)$(TOOL_YASM_KSUBMIT) $(TOOL_YASM_AS)\
 		$(patsubst --mapfile%,--mapfile=$(obj).map,$(flags))\
 		$(addsuffix /,$(addprefix -I, $(incs))) $(addprefix -D, $(defs))\
 		-l $(outbase).lst\
diff --git a/src/Makefile.kmk b/src/Makefile.kmk
index 4f700c7..a951bb3 100644
--- a/src/Makefile.kmk
+++ b/src/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 2413 2010-09-11 17:43:04Z bird $
+# $Id: Makefile.kmk 2846 2016-08-30 12:48:33Z bird $
 ## @file
 # Sub-makefile for the source directory.
 #
@@ -33,6 +33,10 @@ include $(PATH_SUB_CURRENT)/kash/Makefile.kmk
 include $(PATH_SUB_CURRENT)/kDepPre/Makefile.kmk
 include $(PATH_SUB_CURRENT)/kObjCache/Makefile.kmk
 include $(PATH_SUB_CURRENT)/misc/Makefile.kmk
+ifeq ($(KBUILD_TARGET),win)
+ include $(PATH_SUB_CURRENT)/kLibTweaker/Makefile.kmk
+ include $(PATH_SUB_CURRENT)/kWorker/Makefile.kmk
+endif
 
 include $(FILE_KBUILD_SUB_FOOTER)
 
diff --git a/src/kDepPre/Makefile.kmk b/src/kDepPre/Makefile.kmk
index 286f242..0c76b64 100644
--- a/src/kDepPre/Makefile.kmk
+++ b/src/kDepPre/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 2413 2010-09-11 17:43:04Z bird $
+# $Id: Makefile.kmk 2886 2016-09-06 14:31:46Z bird $
 ## @file
 # Sub-makefile for kDepPre, the precompiler based dependency generator.
 #
@@ -28,7 +28,7 @@ include $(KBUILD_PATH)/subheader.kmk
 
 PROGRAMS += kDepPre
 kDepPre_TEMPLATE        = BIN
-kDepPre_LIBS            = $(LIB_KDEP)
+kDepPre_LIBS            = $(LIB_KDEP) $(LIB_KUTIL)
 kDepPre_DEFS.linux      = HAVE_FGETC_UNLOCKED=1
 if1of ($(KBUILD_TARGET), win nt)
 kDepPre_DEFS           += NEED_ISBLANK=1 __WIN32__=1
diff --git a/src/kWorker/Makefile.kmk b/src/kWorker/Makefile.kmk
new file mode 100644
index 0000000..4f362f5
--- /dev/null
+++ b/src/kWorker/Makefile.kmk
@@ -0,0 +1,143 @@
+# $Id: Makefile.kmk 2878 2016-09-05 19:54:49Z bird $
+## @file
+# Sub-makefile for kWorker.
+#
+
+#
+# Copyright (c) 2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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 3 of the License, or
+# (at your option) any later version.
+#
+# kBuild 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 kBuild.  If not, see <http://www.gnu.org/licenses/>
+#
+#
+
+
+SUB_DEPTH = ../..
+include $(PATH_KBUILD)/subheader.kmk
+
+
+PROGRAMS += kWorker
+kWorker_TEMPLATE = BIN-STATIC-THREADED
+kWorker_DEFS.debug = K_STRICT
+kWorker_DEFS.release = NASSERT
+kWorker_SOURCES = kWorker.c
+kWorker_LIBS = \
+	$(kStuff_1_TARGET) \
+	$(kWorkerLib_1_TARGET)
+include $(KBUILD_PATH)/sdks/WINDDK71.kmk
+kWorker_LIBS.win = \
+	$(TEMPLATE_BIN-STATIC-THREADED_LIBS) \
+	$(PATH_SDK_WINDDK71_LIB_WNET)/ntdll.lib \
+	$(PATH_SDK_WINDDK71_LIB_WNET)/psapi.lib
+kWorker_LDFLAGS.win = \
+	/BASE:0x10000 /DYNAMICBASE:NO /FIXED /SECTION:DefLdBuf,EWR
+
+
+#
+# Stuff from ../libs.  Need to rebuilt it with static CRT.
+#
+LIBRARIES += kWorkerLib
+kWorkerLib_TEMPLATE = LIB-STATIC-THREADED
+kWorkerLib_DEFPATH = ../lib # Need fix from r2837.
+kWorkerLib_DEFPATH := $(PATH_SUB_CURRENT)/../lib
+kWorkerLib_SOURCES = \
+	crc32.c \
+	md5.c \
+       kbuild_version.c
+kWorkerLib_SOURCES.win = \
+	nt_fullpath.c \
+	quoted_spawn.c \
+       nt/nthlpcore.c \
+       nt/nthlpfs.c \
+       nt/ntdir.c \
+       nt/ntstat.c \
+       nt/ntunlink.c \
+       nt/kFsCache.c \
+       quote_argv.c
+kbuild_version.c_DEFS = KBUILD_SVN_REV=$(KBUILD_SVN_REV)
+
+#
+# kStuff library.
+#
+LIBRARIES += kStuff
+kStuff_TEMPLATE = LIB-STATIC-THREADED
+kStuff_DEFS.debug = K_STRICT
+kStuff_INCS = kStuff/include
+kStuff_DEFPATH = $(PATH_ROOT)/src/lib
+
+# kLdr
+kStuff_SOURCES += \
+	kStuff/kLdr/kLdr.c \
+	kStuff/kLdr/kLdrDyld.c \
+	kStuff/kLdr/kLdrDyldFind.c \
+	kStuff/kLdr/kLdrDyldMod.c \
+	kStuff/kLdr/kLdrDyldOS.c \
+	kStuff/kLdr/kLdrDyLdSem.c \
+	kStuff/kLdr/kLdrMod.c \
+	kStuff/kLdr/kLdrModLX.c \
+	kStuff/kLdr/kLdrModMachO.c \
+	kStuff/kLdr/kLdrModNative.c \
+	kStuff/kLdr/kLdrModPE.c
+kLdr_SOURCES.os2 += \
+	kStuff/kLdr/kLdr-os2.c \
+	kStuff/kLdr/kLdrA-os2.asm
+kLdr_SOURCES.win += \
+	kStuff/kLdr/kLdr-win.c
+
+# kRdr
+kStuff_SOURCES += \
+	kStuff/kRdr/kRdr.cpp \
+	kStuff/kRdr/kRdrFile.cpp \
+	kStuff/kRdr/kRdrBuffered.cpp
+
+# kCpu
+kStuff_SOURCES += \
+	kStuff/kCpu/kCpuCompare.c \
+	kStuff/kCpu/kCpuGetArchAndCpu.c
+
+# kHlp (CRT)
+kStuff_SOURCES += \
+	kStuff/kHlp/Generic/kHlpMemPComp.c \
+	kStuff/kHlp/Generic/kHlpMemICompAscii.c \
+	kStuff/kHlp/Generic/kHlpStrPCat.c \
+	kStuff/kHlp/Generic/kHlpStrNPCat.c \
+	kStuff/kHlp/Generic/kHlpStrPComp.c \
+	kStuff/kHlp/Generic/kHlpStrNPComp.c \
+	kStuff/kHlp/Generic/kHlpStrICompAscii.c \
+	kStuff/kHlp/Generic/kHlpStrIPCompAscii.c \
+	kStuff/kHlp/Generic/kHlpStrNICompAscii.c \
+	kStuff/kHlp/Generic/kHlpStrNIPCompAscii.c \
+	kStuff/kHlp/Generic/kHlpStrPCopy.c \
+	kStuff/kHlp/Generic/kHlpStrNLen.c \
+	kStuff/kHlp/Generic/kHlpInt2Ascii.c \
+	\
+	kStuff/kHlp/Generic/kHlpGetEnvUZ.c \
+	\
+	kStuff/kHlp/Generic/kHlpGetExt.c \
+	kStuff/kHlp/Generic/kHlpGetFilename.c \
+	kStuff/kHlp/Generic/kHlpIsFilenameOnly.c \
+	\
+	kStuff/kHlp/Generic/kHlpPage.c \
+	\
+	kStuff/kHlp/CRT/kHlpCRTAlloc.cpp \
+	kStuff/kHlp/CRT/kHlpCRTEnv.cpp \
+	kStuff/kHlp/CRT/kHlpCRTString.cpp
+kStuff_SOURCES.darwin += \
+	kStuff/kHlp/Bare/kHlpSys-darwin.c
+
+
+
+include $(KBUILD_PATH)/subfooter.kmk
+
diff --git a/src/kWorker/kWorker.c b/src/kWorker/kWorker.c
new file mode 100644
index 0000000..fb46d62
--- /dev/null
+++ b/src/kWorker/kWorker.c
@@ -0,0 +1,7451 @@
+/* $Id: kWorker.c 2888 2016-09-06 15:02:20Z bird $ */
+/** @file
+ * kWorker - experimental process reuse worker for Windows.
+ *
+ * Note! This module must be linked statically in order to avoid
+ *       accidentally intercepting our own CRT calls.
+ */
+
+/*
+ * Copyright (c) 2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * kBuild 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 kBuild.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+//#undef NDEBUG
+#define PSAPI_VERSION 1
+#include <k/kHlp.h>
+#include <k/kLdr.h>
+
+#include <stdio.h>
+#include <intrin.h>
+#include <setjmp.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "nt/ntstat.h"
+#include "kbuild_version.h"
+/* lib/nt_fullpath.c */
+extern void nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull);
+
+#include "nt/ntstuff.h"
+#include <psapi.h>
+
+#include "nt/kFsCache.h"
+#include "quote_argv.h"
+#include "md5.h"
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+/** @def WITH_TEMP_MEMORY_FILES
+ * Enables temporary memory files for cl.exe.  */
+#define WITH_TEMP_MEMORY_FILES
+
+/** @def WITH_HASH_MD5_CACHE
+ * Enables caching of MD5 sums for cl.exe.
+ * This prevents wasting time on rehashing common headers each time
+ * they are included. */
+#define WITH_HASH_MD5_CACHE
+
+
+/** String constant comma length.   */
+#define TUPLE(a_sz)                     a_sz, sizeof(a_sz) - 1
+
+/** @def KW_LOG
+ * Generic logging.
+ * @param a     Argument list for kwDbgPrintf  */
+#ifndef NDEBUG
+# define KW_LOG(a) kwDbgPrintf a
+#else
+# define KW_LOG(a) do { } while (0)
+#endif
+
+/** @def KWFS_LOG
+ * FS cache logging.
+ * @param a     Argument list for kwDbgPrintf  */
+#ifndef NDEBUG
+# define KWFS_LOG(a) kwDbgPrintf a
+#else
+# define KWFS_LOG(a) do { } while (0)
+#endif
+
+/** @def KWCRYPT_LOG
+ * FS cache logging.
+ * @param a     Argument list for kwDbgPrintf  */
+#ifndef NDEBUG
+# define KWCRYPT_LOG(a) kwDbgPrintf a
+#else
+# define KWCRYPT_LOG(a) do { } while (0)
+#endif
+
+/** Converts a windows handle to a handle table index.
+ * @note We currently just mask off the 31th bit, and do no shifting or anything
+ *     else to create an index of the handle.
+ * @todo consider shifting by 2 or 3. */
+#define KW_HANDLE_TO_INDEX(a_hHandle)   ((KUPTR)(a_hHandle) & ~(KUPTR)KU32_C(0x8000000))
+/** Maximum handle value we can deal with.   */
+#define KW_HANDLE_MAX                   0x20000
+
+/** Max temporary file size (memory backed).  */
+#if K_ARCH_BITS >= 64
+# define KWFS_TEMP_FILE_MAX             (256*1024*1024)
+#else
+# define KWFS_TEMP_FILE_MAX             (64*1024*1024)
+#endif
+
+/** Marks unfinished code.  */
+#if 1
+# define KWFS_TODO()    do { kwErrPrintf("\nHit TODO on line %u in %s!\n", __LINE__, __FUNCTION__); __debugbreak(); } while (0)
+#else
+# define KWFS_TODO()    do { kwErrPrintf("\nHit TODO on line %u in %s!\n", __LINE__, __FUNCTION__); } while (0)
+#endif
+
+/** User data key for tools. */
+#define KW_DATA_KEY_TOOL                (~(KUPTR)16381)
+/** User data key for a cached file. */
+#define KW_DATA_KEY_CACHED_FILE         (~(KUPTR)65521)
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+typedef enum KWLOCATION
+{
+    KWLOCATION_INVALID = 0,
+    KWLOCATION_EXE_DIR,
+    KWLOCATION_IMPORTER_DIR,
+    KWLOCATION_SYSTEM32,
+    KWLOCATION_UNKNOWN_NATIVE,
+    KWLOCATION_UNKNOWN,
+} KWLOCATION;
+
+typedef enum KWMODSTATE
+{
+    KWMODSTATE_INVALID = 0,
+    KWMODSTATE_NEEDS_BITS,
+    KWMODSTATE_NEEDS_INIT,
+    KWMODSTATE_BEING_INITED,
+    KWMODSTATE_INIT_FAILED,
+    KWMODSTATE_READY,
+} KWMODSTATE;
+
+typedef struct KWMODULE *PKWMODULE;
+typedef struct KWMODULE
+{
+    /** Pointer to the next image. */
+    PKWMODULE           pNext;
+    /** The normalized path to the image. */
+    const char         *pszPath;
+    /** The hash of the program path. */
+    KU32                uHashPath;
+    /** Number of references. */
+    KU32                cRefs;
+    /** UTF-16 version of pszPath. */
+    const wchar_t      *pwszPath;
+    /** The offset of the filename in pszPath. */
+    KU16                offFilename;
+    /** Set if executable. */
+    KBOOL               fExe;
+    /** Set if native module entry. */
+    KBOOL               fNative;
+    /** Loader module handle. */
+    PKLDRMOD            pLdrMod;
+    /** The windows module handle. */
+    HMODULE             hOurMod;
+    /** The of the loaded image bits. */
+    KSIZE               cbImage;
+
+    union
+    {
+        /** Data for a manually loaded image. */
+        struct
+        {
+            /** Where we load the image. */
+            void               *pvLoad;
+            /** Virgin copy of the image. */
+            void               *pvCopy;
+            /** Ldr pvBits argument.  This is NULL till we've successfully resolved
+             *  the imports. */
+            void               *pvBits;
+            /** The state. */
+            KWMODSTATE          enmState;
+#if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_AMD64)
+            /** The number of entries in the table. */
+            KU32                cFunctions;
+            /** The function table address (in the copy). */
+            PRUNTIME_FUNCTION   paFunctions;
+            /** Set if we've already registered a function table already. */
+            KBOOL               fRegisteredFunctionTable;
+#endif
+            /** Set if we share memory with other executables. */
+            KBOOL               fUseLdBuf;
+            /** Number of imported modules. */
+            KSIZE               cImpMods;
+            /** Import array (variable size). */
+            PKWMODULE           apImpMods[1];
+        } Manual;
+    } u;
+} KWMODULE;
+
+
+typedef struct KWDYNLOAD *PKWDYNLOAD;
+typedef struct KWDYNLOAD
+{
+    /** Pointer to the next in the list. */
+    PKWDYNLOAD          pNext;
+
+    /** The module handle we present to the application.
+     * This is the LoadLibraryEx return value for special modules and the
+     * KWMODULE.hOurMod value for the others. */
+    HMODULE             hmod;
+
+    /** The module for non-special resource stuff, NULL if special. */
+    PKWMODULE           pMod;
+
+    /** The length of the LoadLibary filename. */
+    KSIZE               cchRequest;
+    /** The LoadLibrary filename. */
+    char                szRequest[1];
+} KWDYNLOAD;
+
+
+/**
+ * GetModuleHandle cache for system modules frequently queried.
+ */
+typedef struct KWGETMODULEHANDLECACHE
+{
+    const char     *pszName;
+    KU8             cchName;
+    KU8             cwcName;
+    const wchar_t  *pwszName;
+    HANDLE          hmod;
+} KWGETMODULEHANDLECACHE;
+typedef KWGETMODULEHANDLECACHE *PKWGETMODULEHANDLECACHE;
+
+
+/**
+ * A cached file.
+ */
+typedef struct KFSWCACHEDFILE
+{
+    /** The user data core. */
+    KFSUSERDATA         Core;
+
+    /** Cached file handle. */
+    HANDLE              hCached;
+    /** Cached file content. */
+    KU8                *pbCached;
+    /** The file size. */
+    KU32                cbCached;
+#ifdef WITH_HASH_MD5_CACHE
+    /** Set if we've got a valid MD5 hash in abMd5Digest. */
+    KBOOL               fValidMd5;
+    /** The MD5 digest if fValidMd5 is set. */
+    KU8                 abMd5Digest[16];
+#endif
+
+    /** Circular self reference. Prevents the object from ever going away and
+     * keeps it handy for debugging. */
+    PKFSOBJ             pFsObj;
+    /** The file path (for debugging).   */
+    char                szPath[1];
+} KFSWCACHEDFILE;
+/** Pointer to a cached filed. */
+typedef KFSWCACHEDFILE *PKFSWCACHEDFILE;
+
+
+#ifdef WITH_HASH_MD5_CACHE
+/** Pointer to a MD5 hash instance. */
+typedef struct KWHASHMD5 *PKWHASHMD5;
+/**
+ * A MD5 hash instance.
+ */
+typedef struct KWHASHMD5
+{
+    /** The magic value. */
+    KUPTR               uMagic;
+    /** Pointer to the next hash handle. */
+    PKWHASHMD5          pNext;
+    /** The cached file we've associated this handle with. */
+    PKFSWCACHEDFILE     pCachedFile;
+    /** The number of bytes we've hashed. */
+    KU32                cbHashed;
+    /** Set if this has gone wrong. */
+    KBOOL               fGoneBad;
+    /** Set if we're in fallback mode (file not cached). */
+    KBOOL               fFallbackMode;
+    /** Set if we've already finalized the digest. */
+    KBOOL               fFinal;
+    /** The MD5 fallback context. */
+    struct MD5Context   Md5Ctx;
+    /** The finalized digest. */
+    KU8                 abDigest[16];
+
+} KWHASHMD5;
+/** Magic value for KWHASHMD5::uMagic (Les McCann). */
+# define KWHASHMD5_MAGIC    KUPTR_C(0x19350923)
+#endif /* WITH_HASH_MD5_CACHE */
+
+
+
+typedef struct KWFSTEMPFILESEG *PKWFSTEMPFILESEG;
+typedef struct KWFSTEMPFILESEG
+{
+    /** File offset of data. */
+    KU32                offData;
+    /** The size of the buffer pbData points to. */
+    KU32                cbDataAlloc;
+    /** The segment data. */
+    KU8                *pbData;
+} KWFSTEMPFILESEG;
+
+typedef struct KWFSTEMPFILE *PKWFSTEMPFILE;
+typedef struct KWFSTEMPFILE
+{
+    /** Pointer to the next temporary file for this run. */
+    PKWFSTEMPFILE       pNext;
+    /** The UTF-16 path. (Allocated after this structure.)  */
+    const wchar_t      *pwszPath;
+    /** The path length. */
+    KU16                cwcPath;
+    /** Number of active handles using this file/mapping (<= 2). */
+    KU8                 cActiveHandles;
+    /** Number of active mappings (mapped views) (0 or 1). */
+    KU8                 cMappings;
+    /** The amount of space allocated in the segments. */
+    KU32                cbFileAllocated;
+    /** The current file size. */
+    KU32                cbFile;
+    /** The number of segments. */
+    KU32                cSegs;
+    /** Segments making up the file. */
+    PKWFSTEMPFILESEG    paSegs;
+} KWFSTEMPFILE;
+
+
+/** Handle type.   */
+typedef enum KWHANDLETYPE
+{
+    KWHANDLETYPE_INVALID = 0,
+    KWHANDLETYPE_FSOBJ_READ_CACHE,
+    KWHANDLETYPE_TEMP_FILE,
+    KWHANDLETYPE_TEMP_FILE_MAPPING
+    //KWHANDLETYPE_CONSOLE_CACHE
+} KWHANDLETYPE;
+
+/** Handle data. */
+typedef struct KWHANDLE
+{
+    KWHANDLETYPE        enmType;
+    /** The current file offset. */
+    KU32                offFile;
+    /** Handle access. */
+    KU32                dwDesiredAccess;
+    /** The handle. */
+    HANDLE              hHandle;
+
+    /** Type specific data. */
+    union
+    {
+        /** The file system object.   */
+        PKFSWCACHEDFILE     pCachedFile;
+        /** Temporary file handle or mapping handle. */
+        PKWFSTEMPFILE       pTempFile;
+    } u;
+} KWHANDLE;
+typedef KWHANDLE *PKWHANDLE;
+
+
+/** Pointer to a VirtualAlloc tracker entry. */
+typedef struct KWVIRTALLOC *PKWVIRTALLOC;
+/**
+ * Tracking an VirtualAlloc allocation.
+ */
+typedef struct KWVIRTALLOC
+{
+    PKWVIRTALLOC        pNext;
+    void               *pvAlloc;
+    KSIZE               cbAlloc;
+} KWVIRTALLOC;
+
+
+/** Pointer to a FlsAlloc/TlsAlloc tracker entry. */
+typedef struct KWLOCALSTORAGE *PKWLOCALSTORAGE;
+/**
+ * Tracking an FlsAlloc/TlsAlloc index.
+ */
+typedef struct KWLOCALSTORAGE
+{
+    PKWLOCALSTORAGE     pNext;
+    KU32                idx;
+} KWLOCALSTORAGE;
+
+
+typedef enum KWTOOLTYPE
+{
+    KWTOOLTYPE_INVALID = 0,
+    KWTOOLTYPE_SANDBOXED,
+    KWTOOLTYPE_WATCOM,
+    KWTOOLTYPE_EXEC,
+    KWTOOLTYPE_END
+} KWTOOLTYPE;
+
+typedef enum KWTOOLHINT
+{
+    KWTOOLHINT_INVALID = 0,
+    KWTOOLHINT_NONE,
+    KWTOOLHINT_VISUAL_CPP_CL,
+    KWTOOLHINT_END
+} KWTOOLHINT;
+
+
+/**
+ * A kWorker tool.
+ */
+typedef struct KWTOOL
+{
+    /** The user data core structure. */
+    KFSUSERDATA         Core;
+
+    /** The normalized path to the program. */
+    const char         *pszPath;
+    /** UTF-16 version of pszPath. */
+    wchar_t const      *pwszPath;
+    /** The kind of tool. */
+    KWTOOLTYPE          enmType;
+
+    union
+    {
+        struct
+        {
+            /** The main entry point. */
+            KUPTR       uMainAddr;
+            /** The executable. */
+            PKWMODULE   pExe;
+            /** List of dynamically loaded modules.
+             * These will be kept loaded till the tool is destroyed (if we ever do that). */
+            PKWDYNLOAD  pDynLoadHead;
+            /** Module array sorted by hOurMod. */
+            PKWMODULE  *papModules;
+            /** Number of entries in papModules. */
+            KU32        cModules;
+
+            /** Tool hint (for hacks and such). */
+            KWTOOLHINT  enmHint;
+        } Sandboxed;
+    } u;
+} KWTOOL;
+/** Pointer to a tool. */
+typedef struct KWTOOL *PKWTOOL;
+
+
+typedef struct KWSANDBOX *PKWSANDBOX;
+typedef struct KWSANDBOX
+{
+    /** The tool currently running in the sandbox. */
+    PKWTOOL     pTool;
+    /** Jump buffer. */
+    jmp_buf     JmpBuf;
+    /** The thread ID of the main thread (owner of JmpBuf). */
+    DWORD       idMainThread;
+    /** Copy of the NT TIB of the main thread. */
+    NT_TIB      TibMainThread;
+    /** The NT_TIB::ExceptionList value inside the try case.
+     * We restore this prior to the longjmp.  */
+    void       *pOutXcptListHead;
+    /** The exit code in case of longjmp.   */
+    int         rcExitCode;
+    /** Set if we're running. */
+    KBOOL       fRunning;
+
+    /** The command line.   */
+    char       *pszCmdLine;
+    /** The UTF-16 command line. */
+    wchar_t    *pwszCmdLine;
+    /** Number of arguments in papszArgs. */
+    int         cArgs;
+    /** The argument vector. */
+    char      **papszArgs;
+    /** The argument vector. */
+    wchar_t   **papwszArgs;
+
+    /** The _pgmptr msvcrt variable.  */
+    char       *pgmptr;
+    /** The _wpgmptr msvcrt variable. */
+    wchar_t    *wpgmptr;
+
+    /** The _initenv msvcrt variable. */
+    char      **initenv;
+    /** The _winitenv msvcrt variable. */
+    wchar_t   **winitenv;
+
+    /** Size of the array we've allocated (ASSUMES nobody messes with it!). */
+    KSIZE       cEnvVarsAllocated;
+    /** The _environ msvcrt variable. */
+    char      **environ;
+    /** The _wenviron msvcrt variable. */
+    wchar_t   **wenviron;
+    /** The shadow _environ msvcrt variable. */
+    char      **papszEnvVars;
+    /** The shadow _wenviron msvcrt variable. */
+    wchar_t   **papwszEnvVars;
+
+
+    /** Handle table. */
+    PKWHANDLE      *papHandles;
+    /** Size of the handle table. */
+    KU32            cHandles;
+    /** Number of active handles in the table. */
+    KU32            cActiveHandles;
+
+    /** Head of the list of temporary file. */
+    PKWFSTEMPFILE   pTempFileHead;
+
+    /** Head of the virtual alloc allocations. */
+    PKWVIRTALLOC    pVirtualAllocHead;
+    /** Head of the FlsAlloc indexes. */
+    PKWLOCALSTORAGE pFlsAllocHead;
+    /** Head of the TlsAlloc indexes. */
+    PKWLOCALSTORAGE pTlsAllocHead;
+
+    UNICODE_STRING  SavedCommandLine;
+
+#ifdef WITH_HASH_MD5_CACHE
+    /** The special MD5 hash instance. */
+    PKWHASHMD5      pHashHead;
+    /** ReadFile sets these while CryptHashData claims and clears them.
+     *
+     * This is part of the heuristics we use for MD5 caching for header files. The
+     * observed pattern is that c1.dll/c1xx.dll first reads a chunk of a source or
+     * header, then passes the same buffer and read byte count to CryptHashData.
+     */
+    struct
+    {
+        /** The cached file last read from. */
+        PKFSWCACHEDFILE pCachedFile;
+        /** The file offset of the last cached read. */
+        KU32            offRead;
+        /** The number of bytes read last. */
+        KU32            cbRead;
+        /** The buffer pointer of the last read. */
+        void           *pvRead;
+    } LastHashRead;
+#endif
+} KWSANDBOX;
+
+/** Replacement function entry. */
+typedef struct KWREPLACEMENTFUNCTION
+{
+    /** The function name. */
+    const char *pszFunction;
+    /** The length of the function name. */
+    KSIZE       cchFunction;
+    /** The module name (optional). */
+    const char *pszModule;
+    /** The replacement function or data address. */
+    KUPTR       pfnReplacement;
+} KWREPLACEMENTFUNCTION;
+typedef KWREPLACEMENTFUNCTION const *PCKWREPLACEMENTFUNCTION;
+
+#if 0
+/** Replacement function entry. */
+typedef struct KWREPLACEMENTDATA
+{
+    /** The function name. */
+    const char *pszFunction;
+    /** The length of the function name. */
+    KSIZE       cchFunction;
+    /** The module name (optional). */
+    const char *pszModule;
+    /** Function providing the replacement. */
+    KUPTR     (*pfnMakeReplacement)(PKWMODULE pMod, const char *pchSymbol, KSIZE cchSymbol);
+} KWREPLACEMENTDATA;
+typedef KWREPLACEMENTDATA const *PCKWREPLACEMENTDATA;
+#endif
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** The sandbox data. */
+static KWSANDBOX    g_Sandbox;
+
+/** The module currently occupying g_abDefLdBuf. */
+static PKWMODULE    g_pModInLdBuf = NULL;
+
+/** Module hash table. */
+static PKWMODULE    g_apModules[127];
+
+/** GetModuleHandle cache. */
+static KWGETMODULEHANDLECACHE g_aGetModuleHandleCache[] =
+{
+#define MOD_CACHE_STRINGS(str) str, sizeof(str) - 1, (sizeof(L##str) / sizeof(wchar_t)) - 1, L##str
+    { MOD_CACHE_STRINGS("KERNEL32.DLL"),    NULL },
+    { MOD_CACHE_STRINGS("mscoree.dll"),     NULL },
+};
+
+
+/** The file system cache. */
+static PKFSCACHE    g_pFsCache;
+/** The current directory (referenced). */
+static PKFSOBJ      g_pCurDirObj = NULL;
+
+/** Verbosity level. */
+static int          g_cVerbose = 2;
+
+/** Whether we should restart the worker. */
+static KBOOL        g_fRestart = K_FALSE;
+
+/* Further down. */
+extern KWREPLACEMENTFUNCTION const g_aSandboxReplacements[];
+extern KU32                  const g_cSandboxReplacements;
+
+extern KWREPLACEMENTFUNCTION const g_aSandboxNativeReplacements[];
+extern KU32                  const g_cSandboxNativeReplacements;
+
+/** Create a larget BSS blob that with help of /IMAGEBASE:0x10000 should
+ * cover the default executable link address of 0x400000. */
+#pragma section("DefLdBuf", write, execute, read)
+__declspec(allocate("DefLdBuf"))
+static KU8          g_abDefLdBuf[16*1024*1024];
+
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+static FNKLDRMODGETIMPORT kwLdrModuleGetImportCallback;
+static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWMODULE pImporter, PKWMODULE *ppMod);
+static KBOOL kwSandboxHandleTableEnter(PKWSANDBOX pSandbox, PKWHANDLE pHandle);
+
+
+
+/**
+ * Debug printing.
+ * @param   pszFormat           Debug format string.
+ * @param   ...                 Format argument.
+ */
+static void kwDbgPrintfV(const char *pszFormat, va_list va)
+{
+    if (g_cVerbose >= 2)
+    {
+        DWORD const dwSavedErr = GetLastError();
+
+        fprintf(stderr, "debug: ");
+        vfprintf(stderr, pszFormat, va);
+
+        SetLastError(dwSavedErr);
+    }
+}
+
+
+/**
+ * Debug printing.
+ * @param   pszFormat           Debug format string.
+ * @param   ...                 Format argument.
+ */
+static void kwDbgPrintf(const char *pszFormat, ...)
+{
+    if (g_cVerbose >= 2)
+    {
+        va_list va;
+        va_start(va, pszFormat);
+        kwDbgPrintfV(pszFormat, va);
+        va_end(va);
+    }
+}
+
+
+/**
+ * Debugger printing.
+ * @param   pszFormat           Debug format string.
+ * @param   ...                 Format argument.
+ */
+static void kwDebuggerPrintfV(const char *pszFormat, va_list va)
+{
+    if (IsDebuggerPresent())
+    {
+        DWORD const dwSavedErr = GetLastError();
+        char szTmp[2048];
+
+        _vsnprintf(szTmp, sizeof(szTmp), pszFormat, va);
+        OutputDebugStringA(szTmp);
+
+        SetLastError(dwSavedErr);
+    }
+}
+
+
+/**
+ * Debugger printing.
+ * @param   pszFormat           Debug format string.
+ * @param   ...                 Format argument.
+ */
+static void kwDebuggerPrintf(const char *pszFormat, ...)
+{
+    va_list va;
+    va_start(va, pszFormat);
+    kwDebuggerPrintfV(pszFormat, va);
+    va_end(va);
+}
+
+
+
+/**
+ * Error printing.
+ * @param   pszFormat           Message format string.
+ * @param   ...                 Format argument.
+ */
+static void kwErrPrintfV(const char *pszFormat, va_list va)
+{
+    DWORD const dwSavedErr = GetLastError();
+
+    fprintf(stderr, "kWorker: error: ");
+    vfprintf(stderr, pszFormat, va);
+
+    SetLastError(dwSavedErr);
+}
+
+
+/**
+ * Error printing.
+ * @param   pszFormat           Message format string.
+ * @param   ...                 Format argument.
+ */
+static void kwErrPrintf(const char *pszFormat, ...)
+{
+    va_list va;
+    va_start(va, pszFormat);
+    kwErrPrintfV(pszFormat, va);
+    va_end(va);
+}
+
+
+/**
+ * Error printing.
+ * @return  rc;
+ * @param   rc                  Return value
+ * @param   pszFormat           Message format string.
+ * @param   ...                 Format argument.
+ */
+static int kwErrPrintfRc(int rc, const char *pszFormat, ...)
+{
+    va_list va;
+    va_start(va, pszFormat);
+    kwErrPrintfV(pszFormat, va);
+    va_end(va);
+    return rc;
+}
+
+
+#ifdef K_STRICT
+
+KHLP_DECL(void) kHlpAssertMsg1(const char *pszExpr, const char *pszFile, unsigned iLine, const char *pszFunction)
+{
+    DWORD const dwSavedErr = GetLastError();
+
+    fprintf(stderr,
+            "\n"
+            "!!Assertion failed!!\n"
+            "Expression: %s\n"
+            "Function :  %s\n"
+            "File:       %s\n"
+            "Line:       %d\n"
+            ,  pszExpr, pszFunction, pszFile, iLine);
+
+    SetLastError(dwSavedErr);
+}
+
+
+KHLP_DECL(void) kHlpAssertMsg2(const char *pszFormat, ...)
+{
+    DWORD const dwSavedErr = GetLastError();
+    va_list va;
+
+    va_start(va, pszFormat);
+    fprintf(stderr, pszFormat, va);
+    va_end(va);
+
+    SetLastError(dwSavedErr);
+}
+
+#endif /* K_STRICT */
+
+
+/**
+ * Hashes a string.
+ *
+ * @returns 32-bit string hash.
+ * @param   pszString           String to hash.
+ */
+static KU32 kwStrHash(const char *pszString)
+{
+    /* This algorithm was created for sdbm (a public-domain reimplementation of
+       ndbm) database library. it was found to do well in scrambling bits,
+       causing better distribution of the keys and fewer splits. it also happens
+       to be a good general hashing function with good distribution. the actual
+       function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below
+       is the faster version used in gawk. [there is even a faster, duff-device
+       version] the magic constant 65599 was picked out of thin air while
+       experimenting with different constants, and turns out to be a prime.
+       this is one of the algorithms used in berkeley db (see sleepycat) and
+       elsewhere. */
+    KU32 uHash = 0;
+    KU32 uChar;
+    while ((uChar = (unsigned char)*pszString++) != 0)
+        uHash = uChar + (uHash << 6) + (uHash << 16) - uHash;
+    return uHash;
+}
+
+
+/**
+ * Hashes a string.
+ *
+ * @returns The string length.
+ * @param   pszString           String to hash.
+ * @param   puHash              Where to return the 32-bit string hash.
+ */
+static KSIZE kwStrHashEx(const char *pszString, KU32 *puHash)
+{
+    const char * const pszStart = pszString;
+    KU32 uHash = 0;
+    KU32 uChar;
+    while ((uChar = (unsigned char)*pszString) != 0)
+    {
+        uHash = uChar + (uHash << 6) + (uHash << 16) - uHash;
+        pszString++;
+    }
+    *puHash = uHash;
+    return pszString - pszStart;
+}
+
+
+/**
+ * Hashes a string.
+ *
+ * @returns The string length in wchar_t units.
+ * @param   pwszString          String to hash.
+ * @param   puHash              Where to return the 32-bit string hash.
+ */
+static KSIZE kwUtf16HashEx(const wchar_t *pwszString, KU32 *puHash)
+{
+    const wchar_t * const pwszStart = pwszString;
+    KU32 uHash = 0;
+    KU32 uChar;
+    while ((uChar = *pwszString) != 0)
+    {
+        uHash = uChar + (uHash << 6) + (uHash << 16) - uHash;
+        pwszString++;
+    }
+    *puHash = uHash;
+    return pwszString - pwszStart;
+}
+
+
+/**
+ * Converts the given string to unicode.
+ *
+ * @returns Length of the resulting string in wchar_t's.
+ * @param   pszSrc              The source string.
+ * @param   pwszDst             The destination buffer.
+ * @param   cwcDst              The size of the destination buffer in wchar_t's.
+ */
+static KSIZE kwStrToUtf16(const char *pszSrc, wchar_t *pwszDst, KSIZE cwcDst)
+{
+    /* Just to the quick ASCII stuff for now. correct ansi code page stuff later some time.  */
+    KSIZE offDst = 0;
+    while (offDst < cwcDst)
+    {
+        char ch = *pszSrc++;
+        pwszDst[offDst++] = ch;
+        if (!ch)
+            return offDst - 1;
+        kHlpAssert((unsigned)ch < 127);
+    }
+
+    pwszDst[offDst - 1] = '\0';
+    return offDst;
+}
+
+
+/**
+ * Converts the given string to UTF-16, allocating the buffer.
+ *
+ * @returns Pointer to the new heap allocation containing the UTF-16 version of
+ *          the source string.
+ * @param   pchSrc              The source string.
+ * @param   cchSrc              The length of the source string.
+ */
+static wchar_t *kwStrToUtf16AllocN(const char *pchSrc, KSIZE cchSrc)
+{
+    DWORD const dwErrSaved = GetLastError();
+    KSIZE       cwcBuf     = cchSrc + 1;
+    wchar_t    *pwszBuf    = (wchar_t *)kHlpAlloc(cwcBuf * sizeof(pwszBuf));
+    if (pwszBuf)
+    {
+        if (cchSrc > 0)
+        {
+            int cwcRet = MultiByteToWideChar(CP_ACP, 0, pchSrc, (int)cchSrc, pwszBuf, (int)cwcBuf - 1);
+            if (cwcRet > 0)
+            {
+                kHlpAssert(cwcRet < (KSSIZE)cwcBuf);
+                pwszBuf[cwcRet] = '\0';
+            }
+            else
+            {
+                kHlpFree(pwszBuf);
+
+                /* Figure the length and allocate the right buffer size. */
+                SetLastError(NO_ERROR);
+                cwcRet = MultiByteToWideChar(CP_ACP, 0, pchSrc, (int)cchSrc, pwszBuf, 0);
+                if (cwcRet)
+                {
+                    cwcBuf = cwcRet + 2;
+                    pwszBuf = (wchar_t *)kHlpAlloc(cwcBuf * sizeof(pwszBuf));
+                    if (pwszBuf)
+                    {
+                        SetLastError(NO_ERROR);
+                        cwcRet = MultiByteToWideChar(CP_ACP, 0, pchSrc, (int)cchSrc, pwszBuf, (int)cwcBuf - 1);
+                        if (cwcRet)
+                        {
+                            kHlpAssert(cwcRet < (KSSIZE)cwcBuf);
+                            pwszBuf[cwcRet] = '\0';
+                        }
+                        else
+                        {
+                            kwErrPrintf("MultiByteToWideChar(,,%*.*s,,) -> dwErr=%d\n", cchSrc, cchSrc, pchSrc, GetLastError());
+                            kHlpFree(pwszBuf);
+                            pwszBuf = NULL;
+                        }
+                    }
+                }
+                else
+                {
+                    kwErrPrintf("MultiByteToWideChar(,,%*.*s,,NULL,0) -> dwErr=%d\n", cchSrc, cchSrc, pchSrc, GetLastError());
+                    pwszBuf = NULL;
+                }
+            }
+        }
+        else
+            pwszBuf[0] = '\0';
+    }
+    SetLastError(dwErrSaved);
+    return pwszBuf;
+}
+
+
+/**
+ * Converts the given UTF-16 to a normal string.
+ *
+ * @returns Length of the resulting string.
+ * @param   pwszSrc             The source UTF-16 string.
+ * @param   pszDst              The destination buffer.
+ * @param   cbDst               The size of the destination buffer in bytes.
+ */
+static KSIZE kwUtf16ToStr(const wchar_t *pwszSrc, char *pszDst, KSIZE cbDst)
+{
+    /* Just to the quick ASCII stuff for now. correct ansi code page stuff later some time.  */
+    KSIZE offDst = 0;
+    while (offDst < cbDst)
+    {
+        wchar_t wc = *pwszSrc++;
+        pszDst[offDst++] = (char)wc;
+        if (!wc)
+            return offDst - 1;
+        kHlpAssert((unsigned)wc < 127);
+    }
+
+    pszDst[offDst - 1] = '\0';
+    return offDst;
+}
+
+
+/**
+ * Converts the given UTF-16 to ASSI, allocating the buffer.
+ *
+ * @returns Pointer to the new heap allocation containing the ANSI version of
+ *          the source string.
+ * @param   pwcSrc              The source string.
+ * @param   cwcSrc              The length of the source string.
+ */
+static char *kwUtf16ToStrAllocN(const wchar_t *pwcSrc, KSIZE cwcSrc)
+{
+    DWORD const dwErrSaved = GetLastError();
+    KSIZE       cbBuf      = cwcSrc + (cwcSrc >> 1) + 1;
+    char       *pszBuf     = (char *)kHlpAlloc(cbBuf);
+    if (pszBuf)
+    {
+        if (cwcSrc > 0)
+        {
+            int cchRet = WideCharToMultiByte(CP_ACP, 0, pwcSrc, (int)cwcSrc, pszBuf, (int)cbBuf - 1, NULL, NULL);
+            if (cchRet > 0)
+            {
+                kHlpAssert(cchRet < (KSSIZE)cbBuf);
+                pszBuf[cchRet] = '\0';
+            }
+            else
+            {
+                kHlpFree(pszBuf);
+
+                /* Figure the length and allocate the right buffer size. */
+                SetLastError(NO_ERROR);
+                cchRet = WideCharToMultiByte(CP_ACP, 0, pwcSrc, (int)cwcSrc, pszBuf, 0, NULL, NULL);
+                if (cchRet)
+                {
+                    cbBuf = cchRet + 2;
+                    pszBuf = (char *)kHlpAlloc(cbBuf);
+                    if (pszBuf)
+                    {
+                        SetLastError(NO_ERROR);
+                        cchRet = WideCharToMultiByte(CP_ACP, 0, pwcSrc, (int)cwcSrc, pszBuf, (int)cbBuf - 1, NULL, NULL);
+                        if (cchRet)
+                        {
+                            kHlpAssert(cchRet < (KSSIZE)cbBuf);
+                            pszBuf[cchRet] = '\0';
+                        }
+                        else
+                        {
+                            kwErrPrintf("WideCharToMultiByte(,,%*.*ls,,) -> dwErr=%d\n", cwcSrc, cwcSrc, pwcSrc, GetLastError());
+                            kHlpFree(pszBuf);
+                            pszBuf = NULL;
+                        }
+                    }
+                }
+                else
+                {
+                    kwErrPrintf("WideCharToMultiByte(,,%*.*ls,,NULL,0) -> dwErr=%d\n", cwcSrc, cwcSrc, pwcSrc, GetLastError());
+                    pszBuf = NULL;
+                }
+            }
+        }
+        else
+            pszBuf[0] = '\0';
+    }
+    SetLastError(dwErrSaved);
+    return pszBuf;
+}
+
+
+
+/** UTF-16 string length.  */
+static KSIZE kwUtf16Len(wchar_t const *pwsz)
+{
+    KSIZE cwc = 0;
+    while (*pwsz != '\0')
+        cwc++, pwsz++;
+    return cwc;
+}
+
+/**
+ * Copy out the UTF-16 string following the convension of GetModuleFileName
+ */
+static DWORD kwUtf16CopyStyle1(wchar_t const *pwszSrc, wchar_t *pwszDst, KSIZE cwcDst)
+{
+    KSIZE cwcSrc = kwUtf16Len(pwszSrc);
+    if (cwcSrc + 1 <= cwcDst)
+    {
+        kHlpMemCopy(pwszDst, pwszSrc, (cwcSrc + 1) * sizeof(wchar_t));
+        return (DWORD)cwcSrc;
+    }
+    if (cwcDst > 0)
+    {
+        KSIZE cwcDstTmp = cwcDst - 1;
+        pwszDst[cwcDstTmp] = '\0';
+        if (cwcDstTmp > 0)
+            kHlpMemCopy(pwszDst, pwszSrc, cwcDstTmp);
+    }
+    SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    return (DWORD)cwcDst;
+}
+
+
+/**
+ * Copy out the ANSI string following the convension of GetModuleFileName
+ */
+static DWORD kwStrCopyStyle1(char const *pszSrc, char *pszDst, KSIZE cbDst)
+{
+    KSIZE cchSrc = kHlpStrLen(pszSrc);
+    if (cchSrc + 1 <= cbDst)
+    {
+        kHlpMemCopy(pszDst, pszSrc, cchSrc + 1);
+        return (DWORD)cchSrc;
+    }
+    if (cbDst > 0)
+    {
+        KSIZE cbDstTmp = cbDst - 1;
+        pszDst[cbDstTmp] = '\0';
+        if (cbDstTmp > 0)
+            kHlpMemCopy(pszDst, pszSrc, cbDstTmp);
+    }
+    SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    return (DWORD)cbDst;
+}
+
+
+/**
+ * Normalizes the path so we get a consistent hash.
+ *
+ * @returns status code.
+ * @param   pszPath             The path.
+ * @param   pszNormPath         The output buffer.
+ * @param   cbNormPath          The size of the output buffer.
+ */
+static int kwPathNormalize(const char *pszPath, char *pszNormPath, KSIZE cbNormPath)
+{
+    KFSLOOKUPERROR enmError;
+    PKFSOBJ pFsObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError);
+    if (pFsObj)
+    {
+        KBOOL fRc;
+        fRc = kFsCacheObjGetFullPathA(pFsObj, pszNormPath, cbNormPath, '\\');
+        kFsCacheObjRelease(g_pFsCache, pFsObj);
+        if (fRc)
+            return 0;
+        return KERR_BUFFER_OVERFLOW;
+    }
+    return KERR_FILE_NOT_FOUND;
+}
+
+
+/**
+ * Get the pointer to the filename part of the path.
+ *
+ * @returns Pointer to where the filename starts within the string pointed to by pszFilename.
+ * @returns Pointer to the terminator char if no filename.
+ * @param   pszPath     The path to parse.
+ */
+static wchar_t *kwPathGetFilenameW(const wchar_t *pwszPath)
+{
+    const wchar_t *pwszLast = NULL;
+    for (;;)
+    {
+        wchar_t wc = *pwszPath;
+#if K_OS == K_OS_OS2 || K_OS == K_OS_WINDOWS
+        if (wc == '/' || wc == '\\' || wc == ':')
+        {
+            while ((wc = *++pwszPath) == '/' || wc == '\\' || wc == ':')
+                /* nothing */;
+            pwszLast = pwszPath;
+        }
+#else
+        if (wc == '/')
+        {
+            while ((wc = *++pszFilename) == '/')
+                /* betsuni */;
+            pwszLast = pwszPath;
+        }
+#endif
+        if (!wc)
+            return (wchar_t *)(pwszLast ? pwszLast : pwszPath);
+        pwszPath++;
+    }
+}
+
+
+
+/**
+ * Retains a new reference to the given module
+ * @returns pMod
+ * @param   pMod                The module to retain.
+ */
+static PKWMODULE kwLdrModuleRetain(PKWMODULE pMod)
+{
+    kHlpAssert(pMod->cRefs > 0);
+    kHlpAssert(pMod->cRefs < 64);
+    pMod->cRefs++;
+    return pMod;
+}
+
+
+/**
+ * Releases a module reference.
+ *
+ * @param   pMod                The module to release.
+ */
+static void kwLdrModuleRelease(PKWMODULE pMod)
+{
+    if (--pMod->cRefs == 0)
+    {
+        /* Unlink it. */
+        if (!pMod->fExe)
+        {
+            PKWMODULE pPrev = NULL;
+            unsigned  idx   = pMod->uHashPath % K_ELEMENTS(g_apModules);
+            if (g_apModules[idx] == pMod)
+                g_apModules[idx] = pMod->pNext;
+            else
+            {
+                PKWMODULE pPrev = g_apModules[idx];
+                kHlpAssert(pPrev != NULL);
+                while (pPrev->pNext != pMod)
+                {
+                    pPrev = pPrev->pNext;
+                    kHlpAssert(pPrev != NULL);
+                }
+                pPrev->pNext = pMod->pNext;
+            }
+        }
+
+        /* Release import modules. */
+        if (!pMod->fNative)
+        {
+            KSIZE idx = pMod->u.Manual.cImpMods;
+            while (idx-- > 0)
+                if (pMod->u.Manual.apImpMods[idx])
+                {
+                    kwLdrModuleRelease(pMod->u.Manual.apImpMods[idx]);
+                    pMod->u.Manual.apImpMods[idx] = NULL;
+                }
+        }
+
+        /* Free our resources. */
+        kLdrModClose(pMod->pLdrMod);
+        pMod->pLdrMod = NULL;
+
+        if (!pMod->fNative)
+        {
+            kHlpPageFree(pMod->u.Manual.pvCopy, pMod->cbImage);
+            kHlpPageFree(pMod->u.Manual.pvLoad, pMod->cbImage);
+        }
+
+        kHlpFree(pMod);
+    }
+    else
+        kHlpAssert(pMod->cRefs < 64);
+}
+
+
+/**
+ * Links the module into the module hash table.
+ *
+ * @returns pMod
+ * @param   pMod                The module to link.
+ */
+static PKWMODULE kwLdrModuleLink(PKWMODULE pMod)
+{
+    unsigned idx = pMod->uHashPath % K_ELEMENTS(g_apModules);
+    pMod->pNext = g_apModules[idx];
+    g_apModules[idx] = pMod;
+    return pMod;
+}
+
+
+/**
+ * Replaces imports for this module according to g_aSandboxNativeReplacements.
+ *
+ * @param   pMod                The natively loaded module to process.
+ */
+static void kwLdrModuleDoNativeImportReplacements(PKWMODULE pMod)
+{
+    KSIZE const                 cbImage = (KSIZE)kLdrModSize(pMod->pLdrMod);
+    KU8 const * const           pbImage = (KU8 const *)pMod->hOurMod;
+    IMAGE_DOS_HEADER const     *pMzHdr  = (IMAGE_DOS_HEADER const *)pbImage;
+    IMAGE_NT_HEADERS const     *pNtHdrs;
+    IMAGE_DATA_DIRECTORY const *pDirEnt;
+
+    kHlpAssert(pMod->fNative);
+
+    /*
+     * Locate the export descriptors.
+     */
+    /* MZ header. */
+    if (pMzHdr->e_magic == IMAGE_DOS_SIGNATURE)
+    {
+        kHlpAssertReturnVoid((KU32)pMzHdr->e_lfanew <= cbImage - sizeof(*pNtHdrs));
+        pNtHdrs = (IMAGE_NT_HEADERS const *)&pbImage[pMzHdr->e_lfanew];
+    }
+    else
+        pNtHdrs = (IMAGE_NT_HEADERS const *)pbImage;
+
+    /* Check PE header. */
+    kHlpAssertReturnVoid(pNtHdrs->Signature == IMAGE_NT_SIGNATURE);
+    kHlpAssertReturnVoid(pNtHdrs->FileHeader.SizeOfOptionalHeader == sizeof(pNtHdrs->OptionalHeader));
+
+    /* Locate the import descriptor array. */
+    pDirEnt = (IMAGE_DATA_DIRECTORY const *)&pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+    if (   pDirEnt->Size > 0
+        && pDirEnt->VirtualAddress != 0)
+    {
+        const IMAGE_IMPORT_DESCRIPTOR  *pImpDesc    = (const IMAGE_IMPORT_DESCRIPTOR *)&pbImage[pDirEnt->VirtualAddress];
+        KU32                            cLeft       = pDirEnt->Size / sizeof(*pImpDesc);
+        MEMORY_BASIC_INFORMATION        ProtInfo    = { NULL, NULL, 0, 0, 0, 0, 0 };
+        KU8                            *pbProtRange = NULL;
+        SIZE_T                          cbProtRange = 0;
+        DWORD                           fOldProt    = 0;
+        KU32 const                      cbPage      = 0x1000;
+        BOOL                            fRc;
+
+
+        kHlpAssertReturnVoid(pDirEnt->VirtualAddress < cbImage);
+        kHlpAssertReturnVoid(pDirEnt->Size < cbImage);
+        kHlpAssertReturnVoid(pDirEnt->VirtualAddress + pDirEnt->Size <= cbImage);
+
+        /*
+         * Walk the import descriptor array.
+         * Note! This only works if there's a backup thunk array, otherwise we cannot get at the name.
+         */
+        while (   cLeft-- > 0
+               && pImpDesc->Name > 0
+               && pImpDesc->FirstThunk > 0)
+        {
+            KU32                iThunk;
+            const char * const  pszImport   = (const char *)&pbImage[pImpDesc->Name];
+            PIMAGE_THUNK_DATA   paThunks    = (PIMAGE_THUNK_DATA)&pbImage[pImpDesc->FirstThunk];
+            PIMAGE_THUNK_DATA   paOrgThunks = (PIMAGE_THUNK_DATA)&pbImage[pImpDesc->OriginalFirstThunk];
+            kHlpAssertReturnVoid(pImpDesc->Name < cbImage);
+            kHlpAssertReturnVoid(pImpDesc->FirstThunk < cbImage);
+            kHlpAssertReturnVoid(pImpDesc->OriginalFirstThunk < cbImage);
+            kHlpAssertReturnVoid(pImpDesc->OriginalFirstThunk != pImpDesc->FirstThunk);
+            kHlpAssertReturnVoid(pImpDesc->OriginalFirstThunk);
+
+            /* Iterate the thunks. */
+            for (iThunk = 0; paOrgThunks[iThunk].u1.Ordinal != 0; iThunk++)
+            {
+                KUPTR const off = paOrgThunks[iThunk].u1.Function;
+                kHlpAssertReturnVoid(off < cbImage);
+                if (!IMAGE_SNAP_BY_ORDINAL(off))
+                {
+                    IMAGE_IMPORT_BY_NAME const *pName     = (IMAGE_IMPORT_BY_NAME const *)&pbImage[off];
+                    KSIZE const                 cchSymbol = kHlpStrLen(pName->Name);
+                    KU32                        i         = g_cSandboxNativeReplacements;
+                    while (i-- > 0)
+                        if (   g_aSandboxNativeReplacements[i].cchFunction == cchSymbol
+                            && kHlpMemComp(g_aSandboxNativeReplacements[i].pszFunction, pName->Name, cchSymbol) == 0)
+                        {
+                            if (   !g_aSandboxNativeReplacements[i].pszModule
+                                || kHlpStrICompAscii(g_aSandboxNativeReplacements[i].pszModule, pszImport) == 0)
+                            {
+                                KW_LOG(("%s: replacing %s!%s\n", pMod->pLdrMod->pszName, pszImport, pName->Name));
+
+                                /* The .rdata section is normally read-only, so we need to make it writable first. */
+                                if ((KUPTR)&paThunks[iThunk] - (KUPTR)pbProtRange >= cbPage)
+                                {
+                                    /* Restore previous .rdata page. */
+                                    if (fOldProt)
+                                    {
+                                        fRc = VirtualProtect(pbProtRange, cbProtRange, fOldProt, NULL /*pfOldProt*/);
+                                        kHlpAssert(fRc);
+                                        fOldProt = 0;
+                                    }
+
+                                    /* Query attributes for the current .rdata page. */
+                                    pbProtRange = (KU8 *)((KUPTR)&paThunks[iThunk] & ~(KUPTR)(cbPage - 1));
+                                    cbProtRange = VirtualQuery(pbProtRange, &ProtInfo, sizeof(ProtInfo));
+                                    kHlpAssert(cbProtRange);
+                                    if (cbProtRange)
+                                    {
+                                        switch (ProtInfo.Protect)
+                                        {
+                                            case PAGE_READWRITE:
+                                            case PAGE_WRITECOPY:
+                                            case PAGE_EXECUTE_READWRITE:
+                                            case PAGE_EXECUTE_WRITECOPY:
+                                                /* Already writable, nothing to do. */
+                                                break;
+
+                                            default:
+                                                kHlpAssertMsgFailed(("%#x\n", ProtInfo.Protect));
+                                            case PAGE_READONLY:
+                                                cbProtRange = cbPage;
+                                                fRc = VirtualProtect(pbProtRange, cbProtRange, PAGE_READWRITE, &fOldProt);
+                                                break;
+
+                                            case PAGE_EXECUTE:
+                                            case PAGE_EXECUTE_READ:
+                                                cbProtRange = cbPage;
+                                                fRc = VirtualProtect(pbProtRange, cbProtRange, PAGE_EXECUTE_READWRITE, &fOldProt);
+                                                break;
+                                        }
+                                        kHlpAssertStmt(fRc, fOldProt = 0);
+                                    }
+                                }
+
+                                paThunks[iThunk].u1.AddressOfData = g_aSandboxNativeReplacements[i].pfnReplacement;
+                                break;
+                            }
+                        }
+                }
+            }
+
+
+            /* Next import descriptor. */
+            pImpDesc++;
+        }
+
+
+        if (fOldProt)
+        {
+            DWORD fIgnore = 0;
+            fRc = VirtualProtect(pbProtRange, cbProtRange, fOldProt, &fIgnore);
+            kHlpAssertMsg(fRc, ("%u\n", GetLastError())); K_NOREF(fRc);
+        }
+    }
+
+}
+
+
+/**
+ * Creates a module from a native kLdr module handle.
+ *
+ * @returns Module w/ 1 reference on success, NULL on failure.
+ * @param   pLdrMod             The native kLdr module.
+ * @param   pszPath             The normalized path to the module.
+ * @param   cbPath              The module path length with terminator.
+ * @param   uHashPath           The module path hash.
+ * @param   fDoReplacements     Whether to do import replacements on this
+ *                              module.
+ */
+static PKWMODULE kwLdrModuleCreateForNativekLdrModule(PKLDRMOD pLdrMod, const char *pszPath, KSIZE cbPath, KU32 uHashPath,
+                                                      KBOOL fDoReplacements)
+{
+    /*
+     * Create the entry.
+     */
+    PKWMODULE pMod   = (PKWMODULE)kHlpAllocZ(sizeof(*pMod) + cbPath + cbPath * 2 * sizeof(wchar_t));
+    if (pMod)
+    {
+        pMod->pwszPath      = (wchar_t *)(pMod + 1);
+        kwStrToUtf16(pszPath, (wchar_t *)pMod->pwszPath, cbPath * 2);
+        pMod->pszPath       = (char *)kHlpMemCopy((char *)&pMod->pwszPath[cbPath * 2], pszPath, cbPath);
+        pMod->uHashPath     = uHashPath;
+        pMod->cRefs         = 1;
+        pMod->offFilename   = (KU16)(kHlpGetFilename(pszPath) - pszPath);
+        pMod->fExe          = K_FALSE;
+        pMod->fNative       = K_TRUE;
+        pMod->pLdrMod       = pLdrMod;
+        pMod->hOurMod       = (HMODULE)(KUPTR)pLdrMod->aSegments[0].MapAddress;
+        pMod->cbImage       = (KSIZE)kLdrModSize(pLdrMod);
+
+        if (fDoReplacements)
+        {
+            DWORD const dwSavedErr = GetLastError();
+            kwLdrModuleDoNativeImportReplacements(pMod);
+            SetLastError(dwSavedErr);
+        }
+
+        KW_LOG(("New module: %p LB %#010x %s (native)\n",
+                (KUPTR)pMod->pLdrMod->aSegments[0].MapAddress, kLdrModSize(pMod->pLdrMod), pMod->pszPath));
+        return kwLdrModuleLink(pMod);
+    }
+    return NULL;
+}
+
+
+
+/**
+ * Creates a module using the native loader.
+ *
+ * @returns Module w/ 1 reference on success, NULL on failure.
+ * @param   pszPath             The normalized path to the module.
+ * @param   uHashPath           The module path hash.
+ * @param   fDoReplacements     Whether to do import replacements on this
+ *                              module.
+ */
+static PKWMODULE kwLdrModuleCreateNative(const char *pszPath, KU32 uHashPath, KBOOL fDoReplacements)
+{
+    /*
+     * Open the module and check the type.
+     */
+    PKLDRMOD pLdrMod;
+    int rc = kLdrModOpenNative(pszPath, &pLdrMod);
+    if (rc == 0)
+    {
+        PKWMODULE pMod = kwLdrModuleCreateForNativekLdrModule(pLdrMod, pszPath, kHlpStrLen(pszPath) + 1,
+                                                              uHashPath, fDoReplacements);
+        if (pMod)
+            return pMod;
+        kLdrModClose(pLdrMod);
+    }
+    return NULL;
+}
+
+
+/**
+ * Creates a module using the our own loader.
+ *
+ * @returns Module w/ 1 reference on success, NULL on failure.
+ * @param   pszPath             The normalized path to the module.
+ * @param   uHashPath           The module path hash.
+ * @param   fExe                K_TRUE if this is an executable image, K_FALSE
+ *                              if not.  Executable images does not get entered
+ *                              into the global module table.
+ * @param   pExeMod             The executable module of the process (for
+ *                              resolving imports).  NULL if fExe is set.
+ */
+static PKWMODULE kwLdrModuleCreateNonNative(const char *pszPath, KU32 uHashPath, KBOOL fExe, PKWMODULE pExeMod)
+{
+    /*
+     * Open the module and check the type.
+     */
+    PKLDRMOD pLdrMod;
+    int rc = kLdrModOpen(pszPath, 0 /*fFlags*/, (KCPUARCH)K_ARCH, &pLdrMod);
+    if (rc == 0)
+    {
+        switch (pLdrMod->enmType)
+        {
+            case KLDRTYPE_EXECUTABLE_FIXED:
+            case KLDRTYPE_EXECUTABLE_RELOCATABLE:
+            case KLDRTYPE_EXECUTABLE_PIC:
+                if (!fExe)
+                    rc = KERR_GENERAL_FAILURE;
+                break;
+
+            case KLDRTYPE_SHARED_LIBRARY_RELOCATABLE:
+            case KLDRTYPE_SHARED_LIBRARY_PIC:
+            case KLDRTYPE_SHARED_LIBRARY_FIXED:
+                if (fExe)
+                    rc = KERR_GENERAL_FAILURE;
+                break;
+
+            default:
+                rc = KERR_GENERAL_FAILURE;
+                break;
+        }
+        if (rc == 0)
+        {
+            KI32 cImports = kLdrModNumberOfImports(pLdrMod, NULL /*pvBits*/);
+            if (cImports >= 0)
+            {
+                /*
+                 * Create the entry.
+                 */
+                KSIZE     cbPath = kHlpStrLen(pszPath) + 1;
+                PKWMODULE pMod   = (PKWMODULE)kHlpAllocZ(sizeof(*pMod)
+                                                         + sizeof(pMod) * cImports
+                                                         + cbPath
+                                                         + cbPath * 2 * sizeof(wchar_t));
+                if (pMod)
+                {
+                    KBOOL fFixed;
+
+                    pMod->cRefs         = 1;
+                    pMod->offFilename   = (KU16)(kHlpGetFilename(pszPath) - pszPath);
+                    pMod->uHashPath     = uHashPath;
+                    pMod->fExe          = fExe;
+                    pMod->fNative       = K_FALSE;
+                    pMod->pLdrMod       = pLdrMod;
+                    pMod->u.Manual.cImpMods = (KU32)cImports;
+                    pMod->u.Manual.fUseLdBuf = K_FALSE;
+#if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_AMD64)
+                    pMod->u.Manual.fRegisteredFunctionTable = K_FALSE;
+#endif
+                    pMod->pszPath       = (char *)kHlpMemCopy(&pMod->u.Manual.apImpMods[cImports + 1], pszPath, cbPath);
+                    pMod->pwszPath      = (wchar_t *)(pMod->pszPath + cbPath + (cbPath & 1));
+                    kwStrToUtf16(pMod->pszPath, (wchar_t *)pMod->pwszPath, cbPath * 2);
+
+                    /*
+                     * Figure out where to load it and get memory there.
+                     */
+                    fFixed = pLdrMod->enmType == KLDRTYPE_EXECUTABLE_FIXED
+                          || pLdrMod->enmType == KLDRTYPE_SHARED_LIBRARY_FIXED;
+                    pMod->u.Manual.pvLoad = fFixed ? (void *)(KUPTR)pLdrMod->aSegments[0].LinkAddress : NULL;
+                    pMod->cbImage = (KSIZE)kLdrModSize(pLdrMod);
+                    if (   !fFixed
+                        || pLdrMod->enmType != KLDRTYPE_EXECUTABLE_FIXED /* only allow fixed executables */
+                        || (KUPTR)pMod->u.Manual.pvLoad - (KUPTR)g_abDefLdBuf >= sizeof(g_abDefLdBuf)
+                        || sizeof(g_abDefLdBuf) - (KUPTR)pMod->u.Manual.pvLoad - (KUPTR)g_abDefLdBuf < pMod->cbImage)
+                        rc = kHlpPageAlloc(&pMod->u.Manual.pvLoad, pMod->cbImage, KPROT_EXECUTE_READWRITE, fFixed);
+                    else
+                        pMod->u.Manual.fUseLdBuf = K_TRUE;
+                    if (rc == 0)
+                    {
+                        rc = kHlpPageAlloc(&pMod->u.Manual.pvCopy, pMod->cbImage, KPROT_READWRITE, K_FALSE);
+                        if (rc == 0)
+                        {
+
+                            KI32 iImp;
+
+                            /*
+                             * Link the module (unless it's an executable image) and process the imports.
+                             */
+                            pMod->hOurMod = (HMODULE)pMod->u.Manual.pvLoad;
+                            if (!fExe)
+                                kwLdrModuleLink(pMod);
+                            KW_LOG(("New module: %p LB %#010x %s (kLdr)\n",
+                                    pMod->u.Manual.pvLoad, pMod->cbImage, pMod->pszPath));
+                            kwDebuggerPrintf("TODO: .reload /f %s=%p\n", pMod->pszPath, pMod->u.Manual.pvLoad);
+
+                            for (iImp = 0; iImp < cImports; iImp++)
+                            {
+                                char szName[1024];
+                                rc = kLdrModGetImport(pMod->pLdrMod, NULL /*pvBits*/, iImp, szName, sizeof(szName));
+                                if (rc == 0)
+                                {
+                                    rc = kwLdrModuleResolveAndLookup(szName, pExeMod, pMod, &pMod->u.Manual.apImpMods[iImp]);
+                                    if (rc == 0)
+                                        continue;
+                                }
+                                break;
+                            }
+
+                            if (rc == 0)
+                            {
+                                rc = kLdrModGetBits(pLdrMod, pMod->u.Manual.pvCopy, (KUPTR)pMod->u.Manual.pvLoad,
+                                                    kwLdrModuleGetImportCallback, pMod);
+                                if (rc == 0)
+                                {
+#if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_AMD64)
+                                    /*
+                                     * Find the function table.  No validation here because the
+                                     * loader did that already, right...
+                                     */
+                                    KU8                        *pbImg = (KU8 *)pMod->u.Manual.pvCopy;
+                                    IMAGE_NT_HEADERS const     *pNtHdrs;
+                                    IMAGE_DATA_DIRECTORY const *pXcptDir;
+                                    if (((PIMAGE_DOS_HEADER)pbImg)->e_magic == IMAGE_DOS_SIGNATURE)
+                                        pNtHdrs = (PIMAGE_NT_HEADERS)&pbImg[((PIMAGE_DOS_HEADER)pbImg)->e_lfanew];
+                                    else
+                                        pNtHdrs = (PIMAGE_NT_HEADERS)pbImg;
+                                    pXcptDir = &pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
+                                    kHlpAssert(pNtHdrs->Signature == IMAGE_NT_SIGNATURE);
+                                    if (pXcptDir->Size > 0)
+                                    {
+                                        pMod->u.Manual.cFunctions  = pXcptDir->Size / sizeof(pMod->u.Manual.paFunctions[0]);
+                                        kHlpAssert(   pMod->u.Manual.cFunctions * sizeof(pMod->u.Manual.paFunctions[0])
+                                                   == pXcptDir->Size);
+                                        pMod->u.Manual.paFunctions = (PRUNTIME_FUNCTION)&pbImg[pXcptDir->VirtualAddress];
+                                    }
+                                    else
+                                    {
+                                        pMod->u.Manual.cFunctions  = 0;
+                                        pMod->u.Manual.paFunctions = NULL;
+                                    }
+#endif
+
+                                    /*
+                                     * Final finish.
+                                     */
+                                    pMod->u.Manual.pvBits = pMod->u.Manual.pvCopy;
+                                    pMod->u.Manual.enmState = KWMODSTATE_NEEDS_BITS;
+                                    return pMod;
+                                }
+                            }
+
+                            kwLdrModuleRelease(pMod);
+                            return NULL;
+                        }
+
+                        kHlpPageFree(pMod->u.Manual.pvLoad, pMod->cbImage);
+                        kwErrPrintf("Failed to allocate %#x bytes\n", pMod->cbImage);
+                    }
+                    else if (fFixed)
+                        kwErrPrintf("Failed to allocate %#x bytes at %p\n",
+                                    pMod->cbImage, (void *)(KUPTR)pLdrMod->aSegments[0].LinkAddress);
+                    else
+                        kwErrPrintf("Failed to allocate %#x bytes\n", pMod->cbImage);
+                }
+            }
+        }
+        kLdrModClose(pLdrMod);
+    }
+    else
+        kwErrPrintf("kLdrOpen failed with %#x (%d) for %s\n", rc, rc, pszPath);
+    return NULL;
+}
+
+
+/** Implements FNKLDRMODGETIMPORT, used by kwLdrModuleCreate. */
+static int kwLdrModuleGetImportCallback(PKLDRMOD pMod, KU32 iImport, KU32 iSymbol, const char *pchSymbol, KSIZE cchSymbol,
+                                        const char *pszVersion, PKLDRADDR puValue, KU32 *pfKind, void *pvUser)
+{
+    PKWMODULE pCurMod = (PKWMODULE)pvUser;
+    PKWMODULE pImpMod = pCurMod->u.Manual.apImpMods[iImport];
+    int rc;
+    K_NOREF(pMod);
+
+    if (pImpMod->fNative)
+        rc = kLdrModQuerySymbol(pImpMod->pLdrMod, NULL /*pvBits*/, KLDRMOD_BASEADDRESS_MAP,
+                                iSymbol, pchSymbol, cchSymbol, pszVersion,
+                                NULL /*pfnGetForwarder*/, NULL /*pvUSer*/,
+                                puValue, pfKind);
+    else
+        rc = kLdrModQuerySymbol(pImpMod->pLdrMod, pImpMod->u.Manual.pvBits, (KUPTR)pImpMod->u.Manual.pvLoad,
+                                iSymbol, pchSymbol, cchSymbol, pszVersion,
+                                NULL /*pfnGetForwarder*/, NULL /*pvUSer*/,
+                                puValue, pfKind);
+    if (rc == 0)
+    {
+        KU32 i = g_cSandboxReplacements;
+        while (i-- > 0)
+            if (   g_aSandboxReplacements[i].cchFunction == cchSymbol
+                && kHlpMemComp(g_aSandboxReplacements[i].pszFunction, pchSymbol, cchSymbol) == 0)
+            {
+                if (   !g_aSandboxReplacements[i].pszModule
+                    || kHlpStrICompAscii(g_aSandboxReplacements[i].pszModule, &pImpMod->pszPath[pImpMod->offFilename]) == 0)
+                {
+                    KW_LOG(("replacing %s!%s\n", &pImpMod->pszPath[pImpMod->offFilename], g_aSandboxReplacements[i].pszFunction));
+                    *puValue = g_aSandboxReplacements[i].pfnReplacement;
+                    break;
+                }
+            }
+    }
+
+    //printf("iImport=%u (%s) %*.*s rc=%d\n", iImport, &pImpMod->pszPath[pImpMod->offFilename], cchSymbol, cchSymbol, pchSymbol, rc);
+    return rc;
+
+}
+
+
+/**
+ * Gets the main entrypoint for a module.
+ *
+ * @returns 0 on success, KERR on failure
+ * @param   pMod                The module.
+ * @param   puAddrMain          Where to return the address.
+ */
+static int kwLdrModuleQueryMainEntrypoint(PKWMODULE pMod, KUPTR *puAddrMain)
+{
+    KLDRADDR uLdrAddrMain;
+    int rc = kLdrModQueryMainEntrypoint(pMod->pLdrMod,  pMod->u.Manual.pvBits, (KUPTR)pMod->u.Manual.pvLoad, &uLdrAddrMain);
+    if (rc == 0)
+    {
+        *puAddrMain = (KUPTR)uLdrAddrMain;
+        return 0;
+    }
+    return rc;
+}
+
+
+/**
+ * Whether to apply g_aSandboxNativeReplacements to the imports of this module.
+ *
+ * @returns K_TRUE/K_FALSE.
+ * @param   pszFilename         The filename (no path).
+ * @param   enmLocation         The location.
+ */
+static KBOOL kwLdrModuleShouldDoNativeReplacements(const char *pszFilename, KWLOCATION enmLocation)
+{
+    if (enmLocation != KWLOCATION_SYSTEM32)
+        return K_TRUE;
+    return kHlpStrNICompAscii(pszFilename, TUPLE("msvc"))   == 0
+        || kHlpStrNICompAscii(pszFilename, TUPLE("msdis"))  == 0
+        || kHlpStrNICompAscii(pszFilename, TUPLE("mspdb"))  == 0;
+}
+
+
+/**
+ * Whether we can load this DLL natively or not.
+ *
+ * @returns K_TRUE/K_FALSE.
+ * @param   pszFilename         The filename (no path).
+ * @param   enmLocation         The location.
+ */
+static KBOOL kwLdrModuleCanLoadNatively(const char *pszFilename, KWLOCATION enmLocation)
+{
+    if (enmLocation == KWLOCATION_SYSTEM32)
+        return K_TRUE;
+    if (enmLocation == KWLOCATION_UNKNOWN_NATIVE)
+        return K_TRUE;
+    return kHlpStrNICompAscii(pszFilename, TUPLE("msvc"))   == 0
+        || kHlpStrNICompAscii(pszFilename, TUPLE("msdis"))  == 0
+        || kHlpStrNICompAscii(pszFilename, TUPLE("mspdb"))  == 0;
+}
+
+
+/**
+ * Check if the path leads to a regular file (that exists).
+ *
+ * @returns K_TRUE / K_FALSE
+ * @param   pszPath             Path to the file to check out.
+ */
+static KBOOL kwLdrModuleIsRegularFile(const char *pszPath)
+{
+    /* For stuff with .DLL extensions, we can use the GetFileAttribute cache to speed this up! */
+    KSIZE cchPath = kHlpStrLen(pszPath);
+    if (   cchPath > 3
+        && pszPath[cchPath - 4] == '.'
+        && (pszPath[cchPath - 3] == 'd' || pszPath[cchPath - 3] == 'D')
+        && (pszPath[cchPath - 2] == 'l' || pszPath[cchPath - 2] == 'L')
+        && (pszPath[cchPath - 1] == 'l' || pszPath[cchPath - 1] == 'L') )
+    {
+        KFSLOOKUPERROR enmError;
+        PKFSOBJ pFsObj = kFsCacheLookupNoMissingA(g_pFsCache, pszPath, &enmError);
+        if (pFsObj)
+        {
+            KBOOL fRc = pFsObj->bObjType == KFSOBJ_TYPE_FILE;
+            kFsCacheObjRelease(g_pFsCache, pFsObj);
+            return fRc;
+        }
+    }
+    else
+    {
+        BirdStat_T Stat;
+        int rc = birdStatFollowLink(pszPath, &Stat);
+        if (rc == 0)
+        {
+            if (S_ISREG(Stat.st_mode))
+                return K_TRUE;
+        }
+    }
+    return K_FALSE;
+}
+
+
+/**
+ * Worker for kwLdrModuleResolveAndLookup that checks out one possibility.
+ *
+ * If the file exists, we consult the module hash table before trying to load it
+ * off the disk.
+ *
+ * @returns Pointer to module on success, NULL if not found, ~(KUPTR)0 on
+ *          failure.
+ * @param   pszPath             The name of the import module.
+ * @param   enmLocation         The location we're searching.  This is used in
+ *                              the heuristics for determining if we can use the
+ *                              native loader or need to sandbox the DLL.
+ * @param   pExe                The executable (optional).
+ */
+static PKWMODULE kwLdrModuleTryLoadDll(const char *pszPath, KWLOCATION enmLocation, PKWMODULE pExeMod)
+{
+    /*
+     * Does the file exists and is it a regular file?
+     */
+    if (kwLdrModuleIsRegularFile(pszPath))
+    {
+        /*
+         * Yes! Normalize it and look it up in the hash table.
+         */
+        char szNormPath[1024];
+        int rc = kwPathNormalize(pszPath, szNormPath, sizeof(szNormPath));
+        if (rc == 0)
+        {
+            const char *pszName;
+            KU32 const  uHashPath = kwStrHash(szNormPath);
+            unsigned    idxHash   = uHashPath % K_ELEMENTS(g_apModules);
+            PKWMODULE   pMod      = g_apModules[idxHash];
+            if (pMod)
+            {
+                do
+                {
+                    if (   pMod->uHashPath == uHashPath
+                        && kHlpStrComp(pMod->pszPath, szNormPath) == 0)
+                        return kwLdrModuleRetain(pMod);
+                    pMod = pMod->pNext;
+                } while (pMod);
+            }
+
+            /*
+             * Not in the hash table, so we have to load it from scratch.
+             */
+            pszName = kHlpGetFilename(szNormPath);
+            if (kwLdrModuleCanLoadNatively(pszName, enmLocation))
+                pMod = kwLdrModuleCreateNative(szNormPath, uHashPath,
+                                               kwLdrModuleShouldDoNativeReplacements(pszName, enmLocation));
+            else
+                pMod = kwLdrModuleCreateNonNative(szNormPath, uHashPath, K_FALSE /*fExe*/, pExeMod);
+            if (pMod)
+                return pMod;
+            return (PKWMODULE)~(KUPTR)0;
+        }
+    }
+    return NULL;
+}
+
+
+/**
+ * Gets a reference to the module by the given name.
+ *
+ * We must do the search path thing, as our hash table may multiple DLLs with
+ * the same base name due to different tools version and similar.  We'll use a
+ * modified search sequence, though.  No point in searching the current
+ * directory for instance.
+ *
+ * @returns 0 on success, KERR on failure.
+ * @param   pszName             The name of the import module.
+ * @param   pExe                The executable (optional).
+ * @param   pImporter           The module doing the importing (optional).
+ * @param   ppMod               Where to return the module pointer w/ reference.
+ */
+static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWMODULE pImporter, PKWMODULE *ppMod)
+{
+    KSIZE const cchName = kHlpStrLen(pszName);
+    char        szPath[1024];
+    char       *psz;
+    PKWMODULE   pMod = NULL;
+    KBOOL       fNeedSuffix = *kHlpGetExt(pszName) == '\0' && kHlpGetFilename(pszName) == pszName;
+    KSIZE       cchSuffix   = fNeedSuffix ? 4 : 0;
+
+
+    /* The import path. */
+    if (pMod == NULL && pImporter != NULL)
+    {
+        if (pImporter->offFilename + cchName + cchSuffix >= sizeof(szPath))
+            return KERR_BUFFER_OVERFLOW;
+
+        psz = (char *)kHlpMemPCopy(kHlpMemPCopy(szPath, pImporter->pszPath, pImporter->offFilename), pszName, cchName + 1);
+        if (fNeedSuffix)
+            kHlpMemCopy(psz - 1, ".dll", sizeof(".dll"));
+        pMod = kwLdrModuleTryLoadDll(szPath, KWLOCATION_IMPORTER_DIR, pExe);
+    }
+
+    /* Application directory first. */
+    if (pMod == NULL && pExe != NULL && pExe != pImporter)
+    {
+        if (pExe->offFilename + cchName + cchSuffix >= sizeof(szPath))
+            return KERR_BUFFER_OVERFLOW;
+        psz = (char *)kHlpMemPCopy(kHlpMemPCopy(szPath, pExe->pszPath, pExe->offFilename), pszName, cchName + 1);
+        if (fNeedSuffix)
+            kHlpMemCopy(psz - 1, ".dll", sizeof(".dll"));
+        pMod = kwLdrModuleTryLoadDll(szPath, KWLOCATION_EXE_DIR, pExe);
+    }
+
+    /* The windows directory. */
+    if (pMod == NULL)
+    {
+        UINT cchDir = GetSystemDirectoryA(szPath, sizeof(szPath));
+        if (   cchDir <= 2
+            || cchDir + 1 + cchName + cchSuffix >= sizeof(szPath))
+            return KERR_BUFFER_OVERFLOW;
+        szPath[cchDir++] = '\\';
+        psz = (char *)kHlpMemPCopy(&szPath[cchDir], pszName, cchName + 1);
+        if (fNeedSuffix)
+            kHlpMemCopy(psz - 1, ".dll", sizeof(".dll"));
+        pMod = kwLdrModuleTryLoadDll(szPath, KWLOCATION_SYSTEM32, pExe);
+    }
+
+    /* Return. */
+    if (pMod != NULL && pMod != (PKWMODULE)~(KUPTR)0)
+    {
+        *ppMod = pMod;
+        return 0;
+    }
+    *ppMod = NULL;
+    return KERR_GENERAL_FAILURE;
+}
+
+
+/**
+ * Does module initialization starting at @a pMod.
+ *
+ * This is initially used on the executable.  Later it is used by the
+ * LoadLibrary interceptor.
+ *
+ * @returns 0 on success, error on failure.
+ * @param   pMod                The module to initialize.
+ */
+static int kwLdrModuleInitTree(PKWMODULE pMod)
+{
+    int rc = 0;
+    if (!pMod->fNative)
+    {
+        /* Need to copy bits? */
+        if (pMod->u.Manual.enmState == KWMODSTATE_NEEDS_BITS)
+        {
+            if (pMod->u.Manual.fUseLdBuf)
+            {
+#if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_AMD64)
+                if (g_pModInLdBuf != NULL && g_pModInLdBuf != pMod && pMod->u.Manual.fRegisteredFunctionTable)
+                {
+                    BOOLEAN fRc = RtlDeleteFunctionTable(pMod->u.Manual.paFunctions);
+                    kHlpAssert(fRc); K_NOREF(fRc);
+                }
+#endif
+                g_pModInLdBuf = pMod;
+            }
+
+            kHlpMemCopy(pMod->u.Manual.pvLoad, pMod->u.Manual.pvCopy, pMod->cbImage);
+            pMod->u.Manual.enmState = KWMODSTATE_NEEDS_INIT;
+        }
+
+#if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_AMD64)
+        /* Need to register function table? */
+        if (   !pMod->u.Manual.fRegisteredFunctionTable
+            && pMod->u.Manual.cFunctions > 0)
+        {
+            pMod->u.Manual.fRegisteredFunctionTable = RtlAddFunctionTable(pMod->u.Manual.paFunctions,
+                                                                          pMod->u.Manual.cFunctions,
+                                                                          (KUPTR)pMod->u.Manual.pvLoad) != FALSE;
+            kHlpAssert(pMod->u.Manual.fRegisteredFunctionTable);
+        }
+#endif
+
+        if (pMod->u.Manual.enmState == KWMODSTATE_NEEDS_INIT)
+        {
+            /* Must do imports first, but mark our module as being initialized to avoid
+               endless recursion should there be a dependency loop. */
+            KSIZE iImp;
+            pMod->u.Manual.enmState = KWMODSTATE_BEING_INITED;
+
+            for (iImp = 0; iImp < pMod->u.Manual.cImpMods; iImp++)
+            {
+                rc = kwLdrModuleInitTree(pMod->u.Manual.apImpMods[iImp]);
+                if (rc != 0)
+                    return rc;
+            }
+
+            rc = kLdrModCallInit(pMod->pLdrMod, pMod->u.Manual.pvLoad, (KUPTR)pMod->u.Manual.pvLoad);
+            if (rc == 0)
+                pMod->u.Manual.enmState = KWMODSTATE_READY;
+            else
+                pMod->u.Manual.enmState = KWMODSTATE_INIT_FAILED;
+        }
+    }
+    return rc;
+}
+
+
+/**
+ * Looks up a module handle for a tool.
+ *
+ * @returns Referenced loader module on success, NULL on if not found.
+ * @param   pTool               The tool.
+ * @param   hmod                The module handle.
+ */
+static PKWMODULE kwToolLocateModuleByHandle(PKWTOOL pTool, HMODULE hmod)
+{
+    KUPTR const     uHMod = (KUPTR)hmod;
+    PKWMODULE      *papMods;
+    KU32            iEnd;
+    KU32            i;
+    PKWDYNLOAD      pDynLoad;
+
+    /* The executable. */
+    if (   hmod == NULL
+        || pTool->u.Sandboxed.pExe->hOurMod == hmod)
+        return kwLdrModuleRetain(pTool->u.Sandboxed.pExe);
+
+    /*
+     * Binary lookup using the module table.
+     */
+    papMods = pTool->u.Sandboxed.papModules;
+    iEnd    = pTool->u.Sandboxed.cModules;
+    if (iEnd)
+    {
+        KU32 iStart  = 0;
+        i = iEnd / 2;
+        for (;;)
+        {
+            KUPTR const uHModThis = (KUPTR)papMods[i]->hOurMod;
+            if (uHMod < uHModThis)
+            {
+                iEnd = i--;
+                if (iStart <= i)
+                { }
+                else
+                    break;
+            }
+            else if (uHMod != uHModThis)
+            {
+                iStart = ++i;
+                if (i < iEnd)
+                { }
+                else
+                    break;
+            }
+            else
+                return kwLdrModuleRetain(papMods[i]);
+
+            i = iStart + (iEnd - iStart) / 2;
+        }
+
+#ifndef NDEBUG
+        iStart = pTool->u.Sandboxed.cModules;
+        while (--iStart > 0)
+            kHlpAssert((KUPTR)papMods[iStart]->hOurMod != uHMod);
+        kHlpAssert(i == 0 || (KUPTR)papMods[i - 1]->hOurMod < uHMod);
+        kHlpAssert(i == pTool->u.Sandboxed.cModules || (KUPTR)papMods[i]->hOurMod > uHMod);
+#endif
+    }
+
+    /*
+     * Dynamically loaded images.
+     */
+    for (pDynLoad = pTool->u.Sandboxed.pDynLoadHead; pDynLoad != NULL; pDynLoad = pDynLoad->pNext)
+        if (pDynLoad->hmod == hmod)
+        {
+            if (pDynLoad->pMod)
+                return kwLdrModuleRetain(pDynLoad->pMod);
+            KWFS_TODO();
+            return NULL;
+        }
+
+    return NULL;
+}
+
+/**
+ * Adds the given module to the tool import table.
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param   pTool               The tool.
+ * @param   pMod                The module.
+ */
+static int kwToolAddModule(PKWTOOL pTool, PKWMODULE pMod)
+{
+    /*
+     * Binary lookup. Locating the right slot for it, return if already there.
+     */
+    KUPTR const     uHMod   = (KUPTR)pMod->hOurMod;
+    PKWMODULE      *papMods = pTool->u.Sandboxed.papModules;
+    KU32            iEnd    = pTool->u.Sandboxed.cModules;
+    KU32            i;
+    if (iEnd)
+    {
+        KU32        iStart  = 0;
+        i = iEnd / 2;
+        for (;;)
+        {
+            KUPTR const uHModThis = (KUPTR)papMods[i]->hOurMod;
+            if (uHMod < uHModThis)
+            {
+                iEnd = i;
+                if (iStart < i)
+                { }
+                else
+                    break;
+            }
+            else if (uHMod != uHModThis)
+            {
+                iStart = ++i;
+                if (i < iEnd)
+                { }
+                else
+                    break;
+            }
+            else
+            {
+                /* Already there in the table. */
+                return 0;
+            }
+
+            i = iStart + (iEnd - iStart) / 2;
+        }
+#ifndef NDEBUG
+        iStart = pTool->u.Sandboxed.cModules;
+        while (--iStart > 0)
+        {
+            kHlpAssert(papMods[iStart] != pMod);
+            kHlpAssert((KUPTR)papMods[iStart]->hOurMod != uHMod);
+        }
+        kHlpAssert(i == 0 || (KUPTR)papMods[i - 1]->hOurMod < uHMod);
+        kHlpAssert(i == pTool->u.Sandboxed.cModules || (KUPTR)papMods[i]->hOurMod > uHMod);
+#endif
+    }
+    else
+        i = 0;
+
+    /*
+     * Grow the table?
+     */
+    if ((pTool->u.Sandboxed.cModules % 16) == 0)
+    {
+        void *pvNew = kHlpRealloc(papMods, sizeof(papMods[0]) * (pTool->u.Sandboxed.cModules + 16));
+        if (!pvNew)
+            return KERR_NO_MEMORY;
+        pTool->u.Sandboxed.papModules = papMods = (PKWMODULE *)pvNew;
+    }
+
+    /* Insert it. */
+    if (i != pTool->u.Sandboxed.cModules)
+        kHlpMemMove(&papMods[i + 1], &papMods[i], (pTool->u.Sandboxed.cModules - i) * sizeof(papMods[0]));
+    papMods[i] = kwLdrModuleRetain(pMod);
+    pTool->u.Sandboxed.cModules++;
+    KW_LOG(("kwToolAddModule: %u modules after adding %p=%s\n", pTool->u.Sandboxed.cModules, uHMod, pMod->pszPath));
+    return 0;
+}
+
+
+/**
+ * Adds the given module and all its imports to the
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param   pTool               The tool.
+ * @param   pMod                The module.
+ */
+static int kwToolAddModuleAndImports(PKWTOOL pTool, PKWMODULE pMod)
+{
+    int rc = kwToolAddModule(pTool, pMod);
+    if (!pMod->fNative && rc == 0)
+    {
+        KSIZE iImp = pMod->u.Manual.cImpMods;
+        while (iImp-- > 0)
+        {
+            rc = kwToolAddModuleAndImports(pTool, pMod->u.Manual.apImpMods[iImp]);
+            if (rc == 0)
+            { }
+            else
+                break;
+        }
+    }
+    return 0;
+}
+
+
+/**
+ * Creates a tool entry and inserts it.
+ *
+ * @returns Pointer to the tool entry.  NULL on failure.
+ * @param   pToolFsObj          The file object of the tool.  The created tool
+ *                              will be associated with it.
+ *
+ *                              A reference is donated by the caller and must be
+ *                              released.
+ */
+static PKWTOOL kwToolEntryCreate(PKFSOBJ pToolFsObj)
+{
+    KSIZE   cwcPath = pToolFsObj->cwcParent + pToolFsObj->cwcName + 1;
+    KSIZE   cbPath  = pToolFsObj->cchParent + pToolFsObj->cchName + 1;
+    PKWTOOL pTool   = (PKWTOOL)kFsCacheObjAddUserData(g_pFsCache, pToolFsObj, KW_DATA_KEY_TOOL,
+                                                      sizeof(*pTool) + cwcPath * sizeof(wchar_t) + cbPath);
+    if (pTool)
+    {
+        KBOOL fRc;
+        pTool->pwszPath = (wchar_t const *)(pTool + 1);
+        fRc = kFsCacheObjGetFullPathW(pToolFsObj, (wchar_t *)pTool->pwszPath, cwcPath, '\\');
+        kHlpAssert(fRc); K_NOREF(fRc);
+
+        pTool->pszPath = (char const *)&pTool->pwszPath[cwcPath];
+        fRc = kFsCacheObjGetFullPathA(pToolFsObj, (char *)pTool->pszPath, cbPath, '\\');
+        kHlpAssert(fRc);
+
+        pTool->enmType = KWTOOLTYPE_SANDBOXED;
+        pTool->u.Sandboxed.pExe = kwLdrModuleCreateNonNative(pTool->pszPath, kwStrHash(pTool->pszPath), K_TRUE /*fExe*/, NULL);
+        if (pTool->u.Sandboxed.pExe)
+        {
+            int rc = kwLdrModuleQueryMainEntrypoint(pTool->u.Sandboxed.pExe, &pTool->u.Sandboxed.uMainAddr);
+            if (rc == 0)
+            {
+                if (kHlpStrICompAscii(pToolFsObj->pszName, "cl.exe") == 0)
+                    pTool->u.Sandboxed.enmHint = KWTOOLHINT_VISUAL_CPP_CL;
+                else
+                    pTool->u.Sandboxed.enmHint = KWTOOLHINT_NONE;
+                kwToolAddModuleAndImports(pTool, pTool->u.Sandboxed.pExe);
+            }
+            else
+            {
+                kwErrPrintf("Failed to get entrypoint for '%s': %u\n", pTool->pszPath, rc);
+                kwLdrModuleRelease(pTool->u.Sandboxed.pExe);
+                pTool->u.Sandboxed.pExe = NULL;
+                pTool->enmType = KWTOOLTYPE_EXEC;
+            }
+        }
+        else
+            pTool->enmType = KWTOOLTYPE_EXEC;
+
+        kFsCacheObjRelease(g_pFsCache, pToolFsObj);
+        return pTool;
+    }
+    kFsCacheObjRelease(g_pFsCache, pToolFsObj);
+    return NULL;
+}
+
+
+/**
+ * Looks up the given tool, creating a new tool table entry if necessary.
+ *
+ * @returns Pointer to the tool entry.  NULL on failure.
+ * @param   pszExe              The executable for the tool (not normalized).
+ */
+static PKWTOOL kwToolLookup(const char *pszExe)
+{
+    /*
+     * We associate the tools instances with the file system objects.
+     */
+    KFSLOOKUPERROR  enmError;
+    PKFSOBJ         pToolFsObj = kFsCacheLookupA(g_pFsCache, pszExe, &enmError);
+    if (pToolFsObj)
+    {
+        if (pToolFsObj->bObjType == KFSOBJ_TYPE_FILE)
+        {
+            PKWTOOL pTool = (PKWTOOL)kFsCacheObjGetUserData(g_pFsCache, pToolFsObj, KW_DATA_KEY_TOOL);
+            if (pTool)
+            {
+                kFsCacheObjRelease(g_pFsCache, pToolFsObj);
+                return pTool;
+            }
+
+            /*
+             * Need to create a new tool.
+             */
+            return kwToolEntryCreate(pToolFsObj);
+        }
+        kFsCacheObjRelease(g_pFsCache, pToolFsObj);
+    }
+    return NULL;
+}
+
+
+
+/*
+ *
+ * File system cache.
+ * File system cache.
+ * File system cache.
+ *
+ */
+
+
+
+/**
+ * Helper for getting the extension of a UTF-16 path.
+ *
+ * @returns Pointer to the extension or the terminator.
+ * @param   pwszPath        The path.
+ * @param   pcwcExt         Where to return the length of the extension.
+ */
+static wchar_t const *kwFsPathGetExtW(wchar_t const *pwszPath, KSIZE *pcwcExt)
+{
+    wchar_t const *pwszName = pwszPath;
+    wchar_t const *pwszExt  = NULL;
+    for (;;)
+    {
+        wchar_t const wc = *pwszPath++;
+        if (wc == '.')
+            pwszExt = pwszPath;
+        else if (wc == '/' || wc == '\\' || wc == ':')
+        {
+            pwszName = pwszPath;
+            pwszExt = NULL;
+        }
+        else if (wc == '\0')
+        {
+            if (pwszExt)
+            {
+                *pcwcExt = pwszPath - pwszExt - 1;
+                return pwszExt;
+            }
+            *pcwcExt = 0;
+            return pwszPath - 1;
+        }
+    }
+}
+
+
+
+/**
+ * Parses the argument string passed in as pszSrc.
+ *
+ * @returns size of the processed arguments.
+ * @param   pszSrc  Pointer to the commandline that's to be parsed.
+ * @param   pcArgs  Where to return the number of arguments.
+ * @param   argv    Pointer to argument vector to put argument pointers in. NULL allowed.
+ * @param   pchPool Pointer to memory pchPool to put the arguments into. NULL allowed.
+ *
+ * @remarks Lifted from startuphacks-win.c
+ */
+static int parse_args(const char *pszSrc, int *pcArgs, char **argv, char *pchPool)
+{
+    int   bs;
+    char  chQuote;
+    char *pfFlags;
+    int   cbArgs;
+    int   cArgs;
+
+#define PUTC(c) do { ++cbArgs; if (pchPool != NULL) *pchPool++ = (c); } while (0)
+#define PUTV    do { ++cArgs;  if (argv != NULL) *argv++ = pchPool; } while (0)
+#define WHITE(c) ((c) == ' ' || (c) == '\t')
+
+#define _ARG_DQUOTE   0x01          /* Argument quoted (")                  */
+#define _ARG_RESPONSE 0x02          /* Argument read from response file     */
+#define _ARG_WILDCARD 0x04          /* Argument expanded from wildcard      */
+#define _ARG_ENV      0x08          /* Argument from environment            */
+#define _ARG_NONZERO  0x80          /* Always set, to avoid end of string   */
+
+    cArgs  = 0;
+    cbArgs = 0;
+
+#if 0
+    /* argv[0] */
+    PUTC((char)_ARG_NONZERO);
+    PUTV;
+    for (;;)
+    {
+        PUTC(*pszSrc);
+        if (*pszSrc == 0)
+            break;
+        ++pszSrc;
+    }
+    ++pszSrc;
+#endif
+
+    for (;;)
+    {
+        while (WHITE(*pszSrc))
+            ++pszSrc;
+        if (*pszSrc == 0)
+            break;
+        pfFlags = pchPool;
+        PUTC((char)_ARG_NONZERO);
+        PUTV;
+        bs = 0; chQuote = 0;
+        for (;;)
+        {
+            if (!chQuote ? (*pszSrc == '"' /*|| *pszSrc == '\''*/) : *pszSrc == chQuote)
+            {
+                while (bs >= 2)
+                {
+                    PUTC('\\');
+                    bs -= 2;
+                }
+                if (bs & 1)
+                    PUTC(*pszSrc);
+                else
+                {
+                    chQuote = chQuote ? 0 : *pszSrc;
+                    if (pfFlags != NULL)
+                        *pfFlags |= _ARG_DQUOTE;
+                }
+                bs = 0;
+            }
+            else if (*pszSrc == '\\')
+                ++bs;
+            else
+            {
+                while (bs != 0)
+                {
+                    PUTC('\\');
+                    --bs;
+                }
+                if (*pszSrc == 0 || (WHITE(*pszSrc) && !chQuote))
+                    break;
+                PUTC(*pszSrc);
+            }
+            ++pszSrc;
+        }
+        PUTC(0);
+    }
+
+    *pcArgs = cArgs;
+    return cbArgs;
+}
+
+
+
+
+/*
+ *
+ * Process and thread related APIs.
+ * Process and thread related APIs.
+ * Process and thread related APIs.
+ *
+ */
+
+/** Common worker for ExitProcess(), exit() and friends.  */
+static void WINAPI kwSandboxDoExit(int uExitCode)
+{
+    if (g_Sandbox.idMainThread == GetCurrentThreadId())
+    {
+        PNT_TIB pTib = (PNT_TIB)NtCurrentTeb();
+
+        g_Sandbox.rcExitCode = (int)uExitCode;
+
+        /* Before we jump, restore the TIB as we're not interested in any
+           exception chain stuff installed by the sandboxed executable. */
+        *pTib = g_Sandbox.TibMainThread;
+        pTib->ExceptionList = g_Sandbox.pOutXcptListHead;
+
+        longjmp(g_Sandbox.JmpBuf, 1);
+    }
+    KWFS_TODO();
+}
+
+
+/** ExitProcess replacement.  */
+static void WINAPI kwSandbox_Kernel32_ExitProcess(UINT uExitCode)
+{
+    KW_LOG(("kwSandbox_Kernel32_ExitProcess: %u\n", uExitCode));
+    kwSandboxDoExit((int)uExitCode);
+}
+
+
+/** ExitProcess replacement.  */
+static BOOL WINAPI kwSandbox_Kernel32_TerminateProcess(HANDLE hProcess, UINT uExitCode)
+{
+    if (hProcess == GetCurrentProcess())
+        kwSandboxDoExit(uExitCode);
+    KWFS_TODO();
+    return TerminateProcess(hProcess, uExitCode);
+}
+
+
+/** Normal CRT exit(). */
+static void __cdecl kwSandbox_msvcrt_exit(int rcExitCode)
+{
+    KW_LOG(("kwSandbox_msvcrt_exit: %d\n", rcExitCode));
+    kwSandboxDoExit(rcExitCode);
+}
+
+
+/** Quick CRT _exit(). */
+static void __cdecl kwSandbox_msvcrt__exit(int rcExitCode)
+{
+    /* Quick. */
+    KW_LOG(("kwSandbox_msvcrt__exit %d\n", rcExitCode));
+    kwSandboxDoExit(rcExitCode);
+}
+
+
+/** Return to caller CRT _cexit(). */
+static void __cdecl kwSandbox_msvcrt__cexit(int rcExitCode)
+{
+    KW_LOG(("kwSandbox_msvcrt__cexit: %d\n", rcExitCode));
+    kwSandboxDoExit(rcExitCode);
+}
+
+
+/** Quick return to caller CRT _c_exit(). */
+static void __cdecl kwSandbox_msvcrt__c_exit(int rcExitCode)
+{
+    KW_LOG(("kwSandbox_msvcrt__c_exit: %d\n", rcExitCode));
+    kwSandboxDoExit(rcExitCode);
+}
+
+
+/** Runtime error and exit _amsg_exit(). */
+static void __cdecl kwSandbox_msvcrt__amsg_exit(int iMsgNo)
+{
+    KW_LOG(("\nRuntime error #%u!\n", iMsgNo));
+    kwSandboxDoExit(255);
+}
+
+
+/** CRT - terminate().  */
+static void __cdecl kwSandbox_msvcrt_terminate(void)
+{
+    KW_LOG(("\nRuntime - terminate!\n"));
+    kwSandboxDoExit(254);
+}
+
+
+/** The CRT internal __getmainargs() API. */
+static int __cdecl kwSandbox_msvcrt___getmainargs(int *pargc, char ***pargv, char ***penvp,
+                                                  int dowildcard, int const *piNewMode)
+{
+    *pargc = g_Sandbox.cArgs;
+    *pargv = g_Sandbox.papszArgs;
+    *penvp = g_Sandbox.environ;
+
+    /** @todo startinfo points at a newmode (setmode) value.   */
+    return 0;
+}
+
+
+/** The CRT internal __wgetmainargs() API. */
+static int __cdecl kwSandbox_msvcrt___wgetmainargs(int *pargc, wchar_t ***pargv, wchar_t ***penvp,
+                                                   int dowildcard, int const *piNewMode)
+{
+    *pargc = g_Sandbox.cArgs;
+    *pargv = g_Sandbox.papwszArgs;
+    *penvp = g_Sandbox.wenviron;
+
+    /** @todo startinfo points at a newmode (setmode) value.   */
+    return 0;
+}
+
+
+
+/** Kernel32 - GetCommandLineA()  */
+static LPCSTR /*LPSTR*/ WINAPI kwSandbox_Kernel32_GetCommandLineA(VOID)
+{
+    return g_Sandbox.pszCmdLine;
+}
+
+
+/** Kernel32 - GetCommandLineW()  */
+static LPCWSTR /*LPWSTR*/ WINAPI kwSandbox_Kernel32_GetCommandLineW(VOID)
+{
+    return g_Sandbox.pwszCmdLine;
+}
+
+
+/** Kernel32 - GetStartupInfoA()  */
+static VOID WINAPI kwSandbox_Kernel32_GetStartupInfoA(LPSTARTUPINFOA pStartupInfo)
+{
+    KW_LOG(("GetStartupInfoA\n"));
+    GetStartupInfoA(pStartupInfo);
+    pStartupInfo->lpReserved  = NULL;
+    pStartupInfo->lpTitle     = NULL;
+    pStartupInfo->lpReserved2 = NULL;
+    pStartupInfo->cbReserved2 = 0;
+}
+
+
+/** Kernel32 - GetStartupInfoW()  */
+static VOID WINAPI kwSandbox_Kernel32_GetStartupInfoW(LPSTARTUPINFOW pStartupInfo)
+{
+    KW_LOG(("GetStartupInfoW\n"));
+    GetStartupInfoW(pStartupInfo);
+    pStartupInfo->lpReserved  = NULL;
+    pStartupInfo->lpTitle     = NULL;
+    pStartupInfo->lpReserved2 = NULL;
+    pStartupInfo->cbReserved2 = 0;
+}
+
+
+/** CRT - __p___argc().  */
+static int * __cdecl kwSandbox_msvcrt___p___argc(void)
+{
+    return &g_Sandbox.cArgs;
+}
+
+
+/** CRT - __p___argv().  */
+static char *** __cdecl kwSandbox_msvcrt___p___argv(void)
+{
+    return &g_Sandbox.papszArgs;
+}
+
+
+/** CRT - __p___sargv().  */
+static wchar_t *** __cdecl kwSandbox_msvcrt___p___wargv(void)
+{
+    return &g_Sandbox.papwszArgs;
+}
+
+
+/** CRT - __p__acmdln().  */
+static char ** __cdecl kwSandbox_msvcrt___p__acmdln(void)
+{
+    return (char **)&g_Sandbox.pszCmdLine;
+}
+
+
+/** CRT - __p__acmdln().  */
+static wchar_t ** __cdecl kwSandbox_msvcrt___p__wcmdln(void)
+{
+    return &g_Sandbox.pwszCmdLine;
+}
+
+
+/** CRT - __p__pgmptr().  */
+static char ** __cdecl kwSandbox_msvcrt___p__pgmptr(void)
+{
+    return &g_Sandbox.pgmptr;
+}
+
+
+/** CRT - __p__wpgmptr().  */
+static wchar_t ** __cdecl kwSandbox_msvcrt___p__wpgmptr(void)
+{
+    return &g_Sandbox.wpgmptr;
+}
+
+
+/** CRT - _get_pgmptr().  */
+static errno_t __cdecl kwSandbox_msvcrt__get_pgmptr(char **ppszValue)
+{
+    *ppszValue = g_Sandbox.pgmptr;
+    return 0;
+}
+
+
+/** CRT - _get_wpgmptr().  */
+static errno_t __cdecl kwSandbox_msvcrt__get_wpgmptr(wchar_t **ppwszValue)
+{
+    *ppwszValue = g_Sandbox.wpgmptr;
+    return 0;
+}
+
+/** Just in case. */
+static void kwSandbox_msvcrt__wincmdln(void)
+{
+    KWFS_TODO();
+}
+
+
+/** Just in case. */
+static void kwSandbox_msvcrt__wwincmdln(void)
+{
+    KWFS_TODO();
+}
+
+/** CreateThread interceptor. */
+static HANDLE WINAPI kwSandbox_Kernel32_CreateThread(LPSECURITY_ATTRIBUTES pSecAttr, SIZE_T cbStack,
+                                                     PTHREAD_START_ROUTINE pfnThreadProc, PVOID pvUser,
+                                                     DWORD fFlags, PDWORD pidThread)
+{
+    KWFS_TODO();
+    return NULL;
+}
+
+
+/** _beginthread - create a new thread. */
+static uintptr_t __cdecl kwSandbox_msvcrt__beginthread(void (__cdecl *pfnThreadProc)(void *), unsigned cbStack, void *pvUser)
+{
+    KWFS_TODO();
+    return 0;
+}
+
+
+/** _beginthreadex - create a new thread. */
+static uintptr_t __cdecl kwSandbox_msvcrt__beginthreadex(void *pvSecAttr, unsigned cbStack,
+                                                         unsigned (__stdcall *pfnThreadProc)(void *), void *pvUser,
+                                                         unsigned fCreate, unsigned *pidThread)
+{
+    KWFS_TODO();
+    return 0;
+}
+
+
+/*
+ *
+ * Environment related APIs.
+ * Environment related APIs.
+ * Environment related APIs.
+ *
+ */
+
+/** Kernel32 - GetEnvironmentStringsA (Watcom uses this one). */
+static LPCH WINAPI kwSandbox_Kernel32_GetEnvironmentStringsA(void)
+{
+    char *pszzEnv;
+
+    /* Figure how space much we need first.  */
+    char *pszCur;
+    KSIZE cbNeeded = 1;
+    KSIZE iVar = 0;
+    while ((pszCur = g_Sandbox.papszEnvVars[iVar++]) != NULL)
+        cbNeeded += kHlpStrLen(pszCur) + 1;
+
+    /* Allocate it. */
+    pszzEnv = kHlpAlloc(cbNeeded);
+    if (pszzEnv)
+    {
+        char *psz = pszzEnv;
+        iVar = 0;
+        while ((pszCur = g_Sandbox.papszEnvVars[iVar++]) != NULL)
+        {
+            KSIZE cbCur = kHlpStrLen(pszCur) + 1;
+            kHlpAssert((KUPTR)(&psz[cbCur] - pszzEnv) < cbNeeded);
+            psz = (char *)kHlpMemPCopy(psz, pszCur, cbCur);
+        }
+        *psz++ = '\0';
+        kHlpAssert(psz - pszzEnv == cbNeeded);
+    }
+
+    KW_LOG(("GetEnvironmentStringsA -> %p [%u]\n", pszzEnv, cbNeeded));
+#if 0
+    fprintf(stderr, "GetEnvironmentStringsA: %p LB %#x\n", pszzEnv, cbNeeded);
+    pszCur = pszzEnv;
+    iVar = 0;
+    while (*pszCur)
+    {
+        fprintf(stderr, "  %u:%p=%s<eos>\n\n", iVar, pszCur, pszCur);
+        iVar++;
+        pszCur += kHlpStrLen(pszCur) + 1;
+    }
+    fprintf(stderr, "  %u:%p=<eos>\n\n", iVar, pszCur);
+    pszCur++;
+    fprintf(stderr, "ended at %p, after %u bytes (exepcted %u)\n", pszCur, pszCur - pszzEnv, cbNeeded);
+#endif
+    return pszzEnv;
+}
+
+
+/** Kernel32 - GetEnvironmentStrings */
+static LPCH WINAPI kwSandbox_Kernel32_GetEnvironmentStrings(void)
+{
+    KW_LOG(("GetEnvironmentStrings!\n"));
+    return kwSandbox_Kernel32_GetEnvironmentStringsA();
+}
+
+
+/** Kernel32 - GetEnvironmentStringsW */
+static LPWCH WINAPI kwSandbox_Kernel32_GetEnvironmentStringsW(void)
+{
+    wchar_t *pwszzEnv;
+
+    /* Figure how space much we need first.  */
+    wchar_t *pwszCur;
+    KSIZE    cwcNeeded = 1;
+    KSIZE    iVar = 0;
+    while ((pwszCur = g_Sandbox.papwszEnvVars[iVar++]) != NULL)
+        cwcNeeded += kwUtf16Len(pwszCur) + 1;
+
+    /* Allocate it. */
+    pwszzEnv = kHlpAlloc(cwcNeeded * sizeof(wchar_t));
+    if (pwszzEnv)
+    {
+        wchar_t *pwsz = pwszzEnv;
+        iVar = 0;
+        while ((pwszCur = g_Sandbox.papwszEnvVars[iVar++]) != NULL)
+        {
+            KSIZE cwcCur = kwUtf16Len(pwszCur) + 1;
+            kHlpAssert((KUPTR)(&pwsz[cwcCur] - pwszzEnv) < cwcNeeded);
+            pwsz = (wchar_t *)kHlpMemPCopy(pwsz, pwszCur, cwcCur * sizeof(wchar_t));
+        }
+        *pwsz++ = '\0';
+        kHlpAssert(pwsz - pwszzEnv == cwcNeeded);
+    }
+
+    KW_LOG(("GetEnvironmentStringsW -> %p [%u]\n", pwszzEnv, cwcNeeded));
+    return pwszzEnv;
+}
+
+
+/** Kernel32 - FreeEnvironmentStringsA   */
+static BOOL WINAPI kwSandbox_Kernel32_FreeEnvironmentStringsA(LPCH pszzEnv)
+{
+    KW_LOG(("FreeEnvironmentStringsA: %p -> TRUE\n", pszzEnv));
+    kHlpFree(pszzEnv);
+    return TRUE;
+}
+
+
+/** Kernel32 - FreeEnvironmentStringsW   */
+static BOOL WINAPI kwSandbox_Kernel32_FreeEnvironmentStringsW(LPWCH pwszzEnv)
+{
+    KW_LOG(("FreeEnvironmentStringsW: %p -> TRUE\n", pwszzEnv));
+    kHlpFree(pwszzEnv);
+    return TRUE;
+}
+
+
+/**
+ * Grows the environment vectors (KWSANDBOX::environ, KWSANDBOX::papszEnvVars,
+ * KWSANDBOX::wenviron, and KWSANDBOX::papwszEnvVars).
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param   pSandbox            The sandbox.
+ * @param   cMin                Minimum size, including terminator.
+ */
+static int kwSandboxGrowEnv(PKWSANDBOX pSandbox, KSIZE cMin)
+{
+    void       *pvNew;
+    KSIZE const cOld = pSandbox->cEnvVarsAllocated;
+    KSIZE       cNew = cOld + 256;
+    while (cNew < cMin)
+        cNew += 256;
+
+
+    pvNew = kHlpRealloc(pSandbox->environ, cNew * sizeof(pSandbox->environ[0]));
+    if (pvNew)
+    {
+        pSandbox->environ = (char **)pvNew;
+        pSandbox->environ[cOld] = NULL;
+
+        pvNew = kHlpRealloc(pSandbox->papszEnvVars, cNew * sizeof(pSandbox->papszEnvVars[0]));
+        if (pvNew)
+        {
+            pSandbox->papszEnvVars = (char **)pvNew;
+            pSandbox->papszEnvVars[cOld] = NULL;
+
+            pvNew = kHlpRealloc(pSandbox->wenviron, cNew * sizeof(pSandbox->wenviron[0]));
+            if (pvNew)
+            {
+                pSandbox->wenviron = (wchar_t **)pvNew;
+                pSandbox->wenviron[cOld] = NULL;
+
+                pvNew = kHlpRealloc(pSandbox->papwszEnvVars, cNew * sizeof(pSandbox->papwszEnvVars[0]));
+                if (pvNew)
+                {
+                    pSandbox->papwszEnvVars = (wchar_t **)pvNew;
+                    pSandbox->papwszEnvVars[cOld] = NULL;
+
+                    pSandbox->cEnvVarsAllocated = cNew;
+                    KW_LOG(("kwSandboxGrowEnv: cNew=%d - crt: %p / %p; shadow: %p, %p\n",
+                            cNew, pSandbox->environ, pSandbox->wenviron, pSandbox->papszEnvVars, pSandbox->papwszEnvVars));
+                    return 0;
+                }
+            }
+        }
+    }
+    kwErrPrintf("kwSandboxGrowEnv ran out of memory! cNew=%u\n", cNew);
+    return KERR_NO_MEMORY;
+}
+
+
+/**
+ * Sets an environment variable, ANSI style.
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param   pSandbox            The sandbox.
+ * @param   pchVar              The variable name.
+ * @param   cchVar              The length of the name.
+ * @param   pszValue            The value.
+ */
+static int kwSandboxDoSetEnvA(PKWSANDBOX pSandbox, const char *pchVar, KSIZE cchVar, const char *pszValue)
+{
+    /* Allocate and construct the new strings. */
+    KSIZE  cchTmp = kHlpStrLen(pszValue);
+    char  *pszNew = (char *)kHlpAlloc(cchVar + 1 + cchTmp + 1);
+    if (pszNew)
+    {
+        wchar_t *pwszNew;
+        kHlpMemCopy(pszNew, pchVar, cchVar);
+        pszNew[cchVar] = '=';
+        kHlpMemCopy(&pszNew[cchVar + 1], pszValue, cchTmp);
+        cchTmp += cchVar + 1;
+        pszNew[cchTmp] = '\0';
+
+        pwszNew = kwStrToUtf16AllocN(pszNew, cchTmp);
+        if (pwszNew)
+        {
+            /* Look it up. */
+            KSIZE   iVar = 0;
+            char   *pszEnv;
+            while ((pszEnv = pSandbox->papszEnvVars[iVar]) != NULL)
+            {
+                if (   _strnicmp(pszEnv, pchVar, cchVar) == 0
+                    && pszEnv[cchVar] == '=')
+                {
+                    KW_LOG(("kwSandboxDoSetEnvA: Replacing iVar=%d: %p='%s' and %p='%ls'\n"
+                            "                              iVar=%d: %p='%s' and %p='%ls'\n",
+                            iVar, pSandbox->papszEnvVars[iVar], pSandbox->papszEnvVars[iVar],
+                            pSandbox->papwszEnvVars[iVar], pSandbox->papwszEnvVars[iVar],
+                            iVar, pszNew, pszNew, pwszNew, pwszNew));
+
+                    kHlpFree(pSandbox->papszEnvVars[iVar]);
+                    pSandbox->papszEnvVars[iVar]  = pszNew;
+                    pSandbox->environ[iVar]       = pszNew;
+
+                    kHlpFree(pSandbox->papwszEnvVars[iVar]);
+                    pSandbox->papwszEnvVars[iVar] = pwszNew;
+                    pSandbox->wenviron[iVar]      = pwszNew;
+                    return 0;
+                }
+                iVar++;
+            }
+
+            /* Not found, do we need to grow the table first? */
+            if (iVar + 1 >= pSandbox->cEnvVarsAllocated)
+                kwSandboxGrowEnv(pSandbox, iVar + 2);
+            if (iVar + 1 < pSandbox->cEnvVarsAllocated)
+            {
+                KW_LOG(("kwSandboxDoSetEnvA: Adding iVar=%d: %p='%s' and %p='%ls'\n", iVar, pszNew, pszNew, pwszNew, pwszNew));
+
+                pSandbox->papszEnvVars[iVar + 1]  = NULL;
+                pSandbox->papszEnvVars[iVar]      = pszNew;
+                pSandbox->environ[iVar + 1]       = NULL;
+                pSandbox->environ[iVar]           = pszNew;
+
+                pSandbox->papwszEnvVars[iVar + 1] = NULL;
+                pSandbox->papwszEnvVars[iVar]     = pwszNew;
+                pSandbox->wenviron[iVar + 1]      = NULL;
+                pSandbox->wenviron[iVar]          = pwszNew;
+                return 0;
+            }
+
+            kHlpFree(pwszNew);
+        }
+        kHlpFree(pszNew);
+    }
+    KW_LOG(("Out of memory!\n"));
+    return 0;
+}
+
+
+/**
+ * Sets an environment variable, UTF-16 style.
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param   pSandbox            The sandbox.
+ * @param   pwcVar              The variable name.
+ * @param   cwcVar              The length of the name.
+ * @param   pwszValue           The value.
+ */
+static int kwSandboxDoSetEnvW(PKWSANDBOX pSandbox, const wchar_t *pwchVar, KSIZE cwcVar, const wchar_t *pwszValue)
+{
+    /* Allocate and construct the new strings. */
+    KSIZE    cwcTmp = kwUtf16Len(pwszValue);
+    wchar_t *pwszNew = (wchar_t *)kHlpAlloc((cwcVar + 1 + cwcTmp + 1) * sizeof(wchar_t));
+    if (pwszNew)
+    {
+        char *pszNew;
+        kHlpMemCopy(pwszNew, pwchVar, cwcVar * sizeof(wchar_t));
+        pwszNew[cwcVar] = '=';
+        kHlpMemCopy(&pwszNew[cwcVar + 1], pwszValue, cwcTmp * sizeof(wchar_t));
+        cwcTmp += cwcVar + 1;
+        pwszNew[cwcVar] = '\0';
+
+        pszNew = kwUtf16ToStrAllocN(pwszNew, cwcVar);
+        if (pszNew)
+        {
+            /* Look it up. */
+            KSIZE    iVar = 0;
+            wchar_t *pwszEnv;
+            while ((pwszEnv = pSandbox->papwszEnvVars[iVar]) != NULL)
+            {
+                if (   _wcsnicmp(pwszEnv, pwchVar, cwcVar) == 0
+                    && pwszEnv[cwcVar] == '=')
+                {
+                    KW_LOG(("kwSandboxDoSetEnvW: Replacing iVar=%d: %p='%s' and %p='%ls'\n"
+                            "                              iVar=%d: %p='%s' and %p='%ls'\n",
+                            iVar, pSandbox->papszEnvVars[iVar], pSandbox->papszEnvVars[iVar],
+                            pSandbox->papwszEnvVars[iVar], pSandbox->papwszEnvVars[iVar],
+                            iVar, pszNew, pszNew, pwszNew, pwszNew));
+
+                    kHlpFree(pSandbox->papszEnvVars[iVar]);
+                    pSandbox->papszEnvVars[iVar]  = pszNew;
+                    pSandbox->environ[iVar]       = pszNew;
+
+                    kHlpFree(pSandbox->papwszEnvVars[iVar]);
+                    pSandbox->papwszEnvVars[iVar] = pwszNew;
+                    pSandbox->wenviron[iVar]      = pwszNew;
+                    return 0;
+                }
+                iVar++;
+            }
+
+            /* Not found, do we need to grow the table first? */
+            if (iVar + 1 >= pSandbox->cEnvVarsAllocated)
+                kwSandboxGrowEnv(pSandbox, iVar + 2);
+            if (iVar + 1 < pSandbox->cEnvVarsAllocated)
+            {
+                KW_LOG(("kwSandboxDoSetEnvW: Adding iVar=%d: %p='%s' and %p='%ls'\n", iVar, pszNew, pszNew, pwszNew, pwszNew));
+
+                pSandbox->papszEnvVars[iVar + 1]  = NULL;
+                pSandbox->papszEnvVars[iVar]      = pszNew;
+                pSandbox->environ[iVar + 1]       = NULL;
+                pSandbox->environ[iVar]           = pszNew;
+
+                pSandbox->papwszEnvVars[iVar + 1] = NULL;
+                pSandbox->papwszEnvVars[iVar]     = pwszNew;
+                pSandbox->wenviron[iVar + 1]      = NULL;
+                pSandbox->wenviron[iVar]          = pwszNew;
+                return 0;
+            }
+
+            kHlpFree(pwszNew);
+        }
+        kHlpFree(pszNew);
+    }
+    KW_LOG(("Out of memory!\n"));
+    return 0;
+}
+
+
+/** ANSI unsetenv worker. */
+static int kwSandboxDoUnsetEnvA(PKWSANDBOX pSandbox, const char *pchVar, KSIZE cchVar)
+{
+    KSIZE   iVar   = 0;
+    char   *pszEnv;
+    while ((pszEnv = pSandbox->papszEnvVars[iVar]) != NULL)
+    {
+        if (   _strnicmp(pszEnv, pchVar, cchVar) == 0
+            && pszEnv[cchVar] == '=')
+        {
+            KSIZE cVars = iVar;
+            while (pSandbox->papszEnvVars[cVars])
+                cVars++;
+            kHlpAssert(pSandbox->papwszEnvVars[iVar] != NULL);
+            kHlpAssert(pSandbox->papwszEnvVars[cVars] == NULL);
+
+            KW_LOG(("kwSandboxDoUnsetEnvA: Removing iVar=%d: %p='%s' and %p='%ls'; new cVars=%d\n", iVar,
+                    pSandbox->papszEnvVars[iVar], pSandbox->papszEnvVars[iVar],
+                    pSandbox->papwszEnvVars[iVar], pSandbox->papwszEnvVars[iVar], cVars - 1));
+
+            kHlpFree(pSandbox->papszEnvVars[iVar]);
+            pSandbox->papszEnvVars[iVar]    = pSandbox->papszEnvVars[cVars];
+            pSandbox->environ[iVar]         = pSandbox->papszEnvVars[cVars];
+            pSandbox->papszEnvVars[cVars]   = NULL;
+            pSandbox->environ[cVars]        = NULL;
+
+            kHlpFree(pSandbox->papwszEnvVars[iVar]);
+            pSandbox->papwszEnvVars[iVar]   = pSandbox->papwszEnvVars[cVars];
+            pSandbox->wenviron[iVar]        = pSandbox->papwszEnvVars[cVars];
+            pSandbox->papwszEnvVars[cVars]  = NULL;
+            pSandbox->wenviron[cVars]       = NULL;
+            return 0;
+        }
+        iVar++;
+    }
+    return KERR_ENVVAR_NOT_FOUND;
+}
+
+
+/** UTF-16 unsetenv worker. */
+static int kwSandboxDoUnsetEnvW(PKWSANDBOX pSandbox, const wchar_t *pwcVar, KSIZE cwcVar)
+{
+    KSIZE    iVar   = 0;
+    wchar_t *pwszEnv;
+    while ((pwszEnv = pSandbox->papwszEnvVars[iVar]) != NULL)
+    {
+        if (   _wcsnicmp(pwszEnv, pwcVar, cwcVar) == 0
+            && pwszEnv[cwcVar] == '=')
+        {
+            KSIZE cVars = iVar;
+            while (pSandbox->papwszEnvVars[cVars])
+                cVars++;
+            kHlpAssert(pSandbox->papszEnvVars[iVar] != NULL);
+            kHlpAssert(pSandbox->papszEnvVars[cVars] == NULL);
+
+            KW_LOG(("kwSandboxDoUnsetEnvA: Removing iVar=%d: %p='%s' and %p='%ls'; new cVars=%d\n", iVar,
+                    pSandbox->papszEnvVars[iVar], pSandbox->papszEnvVars[iVar],
+                    pSandbox->papwszEnvVars[iVar], pSandbox->papwszEnvVars[iVar], cVars - 1));
+
+            kHlpFree(pSandbox->papszEnvVars[iVar]);
+            pSandbox->papszEnvVars[iVar]    = pSandbox->papszEnvVars[cVars];
+            pSandbox->environ[iVar]         = pSandbox->papszEnvVars[cVars];
+            pSandbox->papszEnvVars[cVars]   = NULL;
+            pSandbox->environ[cVars]        = NULL;
+
+            kHlpFree(pSandbox->papwszEnvVars[iVar]);
+            pSandbox->papwszEnvVars[iVar]   = pSandbox->papwszEnvVars[cVars];
+            pSandbox->wenviron[iVar]        = pSandbox->papwszEnvVars[cVars];
+            pSandbox->papwszEnvVars[cVars]  = NULL;
+            pSandbox->wenviron[cVars]       = NULL;
+            return 0;
+        }
+        iVar++;
+    }
+    return KERR_ENVVAR_NOT_FOUND;
+}
+
+
+
+/** ANSI getenv worker. */
+static char *kwSandboxDoGetEnvA(PKWSANDBOX pSandbox, const char *pchVar, KSIZE cchVar)
+{
+    KSIZE   iVar   = 0;
+    char   *pszEnv;
+    while ((pszEnv = pSandbox->papszEnvVars[iVar++]) != NULL)
+        if (   _strnicmp(pszEnv, pchVar, cchVar) == 0
+            && pszEnv[cchVar] == '=')
+            return &pszEnv[cchVar + 1];
+    return NULL;
+}
+
+
+/** UTF-16 getenv worker. */
+static wchar_t *kwSandboxDoGetEnvW(PKWSANDBOX pSandbox, const wchar_t *pwcVar, KSIZE cwcVar)
+{
+    KSIZE    iVar   = 0;
+    wchar_t *pwszEnv;
+    while ((pwszEnv = pSandbox->papwszEnvVars[iVar++]) != NULL)
+        if (   _wcsnicmp(pwszEnv, pwcVar, cwcVar) == 0
+            && pwszEnv[cwcVar] == '=')
+            return &pwszEnv[cwcVar + 1];
+    return NULL;
+}
+
+
+/** Kernel32 - GetEnvironmentVariableA()  */
+static DWORD WINAPI kwSandbox_Kernel32_GetEnvironmentVariableA(LPCSTR pszVar, LPSTR pszValue, DWORD cbValue)
+{
+    char *pszFoundValue = kwSandboxDoGetEnvA(&g_Sandbox, pszVar, kHlpStrLen(pszVar));
+    if (pszFoundValue)
+    {
+        DWORD cchRet = kwStrCopyStyle1(pszFoundValue, pszValue, cbValue);
+        KW_LOG(("GetEnvironmentVariableA: '%s' -> %u (%s)\n", pszVar, cchRet, pszFoundValue));
+        return cchRet;
+    }
+    KW_LOG(("GetEnvironmentVariableA: '%s' -> 0\n", pszVar));
+    SetLastError(ERROR_ENVVAR_NOT_FOUND);
+    return 0;
+}
+
+
+/** Kernel32 - GetEnvironmentVariableW()  */
+static DWORD WINAPI kwSandbox_Kernel32_GetEnvironmentVariableW(LPCWSTR pwszVar, LPWSTR pwszValue, DWORD cwcValue)
+{
+    wchar_t *pwszFoundValue = kwSandboxDoGetEnvW(&g_Sandbox, pwszVar, kwUtf16Len(pwszVar));
+    if (pwszFoundValue)
+    {
+        DWORD cchRet = kwUtf16CopyStyle1(pwszFoundValue, pwszValue, cwcValue);
+        KW_LOG(("GetEnvironmentVariableW: '%ls' -> %u (%ls)\n", pwszVar, cchRet, pwszFoundValue));
+        return cchRet;
+    }
+    KW_LOG(("GetEnvironmentVariableW: '%ls' -> 0\n", pwszVar));
+    SetLastError(ERROR_ENVVAR_NOT_FOUND);
+    return 0;
+}
+
+
+/** Kernel32 - SetEnvironmentVariableA()  */
+static BOOL WINAPI kwSandbox_Kernel32_SetEnvironmentVariableA(LPCSTR pszVar, LPCSTR pszValue)
+{
+    int rc;
+    if (pszValue)
+        rc = kwSandboxDoSetEnvA(&g_Sandbox, pszVar, kHlpStrLen(pszVar), pszValue);
+    else
+    {
+        kwSandboxDoUnsetEnvA(&g_Sandbox, pszVar, kHlpStrLen(pszVar));
+        rc = 0; //??
+    }
+    if (rc == 0)
+    {
+        KW_LOG(("SetEnvironmentVariableA(%s,%s) -> TRUE\n", pszVar, pszValue));
+        return TRUE;
+    }
+    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    KW_LOG(("SetEnvironmentVariableA(%s,%s) -> FALSE!\n", pszVar, pszValue));
+    return FALSE;
+}
+
+
+/** Kernel32 - SetEnvironmentVariableW()  */
+static BOOL WINAPI kwSandbox_Kernel32_SetEnvironmentVariableW(LPCWSTR pwszVar, LPCWSTR pwszValue)
+{
+    int rc;
+    if (pwszValue)
+        rc = kwSandboxDoSetEnvW(&g_Sandbox, pwszVar, kwUtf16Len(pwszVar), pwszValue);
+    else
+    {
+        kwSandboxDoUnsetEnvW(&g_Sandbox, pwszVar, kwUtf16Len(pwszVar));
+        rc = 0; //??
+    }
+    if (rc == 0)
+    {
+        KW_LOG(("SetEnvironmentVariableA(%ls,%ls) -> TRUE\n", pwszVar, pwszValue));
+        return TRUE;
+    }
+    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    KW_LOG(("SetEnvironmentVariableA(%ls,%ls) -> FALSE!\n", pwszVar, pwszValue));
+    return FALSE;
+}
+
+
+/** Kernel32 - ExpandEnvironmentStringsA()  */
+static DWORD WINAPI kwSandbox_Kernel32_ExpandEnvironmentStringsA(LPCSTR pszSrc, LPSTR pwszDst, DWORD cbDst)
+{
+    KWFS_TODO();
+    return 0;
+}
+
+
+/** Kernel32 - ExpandEnvironmentStringsW()  */
+static DWORD WINAPI kwSandbox_Kernel32_ExpandEnvironmentStringsW(LPCWSTR pwszSrc, LPWSTR pwszDst, DWORD cbDst)
+{
+    KWFS_TODO();
+    return 0;
+}
+
+
+/** CRT - _putenv(). */
+static int __cdecl kwSandbox_msvcrt__putenv(const char *pszVarEqualValue)
+{
+    int rc;
+    char const *pszEqual = kHlpStrChr(pszVarEqualValue, '=');
+    if (pszEqual)
+    {
+        rc = kwSandboxDoSetEnvA(&g_Sandbox, pszVarEqualValue, pszEqual - pszVarEqualValue, pszEqual + 1);
+        if (rc == 0)
+        { }
+        else
+            rc = -1;
+    }
+    else
+    {
+        kwSandboxDoUnsetEnvA(&g_Sandbox, pszVarEqualValue, kHlpStrLen(pszVarEqualValue));
+        rc = 0;
+    }
+    KW_LOG(("_putenv(%s) -> %d\n", pszVarEqualValue, rc));
+    return rc;
+}
+
+
+/** CRT - _wputenv(). */
+static int __cdecl kwSandbox_msvcrt__wputenv(const wchar_t *pwszVarEqualValue)
+{
+    int rc;
+    wchar_t const *pwszEqual = wcschr(pwszVarEqualValue, '=');
+    if (pwszEqual)
+    {
+        rc = kwSandboxDoSetEnvW(&g_Sandbox, pwszVarEqualValue, pwszEqual - pwszVarEqualValue, pwszEqual + 1);
+        if (rc == 0)
+        { }
+        else
+            rc = -1;
+    }
+    else
+    {
+        kwSandboxDoUnsetEnvW(&g_Sandbox, pwszVarEqualValue, kwUtf16Len(pwszVarEqualValue));
+        rc = 0;
+    }
+    KW_LOG(("_wputenv(%ls) -> %d\n", pwszVarEqualValue, rc));
+    return rc;
+}
+
+
+/** CRT - _putenv_s(). */
+static errno_t __cdecl kwSandbox_msvcrt__putenv_s(const char *pszVar, const char *pszValue)
+{
+    char const *pszEqual = kHlpStrChr(pszVar, '=');
+    if (pszEqual == NULL)
+    {
+        if (pszValue)
+        {
+            int rc = kwSandboxDoSetEnvA(&g_Sandbox, pszVar, kHlpStrLen(pszVar), pszValue);
+            if (rc == 0)
+            {
+                KW_LOG(("_putenv_s(%s,%s) -> 0\n", pszVar, pszValue));
+                return 0;
+            }
+        }
+        else
+        {
+            kwSandboxDoUnsetEnvA(&g_Sandbox, pszVar, kHlpStrLen(pszVar));
+            KW_LOG(("_putenv_s(%ls,NULL) -> 0\n", pszVar));
+            return 0;
+        }
+        KW_LOG(("_putenv_s(%s,%s) -> ENOMEM\n", pszVar, pszValue));
+        return ENOMEM;
+    }
+    KW_LOG(("_putenv_s(%s,%s) -> EINVAL\n", pszVar, pszValue));
+    return EINVAL;
+}
+
+
+/** CRT - _wputenv_s(). */
+static errno_t __cdecl kwSandbox_msvcrt__wputenv_s(const wchar_t *pwszVar, const wchar_t *pwszValue)
+{
+    wchar_t const *pwszEqual = wcschr(pwszVar, '=');
+    if (pwszEqual == NULL)
+    {
+        if (pwszValue)
+        {
+            int rc = kwSandboxDoSetEnvW(&g_Sandbox, pwszVar, kwUtf16Len(pwszVar), pwszValue);
+            if (rc == 0)
+            {
+                KW_LOG(("_wputenv_s(%ls,%ls) -> 0\n", pwszVar, pwszValue));
+                return 0;
+            }
+        }
+        else
+        {
+            kwSandboxDoUnsetEnvW(&g_Sandbox, pwszVar, kwUtf16Len(pwszVar));
+            KW_LOG(("_wputenv_s(%ls,NULL) -> 0\n", pwszVar));
+            return 0;
+        }
+        KW_LOG(("_wputenv_s(%ls,%ls) -> ENOMEM\n", pwszVar, pwszValue));
+        return ENOMEM;
+    }
+    KW_LOG(("_wputenv_s(%ls,%ls) -> EINVAL\n", pwszVar, pwszValue));
+    return EINVAL;
+}
+
+
+/** CRT - get pointer to the __initenv variable (initial environment).   */
+static char *** __cdecl kwSandbox_msvcrt___p___initenv(void)
+{
+    KW_LOG(("__p___initenv\n"));
+    KWFS_TODO();
+    return &g_Sandbox.initenv;
+}
+
+
+/** CRT - get pointer to the __winitenv variable (initial environment).   */
+static wchar_t *** __cdecl kwSandbox_msvcrt___p___winitenv(void)
+{
+    KW_LOG(("__p___winitenv\n"));
+    KWFS_TODO();
+    return &g_Sandbox.winitenv;
+}
+
+
+/** CRT - get pointer to the _environ variable (current environment).   */
+static char *** __cdecl kwSandbox_msvcrt___p__environ(void)
+{
+    KW_LOG(("__p__environ\n"));
+    return &g_Sandbox.environ;
+}
+
+
+/** CRT - get pointer to the _wenviron variable (current environment).   */
+static wchar_t *** __cdecl kwSandbox_msvcrt___p__wenviron(void)
+{
+    KW_LOG(("__p__wenviron\n"));
+    return &g_Sandbox.wenviron;
+}
+
+
+/** CRT - get the _environ variable (current environment).
+ * @remarks Not documented or prototyped?  */
+static KUPTR /*void*/ __cdecl kwSandbox_msvcrt__get_environ(char ***ppapszEnviron)
+{
+    KWFS_TODO(); /** @todo check the callers expectations! */
+    *ppapszEnviron = g_Sandbox.environ;
+    return 0;
+}
+
+
+/** CRT - get the _wenviron variable (current environment).
+ * @remarks Not documented or prototyped? */
+static KUPTR /*void*/ __cdecl kwSandbox_msvcrt__get_wenviron(wchar_t ***ppapwszEnviron)
+{
+    KWFS_TODO(); /** @todo check the callers expectations! */
+    *ppapwszEnviron = g_Sandbox.wenviron;
+    return 0;
+}
+
+
+
+/*
+ *
+ * Loader related APIs
+ * Loader related APIs
+ * Loader related APIs
+ *
+ */
+
+/**
+ * Kernel32 - LoadLibraryExA() worker that loads resource files and such.
+ */
+static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExA_Resource(PKWDYNLOAD pDynLoad, DWORD fFlags)
+{
+    /* Load it first. */
+    HMODULE hmod = LoadLibraryExA(pDynLoad->szRequest, NULL /*hFile*/, fFlags);
+    if (hmod)
+    {
+        pDynLoad->hmod = hmod;
+        pDynLoad->pMod = NULL; /* indicates special  */
+
+        pDynLoad->pNext = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead;
+        g_Sandbox.pTool->u.Sandboxed.pDynLoadHead = pDynLoad;
+        KW_LOG(("LoadLibraryExA(%s,,[resource]) -> %p\n", pDynLoad->szRequest, pDynLoad->hmod));
+    }
+    else
+        kHlpFree(pDynLoad);
+    return hmod;
+}
+
+
+/**
+ * Kernel32 - LoadLibraryExA() worker that deals with the api-ms-xxx modules.
+ */
+static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExA_VirtualApiModule(PKWDYNLOAD pDynLoad, DWORD fFlags)
+{
+    HMODULE     hmod;
+    PKWMODULE   pMod;
+    KU32        uHashPath;
+    KSIZE       idxHash;
+    char        szNormPath[256];
+    KSIZE       cbFilename = kHlpStrLen(pDynLoad->szRequest) + 1;
+
+    /*
+     * Lower case it.
+     */
+    if (cbFilename <= sizeof(szNormPath))
+    {
+        kHlpMemCopy(szNormPath, pDynLoad->szRequest, cbFilename);
+        _strlwr(szNormPath);
+    }
+    else
+    {
+        SetLastError(ERROR_FILENAME_EXCED_RANGE);
+        return NULL;
+    }
+
+    /*
+     * Check if it has already been loaded so we don't create an unnecessary
+     * loader module for it.
+     */
+    uHashPath = kwStrHash(szNormPath);
+    idxHash   = uHashPath % K_ELEMENTS(g_apModules);
+    pMod      = g_apModules[idxHash];
+    if (pMod)
+    {
+        do
+        {
+            if (   pMod->uHashPath == uHashPath
+                && kHlpStrComp(pMod->pszPath, szNormPath) == 0)
+            {
+                pDynLoad->pMod = kwLdrModuleRetain(pMod);
+                pDynLoad->hmod = pMod->hOurMod;
+
+                pDynLoad->pNext = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead;
+                g_Sandbox.pTool->u.Sandboxed.pDynLoadHead = pDynLoad;
+                KW_LOG(("LoadLibraryExA(%s,,) -> %p [already loaded]\n", pDynLoad->szRequest, pDynLoad->hmod));
+                return pDynLoad->hmod;
+            }
+            pMod = pMod->pNext;
+        } while (pMod);
+    }
+
+
+    /*
+     * Try load it and make a kLdr module for it.
+     */
+    hmod = LoadLibraryExA(szNormPath, NULL /*hFile*/, fFlags);
+    if (hmod)
+    {
+        PKLDRMOD pLdrMod;
+        int rc = kLdrModOpenNativeByHandle((KUPTR)hmod, &pLdrMod);
+        if (rc == 0)
+        {
+            PKWMODULE pMod = kwLdrModuleCreateForNativekLdrModule(pLdrMod, szNormPath, cbFilename, uHashPath,
+                                                                  K_FALSE /*fDoReplacements*/);
+            if (pMod)
+            {
+                kwToolAddModuleAndImports(g_Sandbox.pTool, pMod);
+
+                pDynLoad = (PKWDYNLOAD)kHlpAlloc(sizeof(*pDynLoad) + cbFilename + cbFilename * sizeof(wchar_t));
+                if (pDynLoad)
+                {
+                    pDynLoad->pMod = pMod;
+                    pDynLoad->hmod = hmod;
+
+                    pDynLoad->pNext = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead;
+                    g_Sandbox.pTool->u.Sandboxed.pDynLoadHead = pDynLoad;
+                    KW_LOG(("LoadLibraryExA(%s,,) -> %p\n", pDynLoad->szRequest, pDynLoad->hmod));
+                    return hmod;
+                }
+
+                KWFS_TODO();
+            }
+            else
+                KWFS_TODO();
+        }
+        else
+            KWFS_TODO();
+    }
+    kHlpFree(pDynLoad);
+    return hmod;
+}
+
+
+/** Kernel32 - LoadLibraryExA() */
+static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExA(LPCSTR pszFilename, HANDLE hFile, DWORD fFlags)
+{
+    KSIZE       cchFilename = kHlpStrLen(pszFilename);
+    PKWDYNLOAD  pDynLoad;
+    PKWMODULE   pMod;
+    int         rc;
+
+    /*
+     * Deal with a couple of extremely unlikely special cases right away.
+     */
+    if (   !(fFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)
+        && (hFile == NULL || hFile == INVALID_HANDLE_VALUE) )
+    { /* likely */ }
+    else
+    {
+        KWFS_TODO();
+        return LoadLibraryExA(pszFilename, hFile, fFlags);
+    }
+
+    /*
+     * Check if we've already got a dynload entry for this one.
+     */
+    for (pDynLoad = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead; pDynLoad; pDynLoad = pDynLoad->pNext)
+        if (   pDynLoad->cchRequest == cchFilename
+            && kHlpMemComp(pDynLoad->szRequest, pszFilename, cchFilename) == 0)
+        {
+            if (pDynLoad->pMod)
+                rc = kwLdrModuleInitTree(pDynLoad->pMod);
+            else
+                rc = 0;
+            if (rc == 0)
+            {
+                KW_LOG(("LoadLibraryExA(%s,,) -> %p [cached]\n", pszFilename, pDynLoad->hmod));
+                return pDynLoad->hmod;
+            }
+            SetLastError(ERROR_DLL_INIT_FAILED);
+            return NULL;
+        }
+
+    /*
+     * Allocate a dynload entry for the request.
+     */
+    pDynLoad = (PKWDYNLOAD)kHlpAlloc(sizeof(*pDynLoad) + cchFilename + 1);
+    if (pDynLoad)
+    {
+        pDynLoad->cchRequest = cchFilename;
+        kHlpMemCopy(pDynLoad->szRequest, pszFilename, cchFilename + 1);
+    }
+    else
+    {
+        KW_LOG(("LoadLibraryExA: Out of memory!\n"));
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return NULL;
+    }
+
+    /*
+     * Deal with resource / data DLLs.
+     */
+    if (fFlags & (  DONT_RESOLVE_DLL_REFERENCES
+                  | LOAD_LIBRARY_AS_DATAFILE
+                  | LOAD_LIBRARY_AS_IMAGE_RESOURCE) )
+        return kwSandbox_Kernel32_LoadLibraryExA_Resource(pDynLoad, fFlags);
+
+    /*
+     * Special case: api-ms-win-core-synch-l1-2-0 and friends (32-bit yasm, built with VS2015).
+     */
+    if (   strnicmp(pszFilename, TUPLE("api-ms-")) == 0
+        && kHlpIsFilenameOnly(pszFilename))
+        return kwSandbox_Kernel32_LoadLibraryExA_VirtualApiModule(pDynLoad, fFlags);
+
+    /*
+     * Normal library loading.
+     * We start by being very lazy and reusing the code for resolving imports.
+     */
+    if (!kHlpIsFilenameOnly(pszFilename))
+        pMod = kwLdrModuleTryLoadDll(pszFilename, KWLOCATION_UNKNOWN, g_Sandbox.pTool->u.Sandboxed.pExe);
+    else
+    {
+        rc = kwLdrModuleResolveAndLookup(pszFilename, g_Sandbox.pTool->u.Sandboxed.pExe, NULL /*pImporter*/, &pMod);
+        if (rc != 0)
+            pMod = NULL;
+    }
+    if (pMod)
+    {
+        /* Enter it into the tool module table and dynamic link request cache. */
+        kwToolAddModuleAndImports(g_Sandbox.pTool, pMod);
+
+        pDynLoad->pMod = pMod;
+        pDynLoad->hmod = pMod->hOurMod;
+
+        pDynLoad->pNext = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead;
+        g_Sandbox.pTool->u.Sandboxed.pDynLoadHead = pDynLoad;
+
+        /*
+         * Make sure it's initialized (need to link it first since DllMain may
+         * use loader APIs).
+         */
+        rc = kwLdrModuleInitTree(pMod);
+        if (rc == 0)
+        {
+            KW_LOG(("LoadLibraryExA(%s,,) -> %p\n", pszFilename, pDynLoad->hmod));
+            return pDynLoad->hmod;
+        }
+
+        SetLastError(ERROR_DLL_INIT_FAILED);
+    }
+    else
+    {
+        KWFS_TODO();
+        kHlpFree(pDynLoad);
+        SetLastError(ERROR_MOD_NOT_FOUND);
+    }
+    return NULL;
+}
+
+
+/** Kernel32 - LoadLibraryExW()   */
+static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExW(LPCWSTR pwszFilename, HANDLE hFile, DWORD fFlags)
+{
+    char szTmp[4096];
+    KSIZE cchTmp = kwUtf16ToStr(pwszFilename, szTmp, sizeof(szTmp));
+    if (cchTmp < sizeof(szTmp))
+        return kwSandbox_Kernel32_LoadLibraryExA(szTmp, hFile, fFlags);
+
+    KWFS_TODO();
+    SetLastError(ERROR_FILENAME_EXCED_RANGE);
+    return NULL;
+}
+
+/** Kernel32 - LoadLibraryA()   */
+static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryA(LPCSTR pszFilename)
+{
+    return kwSandbox_Kernel32_LoadLibraryExA(pszFilename, NULL /*hFile*/, 0 /*fFlags*/);
+}
+
+
+/** Kernel32 - LoadLibraryW()   */
+static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryW(LPCWSTR pwszFilename)
+{
+    char szTmp[4096];
+    KSIZE cchTmp = kwUtf16ToStr(pwszFilename, szTmp, sizeof(szTmp));
+    if (cchTmp < sizeof(szTmp))
+        return kwSandbox_Kernel32_LoadLibraryExA(szTmp, NULL /*hFile*/, 0 /*fFlags*/);
+    KWFS_TODO();
+    SetLastError(ERROR_FILENAME_EXCED_RANGE);
+    return NULL;
+}
+
+
+/** Kernel32 - FreeLibrary()   */
+static BOOL WINAPI kwSandbox_Kernel32_FreeLibrary(HMODULE hmod)
+{
+    /* Ignored, we like to keep everything loaded. */
+    return TRUE;
+}
+
+
+/** Kernel32 - GetModuleHandleA()   */
+static HMODULE WINAPI kwSandbox_Kernel32_GetModuleHandleA(LPCSTR pszModule)
+{
+    KSIZE i;
+    KSIZE cchModule;
+
+    /*
+     * The executable.
+     */
+    if (pszModule == NULL)
+        return (HMODULE)g_Sandbox.pTool->u.Sandboxed.pExe->hOurMod;
+
+    /*
+     * Cache of system modules we've seen queried.
+     */
+    cchModule = kHlpStrLen(pszModule);
+    for (i = 0; i < K_ELEMENTS(g_aGetModuleHandleCache); i++)
+        if (   g_aGetModuleHandleCache[i].cchName == cchModule
+            && stricmp(pszModule, g_aGetModuleHandleCache[i].pszName) == 0)
+        {
+            if (g_aGetModuleHandleCache[i].hmod != NULL)
+                return g_aGetModuleHandleCache[i].hmod;
+            return g_aGetModuleHandleCache[i].hmod = GetModuleHandleA(pszModule);
+        }
+
+    KWFS_TODO();
+    return NULL;
+}
+
+
+/** Kernel32 - GetModuleHandleW()   */
+static HMODULE WINAPI kwSandbox_Kernel32_GetModuleHandleW(LPCWSTR pwszModule)
+{
+    KSIZE i;
+    KSIZE cwcModule;
+
+    /*
+     * The executable.
+     */
+    if (pwszModule == NULL)
+        return (HMODULE)g_Sandbox.pTool->u.Sandboxed.pExe->hOurMod;
+
+    /*
+     * Cache of system modules we've seen queried.
+     */
+    cwcModule = kwUtf16Len(pwszModule);
+    for (i = 0; i < K_ELEMENTS(g_aGetModuleHandleCache); i++)
+        if (   g_aGetModuleHandleCache[i].cwcName == cwcModule
+            && _wcsicmp(pwszModule, g_aGetModuleHandleCache[i].pwszName) == 0)
+        {
+            if (g_aGetModuleHandleCache[i].hmod != NULL)
+                return g_aGetModuleHandleCache[i].hmod;
+            return g_aGetModuleHandleCache[i].hmod = GetModuleHandleW(pwszModule);
+        }
+
+    KWFS_TODO();
+    return NULL;
+}
+
+
+/** Used to debug dynamically resolved procedures. */
+static UINT WINAPI kwSandbox_BreakIntoDebugger(void *pv1, void *pv2, void *pv3, void *pv4)
+{
+    KWFS_TODO();
+    return -1;
+}
+
+
+/** Kernel32 - GetProcAddress()   */
+static FARPROC WINAPI kwSandbox_Kernel32_GetProcAddress(HMODULE hmod, LPCSTR pszProc)
+{
+    KSIZE i;
+
+    /*
+     * Try locate the module.
+     */
+    PKWMODULE pMod = kwToolLocateModuleByHandle(g_Sandbox.pTool, hmod);
+    if (pMod)
+    {
+        KLDRADDR uValue;
+        int rc = kLdrModQuerySymbol(pMod->pLdrMod,
+                                    pMod->fNative ? NULL : pMod->u.Manual.pvBits,
+                                    pMod->fNative ? KLDRMOD_BASEADDRESS_MAP : (KUPTR)pMod->u.Manual.pvLoad,
+                                    KU32_MAX /*iSymbol*/,
+                                    pszProc,
+                                    kHlpStrLen(pszProc),
+                                    NULL /*pszVersion*/,
+                                    NULL /*pfnGetForwarder*/, NULL /*pvUser*/,
+                                    &uValue,
+                                    NULL /*pfKind*/);
+        if (rc == 0)
+        {
+            static int s_cDbgGets = 0;
+            s_cDbgGets++;
+            KW_LOG(("GetProcAddress(%s, %s) -> %p [%d]\n", pMod->pszPath, pszProc, (KUPTR)uValue, s_cDbgGets));
+            kwLdrModuleRelease(pMod);
+            //if (s_cGets >= 3)
+            //    return (FARPROC)kwSandbox_BreakIntoDebugger;
+            return (FARPROC)(KUPTR)uValue;
+        }
+
+        KWFS_TODO();
+        SetLastError(ERROR_PROC_NOT_FOUND);
+        kwLdrModuleRelease(pMod);
+        return NULL;
+    }
+
+    /*
+     * Hmm... could be a cached module-by-name.
+     */
+    for (i = 0; i < K_ELEMENTS(g_aGetModuleHandleCache); i++)
+        if (g_aGetModuleHandleCache[i].hmod == hmod)
+            return GetProcAddress(hmod, pszProc);
+
+    KWFS_TODO();
+    return GetProcAddress(hmod, pszProc);
+}
+
+
+/** Kernel32 - GetModuleFileNameA()   */
+static DWORD WINAPI kwSandbox_Kernel32_GetModuleFileNameA(HMODULE hmod, LPSTR pszFilename, DWORD cbFilename)
+{
+    PKWMODULE pMod = kwToolLocateModuleByHandle(g_Sandbox.pTool, hmod);
+    if (pMod != NULL)
+    {
+        DWORD cbRet = kwStrCopyStyle1(pMod->pszPath, pszFilename, cbFilename);
+        kwLdrModuleRelease(pMod);
+        return cbRet;
+    }
+    KWFS_TODO();
+    return 0;
+}
+
+
+/** Kernel32 - GetModuleFileNameW()   */
+static DWORD WINAPI kwSandbox_Kernel32_GetModuleFileNameW(HMODULE hmod, LPWSTR pwszFilename, DWORD cbFilename)
+{
+    PKWMODULE pMod = kwToolLocateModuleByHandle(g_Sandbox.pTool, hmod);
+    if (pMod)
+    {
+        DWORD cwcRet = kwUtf16CopyStyle1(pMod->pwszPath, pwszFilename, cbFilename);
+        kwLdrModuleRelease(pMod);
+        return cwcRet;
+    }
+
+    KWFS_TODO();
+    return 0;
+}
+
+
+/** NtDll - RtlPcToFileHeader
+ * This is necessary for msvcr100.dll!CxxThrowException.  */
+static PVOID WINAPI kwSandbox_ntdll_RtlPcToFileHeader(PVOID pvPC, PVOID *ppvImageBase)
+{
+    PVOID pvRet;
+
+    /*
+     * Do a binary lookup of the module table for the current tool.
+     * This will give us a
+     */
+    if (g_Sandbox.fRunning)
+    {
+        KUPTR const     uPC     = (KUPTR)pvPC;
+        PKWMODULE      *papMods = g_Sandbox.pTool->u.Sandboxed.papModules;
+        KU32            iEnd    = g_Sandbox.pTool->u.Sandboxed.cModules;
+        KU32            i;
+        if (iEnd)
+        {
+            KU32        iStart  = 0;
+            i = iEnd / 2;
+            for (;;)
+            {
+                KUPTR const uHModThis = (KUPTR)papMods[i]->hOurMod;
+                if (uPC < uHModThis)
+                {
+                    iEnd = i;
+                    if (iStart < i)
+                    { }
+                    else
+                        break;
+                }
+                else if (uPC != uHModThis)
+                {
+                    iStart = ++i;
+                    if (i < iEnd)
+                    { }
+                    else
+                        break;
+                }
+                else
+                {
+                    /* This isn't supposed to happen. */
+                    break;
+                }
+
+                i = iStart + (iEnd - iStart) / 2;
+            }
+
+            /* For reasons of simplicity (= copy & paste), we end up with the
+               module after the one we're interested in here.  */
+            i--;
+            if (i < g_Sandbox.pTool->u.Sandboxed.cModules
+                && papMods[i]->pLdrMod)
+            {
+                KSIZE uRvaPC = uPC - (KUPTR)papMods[i]->hOurMod;
+                if (uRvaPC < papMods[i]->cbImage)
+                {
+                    *ppvImageBase = papMods[i]->hOurMod;
+                    pvRet = papMods[i]->hOurMod;
+                    KW_LOG(("RtlPcToFileHeader(PC=%p) -> %p, *ppvImageBase=%p [our]\n", pvPC, pvRet, *ppvImageBase));
+                    return pvRet;
+                }
+            }
+        }
+        else
+            i = 0;
+    }
+
+    /*
+     * Call the regular API.
+     */
+    pvRet = RtlPcToFileHeader(pvPC, ppvImageBase);
+    KW_LOG(("RtlPcToFileHeader(PC=%p) -> %p, *ppvImageBase=%p \n", pvPC, pvRet, *ppvImageBase));
+    return pvRet;
+}
+
+
+/*
+ *
+ * File access APIs (for speeding them up).
+ * File access APIs (for speeding them up).
+ * File access APIs (for speeding them up).
+ *
+ */
+
+
+/**
+ * Converts a lookup error to a windows error code.
+ *
+ * @returns The windows error code.
+ * @param   enmError            The lookup error.
+ */
+static DWORD kwFsLookupErrorToWindowsError(KFSLOOKUPERROR enmError)
+{
+    switch (enmError)
+    {
+        case KFSLOOKUPERROR_NOT_FOUND:
+        case KFSLOOKUPERROR_NOT_DIR:
+            return ERROR_FILE_NOT_FOUND;
+
+        case KFSLOOKUPERROR_PATH_COMP_NOT_FOUND:
+        case KFSLOOKUPERROR_PATH_COMP_NOT_DIR:
+            return ERROR_PATH_NOT_FOUND;
+
+        case KFSLOOKUPERROR_PATH_TOO_LONG:
+            return ERROR_FILENAME_EXCED_RANGE;
+
+        case KFSLOOKUPERROR_OUT_OF_MEMORY:
+            return ERROR_NOT_ENOUGH_MEMORY;
+
+        default:
+            return ERROR_PATH_NOT_FOUND;
+    }
+}
+
+#ifdef WITH_TEMP_MEMORY_FILES
+
+/**
+ * Checks for a cl.exe temporary file.
+ *
+ * There are quite a bunch of these.  They seems to be passing data between the
+ * first and second compiler pass.  Since they're on disk, they get subjected to
+ * AV software screening and normal file consistency rules.  So, not necessarily
+ * a very efficient way of handling reasonably small amounts of data.
+ *
+ * We make the files live in virtual memory by intercepting their  opening,
+ * writing, reading, closing , mapping, unmapping, and maybe some more stuff.
+ *
+ * @returns K_TRUE / K_FALSE
+ * @param   pwszFilename    The file name being accessed.
+ */
+static KBOOL kwFsIsClTempFileW(const wchar_t *pwszFilename)
+{
+    wchar_t const *pwszName = kwPathGetFilenameW(pwszFilename);
+    if (pwszName)
+    {
+        /* The name starts with _CL_... */
+        if (   pwszName[0] == '_'
+            && pwszName[1] == 'C'
+            && pwszName[2] == 'L'
+            && pwszName[3] == '_' )
+        {
+            /* ... followed by 8 xdigits and ends with a two letter file type.  Simplify
+               this check by just checking that it's alpha numerical ascii from here on. */
+            wchar_t wc;
+            pwszName += 4;
+            while ((wc = *pwszName++) != '\0')
+            {
+                if (wc < 127 && iswalnum(wc))
+                { /* likely */ }
+                else
+                    return K_FALSE;
+            }
+            return K_TRUE;
+        }
+    }
+    return K_FALSE;
+}
+
+
+/**
+ * Creates a handle to a temporary file.
+ *
+ * @returns The handle on success.
+ *          INVALID_HANDLE_VALUE and SetLastError on failure.
+ * @param   pTempFile           The temporary file.
+ * @param   dwDesiredAccess     The desired access to the handle.
+ * @param   fMapping            Whether this is a mapping (K_TRUE) or file
+ *                              (K_FALSE) handle type.
+ */
+static HANDLE kwFsTempFileCreateHandle(PKWFSTEMPFILE pTempFile, DWORD dwDesiredAccess, KBOOL fMapping)
+{
+    /*
+     * Create a handle to the temporary file.
+     */
+    HANDLE hFile = INVALID_HANDLE_VALUE;
+    HANDLE hProcSelf = GetCurrentProcess();
+    if (DuplicateHandle(hProcSelf, hProcSelf,
+                        hProcSelf, &hFile,
+                        SYNCHRONIZE, FALSE,
+                        0 /*dwOptions*/))
+    {
+        PKWHANDLE pHandle = (PKWHANDLE)kHlpAlloc(sizeof(*pHandle));
+        if (pHandle)
+        {
+            pHandle->enmType            = !fMapping ? KWHANDLETYPE_TEMP_FILE : KWHANDLETYPE_TEMP_FILE_MAPPING;
+            pHandle->offFile            = 0;
+            pHandle->hHandle            = hFile;
+            pHandle->dwDesiredAccess    = dwDesiredAccess;
+            pHandle->u.pTempFile        = pTempFile;
+            if (kwSandboxHandleTableEnter(&g_Sandbox, pHandle))
+            {
+                pTempFile->cActiveHandles++;
+                kHlpAssert(pTempFile->cActiveHandles >= 1);
+                kHlpAssert(pTempFile->cActiveHandles <= 2);
+                KWFS_LOG(("kwFsTempFileCreateHandle: Temporary file '%ls' -> %p\n", pTempFile->pwszPath, hFile));
+                return hFile;
+            }
+
+            kHlpFree(pHandle);
+        }
+        else
+            KWFS_LOG(("kwFsTempFileCreateHandle: Out of memory!\n"));
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    }
+    else
+        KWFS_LOG(("kwFsTempFileCreateHandle: DuplicateHandle failed: err=%u\n", GetLastError()));
+    return INVALID_HANDLE_VALUE;
+}
+
+
+static HANDLE kwFsTempFileCreateW(const wchar_t *pwszFilename, DWORD dwDesiredAccess, DWORD dwCreationDisposition)
+{
+    HANDLE hFile;
+    DWORD  dwErr;
+
+    /*
+     * Check if we've got an existing temp file.
+     * ASSUME exact same path for now.
+     */
+    KSIZE const   cwcFilename = kwUtf16Len(pwszFilename);
+    PKWFSTEMPFILE pTempFile;
+    for (pTempFile = g_Sandbox.pTempFileHead; pTempFile != NULL; pTempFile = pTempFile->pNext)
+    {
+        /* Since the last two chars are usually the only difference, we check them manually before calling memcmp. */
+        if (   pTempFile->cwcPath == cwcFilename
+            && pTempFile->pwszPath[cwcFilename - 1] == pwszFilename[cwcFilename - 1]
+            && pTempFile->pwszPath[cwcFilename - 2] == pwszFilename[cwcFilename - 2]
+            && kHlpMemComp(pTempFile->pwszPath, pwszFilename, cwcFilename) == 0)
+            break;
+    }
+
+    /*
+     * Create a new temporary file instance if not found.
+     */
+    if (pTempFile == NULL)
+    {
+        KSIZE cbFilename;
+
+        switch (dwCreationDisposition)
+        {
+            case CREATE_ALWAYS:
+            case OPEN_ALWAYS:
+                dwErr = NO_ERROR;
+                break;
+
+            case CREATE_NEW:
+                kHlpAssertFailed();
+                SetLastError(ERROR_ALREADY_EXISTS);
+                return INVALID_HANDLE_VALUE;
+
+            case OPEN_EXISTING:
+            case TRUNCATE_EXISTING:
+                kHlpAssertFailed();
+                SetLastError(ERROR_FILE_NOT_FOUND);
+                return INVALID_HANDLE_VALUE;
+
+            default:
+                kHlpAssertFailed();
+                SetLastError(ERROR_INVALID_PARAMETER);
+                return INVALID_HANDLE_VALUE;
+        }
+
+        cbFilename = (cwcFilename + 1) * sizeof(wchar_t);
+        pTempFile = (PKWFSTEMPFILE)kHlpAlloc(sizeof(*pTempFile) + cbFilename);
+        if (pTempFile)
+        {
+            pTempFile->cwcPath          = (KU16)cwcFilename;
+            pTempFile->cbFile           = 0;
+            pTempFile->cbFileAllocated  = 0;
+            pTempFile->cActiveHandles   = 0;
+            pTempFile->cMappings        = 0;
+            pTempFile->cSegs            = 0;
+            pTempFile->paSegs           = NULL;
+            pTempFile->pwszPath         = (wchar_t const *)kHlpMemCopy(pTempFile + 1, pwszFilename, cbFilename);
+
+            pTempFile->pNext = g_Sandbox.pTempFileHead;
+            g_Sandbox.pTempFileHead = pTempFile;
+            KWFS_LOG(("kwFsTempFileCreateW: Created new temporary file '%ls'\n", pwszFilename));
+        }
+        else
+        {
+            KWFS_LOG(("kwFsTempFileCreateW: Out of memory!\n"));
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            return INVALID_HANDLE_VALUE;
+        }
+    }
+    else
+    {
+        switch (dwCreationDisposition)
+        {
+            case OPEN_EXISTING:
+                dwErr = NO_ERROR;
+                break;
+            case OPEN_ALWAYS:
+                dwErr = ERROR_ALREADY_EXISTS ;
+                break;
+
+            case TRUNCATE_EXISTING:
+            case CREATE_ALWAYS:
+                kHlpAssertFailed();
+                pTempFile->cbFile = 0;
+                dwErr = ERROR_ALREADY_EXISTS;
+                break;
+
+            case CREATE_NEW:
+                kHlpAssertFailed();
+                SetLastError(ERROR_FILE_EXISTS);
+                return INVALID_HANDLE_VALUE;
+
+            default:
+                kHlpAssertFailed();
+                SetLastError(ERROR_INVALID_PARAMETER);
+                return INVALID_HANDLE_VALUE;
+        }
+    }
+
+    /*
+     * Create a handle to the temporary file.
+     */
+    hFile = kwFsTempFileCreateHandle(pTempFile, dwDesiredAccess, K_FALSE /*fMapping*/);
+    if (hFile != INVALID_HANDLE_VALUE)
+        SetLastError(dwErr);
+    return hFile;
+}
+
+#endif /* WITH_TEMP_MEMORY_FILES */
+
+
+/**
+ * Checks if the file extension indicates that the file/dir is something we
+ * ought to cache.
+ *
+ * @returns K_TRUE if cachable, K_FALSE if not.
+ * @param   pszExt              The kHlpGetExt result.
+ * @param   fAttrQuery          Set if it's for an attribute query, clear if for
+ *                              file creation.
+ */
+static KBOOL kwFsIsCachableExtensionA(const char *pszExt, KBOOL fAttrQuery)
+{
+    char const chFirst = *pszExt;
+
+    /* C++ header without an extension or a directory. */
+    if (chFirst == '\0')
+    {
+        /** @todo exclude temporary files...  */
+        return K_TRUE;
+    }
+
+    /* C Header: .h */
+    if (chFirst == 'h' || chFirst == 'H')
+    {
+        char        chThird;
+        char const  chSecond = pszExt[1];
+        if (chSecond == '\0')
+            return K_TRUE;
+        chThird = pszExt[2];
+
+        /* C++ Header: .hpp, .hxx */
+        if (   (chSecond == 'p' || chSecond == 'P')
+            && (chThird  == 'p' || chThird  == 'P')
+            && pszExt[3] == '\0')
+            return K_TRUE;
+        if (   (chSecond == 'x' || chSecond == 'X')
+            && (chThird  == 'x' || chThird  == 'X')
+            && pszExt[3] == '\0')
+            return K_TRUE;
+
+    }
+    /* Misc starting with i. */
+    else if (chFirst == 'i' || chFirst == 'I')
+    {
+        char const chSecond = pszExt[1];
+        if (chSecond != '\0')
+        {
+            if (chSecond == 'n' || chSecond == 'N')
+            {
+                char const chThird = pszExt[2];
+
+                /* C++ inline header: .inl */
+                if (   (chThird == 'l' || chThird == 'L')
+                    && pszExt[3] == '\0')
+                    return K_TRUE;
+
+                /* Assembly include file: .inc */
+                if (   (chThird == 'c' || chThird == 'C')
+                    && pszExt[3] == '\0')
+                    return K_TRUE;
+            }
+        }
+    }
+    else if (fAttrQuery)
+    {
+        /* Dynamic link library: .dll */
+        if (chFirst == 'd' || chFirst == 'D')
+        {
+            char const chSecond = pszExt[1];
+            if (chSecond == 'l' || chSecond == 'L')
+            {
+                char const chThird = pszExt[2];
+                if (chThird == 'l' || chThird == 'L')
+                    return K_TRUE;
+            }
+        }
+        /* Executable file: .exe */
+        else if (chFirst == 'e' || chFirst == 'E')
+        {
+            char const chSecond = pszExt[1];
+            if (chSecond == 'x' || chSecond == 'X')
+            {
+                char const chThird = pszExt[2];
+                if (chThird == 'e' || chThird == 'e')
+                    return K_TRUE;
+            }
+        }
+    }
+
+    return K_FALSE;
+}
+
+
+/**
+ * Checks if the extension of the given UTF-16 path indicates that the file/dir
+ * should be cached.
+ *
+ * @returns K_TRUE if cachable, K_FALSE if not.
+ * @param   pwszPath            The UTF-16 path to examine.
+ * @param   fAttrQuery          Set if it's for an attribute query, clear if for
+ *                              file creation.
+ */
+static KBOOL kwFsIsCachablePathExtensionW(const wchar_t *pwszPath, KBOOL fAttrQuery)
+{
+    /*
+     * Extract the extension, check that it's in the applicable range, roughly
+     * convert it to ASCII/ANSI, and feed it to kwFsIsCachableExtensionA for
+     * the actual check.  This avoids a lot of code duplication.
+     */
+    wchar_t         wc;
+    char            szExt[4];
+    KSIZE           cwcExt;
+    wchar_t const  *pwszExt = kwFsPathGetExtW(pwszPath, &cwcExt);
+    switch (cwcExt)
+    {
+        case 3: if ((wchar_t)(szExt[2] = (char)(wc = pwszExt[2])) == wc) { /*likely*/ } else break;
+        case 2: if ((wchar_t)(szExt[1] = (char)(wc = pwszExt[1])) == wc) { /*likely*/ } else break;
+        case 1: if ((wchar_t)(szExt[0] = (char)(wc = pwszExt[0])) == wc) { /*likely*/ } else break;
+        case 0:
+            szExt[cwcExt] = '\0';
+            return kwFsIsCachableExtensionA(szExt, fAttrQuery);
+    }
+    return K_FALSE;
+}
+
+
+
+/**
+ * Creates a new
+ *
+ * @returns
+ * @param   pFsObj          .
+ * @param   pwszFilename    .
+ */
+static PKFSWCACHEDFILE kwFsObjCacheNewFile(PKFSOBJ pFsObj)
+{
+    HANDLE                  hFile;
+    MY_IO_STATUS_BLOCK      Ios;
+    MY_OBJECT_ATTRIBUTES    ObjAttr;
+    MY_UNICODE_STRING       UniStr;
+    MY_NTSTATUS             rcNt;
+
+    /*
+     * Open the file relative to the parent directory.
+     */
+    kHlpAssert(pFsObj->bObjType == KFSOBJ_TYPE_FILE);
+    kHlpAssert(pFsObj->pParent);
+    kHlpAssertReturn(pFsObj->pParent->hDir != INVALID_HANDLE_VALUE, NULL);
+
+    Ios.Information = -1;
+    Ios.u.Status    = -1;
+
+    UniStr.Buffer        = (wchar_t *)pFsObj->pwszName;
+    UniStr.Length        = (USHORT)(pFsObj->cwcName * sizeof(wchar_t));
+    UniStr.MaximumLength = UniStr.Length + sizeof(wchar_t);
+
+    MyInitializeObjectAttributes(&ObjAttr, &UniStr, OBJ_CASE_INSENSITIVE, pFsObj->pParent->hDir, NULL /*pSecAttr*/);
+
+    rcNt = g_pfnNtCreateFile(&hFile,
+                             GENERIC_READ | SYNCHRONIZE,
+                             &ObjAttr,
+                             &Ios,
+                             NULL, /*cbFileInitialAlloc */
+                             FILE_ATTRIBUTE_NORMAL,
+                             FILE_SHARE_READ,
+                             FILE_OPEN,
+                             FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+                             NULL, /*pEaBuffer*/
+                             0);   /*cbEaBuffer*/
+    if (MY_NT_SUCCESS(rcNt))
+    {
+        /*
+         * Read the whole file into memory.
+         */
+        LARGE_INTEGER cbFile;
+        if (GetFileSizeEx(hFile, &cbFile))
+        {
+            if (   cbFile.QuadPart >= 0
+                && cbFile.QuadPart < 16*1024*1024)
+            {
+                KU32 cbCache = (KU32)cbFile.QuadPart;
+                KU8 *pbCache = (KU8 *)kHlpAlloc(cbCache);
+                if (pbCache)
+                {
+                    DWORD cbActually = 0;
+                    if (   ReadFile(hFile, pbCache, cbCache, &cbActually, NULL)
+                        && cbActually == cbCache)
+                    {
+                        LARGE_INTEGER offZero;
+                        offZero.QuadPart = 0;
+                        if (SetFilePointerEx(hFile, offZero, NULL /*poffNew*/, FILE_BEGIN))
+                        {
+                            /*
+                             * Create the cached file object.
+                             */
+                            PKFSWCACHEDFILE pCachedFile;
+                            KU32            cbPath = pFsObj->cchParent + pFsObj->cchName + 2;
+                            pCachedFile = (PKFSWCACHEDFILE)kFsCacheObjAddUserData(g_pFsCache, pFsObj, KW_DATA_KEY_CACHED_FILE,
+                                                                                  sizeof(*pCachedFile) + cbPath);
+                            if (pCachedFile)
+                            {
+                                pCachedFile->hCached  = hFile;
+                                pCachedFile->cbCached = cbCache;
+                                pCachedFile->pbCached = pbCache;
+                                pCachedFile->pFsObj   = pFsObj;
+                                kFsCacheObjGetFullPathA(pFsObj, pCachedFile->szPath, cbPath, '/');
+                                kFsCacheObjRetain(pFsObj);
+                                return pCachedFile;
+                            }
+
+                            KWFS_LOG(("Failed to allocate KFSWCACHEDFILE structure!\n"));
+                        }
+                        else
+                            KWFS_LOG(("Failed to seek to start of cached file! err=%u\n", GetLastError()));
+                    }
+                    else
+                        KWFS_LOG(("Failed to read %#x bytes into cache! err=%u cbActually=%#x\n",
+                                  cbCache, GetLastError(), cbActually));
+                    kHlpFree(pbCache);
+                }
+                else
+                    KWFS_LOG(("Failed to allocate %#x bytes for cache!\n", cbCache));
+            }
+            else
+                KWFS_LOG(("File to big to cache! %#llx\n", cbFile.QuadPart));
+        }
+        else
+            KWFS_LOG(("File to get file size! err=%u\n", GetLastError()));
+        g_pfnNtClose(hFile);
+    }
+    else
+        KWFS_LOG(("Error opening '%ls' for caching: %#x\n", pFsObj->pwszName, rcNt));
+    return NULL;
+}
+
+
+/**
+ * Kernel32 - Common code for CreateFileW and CreateFileA.
+ */
+static KBOOL kwFsObjCacheCreateFile(PKFSOBJ pFsObj, DWORD dwDesiredAccess, BOOL fInheritHandle, HANDLE *phFile)
+{
+    *phFile = INVALID_HANDLE_VALUE;
+    kHlpAssert(pFsObj->fHaveStats);
+
+    /*
+     * At the moment we only handle existing files.
+     */
+    if (pFsObj->bObjType == KFSOBJ_TYPE_FILE)
+    {
+        PKFSWCACHEDFILE pCachedFile = (PKFSWCACHEDFILE)kFsCacheObjGetUserData(g_pFsCache, pFsObj, KW_DATA_KEY_CACHED_FILE);
+        if (   pCachedFile != NULL
+            || (pCachedFile = kwFsObjCacheNewFile(pFsObj)) != NULL)
+        {
+            HANDLE hProcSelf = GetCurrentProcess();
+            if (DuplicateHandle(hProcSelf, pCachedFile->hCached,
+                                hProcSelf, phFile,
+                                dwDesiredAccess, fInheritHandle,
+                                0 /*dwOptions*/))
+            {
+                /*
+                 * Create handle table entry for the duplicate handle.
+                 */
+                PKWHANDLE pHandle = (PKWHANDLE)kHlpAlloc(sizeof(*pHandle));
+                if (pHandle)
+                {
+                    pHandle->enmType            = KWHANDLETYPE_FSOBJ_READ_CACHE;
+                    pHandle->offFile            = 0;
+                    pHandle->hHandle            = *phFile;
+                    pHandle->dwDesiredAccess    = dwDesiredAccess;
+                    pHandle->u.pCachedFile      = pCachedFile;
+                    if (kwSandboxHandleTableEnter(&g_Sandbox, pHandle))
+                        return K_TRUE;
+
+                    kHlpFree(pHandle);
+                }
+                else
+                    KWFS_LOG(("Out of memory for handle!\n"));
+
+                CloseHandle(*phFile);
+                *phFile = INVALID_HANDLE_VALUE;
+            }
+            else
+                KWFS_LOG(("DuplicateHandle failed! err=%u\n", GetLastError()));
+        }
+    }
+    /** @todo Deal with non-existing files if it becomes necessary (it's not for VS2010). */
+
+    /* Do fallback, please. */
+    return K_FALSE;
+}
+
+
+/** Kernel32 - CreateFileA */
+static HANDLE WINAPI kwSandbox_Kernel32_CreateFileA(LPCSTR pszFilename, DWORD dwDesiredAccess, DWORD dwShareMode,
+                                                    LPSECURITY_ATTRIBUTES pSecAttrs, DWORD dwCreationDisposition,
+                                                    DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
+{
+    HANDLE hFile;
+    if (dwCreationDisposition == FILE_OPEN_IF)
+    {
+        if (   dwDesiredAccess == GENERIC_READ
+            || dwDesiredAccess == FILE_GENERIC_READ)
+        {
+            if (dwShareMode & FILE_SHARE_READ)
+            {
+                if (   !pSecAttrs
+                    || (   pSecAttrs->nLength == sizeof(*pSecAttrs)
+                        && pSecAttrs->lpSecurityDescriptor == NULL ) )
+                {
+                    const char *pszExt = kHlpGetExt(pszFilename);
+                    if (kwFsIsCachableExtensionA(pszExt, K_FALSE /*fAttrQuery*/))
+                    {
+                        KFSLOOKUPERROR enmError;
+                        PKFSOBJ pFsObj = kFsCacheLookupNoMissingA(g_pFsCache, pszFilename, &enmError);
+                        if (pFsObj)
+                        {
+                            KBOOL fRc = kwFsObjCacheCreateFile(pFsObj, dwDesiredAccess, pSecAttrs && pSecAttrs->bInheritHandle,
+                                                               &hFile);
+                            kFsCacheObjRelease(g_pFsCache, pFsObj);
+                            if (fRc)
+                            {
+                                KWFS_LOG(("CreateFileA(%s) -> %p [cached]\n", pszFilename, hFile));
+                                return hFile;
+                            }
+                        }
+
+                        /* fallback */
+                        hFile = CreateFileA(pszFilename, dwDesiredAccess, dwShareMode, pSecAttrs,
+                                            dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
+                        KWFS_LOG(("CreateFileA(%s) -> %p (err=%u) [fallback]\n", pszFilename, hFile, GetLastError()));
+                        return hFile;
+                    }
+                }
+            }
+        }
+    }
+
+    hFile = CreateFileA(pszFilename, dwDesiredAccess, dwShareMode, pSecAttrs,
+                        dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
+    KWFS_LOG(("CreateFileA(%s) -> %p\n", pszFilename, hFile));
+    return hFile;
+}
+
+
+/** Kernel32 - CreateFileW */
+static HANDLE WINAPI kwSandbox_Kernel32_CreateFileW(LPCWSTR pwszFilename, DWORD dwDesiredAccess, DWORD dwShareMode,
+                                                    LPSECURITY_ATTRIBUTES pSecAttrs, DWORD dwCreationDisposition,
+                                                    DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
+{
+    HANDLE hFile;
+
+#ifdef WITH_TEMP_MEMORY_FILES
+    /* First check for temporary files (cl.exe only). */
+    if (   g_Sandbox.pTool->u.Sandboxed.enmHint == KWTOOLHINT_VISUAL_CPP_CL
+        && !(dwFlagsAndAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE | FILE_FLAG_BACKUP_SEMANTICS))
+        && !(dwDesiredAccess & (GENERIC_EXECUTE | FILE_EXECUTE))
+        && kwFsIsClTempFileW(pwszFilename))
+    {
+        hFile = kwFsTempFileCreateW(pwszFilename, dwDesiredAccess, dwCreationDisposition);
+        KWFS_LOG(("CreateFileW(%ls) -> %p [temp]\n", pwszFilename, hFile));
+        return hFile;
+    }
+#endif
+
+    /* Then check for include files and similar. */
+    if (dwCreationDisposition == FILE_OPEN_IF)
+    {
+        if (   dwDesiredAccess == GENERIC_READ
+            || dwDesiredAccess == FILE_GENERIC_READ)
+        {
+            if (dwShareMode & FILE_SHARE_READ)
+            {
+                if (   !pSecAttrs
+                    || (   pSecAttrs->nLength == sizeof(*pSecAttrs)
+                        && pSecAttrs->lpSecurityDescriptor == NULL ) )
+                {
+                    if (kwFsIsCachablePathExtensionW(pwszFilename, K_FALSE /*fAttrQuery*/))
+                    {
+                        /** @todo rewrite to pure UTF-16. */
+                        char szTmp[2048];
+                        KSIZE cch = kwUtf16ToStr(pwszFilename, szTmp, sizeof(szTmp));
+                        if (cch < sizeof(szTmp))
+                            return kwSandbox_Kernel32_CreateFileA(szTmp, dwDesiredAccess, dwShareMode, pSecAttrs,
+                                                                  dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
+                    }
+                }
+                else
+                    KWFS_LOG(("CreateFileW: incompatible security attributes (nLength=%#x pDesc=%p)\n",
+                              pSecAttrs->nLength, pSecAttrs->lpSecurityDescriptor));
+            }
+            else
+                KWFS_LOG(("CreateFileW: incompatible sharing mode %#x\n", dwShareMode));
+        }
+        else
+            KWFS_LOG(("CreateFileW: incompatible desired access %#x\n", dwDesiredAccess));
+    }
+    else
+        KWFS_LOG(("CreateFileW: incompatible disposition %u\n", dwCreationDisposition));
+    hFile = CreateFileW(pwszFilename, dwDesiredAccess, dwShareMode, pSecAttrs,
+                        dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
+    KWFS_LOG(("CreateFileW(%ls) -> %p\n", pwszFilename, hFile));
+    return hFile;
+}
+
+
+/** Kernel32 - SetFilePointer */
+static DWORD WINAPI kwSandbox_Kernel32_SetFilePointer(HANDLE hFile, LONG cbMove, PLONG pcbMoveHi, DWORD dwMoveMethod)
+{
+    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+    if (idxHandle < g_Sandbox.cHandles)
+    {
+        PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
+        if (pHandle != NULL)
+        {
+            KU32 cbFile;
+            KI64 offMove = pcbMoveHi ? ((KI64)*pcbMoveHi << 32) | cbMove : cbMove;
+            switch (pHandle->enmType)
+            {
+                case KWHANDLETYPE_FSOBJ_READ_CACHE:
+                    cbFile = pHandle->u.pCachedFile->cbCached;
+                    break;
+#ifdef WITH_TEMP_MEMORY_FILES
+                case KWHANDLETYPE_TEMP_FILE:
+                    cbFile = pHandle->u.pTempFile->cbFile;
+                    break;
+                case KWHANDLETYPE_TEMP_FILE_MAPPING:
+#endif
+                default:
+                    kHlpAssertFailed();
+                    SetLastError(ERROR_INVALID_FUNCTION);
+                    return INVALID_SET_FILE_POINTER;
+            }
+
+            switch (dwMoveMethod)
+            {
+                case FILE_BEGIN:
+                    break;
+                case FILE_CURRENT:
+                    offMove += pHandle->offFile;
+                    break;
+                case FILE_END:
+                    offMove += cbFile;
+                    break;
+                default:
+                    KWFS_LOG(("SetFilePointer(%p) - invalid seek method %u! [cached]\n", hFile));
+                    SetLastError(ERROR_INVALID_PARAMETER);
+                    return INVALID_SET_FILE_POINTER;
+            }
+            if (offMove >= 0)
+            {
+                if (offMove >= (KSSIZE)cbFile)
+                {
+                    /* For read-only files, seeking beyond the end isn't useful to us, so clamp it. */
+                    if (pHandle->enmType != KWHANDLETYPE_TEMP_FILE)
+                        offMove = (KSSIZE)cbFile;
+                    /* For writable files, seeking beyond the end is fine, but check that we've got
+                       the type range for the request. */
+                    else if (((KU64)offMove & KU32_MAX) != (KU64)offMove)
+                    {
+                        kHlpAssertMsgFailed(("%#llx\n", offMove));
+                        SetLastError(ERROR_SEEK);
+                        return INVALID_SET_FILE_POINTER;
+                    }
+                }
+                pHandle->offFile = (KU32)offMove;
+            }
+            else
+            {
+                KWFS_LOG(("SetFilePointer(%p) - negative seek! [cached]\n", hFile));
+                SetLastError(ERROR_NEGATIVE_SEEK);
+                return INVALID_SET_FILE_POINTER;
+            }
+            if (pcbMoveHi)
+                *pcbMoveHi = (KU64)offMove >> 32;
+            KWFS_LOG(("SetFilePointer(%p) -> %#llx [cached]\n", hFile, offMove));
+            SetLastError(NO_ERROR);
+            return (KU32)offMove;
+        }
+    }
+    KWFS_LOG(("SetFilePointer(%p)\n", hFile));
+    return SetFilePointer(hFile, cbMove, pcbMoveHi, dwMoveMethod);
+}
+
+
+/** Kernel32 - SetFilePointerEx */
+static BOOL WINAPI kwSandbox_Kernel32_SetFilePointerEx(HANDLE hFile, LARGE_INTEGER offMove, PLARGE_INTEGER poffNew,
+                                                       DWORD dwMoveMethod)
+{
+    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+    if (idxHandle < g_Sandbox.cHandles)
+    {
+        PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
+        if (pHandle != NULL)
+        {
+            KI64 offMyMove = offMove.QuadPart;
+            KU32 cbFile;
+            switch (pHandle->enmType)
+            {
+                case KWHANDLETYPE_FSOBJ_READ_CACHE:
+                    cbFile = pHandle->u.pCachedFile->cbCached;
+                    break;
+#ifdef WITH_TEMP_MEMORY_FILES
+                case KWHANDLETYPE_TEMP_FILE:
+                    cbFile = pHandle->u.pTempFile->cbFile;
+                    break;
+                case KWHANDLETYPE_TEMP_FILE_MAPPING:
+#endif
+                default:
+                    kHlpAssertFailed();
+                    SetLastError(ERROR_INVALID_FUNCTION);
+                    return INVALID_SET_FILE_POINTER;
+            }
+
+            switch (dwMoveMethod)
+            {
+                case FILE_BEGIN:
+                    break;
+                case FILE_CURRENT:
+                    offMyMove += pHandle->offFile;
+                    break;
+                case FILE_END:
+                    offMyMove += cbFile;
+                    break;
+                default:
+                    KWFS_LOG(("SetFilePointer(%p) - invalid seek method %u! [cached]\n", hFile));
+                    SetLastError(ERROR_INVALID_PARAMETER);
+                    return INVALID_SET_FILE_POINTER;
+            }
+            if (offMyMove >= 0)
+            {
+                if (offMyMove >= (KSSIZE)cbFile)
+                {
+                    /* For read-only files, seeking beyond the end isn't useful to us, so clamp it. */
+                    if (pHandle->enmType != KWHANDLETYPE_TEMP_FILE)
+                        offMyMove = (KSSIZE)cbFile;
+                    /* For writable files, seeking beyond the end is fine, but check that we've got
+                       the type range for the request. */
+                    else if (((KU64)offMyMove & KU32_MAX) != (KU64)offMyMove)
+                    {
+                        kHlpAssertMsgFailed(("%#llx\n", offMyMove));
+                        SetLastError(ERROR_SEEK);
+                        return INVALID_SET_FILE_POINTER;
+                    }
+                }
+                pHandle->offFile = (KU32)offMyMove;
+            }
+            else
+            {
+                KWFS_LOG(("SetFilePointerEx(%p) - negative seek! [cached]\n", hFile));
+                SetLastError(ERROR_NEGATIVE_SEEK);
+                return INVALID_SET_FILE_POINTER;
+            }
+            if (poffNew)
+                poffNew->QuadPart = offMyMove;
+            KWFS_LOG(("SetFilePointerEx(%p) -> TRUE, %#llx [cached]\n", hFile, offMyMove));
+            return TRUE;
+        }
+    }
+    KWFS_LOG(("SetFilePointerEx(%p)\n", hFile));
+    return SetFilePointerEx(hFile, offMove, poffNew, dwMoveMethod);
+}
+
+
+/** Kernel32 - ReadFile */
+static BOOL WINAPI kwSandbox_Kernel32_ReadFile(HANDLE hFile, LPVOID pvBuffer, DWORD cbToRead, LPDWORD pcbActuallyRead,
+                                               LPOVERLAPPED pOverlapped)
+{
+    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+    if (idxHandle < g_Sandbox.cHandles)
+    {
+        PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
+        if (pHandle != NULL)
+        {
+            switch (pHandle->enmType)
+            {
+                case KWHANDLETYPE_FSOBJ_READ_CACHE:
+                {
+                    PKFSWCACHEDFILE pCachedFile = pHandle->u.pCachedFile;
+                    KU32            cbActually = pCachedFile->cbCached - pHandle->offFile;
+                    if (cbActually > cbToRead)
+                        cbActually = cbToRead;
+                    else if (cbActually < cbToRead)                                            // debug debug debug
+                        kHlpMemSet((KU8 *)pvBuffer + cbActually, '\0', cbToRead - cbActually); // debug debug debug
+
+#ifdef WITH_HASH_MD5_CACHE
+                    if (g_Sandbox.pHashHead)
+                    {
+                        g_Sandbox.LastHashRead.pCachedFile = pCachedFile;
+                        g_Sandbox.LastHashRead.offRead     = pHandle->offFile;
+                        g_Sandbox.LastHashRead.cbRead      = cbActually;
+                        g_Sandbox.LastHashRead.pvRead      = pvBuffer;
+                    }
+#endif
+
+                    kHlpMemCopy(pvBuffer, &pCachedFile->pbCached[pHandle->offFile], cbActually);
+                    pHandle->offFile += cbActually;
+
+                    kHlpAssert(!pOverlapped); kHlpAssert(pcbActuallyRead);
+                    *pcbActuallyRead = cbActually;
+
+                    KWFS_LOG(("ReadFile(%p,,%#x) -> TRUE, %#x bytes [cached]\n", hFile, cbToRead, cbActually));
+                    return TRUE;
+                }
+
+#ifdef WITH_TEMP_MEMORY_FILES
+                case KWHANDLETYPE_TEMP_FILE:
+                {
+                    PKWFSTEMPFILE   pTempFile  = pHandle->u.pTempFile;
+                    KU32            cbActually;
+                    if (pHandle->offFile < pTempFile->cbFile)
+                    {
+                        cbActually = pTempFile->cbFile - pHandle->offFile;
+                        if (cbActually > cbToRead)
+                            cbActually = cbToRead;
+
+                        /* Copy the data. */
+                        if (cbActually > 0)
+                        {
+                            KU32                    cbLeft;
+                            KU32                    offSeg;
+                            KWFSTEMPFILESEG const  *paSegs = pTempFile->paSegs;
+
+                            /* Locate the segment containing the byte at offFile. */
+                            KU32 iSeg   = pTempFile->cSegs - 1;
+                            kHlpAssert(pTempFile->cSegs > 0);
+                            while (paSegs[iSeg].offData > pHandle->offFile)
+                                iSeg--;
+
+                            /* Copy out the data. */
+                            cbLeft = cbActually;
+                            offSeg = (pHandle->offFile - paSegs[iSeg].offData);
+                            for (;;)
+                            {
+                                KU32 cbAvail = paSegs[iSeg].cbDataAlloc - offSeg;
+                                if (cbAvail >= cbLeft)
+                                {
+                                    kHlpMemCopy(pvBuffer, &paSegs[iSeg].pbData[offSeg], cbLeft);
+                                    break;
+                                }
+
+                                pvBuffer = kHlpMemPCopy(pvBuffer, &paSegs[iSeg].pbData[offSeg], cbAvail);
+                                cbLeft  -= cbAvail;
+                                offSeg   = 0;
+                                iSeg++;
+                                kHlpAssert(iSeg < pTempFile->cSegs);
+                            }
+
+                            /* Update the file offset. */
+                            pHandle->offFile += cbActually;
+                        }
+                    }
+                    /* Read does not commit file space, so return zero bytes. */
+                    else
+                        cbActually = 0;
+
+                    kHlpAssert(!pOverlapped); kHlpAssert(pcbActuallyRead);
+                    *pcbActuallyRead = cbActually;
+
+                    KWFS_LOG(("ReadFile(%p,,%#x) -> TRUE, %#x bytes [temp]\n", hFile, cbToRead, (KU32)cbActually));
+                    return TRUE;
+                }
+
+                case KWHANDLETYPE_TEMP_FILE_MAPPING:
+#endif /* WITH_TEMP_MEMORY_FILES */
+                default:
+                    kHlpAssertFailed();
+                    SetLastError(ERROR_INVALID_FUNCTION);
+                    *pcbActuallyRead = 0;
+                    return FALSE;
+            }
+        }
+    }
+
+    KWFS_LOG(("ReadFile(%p)\n", hFile));
+    return ReadFile(hFile, pvBuffer, cbToRead, pcbActuallyRead, pOverlapped);
+}
+
+
+/** Kernel32 - ReadFileEx */
+static BOOL WINAPI kwSandbox_Kernel32_ReadFileEx(HANDLE hFile, LPVOID pvBuffer, DWORD cbToRead, LPOVERLAPPED pOverlapped,
+                                                 LPOVERLAPPED_COMPLETION_ROUTINE pfnCompletionRoutine)
+{
+    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+    if (idxHandle < g_Sandbox.cHandles)
+    {
+        PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
+        if (pHandle != NULL)
+        {
+            kHlpAssertFailed();
+        }
+    }
+
+    KWFS_LOG(("ReadFile(%p)\n", hFile));
+    return ReadFileEx(hFile, pvBuffer, cbToRead, pOverlapped, pfnCompletionRoutine);
+}
+
+#ifdef WITH_TEMP_MEMORY_FILES
+
+static KBOOL kwFsTempFileEnsureSpace(PKWFSTEMPFILE pTempFile, KU32 offFile, KU32 cbNeeded)
+{
+    KU32 cbMinFile = offFile + cbNeeded;
+    if (cbMinFile >= offFile)
+    {
+        /* Calc how much space we've already allocated and  */
+        if (cbMinFile <= pTempFile->cbFileAllocated)
+            return K_TRUE;
+
+        /* Grow the file. */
+        if (cbMinFile <= KWFS_TEMP_FILE_MAX)
+        {
+            int  rc;
+            KU32 cSegs    = pTempFile->cSegs;
+            KU32 cbNewSeg = cbMinFile > 4*1024*1024 ? 256*1024 : 4*1024*1024;
+            do
+            {
+                /* grow the segment array? */
+                if ((cSegs % 16) == 0)
+                {
+                    void *pvNew = kHlpRealloc(pTempFile->paSegs, (cSegs + 16) * sizeof(pTempFile->paSegs[0]));
+                    if (!pvNew)
+                        return K_FALSE;
+                    pTempFile->paSegs = (PKWFSTEMPFILESEG)pvNew;
+                }
+
+                /* Use page alloc here to simplify mapping later. */
+                rc = kHlpPageAlloc((void **)&pTempFile->paSegs[cSegs].pbData, cbNewSeg, KPROT_READWRITE, K_FALSE);
+                if (rc == 0)
+                { /* likely */ }
+                else
+                {
+                    cbNewSeg = 64*1024;
+                    rc = kHlpPageAlloc((void **)&pTempFile->paSegs[cSegs].pbData, cbNewSeg, KPROT_READWRITE, K_FALSE);
+                    if (rc != 0)
+                    {
+                        kHlpAssertFailed();
+                        return K_FALSE;
+                    }
+                }
+                pTempFile->paSegs[cSegs].offData     = pTempFile->cbFileAllocated;
+                pTempFile->paSegs[cSegs].cbDataAlloc = cbNewSeg;
+                pTempFile->cbFileAllocated          += cbNewSeg;
+                pTempFile->cSegs                     = ++cSegs;
+
+            } while (pTempFile->cbFileAllocated < cbMinFile);
+
+            return K_TRUE;
+        }
+    }
+
+    kHlpAssertMsgFailed(("Out of bounds offFile=%#x + cbNeeded=%#x = %#x\n", offFile, cbNeeded, offFile + cbNeeded));
+    return K_FALSE;
+}
+
+
+/** Kernel32 - WriteFile */
+static BOOL WINAPI kwSandbox_Kernel32_WriteFile(HANDLE hFile, LPCVOID pvBuffer, DWORD cbToWrite, LPDWORD pcbActuallyWritten,
+                                                LPOVERLAPPED pOverlapped)
+{
+    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+    if (idxHandle < g_Sandbox.cHandles)
+    {
+        PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
+        if (pHandle != NULL)
+        {
+            switch (pHandle->enmType)
+            {
+                case KWHANDLETYPE_TEMP_FILE:
+                {
+                    PKWFSTEMPFILE   pTempFile  = pHandle->u.pTempFile;
+
+                    kHlpAssert(!pOverlapped);
+                    kHlpAssert(pcbActuallyWritten);
+
+                    if (kwFsTempFileEnsureSpace(pTempFile, pHandle->offFile, cbToWrite))
+                    {
+                        KU32                    cbLeft;
+                        KU32                    offSeg;
+
+                        /* Locate the segment containing the byte at offFile. */
+                        KWFSTEMPFILESEG const  *paSegs = pTempFile->paSegs;
+                        KU32                    iSeg   = pTempFile->cSegs - 1;
+                        kHlpAssert(pTempFile->cSegs > 0);
+                        while (paSegs[iSeg].offData > pHandle->offFile)
+                            iSeg--;
+
+                        /* Copy in the data. */
+                        cbLeft = cbToWrite;
+                        offSeg = (pHandle->offFile - paSegs[iSeg].offData);
+                        for (;;)
+                        {
+                            KU32 cbAvail = paSegs[iSeg].cbDataAlloc - offSeg;
+                            if (cbAvail >= cbLeft)
+                            {
+                                kHlpMemCopy(&paSegs[iSeg].pbData[offSeg], pvBuffer, cbLeft);
+                                break;
+                            }
+
+                            kHlpMemCopy(&paSegs[iSeg].pbData[offSeg], pvBuffer, cbAvail);
+                            pvBuffer = (KU8 const *)pvBuffer + cbAvail;
+                            cbLeft  -= cbAvail;
+                            offSeg   = 0;
+                            iSeg++;
+                            kHlpAssert(iSeg < pTempFile->cSegs);
+                        }
+
+                        /* Update the file offset. */
+                        pHandle->offFile += cbToWrite;
+                        if (pHandle->offFile > pTempFile->cbFile)
+                            pTempFile->cbFile = pHandle->offFile;
+
+                        *pcbActuallyWritten = cbToWrite;
+                        KWFS_LOG(("WriteFile(%p,,%#x) -> TRUE [temp]\n", hFile, cbToWrite));
+                        return TRUE;
+                    }
+
+                    kHlpAssertFailed();
+                    *pcbActuallyWritten = 0;
+                    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                    return FALSE;
+                }
+
+                case KWHANDLETYPE_FSOBJ_READ_CACHE:
+                    kHlpAssertFailed();
+                    SetLastError(ERROR_ACCESS_DENIED);
+                    *pcbActuallyWritten = 0;
+                    return FALSE;
+
+                default:
+                case KWHANDLETYPE_TEMP_FILE_MAPPING:
+                    kHlpAssertFailed();
+                    SetLastError(ERROR_INVALID_FUNCTION);
+                    *pcbActuallyWritten = 0;
+                    return FALSE;
+            }
+        }
+    }
+
+    KWFS_LOG(("WriteFile(%p)\n", hFile));
+    return WriteFile(hFile, pvBuffer, cbToWrite, pcbActuallyWritten, pOverlapped);
+}
+
+
+/** Kernel32 - WriteFileEx */
+static BOOL WINAPI kwSandbox_Kernel32_WriteFileEx(HANDLE hFile, LPCVOID pvBuffer, DWORD cbToWrite, LPOVERLAPPED pOverlapped,
+                                                  LPOVERLAPPED_COMPLETION_ROUTINE pfnCompletionRoutine)
+{
+    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+    if (idxHandle < g_Sandbox.cHandles)
+    {
+        PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
+        if (pHandle != NULL)
+        {
+            kHlpAssertFailed();
+        }
+    }
+
+    KWFS_LOG(("WriteFileEx(%p)\n", hFile));
+    return WriteFileEx(hFile, pvBuffer, cbToWrite, pOverlapped, pfnCompletionRoutine);
+}
+
+
+/** Kernel32 - SetEndOfFile; */
+static BOOL WINAPI kwSandbox_Kernel32_SetEndOfFile(HANDLE hFile)
+{
+    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+    if (idxHandle < g_Sandbox.cHandles)
+    {
+        PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
+        if (pHandle != NULL)
+        {
+            switch (pHandle->enmType)
+            {
+                case KWHANDLETYPE_TEMP_FILE:
+                {
+                    PKWFSTEMPFILE   pTempFile  = pHandle->u.pTempFile;
+                    if (   pHandle->offFile > pTempFile->cbFile
+                        && !kwFsTempFileEnsureSpace(pTempFile, pHandle->offFile, 0))
+                    {
+                        kHlpAssertFailed();
+                        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                        return FALSE;
+                    }
+
+                    pTempFile->cbFile = pHandle->offFile;
+                    KWFS_LOG(("SetEndOfFile(%p) -> TRUE (cbFile=%#x)\n", hFile, pTempFile->cbFile));
+                    return TRUE;
+                }
+
+                case KWHANDLETYPE_FSOBJ_READ_CACHE:
+                    kHlpAssertFailed();
+                    SetLastError(ERROR_ACCESS_DENIED);
+                    return FALSE;
+
+                default:
+                case KWHANDLETYPE_TEMP_FILE_MAPPING:
+                    kHlpAssertFailed();
+                    SetLastError(ERROR_INVALID_FUNCTION);
+                    return FALSE;
+            }
+        }
+    }
+
+    KWFS_LOG(("SetEndOfFile(%p)\n", hFile));
+    return SetEndOfFile(hFile);
+}
+
+
+/** Kernel32 - GetFileType  */
+static BOOL WINAPI kwSandbox_Kernel32_GetFileType(HANDLE hFile)
+{
+    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+    if (idxHandle < g_Sandbox.cHandles)
+    {
+        PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
+        if (pHandle != NULL)
+        {
+            switch (pHandle->enmType)
+            {
+                case KWHANDLETYPE_FSOBJ_READ_CACHE:
+                    KWFS_LOG(("GetFileType(%p) -> FILE_TYPE_DISK [cached]\n", hFile));
+                    return FILE_TYPE_DISK;
+
+                case KWHANDLETYPE_TEMP_FILE:
+                    KWFS_LOG(("GetFileType(%p) -> FILE_TYPE_DISK [temp]\n", hFile));
+                    return FILE_TYPE_DISK;
+            }
+        }
+    }
+
+    KWFS_LOG(("GetFileType(%p)\n", hFile));
+    return GetFileType(hFile);
+}
+
+
+/** Kernel32 - GetFileSize  */
+static DWORD WINAPI kwSandbox_Kernel32_GetFileSize(HANDLE hFile, LPDWORD pcbHighDword)
+{
+    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+    if (idxHandle < g_Sandbox.cHandles)
+    {
+        PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
+        if (pHandle != NULL)
+        {
+            if (pcbHighDword)
+                *pcbHighDword = 0;
+            SetLastError(NO_ERROR);
+            switch (pHandle->enmType)
+            {
+                case KWHANDLETYPE_FSOBJ_READ_CACHE:
+                    KWFS_LOG(("GetFileSize(%p) -> %#x [cached]\n", hFile, pHandle->u.pCachedFile->cbCached));
+                    return pHandle->u.pCachedFile->cbCached;
+
+                case KWHANDLETYPE_TEMP_FILE:
+                    KWFS_LOG(("GetFileSize(%p) -> %#x [temp]\n", hFile, pHandle->u.pTempFile->cbFile));
+                    return pHandle->u.pTempFile->cbFile;
+
+                default:
+                    kHlpAssertFailed();
+                    SetLastError(ERROR_INVALID_FUNCTION);
+                    return INVALID_FILE_SIZE;
+            }
+        }
+    }
+
+    KWFS_LOG(("GetFileSize(%p,)\n", hFile));
+    return GetFileSize(hFile, pcbHighDword);
+}
+
+
+/** Kernel32 - GetFileSizeEx  */
+static BOOL WINAPI kwSandbox_Kernel32_GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER pcbFile)
+{
+    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+    if (idxHandle < g_Sandbox.cHandles)
+    {
+        PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
+        if (pHandle != NULL)
+        {
+            switch (pHandle->enmType)
+            {
+                case KWHANDLETYPE_FSOBJ_READ_CACHE:
+                    KWFS_LOG(("GetFileSizeEx(%p) -> TRUE, %#x [cached]\n", hFile, pHandle->u.pCachedFile->cbCached));
+                    pcbFile->QuadPart = pHandle->u.pCachedFile->cbCached;
+                    return TRUE;
+
+                case KWHANDLETYPE_TEMP_FILE:
+                    KWFS_LOG(("GetFileSizeEx(%p) -> TRUE, %#x [temp]\n", hFile, pHandle->u.pTempFile->cbFile));
+                    pcbFile->QuadPart = pHandle->u.pTempFile->cbFile;
+                    return TRUE;
+
+                default:
+                    kHlpAssertFailed();
+                    SetLastError(ERROR_INVALID_FUNCTION);
+                    return INVALID_FILE_SIZE;
+            }
+        }
+    }
+
+    KWFS_LOG(("GetFileSizeEx(%p,)\n", hFile));
+    return GetFileSizeEx(hFile, pcbFile);
+}
+
+
+/** Kernel32 - CreateFileMapping  */
+static HANDLE WINAPI kwSandbox_Kernel32_CreateFileMappingW(HANDLE hFile, LPSECURITY_ATTRIBUTES pSecAttrs,
+                                                           DWORD fProtect, DWORD dwMaximumSizeHigh,
+                                                           DWORD dwMaximumSizeLow, LPCWSTR pwszName)
+{
+    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
+    if (idxHandle < g_Sandbox.cHandles)
+    {
+        PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
+        if (pHandle != NULL)
+        {
+            switch (pHandle->enmType)
+            {
+                case KWHANDLETYPE_TEMP_FILE:
+                {
+                    PKWFSTEMPFILE pTempFile = pHandle->u.pTempFile;
+                    if (   (   fProtect == PAGE_READONLY
+                            || fProtect == PAGE_EXECUTE_READ)
+                        && dwMaximumSizeHigh == 0
+                        &&  (   dwMaximumSizeLow == 0
+                             || dwMaximumSizeLow == pTempFile->cbFile)
+                        && pwszName == NULL)
+                    {
+                        HANDLE hMapping = kwFsTempFileCreateHandle(pHandle->u.pTempFile, GENERIC_READ, K_TRUE /*fMapping*/);
+                        KWFS_LOG(("CreateFileMappingW(%p, %u) -> %p [temp]\n", hFile, fProtect, hMapping));
+                        return hMapping;
+                    }
+                    kHlpAssertMsgFailed(("fProtect=%#x cb=%#x'%08x name=%p\n",
+                                         fProtect, dwMaximumSizeHigh, dwMaximumSizeLow, pwszName));
+                    SetLastError(ERROR_ACCESS_DENIED);
+                    return INVALID_HANDLE_VALUE;
+                }
+            }
+        }
+    }
+
+    KWFS_LOG(("CreateFileMappingW(%p)\n", hFile));
+    return CreateFileMappingW(hFile, pSecAttrs, fProtect, dwMaximumSizeHigh, dwMaximumSizeLow, pwszName);
+}
+
+/** Kernel32 - MapViewOfFile  */
+static HANDLE WINAPI kwSandbox_Kernel32_MapViewOfFile(HANDLE hSection, DWORD dwDesiredAccess,
+                                                      DWORD offFileHigh, DWORD offFileLow, SIZE_T cbToMap)
+{
+    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hSection);
+    if (idxHandle < g_Sandbox.cHandles)
+    {
+        PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
+        if (pHandle != NULL)
+        {
+            switch (pHandle->enmType)
+            {
+                case KWHANDLETYPE_FSOBJ_READ_CACHE:
+                case KWHANDLETYPE_TEMP_FILE:
+                    kHlpAssertFailed();
+                    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                    return NULL;
+
+                case KWHANDLETYPE_TEMP_FILE_MAPPING:
+                {
+                    PKWFSTEMPFILE pTempFile = pHandle->u.pTempFile;
+                    if (   dwDesiredAccess == FILE_MAP_READ
+                        && offFileHigh == 0
+                        && offFileLow  == 0
+                        && (cbToMap == 0 || cbToMap == pTempFile->cbFile) )
+                    {
+                        kHlpAssert(pTempFile->cMappings == 0 || pTempFile->cSegs == 1);
+                        if (pTempFile->cSegs != 1)
+                        {
+                            KU32    iSeg;
+                            KU32    cbLeft;
+                            KU32    cbAll = pTempFile->cbFile ? (KU32)K_ALIGN_Z(pTempFile->cbFile, 0x2000) : 0x1000;
+                            KU8    *pbAll = NULL;
+                            int rc = kHlpPageAlloc((void **)&pbAll, cbAll, KPROT_READWRITE, K_FALSE);
+                            if (rc != 0)
+                            {
+                                kHlpAssertFailed();
+                                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                                return NULL;
+                            }
+
+                            cbLeft = pTempFile->cbFile;
+                            for (iSeg = 0; iSeg < pTempFile->cSegs && cbLeft > 0; iSeg++)
+                            {
+                                KU32 cbToCopy = K_MIN(cbLeft, pTempFile->paSegs[iSeg].cbDataAlloc);
+                                kHlpMemCopy(&pbAll[pTempFile->paSegs[iSeg].offData], pTempFile->paSegs[iSeg].pbData, cbToCopy);
+                                cbLeft -= cbToCopy;
+                            }
+
+                            for (iSeg = 0; iSeg < pTempFile->cSegs; iSeg++)
+                            {
+                                kHlpPageFree(pTempFile->paSegs[iSeg].pbData, pTempFile->paSegs[iSeg].cbDataAlloc);
+                                pTempFile->paSegs[iSeg].pbData = NULL;
+                                pTempFile->paSegs[iSeg].cbDataAlloc = 0;
+                            }
+
+                            pTempFile->cSegs                 = 1;
+                            pTempFile->cbFileAllocated       = cbAll;
+                            pTempFile->paSegs[0].cbDataAlloc = cbAll;
+                            pTempFile->paSegs[0].pbData      = pbAll;
+                            pTempFile->paSegs[0].offData     = 0;
+                        }
+
+                        pTempFile->cMappings++;
+                        kHlpAssert(pTempFile->cMappings == 1);
+
+                        KWFS_LOG(("CreateFileMappingW(%p) -> %p [temp]\n", hSection, pTempFile->paSegs[0].pbData));
+                        return pTempFile->paSegs[0].pbData;
+                    }
+
+                    kHlpAssertMsgFailed(("dwDesiredAccess=%#x offFile=%#x'%08x cbToMap=%#x (cbFile=%#x)\n",
+                                         dwDesiredAccess, offFileHigh, offFileLow, cbToMap, pTempFile->cbFile));
+                    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                    return NULL;
+                }
+            }
+        }
+    }
+
+    KWFS_LOG(("MapViewOfFile(%p)\n", hSection));
+    return MapViewOfFile(hSection, dwDesiredAccess, offFileHigh, offFileLow, cbToMap);
+}
+/** @todo MapViewOfFileEx */
+
+
+/** Kernel32 - UnmapViewOfFile  */
+static BOOL WINAPI kwSandbox_Kernel32_UnmapViewOfFile(LPCVOID pvBase)
+{
+    /* Is this one of our temporary mappings? */
+    PKWFSTEMPFILE pCur = g_Sandbox.pTempFileHead;
+    while (pCur)
+    {
+        if (   pCur->cMappings > 0
+            && pCur->paSegs[0].pbData == (KU8 *)pvBase)
+        {
+            pCur->cMappings--;
+            KWFS_LOG(("UnmapViewOfFile(%p) -> TRUE [temp]\n", pvBase));
+            return TRUE;
+        }
+        pCur = pCur->pNext;
+    }
+
+    KWFS_LOG(("UnmapViewOfFile(%p)\n", pvBase));
+    return UnmapViewOfFile(pvBase);
+}
+
+/** @todo UnmapViewOfFileEx */
+
+
+#endif /* WITH_TEMP_MEMORY_FILES */
+
+/** Kernel32 - CloseHandle */
+static BOOL WINAPI kwSandbox_Kernel32_CloseHandle(HANDLE hObject)
+{
+    BOOL        fRet;
+    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hObject);
+    if (   idxHandle < g_Sandbox.cHandles
+        && g_Sandbox.papHandles[idxHandle] != NULL)
+    {
+        fRet = CloseHandle(hObject);
+        if (fRet)
+        {
+            PKWHANDLE pHandle = g_Sandbox.papHandles[idxHandle];
+            g_Sandbox.papHandles[idxHandle] = NULL;
+            g_Sandbox.cActiveHandles--;
+#ifdef WITH_TEMP_MEMORY_FILES
+            if (pHandle->enmType == KWHANDLETYPE_TEMP_FILE)
+            {
+                kHlpAssert(pHandle->u.pTempFile->cActiveHandles > 0);
+                pHandle->u.pTempFile->cActiveHandles--;
+            }
+#endif
+            kHlpFree(pHandle);
+            KWFS_LOG(("CloseHandle(%p) -> TRUE [intercepted handle]\n", hObject));
+        }
+        else
+            KWFS_LOG(("CloseHandle(%p) -> FALSE [intercepted handle] err=%u!\n", hObject, GetLastError()));
+    }
+    else
+    {
+        KWFS_LOG(("CloseHandle(%p)\n", hObject));
+        fRet = CloseHandle(hObject);
+    }
+    return fRet;
+}
+
+
+/** Kernel32 - GetFileAttributesA. */
+static DWORD WINAPI kwSandbox_Kernel32_GetFileAttributesA(LPCSTR pszFilename)
+{
+    DWORD       fRet;
+    const char *pszExt = kHlpGetExt(pszFilename);
+    if (kwFsIsCachableExtensionA(pszExt, K_TRUE /*fAttrQuery*/))
+    {
+        KFSLOOKUPERROR enmError;
+        PKFSOBJ pFsObj = kFsCacheLookupNoMissingA(g_pFsCache, pszFilename, &enmError);
+        if (pFsObj)
+        {
+            kHlpAssert(pFsObj->fHaveStats);
+            fRet = pFsObj->Stats.st_attribs;
+            kFsCacheObjRelease(g_pFsCache, pFsObj);
+        }
+        else
+        {
+            SetLastError(kwFsLookupErrorToWindowsError(enmError));
+            fRet = INVALID_FILE_ATTRIBUTES;
+        }
+
+        KWFS_LOG(("GetFileAttributesA(%s) -> %#x [cached]\n", pszFilename, fRet));
+        return fRet;
+    }
+
+    fRet = GetFileAttributesA(pszFilename);
+    KWFS_LOG(("GetFileAttributesA(%s) -> %#x\n", pszFilename, fRet));
+    return fRet;
+}
+
+
+/** Kernel32 - GetFileAttributesW. */
+static DWORD WINAPI kwSandbox_Kernel32_GetFileAttributesW(LPCWSTR pwszFilename)
+{
+    DWORD fRet;
+    if (kwFsIsCachablePathExtensionW(pwszFilename, K_TRUE /*fAttrQuery*/))
+    {
+        KFSLOOKUPERROR enmError;
+        PKFSOBJ pFsObj = kFsCacheLookupNoMissingW(g_pFsCache, pwszFilename, &enmError);
+        if (pFsObj)
+        {
+            kHlpAssert(pFsObj->fHaveStats);
+            fRet = pFsObj->Stats.st_attribs;
+            kFsCacheObjRelease(g_pFsCache, pFsObj);
+        }
+        else
+        {
+            SetLastError(kwFsLookupErrorToWindowsError(enmError));
+            fRet = INVALID_FILE_ATTRIBUTES;
+        }
+
+        KWFS_LOG(("GetFileAttributesW(%ls) -> %#x [cached]\n", pwszFilename, fRet));
+        return fRet;
+    }
+
+    fRet = GetFileAttributesW(pwszFilename);
+    KWFS_LOG(("GetFileAttributesW(%ls) -> %#x\n", pwszFilename, fRet));
+    return fRet;
+}
+
+
+/** Kernel32 - GetShortPathNameW - c1[xx].dll of VS2010 does this to the
+ * directory containing each include file.  We cache the result to speed
+ * things up a little. */
+static DWORD WINAPI kwSandbox_Kernel32_GetShortPathNameW(LPCWSTR pwszLongPath, LPWSTR pwszShortPath, DWORD cwcShortPath)
+{
+    DWORD cwcRet;
+    if (kwFsIsCachablePathExtensionW(pwszLongPath, K_TRUE /*fAttrQuery*/))
+    {
+        KFSLOOKUPERROR enmError;
+        PKFSOBJ pObj = kFsCacheLookupW(g_pFsCache, pwszLongPath, &enmError);
+        if (pObj)
+        {
+            if (pObj->bObjType != KFSOBJ_TYPE_MISSING)
+            {
+                if (kFsCacheObjGetFullShortPathW(pObj, pwszShortPath, cwcShortPath, '\\'))
+                {
+                    cwcRet = (DWORD)kwUtf16Len(pwszShortPath);
+
+                    /* Should preserve trailing slash on directory paths. */
+                    if (pObj->bObjType == KFSOBJ_TYPE_DIR)
+                    {
+                        if (   cwcRet + 1 < cwcShortPath
+                            && pwszShortPath[cwcRet - 1] != '\\')
+                        {
+                            KSIZE cwcIn = kwUtf16Len(pwszLongPath);
+                            if (   cwcIn > 0
+                                && (pwszLongPath[cwcIn - 1] == '\\' || pwszLongPath[cwcIn - 1] == '/') )
+                            {
+                                pwszShortPath[cwcRet++] = '\\';
+                                pwszShortPath[cwcRet]   = '\0';
+                            }
+                        }
+                    }
+
+                    KWFS_LOG(("GetShortPathNameW(%ls) -> '%*.*ls' & %#x [cached]\n",
+                              pwszLongPath, K_MIN(cwcShortPath, cwcRet), K_MIN(cwcShortPath, cwcRet), pwszShortPath, cwcRet));
+                    kFsCacheObjRelease(g_pFsCache, pObj);
+                    return cwcRet;
+                }
+
+                /* fall back for complicated cases. */
+            }
+            kFsCacheObjRelease(g_pFsCache, pObj);
+        }
+    }
+    cwcRet = GetShortPathNameW(pwszLongPath, pwszShortPath, cwcShortPath);
+    KWFS_LOG(("GetShortPathNameW(%ls) -> '%*.*ls' & %#x\n",
+              pwszLongPath, K_MIN(cwcShortPath, cwcRet), K_MIN(cwcShortPath, cwcRet), pwszShortPath, cwcRet));
+    return cwcRet;
+}
+
+
+#ifdef WITH_TEMP_MEMORY_FILES
+/** Kernel32 - DeleteFileW
+ * Skip deleting the in-memory files. */
+static BOOL WINAPI kwSandbox_Kernel32_DeleteFileW(LPCWSTR pwszFilename)
+{
+    BOOL fRc;
+    if (   g_Sandbox.pTool->u.Sandboxed.enmHint == KWTOOLHINT_VISUAL_CPP_CL
+        && kwFsIsClTempFileW(pwszFilename))
+    {
+        KWFS_LOG(("DeleteFileW(%s) -> TRUE [temp]\n", pwszFilename));
+        fRc = TRUE;
+    }
+    else
+    {
+        fRc = DeleteFileW(pwszFilename);
+        KWFS_LOG(("DeleteFileW(%s) -> %d (%d)\n", pwszFilename, fRc, GetLastError()));
+    }
+    return fRc;
+}
+#endif /* WITH_TEMP_MEMORY_FILES */
+
+
+
+/*
+ *
+ * Virtual memory leak prevension.
+ * Virtual memory leak prevension.
+ * Virtual memory leak prevension.
+ *
+ */
+
+/** Kernel32 - VirtualAlloc - for c1[xx].dll 78GB leaks.   */
+static PVOID WINAPI kwSandbox_Kernel32_VirtualAlloc(PVOID pvAddr, SIZE_T cb, DWORD fAllocType, DWORD fProt)
+{
+    PVOID pvMem = VirtualAlloc(pvAddr, cb, fAllocType, fProt);
+    KW_LOG(("VirtualAlloc: pvAddr=%p cb=%p type=%#x prot=%#x -> %p (last=%d)\n",
+            pvAddr, cb, fAllocType, fProt, pvMem, GetLastError()));
+    if (   g_Sandbox.pTool->u.Sandboxed.enmHint == KWTOOLHINT_VISUAL_CPP_CL
+        && pvMem)
+    {
+        PKWVIRTALLOC pTracker = g_Sandbox.pVirtualAllocHead;
+        while (   pTracker
+               && (KUPTR)pvMem - (KUPTR)pTracker->pvAlloc >= pTracker->cbAlloc)
+            pTracker = pTracker->pNext;
+        if (!pTracker)
+        {
+            DWORD dwErr = GetLastError();
+            PKWVIRTALLOC pTracker = (PKWVIRTALLOC)kHlpAlloc(sizeof(*pTracker));
+            if (pTracker)
+            {
+                pTracker->pvAlloc = pvMem;
+                pTracker->cbAlloc = cb;
+                pTracker->pNext   = g_Sandbox.pVirtualAllocHead;
+                g_Sandbox.pVirtualAllocHead = pTracker;
+            }
+            SetLastError(dwErr);
+        }
+    }
+    return pvMem;
+}
+
+
+/** Kernel32 - VirtualFree.   */
+static BOOL WINAPI kwSandbox_Kernel32_VirtualFree(PVOID pvAddr, SIZE_T cb, DWORD dwFreeType)
+{
+    BOOL fRc = VirtualFree(pvAddr, cb, dwFreeType);
+    KW_LOG(("VirtualFree: pvAddr=%p cb=%p type=%#x -> %d\n", pvAddr, cb, dwFreeType, fRc));
+    if (g_Sandbox.pTool->u.Sandboxed.enmHint == KWTOOLHINT_VISUAL_CPP_CL)
+    {
+        if (dwFreeType & MEM_RELEASE)
+        {
+            PKWVIRTALLOC pTracker = g_Sandbox.pVirtualAllocHead;
+            if (pTracker)
+            {
+                if (pTracker->pvAlloc == pvAddr)
+                    g_Sandbox.pVirtualAllocHead = pTracker->pNext;
+                else
+                {
+                    PKWVIRTALLOC pPrev;
+                    do
+                    {
+                        pPrev = pTracker;
+                        pTracker = pTracker->pNext;
+                    } while (pTracker && pTracker->pvAlloc != pvAddr);
+                    if (pTracker)
+                        pPrev->pNext = pTracker->pNext;
+                }
+                if (pTracker)
+                    kHlpFree(pTracker);
+                else
+                    KW_LOG(("VirtualFree: pvAddr=%p not found!\n", pvAddr));
+            }
+        }
+    }
+    return fRc;
+}
+
+
+
+/*
+ *
+ * Thread/Fiber local storage leak prevention.
+ * Thread/Fiber local storage leak prevention.
+ * Thread/Fiber local storage leak prevention.
+ *
+ * Note! The FlsAlloc/Free causes problems for statically linked VS2010
+ *       code like VBoxBs3ObjConverter.exe.  One thing is that we're
+ *       leaking these indexes, but more importantely we crash during
+ *       worker exit since the callback is triggered multiple times.
+ */
+
+
+/** Kernel32 - FlsAlloc  */
+DWORD WINAPI kwSandbox_Kernel32_FlsAlloc(PFLS_CALLBACK_FUNCTION pfnCallback)
+{
+    DWORD idxFls = FlsAlloc(pfnCallback);
+    KW_LOG(("FlsAlloc(%p) -> %#x\n", pfnCallback, idxFls));
+    if (idxFls != FLS_OUT_OF_INDEXES)
+    {
+        PKWLOCALSTORAGE pTracker = (PKWLOCALSTORAGE)kHlpAlloc(sizeof(*pTracker));
+        if (pTracker)
+        {
+            pTracker->idx = idxFls;
+            pTracker->pNext = g_Sandbox.pFlsAllocHead;
+            g_Sandbox.pFlsAllocHead = pTracker;
+        }
+    }
+
+    return idxFls;
+}
+
+/** Kernel32 - FlsFree */
+BOOL WINAPI kwSandbox_Kernel32_FlsFree(DWORD idxFls)
+{
+    BOOL fRc = FlsFree(idxFls);
+    KW_LOG(("FlsFree(%#x) -> %d\n", idxFls, fRc));
+    if (fRc)
+    {
+        PKWLOCALSTORAGE pTracker = g_Sandbox.pFlsAllocHead;
+        if (pTracker)
+        {
+            if (pTracker->idx == idxFls)
+                g_Sandbox.pFlsAllocHead = pTracker->pNext;
+            else
+            {
+                PKWLOCALSTORAGE pPrev;
+                do
+                {
+                    pPrev = pTracker;
+                    pTracker = pTracker->pNext;
+                } while (pTracker && pTracker->idx != idxFls);
+                if (pTracker)
+                    pPrev->pNext = pTracker->pNext;
+            }
+            if (pTracker)
+            {
+                pTracker->idx   = FLS_OUT_OF_INDEXES;
+                pTracker->pNext = NULL;
+                kHlpFree(pTracker);
+            }
+        }
+    }
+    return fRc;
+}
+
+
+
+/*
+ *
+ * Header file hashing.
+ * Header file hashing.
+ * Header file hashing.
+ *
+ * c1.dll / c1XX.dll hashes the input files.  The Visual C++ 2010 profiler
+ * indicated that ~12% of the time was spent doing MD5 caluclation when
+ * rebuiling openssl.  The hashing it done right after reading the source
+ * via ReadFile, same buffers and sizes.
+ */
+
+#ifdef WITH_HASH_MD5_CACHE
+
+/** Advapi32 - CryptCreateHash */
+static BOOL WINAPI kwSandbox_Advapi32_CryptCreateHash(HCRYPTPROV hProv, ALG_ID idAlg, HCRYPTKEY hKey, DWORD dwFlags,
+                                                      HCRYPTHASH *phHash)
+{
+    BOOL fRc;
+
+    /*
+     * Only do this for cl.exe when it request normal MD5.
+     */
+    if (g_Sandbox.pTool->u.Sandboxed.enmHint == KWTOOLHINT_VISUAL_CPP_CL)
+    {
+        if (idAlg == CALG_MD5)
+        {
+            if (hKey == 0)
+            {
+                if (dwFlags == 0)
+                {
+                    PKWHASHMD5 pHash = (PKWHASHMD5)kHlpAllocZ(sizeof(*pHash));
+                    if (pHash)
+                    {
+                        pHash->uMagic        = KWHASHMD5_MAGIC;
+                        pHash->cbHashed      = 0;
+                        pHash->fGoneBad      = K_FALSE;
+                        pHash->fFallbackMode = K_FALSE;
+                        pHash->fFinal        = K_FALSE;
+
+                        /* link it. */
+                        pHash->pNext         = g_Sandbox.pHashHead;
+                        g_Sandbox.pHashHead  = pHash;
+
+                        *phHash = (KUPTR)pHash;
+                        KWCRYPT_LOG(("CryptCreateHash(hProv=%p, idAlg=CALG_MD5, 0, 0, *phHash=%p) -> %d [cached]\n",
+                                     hProv, *phHash, TRUE));
+                        return TRUE;
+                    }
+
+                    kwErrPrintf("CryptCreateHash: out of memory!\n");
+                }
+                else
+                    kwErrPrintf("CryptCreateHash: dwFlags=%p is not supported with CALG_MD5\n", hKey);
+            }
+            else
+                kwErrPrintf("CryptCreateHash: hKey=%p is not supported with CALG_MD5\n", hKey);
+        }
+        else
+            kwErrPrintf("CryptCreateHash: idAlg=%#x is not supported\n", idAlg);
+    }
+
+    /*
+     * Fallback.
+     */
+    fRc = CryptCreateHash(hProv, idAlg, hKey, dwFlags, phHash);
+    KWCRYPT_LOG(("CryptCreateHash(hProv=%p, idAlg=%#x (%d), hKey=%p, dwFlags=%#x, *phHash=%p) -> %d\n",
+                 hProv, idAlg, idAlg, hKey, dwFlags, *phHash, fRc));
+    return fRc;
+}
+
+
+/** Advapi32 - CryptHashData */
+static BOOL WINAPI kwSandbox_Advapi32_CryptHashData(HCRYPTHASH hHash, CONST BYTE *pbData, DWORD cbData, DWORD dwFlags)
+{
+    BOOL        fRc;
+    PKWHASHMD5  pHash = g_Sandbox.pHashHead;
+    while (pHash && (KUPTR)pHash != hHash)
+        pHash = pHash->pNext;
+    KWCRYPT_LOG(("CryptHashData(hHash=%p/%p, pbData=%p, cbData=%#x, dwFlags=%#x)\n",
+                 hHash, pHash, pbData, cbData, dwFlags));
+    if (pHash)
+    {
+        /*
+         * Validate the state.
+         */
+        if (   pHash->uMagic == KWHASHMD5_MAGIC
+            && !pHash->fFinal)
+        {
+            if (!pHash->fFallbackMode)
+            {
+                /*
+                 * Does this match the previous ReadFile call to a cached file?
+                 * If it doesn't, try falling back.
+                 */
+                if (   g_Sandbox.LastHashRead.cbRead == cbData
+                    && g_Sandbox.LastHashRead.pvRead == (void *)pbData)
+                {
+                    PKFSWCACHEDFILE pCachedFile = g_Sandbox.LastHashRead.pCachedFile;
+                    if (   pCachedFile
+                        && kHlpMemComp(pbData, &pCachedFile->pbCached[g_Sandbox.LastHashRead.offRead], K_MIN(cbData, 64)) == 0)
+                    {
+
+                        if (g_Sandbox.LastHashRead.offRead == pHash->cbHashed)
+                        {
+                            if (   pHash->pCachedFile == NULL
+                                && pHash->cbHashed == 0)
+                                pHash->pCachedFile = pCachedFile;
+                            if (pHash->pCachedFile == pCachedFile)
+                            {
+                                pHash->cbHashed += cbData;
+                                g_Sandbox.LastHashRead.pCachedFile = NULL;
+                                g_Sandbox.LastHashRead.pvRead      = NULL;
+                                g_Sandbox.LastHashRead.cbRead      = 0;
+                                g_Sandbox.LastHashRead.offRead     = 0;
+                                KWCRYPT_LOG(("CryptHashData(hHash=%p/%p/%s, pbData=%p, cbData=%#x, dwFlags=%#x) -> 1 [cached]\n",
+                                             hHash, pCachedFile, pCachedFile->szPath, pbData, cbData, dwFlags));
+                                return TRUE;
+                            }
+
+                            /* Note! it's possible to fall back here too, if necessary. */
+                            kwErrPrintf("CryptHashData: Expected pCachedFile=%p, last read was made to %p!!\n",
+                                        pHash->pCachedFile, g_Sandbox.LastHashRead.pCachedFile);
+                        }
+                        else
+                            kwErrPrintf("CryptHashData: Expected last read at %#x, instead it was made at %#x\n",
+                                        pHash->cbHashed, g_Sandbox.LastHashRead.offRead);
+                    }
+                    else if (!pCachedFile)
+                        kwErrPrintf("CryptHashData: Last pCachedFile is NULL when buffer address and size matches!\n");
+                    else
+                        kwErrPrintf("CryptHashData: First 64 bytes of the buffer doesn't match the cache.\n");
+                }
+                else if (g_Sandbox.LastHashRead.cbRead != 0 && pHash->cbHashed != 0)
+                    kwErrPrintf("CryptHashData: Expected cbRead=%#x and pbData=%p, got %#x and %p instead\n",
+                                g_Sandbox.LastHashRead.cbRead, g_Sandbox.LastHashRead.pvRead, cbData, pbData);
+                if (pHash->cbHashed == 0)
+                    pHash->fFallbackMode = K_TRUE;
+                if (pHash->fFallbackMode)
+                {
+                    /* Initiate fallback mode (file that we don't normally cache, like .c/.cpp). */
+                    pHash->fFallbackMode = K_TRUE;
+                    MD5Init(&pHash->Md5Ctx);
+                    MD5Update(&pHash->Md5Ctx, pbData, cbData);
+                    pHash->cbHashed = cbData;
+                    KWCRYPT_LOG(("CryptHashData(hHash=%p/fallback, pbData=%p, cbData=%#x, dwFlags=%#x) -> 1 [fallback!]\n",
+                                 hHash, pbData, cbData, dwFlags));
+                    return TRUE;
+                }
+                pHash->fGoneBad = K_TRUE;
+                SetLastError(ERROR_INVALID_PARAMETER);
+                fRc = FALSE;
+            }
+            else
+            {
+                /* fallback. */
+                MD5Update(&pHash->Md5Ctx, pbData, cbData);
+                pHash->cbHashed += cbData;
+                fRc = TRUE;
+                KWCRYPT_LOG(("CryptHashData(hHash=%p/fallback, pbData=%p, cbData=%#x, dwFlags=%#x) -> 1 [fallback]\n",
+                             hHash, pbData, cbData, dwFlags));
+            }
+        }
+        /*
+         * Bad handle state.
+         */
+        else
+        {
+            if (pHash->uMagic != KWHASHMD5_MAGIC)
+                kwErrPrintf("CryptHashData: Invalid cached hash handle!!\n");
+            else
+                kwErrPrintf("CryptHashData: Hash is already finalized!!\n");
+            SetLastError(NTE_BAD_HASH);
+            fRc = FALSE;
+        }
+    }
+    else
+    {
+
+        fRc = CryptHashData(hHash, pbData, cbData, dwFlags);
+        KWCRYPT_LOG(("CryptHashData(hHash=%p, pbData=%p, cbData=%#x, dwFlags=%#x) -> %d\n", hHash, pbData, cbData, dwFlags, fRc));
+    }
+    return fRc;
+}
+
+
+/** Advapi32 - CryptGetHashParam */
+static BOOL WINAPI kwSandbox_Advapi32_CryptGetHashParam(HCRYPTHASH hHash, DWORD dwParam,
+                                                        BYTE *pbData, DWORD *pcbData, DWORD dwFlags)
+{
+    BOOL        fRc;
+    PKWHASHMD5  pHash = g_Sandbox.pHashHead;
+    while (pHash && (KUPTR)pHash != hHash)
+        pHash = pHash->pNext;
+    if (pHash)
+    {
+        if (pHash->uMagic == KWHASHMD5_MAGIC)
+        {
+            if (dwFlags == 0)
+            {
+                DWORD cbRet;
+                void *pvRet;
+                union
+                {
+                    DWORD dw;
+                } uBuf;
+
+                switch (dwParam)
+                {
+                    case HP_HASHVAL:
+                    {
+                        /* Check the hash progress. */
+                        PKFSWCACHEDFILE pCachedFile = pHash->pCachedFile;
+                        if (pCachedFile)
+                        {
+                            if (   pCachedFile->cbCached == pHash->cbHashed
+                                && !pHash->fGoneBad)
+                            {
+                                if (pCachedFile->fValidMd5)
+                                    KWCRYPT_LOG(("Already calculated hash for %p/%s! [hit]\n", pCachedFile, pCachedFile->szPath));
+                                else
+                                {
+                                    MD5Init(&pHash->Md5Ctx);
+                                    MD5Update(&pHash->Md5Ctx, pCachedFile->pbCached, pCachedFile->cbCached);
+                                    MD5Final(pCachedFile->abMd5Digest, &pHash->Md5Ctx);
+                                    pCachedFile->fValidMd5 = K_TRUE;
+                                    KWCRYPT_LOG(("Calculated hash for %p/%s.\n", pCachedFile, pCachedFile->szPath));
+                                }
+                                pvRet = pCachedFile->abMd5Digest;
+                            }
+                            else
+                            {
+                                /* This actually happens (iprt/string.h + common/alloc/alloc.cpp), at least
+                                   from what I can tell, so just deal with it. */
+                                KWCRYPT_LOG(("CryptGetHashParam/HP_HASHVAL: Not at end of cached file! cbCached=%#x cbHashed=%#x fGoneBad=%d (%p/%p/%s)\n",
+                                             pHash->pCachedFile->cbCached, pHash->cbHashed, pHash->fGoneBad,
+                                             pHash, pCachedFile, pCachedFile->szPath));
+                                pHash->fFallbackMode = K_TRUE;
+                                pHash->pCachedFile   = NULL;
+                                MD5Init(&pHash->Md5Ctx);
+                                MD5Update(&pHash->Md5Ctx, pCachedFile->pbCached, pHash->cbHashed);
+                                MD5Final(pHash->abDigest, &pHash->Md5Ctx);
+                                pvRet = pHash->abDigest;
+                            }
+                            pHash->fFinal = K_TRUE;
+                            cbRet = 16;
+                            break;
+                        }
+                        else if (pHash->fFallbackMode)
+                        {
+                            if (!pHash->fFinal)
+                            {
+                                pHash->fFinal = K_TRUE;
+                                MD5Final(pHash->abDigest, &pHash->Md5Ctx);
+                            }
+                            pvRet = pHash->abDigest;
+                            cbRet = 16;
+                            break;
+                        }
+                        else
+                        {
+                            kwErrPrintf("CryptGetHashParam/HP_HASHVAL: pCachedFile is NULL!!\n");
+                            SetLastError(ERROR_INVALID_SERVER_STATE);
+                        }
+                        return FALSE;
+                    }
+
+                    case HP_HASHSIZE:
+                        uBuf.dw = 16;
+                        pvRet = &uBuf;
+                        cbRet = sizeof(DWORD);
+                        break;
+
+                    case HP_ALGID:
+                        uBuf.dw = CALG_MD5;
+                        pvRet = &uBuf;
+                        cbRet = sizeof(DWORD);
+                        break;
+
+                    default:
+                        kwErrPrintf("CryptGetHashParam: Unknown dwParam=%#x\n", dwParam);
+                        SetLastError(NTE_BAD_TYPE);
+                        return FALSE;
+                }
+
+                /*
+                 * Copy out cbRet from pvRet.
+                 */
+                if (pbData)
+                {
+                    if (*pcbData >= cbRet)
+                    {
+                        *pcbData = cbRet;
+                        kHlpMemCopy(pbData, pvRet, cbRet);
+                        if (cbRet == 4)
+                            KWCRYPT_LOG(("CryptGetHashParam/%#x/%p/%p: TRUE, cbRet=%#x data=%#x [cached]\n",
+                                         dwParam, pHash, pHash->pCachedFile, cbRet, (DWORD *)pbData));
+                        else if (cbRet == 16)
+                            KWCRYPT_LOG(("CryptGetHashParam/%#x/%p/%p: TRUE, cbRet=%#x data=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x [cached]\n",
+                                         dwParam, pHash, pHash->pCachedFile, cbRet,
+                                         pbData[0],  pbData[1],  pbData[2],  pbData[3],
+                                         pbData[4],  pbData[5],  pbData[6],  pbData[7],
+                                         pbData[8],  pbData[9],  pbData[10], pbData[11],
+                                         pbData[12], pbData[13], pbData[14], pbData[15]));
+                        else
+                            KWCRYPT_LOG(("CryptGetHashParam/%#x%/p%/%p: TRUE, cbRet=%#x [cached]\n",
+                                         dwParam, pHash, pHash->pCachedFile, cbRet));
+                        return TRUE;
+                    }
+
+                    kHlpMemCopy(pbData, pvRet, *pcbData);
+                }
+                SetLastError(ERROR_MORE_DATA);
+                *pcbData = cbRet;
+                KWCRYPT_LOG(("CryptGetHashParam/%#x: ERROR_MORE_DATA\n"));
+            }
+            else
+            {
+                kwErrPrintf("CryptGetHashParam: dwFlags is not zero: %#x!\n", dwFlags);
+                SetLastError(NTE_BAD_FLAGS);
+            }
+        }
+        else
+        {
+            kwErrPrintf("CryptGetHashParam: Invalid cached hash handle!!\n");
+            SetLastError(NTE_BAD_HASH);
+        }
+        fRc = FALSE;
+    }
+    /*
+     * Regular handle.
+     */
+    else
+    {
+        fRc = CryptGetHashParam(hHash, dwParam, pbData, pcbData, dwFlags);
+        KWCRYPT_LOG(("CryptGetHashParam(hHash=%p, dwParam=%#x (%d), pbData=%p, *pcbData=%#x, dwFlags=%#x) -> %d\n",
+                     hHash, dwParam, pbData, *pcbData, dwFlags, fRc));
+    }
+
+    return fRc;
+}
+
+
+/** Advapi32 - CryptDestroyHash */
+static BOOL WINAPI kwSandbox_Advapi32_CryptDestroyHash(HCRYPTHASH hHash)
+{
+    BOOL        fRc;
+    PKWHASHMD5  pPrev = NULL;
+    PKWHASHMD5  pHash = g_Sandbox.pHashHead;
+    while (pHash && (KUPTR)pHash != hHash)
+    {
+        pPrev = pHash;
+        pHash = pHash->pNext;
+    }
+    if (pHash)
+    {
+        if (pHash->uMagic == KWHASHMD5_MAGIC)
+        {
+            pHash->uMagic = 0;
+            if (!pPrev)
+                g_Sandbox.pHashHead = pHash->pNext;
+            else
+                pPrev->pNext = pHash->pNext;
+            kHlpFree(pHash);
+            KWCRYPT_LOG(("CryptDestroyHash(hHash=%p) -> 1 [cached]\n", hHash));
+            fRc = TRUE;
+        }
+        else
+        {
+            kwErrPrintf("CryptDestroyHash: Invalid cached hash handle!!\n");
+            KWCRYPT_LOG(("CryptDestroyHash(hHash=%p) -> FALSE! [cached]\n", hHash));
+            SetLastError(ERROR_INVALID_HANDLE);
+            fRc = FALSE;
+        }
+    }
+    /*
+     * Regular handle.
+     */
+    else
+    {
+        fRc = CryptDestroyHash(hHash);
+        KWCRYPT_LOG(("CryptDestroyHash(hHash=%p) -> %d\n", hHash, fRc));
+    }
+    return fRc;
+}
+
+#endif /* WITH_HASH_MD5_CACHE */
+
+
+/*
+ *
+ * Misc function only intercepted while debugging.
+ * Misc function only intercepted while debugging.
+ * Misc function only intercepted while debugging.
+ *
+ */
+
+#ifndef NDEBUG
+
+/** CRT - memcpy   */
+static void * __cdecl kwSandbox_msvcrt_memcpy(void *pvDst, void const *pvSrc, size_t cb)
+{
+    KU8 const *pbSrc = (KU8 const *)pvSrc;
+    KU8       *pbDst = (KU8 *)pvDst;
+    KSIZE      cbLeft = cb;
+    while (cbLeft-- > 0)
+        *pbDst++ = *pbSrc++;
+    return pvDst;
+}
+
+#endif /* NDEBUG */
+
+
+
+/**
+ * Functions that needs replacing for sandboxed execution.
+ */
+KWREPLACEMENTFUNCTION const g_aSandboxReplacements[] =
+{
+    /*
+     * Kernel32.dll and friends.
+     */
+    { TUPLE("ExitProcess"),                 NULL,       (KUPTR)kwSandbox_Kernel32_ExitProcess },
+    { TUPLE("TerminateProcess"),            NULL,       (KUPTR)kwSandbox_Kernel32_TerminateProcess },
+
+    { TUPLE("LoadLibraryA"),                NULL,       (KUPTR)kwSandbox_Kernel32_LoadLibraryA },
+    { TUPLE("LoadLibraryW"),                NULL,       (KUPTR)kwSandbox_Kernel32_LoadLibraryW },
+    { TUPLE("LoadLibraryExA"),              NULL,       (KUPTR)kwSandbox_Kernel32_LoadLibraryExA },
+    { TUPLE("LoadLibraryExW"),              NULL,       (KUPTR)kwSandbox_Kernel32_LoadLibraryExW },
+    { TUPLE("FreeLibrary"),                 NULL,       (KUPTR)kwSandbox_Kernel32_FreeLibrary },
+    { TUPLE("GetModuleHandleA"),            NULL,       (KUPTR)kwSandbox_Kernel32_GetModuleHandleA },
+    { TUPLE("GetModuleHandleW"),            NULL,       (KUPTR)kwSandbox_Kernel32_GetModuleHandleW },
+    { TUPLE("GetProcAddress"),              NULL,       (KUPTR)kwSandbox_Kernel32_GetProcAddress },
+    { TUPLE("GetModuleFileNameA"),          NULL,       (KUPTR)kwSandbox_Kernel32_GetModuleFileNameA },
+    { TUPLE("GetModuleFileNameW"),          NULL,       (KUPTR)kwSandbox_Kernel32_GetModuleFileNameW },
+    { TUPLE("RtlPcToFileHeader"),           NULL,       (KUPTR)kwSandbox_ntdll_RtlPcToFileHeader },
+
+    { TUPLE("GetCommandLineA"),             NULL,       (KUPTR)kwSandbox_Kernel32_GetCommandLineA },
+    { TUPLE("GetCommandLineW"),             NULL,       (KUPTR)kwSandbox_Kernel32_GetCommandLineW },
+    { TUPLE("GetStartupInfoA"),             NULL,       (KUPTR)kwSandbox_Kernel32_GetStartupInfoA },
+    { TUPLE("GetStartupInfoW"),             NULL,       (KUPTR)kwSandbox_Kernel32_GetStartupInfoW },
+
+    { TUPLE("CreateThread"),                NULL,       (KUPTR)kwSandbox_Kernel32_CreateThread },
+
+    { TUPLE("GetEnvironmentStrings"),       NULL,       (KUPTR)kwSandbox_Kernel32_GetEnvironmentStrings },
+    { TUPLE("GetEnvironmentStringsA"),      NULL,       (KUPTR)kwSandbox_Kernel32_GetEnvironmentStringsA },
+    { TUPLE("GetEnvironmentStringsW"),      NULL,       (KUPTR)kwSandbox_Kernel32_GetEnvironmentStringsW },
+    { TUPLE("FreeEnvironmentStringsA"),     NULL,       (KUPTR)kwSandbox_Kernel32_FreeEnvironmentStringsA },
+    { TUPLE("FreeEnvironmentStringsW"),     NULL,       (KUPTR)kwSandbox_Kernel32_FreeEnvironmentStringsW },
+    { TUPLE("GetEnvironmentVariableA"),     NULL,       (KUPTR)kwSandbox_Kernel32_GetEnvironmentVariableA },
+    { TUPLE("GetEnvironmentVariableW"),     NULL,       (KUPTR)kwSandbox_Kernel32_GetEnvironmentVariableW },
+    { TUPLE("SetEnvironmentVariableA"),     NULL,       (KUPTR)kwSandbox_Kernel32_SetEnvironmentVariableA },
+    { TUPLE("SetEnvironmentVariableW"),     NULL,       (KUPTR)kwSandbox_Kernel32_SetEnvironmentVariableW },
+    { TUPLE("ExpandEnvironmentStringsA"),   NULL,       (KUPTR)kwSandbox_Kernel32_ExpandEnvironmentStringsA },
+    { TUPLE("ExpandEnvironmentStringsW"),   NULL,       (KUPTR)kwSandbox_Kernel32_ExpandEnvironmentStringsW },
+
+    { TUPLE("CreateFileA"),                 NULL,       (KUPTR)kwSandbox_Kernel32_CreateFileA },
+    { TUPLE("CreateFileW"),                 NULL,       (KUPTR)kwSandbox_Kernel32_CreateFileW },
+    { TUPLE("ReadFile"),                    NULL,       (KUPTR)kwSandbox_Kernel32_ReadFile },
+    { TUPLE("ReadFileEx"),                  NULL,       (KUPTR)kwSandbox_Kernel32_ReadFileEx },
+#ifdef WITH_TEMP_MEMORY_FILES
+    { TUPLE("WriteFile"),                   NULL,       (KUPTR)kwSandbox_Kernel32_WriteFile },
+    { TUPLE("WriteFileEx"),                 NULL,       (KUPTR)kwSandbox_Kernel32_WriteFileEx },
+    { TUPLE("SetEndOfFile"),                NULL,       (KUPTR)kwSandbox_Kernel32_SetEndOfFile },
+    { TUPLE("GetFileType"),                 NULL,       (KUPTR)kwSandbox_Kernel32_GetFileType },
+    { TUPLE("GetFileSize"),                 NULL,       (KUPTR)kwSandbox_Kernel32_GetFileSize },
+    { TUPLE("GetFileSizeEx"),               NULL,       (KUPTR)kwSandbox_Kernel32_GetFileSizeEx },
+    { TUPLE("CreateFileMappingW"),          NULL,       (KUPTR)kwSandbox_Kernel32_CreateFileMappingW },
+    { TUPLE("MapViewOfFile"),               NULL,       (KUPTR)kwSandbox_Kernel32_MapViewOfFile },
+    { TUPLE("UnmapViewOfFile"),             NULL,       (KUPTR)kwSandbox_Kernel32_UnmapViewOfFile },
+#endif
+    { TUPLE("SetFilePointer"),              NULL,       (KUPTR)kwSandbox_Kernel32_SetFilePointer },
+    { TUPLE("SetFilePointerEx"),            NULL,       (KUPTR)kwSandbox_Kernel32_SetFilePointerEx },
+    { TUPLE("CloseHandle"),                 NULL,       (KUPTR)kwSandbox_Kernel32_CloseHandle },
+    { TUPLE("GetFileAttributesA"),          NULL,       (KUPTR)kwSandbox_Kernel32_GetFileAttributesA },
+    { TUPLE("GetFileAttributesW"),          NULL,       (KUPTR)kwSandbox_Kernel32_GetFileAttributesW },
+    { TUPLE("GetShortPathNameW"),           NULL,       (KUPTR)kwSandbox_Kernel32_GetShortPathNameW },
+#ifdef WITH_TEMP_MEMORY_FILES
+    { TUPLE("DeleteFileW"),                 NULL,       (KUPTR)kwSandbox_Kernel32_DeleteFileW },
+#endif
+
+    { TUPLE("VirtualAlloc"),                NULL,       (KUPTR)kwSandbox_Kernel32_VirtualAlloc },
+    { TUPLE("VirtualFree"),                 NULL,       (KUPTR)kwSandbox_Kernel32_VirtualFree },
+
+    { TUPLE("FlsAlloc"),                    NULL,       (KUPTR)kwSandbox_Kernel32_FlsAlloc },
+    { TUPLE("FlsFree"),                     NULL,       (KUPTR)kwSandbox_Kernel32_FlsFree },
+
+#ifdef WITH_HASH_MD5_CACHE
+    { TUPLE("CryptCreateHash"),             NULL,       (KUPTR)kwSandbox_Advapi32_CryptCreateHash },
+    { TUPLE("CryptHashData"),               NULL,       (KUPTR)kwSandbox_Advapi32_CryptHashData },
+    { TUPLE("CryptGetHashParam"),           NULL,       (KUPTR)kwSandbox_Advapi32_CryptGetHashParam },
+    { TUPLE("CryptDestroyHash"),            NULL,       (KUPTR)kwSandbox_Advapi32_CryptDestroyHash },
+#endif
+
+    /*
+     * MS Visual C++ CRTs.
+     */
+    { TUPLE("exit"),                        NULL,       (KUPTR)kwSandbox_msvcrt_exit },
+    { TUPLE("_exit"),                       NULL,       (KUPTR)kwSandbox_msvcrt__exit },
+    { TUPLE("_cexit"),                      NULL,       (KUPTR)kwSandbox_msvcrt__cexit },
+    { TUPLE("_c_exit"),                     NULL,       (KUPTR)kwSandbox_msvcrt__c_exit },
+    { TUPLE("_amsg_exit"),                  NULL,       (KUPTR)kwSandbox_msvcrt__amsg_exit },
+    { TUPLE("terminate"),                   NULL,       (KUPTR)kwSandbox_msvcrt_terminate },
+
+    { TUPLE("_beginthread"),                NULL,       (KUPTR)kwSandbox_msvcrt__beginthread },
+    { TUPLE("_beginthreadex"),              NULL,       (KUPTR)kwSandbox_msvcrt__beginthreadex },
+
+    { TUPLE("__argc"),                      NULL,       (KUPTR)&g_Sandbox.cArgs },
+    { TUPLE("__argv"),                      NULL,       (KUPTR)&g_Sandbox.papszArgs },
+    { TUPLE("__wargv"),                     NULL,       (KUPTR)&g_Sandbox.papwszArgs },
+    { TUPLE("__p___argc"),                  NULL,       (KUPTR)kwSandbox_msvcrt___p___argc },
+    { TUPLE("__p___argv"),                  NULL,       (KUPTR)kwSandbox_msvcrt___p___argv },
+    { TUPLE("__p___wargv"),                 NULL,       (KUPTR)kwSandbox_msvcrt___p___wargv },
+    { TUPLE("_acmdln"),                     NULL,       (KUPTR)&g_Sandbox.pszCmdLine },
+    { TUPLE("_wcmdln"),                     NULL,       (KUPTR)&g_Sandbox.pwszCmdLine },
+    { TUPLE("__p__acmdln"),                 NULL,       (KUPTR)kwSandbox_msvcrt___p__acmdln },
+    { TUPLE("__p__wcmdln"),                 NULL,       (KUPTR)kwSandbox_msvcrt___p__wcmdln },
+    { TUPLE("_pgmptr"),                     NULL,       (KUPTR)&g_Sandbox.pgmptr  },
+    { TUPLE("_wpgmptr"),                    NULL,       (KUPTR)&g_Sandbox.wpgmptr },
+    { TUPLE("_get_pgmptr"),                 NULL,       (KUPTR)kwSandbox_msvcrt__get_pgmptr },
+    { TUPLE("_get_wpgmptr"),                NULL,       (KUPTR)kwSandbox_msvcrt__get_wpgmptr },
+    { TUPLE("__p__pgmptr"),                 NULL,       (KUPTR)kwSandbox_msvcrt___p__pgmptr },
+    { TUPLE("__p__wpgmptr"),                NULL,       (KUPTR)kwSandbox_msvcrt___p__wpgmptr },
+    { TUPLE("_wincmdln"),                   NULL,       (KUPTR)kwSandbox_msvcrt__wincmdln },
+    { TUPLE("_wwincmdln"),                  NULL,       (KUPTR)kwSandbox_msvcrt__wwincmdln },
+    { TUPLE("__getmainargs"),               NULL,       (KUPTR)kwSandbox_msvcrt___getmainargs},
+    { TUPLE("__wgetmainargs"),              NULL,       (KUPTR)kwSandbox_msvcrt___wgetmainargs},
+
+    { TUPLE("_putenv"),                     NULL,       (KUPTR)kwSandbox_msvcrt__putenv},
+    { TUPLE("_wputenv"),                    NULL,       (KUPTR)kwSandbox_msvcrt__wputenv},
+    { TUPLE("_putenv_s"),                   NULL,       (KUPTR)kwSandbox_msvcrt__putenv_s},
+    { TUPLE("_wputenv_s"),                  NULL,       (KUPTR)kwSandbox_msvcrt__wputenv_s},
+    { TUPLE("__initenv"),                   NULL,       (KUPTR)&g_Sandbox.initenv },
+    { TUPLE("__winitenv"),                  NULL,       (KUPTR)&g_Sandbox.winitenv },
+    { TUPLE("__p___initenv"),               NULL,       (KUPTR)kwSandbox_msvcrt___p___initenv},
+    { TUPLE("__p___winitenv"),              NULL,       (KUPTR)kwSandbox_msvcrt___p___winitenv},
+    { TUPLE("_environ"),                    NULL,       (KUPTR)&g_Sandbox.environ },
+    { TUPLE("_wenviron"),                   NULL,       (KUPTR)&g_Sandbox.wenviron },
+    { TUPLE("_get_environ"),                NULL,       (KUPTR)kwSandbox_msvcrt__get_environ },
+    { TUPLE("_get_wenviron"),               NULL,       (KUPTR)kwSandbox_msvcrt__get_wenviron },
+    { TUPLE("__p__environ"),                NULL,       (KUPTR)kwSandbox_msvcrt___p__environ },
+    { TUPLE("__p__wenviron"),               NULL,       (KUPTR)kwSandbox_msvcrt___p__wenviron },
+
+#ifndef NDEBUG
+    { TUPLE("memcpy"),                      NULL,       (KUPTR)kwSandbox_msvcrt_memcpy },
+#endif
+};
+/** Number of entries in g_aReplacements. */
+KU32 const                  g_cSandboxReplacements = K_ELEMENTS(g_aSandboxReplacements);
+
+
+/**
+ * Functions that needs replacing in natively loaded DLLs when doing sandboxed
+ * execution.
+ */
+KWREPLACEMENTFUNCTION const g_aSandboxNativeReplacements[] =
+{
+    /*
+     * Kernel32.dll and friends.
+     */
+    { TUPLE("ExitProcess"),                 NULL,       (KUPTR)kwSandbox_Kernel32_ExitProcess },
+    { TUPLE("TerminateProcess"),            NULL,       (KUPTR)kwSandbox_Kernel32_TerminateProcess },
+
+#if 0
+    { TUPLE("CreateThread"),                NULL,       (KUPTR)kwSandbox_Kernel32_CreateThread },
+#endif
+
+    { TUPLE("CreateFileA"),                 NULL,       (KUPTR)kwSandbox_Kernel32_CreateFileA },
+    { TUPLE("CreateFileW"),                 NULL,       (KUPTR)kwSandbox_Kernel32_CreateFileW },
+    { TUPLE("ReadFile"),                    NULL,       (KUPTR)kwSandbox_Kernel32_ReadFile },
+    { TUPLE("ReadFileEx"),                  NULL,       (KUPTR)kwSandbox_Kernel32_ReadFileEx },
+#ifdef WITH_TEMP_MEMORY_FILES
+    { TUPLE("WriteFile"),                   NULL,       (KUPTR)kwSandbox_Kernel32_WriteFile },
+    { TUPLE("WriteFileEx"),                 NULL,       (KUPTR)kwSandbox_Kernel32_WriteFileEx },
+    { TUPLE("SetEndOfFile"),                NULL,       (KUPTR)kwSandbox_Kernel32_SetEndOfFile },
+    { TUPLE("GetFileType"),                 NULL,       (KUPTR)kwSandbox_Kernel32_GetFileType },
+    { TUPLE("GetFileSize"),                 NULL,       (KUPTR)kwSandbox_Kernel32_GetFileSize },
+    { TUPLE("GetFileSizeEx"),               NULL,       (KUPTR)kwSandbox_Kernel32_GetFileSizeEx },
+    { TUPLE("CreateFileMappingW"),          NULL,       (KUPTR)kwSandbox_Kernel32_CreateFileMappingW },
+    { TUPLE("MapViewOfFile"),               NULL,       (KUPTR)kwSandbox_Kernel32_MapViewOfFile },
+    { TUPLE("UnmapViewOfFile"),             NULL,       (KUPTR)kwSandbox_Kernel32_UnmapViewOfFile },
+#endif
+    { TUPLE("SetFilePointer"),              NULL,       (KUPTR)kwSandbox_Kernel32_SetFilePointer },
+    { TUPLE("SetFilePointerEx"),            NULL,       (KUPTR)kwSandbox_Kernel32_SetFilePointerEx },
+    { TUPLE("CloseHandle"),                 NULL,       (KUPTR)kwSandbox_Kernel32_CloseHandle },
+    { TUPLE("GetFileAttributesA"),          NULL,       (KUPTR)kwSandbox_Kernel32_GetFileAttributesA },
+    { TUPLE("GetFileAttributesW"),          NULL,       (KUPTR)kwSandbox_Kernel32_GetFileAttributesW },
+    { TUPLE("GetShortPathNameW"),           NULL,       (KUPTR)kwSandbox_Kernel32_GetShortPathNameW },
+#ifdef WITH_TEMP_MEMORY_FILES
+    { TUPLE("DeleteFileW"),                 NULL,       (KUPTR)kwSandbox_Kernel32_DeleteFileW },
+#endif
+
+#ifdef WITH_HASH_MD5_CACHE
+    { TUPLE("CryptCreateHash"),             NULL,       (KUPTR)kwSandbox_Advapi32_CryptCreateHash },
+    { TUPLE("CryptHashData"),               NULL,       (KUPTR)kwSandbox_Advapi32_CryptHashData },
+    { TUPLE("CryptGetHashParam"),           NULL,       (KUPTR)kwSandbox_Advapi32_CryptGetHashParam },
+    { TUPLE("CryptDestroyHash"),            NULL,       (KUPTR)kwSandbox_Advapi32_CryptDestroyHash },
+#endif
+
+    { TUPLE("RtlPcToFileHeader"),           NULL,       (KUPTR)kwSandbox_ntdll_RtlPcToFileHeader },
+
+    /*
+     * MS Visual C++ CRTs.
+     */
+    { TUPLE("exit"),                        NULL,       (KUPTR)kwSandbox_msvcrt_exit },
+    { TUPLE("_exit"),                       NULL,       (KUPTR)kwSandbox_msvcrt__exit },
+    { TUPLE("_cexit"),                      NULL,       (KUPTR)kwSandbox_msvcrt__cexit },
+    { TUPLE("_c_exit"),                     NULL,       (KUPTR)kwSandbox_msvcrt__c_exit },
+    { TUPLE("_amsg_exit"),                  NULL,       (KUPTR)kwSandbox_msvcrt__amsg_exit },
+    { TUPLE("terminate"),                   NULL,       (KUPTR)kwSandbox_msvcrt_terminate },
+
+#if 0 /* used by mspdbXXX.dll */
+    { TUPLE("_beginthread"),                NULL,       (KUPTR)kwSandbox_msvcrt__beginthread },
+    { TUPLE("_beginthreadex"),              NULL,       (KUPTR)kwSandbox_msvcrt__beginthreadex },
+#endif
+};
+/** Number of entries in g_aSandboxNativeReplacements. */
+KU32 const                  g_cSandboxNativeReplacements = K_ELEMENTS(g_aSandboxNativeReplacements);
+
+
+/**
+ * Used by kwSandboxExec to reset the state of the module tree.
+ *
+ * This is done recursively.
+ *
+ * @param   pMod                The root of the tree to consider.
+ */
+static void kwSandboxResetModuleState(PKWMODULE pMod)
+{
+    if (   !pMod->fNative
+        && pMod->u.Manual.enmState != KWMODSTATE_NEEDS_BITS)
+    {
+        KSIZE iImp;
+        pMod->u.Manual.enmState = KWMODSTATE_NEEDS_BITS;
+        iImp = pMod->u.Manual.cImpMods;
+        while (iImp-- > 0)
+            kwSandboxResetModuleState(pMod->u.Manual.apImpMods[iImp]);
+    }
+}
+
+static PPEB kwSandboxGetProcessEnvironmentBlock(void)
+{
+#if K_ARCH == K_ARCH_X86_32
+    return (PPEB)__readfsdword(0x030 /* offset of ProcessEnvironmentBlock in TEB */);
+#elif K_ARCH == K_ARCH_AMD64
+    return (PPEB)__readgsqword(0x060 /* offset of ProcessEnvironmentBlock in TEB */);
+#else
+# error "Port me!"
+#endif
+}
+
+
+#if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_X86)
+typedef struct _EXCEPTION_REGISTRATION_RECORD
+{
+    struct _EXCEPTION_REGISTRATION_RECORD * volatile PrevStructure;
+    KU32 (__cdecl * volatile ExceptionHandler)(PEXCEPTION_RECORD, struct _EXCEPTION_REGISTRATION_RECORD*, PCONTEXT,
+                                               struct _EXCEPTION_REGISTRATION_RECORD * volatile *);
+};
+
+/**
+ * Vectored exception handler that emulates x86 chained exception handler.
+ *
+ * This is necessary because the RtlIsValidHandler check fails for self loaded
+ * code and prevents cl.exe from working.  (On AMD64 we can register function
+ * tables, but on X86 cooking your own handling seems to be the only viabke
+ * alternative.)
+ *
+ * @returns EXCEPTION_CONTINUE_SEARCH or EXCEPTION_CONTINUE_EXECUTION.
+ * @param   pXcptPtrs           The exception details.
+ */
+static LONG CALLBACK kwSandboxVecXcptEmulateChained(PEXCEPTION_POINTERS pXcptPtrs)
+{
+    PNT_TIB pTib = (PNT_TIB)NtCurrentTeb();
+    KW_LOG(("kwSandboxVecXcptEmulateChained: %#x\n", pXcptPtrs->ExceptionRecord->ExceptionCode));
+    if (g_Sandbox.fRunning)
+    {
+        PEXCEPTION_RECORD                                 pXcptRec = pXcptPtrs->ExceptionRecord;
+        PCONTEXT                                          pXcptCtx = pXcptPtrs->ContextRecord;
+        struct _EXCEPTION_REGISTRATION_RECORD * volatile *ppRegRec = &pTib->ExceptionList;
+        struct _EXCEPTION_REGISTRATION_RECORD *           pRegRec  = *ppRegRec;
+        while (((KUPTR)pRegRec & (sizeof(void *) - 3)) == 0 && pRegRec != NULL)
+        {
+#if 1
+            /* This is a more robust version that isn't subject to calling
+               convension cleanup disputes and such. */
+            KU32 uSavedEdi;
+            KU32 uSavedEsi;
+            KU32 uSavedEbx;
+            KU32 rcHandler;
+            __asm
+            {
+                mov     [uSavedEdi], edi
+                mov     [uSavedEsi], esi
+                mov     [uSavedEbx], ebx
+                mov     esi, esp
+                mov     edi, esp
+                mov     ecx, [pXcptRec]
+                mov     edx, [pRegRec]
+                mov     eax, [pXcptCtx]
+                mov     ebx, [ppRegRec]
+                sub     esp, 16
+                and     esp, 0fffffff0h
+                mov     [esp     ], ecx
+                mov     [esp +  4], edx
+                mov     [esp +  8], eax
+                mov     [esp + 12], ebx
+                call    dword ptr [edx + 4]
+                mov     esp, esi
+                cmp     esp, edi
+                je      stack_ok
+                int     3
+            stack_ok:
+                mov     edi, [uSavedEdi]
+                mov     esi, [uSavedEsi]
+                mov     ebx, [uSavedEbx]
+                mov     [rcHandler], eax
+            }
+#else
+            KU32 rcHandler = pRegRec->ExceptionHandler(pXcptPtrs->ExceptionRecord, pRegRec, pXcptPtrs->ContextRecord, ppRegRec);
+#endif
+            if (rcHandler == ExceptionContinueExecution)
+            {
+                kHlpAssert(!(pXcptPtrs->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE));
+                return EXCEPTION_CONTINUE_EXECUTION;
+            }
+            if (rcHandler == ExceptionContinueSearch)
+                kHlpAssert(!(pXcptPtrs->ExceptionRecord->ExceptionFlags & 8 /*EXCEPTION_STACK_INVALID*/));
+            else if (rcHandler == ExceptionNestedException)
+                kHlpAssertMsgFailed(("Nested exceptions.\n"));
+            else
+                kHlpAssertMsgFailed(("Invalid return %#x (%d).\n", rcHandler, rcHandler));
+
+            /*
+             * Next.
+             */
+            ppRegRec = &pRegRec->PrevStructure;
+            pRegRec = pRegRec->PrevStructure;
+        }
+    }
+    return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif /* WINDOWS + X86 */
+
+
+/**
+ * Enters the given handle into the handle table.
+ *
+ * @returns K_TRUE on success, K_FALSE on failure.
+ * @param   pSandbox            The sandbox.
+ * @param   pHandle             The handle.
+ */
+static KBOOL kwSandboxHandleTableEnter(PKWSANDBOX pSandbox, PKWHANDLE pHandle)
+{
+    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(pHandle->hHandle);
+    kHlpAssertReturn(idxHandle < KW_HANDLE_MAX, K_FALSE);
+
+    /*
+     * Grow handle table.
+     */
+    if (idxHandle >= pSandbox->cHandles)
+    {
+        void *pvNew;
+        KU32  cHandles = pSandbox->cHandles ? pSandbox->cHandles * 2 : 32;
+        while (cHandles <= idxHandle)
+            cHandles *= 2;
+        pvNew = kHlpRealloc(pSandbox->papHandles, cHandles * sizeof(pSandbox->papHandles[0]));
+        if (!pvNew)
+        {
+            KW_LOG(("Out of memory growing handle table to %u handles\n", cHandles));
+            return K_FALSE;
+        }
+        pSandbox->papHandles = (PKWHANDLE *)pvNew;
+        kHlpMemSet(&pSandbox->papHandles[pSandbox->cHandles], 0,
+                   (cHandles - pSandbox->cHandles) * sizeof(pSandbox->papHandles[0]));
+        pSandbox->cHandles = cHandles;
+    }
+
+    /*
+     * Check that the entry is unused then insert it.
+     */
+    kHlpAssertReturn(pSandbox->papHandles[idxHandle] == NULL, K_FALSE);
+    pSandbox->papHandles[idxHandle] = pHandle;
+    pSandbox->cActiveHandles++;
+    return K_TRUE;
+}
+
+
+/**
+ * Creates a correctly quoted ANSI command line string from the given argv.
+ *
+ * @returns Pointer to the command line.
+ * @param   cArgs               Number of arguments.
+ * @param   papszArgs           The argument vector.
+ * @param   fWatcomBrainDamange Whether to apply watcom rules while quoting.
+ * @param   pcbCmdLine          Where to return the command line length,
+ *                              including one terminator.
+ */
+static char *kwSandboxInitCmdLineFromArgv(KU32 cArgs, const char **papszArgs, KBOOL fWatcomBrainDamange, KSIZE *pcbCmdLine)
+{
+    KU32    i;
+    KSIZE   cbCmdLine;
+    char   *pszCmdLine;
+
+    /* Make a copy of the argument vector that we'll be quoting. */
+    char **papszQuotedArgs = alloca(sizeof(papszArgs[0]) * (cArgs + 1));
+    kHlpMemCopy(papszQuotedArgs, papszArgs, sizeof(papszArgs[0]) * (cArgs + 1));
+
+    /* Quote the arguments that need it. */
+    quote_argv(cArgs, papszQuotedArgs, fWatcomBrainDamange, 0 /*leak*/);
+
+    /* figure out cmd line length. */
+    cbCmdLine = 0;
+    for (i = 0; i < cArgs; i++)
+        cbCmdLine += kHlpStrLen(papszQuotedArgs[i]) + 1;
+    *pcbCmdLine = cbCmdLine;
+
+    pszCmdLine = (char *)kHlpAlloc(cbCmdLine + 1);
+    if (pszCmdLine)
+    {
+        char *psz = kHlpStrPCopy(pszCmdLine, papszQuotedArgs[0]);
+        if (papszQuotedArgs[0] != papszArgs[0])
+            free(papszQuotedArgs[0]);
+
+        for (i = 1; i < cArgs; i++)
+        {
+            *psz++ = ' ';
+            psz = kHlpStrPCopy(psz, papszQuotedArgs[i]);
+            if (papszQuotedArgs[i] != papszArgs[i])
+                free(papszQuotedArgs[i]);
+        }
+        kHlpAssert((KSIZE)(&psz[1] - pszCmdLine) == cbCmdLine);
+
+        *psz++ = '\0';
+        *psz++ = '\0';
+    }
+
+    return pszCmdLine;
+}
+
+
+
+static int kwSandboxInit(PKWSANDBOX pSandbox, PKWTOOL pTool,
+                         KU32 cArgs, const char **papszArgs, KBOOL fWatcomBrainDamange,
+                         KU32 cEnvVars, const char **papszEnvVars)
+{
+    PPEB pPeb = kwSandboxGetProcessEnvironmentBlock();
+    wchar_t *pwcPool;
+    KSIZE cbStrings;
+    KSIZE cwc;
+    KSIZE cbCmdLine;
+    KU32 i;
+    int rc;
+
+    /* Simple stuff. */
+    pSandbox->rcExitCode    = 256;
+    pSandbox->pTool         = pTool;
+    pSandbox->idMainThread  = GetCurrentThreadId();
+    pSandbox->pgmptr        = (char *)pTool->pszPath;
+    pSandbox->wpgmptr       = (wchar_t *)pTool->pwszPath;
+    pSandbox->cArgs         = cArgs;
+    pSandbox->papszArgs     = (char **)papszArgs;
+    pSandbox->pszCmdLine    = kwSandboxInitCmdLineFromArgv(cArgs, papszArgs, fWatcomBrainDamange, &cbCmdLine);
+    if (!pSandbox->pszCmdLine)
+        return KERR_NO_MEMORY;
+
+    /*
+     * Convert command line and argv to UTF-16.
+     * We assume each ANSI char requires a surrogate pair in the UTF-16 variant.
+     */
+    pSandbox->papwszArgs = (wchar_t **)kHlpAlloc(sizeof(wchar_t *) * (pSandbox->cArgs + 2) + cbCmdLine * 2 * sizeof(wchar_t));
+    if (!pSandbox->papwszArgs)
+        return KERR_NO_MEMORY;
+    pwcPool = (wchar_t *)&pSandbox->papwszArgs[pSandbox->cArgs + 2];
+    for (i = 0; i < cArgs; i++)
+    {
+        *pwcPool++ = pSandbox->papszArgs[i][-1]; /* flags */
+        pSandbox->papwszArgs[i] = pwcPool;
+        pwcPool += kwStrToUtf16(pSandbox->papszArgs[i], pwcPool, (kHlpStrLen(pSandbox->papszArgs[i]) + 1) * 2);
+        pwcPool++;
+    }
+    pSandbox->papwszArgs[pSandbox->cArgs + 0] = NULL;
+    pSandbox->papwszArgs[pSandbox->cArgs + 1] = NULL;
+
+    /*
+     * Convert the commandline string to UTF-16, same pessimistic approach as above.
+     */
+    cbStrings = (cbCmdLine + 1) * 2 * sizeof(wchar_t);
+    pSandbox->pwszCmdLine = kHlpAlloc(cbStrings);
+    if (!pSandbox->pwszCmdLine)
+        return KERR_NO_MEMORY;
+    cwc = kwStrToUtf16(pSandbox->pszCmdLine, pSandbox->pwszCmdLine, cbStrings / sizeof(wchar_t));
+
+    pSandbox->SavedCommandLine = pPeb->ProcessParameters->CommandLine;
+    pPeb->ProcessParameters->CommandLine.Buffer = pSandbox->pwszCmdLine;
+    pPeb->ProcessParameters->CommandLine.Length = (USHORT)cwc * sizeof(wchar_t);
+
+    /*
+     * Setup the enviornment.
+     */
+    rc = kwSandboxGrowEnv(pSandbox, cEnvVars + 2);
+    if (rc == 0)
+    {
+        KU32 iDst = 0;
+        for (i = 0; i < cEnvVars; i++)
+        {
+            const char *pszVar   = papszEnvVars[i];
+            KSIZE       cchVar   = kHlpStrLen(pszVar);
+            if (   cchVar > 0
+                && kHlpMemChr(pszVar, '=', cchVar) != NULL)
+            {
+                char       *pszCopy  = kHlpDup(pszVar, cchVar + 1);
+                wchar_t    *pwszCopy = kwStrToUtf16AllocN(pszVar, cchVar + 1);
+                if (pszCopy && pwszCopy)
+                {
+                    pSandbox->papszEnvVars[iDst]  = pszCopy;
+                    pSandbox->environ[iDst]       = pszCopy;
+                    pSandbox->papwszEnvVars[iDst] = pwszCopy;
+                    pSandbox->wenviron[iDst]      = pwszCopy;
+                    iDst++;
+                }
+                else
+                {
+                    kHlpFree(pszCopy);
+                    kHlpFree(pwszCopy);
+                    return kwErrPrintfRc(KERR_NO_MEMORY, "Out of memory setting up env vars!\n");
+                }
+            }
+            else
+                kwErrPrintf("kwSandboxInit: Skipping bad env var '%s'\n", pszVar);
+        }
+        pSandbox->papszEnvVars[iDst]  = NULL;
+        pSandbox->environ[iDst]       = NULL;
+        pSandbox->papwszEnvVars[iDst] = NULL;
+        pSandbox->wenviron[iDst]      = NULL;
+    }
+    else
+        return kwErrPrintfRc(KERR_NO_MEMORY, "Error setting up environment variables: %d\n", rc);
+
+    /*
+     * Invalidate the volatile parts of cache (kBuild output directory,
+     * temporary directory, whatever).
+     */
+    kFsCacheInvalidateCustomBoth(g_pFsCache);
+    return 0;
+}
+
+
+/**
+ * Does sandbox cleanup between jobs.
+ *
+ * We postpone whatever isn't externally visible (i.e. files) and doesn't
+ * influence the result, so that kmk can get on with things ASAP.
+ *
+ * @param   pSandbox            The sandbox.
+ */
+static void kwSandboxCleanupLate(PKWSANDBOX pSandbox)
+{
+    PROCESS_MEMORY_COUNTERS     MemInfo;
+    PKWVIRTALLOC                pTracker;
+    PKWLOCALSTORAGE             pLocalStorage;
+#ifdef WITH_HASH_MD5_CACHE
+    PKWHASHMD5                  pHash;
+#endif
+#ifdef WITH_TEMP_MEMORY_FILES
+    PKWFSTEMPFILE               pTempFile;
+
+    /* The temporary files aren't externally visible, they're all in memory. */
+    pTempFile = pSandbox->pTempFileHead;
+    pSandbox->pTempFileHead = NULL;
+    while (pTempFile)
+    {
+        PKWFSTEMPFILE pNext = pTempFile->pNext;
+        KU32          iSeg  = pTempFile->cSegs;
+        while (iSeg-- > 0)
+            kHlpPageFree(pTempFile->paSegs[iSeg].pbData, pTempFile->paSegs[iSeg].cbDataAlloc);
+        kHlpFree(pTempFile->paSegs);
+        pTempFile->pNext = NULL;
+        kHlpFree(pTempFile);
+
+        pTempFile = pNext;
+    }
+#endif
+
+    /* Free left behind VirtualAlloc leaks. */
+    pTracker = g_Sandbox.pVirtualAllocHead;
+    g_Sandbox.pVirtualAllocHead = NULL;
+    while (pTracker)
+    {
+        PKWVIRTALLOC pNext = pTracker->pNext;
+        KW_LOG(("Freeing VirtualFree leak %p LB %#x\n", pTracker->pvAlloc, pTracker->cbAlloc));
+        VirtualFree(pTracker->pvAlloc, 0, MEM_RELEASE);
+        kHlpFree(pTracker);
+        pTracker = pNext;
+    }
+
+    /* Free left behind FlsAlloc leaks. */
+    pLocalStorage = g_Sandbox.pFlsAllocHead;
+    g_Sandbox.pFlsAllocHead = NULL;
+    while (pLocalStorage)
+    {
+        PKWLOCALSTORAGE pNext = pLocalStorage->pNext;
+        KW_LOG(("Freeing leaked FlsAlloc index %#x\n", pLocalStorage->idx));
+        FlsFree(pLocalStorage->idx);
+        kHlpFree(pLocalStorage);
+        pLocalStorage = pNext;
+    }
+
+    /* Free left behind TlsAlloc leaks. */
+    pLocalStorage = g_Sandbox.pTlsAllocHead;
+    g_Sandbox.pTlsAllocHead = NULL;
+    while (pLocalStorage)
+    {
+        PKWLOCALSTORAGE pNext = pLocalStorage->pNext;
+        KW_LOG(("Freeing leaked TlsAlloc index %#x\n", pLocalStorage->idx));
+        TlsFree(pLocalStorage->idx);
+        kHlpFree(pLocalStorage);
+        pLocalStorage = pNext;
+    }
+
+
+    /* Free the environment. */
+    if (pSandbox->papszEnvVars)
+    {
+        KU32 i;
+        for (i = 0; pSandbox->papszEnvVars[i]; i++)
+            kHlpFree(pSandbox->papszEnvVars[i]);
+        pSandbox->environ[0]      = NULL;
+        pSandbox->papszEnvVars[0] = NULL;
+
+        for (i = 0; pSandbox->papwszEnvVars[i]; i++)
+            kHlpFree(pSandbox->papwszEnvVars[i]);
+        pSandbox->wenviron[0]      = NULL;
+        pSandbox->papwszEnvVars[0] = NULL;
+    }
+
+#ifdef WITH_HASH_MD5_CACHE
+    /*
+     * Hash handles.
+     */
+    pHash = pSandbox->pHashHead;
+    pSandbox->pHashHead = NULL;
+    while (pHash)
+    {
+        PKWHASHMD5 pNext = pHash->pNext;
+        KWCRYPT_LOG(("Freeing leaked hash instance %#p\n", pHash));
+        kHlpFree(pHash);
+        pHash = pNext;
+    }
+#endif
+
+    /*
+     * Check the memory usage.  If it's getting high, trigger a respawn
+     * after the next job.
+     */
+    MemInfo.WorkingSetSize = 0;
+    if (GetProcessMemoryInfo(GetCurrentProcess(), &MemInfo, sizeof(MemInfo)))
+    {
+#if K_ARCH_BITS >= 64
+        if (MemInfo.WorkingSetSize >= 512*1024*1024)
+#else
+        if (MemInfo.WorkingSetSize >= 384*1024*1024)
+#endif
+        {
+            KW_LOG(("WorkingSetSize = %#x - > restart next time.\n", MemInfo.WorkingSetSize));
+            //fprintf(stderr, "WorkingSetSize = %#x - > restart next time.\n", MemInfo.WorkingSetSize);
+            g_fRestart = K_TRUE;
+        }
+    }
+}
+
+
+static void kwSandboxCleanup(PKWSANDBOX pSandbox)
+{
+    /*
+     * Restore the parent command line string.
+     */
+    PPEB pPeb = kwSandboxGetProcessEnvironmentBlock();
+    pPeb->ProcessParameters->CommandLine = pSandbox->SavedCommandLine;
+
+    /*
+     * Kill all open handles.
+     */
+    if (pSandbox->cActiveHandles > 0)
+    {
+        KU32 i = pSandbox->cHandles;
+        while (i-- > 0)
+            if (pSandbox->papHandles[i] == NULL)
+            { /* likely */ }
+            else
+            {
+                PKWHANDLE pHandle = pSandbox->papHandles[i];
+                pSandbox->papHandles[i] = NULL;
+                switch (pHandle->enmType)
+                {
+                    case KWHANDLETYPE_FSOBJ_READ_CACHE:
+                        break;
+                    case KWHANDLETYPE_TEMP_FILE:
+                    case KWHANDLETYPE_TEMP_FILE_MAPPING:
+                        pHandle->u.pTempFile->cActiveHandles--;
+                        break;
+                    default:
+                        kHlpAssertFailed();
+                }
+                kHlpFree(pHandle);
+                if (--pSandbox->cActiveHandles == 0)
+                    break;
+            }
+    }
+}
+
+
+static int kwSandboxExec(PKWSANDBOX pSandbox, PKWTOOL pTool, KU32 cArgs, const char **papszArgs, KBOOL fWatcomBrainDamange,
+                         KU32 cEnvVars, const char **papszEnvVars)
+{
+    int rcExit = 42;
+    int rc;
+
+    /*
+     * Initialize the sandbox environment.
+     */
+    rc = kwSandboxInit(&g_Sandbox, pTool, cArgs, papszArgs, fWatcomBrainDamange, cEnvVars, papszEnvVars);
+    if (rc == 0)
+    {
+        /*
+         * Do module initialization.
+         */
+        kwSandboxResetModuleState(pTool->u.Sandboxed.pExe);
+        rc = kwLdrModuleInitTree(pTool->u.Sandboxed.pExe);
+        if (rc == 0)
+        {
+            /*
+             * Call the main function.
+             */
+#if K_ARCH == K_ARCH_AMD64
+            int (*pfnWin64Entrypoint)(void *pvPeb, void *, void *, void *);
+#elif K_ARCH == K_ARCH_X86_32
+            int (__cdecl *pfnWin32Entrypoint)(void *pvPeb);
+#else
+# error "Port me!"
+#endif
+
+            /* Save the NT TIB first (should do that here, not in some other function). */
+            PNT_TIB pTib = (PNT_TIB)NtCurrentTeb();
+            pSandbox->TibMainThread = *pTib;
+
+            /* Make the call in a guarded fashion. */
+#if K_ARCH == K_ARCH_AMD64
+            /* AMD64 */
+            *(KUPTR *)&pfnWin64Entrypoint = pTool->u.Sandboxed.uMainAddr;
+            __try
+            {
+                pSandbox->pOutXcptListHead = pTib->ExceptionList;
+                if (setjmp(pSandbox->JmpBuf) == 0)
+                {
+                    *(KU64*)(pSandbox->JmpBuf) = 0; /** @todo find other way to prevent longjmp from doing unwind! */
+                    pSandbox->fRunning = K_TRUE;
+                    rcExit = pfnWin64Entrypoint(kwSandboxGetProcessEnvironmentBlock(), NULL, NULL, NULL);
+                    pSandbox->fRunning = K_FALSE;
+                }
+                else
+                    rcExit = pSandbox->rcExitCode;
+            }
+#elif K_ARCH == K_ARCH_X86_32
+            /* x86 (see _tmainCRTStartup) */
+            *(KUPTR *)&pfnWin32Entrypoint = pTool->u.Sandboxed.uMainAddr;
+            __try
+            {
+                pSandbox->pOutXcptListHead = pTib->ExceptionList;
+                if (setjmp(pSandbox->JmpBuf) == 0)
+                {
+                    //*(KU64*)(pSandbox->JmpBuf) = 0; /** @todo find other way to prevent longjmp from doing unwind! */
+                    pSandbox->fRunning = K_TRUE;
+                    rcExit = pfnWin32Entrypoint(kwSandboxGetProcessEnvironmentBlock());
+                    pSandbox->fRunning = K_FALSE;
+                }
+                else
+                    rcExit = pSandbox->rcExitCode;
+            }
+#endif
+            __except (EXCEPTION_EXECUTE_HANDLER)
+            {
+                rcExit = 512;
+            }
+            pSandbox->fRunning = K_FALSE;
+
+            /* Now, restore the NT TIB. */
+            *pTib = pSandbox->TibMainThread;
+        }
+        else
+            rcExit = 42 + 4;
+
+        /* Clean up essential bits only, the rest is done after we've replied to kmk. */
+        kwSandboxCleanup(&g_Sandbox);
+    }
+    else
+        rcExit = 42 + 3;
+
+    return rcExit;
+}
+
+
+/**
+ * Part 2 of the "JOB" command handler.
+ *
+ * @returns The exit code of the job.
+ * @param   pszExecutable   The executable to execute.
+ * @param   pszCwd          The current working directory of the job.
+ * @param   cArgs           The number of arguments.
+ * @param   papszArgs       The argument vector.
+ * @param   fWatcomBrainDamange Whether to apply watcom rules while quoting.
+ * @param   cEnvVars        The number of environment variables.
+ * @param   papszEnvVars    The enviornment vector.
+ */
+static int kSubmitHandleJobUnpacked(const char *pszExecutable, const char *pszCwd,
+                                    KU32 cArgs, const char **papszArgs, KBOOL fWatcomBrainDamange,
+                                    KU32 cEnvVars, const char **papszEnvVars)
+{
+    int rcExit;
+    PKWTOOL pTool;
+
+    /*
+     * Lookup the tool.
+     */
+    pTool = kwToolLookup(pszExecutable);
+    if (pTool)
+    {
+        /*
+         * Change the directory if we're going to execute the job inside
+         * this process.  Then invoke the tool type specific handler.
+         */
+        switch (pTool->enmType)
+        {
+            case KWTOOLTYPE_SANDBOXED:
+            case KWTOOLTYPE_WATCOM:
+            {
+                /* Change dir. */
+                KFSLOOKUPERROR  enmError;
+                PKFSOBJ         pNewCurDir = kFsCacheLookupA(g_pFsCache, pszCwd, &enmError);
+                if (   pNewCurDir           == g_pCurDirObj
+                    && pNewCurDir->bObjType == KFSOBJ_TYPE_DIR)
+                    kFsCacheObjRelease(g_pFsCache, pNewCurDir);
+                else if (SetCurrentDirectoryA(pszCwd))
+                {
+                    kFsCacheObjRelease(g_pFsCache, g_pCurDirObj);
+                    g_pCurDirObj = pNewCurDir;
+                }
+                else
+                {
+                    kwErrPrintf("SetCurrentDirectory failed with %u on '%s'\n", GetLastError(), pszCwd);
+                    kFsCacheObjRelease(g_pFsCache, pNewCurDir);
+                    rcExit = 42 + 1;
+                    break;
+                }
+
+                /* Call specific handler. */
+                if (pTool->enmType == KWTOOLTYPE_SANDBOXED)
+                {
+                    KW_LOG(("Sandboxing tool %s\n", pTool->pszPath));
+                    rcExit = kwSandboxExec(&g_Sandbox, pTool, cArgs, papszArgs, fWatcomBrainDamange, cEnvVars, papszEnvVars);
+                }
+                else
+                {
+                    kwErrPrintf("TODO: Watcom style tool %s\n", pTool->pszPath);
+                    rcExit = 42 + 2;
+                }
+                break;
+            }
+
+            case KWTOOLTYPE_EXEC:
+                kwErrPrintf("TODO: Direct exec tool %s\n", pTool->pszPath);
+                rcExit = 42 + 2;
+                break;
+
+            default:
+                kHlpAssertFailed();
+                kwErrPrintf("Internal tool type corruption!!\n");
+                rcExit = 42 + 2;
+                g_fRestart = K_TRUE;
+                break;
+        }
+    }
+    else
+        rcExit = 42 + 1;
+    return rcExit;
+}
+
+
+/**
+ * Handles a "JOB" command.
+ *
+ * @returns The exit code of the job.
+ * @param   pszMsg              Points to the "JOB" command part of the message.
+ * @param   cbMsg               Number of message bytes at @a pszMsg.  There are
+ *                              4 more zero bytes after the message body to
+ *                              simplify parsing.
+ */
+static int kSubmitHandleJob(const char *pszMsg, KSIZE cbMsg)
+{
+    int rcExit = 42;
+
+    /*
+     * Unpack the message.
+     */
+    const char     *pszExecutable;
+    KSIZE           cbTmp;
+
+    pszMsg += sizeof("JOB");
+    cbMsg  -= sizeof("JOB");
+
+    /* Executable name. */
+    pszExecutable = pszMsg;
+    cbTmp = kHlpStrLen(pszMsg) + 1;
+    pszMsg += cbTmp;
+    if (   cbTmp < cbMsg
+        && cbTmp > 2)
+    {
+        const char *pszCwd;
+        cbMsg -= cbTmp;
+
+        /* Current working directory. */
+        pszCwd = pszMsg;
+        cbTmp = kHlpStrLen(pszMsg) + 1;
+        pszMsg += cbTmp;
+        if (   cbTmp + sizeof(KU32) < cbMsg
+            && cbTmp >= 2)
+        {
+            KU32    cArgs;
+            cbMsg  -= cbTmp;
+
+            /* Argument count. */
+            kHlpMemCopy(&cArgs, pszMsg, sizeof(cArgs));
+            pszMsg += sizeof(cArgs);
+            cbMsg  -= sizeof(cArgs);
+
+            if (cArgs > 0 && cArgs < 4096)
+            {
+                /* The argument vector. */
+                char const **papszArgs = kHlpAlloc((cArgs + 1) * sizeof(papszArgs[0]));
+                if (papszArgs)
+                {
+                    KU32 i;
+                    for (i = 0; i < cArgs; i++)
+                    {
+                        papszArgs[i] = pszMsg + 1; /* First byte is expansion flags for MSC & EMX. */
+                        cbTmp = 1 + kHlpStrLen(pszMsg + 1) + 1;
+                        pszMsg += cbTmp;
+                        if (cbTmp < cbMsg)
+                            cbMsg -= cbTmp;
+                        else
+                        {
+                            cbMsg = 0;
+                            break;
+                        }
+
+                    }
+                    papszArgs[cArgs] = 0;
+
+                    /* Environment variable count. */
+                    if (cbMsg > sizeof(KU32))
+                    {
+                        KU32    cEnvVars;
+                        kHlpMemCopy(&cEnvVars, pszMsg, sizeof(cEnvVars));
+                        pszMsg += sizeof(cEnvVars);
+                        cbMsg  -= sizeof(cEnvVars);
+
+                        if (cEnvVars >= 0 && cEnvVars < 4096)
+                        {
+                            /* The argument vector. */
+                            char const **papszEnvVars = kHlpAlloc((cEnvVars + 1) * sizeof(papszEnvVars[0]));
+                            if (papszEnvVars)
+                            {
+                                KU32 i;
+                                for (i = 0; i < cEnvVars; i++)
+                                {
+                                    papszEnvVars[i] = pszMsg;
+                                    cbTmp = kHlpStrLen(pszMsg) + 1;
+                                    pszMsg += cbTmp;
+                                    if (cbTmp < cbMsg)
+                                        cbMsg -= cbTmp;
+                                    else
+                                    {
+                                        cbMsg = 0;
+                                        break;
+                                    }
+                                }
+                                papszEnvVars[cEnvVars] = 0;
+                                if (cbMsg >= sizeof(KU8))
+                                {
+                                    KBOOL fWatcomBrainDamange = *pszMsg++;
+                                    cbMsg--;
+                                    if (cbMsg == 0)
+                                    {
+                                        /*
+                                         * The next step.
+                                         */
+                                        rcExit = kSubmitHandleJobUnpacked(pszExecutable, pszCwd,
+                                                                          cArgs, papszArgs, fWatcomBrainDamange,
+                                                                          cEnvVars, papszEnvVars);
+                                    }
+                                    else
+                                        kwErrPrintf("Message has %u bytes unknown trailing bytes\n", cbMsg);
+                                }
+                                else
+                                    kwErrPrintf("Detected bogus message unpacking environment variables!\n");
+                                kHlpFree((void *)papszEnvVars);
+                            }
+                            else
+                                kwErrPrintf("Error allocating papszEnvVars for %u variables\n", cEnvVars);
+                        }
+                        else
+                            kwErrPrintf("Bogus environment variable count: %u (%#x)\n", cEnvVars, cEnvVars);
+                    }
+                    else
+                        kwErrPrintf("Detected bogus message unpacking arguments and environment variable count!\n");
+                    kHlpFree((void *)papszArgs);
+                }
+                else
+                    kwErrPrintf("Error allocating argv for %u arguments\n", cArgs);
+            }
+            else
+                kwErrPrintf("Bogus argument count: %u (%#x)\n", cArgs, cArgs);
+        }
+        else
+            kwErrPrintf("Detected bogus message unpacking CWD path and argument count!\n");
+    }
+    else
+        kwErrPrintf("Detected bogus message unpacking executable path!\n");
+    return rcExit;
+}
+
+
+/**
+ * Wrapper around WriteFile / write that writes the whole @a cbToWrite.
+ *
+ * @retval  0 on success.
+ * @retval  -1 on error (fully bitched).
+ *
+ * @param   hPipe               The pipe handle.
+ * @param   pvBuf               The buffer to write out out.
+ * @param   cbToWrite           The number of bytes to write.
+ */
+static int kSubmitWriteIt(HANDLE hPipe, const void *pvBuf, KU32 cbToWrite)
+{
+    KU8 const  *pbBuf  = (KU8 const *)pvBuf;
+    KU32        cbLeft = cbToWrite;
+    for (;;)
+    {
+        DWORD cbActuallyWritten = 0;
+        if (WriteFile(hPipe, pbBuf, cbLeft, &cbActuallyWritten, NULL /*pOverlapped*/))
+        {
+            cbLeft -= cbActuallyWritten;
+            if (!cbLeft)
+                return 0;
+            pbBuf  += cbActuallyWritten;
+        }
+        else
+        {
+            DWORD dwErr = GetLastError();
+            if (cbLeft == cbToWrite)
+                kwErrPrintf("WriteFile failed: %u\n", dwErr);
+            else
+                kwErrPrintf("WriteFile failed %u byte(s) in: %u\n", cbToWrite - cbLeft, dwErr);
+            return -1;
+        }
+    }
+}
+
+
+/**
+ * Wrapper around ReadFile / read that reads the whole @a cbToRead.
+ *
+ * @retval  0 on success.
+ * @retval  1 on shut down (fShutdownOkay must be K_TRUE).
+ * @retval  -1 on error (fully bitched).
+ * @param   hPipe               The pipe handle.
+ * @param   pvBuf               The buffer to read into.
+ * @param   cbToRead            The number of bytes to read.
+ * @param   fShutdownOkay       Whether connection shutdown while reading the
+ *                              first byte is okay or not.
+ */
+static int kSubmitReadIt(HANDLE hPipe, void *pvBuf, KU32 cbToRead, KBOOL fMayShutdown)
+{
+    KU8 *pbBuf  = (KU8 *)pvBuf;
+    KU32 cbLeft = cbToRead;
+    for (;;)
+    {
+        DWORD cbActuallyRead = 0;
+        if (ReadFile(hPipe, pbBuf, cbLeft, &cbActuallyRead, NULL /*pOverlapped*/))
+        {
+            cbLeft -= cbActuallyRead;
+            if (!cbLeft)
+                return 0;
+            pbBuf  += cbActuallyRead;
+        }
+        else
+        {
+            DWORD dwErr = GetLastError();
+            if (cbLeft == cbToRead)
+            {
+                if (   fMayShutdown
+                    && dwErr == ERROR_BROKEN_PIPE)
+                    return 1;
+                kwErrPrintf("ReadFile failed: %u\n", dwErr);
+            }
+            else
+                kwErrPrintf("ReadFile failed %u byte(s) in: %u\n", cbToRead - cbLeft, dwErr);
+            return -1;
+        }
+    }
+}
+
+
+/**
+ * Handles what comes after --test.
+ *
+ * @returns Exit code.
+ * @param   argc                Number of arguments after --test.
+ * @param   argv                Arguments after --test.
+ */
+static int kwTestRun(int argc, char **argv)
+{
+    int         i;
+    int         j;
+    int         rcExit;
+    int         cRepeats;
+    char        szCwd[MAX_PATH];
+    const char *pszCwd = getcwd(szCwd, sizeof(szCwd));
+    KU32        cEnvVars;
+    KBOOL       fWatcomBrainDamange = K_FALSE;
+
+    /*
+     * Parse arguments.
+     */
+    /* Repeat count. */
+    i = 0;
+    if (i >= argc)
+        return kwErrPrintfRc(2, "--test takes an repeat count argument or '--'!\n");
+    if (strcmp(argv[i], "--") != 0)
+    {
+        cRepeats = atoi(argv[i]);
+        if (cRepeats <= 0)
+            return kwErrPrintfRc(2, "The repeat count '%s' is zero, negative or invalid!\n", argv[i]);
+        i++;
+
+        /* Optional directory change. */
+        if (   i < argc
+            && strcmp(argv[i], "--chdir") == 0)
+        {
+            i++;
+            if (i >= argc)
+                return kwErrPrintfRc(2, "--chdir takes an argument!\n");
+            pszCwd = argv[i++];
+        }
+
+        /* Optional watcom flag directory change. */
+        if (   i < argc
+            && (   strcmp(argv[i], "--wcc-brain-damage") == 0
+                || strcmp(argv[i], "--watcom-brain-damage") == 0) )
+        {
+            fWatcomBrainDamange = K_TRUE;
+            i++;
+        }
+
+        /* Check for '--'. */
+        if (i >= argc)
+            return kwErrPrintfRc(2, "Missing '--'\n");
+        if (strcmp(argv[i], "--") != 0)
+            return kwErrPrintfRc(2, "Expected '--' found '%s'\n", argv[i]);
+        i++;
+    }
+    else
+    {
+        cRepeats = 1;
+        i++;
+    }
+    if (i >= argc)
+        return kwErrPrintfRc(2, "Nothing to execute after '--'!\n");
+
+    /*
+     * Do the job.
+     */
+    cEnvVars = 0;
+    while (environ[cEnvVars] != NULL)
+        cEnvVars++;
+
+    for (j = 0; j < cRepeats; j++)
+    {
+        rcExit = kSubmitHandleJobUnpacked(argv[i], pszCwd,
+                                          argc - i, &argv[i], fWatcomBrainDamange,
+                                          cEnvVars, environ);
+        KW_LOG(("rcExit=%d\n", rcExit));
+        kwSandboxCleanupLate(&g_Sandbox);
+    }
+
+    return rcExit;
+}
+
+#if 1
+
+int main(int argc, char **argv)
+{
+    KSIZE           cbMsgBuf = 0;
+    KU8            *pbMsgBuf = NULL;
+    int             i;
+    HANDLE          hPipe = INVALID_HANDLE_VALUE;
+    const char     *pszTmp;
+    KFSLOOKUPERROR  enmIgnored;
+#if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_X86)
+    PVOID           pvVecXcptHandler = AddVectoredExceptionHandler(0 /*called last*/, kwSandboxVecXcptEmulateChained);
+#endif
+
+    /*
+     * Create the cache and mark the temporary directory as using the custom revision.
+     */
+    g_pFsCache = kFsCacheCreate(KFSCACHE_F_MISSING_OBJECTS | KFSCACHE_F_MISSING_PATHS);
+    if (!g_pFsCache)
+        return kwErrPrintfRc(3, "kFsCacheCreate failed!\n");
+
+    pszTmp = getenv("TEMP");
+    if (pszTmp && *pszTmp != '\0')
+        kFsCacheSetupCustomRevisionForTree(g_pFsCache, kFsCacheLookupA(g_pFsCache, pszTmp, &enmIgnored));
+    pszTmp = getenv("TMP");
+    if (pszTmp && *pszTmp != '\0')
+        kFsCacheSetupCustomRevisionForTree(g_pFsCache, kFsCacheLookupA(g_pFsCache, pszTmp, &enmIgnored));
+    pszTmp = getenv("TMPDIR");
+    if (pszTmp && *pszTmp != '\0')
+        kFsCacheSetupCustomRevisionForTree(g_pFsCache, kFsCacheLookupA(g_pFsCache, pszTmp, &enmIgnored));
+
+    /*
+     * Parse arguments.
+     */
+    for (i = 1; i < argc; i++)
+    {
+        if (strcmp(argv[i], "--pipe") == 0)
+        {
+            i++;
+            if (i < argc)
+            {
+                char *pszEnd = NULL;
+                unsigned __int64 u64Value = _strtoui64(argv[i], &pszEnd, 16);
+                if (   *argv[i]
+                    && pszEnd != NULL
+                    && *pszEnd == '\0'
+                    && u64Value != 0
+                    && u64Value != (uintptr_t)INVALID_HANDLE_VALUE
+                    && (uintptr_t)u64Value == u64Value)
+                    hPipe = (HANDLE)(uintptr_t)u64Value;
+                else
+                    return kwErrPrintfRc(2, "Invalid --pipe argument: %s\n", argv[i]);
+            }
+            else
+                return kwErrPrintfRc(2, "--pipe takes an argument!\n");
+        }
+        else if (strcmp(argv[i], "--volatile") == 0)
+        {
+            i++;
+            if (i < argc)
+                kFsCacheSetupCustomRevisionForTree(g_pFsCache, kFsCacheLookupA(g_pFsCache, argv[i], &enmIgnored));
+            else
+                return kwErrPrintfRc(2, "--volatile takes an argument!\n");
+        }
+        else if (strcmp(argv[i], "--test") == 0)
+            return kwTestRun(argc - i - 1, &argv[i + 1]);
+        else if (   strcmp(argv[i], "--help") == 0
+                 || strcmp(argv[i], "-h") == 0
+                 || strcmp(argv[i], "-?") == 0)
+        {
+            printf("usage: kWorker [--volatile dir] --pipe <pipe-handle>\n"
+                   "usage: kWorker <--help|-h>\n"
+                   "usage: kWorker <--version|-V>\n"
+                   "usage: kWorker [--volatile dir] --test [<times> [--chdir <dir>]] -- args\n"
+                   "\n"
+                   "This is an internal kmk program that is used via the builtin_kSubmit.\n");
+            return 0;
+        }
+        else if (   strcmp(argv[i], "--version") == 0
+                 || strcmp(argv[i], "-V") == 0)
+            return kbuild_version(argv[0]);
+        else
+            return kwErrPrintfRc(2, "Unknown argument '%s'\n", argv[i]);
+    }
+
+    if (hPipe == INVALID_HANDLE_VALUE)
+        return kwErrPrintfRc(2, "Missing --pipe <pipe-handle> argument!\n");
+
+    /*
+     * Serve the pipe.
+     */
+    for (;;)
+    {
+        KU32 cbMsg = 0;
+        int rc = kSubmitReadIt(hPipe, &cbMsg, sizeof(cbMsg), K_TRUE /*fShutdownOkay*/);
+        if (rc == 0)
+        {
+            /* Make sure the message length is within sane bounds.  */
+            if (   cbMsg > 4
+                && cbMsg <= 256*1024*1024)
+            {
+                /* Reallocate the message buffer if necessary.  We add 4 zero bytes.  */
+                if (cbMsg + 4 <= cbMsgBuf)
+                { /* likely */ }
+                else
+                {
+                    cbMsgBuf = K_ALIGN_Z(cbMsg + 4, 2048);
+                    pbMsgBuf = kHlpRealloc(pbMsgBuf, cbMsgBuf);
+                    if (!pbMsgBuf)
+                        return kwErrPrintfRc(1, "Failed to allocate %u bytes for a message buffer!\n", cbMsgBuf);
+                }
+
+                /* Read the whole message into the buffer, making sure there is are a 4 zero bytes following it. */
+                *(KU32 *)pbMsgBuf = cbMsg;
+                rc = kSubmitReadIt(hPipe, &pbMsgBuf[sizeof(cbMsg)], cbMsg - sizeof(cbMsg), K_FALSE /*fShutdownOkay*/);
+                if (rc == 0)
+                {
+                    const char *psz;
+
+                    pbMsgBuf[cbMsg]     = '\0';
+                    pbMsgBuf[cbMsg + 1] = '\0';
+                    pbMsgBuf[cbMsg + 2] = '\0';
+                    pbMsgBuf[cbMsg + 3] = '\0';
+
+                    /* The first string after the header is the command. */
+                    psz = (const char *)&pbMsgBuf[sizeof(cbMsg)];
+                    if (strcmp(psz, "JOB") == 0)
+                    {
+                        struct
+                        {
+                            KI32 rcExitCode;
+                            KU8  bExiting;
+                            KU8  abZero[3];
+                        } Reply;
+                        Reply.rcExitCode = kSubmitHandleJob(psz, cbMsg - sizeof(cbMsg));
+                        Reply.bExiting   = g_fRestart;
+                        Reply.abZero[0]  = 0;
+                        Reply.abZero[1]  = 0;
+                        Reply.abZero[2]  = 0;
+                        rc = kSubmitWriteIt(hPipe, &Reply, sizeof(Reply));
+                        if (   rc == 0
+                            && !g_fRestart)
+                        {
+                            kwSandboxCleanupLate(&g_Sandbox);
+                            continue;
+                        }
+                    }
+                    else
+                        rc = kwErrPrintfRc(-1, "Unknown command: '%s'\n", psz);
+                }
+            }
+            else
+                rc = kwErrPrintfRc(-1, "Bogus message length: %u (%#x)\n", cbMsg, cbMsg);
+        }
+
+        /*
+         * If we're exitting because we're restarting, we need to delay till
+         * kmk/kSubmit has read the result.  Windows documentation says it
+         * immediately discards pipe buffers once the pipe is broken by the
+         * server (us).  So, We flush the buffer and queues a 1 byte read
+         * waiting for kSubmit to close the pipe when it receives the
+         * bExiting = K_TRUE result.
+         */
+        if (g_fRestart)
+        {
+            KU8 b;
+            FlushFileBuffers(hPipe);
+            ReadFile(hPipe, &b, 1, &cbMsg, NULL);
+        }
+
+        CloseHandle(hPipe);
+        return rc > 0 ? 0 : 1;
+    }
+}
+
+#else
+
+static int kwExecCmdLine(const char *pszExe, const char *pszCmdLine)
+{
+    int rc;
+    PKWTOOL pTool = kwToolLookup(pszExe);
+    if (pTool)
+    {
+        int rcExitCode;
+        switch (pTool->enmType)
+        {
+            case KWTOOLTYPE_SANDBOXED:
+                KW_LOG(("Sandboxing tool %s\n", pTool->pszPath));
+                rc = kwSandboxExec(&g_Sandbox, pTool, pszCmdLine, &rcExitCode);
+                break;
+            default:
+                kHlpAssertFailed();
+                KW_LOG(("TODO: Direct exec tool %s\n", pTool->pszPath));
+                rc = rcExitCode = 2;
+                break;
+        }
+        KW_LOG(("rcExitCode=%d (rc=%d)\n", rcExitCode, rc));
+    }
+    else
+        rc = 1;
+    return rc;
+}
+
+int main(int argc, char **argv)
+{
+    int rc = 0;
+    int i;
+    argv[2] = "\"E:/vbox/svn/trunk/tools/win.x86/vcc/v10sp1/bin/amd64/cl.exe\" -c -c -TP -nologo -Zi -Zi -Zl -GR- -EHsc -GF -Zc:wchar_t- -Oy- -MT -W4 -Wall -wd4065 -wd4996 -wd4127 -wd4706 -wd4201 -wd4214 -wd4510 -wd4512 -wd4610 -wd4514 -wd4820 -wd4365 -wd4987 -wd4710 -wd4061 -wd4986 -wd4191 -wd4574 -wd4917 -wd4711 -wd4611 -wd4571 -wd4324 -wd4505 -wd4263 -wd4264 -wd4738 -wd4242 -wd4244 -WX -RTCsu -IE:/vbox/svn/trunk/tools/win.x86/vcc/v10sp1/include -IE:/vbox/svn/trunk/tools/win.x86/vcc/v1 [...]
+# if 0
+    rc = kwExecCmdLine(argv[1], argv[2]);
+    rc = kwExecCmdLine(argv[1], argv[2]);
+    K_NOREF(i);
+# else
+// Skylake (W10/amd64, only stdandard MS defender):
+//     cmd 1:  48    /1024 = 0x0 (0.046875)        [for /l %i in (1,1,1024) do ...]
+//     kmk 1:  44    /1024 = 0x0 (0.04296875)      [all: ; 1024 x cl.exe]
+//     run 1:  37    /1024 = 0x0 (0.0361328125)    [just process creation gain]
+//     run 2:  34    /1024 = 0x0 (0.033203125)     [get file attribs]
+//     run 3:  32.77 /1024 = 0x0 (0.032001953125)  [read caching of headers]
+//     run 4:  32.67 /1024 = 0x0 (0.031904296875)  [loader tweaking]
+//     run 5:  29.144/1024 = 0x0 (0.0284609375)    [with temp files in memory]
+//    r2881 building src/VBox/Runtime:
+//     without: 2m01.016388s = 120.016388 s
+//     with:    1m15.165069s = 75.165069 s => 120.016388s - 75.165069s = 44.851319s => 44.85/120.02 = 37% speed up.
+//    r2884 building vbox/debug (r110512):
+//     without: 11m14.446609s = 674.446609 s
+//     with:     9m01.017344s = 540.017344 s => 674.446609s - 540.017344s = 134.429265s => 134.43/674.45 = 20% speed up
+//
+// Dell (W7/amd64, infected by mcafee):
+//     kmk 1: 285.278/1024 = 0x0 (0.278591796875)
+//     run 1: 134.503/1024 = 0x0 (0.1313505859375) [w/o temp files in memory]
+//     run 2:  78.161/1024 = 0x0 (0.0763291015625) [with temp files in memory]
+    g_cVerbose = 0;
+    for (i = 0; i < 1024 && rc == 0; i++)
+        rc = kwExecCmdLine(argv[1], argv[2]);
+# endif
+    return rc;
+}
+
+#endif
+
diff --git a/src/kWorker/tst-1-c1xx-xcpt.cpp b/src/kWorker/tst-1-c1xx-xcpt.cpp
new file mode 100644
index 0000000..31540f1
--- /dev/null
+++ b/src/kWorker/tst-1-c1xx-xcpt.cpp
@@ -0,0 +1,345 @@
+/* $Id: tst-1-c1xx-xcpt.cpp 2865 2016-09-02 22:17:13Z bird $ */
+
+/*
+ * kWorker testcase.
+ *
+ * This is a testcase sitched together from bits of iprt/cdefs.h,
+ * iprt/assert.h and VBox/vmm/hm_vmx.h.
+ *
+ * It triggers an 0xc0000005 exception (#PF) via RT_BF_ASSERT_COMPILE_CHECKS,
+ * guess this is due to deep preprocessor expansion nesting (around 32 levels).
+ *
+ * This doesn't work if we haven't got the exception handling right,
+ * like the RtlAddFunctionTable and RtlDeleteFunctionTable calls.
+ *
+ */
+
+/* glue */
+#define UINT32_C(x) x##U
+#define UINT32_MAX  0xffffffffU
+
+
+/** @file
+ * IPRT - Common C and C++ definitions.
+ */
+
+/*
+ * Copyright (C) 2006-2016 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+/** @def RT_EXPAND_2
+ * Helper for RT_EXPAND. */
+#define RT_EXPAND_2(a_Expr)     a_Expr
+/** @def RT_EXPAND
+ * Returns the expanded expression.
+ * @param   a_Expr              The expression to expand. */
+#define RT_EXPAND(a_Expr)       RT_EXPAND_2(a_Expr)
+
+
+/** @def RT_UNPACK_CALL
+ * Unpacks the an argument list inside an extra set of parenthesis and turns it
+ * into a call to @a a_Fn.
+ *
+ * @param   a_Fn        Function/macro to call.
+ * @param   a_Args      Parameter list in parenthesis.
+ */
+#define RT_UNPACK_CALL(a_Fn, a_Args) a_Fn a_Args
+
+
+/** @def RT_UNPACK_ARGS
+ * Returns the arguments without parenthesis.
+ *
+ * @param   ...         Parameter list in parenthesis.
+ * @remarks Requires RT_COMPILER_SUPPORTS_VA_ARGS.
+ */
+# define RT_UNPACK_ARGS(...)    __VA_ARGS__
+
+/** @def RT_COUNT_VA_ARGS_HLP
+ * Helper for RT_COUNT_VA_ARGS that picks out the argument count from
+ * RT_COUNT_VA_ARGS_REV_SEQ. */
+#define RT_COUNT_VA_ARGS_HLP( \
+    c69, c68, c67, c66, c65, c64, c63, c62, c61, c60, \
+    c59, c58, c57, c56, c55, c54, c53, c52, c51, c50, \
+    c49, c48, c47, c46, c45, c44, c43, c42, c41, c40, \
+    c39, c38, c37, c36, c35, c34, c33, c32, c31, c30, \
+    c29, c28, c27, c26, c25, c24, c23, c22, c21, c20, \
+    c19, c18, c17, c16, c15, c14, c13, c12, c11, c10, \
+     c9,  c8,  c7,  c6,  c5,  c4,  c3,  c2,  c1, cArgs, ...) cArgs
+/** Argument count sequence. */
+#define RT_COUNT_VA_ARGS_REV_SEQ \
+     69,  68,  67,  66,  65,  64,  63,  62,  61,  60, \
+     59,  58,  57,  56,  55,  54,  53,  52,  51,  50, \
+     49,  48,  47,  46,  45,  44,  43,  42,  41,  40, \
+     39,  38,  37,  36,  35,  34,  33,  32,  31,  30, \
+     29,  28,  27,  26,  25,  24,  23,  22,  21,  20, \
+     19,  18,  17,  16,  15,  14,  13,  12,  11,  10, \
+      9,   8,   7,   6,   5,   4,   3,   2,   1,   0
+/** This is for zero arguments. At least Visual C++ requires it. */
+#define RT_COUNT_VA_ARGS_PREFIX_RT_NOTHING       RT_COUNT_VA_ARGS_REV_SEQ
+/**
+ * Counts the number of arguments given to the variadic macro.
+ *
+ * Max is 69.
+ *
+ * @returns Number of arguments in the ellipsis
+ * @param   ...     Arguments to count.
+ * @remarks Requires RT_COMPILER_SUPPORTS_VA_ARGS.
+ */
+#define RT_COUNT_VA_ARGS(...) \
+      RT_UNPACK_CALL(RT_COUNT_VA_ARGS_HLP, (RT_COUNT_VA_ARGS_PREFIX_ ## __VA_ARGS__ ## RT_NOTHING, \
+                                            RT_COUNT_VA_ARGS_REV_SEQ))
+/** @def RT_CONCAT
+ * Concatenate the expanded arguments without any extra spaces in between.
+ *
+ * @param   a       The first part.
+ * @param   b       The second part.
+ */
+#define RT_CONCAT(a,b)              RT_CONCAT_HLP(a,b)
+/** RT_CONCAT helper, don't use.  */
+#define RT_CONCAT_HLP(a,b)          a##b
+
+/** @def RT_CONCAT3
+ * Concatenate the expanded arguments without any extra spaces in between.
+ *
+ * @param   a       The 1st part.
+ * @param   b       The 2nd part.
+ * @param   c       The 3rd part.
+ */
+#define RT_CONCAT3(a,b,c)           RT_CONCAT3_HLP(a,b,c)
+/** RT_CONCAT3 helper, don't use.  */
+#define RT_CONCAT3_HLP(a,b,c)       a##b##c
+
+/** Bit field compile time check helper
+ * @internal */
+#define RT_BF_CHECK_DO_XOR_MASK(a_uLeft, a_RightPrefix, a_FieldNm)  ((a_uLeft) ^ RT_CONCAT3(a_RightPrefix, a_FieldNm, _MASK))
+/** Bit field compile time check helper
+ * @internal */
+#define RT_BF_CHECK_DO_OR_MASK(a_uLeft, a_RightPrefix, a_FieldNm)   ((a_uLeft) | RT_CONCAT3(a_RightPrefix, a_FieldNm, _MASK))
+/** Bit field compile time check helper
+ * @internal */
+#define RT_BF_CHECK_DO_1ST_MASK_BIT(a_uLeft, a_RightPrefix, a_FieldNm) \
+    ((a_uLeft) && ( (RT_CONCAT3(a_RightPrefix, a_FieldNm, _MASK) >> RT_CONCAT3(a_RightPrefix, a_FieldNm, _SHIFT)) & 1U ) )
+/** Used to check that a bit field mask does not start too early.
+ * @internal */
+#define RT_BF_CHECK_DO_MASK_START(a_uLeft, a_RightPrefix, a_FieldNm) \
+    (   (a_uLeft) \
+     && (   RT_CONCAT3(a_RightPrefix, a_FieldNm, _SHIFT) == 0 \
+         || (  (  (   ((RT_CONCAT3(a_RightPrefix, a_FieldNm, _MASK) >> RT_CONCAT3(a_RightPrefix, a_FieldNm, _SHIFT)) & 1U) \
+                   << RT_CONCAT3(a_RightPrefix, a_FieldNm, _SHIFT)) /* => single bit mask, correct type */ \
+                - 1U) /* => mask of all bits below the field */ \
+             & RT_CONCAT3(a_RightPrefix, a_FieldNm, _MASK)) == 0 ) )
+/** @name Bit field compile time check recursion workers.
+ * @internal
+ * @{  */
+#define RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix, f1) \
+    a_DoThis(a_uLeft, a_RightPrefix, f1)
+#define RT_BF_CHECK_DO_2(a_DoThis, a_uLeft, a_RightPrefix,                                        f1, f2) \
+    RT_BF_CHECK_DO_1(a_DoThis,  RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2)
+#define RT_BF_CHECK_DO_3(a_DoThis, a_uLeft, a_RightPrefix,                                        f1, f2, f3) \
+    RT_BF_CHECK_DO_2(a_DoThis,  RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3)
+#define RT_BF_CHECK_DO_4(a_DoThis, a_uLeft, a_RightPrefix,                                        f1, f2, f3, f4) \
+    RT_BF_CHECK_DO_3(a_DoThis,  RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4)
+#define RT_BF_CHECK_DO_5(a_DoThis, a_uLeft, a_RightPrefix,                                        f1, f2, f3, f4, f5) \
+    RT_BF_CHECK_DO_4(a_DoThis,  RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5)
+#define RT_BF_CHECK_DO_6(a_DoThis, a_uLeft, a_RightPrefix,                                        f1, f2, f3, f4, f5, f6) \
+    RT_BF_CHECK_DO_5(a_DoThis,  RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6)
+#define RT_BF_CHECK_DO_7(a_DoThis, a_uLeft, a_RightPrefix,                                        f1, f2, f3, f4, f5, f6, f7) \
+    RT_BF_CHECK_DO_6(a_DoThis,  RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7)
+#define RT_BF_CHECK_DO_8(a_DoThis, a_uLeft, a_RightPrefix,                                        f1, f2, f3, f4, f5, f6, f7, f8) \
+    RT_BF_CHECK_DO_7(a_DoThis,  RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8)
+#define RT_BF_CHECK_DO_9(a_DoThis, a_uLeft, a_RightPrefix,                                        f1, f2, f3, f4, f5, f6, f7, f8, f9) \
+    RT_BF_CHECK_DO_8(a_DoThis,  RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9)
+#define RT_BF_CHECK_DO_10(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \
+    RT_BF_CHECK_DO_9(a_DoThis,  RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10)
+#define RT_BF_CHECK_DO_11(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \
+    RT_BF_CHECK_DO_10(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11)
+#define RT_BF_CHECK_DO_12(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12) \
+    RT_BF_CHECK_DO_11(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12)
+#define RT_BF_CHECK_DO_13(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13) \
+    RT_BF_CHECK_DO_12(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13)
+#define RT_BF_CHECK_DO_14(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14) \
+    RT_BF_CHECK_DO_13(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14)
+#define RT_BF_CHECK_DO_15(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15) \
+    RT_BF_CHECK_DO_14(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15)
+#define RT_BF_CHECK_DO_16(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16) \
+    RT_BF_CHECK_DO_15(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16)
+#define RT_BF_CHECK_DO_17(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17) \
+    RT_BF_CHECK_DO_16(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17)
+#define RT_BF_CHECK_DO_18(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18) \
+    RT_BF_CHECK_DO_17(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18)
+#define RT_BF_CHECK_DO_19(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19) \
+    RT_BF_CHECK_DO_18(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19)
+#define RT_BF_CHECK_DO_20(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20) \
+    RT_BF_CHECK_DO_19(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20)
+#define RT_BF_CHECK_DO_21(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21) \
+    RT_BF_CHECK_DO_20(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21)
+#define RT_BF_CHECK_DO_22(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22) \
+    RT_BF_CHECK_DO_21(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22)
+#define RT_BF_CHECK_DO_23(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23) \
+    RT_BF_CHECK_DO_22(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23)
+#define RT_BF_CHECK_DO_24(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24) \
+    RT_BF_CHECK_DO_23(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24)
+#define RT_BF_CHECK_DO_25(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25) \
+    RT_BF_CHECK_DO_24(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25)
+#define RT_BF_CHECK_DO_26(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26) \
+    RT_BF_CHECK_DO_25(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26)
+#define RT_BF_CHECK_DO_27(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27) \
+    RT_BF_CHECK_DO_26(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27)
+#define RT_BF_CHECK_DO_28(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28) \
+    RT_BF_CHECK_DO_27(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28)
+#define RT_BF_CHECK_DO_29(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28, f29) \
+    RT_BF_CHECK_DO_28(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28, f29)
+#define RT_BF_CHECK_DO_30(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28, f29, f30) \
+    RT_BF_CHECK_DO_29(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28, f29, f30)
+#define RT_BF_CHECK_DO_31(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28, f29, f30, f31) \
+    RT_BF_CHECK_DO_30(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28, f29, f30, f31)
+#define RT_BF_CHECK_DO_32(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28, f29, f30, f31, f32) \
+    RT_BF_CHECK_DO_31(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28, f29, f30, f31, f32)
+#define RT_BF_CHECK_DO_33(a_DoThis, a_uLeft, a_RightPrefix,                                       f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28, f29, f30, f31, f32, f33) \
+    RT_BF_CHECK_DO_32(a_DoThis, RT_BF_CHECK_DO_1(a_DoThis, a_uLeft, a_RightPrefix,f1), a_RightPrefix, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28, f29, f30, f31, f32, f33)
+/** @} */
+
+/** @def RT_BF_ASSERT_COMPILE_CHECKS
+ * Emits a series of AssertCompile statements checking that the bit-field
+ * declarations doesn't overlap, has holes, and generally makes some sense.
+ *
+ * This requires variadic macros because its too much to type otherwise.
+ */
+#define RT_BF_ASSERT_COMPILE_CHECKS(a_Prefix, a_uZero, a_uCovered, a_Fields) \
+    AssertCompile(RT_BF_CHECK_DO_N(RT_BF_CHECK_DO_OR_MASK,     a_uZero, a_Prefix, RT_UNPACK_ARGS a_Fields ) == a_uCovered); \
+    AssertCompile(RT_BF_CHECK_DO_N(RT_BF_CHECK_DO_XOR_MASK, a_uCovered, a_Prefix, RT_UNPACK_ARGS a_Fields ) == 0); \
+    AssertCompile(RT_BF_CHECK_DO_N(RT_BF_CHECK_DO_1ST_MASK_BIT,   true, a_Prefix, RT_UNPACK_ARGS a_Fields ) == true); \
+    AssertCompile(RT_BF_CHECK_DO_N(RT_BF_CHECK_DO_MASK_START,     true, a_Prefix, RT_UNPACK_ARGS a_Fields ) == true)
+/** Bit field compile time check helper
+ * @internal */
+#define RT_BF_CHECK_DO_N(a_DoThis, a_uLeft, a_RightPrefix, ...) \
+        RT_UNPACK_CALL(RT_CONCAT(RT_BF_CHECK_DO_, RT_EXPAND(RT_COUNT_VA_ARGS(__VA_ARGS__))), (a_DoThis, a_uLeft, a_RightPrefix, __VA_ARGS__))
+
+
+/** @file
+ * IPRT - Assertions.
+ */
+
+/*
+ * Copyright (C) 2006-2016 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+/** @def AssertCompile
+ * Asserts that a C++0x compile-time expression is true. If it's not break the
+ * build.
+ * @param   expr    Expression which should be true.
+ */
+#define AssertCompile(expr)    static_assert(!!(expr), #expr)
+
+
+
+
+/** @file
+ * HM - VMX Structures and Definitions. (VMM)
+ */
+
+/*
+ * Copyright (C) 2006-2016 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+/** Address calculation scaling field (powers of two). */
+#define VMX_XDTR_INSINFO_SCALE_SHIFT                            0
+#define VMX_XDTR_INSINFO_SCALE_MASK                             UINT32_C(0x00000003)
+/** Bits 2 thru 6 are undefined. */
+#define VMX_XDTR_INSINFO_UNDEF_2_6_SHIFT                        2
+#define VMX_XDTR_INSINFO_UNDEF_2_6_MASK                         UINT32_C(0x0000007c)
+/** Address size, only 0(=16), 1(=32) and 2(=64) are defined.
+ * @remarks anyone's guess why this is a 3 bit field...  */
+#define VMX_XDTR_INSINFO_ADDR_SIZE_SHIFT                        7
+#define VMX_XDTR_INSINFO_ADDR_SIZE_MASK                         UINT32_C(0x00000380)
+/** Bit 10 is defined as zero. */
+#define VMX_XDTR_INSINFO_ZERO_10_SHIFT                          10
+#define VMX_XDTR_INSINFO_ZERO_10_MASK                           UINT32_C(0x00000400)
+/** Operand size, either (1=)32-bit or (0=)16-bit, but get this, it's undefined
+ * for exits from 64-bit code as the operand size there is fixed. */
+#define VMX_XDTR_INSINFO_OP_SIZE_SHIFT                          11
+#define VMX_XDTR_INSINFO_OP_SIZE_MASK                           UINT32_C(0x00000800)
+/** Bits 12 thru 14 are undefined. */
+#define VMX_XDTR_INSINFO_UNDEF_12_14_SHIFT                      12
+#define VMX_XDTR_INSINFO_UNDEF_12_14_MASK                       UINT32_C(0x00007000)
+/** Applicable segment register (X86_SREG_XXX values). */
+#define VMX_XDTR_INSINFO_SREG_SHIFT                             15
+#define VMX_XDTR_INSINFO_SREG_MASK                              UINT32_C(0x00038000)
+/** Index register (X86_GREG_XXX values). Undefined if HAS_INDEX_REG is clear. */
+#define VMX_XDTR_INSINFO_INDEX_REG_SHIFT                        18
+#define VMX_XDTR_INSINFO_INDEX_REG_MASK                         UINT32_C(0x003c0000)
+/** Is VMX_XDTR_INSINFO_INDEX_REG_XXX valid (=1) or not (=0). */
+#define VMX_XDTR_INSINFO_HAS_INDEX_REG_SHIFT                    22
+#define VMX_XDTR_INSINFO_HAS_INDEX_REG_MASK                     UINT32_C(0x00400000)
+/** Base register (X86_GREG_XXX values). Undefined if HAS_BASE_REG is clear. */
+#define VMX_XDTR_INSINFO_BASE_REG_SHIFT                         23
+#define VMX_XDTR_INSINFO_BASE_REG_MASK                          UINT32_C(0x07800000)
+/** Is VMX_XDTR_INSINFO_BASE_REG_XXX valid (=1) or not (=0). */
+#define VMX_XDTR_INSINFO_HAS_BASE_REG_SHIFT                     27
+#define VMX_XDTR_INSINFO_HAS_BASE_REG_MASK                      UINT32_C(0x08000000)
+/** The instruction identity (VMX_XDTR_INSINFO_II_XXX values) */
+#define VMX_XDTR_INSINFO_INSTR_ID_SHIFT                         28
+#define VMX_XDTR_INSINFO_INSTR_ID_MASK                          UINT32_C(0x30000000)
+#define VMX_XDTR_INSINFO_II_SGDT                                0 /**< Instruction ID: SGDT */
+#define VMX_XDTR_INSINFO_II_SIDT                                1 /**< Instruction ID: SIDT */
+#define VMX_XDTR_INSINFO_II_LGDT                                2 /**< Instruction ID: LGDT */
+#define VMX_XDTR_INSINFO_II_LIDT                                3 /**< Instruction ID: LIDT */
+/** Bits 30 & 31 are undefined. */
+#define VMX_XDTR_INSINFO_UNDEF_30_31_SHIFT                      30
+#define VMX_XDTR_INSINFO_UNDEF_30_31_MASK                       UINT32_C(0xc0000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_XDTR_INSINFO_, UINT32_C(0), UINT32_MAX,
+                            (SCALE, UNDEF_2_6, ADDR_SIZE, ZERO_10, OP_SIZE, UNDEF_12_14, SREG, INDEX_REG, HAS_INDEX_REG,
+                             BASE_REG, HAS_BASE_REG, INSTR_ID, UNDEF_30_31));
+
+
diff --git a/src/kmk/Makefile.kmk b/src/kmk/Makefile.kmk
index aa07e1b..80c5168 100644
--- a/src/kmk/Makefile.kmk
+++ b/src/kmk/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 2801 2015-09-20 19:13:24Z bird $
+# $Id: Makefile.kmk 2886 2016-09-06 14:31:46Z bird $
 ## @file
 # Sub-makefile for kmk / GNU Make.
 #
@@ -87,7 +87,6 @@ kmkmissing_SOURCES = \
 	kmkbuiltin/fts.c \
 	kmkbuiltin/setmode.c \
 	kmkbuiltin/strmode.c \
-	kmkbuiltin/kbuild_version.c \
 	kmkbuiltin/kbuild_protection.c \
 	getopt.c \
 	getopt1.c \
@@ -128,7 +127,6 @@ kmkmissing_SOURCES.win += \
 	glob/fnmatch.c \
 	getloadavg.c \
 	w32/subproc/misc.c \
-	w32/subproc/sub_proc.c \
 	w32/subproc/w32err.c \
 	w32/pathstuff.c \
 	w32/imagecache.c
@@ -193,11 +191,11 @@ kmk_DEFS = \
 	CONFIG_WITH_RDONLY_VARIABLE_VALUE \
 	CONFIG_WITH_LAZY_DEPS_VARS \
 	CONFIG_WITH_MEMORY_OPTIMIZATIONS \
-	CONFIG_WITH_COMPILER \
 	\
 	KBUILD_HOST=\"$(KBUILD_TARGET)\" \
 	KBUILD_HOST_ARCH=\"$(KBUILD_TARGET_ARCH)\" \
 	KBUILD_HOST_CPU=\"$(KBUILD_TARGET_CPU)\"
+# kmk_DEFS += CONFIG_WITH_COMPILER  # experimental, doesn't work 101% right it seems.
 kmk_DEFS.x86 = CONFIG_WITH_OPTIMIZATION_HACKS
 kmk_DEFS.amd64 = CONFIG_WITH_OPTIMIZATION_HACKS
 kmk_DEFS.win = CONFIG_NEW_WIN32_CTRL_EVENT CONFIG_WITH_FAST_IS_SPACE
@@ -222,7 +220,6 @@ kmk_SOURCES = \
 	arscan.c \
 	commands.c \
 	default.c \
-	dir.c \
 	expand.c \
 	file.c \
 	function.c \
@@ -243,6 +240,14 @@ kmk_SOURCES = \
        kmk_cc_exec.c \
 	kbuild.c \
 	kbuild-object.c
+ifeq ($(KBUILD_TARGET),win)
+ kmk_SOURCES += dir-nt-bird.c
+else
+ kmk_SOURCES += dir.c
+endif
+
+kmk_SOURCES.win = \
+	w32/subproc/sub_proc.c
 
 kmk_DEFS.freebsd.x86 = CONFIG_WITHOUT_THREADS
 
@@ -253,7 +258,7 @@ kmk_DEFS.freebsd.x86 = CONFIG_WITHOUT_THREADS
 # kmkbuiltin commands
 #
 kmk_DEFS += CONFIG_WITH_KMK_BUILTIN
-kmk_LIBS += $(LIB_KUTIL) $(LIB_KDEP)
+kmk_LIBS += $(LIB_KUTIL) #$(LIB_KDEP)
 kmk_SOURCES += \
 	kmkbuiltin.c \
 	kmkbuiltin/append.c \
@@ -268,6 +273,7 @@ kmk_SOURCES += \
 	kmkbuiltin/install.c \
 	kmkbuiltin/kDepIDB.c \
 	kmkbuiltin/kDepObj.c \
+	../lib/kDep.c \
 	kmkbuiltin/md5sum.c \
 	kmkbuiltin/mkdir.c \
 	kmkbuiltin/mv.c \
@@ -275,8 +281,9 @@ kmk_SOURCES += \
 	kmkbuiltin/printf.c \
 	kmkbuiltin/rm.c \
 	kmkbuiltin/rmdir.c \
+	kmkbuiltin/kSubmit.c \
 	kmkbuiltin/sleep.c \
-	kmkbuiltin/test.c \
+	kmkbuiltin/test.c
 
 ## @todo kmkbuiltin/redirect.c
 
@@ -411,14 +418,14 @@ kmk_test_SOURCES = \
 kDepIDB_TEMPLATE = BIN-KMK
 kDepIDB_DEFS = kmk_builtin_kDepIDB=main
 kDepIDB_INCS = .
-kDepIDB_LIBS = $(LIB_KDEP)
+kDepIDB_LIBS = $(LIB_KDEP) $(LIB_KUTIL)
 kDepIDB_SOURCES = \
 	kmkbuiltin/kDepIDB.c
 
 kDepObj_TEMPLATE = BIN-KMK
 kDepObj_DEFS = kmk_builtin_kDepObj=main
 kDepObj_INCS = .
-kDepObj_LIBS = $(LIB_KDEP)
+kDepObj_LIBS = $(LIB_KDEP) $(LIB_KUTIL)
 kDepObj_SOURCES = \
 	kmkbuiltin/kDepObj.c
 
@@ -459,6 +466,9 @@ kmk_gmake_SOURCES = \
 	vpath.c \
 	remote-stub.c
 
+kmk_gmake_SOURCES.win = \
+	w32/subproc/sub_proc.c
+
 
 #
 # kmk_fmake - Faster GNU Make.
@@ -509,6 +519,17 @@ kmk_fgmake_SOURCES = \
 	vpath.c \
 	remote-stub.c
 
+kmk_fgmake_SOURCES.win = \
+	w32/subproc/sub_proc.c
+
+
+#
+# tstFileInfo
+#
+PROGRAMS.win += tstFileInfo
+tstFileInfo_TEMPLATE = BIN
+tstFileInfo_SOURCES = w32/tstFileInfo.c
+
 
 include $(FILE_KBUILD_SUB_FOOTER)
 
diff --git a/src/kmk/config.h.win b/src/kmk/config.h.win
index 64e42d7..d6d3c17 100644
--- a/src/kmk/config.h.win
+++ b/src/kmk/config.h.win
@@ -442,7 +442,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
 #define gid_t int
 
 /* Define to `int' if <sys/types.h> does not define. */
-#define pid_t int
+/* Note (bird)! sub_proc.c needs this to be pointer sized. */
+#define pid_t intptr_t
 
 /* Define to `int' if <sys/types.h> doesn't define. */
 #define uid_t int
diff --git a/src/kmk/dir-nt-bird.c b/src/kmk/dir-nt-bird.c
new file mode 100644
index 0000000..cd8ad6d
--- /dev/null
+++ b/src/kmk/dir-nt-bird.c
@@ -0,0 +1,587 @@
+/* $Id: dir-nt-bird.c 2886 2016-09-06 14:31:46Z bird $ */
+/** @file
+ * Reimplementation of dir.c for NT using kFsCache.
+ *
+ * This should perform better on NT, especially on machines "infected"
+ * by antivirus programs.
+ */
+
+/*
+ * Copyright (c) 2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * kBuild 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 kBuild.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "nt/kFsCache.h"
+#include "make.h"
+#if defined(KMK) && !defined(__OS2__)
+# include "glob/glob.h"
+#else
+# include <glob.h>
+#endif
+
+
+#include "nt_fullpath.h" /* for the time being - will be implemented here later on. */
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+/** User data key indicating that it's an impossible file to make.
+ * See file_impossible() and file_impossible_p(). */
+#define KMK_DIR_NT_IMPOSSIBLE_KEY   (~(KUPTR)7)
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * glob directory stream.
+ */
+typedef struct KMKNTOPENDIR
+{
+    /** Reference to the directory. */
+    PKFSDIR         pDir;
+    /** Index of the next directory entry (child) to return. */
+    KU32            idxNext;
+    /** The structure in which to return the directory entry.   */
+    struct dirent   DirEnt;
+} KMKNTOPENDIR;
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** The cache.*/
+PKFSCACHE   g_pFsCache = NULL;
+/** Number of times dir_cache_invalid_missing was called. */
+static KU32 g_cInvalidates = 0;
+/** Set by dir_cache_volatile_dir to indicate that the user has marked the
+ * volatile parts of the file system with custom revisioning and we only need to
+ * flush these.  This is very handy when using a separate output directory
+ * from the sources.  */
+static KBOOL g_fFsCacheIsUsingCustomRevision = K_FALSE;
+
+
+void hash_init_directories(void)
+{
+    g_pFsCache = kFsCacheCreate(0);
+    if (g_pFsCache)
+        return;
+    fputs("kFsCacheCreate failed!", stderr);
+    exit(9);
+}
+
+
+/**
+ * Checks if @a pszName exists in directory @a pszDir.
+ *
+ * @returns 1 if it does, 0 if it doesn't.
+ *
+ * @param   pszDir      The directory.
+ * @param   pszName     The name.
+ *
+ *                      If empty string, just check if the directory exists.
+ *
+ *                      If NULL, just read the whole cache the directory into
+ *                      the cache (we always do that).
+ */
+int dir_file_exists_p(const char *pszDir, const char *pszName)
+{
+    int             fRc     = 0;
+    KFSLOOKUPERROR  enmError;
+    PKFSOBJ         pDirObj = kFsCacheLookupA(g_pFsCache, pszDir, &enmError);
+    if (pDirObj)
+    {
+        if (pDirObj->bObjType == KFSOBJ_TYPE_DIR)
+        {
+            if (pszName != 0)
+            {
+                /* Empty filename is just checking out the directory. */
+                if (*pszName == '\0')
+                    fRc = 1;
+                else
+                {
+                    PKFSOBJ pNameObj = kFsCacheLookupRelativeToDirA(g_pFsCache, (PKFSDIR)pDirObj,
+                                                                    pszName, strlen(pszName), &enmError, NULL);
+                    if (pNameObj)
+                    {
+                        fRc = pNameObj->bObjType == KFSOBJ_TYPE_MISSING;
+                        kFsCacheObjRelease(g_pFsCache, pNameObj);
+                    }
+                }
+            }
+        }
+        kFsCacheObjRelease(g_pFsCache, pDirObj);
+    }
+    return fRc;
+}
+
+
+/**
+ * Checks if a file exists.
+ *
+ * @returns 1 if it does exist, 0 if it doesn't.
+ * @param   pszPath     The path to check out.
+ */
+int file_exists_p(const char *pszPath)
+{
+    int             fRc;
+    KFSLOOKUPERROR  enmError;
+    PKFSOBJ         pPathObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError);
+    if (pPathObj)
+    {
+        fRc = pPathObj->bObjType != KFSOBJ_TYPE_MISSING;
+        kFsCacheObjRelease(g_pFsCache, pPathObj);
+    }
+    else
+        fRc = 0;
+    return fRc;
+}
+
+
+/**
+ * Just a way for vpath.c to get a correctly cased path, I think.
+ *
+ * @returns Directory path in string cache.
+ * @param   pszDir      The directory.
+ */
+const char *dir_name(const char *pszDir)
+{
+    char szTmp[MAX_PATH];
+    nt_fullpath(pszDir, szTmp, sizeof(szTmp));
+    return strcache_add(szTmp);
+}
+
+
+/**
+ * Makes future file_impossible_p calls return 1 for pszPath.
+ */
+void file_impossible(const char *pszPath)
+{
+    KFSLOOKUPERROR  enmError;
+    PKFSOBJ         pPathObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError);
+    if (pPathObj)
+    {
+        kFsCacheObjAddUserData(g_pFsCache, pPathObj, KMK_DIR_NT_IMPOSSIBLE_KEY, sizeof(KFSUSERDATA));
+        kFsCacheObjRelease(g_pFsCache, pPathObj);
+    }
+}
+
+/**
+ * Makes future file_impossible_p calls return 1 for pszPath.
+ */
+int file_impossible_p(const char *pszPath)
+{
+    int             fRc;
+    KFSLOOKUPERROR  enmError;
+    PKFSOBJ         pPathObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError);
+    if (pPathObj)
+    {
+        fRc = kFsCacheObjGetUserData(g_pFsCache, pPathObj, KMK_DIR_NT_IMPOSSIBLE_KEY) != NULL;
+        kFsCacheObjRelease(g_pFsCache, pPathObj);
+    }
+    else
+        fRc = 0;
+    return fRc;
+}
+
+
+/**
+ * opendir for glob.
+ *
+ * @returns Pointer to DIR like handle, NULL if directory not found.
+ * @param   pszDir              The directory to enumerate.
+ */
+static __ptr_t dir_glob_opendir(const char *pszDir)
+{
+    KFSLOOKUPERROR  enmError;
+    PKFSOBJ         pDirObj = kFsCacheLookupA(g_pFsCache, pszDir, &enmError);
+    if (pDirObj)
+    {
+        if (pDirObj->bObjType == KFSOBJ_TYPE_DIR)
+        {
+            if (kFsCacheDirEnsurePopuplated(g_pFsCache, (PKFSDIR)pDirObj, NULL))
+            {
+                KMKNTOPENDIR *pDir = xmalloc(sizeof(*pDir));
+                pDir->pDir    = (PKFSDIR)pDirObj;
+                pDir->idxNext = 0;
+                return pDir;
+            }
+        }
+        kFsCacheObjRelease(g_pFsCache, pDirObj);
+    }
+    return NULL;
+}
+
+
+/**
+ * readdir for glob.
+ *
+ * @returns Pointer to DIR like handle, NULL if directory not found.
+ * @param   pDir                Directory enum handle by dir_glob_opendir.
+ */
+static struct dirent *dir_glob_readdir(__ptr_t pvDir)
+{
+    KMKNTOPENDIR *pDir = (KMKNTOPENDIR *)pvDir;
+    KU32 const    cChildren = pDir->pDir->cChildren;
+    while (pDir->idxNext < cChildren)
+    {
+        PKFSOBJ pEntry = pDir->pDir->papChildren[pDir->idxNext++];
+
+        /* Don't return missing objects. */
+        if (pEntry->bObjType != KFSOBJ_TYPE_MISSING)
+        {
+            /* Copy the name that fits.  If neither fits, skip the name. */
+            if (pEntry->cchName < sizeof(pDir->DirEnt.d_name))
+            {
+                pDir->DirEnt.d_namlen = pEntry->cchName;
+                memcpy(pDir->DirEnt.d_name, pEntry->pszName, pEntry->cchName + 1);
+            }
+            else if (pEntry->cchShortName < sizeof(pDir->DirEnt.d_name))
+            {
+                pDir->DirEnt.d_namlen = pEntry->cchShortName;
+                memcpy(pDir->DirEnt.d_name, pEntry->pszShortName, pEntry->cchShortName + 1);
+            }
+            else
+                continue;
+
+            pDir->DirEnt.d_reclen = offsetof(struct dirent, d_name) + pDir->DirEnt.d_namlen;
+            if (pEntry->bObjType == KFSOBJ_TYPE_DIR)
+                pDir->DirEnt.d_type = DT_DIR;
+            else if (pEntry->bObjType == KFSOBJ_TYPE_FILE)
+                pDir->DirEnt.d_type = DT_REG;
+            else
+                pDir->DirEnt.d_type   = DT_UNKNOWN;
+
+            return &pDir->DirEnt;
+        }
+    }
+
+    /*
+     * Fake the '.' and '..' directories because they're not part of papChildren above.
+     */
+    if (pDir->idxNext < cChildren + 2)
+    {
+        pDir->idxNext++;
+        pDir->DirEnt.d_type    = DT_DIR;
+        pDir->DirEnt.d_namlen  = pDir->idxNext - cChildren;
+        pDir->DirEnt.d_reclen  = offsetof(struct dirent, d_name) + pDir->DirEnt.d_namlen;
+        pDir->DirEnt.d_name[0] = '.';
+        pDir->DirEnt.d_name[1] = '.';
+        pDir->DirEnt.d_name[pDir->DirEnt.d_namlen] = '\0';
+        return &pDir->DirEnt;
+    }
+
+    return NULL;
+}
+
+
+/**
+ * closedir for glob.
+ *
+ * @param   pDir                Directory enum handle by dir_glob_opendir.
+ */
+static void dir_glob_closedir(__ptr_t pvDir)
+{
+    KMKNTOPENDIR *pDir = (KMKNTOPENDIR *)pvDir;
+    kFsCacheObjRelease(g_pFsCache, &pDir->pDir->Obj);
+    pDir->pDir = NULL;
+    free(pDir);
+}
+
+
+/**
+ * stat for glob.
+ *
+ * @returns 0 on success, -1 + errno on failure.
+ * @param   pszPath             The path to stat.
+ * @param   pStat               Where to return the info.
+ */
+static int dir_glob_stat(const char *pszPath, struct stat *pStat)
+{
+    KFSLOOKUPERROR  enmError;
+    PKFSOBJ         pPathObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError);
+/** @todo follow symlinks vs. on symlink!   */
+    if (pPathObj)
+    {
+        if (pPathObj->bObjType != KFSOBJ_TYPE_MISSING)
+        {
+            kHlpAssert(pPathObj->fHaveStats); /* currently always true. */
+            *pStat = pPathObj->Stats;
+            kFsCacheObjRelease(g_pFsCache, pPathObj);
+            return 0;
+        }
+        kFsCacheObjRelease(g_pFsCache, pPathObj);
+    }
+    errno = ENOENT;
+    return -1;
+}
+
+
+/**
+ * lstat for glob.
+ *
+ * @returns 0 on success, -1 + errno on failure.
+ * @param   pszPath             The path to stat.
+ * @param   pStat               Where to return the info.
+ */
+static int dir_glob_lstat(const char *pszPath, struct stat *pStat)
+{
+    KFSLOOKUPERROR  enmError;
+    PKFSOBJ         pPathObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError);
+    if (pPathObj)
+    {
+        if (pPathObj->bObjType != KFSOBJ_TYPE_MISSING)
+        {
+            kHlpAssert(pPathObj->fHaveStats); /* currently always true. */
+            *pStat = pPathObj->Stats;
+            kFsCacheObjRelease(g_pFsCache, pPathObj);
+            return 0;
+        }
+        kFsCacheObjRelease(g_pFsCache, pPathObj);
+        errno = ENOENT;
+    }
+    else
+        errno =    enmError == KFSLOOKUPERROR_NOT_DIR
+                || enmError == KFSLOOKUPERROR_PATH_COMP_NOT_DIR
+              ? ENOTDIR : ENOENT;
+
+    return -1;
+}
+
+
+/**
+ * Checks if @a pszDir exists and is a directory.
+ *
+ * @returns 1 if is directory, 0 if isn't or doesn't exists.
+ * @param   pszDir              The alleged directory.
+ */
+static int dir_globl_dir_exists_p(const char *pszDir)
+{
+    int             fRc;
+    KFSLOOKUPERROR  enmError;
+    PKFSOBJ         pDirObj = kFsCacheLookupA(g_pFsCache, pszDir, &enmError);
+    if (pDirObj)
+    {
+        fRc = pDirObj->bObjType == KFSOBJ_TYPE_DIR;
+        kFsCacheObjRelease(g_pFsCache, pDirObj);
+    }
+    else
+        fRc = 0;
+    return fRc;
+
+}
+
+
+/**
+ * Sets up pGlob with the necessary callbacks.
+ *
+ * @param   pGlob               Structure to populate.
+ */
+void dir_setup_glob(glob_t *pGlob)
+{
+    pGlob->gl_opendir   = dir_glob_opendir;
+    pGlob->gl_readdir   = dir_glob_readdir;
+    pGlob->gl_closedir  = dir_glob_closedir;
+    pGlob->gl_stat      = dir_glob_stat;
+#ifdef __EMX__ /* The FreeBSD implementation actually uses gl_lstat!! */
+    pGlob->gl_lstat     = dir_glob_lstat;
+#else
+    pGlob->gl_exists    = file_exists_p;
+    pGlob->gl_isdir     = dir_globl_dir_exists_p;
+#endif
+}
+
+
+void print_dir_data_base(void)
+{
+    /** @todo. */
+}
+
+
+
+void nt_fullpath_cached(const char *pszPath, char *pszFull, size_t cbFull)
+{
+    KFSLOOKUPERROR  enmError;
+    PKFSOBJ         pPathObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError);
+    if (pPathObj)
+    {
+        KSIZE off = pPathObj->cchParent;
+        if (off > 0)
+        {
+            KSIZE offEnd = off + pPathObj->cchName;
+            if (offEnd < cbFull)
+            {
+                PKFSDIR pAncestor;
+
+                pszFull[off + pPathObj->cchName] = '\0';
+                memcpy(&pszFull[off], pPathObj->pszName, pPathObj->cchName);
+
+                for (pAncestor = pPathObj->pParent; off > 0; pAncestor = pAncestor->Obj.pParent)
+                {
+                    kHlpAssert(off > 1);
+                    kHlpAssert(pAncestor != NULL);
+                    kHlpAssert(pAncestor->ObjcchName > 0);
+                    pszFull[--off] = '/';
+                    off -= pAncestor->Obj.cchName;
+                    kHlpAssert(pAncestor->Obj.cchParent == off);
+                    memcpy(&pszFull[off], pAncestor->Obj.pszName, pAncestor->Obj.cchName);
+                }
+                kFsCacheObjRelease(g_pFsCache, pPathObj);
+                return;
+            }
+        }
+        else
+        {
+            if ((size_t)pPathObj->cchName + 1 < cbFull)
+            {
+                memcpy(pszFull, pPathObj->pszName, pPathObj->cchName);
+                pszFull[pPathObj->cchName] = '/';
+                pszFull[pPathObj->cchName + 1] = '\0';
+
+                kFsCacheObjRelease(g_pFsCache, pPathObj);
+                return;
+            }
+        }
+
+        /* do fallback. */
+        kHlpAssertFailed();
+        kFsCacheObjRelease(g_pFsCache, pPathObj);
+    }
+
+    nt_fullpath(pszPath, pszFull, cbFull);
+}
+
+
+/**
+ * Special stat call used by remake.c
+ *
+ * @returns 0 on success, -1 + errno on failure.
+ * @param   pszPath             The path to stat.
+ * @param   pStat               Where to return the mtime field only.
+ */
+int stat_only_mtime(const char *pszPath, struct stat *pStat)
+{
+    /* Currently a little expensive, so just hit the file system once the
+       jobs starts comming in. */
+    if (g_cInvalidates == 0)
+    {
+        KFSLOOKUPERROR  enmError;
+        PKFSOBJ         pPathObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError);
+        if (pPathObj)
+        {
+            if (pPathObj->bObjType != KFSOBJ_TYPE_MISSING)
+            {
+                kHlpAssert(pPathObj->fHaveStats); /* currently always true. */
+                pStat->st_mtime = pPathObj->Stats.st_mtime;
+                kFsCacheObjRelease(g_pFsCache, pPathObj);
+                return 0;
+            }
+
+            kFsCacheObjRelease(g_pFsCache, pPathObj);
+            errno = ENOENT;
+        }
+        else
+            errno =    enmError == KFSLOOKUPERROR_NOT_DIR
+                    || enmError == KFSLOOKUPERROR_PATH_COMP_NOT_DIR
+                  ? ENOTDIR : ENOENT;
+        return -1;
+    }
+    return birdStatModTimeOnly(pszPath, &pStat->st_mtim, 1 /*fFollowLink*/);
+}
+
+/**
+ * Do cache invalidation after a job completes.
+ */
+void dir_cache_invalid_after_job(void)
+{
+    g_cInvalidates++;
+    if (g_fFsCacheIsUsingCustomRevision)
+        kFsCacheInvalidateCustomBoth(g_pFsCache);
+    else
+        kFsCacheInvalidateAll(g_pFsCache);
+}
+
+/**
+ * Invalidate the whole directory cache
+ *
+ * Used by $(dircache-ctl invalidate)
+ */
+void dir_cache_invalid_all(void)
+{
+    g_cInvalidates++;
+    kFsCacheInvalidateAll(g_pFsCache);
+}
+
+/**
+ * Invalidate missing bits of the directory cache.
+ *
+ * Used by $(dircache-ctl invalidate-missing)
+ */
+void dir_cache_invalid_missing(void)
+{
+    g_cInvalidates++;
+    kFsCacheInvalidateAll(g_pFsCache);
+}
+
+/**
+ * Invalidate the volatile bits of the directory cache.
+ *
+ * Used by $(dircache-ctl invalidate-missing)
+ */
+void dir_cache_invalid_volatile(void)
+{
+    g_cInvalidates++;
+    if (g_fFsCacheIsUsingCustomRevision)
+        kFsCacheInvalidateCustomBoth(g_pFsCache);
+    else
+        kFsCacheInvalidateAll(g_pFsCache);
+}
+
+/**
+ * Used by $(dircache-ctl ) to mark a directory subtree or file as volatile.
+ *
+ * The first call changes the rest of the cache to be considered non-volatile.
+ *
+ * @returns 0 on success, -1 on failure.
+ * @param   pszDir      The directory (or file for what that is worth).
+ */
+int dir_cache_volatile_dir(const char *pszDir)
+{
+    KFSLOOKUPERROR enmError;
+    PKFSOBJ pObj = kFsCacheLookupA(g_pFsCache, pszDir, &enmError);
+    if (pObj)
+    {
+        KBOOL fRc = kFsCacheSetupCustomRevisionForTree(g_pFsCache, pObj);
+        kFsCacheObjRelease(g_pFsCache, pObj);
+        if (fRc)
+        {
+            g_fFsCacheIsUsingCustomRevision = K_TRUE;
+            return 0;
+        }
+        error(reading_file, "failed to mark '%s' as volatile", pszDir);
+    }
+    else
+        error(reading_file, "failed to mark '%s' as volatile (not found)", pszDir);
+    return -1;
+}
+
diff --git a/src/kmk/dir.c b/src/kmk/dir.c
index 2bef610..b0e5215 100644
--- a/src/kmk/dir.c
+++ b/src/kmk/dir.c
@@ -590,6 +590,10 @@ find_directory (const char *name)
 
 	  if (HASH_VACANT (dc))
 	    {
+#if defined(WINDOWS32) && defined(KMK)
+              static char s_last_volume[4];
+              static int  s_last_flags;
+#endif
 	      /* Nope; this really is a directory we haven't seen before.  */
 
 #ifndef CONFIG_WITH_ALLOC_CACHES
@@ -621,6 +625,15 @@ find_directory (const char *name)
                * a directory.
                */
               w32_path[3] = '\0';
+# ifdef KMK /* Need for speed: Cache the GetVolumeInformation result. */
+              if (   s_last_volume[0] == w32_path[0]
+                  && s_last_volume[1] == w32_path[1]
+                  && s_last_volume[2] == w32_path[2]
+                  && s_last_volume[3] == w32_path[3])
+                dc->fs_flags = s_last_flags;
+              else
+                {
+# endif
               if (GetVolumeInformation(w32_path,
                      fs_label, sizeof (fs_label),
                      &fs_serno, &fs_len,
@@ -632,6 +645,14 @@ find_directory (const char *name)
                 dc->fs_flags = FS_NTFS;
               else
                 dc->fs_flags = FS_UNKNOWN;
+# ifdef KMK
+                  s_last_volume[0] = w32_path[0];
+                  s_last_volume[1] = w32_path[1];
+                  s_last_volume[2] = w32_path[2];
+                  s_last_volume[3] = w32_path[3];
+                  s_last_flags     = dc->fs_flags;
+                }
+# endif
 #else
 # ifdef VMS
 	      dc->ino[0] = st.st_ino[0];
diff --git a/src/kmk/function.c b/src/kmk/function.c
index 740d7ab..ddaf1a9 100644
--- a/src/kmk/function.c
+++ b/src/kmk/function.c
@@ -5439,6 +5439,46 @@ func_set_umask (char *o, char **argv UNUSED, const char *funcname UNUSED)
   return o;
 }
 
+
+/* Controls the cache in dir-bird-nt.c. */
+
+char *
+func_dircache_ctl (char *o, char **argv UNUSED, const char *funcname UNUSED)
+{
+# ifdef KBUILD_OS_WINDOWS
+  const char *cmd = argv[0];
+  while (isblank ((unsigned char)*cmd))
+    cmd++;
+  if (strcmp (cmd, "invalidate") == 0)
+    {
+      if (argv[1] != NULL)
+        error (reading_file, "$(dircache-ctl invalidate) takes no parameters");
+      dir_cache_invalid_all ();
+    }
+  else if (strcmp (cmd, "invalidate-missing") == 0)
+    {
+      if (argv[1] != NULL)
+        error (reading_file, "$(dircache-ctl invalidate-missing) takes no parameters");
+      dir_cache_invalid_missing ();
+    }
+  else if (strcmp (cmd, "volatile") == 0)
+    {
+      size_t i;
+      for (i = 1; argv[i] != NULL; i++)
+        {
+          const char *dir = argv[i];
+          while (isblank ((unsigned char)*dir))
+            dir++;
+          if (*dir)
+            dir_cache_volatile_dir (dir);
+        }
+    }
+  else
+    error (reading_file, "Unknown $(dircache-ctl ) command: '%s'", cmd);
+# endif
+  return o;
+}
+
 #endif /* KMK */
 
 
@@ -5627,6 +5667,7 @@ static struct function_table_entry function_table_init[] =
   { STRING_SIZE_TUPLE("kb-exp-tmpl"),   6,  6,  1,  func_kbuild_expand_template},
 #endif
 #ifdef KMK
+  { STRING_SIZE_TUPLE("dircache-ctl"),  1,  0,  1,  func_dircache_ctl},
   { STRING_SIZE_TUPLE("breakpoint"),    0,  0,  0,  func_breakpoint},
   { STRING_SIZE_TUPLE("set-umask"),     1,  3,  1,  func_set_umask},
   { STRING_SIZE_TUPLE("get-umask"),     0,  0,  0,  func_get_umask},
diff --git a/src/kmk/incdep.c b/src/kmk/incdep.c
index bcf037f..17e46a7 100644
--- a/src/kmk/incdep.c
+++ b/src/kmk/incdep.c
@@ -1,5 +1,5 @@
 #ifdef CONFIG_WITH_INCLUDEDEP
-/* $Id: incdep.c 2745 2015-01-03 19:32:00Z bird $ */
+/* $Id: incdep.c 2869 2016-09-04 13:48:28Z bird $ */
 /** @file
  * incdep - Simple dependency files.
  */
@@ -31,6 +31,11 @@
 # define INCL_BASE
 # define INCL_ERRORS
 #endif
+#ifdef KBUILD_OS_WINDOWS
+# ifdef KMK
+#  define INCDEP_USE_KFSCACHE
+# endif
+#endif
 
 #include "make.h"
 
@@ -64,6 +69,11 @@
 # define PARSE_IN_WORKER
 #endif
 
+#ifdef INCDEP_USE_KFSCACHE
+# include "nt/kFsCache.h"
+extern PKFSCACHE g_pFsCache; /* dir-nt-bird.c for now */
+#endif
+
 #ifdef __OS2__
 # include <os2.h>
 # include <sys/fmutex.h>
@@ -145,8 +155,12 @@ struct incdep
   struct incdep_recorded_file *recorded_file_head;
   struct incdep_recorded_file *recorded_file_tail;
 #endif
-
+#ifdef INCDEP_USE_KFSCACHE
+  /** Pointer to the fs cache object for this file (it exists and is a file). */
+  PKFSOBJ pFileObj;
+#else
   char name[1];
+#endif
 };
 
 
@@ -483,6 +497,24 @@ incdep_wait_todo (void)
 static int
 incdep_read_file (struct incdep *cur, struct floc *f)
 {
+#ifdef INCDEP_USE_KFSCACHE
+  size_t const cbFile = (size_t)cur->pFileObj->Stats.st_size;
+
+  assert(cur->pFileObj->fHaveStats);
+  cur->file_base = incdep_xmalloc (cur, cbFile + 1);
+  if (cur->file_base)
+    {
+      if (kFsCacheFileSimpleOpenReadClose (g_pFsCache, cur->pFileObj, 0, cur->file_base, cbFile))
+        {
+          cur->file_end = cur->file_base + cbFile;
+          cur->file_base[cbFile] = '\0';
+          return 0;
+        }
+      incdep_xfree (cur, cur->file_base);
+    }
+  error (f, "%s/%s: error reading file", cur->pFileObj->pParent->Obj.pszName, cur->pFileObj->pszName);
+
+#else /* !INCDEP_USE_KFSCACHE */
   int fd;
   struct stat st;
 
@@ -501,7 +533,11 @@ incdep_read_file (struct incdep *cur, struct floc *f)
       error (f, "%s: %s", cur->name, strerror (err));
       return -1;
     }
+#ifdef KBUILD_OS_WINDOWS /* fewer kernel calls */
+  if (!birdStatOnFdJustSize (fd, &st.st_size))
+#else
   if (!fstat (fd, &st))
+#endif
     {
       cur->file_base = incdep_xmalloc (cur, st.st_size + 1);
       if (read (fd, cur->file_base, st.st_size) == st.st_size)
@@ -521,6 +557,7 @@ incdep_read_file (struct incdep *cur, struct floc *f)
     error (f, "%s: fstat: %s", cur->name, strerror (errno));
 
   close (fd);
+#endif /* !INCDEP_USE_KFSCACHE */
   cur->file_base = cur->file_end = NULL;
   return -1;
 }
@@ -536,6 +573,9 @@ incdep_freeit (struct incdep *cur)
 #endif
 
   incdep_xfree (cur, cur->file_base);
+#ifdef INCDEP_USE_KFSCACHE
+  /** @todo release object ref some day... */
+#endif
   cur->next = NULL;
   free (cur);
 }
@@ -885,7 +925,11 @@ incdep_flush_recorded_instructions (struct incdep *cur)
   /* Display saved error. */
 
   if (cur->err_msg)
+#ifdef INCDEP_USE_KFSCACHE
+    error(NILF, "%s/%s(%d): %s", cur->pFileObj->pParent->Obj.pszName, cur->pFileObj->pszName, cur->err_line_no, cur->err_msg);
+#else
     error(NILF, "%s(%d): %s", cur->name, cur->err_line_no, cur->err_msg);
+#endif
 
 
   /* define_variable_in_set */
@@ -962,7 +1006,11 @@ static void
 incdep_warn (struct incdep *cur, unsigned int line_no, const char *msg)
 {
   if (cur->worker_tid == -1)
+#ifdef INCDEP_USE_KFSCACHE
+    error (NILF, "%s/%s(%d): %s", cur->pFileObj->pParent->Obj.pszName, cur->pFileObj->pszName, line_no, msg);
+#else
     error (NILF, "%s(%d): %s", cur->name, line_no, msg);
+#endif
 #ifdef PARSE_IN_WORKER
   else
     {
@@ -1749,10 +1797,26 @@ eval_include_dep (const char *names, struct floc *f, enum incdep_op op)
 
   while ((name = find_next_token (&names_iterator, &name_len)) != 0)
     {
+#ifdef INCDEP_USE_KFSCACHE
+       KFSLOOKUPERROR enmError;
+       PKFSOBJ pFileObj = kFsCacheLookupWithLengthA (g_pFsCache, name, name_len, &enmError);
+       if (!pFileObj)
+         continue;
+       if (pFileObj->bObjType != KFSOBJ_TYPE_FILE)
+         {
+           kFsCacheObjRelease (g_pFsCache, pFileObj);
+           continue;
+         }
+
+       cur = xmalloc (sizeof (*cur));            /* not incdep_xmalloc here */
+       cur->pFileObj = pFileObj;
+#else
        cur = xmalloc (sizeof (*cur) + name_len); /* not incdep_xmalloc here */
-       cur->file_base = cur->file_end = NULL;
        memcpy (cur->name, name, name_len);
        cur->name[name_len] = '\0';
+#endif
+
+       cur->file_base = cur->file_end = NULL;
        cur->worker_tid = -1;
 #ifdef PARSE_IN_WORKER
        cur->err_line_no = 0;
diff --git a/src/kmk/job.c b/src/kmk/job.c
index 340420e..06efde3 100644
--- a/src/kmk/job.c
+++ b/src/kmk/job.c
@@ -463,9 +463,15 @@ child_error (const char *target_name,
              target_name, exit_code);
 #else
   if (exit_sig == 0)
+# if defined(KMK) && defined(KBUILD_OS_WINDOWS)
+    error (NILF, ignored ? _("[%s] Error %d (%#x) (ignored)") :
+           _("*** [%s] Error %d (%#x)"),
+           target_name, exit_code, exit_code);
+# else
     error (NILF, ignored ? _("[%s] Error %d (ignored)") :
 	   _("*** [%s] Error %d"),
 	   target_name, exit_code);
+# endif
   else
     error (NILF, "*** [%s] %s%s",
 	   target_name, strsignal (exit_sig),
@@ -1311,15 +1317,16 @@ start_job_command (struct child *child)
         p2++;
       assert (*p2);
       set_command_state (child->file, cs_running);
+      child->deleted = 0;
       child->pid = 0;
       if (p2 != argv)
-        rc = kmk_builtin_command (*p2, &argv_spawn, &child->pid);
+        rc = kmk_builtin_command (*p2, child, &argv_spawn, &child->pid);
       else
         {
           int argc = 1;
           while (argv[argc])
             argc++;
-          rc = kmk_builtin_command_parsed (argc, argv, &argv_spawn, &child->pid);
+          rc = kmk_builtin_command_parsed (argc, argv, child, &argv_spawn, &child->pid);
         }
 
 # ifndef VMS
@@ -1327,15 +1334,18 @@ start_job_command (struct child *child)
       free ((char *) argv);
 # endif
 
-      /* synchronous command execution? */
-      if (!rc && !argv_spawn)
-        goto next_command;
-
-      /* spawned a child? */
-      if (!rc && child->pid)
+      if (!rc)
         {
-          ++job_counter;
-          return;
+          /* spawned a child? */
+          if (child->pid)
+            {
+              ++job_counter;
+              return;
+            }
+
+          /* synchronous command execution? */
+          if (!argv_spawn)
+            goto next_command;
         }
 
       /* failure? */
diff --git a/src/kmk/kbuild.c b/src/kmk/kbuild.c
index 5dcd397..1a2399f 100644
--- a/src/kmk/kbuild.c
+++ b/src/kmk/kbuild.c
@@ -1,4 +1,4 @@
-/* $Id: kbuild.c 2771 2015-02-01 20:48:36Z bird $ */
+/* $Id: kbuild.c 2861 2016-09-01 22:42:55Z bird $ */
 /** @file
  * kBuild specific make functionality.
  */
@@ -28,6 +28,7 @@
 /*******************************************************************************
 *   Header Files                                                               *
 *******************************************************************************/
+#define NO_MEMCOPY_HACK
 #include "make.h"
 #include "filedef.h"
 #include "variable.h"
@@ -382,6 +383,7 @@ kbuild_apply_defpath(struct variable *pDefPath, char **ppsz, unsigned int *pcch,
     const char *pszIterator;
     const char *pszInCur;
     unsigned int cchInCur;
+    unsigned int cchMaxRelative = 0;
     unsigned int cRelativePaths;
 
     /*
@@ -389,7 +391,7 @@ kbuild_apply_defpath(struct variable *pDefPath, char **ppsz, unsigned int *pcch,
      */
     cRelativePaths = 0;
     pszIterator = *ppsz;
-    while ((pszInCur = find_next_token(&pszIterator, &cchInCur)))
+    while ((pszInCur = find_next_token(&pszIterator, &cchInCur)) != NULL)
     {
         /* is relative? */
 #ifdef HAVE_DOS_PATHS
@@ -397,7 +399,11 @@ kbuild_apply_defpath(struct variable *pDefPath, char **ppsz, unsigned int *pcch,
 #else
         if (pszInCur[0] != '/')
 #endif
+        {
             cRelativePaths++;
+            if (cchInCur > cchMaxRelative)
+                cchMaxRelative = cchInCur;
+        }
     }
 
     /*
@@ -405,11 +411,29 @@ kbuild_apply_defpath(struct variable *pDefPath, char **ppsz, unsigned int *pcch,
      */
     if (cRelativePaths)
     {
-        const size_t cchOut = *pcch + cRelativePaths * (pDefPath->value_length + 1) + 1;
-        char *pszOut = xmalloc(cchOut);
-        char *pszOutCur = pszOut;
+        size_t const cchAbsPathBuf = MAX(GET_PATH_MAX, pDefPath->value_length + cchInCur + 1 + 16);
+        char *pszAbsPathOut = (char *)alloca(cchAbsPathBuf);
+        char *pszAbsPathIn  = (char *)alloca(cchAbsPathBuf);
+        size_t cchAbsDefPath;
+        size_t cchOut;
+        char *pszOut;
+        char *pszOutCur;
         const char *pszInNextCopy = *ppsz;
 
+        /* make defpath absolute and have a trailing slash first. */
+        if (abspath(pDefPath->value, pszAbsPathIn) == NULL)
+            memcpy(pszAbsPathIn, pDefPath->value, pDefPath->value_length);
+        cchAbsDefPath = strlen(pszAbsPathIn);
+#ifdef HAVE_DOS_PATHS
+        if (pszAbsPathIn[cchAbsDefPath - 1] != '/' && pszAbsPathIn[cchAbsDefPath - 1] != '\\')
+#else
+        if (pszAbsPathIn[cchAbsDefPath - 1] != '/')
+#endif
+            pszAbsPathIn[cchAbsDefPath++] = '/';
+
+        cchOut = *pcch + cRelativePaths * cchAbsDefPath + 1;
+        pszOutCur = pszOut = xmalloc(cchOut);
+
         cRelativePaths = 0;
         pszIterator = *ppsz;
         while ((pszInCur = find_next_token(&pszIterator, &cchInCur)))
@@ -421,38 +445,35 @@ kbuild_apply_defpath(struct variable *pDefPath, char **ppsz, unsigned int *pcch,
             if (pszInCur[0] != '/')
 #endif
             {
-                PATH_VAR(szAbsPathIn);
-                PATH_VAR(szAbsPathOut);
-
-                if (pDefPath->value_length + cchInCur + 1 >= GET_PATH_MAX)
-                    continue;
+                const char *pszToCopy;
+                size_t      cchToCopy;
 
                 /* Create the abspath input. */
-                memcpy(szAbsPathIn, pDefPath->value, pDefPath->value_length);
-                szAbsPathIn[pDefPath->value_length] = '/';
-                memcpy(&szAbsPathIn[pDefPath->value_length + 1], pszInCur, cchInCur);
-                szAbsPathIn[pDefPath->value_length + 1 + cchInCur] = '\0';
+                memcpy(&pszAbsPathIn[cchAbsDefPath], pszInCur, cchInCur);
+                pszAbsPathIn[cchAbsDefPath + cchInCur] = '\0';
 
-                if (abspath(szAbsPathIn, szAbsPathOut) != NULL)
+                pszToCopy = abspath(pszAbsPathIn, pszAbsPathOut);
+                if (!pszToCopy)
+                    pszToCopy = pszAbsPathIn;
+
+                /* copy leading input */
+                if (pszInCur != pszInNextCopy)
                 {
-                    const size_t cchAbsPathOut = strlen(szAbsPathOut);
-                    assert(cchAbsPathOut <= pDefPath->value_length + 1 + cchInCur);
-
-                    /* copy leading input */
-                    if (pszInCur != pszInNextCopy)
-                    {
-                        const size_t cchCopy = pszInCur - pszInNextCopy;
-                        memcpy(pszOutCur, pszInNextCopy, cchCopy);
-                        pszOutCur += cchCopy;
-                    }
-                    pszInNextCopy = pszInCur + cchInCur;
-
-                    /* copy out the abspath. */
-                    memcpy(pszOutCur, szAbsPathOut, cchAbsPathOut);
-                    pszOutCur += cchAbsPathOut;
+                    const size_t cchCopy = pszInCur - pszInNextCopy;
+                    memcpy(pszOutCur, pszInNextCopy, cchCopy);
+                    pszOutCur += cchCopy;
                 }
+                pszInNextCopy = pszInCur + cchInCur;
+
+                /* copy out the abspath. */
+                cchToCopy = strlen(pszToCopy);
+                assert(cchToCopy <= cchAbsDefPath + cchInCur);
+                memcpy(pszOutCur, pszToCopy, cchToCopy);
+                pszOutCur += cchToCopy;
             }
+            /* else: Copy absolute paths as bulk when we hit then next relative one or the end. */
         }
+
         /* the final copy (includes the nil). */
         cchInCur = *ppsz + *pcch - pszInNextCopy;
         memcpy(pszOutCur, pszInNextCopy, cchInCur);
@@ -1961,7 +1982,7 @@ dep     := $(obj)$(SUFF_DEP)
 char *
 func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
 {
-    static int s_fNoCompileCmdsDepsDefined = -1;
+    static int s_fNoCompileDepsDefined = -1;
     struct variable *pTarget    = kbuild_get_variable_n(ST("target"));
     struct variable *pSource    = kbuild_get_variable_n(ST("source"));
     struct variable *pDefPath   = kbuild_get_variable_n(ST("defpath"));
@@ -2024,6 +2045,8 @@ func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
 
     if (pDefPath && !pDefPath->value_length)
         pDefPath = NULL;
+
+
     pDefs      = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
                                             ST("DEFS"),  ST("defs"), 1/* left-to-right */);
     pIncs      = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
@@ -2052,14 +2075,14 @@ func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
 
     /*
     # dependencies
-    ifndef NO_COMPILE_CMDS_DEPS
+    ifndef NO_COMPILE_DEPS
     _DEPFILES_INCLUDED += $(dep)
     $(if $(wildcard $(dep)),$(eval include $(dep)))
     endif
      */
-    if (s_fNoCompileCmdsDepsDefined == -1)
-        s_fNoCompileCmdsDepsDefined = kbuild_lookup_variable_n(ST("NO_COMPILE_CMDS_DEPS")) != NULL;
-    if (!s_fNoCompileCmdsDepsDefined)
+    if (s_fNoCompileDepsDefined == -1)
+        s_fNoCompileDepsDefined = kbuild_lookup_variable_n(ST("NO_COMPILE_DEPS")) != NULL;
+    if (!s_fNoCompileDepsDefined)
     {
         pVar = kbuild_query_recursive_variable_n("_DEPFILES_INCLUDED", sizeof("_DEPFILES_INCLUDED") - 1);
         if (pVar)
diff --git a/src/kmk/kmk_cc_exec.c b/src/kmk/kmk_cc_exec.c
index 82e2875..64242e8 100644
--- a/src/kmk/kmk_cc_exec.c
+++ b/src/kmk/kmk_cc_exec.c
@@ -1,5 +1,5 @@
 #ifdef CONFIG_WITH_COMPILER
-/* $Id: kmk_cc_exec.c 2811 2016-03-12 13:26:33Z bird $ */
+/* $Id: kmk_cc_exec.c 2817 2016-08-14 12:18:20Z bird $ */
 /** @file
  * kmk_cc - Make "Compiler".
  */
@@ -2390,7 +2390,7 @@ static PKMKCCEXPPROG kmk_cc_exp_compile(const char *pchStr, uint32_t cchStr)
 /**
  * Updates the recursive_without_dollar member of a variable structure.
  *
- * This avoid compiling string expansion programs without only a CopyString
+ * This avoid compiling string expansion programs with only a CopyString
  * instruction.  By setting recursive_without_dollar to 1, code calling
  * kmk_cc_compile_variable_for_expand and kmk_exec_expand_to_var_buf will
  * instead treat start treating it as a simple variable, which is faster.
diff --git a/src/kmk/kmkbuiltin.c b/src/kmk/kmkbuiltin.c
index 30c4509..358f3fc 100644
--- a/src/kmk/kmkbuiltin.c
+++ b/src/kmk/kmkbuiltin.c
@@ -1,4 +1,4 @@
-/* $Id: kmkbuiltin.c 2591 2012-06-17 20:45:31Z bird $ */
+/* $Id: kmkbuiltin.c 2843 2016-08-28 15:31:02Z bird $ */
 /** @file
  * kMk Builtin command execution.
  */
@@ -42,7 +42,7 @@
 extern char **environ;
 #endif
 
-int kmk_builtin_command(const char *pszCmd, char ***ppapszArgvToSpawn, pid_t *pPidSpawned)
+int kmk_builtin_command(const char *pszCmd, struct child *pChild, char ***ppapszArgvToSpawn, pid_t *pPidSpawned)
 {
     int         argc;
     char      **argv;
@@ -154,7 +154,7 @@ int kmk_builtin_command(const char *pszCmd, char ***ppapszArgvToSpawn, pid_t *pP
      * Execute the command if parsing was successful.
      */
     if (!*pszCmd)
-        rc = kmk_builtin_command_parsed(argc, argv, ppapszArgvToSpawn, pPidSpawned);
+        rc = kmk_builtin_command_parsed(argc, argv, pChild, ppapszArgvToSpawn, pPidSpawned);
     else
         rc = 1;
 
@@ -166,10 +166,10 @@ int kmk_builtin_command(const char *pszCmd, char ***ppapszArgvToSpawn, pid_t *pP
 }
 
 
-int kmk_builtin_command_parsed(int argc, char **argv, char ***ppapszArgvToSpawn, pid_t *pPidSpawned)
+int kmk_builtin_command_parsed(int argc, char **argv, struct child *pChild, char ***ppapszArgvToSpawn, pid_t *pPidSpawned)
 {
     const char *pszCmd = argv[0];
-    int         iumask;
+    int         iUmask;
     int         rc;
 
     /*
@@ -183,10 +183,10 @@ int kmk_builtin_command_parsed(int argc, char **argv, char ***ppapszArgvToSpawn,
     pszCmd += sizeof("kmk_builtin_") - 1;
 
     /*
-     * String switch on the command.
+     * String switch on the command (frequent stuff at the top).
      */
-    iumask = umask(0);
-    umask(iumask);
+    iUmask = umask(0);
+    umask(iUmask);
     if (!strcmp(pszCmd, "append"))
         rc = kmk_builtin_append(argc, argv, environ);
     else if (!strcmp(pszCmd, "printf"))
@@ -197,6 +197,10 @@ int kmk_builtin_command_parsed(int argc, char **argv, char ***ppapszArgvToSpawn,
         rc = kmk_builtin_install(argc, argv, environ);
     else if (!strcmp(pszCmd, "kDepIDB"))
         rc = kmk_builtin_kDepIDB(argc, argv, environ);
+#ifdef KBUILD_OS_WINDOWS
+    else if (!strcmp(pszCmd, "kSubmit"))
+        rc = kmk_builtin_kSubmit(argc, argv, environ, pChild, pPidSpawned);
+#endif
     else if (!strcmp(pszCmd, "mkdir"))
         rc = kmk_builtin_mkdir(argc, argv, environ);
     else if (!strcmp(pszCmd, "mv"))
@@ -238,7 +242,7 @@ int kmk_builtin_command_parsed(int argc, char **argv, char ***ppapszArgvToSpawn,
      * Cleanup.
      */
     g_progname = "kmk";                 /* paranoia, make sure it's not pointing at a freed argv[0]. */
-    umask(iumask);
+    umask(iUmask);
 
 
     /*
@@ -260,7 +264,7 @@ int kmk_builtin_command_parsed(int argc, char **argv, char ***ppapszArgvToSpawn,
         assert(!*pPidSpawned);
 
         *ppapszArgvToSpawn = NULL;
-        rc = kmk_builtin_command_parsed(argc_new, argv_new, ppapszArgvToSpawn, pPidSpawned);
+        rc = kmk_builtin_command_parsed(argc_new, argv_new, pChild, ppapszArgvToSpawn, pPidSpawned);
 
         free(argv_new[0]);
         free(argv_new);
diff --git a/src/kmk/kmkbuiltin.h b/src/kmk/kmkbuiltin.h
index 4d3ef5f..04e964b 100644
--- a/src/kmk/kmkbuiltin.h
+++ b/src/kmk/kmkbuiltin.h
@@ -1,10 +1,10 @@
-/* $Id: kmkbuiltin.h 2736 2014-12-23 21:15:40Z bird $ */
+/* $Id: kmkbuiltin.h 2846 2016-08-30 12:48:33Z bird $ */
 /** @file
  * kMk Builtin command handling.
  */
 
 /*
- * Copyright (c) 2005-2010 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ * Copyright (c) 2005-2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
  *
  * This file is part of kBuild.
  *
@@ -23,16 +23,21 @@
  *
  */
 
+#ifndef ___kmk_kmkbuiltin_h___
+#define ___kmk_kmkbuiltin_h___
+
 #ifdef _MSC_VER
 # ifndef pid_t /* see config.h.win */
-#  define pid_t int
+#  define pid_t intptr_t /* Note! sub_proc.c needs it to be pointer sized. */
 # endif
 #else
 # include <sys/types.h>
 #endif
 
-int kmk_builtin_command(const char *pszCmd, char ***ppapszArgvToSpawn, pid_t *pPidSpawned);
-int kmk_builtin_command_parsed(int argc, char **argv, char ***ppapszArgvToSpawn, pid_t *pPidSpawned);
+#include "kbuild_version.h"
+
+int kmk_builtin_command(const char *pszCmd, struct child *pChild, char ***ppapszArgvToSpawn, pid_t *pPidSpawned);
+int kmk_builtin_command_parsed(int argc, char **argv, struct child *pChild, char ***ppapszArgvToSpawn, pid_t *pPidSpawned);
 
 extern int kmk_builtin_append(int argc, char **argv, char **envp);
 extern int kmk_builtin_cp(int argc, char **argv, char **envp);
@@ -55,10 +60,16 @@ extern int kmk_builtin_test(int argc, char **argv, char **envp
                             , char ***ppapszArgvSpawn
 #endif
                             );
+#ifdef KBUILD_OS_WINDOWS
+extern int kmk_builtin_kSubmit(int argc, char **argv, char **envp, struct child *pChild, pid_t *pPidSpawned);
+extern int kSubmitSubProcGetResult(intptr_t pvUser, int *prcExit, int *piSigNo);
+extern int kSubmitSubProcKill(intptr_t pvUser, int iSignal);
+extern void kSubmitSubProcCleanup(intptr_t pvUser);
+#endif
 extern int kmk_builtin_kDepIDB(int argc, char **argv, char **envp);
 extern int kmk_builtin_kDepObj(int argc, char **argv, char **envp);
 
 extern char *kmk_builtin_func_printf(char *o, char **argv, const char *funcname);
 
-extern int kbuild_version(const char *);
+#endif
 
diff --git a/src/kmk/kmkbuiltin/kDepIDB.c b/src/kmk/kmkbuiltin/kDepIDB.c
index e5fd714..e12d39a 100644
--- a/src/kmk/kmkbuiltin/kDepIDB.c
+++ b/src/kmk/kmkbuiltin/kDepIDB.c
@@ -1,4 +1,4 @@
-/* $Id: kDepIDB.c 2413 2010-09-11 17:43:04Z bird $ */
+/* $Id: kDepIDB.c 2856 2016-09-01 02:42:08Z bird $ */
 /** @file
  * kDepIDB - Extract dependency information from a MS Visual C++ .idb file.
  */
@@ -41,9 +41,9 @@
 #else
 # include <io.h>
 #endif
-#include "../../lib/k/kDefs.h"
-#include "../../lib/k/kTypes.h"
-#include "../../lib/kDep.h"
+#include "k/kDefs.h"
+#include "k/kTypes.h"
+#include "kDep.h"
 #include "kmkbuiltin.h"
 
 
diff --git a/src/kmk/kmkbuiltin/kDepObj.c b/src/kmk/kmkbuiltin/kDepObj.c
index 3469088..910ee5f 100644
--- a/src/kmk/kmkbuiltin/kDepObj.c
+++ b/src/kmk/kmkbuiltin/kDepObj.c
@@ -1,4 +1,4 @@
-/* $Id: kDepObj.c 2804 2016-01-07 20:47:06Z bird $ */
+/* $Id: kDepObj.c 2856 2016-09-01 02:42:08Z bird $ */
 /** @file
  * kDepObj - Extract dependency information from an object file.
  */
@@ -43,10 +43,10 @@
 #else
 # include <io.h>
 #endif
-#include "../../lib/k/kDefs.h"
-#include "../../lib/k/kTypes.h"
-#include "../../lib/k/kLdrFmts/pe.h"
-#include "../../lib/kDep.h"
+#include "k/kDefs.h"
+#include "k/kTypes.h"
+#include "k/kLdrFmts/pe.h"
+#include "kDep.h"
 #include "kmkbuiltin.h"
 
 
diff --git a/src/kmk/kmkbuiltin/kSubmit.c b/src/kmk/kmkbuiltin/kSubmit.c
new file mode 100644
index 0000000..b69709d
--- /dev/null
+++ b/src/kmk/kmkbuiltin/kSubmit.c
@@ -0,0 +1,1594 @@
+/* $Id: kSubmit.c 2884 2016-09-06 03:11:19Z bird $ */
+/** @file
+ * kMk Builtin command - submit job to a kWorker.
+ */
+
+/*
+ * Copyright (c) 2007-2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * kBuild 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 kBuild.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#ifdef __APPLE__
+# define _POSIX_C_SOURCE 1 /* 10.4 sdk and unsetenv */
+#endif
+#include "make.h"
+#include "job.h"
+#include "variable.h"
+#include "pathstuff.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
+#if defined(_MSC_VER)
+# include <ctype.h>
+# include <io.h>
+# include <direct.h>
+# include <process.h>
+#else
+# include <unistd.h>
+#endif
+#ifdef KBUILD_OS_WINDOWS
+# include "sub_proc.h"
+#endif
+
+#include "kbuild.h"
+#include "kmkbuiltin.h"
+#include "err.h"
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+/** Hashes a pid. */
+#define KWORKER_PID_HASH(a_pid) ((size_t)(a_pid) % 61)
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+typedef struct WORKERINSTANCE *PWORKERINSTANCE;
+typedef struct WORKERINSTANCE
+{
+    /** Pointer to the next worker instance. */
+    PWORKERINSTANCE         pNext;
+    /** Pointer to the previous worker instance. */
+    PWORKERINSTANCE         pPrev;
+    /** Pointer to the next worker with the same pid hash slot. */
+    PWORKERINSTANCE         pNextPidHash;
+    /** 32 or 64. */
+    unsigned                cBits;
+    /** The process ID of the kWorker process. */
+    pid_t                   pid;
+    union
+    {
+        struct
+        {
+            /** The exit code. */
+            int32_t         rcExit;
+            /** Set to 1 if the worker is exiting. */
+            uint8_t         bWorkerExiting;
+            uint8_t         abUnused[3];
+        } s;
+        uint8_t             ab[8];
+    } Result;
+    /** Number of result bytes read alread.  */
+    size_t                  cbResultRead;
+
+#ifdef KBUILD_OS_WINDOWS
+    /** The process handle. */
+    HANDLE                  hProcess;
+    /** The bi-directional pipe we use to talk to the kWorker process. */
+    HANDLE                  hPipe;
+    /** For overlapped read (have valid event semaphore). */
+    OVERLAPPED              OverlappedRead;
+#else
+    /** The socket descriptor we use to talk to the kWorker process. */
+    int                     fdSocket;
+#endif
+
+    /** What it's busy with.  NULL if idle. */
+    struct child           *pBusyWith;
+} WORKERINSTANCE;
+
+
+typedef struct WORKERLIST
+{
+    /** The head of the list.  NULL if empty. */
+    PWORKERINSTANCE         pHead;
+    /** The tail of the list.  NULL if empty. */
+    PWORKERINSTANCE         pTail;
+    /** Number of list entries. */
+    size_t                  cEntries;
+} WORKERLIST;
+typedef WORKERLIST *PWORKERLIST;
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** List of idle worker.*/
+static WORKERLIST           g_IdleList;
+/** List of busy workers. */
+static WORKERLIST           g_BusyList;
+/** PID hash table for the workers.
+ * @sa KWORKER_PID_HASH() */
+static PWORKERINSTANCE      g_apPidHash[61];
+
+#ifdef KBUILD_OS_WINDOWS
+/** For naming the pipes.
+ * Also indicates how many worker instances we've spawned. */
+static unsigned             g_uWorkerSeqNo = 0;
+#endif
+/** Set if we've registred the atexit handler already. */
+static int                  g_fAtExitRegistered = 0;
+
+/** @var g_cArchBits
+ * The bit count of the architecture this binary is compiled for. */
+/** @var g_szArch
+ * The name of the architecture this binary is compiled for. */
+/** @var g_cArchBits
+ * The bit count of the alternative architecture. */
+/** @var g_szAltArch
+ * The name of the alternative architecture. */
+#if defined(KBUILD_ARCH_AMD64)
+static unsigned             g_cArchBits    = 64;
+static char const           g_szArch[]     = "amd64";
+static unsigned             g_cAltArchBits = 32;
+static char const           g_szAltArch[]  = "x86";
+#elif defined(KBUILD_ARCH_X86)
+static unsigned             g_cArchBits    = 32;
+static char const           g_szArch[]     = "x86";
+static unsigned             g_cAltArchBits = 64;
+static char const           g_szAltArch[]  = "amd64";
+#else
+# error "Port me!"
+#endif
+
+
+
+/**
+ * Unlinks a worker instance from a list.
+ *
+ * @param   pList               The list.
+ * @param   pWorker             The worker.
+ */
+static void kSubmitListUnlink(PWORKERLIST pList, PWORKERINSTANCE pWorker)
+{
+    PWORKERINSTANCE pNext = pWorker->pNext;
+    PWORKERINSTANCE pPrev = pWorker->pPrev;
+
+    if (pNext)
+    {
+        assert(pNext->pPrev == pWorker);
+        pNext->pPrev = pPrev;
+    }
+    else
+    {
+        assert(pList->pTail == pWorker);
+        pList->pTail = pPrev;
+    }
+
+    if (pPrev)
+    {
+        assert(pPrev->pNext == pWorker);
+        pPrev->pNext = pNext;
+    }
+    else
+    {
+        assert(pList->pHead == pWorker);
+        pList->pHead = pNext;
+    }
+
+    assert(!pList->pHead || pList->pHead->pPrev == NULL);
+    assert(!pList->pTail || pList->pTail->pNext == NULL);
+
+    assert(pList->cEntries > 0);
+    pList->cEntries--;
+
+    pWorker->pNext = NULL;
+    pWorker->pPrev = NULL;
+}
+
+
+/**
+ * Appends a worker instance to the tail of a list.
+ *
+ * @param   pList               The list.
+ * @param   pWorker             The worker.
+ */
+static void kSubmitListAppend(PWORKERLIST pList, PWORKERINSTANCE pWorker)
+{
+    PWORKERINSTANCE pTail = pList->pTail;
+
+    assert(pTail != pWorker);
+    assert(pList->pHead != pWorker);
+
+    pWorker->pNext = NULL;
+    pWorker->pPrev = pTail;
+    if (pTail != NULL)
+    {
+        assert(pTail->pNext == NULL);
+        pTail->pNext = pWorker;
+    }
+    else
+    {
+        assert(pList->pHead == NULL);
+        pList->pHead = pWorker;
+    }
+    pList->pTail = pWorker;
+
+    assert(pList->pHead->pPrev == NULL);
+    assert(pList->pTail->pNext == NULL);
+
+    pList->cEntries++;
+}
+
+
+/**
+ * Remove worker from the process ID hash table.
+ *
+ * @param   pWorker             The worker.
+ */
+static void kSubmitPidHashRemove(PWORKERINSTANCE pWorker)
+{
+    size_t idxHash = KWORKER_PID_HASH(pWorker->pid);
+    if (g_apPidHash[idxHash] == pWorker)
+        g_apPidHash[idxHash] = pWorker->pNext;
+    else
+    {
+        PWORKERINSTANCE pPrev = g_apPidHash[idxHash];
+        while (pPrev && pPrev->pNext != pWorker)
+            pPrev = pPrev->pNext;
+        assert(pPrev != NULL);
+        if (pPrev)
+            pPrev->pNext = pWorker->pNext;
+    }
+    pWorker->pid = -1;
+}
+
+
+/**
+ * Looks up a worker by its process ID.
+ *
+ * @returns Pointer to the worker instance if found. NULL if not.
+ * @param   pid                 The process ID of the worker.
+ */
+static PWORKERINSTANCE kSubmitFindWorkerByPid(pid_t pid)
+{
+    PWORKERINSTANCE pWorker = g_apPidHash[KWORKER_PID_HASH(pid)];
+    while (pWorker && pWorker->pid != pid)
+        pWorker = pWorker->pNextPidHash;
+    return pWorker;
+}
+
+
+/**
+ * Creates a new worker process.
+ *
+ * @returns 0 on success, non-zero value on failure.
+ * @param   pWorker             The worker structure.  Caller does the linking
+ *                              (as we might be reusing an existing worker
+ *                              instance because a worker shut itself down due
+ *                              to high resource leak level).
+ * @param   cVerbosity          The verbosity level.
+ */
+static int kSubmitSpawnWorker(PWORKERINSTANCE pWorker, int cVerbosity)
+{
+#if defined(KBUILD_OS_WINDOWS) || defined(KBUILD_OS_OS2)
+    static const char s_szWorkerName[] = "kWorker.exe";
+#else
+    static const char s_szWorkerName[] = "kWorker";
+#endif
+    const char     *pszBinPath = get_kbuild_bin_path();
+    size_t const    cchBinPath = strlen(pszBinPath);
+    size_t          cchExectuable;
+    size_t const    cbExecutableBuf = GET_PATH_MAX;
+    PATH_VAR(szExecutable);
+#define TUPLE(a_sz)     a_sz, sizeof(a_sz) - 1
+    struct variable *pVarVolatile = lookup_variable(TUPLE("PATH_OUT"));
+    if (pVarVolatile)
+    { /* likely */ }
+    else
+    {
+        pVarVolatile = lookup_variable(TUPLE("PATH_OUT_BASE"));
+        if (!pVarVolatile)
+            warn("Neither PATH_OUT_BASE nor PATH_OUT was found.");
+    }
+
+    /*
+     * Construct the executable path.
+     */
+    if (   pWorker->cBits == g_cArchBits
+        ?  cchBinPath + 1 + sizeof(s_szWorkerName) <= cbExecutableBuf
+        :  cchBinPath + 1 - sizeof(g_szArch) + sizeof(g_szAltArch) + sizeof(s_szWorkerName) <= cbExecutableBuf )
+    {
+#ifdef KBUILD_OS_WINDOWS
+        static DWORD        s_fDenyRemoteClients = ~(DWORD)0;
+        wchar_t             wszPipeName[64];
+        HANDLE              hWorkerPipe;
+        SECURITY_ATTRIBUTES SecAttrs = { /*nLength:*/ sizeof(SecAttrs), /*pAttrs:*/ NULL, /*bInheritHandle:*/ TRUE };
+#else
+        int                 aiPair[2] = { -1, -1 };
+#endif
+
+        memcpy(szExecutable, pszBinPath, cchBinPath);
+        cchExectuable = cchBinPath;
+
+        /* Replace the arch bin directory extension with the alternative one if requested. */
+        if (pWorker->cBits != g_cArchBits)
+        {
+            if (   cchBinPath < sizeof(g_szArch)
+                || memcmp(&szExecutable[cchBinPath - sizeof(g_szArch) + 1], g_szArch, sizeof(g_szArch) - 1) != 0)
+                return errx(1, "KBUILD_BIN_PATH does not end with main architecture (%s) as expected: %s", pszBinPath, g_szArch);
+            cchExectuable -= sizeof(g_szArch) - 1;
+            memcpy(&szExecutable[cchExectuable], g_szAltArch, sizeof(g_szAltArch) - 1);
+            cchExectuable += sizeof(g_szAltArch) - 1;
+        }
+
+        /* Append a slash and the worker name. */
+        szExecutable[cchExectuable++] = '/';
+        memcpy(&szExecutable[cchExectuable], s_szWorkerName, sizeof(s_szWorkerName));
+
+#ifdef KBUILD_OS_WINDOWS
+        /*
+         * Create the bi-directional pipe.  Worker end is marked inheritable, our end is not.
+         */
+        if (s_fDenyRemoteClients == ~(DWORD)0)
+            s_fDenyRemoteClients = GetVersion() >= 0x60000 ? PIPE_REJECT_REMOTE_CLIENTS : 0;
+        _snwprintf(wszPipeName, sizeof(wszPipeName), L"\\\\.\\pipe\\kmk-%u-kWorker-%u", getpid(), g_uWorkerSeqNo++);
+        hWorkerPipe = CreateNamedPipeW(wszPipeName,
+                                       PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE /* win2k sp2+ */,
+                                       PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | s_fDenyRemoteClients,
+                                       1 /* cMaxInstances */,
+                                       64 /*cbOutBuffer*/,
+                                       65536 /*cbInBuffer*/,
+                                       0 /*cMsDefaultTimeout -> 50ms*/,
+                                       &SecAttrs /* inherit */);
+        if (hWorkerPipe != INVALID_HANDLE_VALUE)
+        {
+            pWorker->hPipe = CreateFileW(wszPipeName,
+                                         GENERIC_READ | GENERIC_WRITE,
+                                         0 /* dwShareMode - no sharing */,
+                                         NULL /*pSecAttr - no inherit */,
+                                         OPEN_EXISTING,
+                                         FILE_FLAG_OVERLAPPED,
+                                         NULL /*hTemplate*/);
+            if (pWorker->hPipe != INVALID_HANDLE_VALUE)
+            {
+                pWorker->OverlappedRead.hEvent = CreateEventW(NULL /*pSecAttrs - no inherit*/, TRUE /*bManualReset*/,
+                                                              TRUE /*bInitialState*/, NULL /*pwszName*/);
+                if (pWorker->OverlappedRead.hEvent != NULL)
+                {
+                    char        szHandleArg[32];
+                    const char *apszArgs[6] =
+                    {
+                        szExecutable, "--pipe", szHandleArg,
+                        pVarVolatile ? "--volatile" : NULL, pVarVolatile ? pVarVolatile->value : NULL,
+                        NULL
+                    };
+                    _snprintf(szHandleArg, sizeof(szHandleArg), "%p", hWorkerPipe);
+
+                    /*
+                     * Create the worker process.
+                     */
+                    pWorker->hProcess = (HANDLE) _spawnve(_P_NOWAIT, szExecutable, apszArgs, environ);
+                    if ((intptr_t)pWorker->hProcess != -1)
+                    {
+                        CloseHandle(hWorkerPipe);
+                        pWorker->pid = GetProcessId(pWorker->hProcess);
+                        if (cVerbosity > 0)
+                            fprintf(stderr, "kSubmit: created %d bit worker %d\n", pWorker->cBits, pWorker->pid);
+                        return 0;
+                    }
+                    err(1, "_spawnve(,%s,,)", szExecutable);
+                    CloseHandle(pWorker->OverlappedRead.hEvent);
+                    pWorker->OverlappedRead.hEvent = INVALID_HANDLE_VALUE;
+                }
+                else
+                    errx(1, "CreateEventW failed: %u", GetLastError());
+                CloseHandle(pWorker->hPipe);
+                pWorker->hPipe = INVALID_HANDLE_VALUE;
+            }
+            else
+                errx(1, "Opening named pipe failed: %u", GetLastError());
+            CloseHandle(hWorkerPipe);
+        }
+        else
+            errx(1, "CreateNamedPipeW failed: %u", GetLastError());
+
+#else
+        /*
+         * Create a socket pair.
+         */
+        if (socketpair(AF_LOCAL, SOCK_STREAM, 0, aiPair) == 0)
+        {
+            pWorker->fdSocket = aiPair[1];
+        }
+        else
+            err(1, "socketpair");
+#endif
+    }
+    else
+        errx(1, "KBUILD_BIN_PATH is too long");
+    return -1;
+}
+
+
+/**
+ * Selects an idle worker or spawns a new one.
+ *
+ * @returns Pointer to the selected worker instance.  NULL on error.
+ * @param   pWorker             The idle worker instance to respawn.
+ *                              On failure this will be freed!
+ * @param   cBitsWorker         The worker bitness - 64 or 32.
+ */
+static int kSubmitRespawnWorker(PWORKERINSTANCE pWorker, int cVerbosity)
+{
+    /*
+     * Clean up after the old worker.
+     */
+#ifdef KBUILD_OS_WINDOWS
+    DWORD   rcWait;
+
+    /* Close the pipe handle first, breaking the pipe in case it's not already
+       busted up.  Close the event semaphore too before waiting for the process. */
+    if (pWorker->hPipe != INVALID_HANDLE_VALUE)
+    {
+        if (!CloseHandle(pWorker->hPipe))
+            warnx("CloseHandle(pWorker->hPipe): %u", GetLastError());
+        pWorker->hPipe = INVALID_HANDLE_VALUE;
+    }
+
+    if (!CloseHandle(pWorker->OverlappedRead.hEvent))
+        warnx("CloseHandle(pWorker->OverlappedRead.hEvent): %u", GetLastError());
+    pWorker->OverlappedRead.hEvent = INVALID_HANDLE_VALUE;
+
+    /* It's probably shutdown already, if not give it 10 milliseconds before
+       we terminate it forcefully. */
+    rcWait = WaitForSingleObject(pWorker->hProcess, 10);
+    if (rcWait != WAIT_OBJECT_0)
+    {
+        BOOL fRc = TerminateProcess(pWorker->hProcess, 127);
+        rcWait = WaitForSingleObject(pWorker->hProcess, 100);
+        if (rcWait != WAIT_OBJECT_0)
+            warnx("WaitForSingleObject returns %u (and TerminateProcess %d)", rcWait, fRc);
+    }
+
+    if (!CloseHandle(pWorker->hProcess))
+        warnx("CloseHandle(pWorker->hProcess): %u", GetLastError());
+    pWorker->hProcess = INVALID_HANDLE_VALUE;
+
+#else
+    pid_t   pidWait;
+    int     rc;
+
+    if (pWorker->fdSocket != -1)
+    {
+        if (close(pWorker->fdSocket) != 0)
+            warn("close(pWorker->fdSocket)");
+        pWorker->fdSocket = -1;
+    }
+
+    kill(pWorker->pid, SIGTERM);
+    pidWait = waitpid(pWorker->pid, &rc, 0);
+    if (pidWait != pWorker->pid)
+        warn("waitpid(pWorker->pid,,0)");
+#endif
+
+    /*
+     * Unlink it from the hash table.
+     */
+    kSubmitPidHashRemove(pWorker);
+
+    /*
+     * Respawn it.
+     */
+    if (kSubmitSpawnWorker(pWorker, cVerbosity) == 0)
+    {
+        /*
+         * Insert it into the process ID hash table and idle list.
+         */
+        size_t idxHash = KWORKER_PID_HASH(pWorker->pid);
+        pWorker->pNextPidHash = g_apPidHash[idxHash];
+        g_apPidHash[idxHash] = pWorker;
+        return 0;
+    }
+
+    kSubmitListUnlink(&g_IdleList, pWorker);
+    free(pWorker);
+    return -1;
+}
+
+
+/**
+ * Selects an idle worker or spawns a new one.
+ *
+ * @returns Pointer to the selected worker instance.  NULL on error.
+ * @param   cBitsWorker         The worker bitness - 64 or 32.
+ */
+static PWORKERINSTANCE kSubmitSelectWorkSpawnNewIfNecessary(unsigned cBitsWorker, int cVerbosity)
+{
+    /*
+     * Lookup up an idle worker.
+     */
+    PWORKERINSTANCE pWorker = g_IdleList.pHead;
+    while (pWorker)
+    {
+        if (pWorker->cBits == cBitsWorker)
+            return pWorker;
+        pWorker = pWorker->pNext;
+    }
+
+    /*
+     * Create a new worker instance.
+     */
+    pWorker = (PWORKERINSTANCE)xcalloc(sizeof(*pWorker));
+    pWorker->cBits = cBitsWorker;
+    if (kSubmitSpawnWorker(pWorker, cVerbosity) == 0)
+    {
+        /*
+         * Insert it into the process ID hash table and idle list.
+         */
+        size_t idxHash = KWORKER_PID_HASH(pWorker->pid);
+        pWorker->pNextPidHash = g_apPidHash[idxHash];
+        g_apPidHash[idxHash] = pWorker;
+
+        kSubmitListAppend(&g_IdleList, pWorker);
+        return pWorker;
+    }
+
+    free(pWorker);
+    return NULL;
+}
+
+
+/**
+ * Composes a JOB mesage for a worker.
+ *
+ * @returns Pointer to the message.
+ * @param   pszExecutable       The executable to run.
+ * @param   papszArgs           The argument vector.
+ * @param   papszEnvVars        The environment vector.
+ * @param   pszCwd              The current directory.
+ * @param   fWatcomBrainDamage  The wcc/wcc386 workaround.
+ * @param   pcbMsg              Where to return the message length.
+ */
+static void *kSubmitComposeJobMessage(const char *pszExecutable, char **papszArgs, char **papszEnvVars,
+                                      const char *pszCwd, int fWatcomBrainDamage, uint32_t *pcbMsg)
+{
+    size_t   cbTmp;
+    uint32_t i;
+    uint32_t cbMsg;
+    uint32_t cArgs;
+    uint32_t cEnvVars;
+    uint8_t *pbMsg;
+    uint8_t *pbCursor;
+
+    /*
+     * Adjust input.
+     */
+    if (!pszExecutable)
+        pszExecutable = papszArgs[0];
+
+    /*
+     * Calculate the message length first.
+     */
+    cbMsg  = sizeof(cbMsg);
+    cbMsg += sizeof("JOB");
+    cbMsg += strlen(pszExecutable) + 1;
+    cbMsg += strlen(pszCwd) + 1;
+
+    cbMsg += sizeof(cArgs);
+    for (i = 0; papszArgs[i] != NULL; i++)
+        cbMsg += 1 + strlen(papszArgs[i]) + 1;
+    cArgs  = i;
+
+    cbMsg += sizeof(cArgs);
+    for (i = 0; papszEnvVars[i] != NULL; i++)
+        cbMsg += strlen(papszEnvVars[i]) + 1;
+    cEnvVars = i;
+
+    cbMsg += 1;
+
+    /*
+     * Compose the message.
+     */
+    pbMsg = pbCursor = xmalloc(cbMsg);
+
+    memcpy(pbCursor, &cbMsg, sizeof(cbMsg));
+    pbCursor += sizeof(cbMsg);
+    memcpy(pbCursor, "JOB", sizeof("JOB"));
+    pbCursor += sizeof("JOB");
+
+    cbTmp = strlen(pszExecutable) + 1;
+    memcpy(pbCursor, pszExecutable, cbTmp);
+    pbCursor += cbTmp;
+
+    cbTmp = strlen(pszCwd) + 1;
+    memcpy(pbCursor, pszCwd, cbTmp);
+    pbCursor += cbTmp;
+
+    memcpy(pbCursor, &cArgs, sizeof(cArgs));
+    pbCursor += sizeof(cArgs);
+    for (i = 0; papszArgs[i] != NULL; i++)
+    {
+        *pbCursor++ = 0; /* Argument expansion flags (MSC, EMX). */
+        cbTmp = strlen(papszArgs[i]) + 1;
+        memcpy(pbCursor, papszArgs[i], cbTmp);
+        pbCursor += cbTmp;
+    }
+    assert(i == cArgs);
+
+    memcpy(pbCursor, &cEnvVars, sizeof(cEnvVars));
+    pbCursor += sizeof(cEnvVars);
+    for (i = 0; papszEnvVars[i] != NULL; i++)
+    {
+        cbTmp = strlen(papszEnvVars[i]) + 1;
+        memcpy(pbCursor, papszEnvVars[i], cbTmp);
+        pbCursor += cbTmp;
+    }
+    assert(i == cEnvVars);
+
+    *pbCursor++ = fWatcomBrainDamage != 0;
+
+    assert(pbCursor - pbMsg == (size_t)cbMsg);
+
+    /* done */
+    *pcbMsg = cbMsg;
+    return pbMsg;
+}
+
+
+/**
+ * Sends the job message to the given worker, respawning the worker if
+ * necessary.
+ *
+ * @returns 0 on success, non-zero on failure.
+ *
+ * @param   pWorker             The work to send the request to.  The worker is
+ *                              on the idle list.
+ * @param   pvMsg               The message to send.
+ * @param   cbMsg               The size of the message.
+ * @param   fNoRespawning       Set if
+ * @param   cVerbosity          The verbosity level.
+ */
+static int kSubmitSendJobMessage(PWORKERINSTANCE pWorker, void const *pvMsg, uint32_t cbMsg, int fNoRespawning, int cVerbosity)
+{
+    int cRetries;
+
+    /*
+     * Respawn the worker if it stopped by itself and we closed the pipe already.
+     */
+#ifdef KBUILD_OS_WINDOWS
+    if (pWorker->hPipe == INVALID_HANDLE_VALUE)
+#else
+    if (pWorker->fdSocket == -1)
+#endif
+    {
+        if (!fNoRespawning)
+        {
+            if (cVerbosity > 0)
+                fprintf(stderr,  "kSubmit: Respawning worker (#1)...\n");
+            if (kSubmitRespawnWorker(pWorker, cVerbosity) != 0)
+                return 2;
+        }
+
+    }
+
+    /*
+     * Restart-on-broken-pipe loop. Necessary?
+     */
+    for (cRetries = !fNoRespawning ? 1 : 0; ; cRetries--)
+    {
+        /*
+         * Try write the message.
+         */
+        uint32_t        cbLeft = cbMsg;
+        uint8_t const  *pbLeft = (uint8_t const  *)pvMsg;
+#ifdef KBUILD_OS_WINDOWS
+        DWORD           dwErr;
+        DWORD           cbWritten;
+        while (WriteFile(pWorker->hPipe, pbLeft, cbLeft, &cbWritten, NULL /*pOverlapped*/))
+        {
+            assert(cbWritten <= cbLeft);
+            cbLeft -= cbWritten;
+            if (!cbLeft)
+                return 0;
+
+            /* This scenario shouldn't really ever happen. But just in case... */
+            pbLeft += cbWritten;
+        }
+        dwErr = GetLastError();
+        if (   (   dwErr != ERROR_BROKEN_PIPE
+                && dwErr != ERROR_NO_DATA)
+            || cRetries <= 0)
+            return errx(1, "Error writing to worker: %u", dwErr);
+#else
+        ssize_t cbWritten
+        while ((cbWritten = write(pWorker->fdSocket, pbLeft, cbLeft)) >= 0)
+        {
+            assert(cbWritten <= cbLeft);
+            cbLeft -= cbWritten;
+            if (!cbLeft)
+                return 0;
+
+            pbLeft += cbWritten;
+        }
+        if (  (   errno != EPIPE
+               && errno != ENOTCONN
+               && errno != ECONNRESET))
+            || cRetries <= 0)
+            return err(1, "Error writing to worker");
+# error "later"
+#endif
+
+        /*
+         * Broken connection. Try respawn the worker.
+         */
+        if (cVerbosity > 0)
+            fprintf(stderr,  "kSubmit: Respawning worker (#2)...\n");
+        if (kSubmitRespawnWorker(pWorker, cVerbosity) != 0)
+            return 2;
+    }
+}
+
+
+/**
+ * Closes the connection on a worker that said it is going to exit now.
+ *
+ * This is a way of dealing with imperfect resource management in the worker, it
+ * will monitor it a little and trigger a respawn when it looks bad.
+ *
+ * This function just closes the pipe / socket connection to the worker.  The
+ * kSubmitSendJobMessage function will see this a trigger a respawn the next
+ * time the worker is engaged.  This will usually mean there's a little delay in
+ * which the process can terminate without us having to actively wait for it.
+ *
+ * @param   pWorker             The worker instance.
+ */
+static void kSubmitCloseConnectOnExitingWorker(PWORKERINSTANCE pWorker)
+{
+#ifdef KBUILD_OS_WINDOWS
+    if (!CloseHandle(pWorker->hPipe))
+        warnx("CloseHandle(pWorker->hPipe): %u", GetLastError());
+    pWorker->hPipe = INVALID_HANDLE_VALUE;
+#else
+    if (close(pWorker->fdSocket) != 0)
+        warn("close(pWorker->fdSocket)");
+    pWorker->fdSocket = -1;
+#endif
+}
+
+
+#ifdef KBUILD_OS_WINDOWS
+
+/**
+ * Handles read failure.
+ *
+ * @returns Exit code.
+ * @param   pWorker             The worker instance.
+ * @param   dwErr               The error code.
+ * @param   pszWhere            Where it failed.
+ */
+static int kSubmitWinReadFailed(PWORKERINSTANCE pWorker, DWORD dwErr, const char *pszWhere)
+{
+    DWORD dwExitCode;
+
+    if (pWorker->cbResultRead == 0)
+        errx(1, "%s/ReadFile failed: %u", pszWhere, dwErr);
+    else
+        errx(1, "%s/ReadFile failed: %u (read %u bytes)", pszWhere, dwErr, pWorker->cbResultRead);
+    assert(dwErr != 0);
+
+    /* Complete the result. */
+    pWorker->Result.s.rcExit         = 127;
+    pWorker->Result.s.bWorkerExiting = 1;
+    pWorker->cbResultRead            = sizeof(pWorker->Result);
+
+    if (GetExitCodeProcess(pWorker->hProcess, &dwExitCode))
+    {
+        if (dwExitCode != 0)
+            pWorker->Result.s.rcExit = dwExitCode;
+    }
+
+    return dwErr != 0 ? (int)(dwErr & 0x7fffffff) : 0x7fffffff;
+
+}
+
+
+/**
+ * Used by
+ * @returns 0 if we got the whole result, -1 if I/O is pending, and windows last
+ *          error on ReadFile failure.
+ * @param   pWorker             The worker instance.
+ */
+static int kSubmitReadMoreResultWin(PWORKERINSTANCE pWorker, const char *pszWhere)
+{
+    /*
+     * Set up the result read, telling the sub_proc.c unit about it.
+     */
+    while (pWorker->cbResultRead < sizeof(pWorker->Result))
+    {
+        DWORD cbRead = 0;
+
+        BOOL fRc = ResetEvent(pWorker->OverlappedRead.hEvent);
+        assert(fRc); (void)fRc;
+
+        pWorker->OverlappedRead.Offset     = 0;
+        pWorker->OverlappedRead.OffsetHigh = 0;
+
+        if (!ReadFile(pWorker->hPipe, &pWorker->Result.ab[pWorker->cbResultRead],
+                     sizeof(pWorker->Result) - pWorker->cbResultRead,
+                     &cbRead,
+                     &pWorker->OverlappedRead))
+        {
+            DWORD dwErr = GetLastError();
+            if (dwErr == ERROR_IO_PENDING)
+                return -1;
+            return kSubmitWinReadFailed(pWorker, dwErr, pszWhere);
+        }
+
+        pWorker->cbResultRead += cbRead;
+        assert(pWorker->cbResultRead <= sizeof(pWorker->Result));
+    }
+    return 0;
+}
+
+#endif /* KBUILD_OS_WINDOWS */
+
+/**
+ * Marks the worker active.
+ *
+ * On windows this involves setting up the async result read and telling
+ * sub_proc.c about the process.
+ *
+ * @returns Exit code.
+ * @param   pWorker             The worker instance to mark as active.
+ * @param   cVerbosity          The verbosity level.
+ * @param   pChild              The kmk child to associate the job with.
+ * @param   pPidSpawned         If @a *pPidSpawned is non-zero if the child is
+ *                              running, otherwise the worker is already done
+ *                              and we've returned the exit code of the job.
+ */
+static int kSubmitMarkActive(PWORKERINSTANCE pWorker, int cVerbosity, struct child *pChild, pid_t *pPidSpawned)
+{
+#ifdef KBUILD_OS_WINDOWS
+    int rc;
+#endif
+
+    pWorker->cbResultRead = 0;
+
+#ifdef KBUILD_OS_WINDOWS
+    /*
+     * Setup the async result read on windows.  If we're slow and the worker
+     * very fast, this may actually get the result immediately.
+     */
+l_again:
+    rc = kSubmitReadMoreResultWin(pWorker, "kSubmitMarkActive");
+    if (rc == -1)
+    {
+        if (process_kmk_register_submit(pWorker->OverlappedRead.hEvent, (intptr_t)pWorker, pPidSpawned) == 0)
+        { /* likely */ }
+        else
+        {
+            /* We need to do the waiting here because sub_proc.c has too much to do. */
+            warnx("Too many processes for sub_proc.c to handle!");
+            WaitForSingleObject(pWorker->OverlappedRead.hEvent, INFINITE);
+            goto l_again;
+        }
+    }
+    else
+    {
+        assert(rc == 0 || pWorker->Result.s.rcExit != 0);
+        if (pWorker->Result.s.bWorkerExiting)
+            kSubmitCloseConnectOnExitingWorker(pWorker);
+        *pPidSpawned = 0;
+        return pWorker->Result.s.rcExit;
+    }
+#endif
+
+    /*
+     * Mark it busy and move it to the active instance.
+     */
+    pWorker->pBusyWith = pChild;
+#ifndef KBUILD_OS_WINDOWS
+    *pPidSpawned = pWorker->pid;
+#endif
+
+    kSubmitListUnlink(&g_IdleList, pWorker);
+    kSubmitListAppend(&g_BusyList, pWorker);
+    return 0;
+}
+
+
+#ifdef KBUILD_OS_WINDOWS
+
+/**
+ * Retrieve the worker child result.
+ *
+ * If incomplete, we restart the ReadFile operation like kSubmitMarkActive does.
+ *
+ * @returns 0 on success, -1 if ReadFile was restarted.
+ * @param   pvUser              The worker instance.
+ * @param   prcExit             Where to return the exit code.
+ * @param   piSigNo             Where to return the signal number.
+ */
+int kSubmitSubProcGetResult(intptr_t pvUser, int *prcExit, int *piSigNo)
+{
+    PWORKERINSTANCE pWorker = (PWORKERINSTANCE)pvUser;
+
+    /*
+     * Get the overlapped result.  There should be one since we're here
+     * because of a satisfied WaitForMultipleObject.
+     */
+    DWORD cbRead = 0;
+    if (GetOverlappedResult(pWorker->hPipe, &pWorker->OverlappedRead, &cbRead, TRUE))
+    {
+        pWorker->cbResultRead += cbRead;
+        assert(pWorker->cbResultRead <= sizeof(pWorker->Result));
+
+        /* More to be read? */
+        while (pWorker->cbResultRead < sizeof(pWorker->Result))
+        {
+            int rc = kSubmitReadMoreResultWin(pWorker, "kSubmitSubProcGetResult/more");
+            if (rc == -1)
+                return -1;
+            assert(rc == 0 || pWorker->Result.s.rcExit != 0);
+        }
+        assert(pWorker->cbResultRead == sizeof(pWorker->Result));
+    }
+    else
+    {
+        DWORD dwErr = GetLastError();
+        kSubmitWinReadFailed(pWorker, dwErr, "kSubmitSubProcGetResult/result");
+    }
+
+    /*
+     * Okay, we've got a result.
+     */
+    *prcExit = pWorker->Result.s.rcExit;
+    switch (pWorker->Result.s.rcExit)
+    {
+        default:                                *piSigNo = 0; break;
+        case CONTROL_C_EXIT:                    *piSigNo = SIGINT; break;
+        case STATUS_INTEGER_DIVIDE_BY_ZERO:     *piSigNo = SIGFPE; break;
+        case STATUS_ACCESS_VIOLATION:           *piSigNo = SIGSEGV; break;
+        case STATUS_PRIVILEGED_INSTRUCTION:
+        case STATUS_ILLEGAL_INSTRUCTION:        *piSigNo = SIGILL; break;
+    }
+    if (pWorker->Result.s.bWorkerExiting)
+        kSubmitCloseConnectOnExitingWorker(pWorker);
+
+    return 0;
+}
+
+
+int kSubmitSubProcKill(intptr_t pvUser, int iSignal)
+{
+    return -1;
+}
+
+
+/**
+ * Called by process_cleanup when it's done with the worker.
+ *
+ * @param   pvUser              The worker instance.
+ */
+void kSubmitSubProcCleanup(intptr_t pvUser)
+{
+    PWORKERINSTANCE pWorker = (PWORKERINSTANCE)pvUser;
+    kSubmitListUnlink(&g_BusyList, pWorker);
+    kSubmitListAppend(&g_IdleList, pWorker);
+}
+
+#endif /* KBUILD_OS_WINDOWS */
+
+
+/**
+ * atexit callback that trigger worker termination.
+ */
+static void kSubmitAtExitCallback(void)
+{
+    PWORKERINSTANCE pWorker;
+    DWORD           msStartTick;
+    DWORD           cKillRaids = 0;
+
+    /*
+     * Tell all the workers to exit by breaking the connection.
+     */
+    for (pWorker = g_IdleList.pHead; pWorker != NULL; pWorker = pWorker->pNext)
+        kSubmitCloseConnectOnExitingWorker(pWorker);
+    for (pWorker = g_BusyList.pHead; pWorker != NULL; pWorker = pWorker->pNext)
+        kSubmitCloseConnectOnExitingWorker(pWorker);
+
+    /*
+     * Wait a little while for them to stop.
+     */
+    Sleep(0);
+    msStartTick = GetTickCount();
+    for (;;)
+    {
+        /*
+         * Collect handles of running processes.
+         */
+        PWORKERINSTANCE apWorkers[MAXIMUM_WAIT_OBJECTS];
+        HANDLE          ahHandles[MAXIMUM_WAIT_OBJECTS];
+        DWORD           cHandles = 0;
+
+        for (pWorker = g_IdleList.pHead; pWorker != NULL; pWorker = pWorker->pNext)
+            if (pWorker->hProcess != INVALID_HANDLE_VALUE)
+            {
+                if (cHandles < MAXIMUM_WAIT_OBJECTS)
+                {
+                    apWorkers[cHandles] = pWorker;
+                    ahHandles[cHandles] = pWorker->hProcess;
+                }
+                cHandles++;
+            }
+        for (pWorker = g_BusyList.pHead; pWorker != NULL; pWorker = pWorker->pNext)
+            if (pWorker->hProcess != INVALID_HANDLE_VALUE)
+            {
+                if (cHandles < MAXIMUM_WAIT_OBJECTS)
+                {
+                    apWorkers[cHandles] = pWorker;
+                    ahHandles[cHandles] = pWorker->hProcess;
+                }
+                cHandles++;
+            }
+        if (cHandles == 0)
+            return;
+
+        /*
+         * Wait for the processes.
+         */
+        for (;;)
+        {
+            DWORD cMsElapsed = GetTickCount() - msStartTick;
+            DWORD dwWait = WaitForMultipleObjects(cHandles <= MAXIMUM_WAIT_OBJECTS ? cHandles : MAXIMUM_WAIT_OBJECTS,
+                                                  ahHandles, FALSE /*bWaitAll*/,
+                                                  cMsElapsed < 1000 ? 1000 - cMsElapsed + 16 : 16);
+            if (   dwWait >= WAIT_OBJECT_0
+                && dwWait <= WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS)
+            {
+                size_t idx = dwWait - WAIT_OBJECT_0;
+                CloseHandle(apWorkers[idx]->hProcess);
+                apWorkers[idx]->hProcess = INVALID_HANDLE_VALUE;
+
+                if (cHandles <= MAXIMUM_WAIT_OBJECTS)
+                {
+                    /* Restart the wait with the worker removed, or quit if it was the last worker. */
+                    cHandles--;
+                    if (!cHandles)
+                        return;
+                    if (idx != cHandles)
+                    {
+                        apWorkers[idx] = apWorkers[cHandles];
+                        ahHandles[idx] = ahHandles[cHandles];
+                    }
+                    continue;
+                }
+                /* else: Reconstruct the wait array so we get maximum coverage. */
+            }
+            else if (dwWait == WAIT_TIMEOUT)
+            {
+                /* Terminate the whole bunch. */
+                cKillRaids++;
+                if (cKillRaids <= 2)
+                {
+                    fprintf(stderr, "kmk/kSubmit: Killing %u lingering worker processe(s)!\n", cHandles);
+                    for (pWorker = g_IdleList.pHead; pWorker != NULL; pWorker = pWorker->pNext)
+                        if (pWorker->hProcess != INVALID_HANDLE_VALUE)
+                            TerminateProcess(pWorker->hProcess, WAIT_TIMEOUT);
+                    for (pWorker = g_BusyList.pHead; pWorker != NULL; pWorker = pWorker->pNext)
+                        if (pWorker->hProcess != INVALID_HANDLE_VALUE)
+                            TerminateProcess(pWorker->hProcess, WAIT_TIMEOUT);
+                }
+                else
+                {
+                    fprintf(stderr, "kmk/kSubmit: Giving up on the last %u worker processe(s). :-(\n", cHandles);
+                    break;
+                }
+            }
+            else
+            {
+                /* Some kind of wait error.  Could be a bad handle, check each and remove
+                   bad ones as well as completed ones. */
+                size_t idx;
+                fprintf(stderr, "kmk/kSubmit: WaitForMultipleObjects unexpectedly returned %#u (err=%u)\n",
+                        dwWait, GetLastError());
+                for (idx = 0; idx < cHandles; idx++)
+                {
+                    dwWait = WaitForSingleObject(ahHandles[idx], 0 /*ms*/);
+                    if (dwWait != WAIT_TIMEOUT)
+                    {
+                        CloseHandle(apWorkers[idx]->hProcess);
+                        apWorkers[idx]->hProcess = INVALID_HANDLE_VALUE;
+                    }
+                }
+            }
+            break;
+        } /* wait loop */
+    } /* outer wait loop */
+}
+
+
+/** The environment variable compare function.
+ * We must use case insensitive compare on windows (Path vs PATH).  */
+#ifdef KBUILD_OS_WINDOWS
+# define KSUBMIT_ENV_NCMP   _strnicmp
+#else
+# define KSUBMIT_ENV_NCMP   strncmp
+#endif
+
+
+/**
+ * Handles the --set var=value option.
+ *
+ * @returns 0 on success, non-zero exit code on error.
+ * @param   papszEnv            The environment vector.
+ * @param   pcEnvVars           Pointer to the variable holding the number of
+ *                              environment variables held by @a papszEnv.
+ * @param   pcAllocatedEnvVars  Pointer to the variable holding max size of the
+ *                              environment vector.
+ * @param   cVerbosity          The verbosity level.
+ * @param   pszValue            The var=value string to apply.
+ */
+static int kSubmitOptEnvSet(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
+                            int cVerbosity, const char *pszValue)
+{
+    const char *pszEqual = strchr(pszValue, '=');
+    if (pszEqual)
+    {
+        char   **papszEnv = *ppapszEnv;
+        unsigned iEnvVar;
+        unsigned cEnvVars = *pcEnvVars;
+        size_t const cchVar = pszEqual - pszValue;
+        for (iEnvVar = 0; iEnvVar < cEnvVars; iEnvVar++)
+        {
+            char *pszCur = papszEnv[iEnvVar];
+            if (   KSUBMIT_ENV_NCMP(pszCur, pszValue, cchVar) == 0
+                && pszCur[cchVar] == '=')
+            {
+                if (cVerbosity > 0)
+                    fprintf(stderr, "kSubmit: replacing '%s' with '%s'\n", papszEnv[iEnvVar], pszValue);
+                free(papszEnv[iEnvVar]);
+                papszEnv[iEnvVar] = xstrdup(pszValue);
+                break;
+            }
+        }
+        if (iEnvVar == cEnvVars)
+        {
+            /* Append new variable. We probably need to resize the vector. */
+            if ((cEnvVars + 2) > *pcAllocatedEnvVars)
+            {
+                *pcAllocatedEnvVars = (cEnvVars + 2 + 0xf) & ~(unsigned)0xf;
+                *ppapszEnv = papszEnv = (char **)xrealloc(papszEnv, *pcAllocatedEnvVars * sizeof(papszEnv[0]));
+            }
+            papszEnv[cEnvVars++] = xstrdup(pszValue);
+            papszEnv[cEnvVars]   = NULL;
+            *pcEnvVars = cEnvVars;
+            if (cVerbosity > 0)
+                fprintf(stderr, "kSubmit: added '%s'\n", papszEnv[iEnvVar]);
+        }
+        else
+        {
+            /* Check for duplicates. */
+            for (iEnvVar++; iEnvVar < cEnvVars; iEnvVar++)
+                if (   KSUBMIT_ENV_NCMP(papszEnv[iEnvVar], pszValue, cchVar) == 0
+                    && papszEnv[iEnvVar][cchVar] == '=')
+                {
+                    if (cVerbosity > 0)
+                        fprintf(stderr, "kSubmit: removing duplicate '%s'\n", papszEnv[iEnvVar]);
+                    free(papszEnv[iEnvVar]);
+                    cEnvVars--;
+                    if (iEnvVar != cEnvVars)
+                        papszEnv[iEnvVar] = papszEnv[cEnvVars];
+                    papszEnv[cEnvVars] = NULL;
+                    iEnvVar--;
+                }
+        }
+    }
+    else
+        return errx(1, "Missing '=': -E %s", pszValue);
+
+    return 0;
+}
+
+
+/**
+ * Handles the --unset var option.
+ *
+ * @returns 0 on success, non-zero exit code on error.
+ * @param   papszEnv            The environment vector.
+ * @param   pcEnvVars           Pointer to the variable holding the number of
+ *                              environment variables held by @a papszEnv.
+ * @param   cVerbosity          The verbosity level.
+ * @param   pszVarToRemove      The name of the variable to remove.
+ */
+static int kSubmitOptEnvUnset(char **papszEnv, unsigned *pcEnvVars, int cVerbosity, const char *pszVarToRemove)
+{
+    if (strchr(pszVarToRemove, '=') == NULL)
+    {
+        unsigned     cRemoved = 0;
+        size_t const cchVar   = strlen(pszVarToRemove);
+        unsigned     cEnvVars = *pcEnvVars;
+        unsigned     iEnvVar;
+
+        for (iEnvVar = 0; iEnvVar < cEnvVars; iEnvVar++)
+            if (   KSUBMIT_ENV_NCMP(papszEnv[iEnvVar], pszVarToRemove, cchVar) == 0
+                && papszEnv[iEnvVar][cchVar] == '=')
+            {
+                if (cVerbosity > 0)
+                    fprintf(stderr, !cRemoved ? "kSubmit: removing '%s'\n"
+                            : "kSubmit: removing duplicate '%s'\n", papszEnv[iEnvVar]);
+                free(papszEnv[iEnvVar]);
+                cEnvVars--;
+                if (iEnvVar != cEnvVars)
+                    papszEnv[iEnvVar] = papszEnv[cEnvVars];
+                papszEnv[cEnvVars] = NULL;
+                cRemoved++;
+                iEnvVar--;
+            }
+        *pcEnvVars = cEnvVars;
+
+        if (cVerbosity > 0 && !cRemoved)
+            fprintf(stderr, "kSubmit: not found '%s'\n", pszVarToRemove);
+    }
+    else
+        return errx(1, "Found invalid variable name character '=' in: -U %s", pszVarToRemove);
+    return 0;
+}
+
+
+
+/**
+ * Handles the --chdir dir option.
+ *
+ * @returns 0 on success, non-zero exit code on error.
+ * @param   pszCwd              The CWD buffer.  Contains current CWD on input,
+ *                              modified by @a pszValue on output.
+ * @param   cbCwdBuf            The size of the CWD buffer.
+ * @param   pszValue            The --chdir value to apply.
+ */
+static int kSubmitOptChDir(char *pszCwd, size_t cbCwdBuf, const char *pszValue)
+{
+    size_t cchNewCwd = strlen(pszValue);
+    size_t offDst;
+    if (cchNewCwd)
+    {
+#ifdef HAVE_DOS_PATHS
+        if (*pszValue == '/' || *pszValue == '\\')
+        {
+            if (pszValue[1] == '/' || pszValue[1] == '\\')
+                offDst = 0; /* UNC */
+            else if (pszCwd[1] == ':' && isalpha(pszCwd[0]))
+                offDst = 2; /* Take drive letter from CWD. */
+            else
+                return errx(1, "UNC relative CWD not implemented: cur='%s' new='%s'", pszCwd, pszValue);
+        }
+        else if (   pszValue[1] == ':'
+                 && isalpha(pszValue[0]))
+        {
+            if (pszValue[2] == '/'|| pszValue[2] == '\\')
+                offDst = 0; /* DOS style absolute path. */
+            else if (   pszCwd[1] == ':'
+                     && tolower(pszCwd[0]) == tolower(pszValue[0]) )
+            {
+                pszValue += 2; /* Same drive as CWD, append drive relative path from value. */
+                cchNewCwd -= 2;
+                offDst = strlen(pszCwd);
+            }
+            else
+            {
+                /* Get current CWD on the specified drive and append value. */
+                int iDrive = tolower(pszValue[0]) - 'a' + 1;
+                if (!_getdcwd(iDrive, pszCwd, cbCwdBuf))
+                    return err(1, "_getdcwd(%d,,) failed", iDrive);
+                pszValue += 2;
+                cchNewCwd -= 2;
+            }
+        }
+#else
+        if (*pszValue == '/')
+            offDst = 0;
+#endif
+        else
+            offDst = strlen(pszCwd); /* Relative path, append to the existing CWD value. */
+
+        /* Do the copying. */
+#ifdef HAVE_DOS_PATHS
+        if (offDst > 0 && pszCwd[offDst - 1] != '/' && pszCwd[offDst - 1] != '\\')
+#else
+        if (offDst > 0 && pszCwd[offDst - 1] != '/')
+#endif
+             pszCwd[offDst++] = '/';
+        if (offDst + cchNewCwd >= cbCwdBuf)
+            return errx(1, "Too long CWD: %*.*s%s", offDst, offDst, pszCwd, pszValue);
+        memcpy(&pszCwd[offDst], pszValue, cchNewCwd + 1);
+    }
+    /* else: relative, no change - quitely ignore. */
+    return 0;
+}
+
+
+static int usage(FILE *pOut,  const char *argv0)
+{
+    fprintf(pOut,
+            "usage: %s [-Z|--zap-env] [-E|--set <var=val>] [-U|--unset <var=val>]\n"
+            "           [-C|--chdir <dir>] [--wcc-brain-damage]\n"
+            "           [-3|--32-bit] [-6|--64-bit] [-v] -- <program> [args]\n"
+            "   or: %s --help\n"
+            "   or: %s --version\n"
+            "\n"
+            "Options:\n"
+            "  -Z, --zap-env, -i, --ignore-environment\n"
+            "    Zaps the environment. Position dependent.\n"
+            "  -E, --set <var>=[value]\n"
+            "    Sets an enviornment variable putenv fashion. Position dependent.\n"
+            "  -U, --unset <var>\n"
+            "    Removes an environment variable. Position dependent.\n"
+            "  -C, --chdir <dir>\n"
+            "    Specifies the current directory for the program.  Relative paths\n"
+            "    are relative to the previous -C option.  Default is getcwd value.\n"
+            "  -3, --32-bit\n"
+            "    Selects a 32-bit kWorker process. Default: kmk bit count\n"
+            "  -6, --64-bit\n"
+            "    Selects a 64-bit kWorker process. Default: kmk bit count\n"
+            "  --wcc-brain-damage\n"
+            "    Works around wcc and wcc386 (Open Watcom) not following normal\n"
+            "    quoting conventions on Windows, OS/2, and DOS.\n"
+            "  -v,--verbose\n"
+            "    More verbose execution.\n"
+            "  -V,--version\n"
+            "    Show the version number.\n"
+            "  -h,--help\n"
+            "    Show this usage information.\n"
+            "\n"
+            ,
+            argv0, argv0, argv0);
+    return 1;
+}
+
+
+int kmk_builtin_kSubmit(int argc, char **argv, char **envp, struct child *pChild, pid_t *pPidSpawned)
+{
+    int             rcExit = 0;
+    int             iArg;
+    unsigned        cAllocatedEnvVars;
+    unsigned        iEnvVar;
+    unsigned        cEnvVars;
+    char          **papszEnv            = NULL;
+    const char     *pszExecutable       = NULL;
+    const char     *pszCwd              = NULL;
+    unsigned        cBitsWorker         = g_cArchBits;
+    int             fWatcomBrainDamage  = 0;
+    int             cVerbosity          = 0;
+    size_t const    cbCwdBuf            = GET_PATH_MAX;
+    PATH_VAR(szCwd);
+
+    g_progname = argv[0];
+
+    /*
+     * Create default program environment.
+     */
+    if (getcwd_fs(szCwd, cbCwdBuf) != NULL)
+    { /* likely */ }
+    else
+        return err(1, "getcwd_fs failed\n");
+
+    papszEnv = pChild->environment;
+    if (!papszEnv)
+        pChild->environment = papszEnv = target_environment(pChild->file);
+    cEnvVars = 0;
+    while (papszEnv[cEnvVars] != NULL)
+        cEnvVars++;
+    cAllocatedEnvVars = cEnvVars;
+
+    /*
+     * Parse the command line.
+     */
+    for (iArg = 1; iArg < argc; iArg++)
+    {
+        const char *pszArg = argv[iArg];
+        if (*pszArg == '-')
+        {
+            char chOpt = *++pszArg;
+            pszArg++;
+            if (chOpt != '-')
+            {
+                if (chOpt != '\0')
+                { /* likely */ }
+                else
+                {
+                    errx(1, "Incomplete option: '-'");
+                    return usage(stderr, argv[0]);
+                }
+            }
+            else
+            {
+                /* '--' indicates where the bits to execute start. */
+                if (*pszArg == '\0')
+                {
+                    iArg++;
+                    break;
+                }
+
+                if (   strcmp(pszArg, "wcc-brain-damage") == 0
+                    || strcmp(pszArg, "watcom-brain-damage") == 0)
+                {
+                    fWatcomBrainDamage = 1;
+                    continue;
+                }
+
+                /* convert to short. */
+                if (strcmp(pszArg, "help") == 0)
+                    chOpt = 'h';
+                else if (strcmp(pszArg, "version") == 0)
+                    chOpt = 'V';
+                else if (strcmp(pszArg, "set") == 0)
+                    chOpt = 'E';
+                else if (strcmp(pszArg, "unset") == 0)
+                    chOpt = 'U';
+                else if (   strcmp(pszArg, "zap-env") == 0
+                         || strcmp(pszArg, "ignore-environment") == 0 /* GNU env compatibility. */ )
+                    chOpt = 'Z';
+                else if (strcmp(pszArg, "chdir") == 0)
+                    chOpt = 'C';
+                else if (strcmp(pszArg, "32-bit") == 0)
+                    chOpt = '3';
+                else if (strcmp(pszArg, "64-bit") == 0)
+                    chOpt = '6';
+                else if (strcmp(pszArg, "verbose") == 0)
+                    chOpt = 'v';
+                else if (strcmp(pszArg, "executable") == 0)
+                    chOpt = 'e';
+                else
+                {
+                    errx(1, "Unknown option: '%s'", pszArg - 2);
+                    return usage(stderr, argv[0]);
+                }
+                pszArg = "";
+            }
+
+            do
+            {
+                /* Get option value first, if the option takes one. */
+                const char *pszValue = NULL;
+                switch (chOpt)
+                {
+                    case 'E':
+                    case 'U':
+                    case 'C':
+                    case 'e':
+                        if (*pszArg != '\0')
+                            pszValue = pszArg + (*pszArg == ':' || *pszArg == '=');
+                        else if (++iArg < argc)
+                            pszValue = argv[iArg];
+                        else
+                        {
+                            errx(1, "Option -%c requires an value!", chOpt);
+                            return usage(stderr, argv[0]);
+                        }
+                        break;
+                }
+
+                switch (chOpt)
+                {
+                    case 'Z':
+                    case 'i': /* GNU env compatibility. */
+                        for (iEnvVar = 0; iEnvVar < cEnvVars; iEnvVar++)
+                            free(papszEnv[iEnvVar]);
+                        papszEnv[0] = NULL;
+                        cEnvVars = 0;
+                        break;
+
+                    case 'E':
+                        rcExit = kSubmitOptEnvSet(&papszEnv, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
+                        pChild->environment = papszEnv;
+                        if (rcExit == 0)
+                            break;
+                        return rcExit;
+
+                    case 'U':
+                        rcExit = kSubmitOptEnvUnset(papszEnv, &cEnvVars, cVerbosity, pszValue);
+                        if (rcExit == 0)
+                            break;
+                        return rcExit;
+
+                    case 'C':
+                        rcExit = kSubmitOptChDir(szCwd, cbCwdBuf, pszValue);
+                        if (rcExit == 0)
+                            break;
+                        return rcExit;
+
+                    case '3':
+                        cBitsWorker = 32;
+                        break;
+
+                    case '6':
+                        cBitsWorker = 64;
+                        break;
+
+                    case 'e':
+                        pszExecutable = pszValue;
+                        break;
+
+                    case 'v':
+                        cVerbosity++;
+                        break;
+
+                    case 'h':
+                        usage(stdout, argv[0]);
+                        return 0;
+
+                    case 'V':
+                        return kbuild_version(argv[0]);
+                }
+            } while ((chOpt = *pszArg++) != '\0');
+        }
+        else
+        {
+            errx(1, "Unknown argument: '%s'", pszArg);
+            return usage(stderr, argv[0]);
+        }
+    }
+
+    /*
+     * Check that we've got something to execute.
+     */
+    if (iArg < argc)
+    {
+        uint32_t        cbMsg;
+        void           *pvMsg   = kSubmitComposeJobMessage(pszExecutable, &argv[iArg], papszEnv, szCwd,
+                                                           fWatcomBrainDamage, &cbMsg);
+        PWORKERINSTANCE pWorker = kSubmitSelectWorkSpawnNewIfNecessary(cBitsWorker, cVerbosity);
+        if (pWorker)
+        {
+            if (!pszExecutable)
+                pszExecutable = argv[iArg];
+
+            rcExit = kSubmitSendJobMessage(pWorker, pvMsg, cbMsg, 0 /*fNoRespawning*/, cVerbosity);
+            if (rcExit == 0)
+                rcExit = kSubmitMarkActive(pWorker, cVerbosity, pChild, pPidSpawned);
+
+            if (!g_fAtExitRegistered)
+                if (atexit(kSubmitAtExitCallback) == 0)
+                    g_fAtExitRegistered = 1;
+        }
+        else
+            rcExit = 1;
+        free(pvMsg);
+    }
+    else
+    {
+        errx(1, "Nothing to executed!");
+        rcExit = usage(stderr, argv[0]);
+    }
+
+    return rcExit;
+}
+
+
+
diff --git a/src/kmk/kmkbuiltin/kbuild_version.c b/src/kmk/kmkbuiltin/kbuild_version.c
deleted file mode 100644
index 29d514d..0000000
--- a/src/kmk/kmkbuiltin/kbuild_version.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/* $Id: kbuild_version.c 2591 2012-06-17 20:45:31Z bird $ */
-/** @file
- * kbuild_version(), helper function.
- */
-
-/*
- * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
- *
- * This file is part of kBuild.
- *
- * kBuild 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 3 of the License, or
- * (at your option) any later version.
- *
- * kBuild 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 kBuild.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include "config.h"
-#include "kmkbuiltin.h"
-#include <string.h>
-#include <stdio.h>
-
-
-/**
- * Prints the kBuild version message and returns 0.
- *
- * @returns 0
- * @param   argv0       The argv0.
- */
-int kbuild_version(const char *argv0)
-{
-    const char *tmp;
-
-    /* skip the path */
-    for (tmp = strpbrk(argv0, "\\/:"); tmp; tmp = strpbrk(argv0, "\\/:"))
-        argv0 = tmp + 1;
-
-    /* find the end, ignoring extenions */
-    tmp = strrchr(argv0, '.');
-    if (!tmp)
-        tmp = strchr(argv0, '\0');
-
-    printf("%.*s - kBuild version %d.%d.%d (r%u)\n",
-           (int)(tmp - argv0), argv0,
-           KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH,
-           KBUILD_SVN_REV);
-    return 0;
-}
-
diff --git a/src/kmk/kmkbuiltin/redirect.c b/src/kmk/kmkbuiltin/redirect.c
index c1fdfd2..cd4af45 100644
--- a/src/kmk/kmkbuiltin/redirect.c
+++ b/src/kmk/kmkbuiltin/redirect.c
@@ -1,4 +1,4 @@
-/* $Id: redirect.c 2812 2016-03-13 11:22:53Z bird $ */
+/* $Id: redirect.c 2839 2016-08-25 21:46:44Z bird $ */
 /** @file
  * kmk_redirect - Do simple program <-> file redirection (++).
  */
@@ -26,6 +26,9 @@
 /*******************************************************************************
 *   Header Files                                                               *
 *******************************************************************************/
+#ifdef __APPLE__
+# define _POSIX_C_SOURCE 1 /* 10.4 sdk and unsetenv */
+#endif
 #include "config.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -37,6 +40,7 @@
 # include <io.h>
 # include <direct.h>
 # include <process.h>
+# include "quote_argv.h"
 #else
 # include <unistd.h>
 #endif
@@ -59,179 +63,6 @@ static unsigned g_cVerbosity = 0;
 
 #if defined(_MSC_VER)
 
-/**
- * Checks if this is an Watcom option where we must just pass thru the string
- * as-is.
- *
- * This is currnetly only used for -d (defining macros).
- *
- * @returns 1 if pass-thru, 0 if not.
- * @param   pszArg          The argument to consider.
- */
-static int isWatcomPassThruOption(const char *pszArg)
-{
-    char ch = *pszArg++;
-    if (ch != '-' && ch != '/')
-        return 0;
-    ch = *pszArg++;
-    switch (ch)
-    {
-        /* Example: -d+VAR="string-value" */
-        case 'd':
-            if (ch == '+')
-                ch = *pszArg++;
-            if (!isalpha(ch) && ch != '_')
-                return 0;
-            return 1;
-
-        default:
-            return 0;
-    }
-}
-
-
-/**
- * Replaces arguments in need of quoting.
- *
- * This will "leak" the original and/or the replacement string, depending on
- * how you look at it.
- *
- * For details on how MSC parses the command line, see "Parsing C Command-Line
- * Arguments": http://msdn.microsoft.com/en-us/library/a1y7w461.aspx
- *
- * @param   argc                The argument count.
- * @param   argv                The argument vector.
- * @param   fWatcomBrainDamage  Set if we're catering for wcc, wcc386 or similar
- *                              OpenWatcom tools.  They seem to follow some
- *                              ancient or home made quoting convention.
- * @param   pStdErr             For verbose debug info.
- */
-static void quoteArguments(int argc, char **argv, int fWatcomBrainDamage, FILE *pStdErr)
-{
-    int i;
-    for (i = 0; i < argc; i++)
-    {
-        const char *pszOrgOrg = argv[i];
-        const char *pszOrg    = pszOrgOrg;
-        size_t      cchOrg    = strlen(pszOrg);
-        const char *pszQuotes = (const char *)memchr(pszOrg, '"', cchOrg);
-        const char *pszProblem = NULL;
-        if (   pszQuotes
-            || cchOrg == 0
-            || (pszProblem = (const char *)memchr(pszOrg, ' ',  cchOrg)) != NULL
-            || (pszProblem = (const char *)memchr(pszOrg, '\t', cchOrg)) != NULL
-            || (pszProblem = (const char *)memchr(pszOrg, '\n', cchOrg)) != NULL
-            || (pszProblem = (const char *)memchr(pszOrg, '\r', cchOrg)) != NULL
-            || (pszProblem = (const char *)memchr(pszOrg, '&',  cchOrg)) != NULL
-            || (pszProblem = (const char *)memchr(pszOrg, '>',  cchOrg)) != NULL
-            || (pszProblem = (const char *)memchr(pszOrg, '<',  cchOrg)) != NULL
-            || (pszProblem = (const char *)memchr(pszOrg, '|',  cchOrg)) != NULL
-            || (pszProblem = (const char *)memchr(pszOrg, '%',  cchOrg)) != NULL
-            || (pszProblem = (const char *)memchr(pszOrg, '\'', cchOrg)) != NULL
-            || (   !fWatcomBrainDamage
-                && (pszProblem = (const char *)memchr(pszOrg, '=',  cchOrg)) != NULL)
-            )
-        {
-            char   ch;
-            int    fComplicated = pszQuotes || (cchOrg > 0 && pszOrg[cchOrg - 1] == '\\');
-            size_t cchNew       = fComplicated ? cchOrg * 2 + 2 : cchOrg + 2;
-            char  *pszNew       = (char *)malloc(cchNew + 1 /*term*/ + 3 /*passthru hack*/);
-
-            argv[i] = pszNew;
-
-            /* Watcom does not grok stuff like "-i=c:\program files\watcom\h",
-               it think it's a source specification. In that case the quote
-               must follow the equal sign. */
-            if (fWatcomBrainDamage)
-            {
-                size_t cchUnquoted  = 0;
-                if (pszOrg[0] == '@') /* Response file quoting: @"file name.rsp" */
-                    cchUnquoted = 1;
-                else if (pszOrg[0] == '-' || pszOrg[0] == '/') /* Switch quoting. */
-                {
-                    if (isWatcomPassThruOption(pszOrg))
-                        cchUnquoted = strlen(pszOrg) + 1;
-                    else
-                    {
-                        const char *pszNeedQuoting = (const char *)memchr(pszOrg, '=', cchOrg); /* For -i=dir and similar. */
-                        if (   pszNeedQuoting == NULL
-                            || (uintptr_t)pszNeedQuoting > (uintptr_t)(pszProblem ? pszProblem : pszQuotes))
-                            pszNeedQuoting = pszProblem ? pszProblem : pszQuotes;
-                        else
-                            pszNeedQuoting++;
-                        cchUnquoted = pszNeedQuoting - pszOrg;
-                    }
-                }
-                if (cchUnquoted)
-                {
-                    memcpy(pszNew, pszOrg, cchUnquoted);
-                    pszNew += cchUnquoted;
-                    pszOrg += cchUnquoted;
-                    cchOrg -= cchUnquoted;
-                }
-            }
-
-            *pszNew++ = '"';
-            if (fComplicated)
-            {
-                while ((ch = *pszOrg++) != '\0')
-                {
-                    if (ch == '"')
-                    {
-                        *pszNew++ = '\\';
-                        *pszNew++ = '"';
-                    }
-                    else if (ch == '\\')
-                    {
-                        /* Backslashes are a bit complicated, they depends on
-                           whether a quotation mark follows them or not.  They
-                           only require escaping if one does. */
-                        unsigned cSlashes = 1;
-                        while ((ch = *pszOrg) == '\\')
-                        {
-                            pszOrg++;
-                            cSlashes++;
-                        }
-                        if (ch == '"' || ch == '\0') /* We put a " at the EOS. */
-                        {
-                            while (cSlashes-- > 0)
-                            {
-                                *pszNew++ = '\\';
-                                *pszNew++ = '\\';
-                            }
-                        }
-                        else
-                            while (cSlashes-- > 0)
-                                *pszNew++ = '\\';
-                    }
-                    else
-                        *pszNew++ = ch;
-                }
-            }
-            else
-            {
-                memcpy(pszNew, pszOrg, cchOrg);
-                pszNew += cchOrg;
-            }
-            *pszNew++ = '"';
-            *pszNew = '\0';
-        }
-
-        if (g_cVerbosity > 0)
-        {
-            if (argv[i] == pszOrgOrg)
-                fprintf(pStdErr, "kmk_redirect: debug: argv[%i]=%s<eos>\n", i, pszOrgOrg);
-            else
-            {
-                fprintf(pStdErr, "kmk_redirect: debug: argv[%i]=%s<eos>\n", i, argv[i]);
-                fprintf(pStdErr, "kmk_redirect: debug:(orig[%i]=%s<eos>)\n", i, pszOrgOrg);
-            }
-        }
-    }
-
-    /*for (i = 0; i < argc; i++) fprintf(stderr, "argv[%u]=%s;;\n", i, argv[i]);*/
-}
-
 
 /** Used by safeCloseFd. */
 static void __cdecl ignore_invalid_parameter(const wchar_t *a, const wchar_t *b, const wchar_t *c, unsigned d, uintptr_t e)
@@ -314,10 +145,9 @@ static int usage(FILE *pOut,  const char *argv0)
 int main(int argc, char **argv, char **envp)
 {
     int i;
+    int j;
 #if defined(_MSC_VER)
     intptr_t rc;
-#else
-    int j;
 #endif
     FILE *pStdErr = stderr;
     FILE *pStdOut = stdout;
@@ -820,7 +650,10 @@ int main(int argc, char **argv, char **envp)
     }
 
     /* MSC is a PITA since it refuses to quote the arguments... */
-    quoteArguments(argc - i, &argv[i], fWatcomBrainDamage, pStdErr);
+    quote_argv(argc - i, &argv[i], fWatcomBrainDamage, 0 /*fFreeOrLeak*/);
+    if (g_cVerbosity > 0)
+        for (j = i; j < argc; j++)
+            fprintf(pStdErr, "kmk_redirect: debug: argv[%i]=%s<eos>\n", j - i, argv[j]);
     rc = _spawnvp(_P_WAIT, argv[i], &argv[i]);
     if (rc == -1 && pStdErr)
     {
diff --git a/src/kmk/main.c b/src/kmk/main.c
index b3c46bb..2b45d9d 100644
--- a/src/kmk/main.c
+++ b/src/kmk/main.c
@@ -3841,7 +3841,10 @@ print_stats ()
   when = time ((time_t *) 0);
   printf (_("\n# Make statistics, printed on %s"), ctime (&when));
 
-  /* Aallocators: */
+  /* Allocators: */
+#ifdef CONFIG_WITH_COMPILER
+  kmk_cc_print_stats ();
+#endif
 # ifndef CONFIG_WITH_STRCACHE2
   strcache_print_stats ("#");
 # else
diff --git a/src/kmk/make.h b/src/kmk/make.h
index 60e1e54..1903299 100644
--- a/src/kmk/make.h
+++ b/src/kmk/make.h
@@ -978,6 +978,12 @@ extern char *expr_eval_to_string(char *o, const char *expr);
 #ifdef KMK
 extern char *abspath(const char *name, char *apath);
 extern char *func_breakpoint(char *o, char **argv, const char *funcname);
+# ifdef KBUILD_OS_WINDOWS
+extern void dir_cache_invalid_after_job (void);
+extern void dir_cache_invalid_all (void);
+extern void dir_cache_invalid_missing (void);
+extern int dir_cache_volatile_dir (const char *dir);
+# endif
 #endif
 
 #if defined (CONFIG_WITH_NANOTS) || defined (CONFIG_WITH_PRINT_TIME_SWITCH)
diff --git a/src/kmk/read.c b/src/kmk/read.c
index de4c516..a9296b9 100644
--- a/src/kmk/read.c
+++ b/src/kmk/read.c
@@ -528,7 +528,11 @@ eval_makefile (const char *filename, int flags)
   {
     void *stream_buf = NULL;
     struct stat st;
+# ifdef KBUILD_OS_WINDOWS
+    if (!birdStatOnFdJustSize(fileno(ebuf.fp), &st.st_size))
+# else
     if (!fstat (fileno (ebuf.fp), &st))
+# endif
       {
         int stream_buf_size = 256*1024;
         if (st.st_size < stream_buf_size)
diff --git a/src/kmk/remake.c b/src/kmk/remake.c
index bc14311..06e925d 100644
--- a/src/kmk/remake.c
+++ b/src/kmk/remake.c
@@ -1783,7 +1783,12 @@ name_mtime (const char *name)
   struct stat st;
   int e;
 
+#if defined(KMK) && defined(KBUILD_OS_WINDOWS)
+  extern int stat_only_mtime(const char *pszPath, struct stat *pStat);
+  e = stat_only_mtime (name, &st);
+#else
   EINTRLOOP (e, stat (name, &st));
+#endif
   if (e == 0)
     mtime = FILE_TIMESTAMP_STAT_MODTIME (name, st);
   else if (errno == ENOENT || errno == ENOTDIR)
diff --git a/src/kmk/w32/Makefile.kmk b/src/kmk/w32/Makefile.kmk
deleted file mode 100644
index a6ef432..0000000
--- a/src/kmk/w32/Makefile.kmk
+++ /dev/null
@@ -1,37 +0,0 @@
-# $Id: $
-## @file
-# Sub-makefile for tstFileInfo / w32.
-#
-
-#
-# Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
-#
-# This file is part of kBuild.
-#
-# kBuild 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 3 of the License, or
-# (at your option) any later version.
-#
-# kBuild 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 kBuild.  If not, see <http://www.gnu.org/licenses/>
-#
-#
-
-SUB_DEPTH = ../../..
-include $(KBUILD_PATH)/subheader.kmk
-
-#
-# tstFileInfo
-#
-PROGRAMS.win += tstFileInfo
-tstFileInfo_TEMPLATE = BIN
-tstFileInfo_SOURCES = tstFileInfo.c
-
-include $(FILE_KBUILD_SUB_FOOTER)
-
diff --git a/src/kmk/w32/Makefile.kup b/src/kmk/w32/Makefile.kup
new file mode 100644
index 0000000..e69de29
diff --git a/src/kmk/w32/include/sub_proc.h b/src/kmk/w32/include/sub_proc.h
index 8166dce..4876e51 100644
--- a/src/kmk/w32/include/sub_proc.h
+++ b/src/kmk/w32/include/sub_proc.h
@@ -38,13 +38,18 @@ EXTERN_DECL(long process_begin, (HANDLE proc, char **argv, char **envp,
 	char *exec_path, char *as_user));
 EXTERN_DECL(long process_pipe_io, (HANDLE proc, char *stdin_data,
 	int stdin_data_len));
+#ifndef KMK /* unused */
 EXTERN_DECL(long process_file_io, (HANDLE proc));
+#endif
 EXTERN_DECL(void process_cleanup, (HANDLE proc));
 EXTERN_DECL(HANDLE process_wait_for_any, (VOID_DECL));
 EXTERN_DECL(void process_register, (HANDLE proc));
 EXTERN_DECL(HANDLE process_easy, (char** argv, char** env));
 EXTERN_DECL(BOOL process_kill, (HANDLE proc, int signal));
 EXTERN_DECL(int process_used_slots, (VOID_DECL));
+#ifdef KMK
+EXTERN_DECL(int process_kmk_register_submit, (HANDLE hEvent, intptr_t clue, pid_t *pPid));
+#endif
 
 /* support routines */
 EXTERN_DECL(long process_errno, (HANDLE proc));
diff --git a/src/kmk/w32/pathstuff.c b/src/kmk/w32/pathstuff.c
index 8eea494..1a5c7e0 100644
--- a/src/kmk/w32/pathstuff.c
+++ b/src/kmk/w32/pathstuff.c
@@ -20,6 +20,9 @@ this program.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <string.h>
 #include <stdlib.h>
 #include "pathstuff.h"
+#if 1 /* bird */
+# include "nt_fullpath.h"
+#endif
 
 /*
  * Convert delimiter separated vpath to Canonical format.
@@ -92,10 +95,6 @@ convert_Path_to_windows32(char *Path, char to_delim)
     return Path;
 }
 
-#if 1 /* bird */
-extern void nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull);
-#endif
-
 /*
  * Convert to forward slashes. Resolve to full pathname optionally
  */
@@ -107,7 +106,7 @@ w32ify(const char *filename, int resolve)
 
 #if 1 /* bird */
     if (resolve) {
-        nt_fullpath(filename, w32_path, sizeof(w32_path));
+        nt_fullpath_cached(filename, w32_path, sizeof(w32_path));
     } else {
         w32_path[0] = '\0';
         strncat(w32_path, filename, sizeof(w32_path));
diff --git a/src/kmk/w32/subproc/Makefile.kup b/src/kmk/w32/subproc/Makefile.kup
new file mode 100644
index 0000000..e69de29
diff --git a/src/kmk/w32/subproc/sub_proc.c b/src/kmk/w32/subproc/sub_proc.c
index 4d454b2..695589f 100644
--- a/src/kmk/w32/subproc/sub_proc.c
+++ b/src/kmk/w32/subproc/sub_proc.c
@@ -26,6 +26,12 @@ this program.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <process.h>  /* for msvc _beginthreadex, _endthreadex */
 #include <signal.h>
 #include <windows.h>
+#ifdef KMK
+# include <assert.h>
+# include "make.h"
+# include "kmkbuiltin.h"
+#endif
+
 
 #include "sub_proc.h"
 #include "proc.h"
@@ -33,12 +39,17 @@ this program.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "debug.h"
 
 static char *make_command_line(char *shell_name, char *exec_path, char **argv);
+#ifndef KMK
 extern char *xmalloc (unsigned int);
-#ifdef KMK
+#else
 extern void kmk_cache_exec_image(const char *); /* imagecache.c */
 #endif
 
 typedef struct sub_process_t {
+#ifdef KMK
+	enum { kRegular = 0, kSubmit, kSubProcFreed } enmType;
+	intptr_t clue;
+#endif
 	intptr_t sv_stdin[2];
 	intptr_t sv_stdout[2];
 	intptr_t sv_stderr[2];
@@ -63,6 +74,7 @@ static sub_process *proc_array[MAXIMUM_WAIT_OBJECTS];
 static int proc_index = 0;
 static int fake_exits_pending = 0;
 
+#ifndef KMK /* Inefficient! */
 /*
  * When a process has been waited for, adjust the wait state
  * array so that we don't wait for it again
@@ -87,6 +99,7 @@ process_adjust_wait_state(sub_process* pproc)
 		proc_array[proc_index] = NULL;
 	}
 }
+#endif /* !KMK */
 
 /*
  * Waits for any of the registered child processes to finish.
@@ -111,6 +124,9 @@ process_wait_for_any_private(void)
 
 	/* wait for someone to exit */
 	if (!fake_exits_pending) {
+#ifdef KMK
+l_wait_again:
+#endif
 		retval = WaitForMultipleObjects(proc_index, handles, FALSE, INFINITE);
 		which = retval - WAIT_OBJECT_0;
 	} else {
@@ -122,7 +138,23 @@ process_wait_for_any_private(void)
 	/* return pointer to process */
 	if (retval != WAIT_FAILED) {
 		sub_process* pproc = proc_array[which];
+#ifdef KMK
+		if (pproc->enmType == kSubmit) {
+		    /* Try get the result from kSubmit.c.  This may not succeed if the whole
+		       result hasn't arrived yet, in which we just restart the wait. */
+		    if (kSubmitSubProcGetResult(pproc->clue, &pproc->exit_code, &pproc->signal) != 0) {
+			goto l_wait_again;
+		    }
+		}
+#endif
+#ifndef KMK /* Inefficient! */
 		process_adjust_wait_state(pproc);
+#else
+		proc_index--;
+		if ((int)which < proc_index)
+			proc_array[which] = proc_array[proc_index];
+		proc_array[proc_index] = NULL;
+#endif
 		return pproc;
 	} else
 		return NULL;
@@ -132,11 +164,21 @@ process_wait_for_any_private(void)
  * Terminate a process.
  */
 BOOL
-process_kill(HANDLE proc, int signal)
+ process_kill(HANDLE proc, int signal)
 {
 	sub_process* pproc = (sub_process*) proc;
 	pproc->signal = signal;
+#ifdef KMK
+	if (pproc->enmType == kRegular) {
+#endif
 	return (TerminateProcess((HANDLE) pproc->pid, signal));
+#ifdef KMK
+	} else if (pproc->enmType == kSubmit) {
+		return kSubmitSubProcKill(pproc->clue, signal) == 0;
+	}
+	assert(0);
+	return FALSE;
+#endif
 }
 
 /*
@@ -148,10 +190,40 @@ process_kill(HANDLE proc, int signal)
 void
 process_register(HANDLE proc)
 {
+#ifdef KMK
+	assert(((sub_process *)proc)->enmType == kRegular);
+#endif
 	if (proc_index < MAXIMUM_WAIT_OBJECTS)
 		proc_array[proc_index++] = (sub_process *) proc;
 }
 
+#ifdef KMK
+/**
+ * Interface used by kmkbuiltin/kSubmit.c to register stuff going down in a
+ * worker process.
+ *
+ * @returns 0 on success, -1 if there are too many sub-processes already.
+ * @param   hEvent              The event semaphore to wait on.
+ * @param   clue                The clue to base.
+ * @param   pPid                Where to return the pid that job.c expects.
+ */
+int
+process_kmk_register_submit(HANDLE hEvent, intptr_t clue, pid_t *pPid)
+{
+	if (proc_index < MAXIMUM_WAIT_OBJECTS) {
+		sub_process *pSubProc = (sub_process *)xcalloc(sizeof(*pSubProc));
+		pSubProc->enmType = kSubmit;
+		pSubProc->clue    = clue;
+		pSubProc->pid     = (intptr_t)hEvent;
+
+		proc_array[proc_index++] = pSubProc;
+		*pPid = (intptr_t)pSubProc;
+		return 0;
+	}
+	return -1;
+}
+#endif
+
 /*
  * Return the number of processes that we are still waiting for.
  */
@@ -196,7 +268,14 @@ process_wait_for_any(void)
 		 * will have to use process_last_err()
 		 */
 #ifdef KMK
-		(void) process_file_io_private(pproc, FALSE);
+		/* Invalidate negative directory cache entries now that a
+		   job has completed and possibly created new files that
+		   was missing earlier. */
+		dir_cache_invalid_after_job ();
+
+		if (pproc->enmType == kRegular) {
+		    (void)process_file_io_private(pproc, FALSE);
+		}
 #else
 		(void) process_file_io(pproc);
 #endif
@@ -444,6 +523,8 @@ process_begin(
 	char *envblk=NULL;
 #ifdef KMK
         size_t exec_path_len;
+
+	assert (pproc->enmType == kRegular);
 #endif
 
 
@@ -782,6 +863,9 @@ process_pipe_io(
 	HANDLE ready_hand;
 	bool_t child_dead = FALSE;
 	BOOL GetExitCodeResult;
+#ifdef KMK
+	assert (pproc->enmType == kRegular);
+#endif
 
 	/*
 	 *  Create stdin thread, if needed
@@ -917,6 +1001,7 @@ process_pipe_io(
 
 }
 
+#ifndef KMK /* unused */
 /*
  * Purpose: collects output from child process and returns results
  *
@@ -942,6 +1027,7 @@ process_file_io(
 
 	return process_file_io_private(proc, TRUE);
 }
+#endif /* !KMK - unused */
 
 /* private function, avoid some kernel calls. (bird) */
 static long
@@ -1023,6 +1109,10 @@ process_cleanup(
 	sub_process *pproc = (sub_process *)proc;
 	int i;
 
+#ifdef KMK
+	if (pproc->enmType == kRegular) {
+#endif
+
 	if (pproc->using_pipes) {
 		for (i= 0; i <= 1; i++) {
 			if ((HANDLE)pproc->sv_stdin[i])
@@ -1035,6 +1125,15 @@ process_cleanup(
 	}
 	if ((HANDLE)pproc->pid)
 		CloseHandle((HANDLE)pproc->pid);
+#ifdef KMK
+	} else if (pproc->enmType == kSubmit) {
+	    kSubmitSubProcCleanup(pproc->clue);
+	} else {
+	    assert(0);
+	    return;
+	}
+	pproc->enmType = kSubProcFreed;
+#endif
 
 	free(pproc);
 }
diff --git a/src/lib/Makefile.kmk b/src/lib/Makefile.kmk
index 68df500..f4bac14 100644
--- a/src/lib/Makefile.kmk
+++ b/src/lib/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 2713 2013-11-21 21:11:00Z bird $
+# $Id: Makefile.kmk 2886 2016-09-06 14:31:46Z bird $
 ## @file
 # Sub-makefile for various libraries and stuff.
 #
@@ -30,7 +30,6 @@ LIBRARIES += kDep
 kDep_TEMPLATE = LIB
 kDep_DEFS.win += NEED_ISBLANK=1 __WIN32__=1
 kDep_SOURCES = kDep.c
-kDep_SOURCES.win = nt_fullpath.c
 kDep_NOINST = 1
 
 LIBRARIES += kUtil
@@ -38,21 +37,29 @@ kUtil_TEMPLATE = LIB
 kUtil_DEFS.win = __WIN__
 kUtil_SOURCES = \
 	crc32.c \
-	md5.c
+	md5.c \
+	kbuild_version.c
 kUtil_SOURCES.win = \
 	nt_fullpath.c \
+	nt_fullpath_cached.c \
+	quote_argv.c \
 	quoted_spawn.c \
        nt/nthlpcore.c \
        nt/nthlpfs.c \
        nt/ntdir.c \
        nt/ntstat.c \
-       nt/ntunlink.c
+       nt/ntunlink.c \
+       nt/kFsCache.c \
+       kStuff/kHlp/CRT/kHlpCRTString.cpp \
+       kStuff/kHlp/CRT/kHlpCRTAlloc.cpp
 kUtil_SOURCES.solaris = \
 	restartable-syscall-wrappers.c
 #kUtil_SOURCES.linux = \
 #	restartable-syscall-wrappers.c
 kUtil_NOINST = 1
 
+kbuild_version.c_DEFS = KBUILD_SVN_REV=$(KBUILD_SVN_REV)
+
 LIBRARIES.win += kWinStartup
 kWinStartup_TEMPLATE = LIB
 kWinStartup_SOURCES = startuphacks-win.c
diff --git a/src/lib/kDep.c b/src/lib/kDep.c
index 118176e..da7a0dd 100644
--- a/src/lib/kDep.c
+++ b/src/lib/kDep.c
@@ -1,31 +1,40 @@
-/* $Id: kDep.c 2413 2010-09-11 17:43:04Z bird $ */
+/* $Id: kDep.c 2886 2016-09-06 14:31:46Z bird $ */
 /** @file
  * kDep - Common Dependency Managemnt Code.
  */
 
 /*
- * Copyright (c) 2004-2010 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ * Copyright (c) 2004-2013 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
  *
- * This file is part of kBuild.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
  *
- * kBuild 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 3 of the License, or
- * (at your option) any later version.
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
  *
- * kBuild 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 kBuild.  If not, see <http://www.gnu.org/licenses/>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
  *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
  */
 
+
 /*******************************************************************************
 *   Header Files                                                               *
 *******************************************************************************/
+#ifdef KMK /* For when it gets compiled and linked into kmk. */
+# include "make.h"
+#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -39,7 +48,8 @@
 # define USE_WIN_MMAP
 # include <io.h>
 # include <Windows.h>
- extern void nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull); /* nt_fullpath.c */
+# include "nt_fullpath.h"
+# include "nt/ntstat.h"
 #else
 # include <dirent.h>
 # include <unistd.h>
@@ -188,7 +198,9 @@ void depOptimize(int fFixCase, int fQuiet)
         char        szFilename[PATH_MAX + 1];
 #endif
         char       *pszFilename;
+#ifndef KMK
         struct stat s;
+#endif
 
         /*
          * Skip some fictive names like <built-in> and <command line>.
@@ -213,7 +225,7 @@ void depOptimize(int fFixCase, int fQuiet)
         if (fFixCase)
         {
 #if K_OS == K_OS_WINDOWS
-            nt_fullpath(pszFilename, szFilename, sizeof(szFilename));
+            nt_fullpath_cached(pszFilename, szFilename, sizeof(szFilename));
             fixslash(szFilename);
 #else
             strcpy(szFilename, pszFilename);
@@ -226,7 +238,13 @@ void depOptimize(int fFixCase, int fQuiet)
         /*
          * Check that the file exists before we start depending on it.
          */
-        if (stat(pszFilename, &s))
+#ifdef KMK
+        if (!file_exists_p(pszFilename))
+#elif K_OS == K_OS_WINDOWS
+        if (birdStatModTimeOnly(pszFilename, &s.st_mtim, 1 /*fFollowLink*/) != 0)
+#else
+        if (stat(pszFilename, &s) != 0)
+#endif
         {
             if (   !fQuiet
                 || errno != ENOENT
diff --git a/src/lib/kDep.h b/src/lib/kDep.h
index d9742f1..b1c35aa 100644
--- a/src/lib/kDep.h
+++ b/src/lib/kDep.h
@@ -1,28 +1,34 @@
-/* $Id: kDep.h 2413 2010-09-11 17:43:04Z bird $ */
+/* $Id: kDep.h 2851 2016-08-31 17:30:52Z bird $ */
 /** @file
  * kDep - Common Dependency Managemnt Code.
  */
 
 /*
- * Copyright (c) 2004-2010 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ * Copyright (c) 2004-2013 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
  *
- * This file is part of kBuild.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
  *
- * kBuild 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 3 of the License, or
- * (at your option) any later version.
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
  *
- * kBuild 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 kBuild.  If not, see <http://www.gnu.org/licenses/>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
  *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
  */
 
+
 #ifndef ___kDep_h
 #define ___kDep_h
 
diff --git a/src/lib/kStuff/Config.kmk b/src/lib/kStuff/Config.kmk
new file mode 100644
index 0000000..df3bf4a
--- /dev/null
+++ b/src/lib/kStuff/Config.kmk
@@ -0,0 +1,138 @@
+# $Id: Config.kmk 29 2009-07-01 20:30:29Z bird $
+## @file
+# kBuild configuration for kStuff
+#
+
+#
+# Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+#
+# This is where we install during the build.
+#
+PATH_INS := $(PATH_OUT)/kStuff
+
+
+#
+# Templates for the kStuff.
+#
+TEMPLATE_kStuff = kStuff Template
+TEMPLATE_kStuff_TOOL             = GXX3
+TEMPLATE_kStuff_TOOL.darwin      = GXX4MACHO
+TEMPLATE_kStuff_TOOL.os2         = GXX3OMF
+TEMPLATE_kStuff_TOOL.solaris     = GXX3PLAIN
+TEMPLATE_kStuff_TOOL.win.x86     = VCC70
+TEMPLATE_kStuff_TOOL.win.amd64   = VCC80AMD64
+
+TEMPLATE_kStuff_SDKS.win.x86     = WINPSDK W2K3DDKX86
+TEMPLATE_kStuff_SDKS.win.amd64   = WINPSDK W2K3DDKAMD64
+
+TEMPLATE_kStuff_DEFS.freebsd     = KS_OS_FREEBSD
+TEMPLATE_kStuff_DEFS.darwin      = KS_OS_DARWIN
+TEMPLATE_kStuff_DEFS.linux       = KS_OS_LINUX
+TEMPLATE_kStuff_DEFS.netbsd      = KS_OS_NETBSD
+TEMPLATE_kStuff_DEFS.openbsd     = KS_OS_OPENBSD
+TEMPLATE_kStuff_DEFS.os2         = KS_OS_OS2
+TEMPLATE_kStuff_DEFS.solaris     = KS_OS_SOLARIS
+TEMPLATE_kStuff_DEFS.win         = KS_OS_WINDOWS _CRT_SECURE_NO_DEPRECATE _CRT_NONSTDC_NO_WARNINGS
+
+TEMPLATE_kStuff_DEFS.x86         = KS_BITS=32
+TEMPLATE_kStuff_DEFS.amd64       = KS_BITS=64
+
+TEMPLATE_kStuff_INCS             = $(PATH_ROOT)/include
+
+TEMPLATE_kStuff_ASTOOL           = YASM
+TEMPLATE_kStuff_ASTOOL.os2       = NASM
+TEMPLATE_kStuff_ASFLAGS.freebsd  = -f elf
+TEMPLATE_kStuff_ASFLAGS.linux    = -f elf
+TEMPLATE_kStuff_ASFLAGS.os2      = -f omf
+TEMPLATE_kStuff_ASFLAGS.win.x86  = -f win32 -g cv8
+TEMPLATE_kStuff_ASFLAGS.win.amd64= -f win64 -g cv8
+
+TEMPLATE_kStuff_CFLAGS.darwin    = -g -fno-common
+TEMPLATE_kStuff_CFLAGS.freebsd   = -g
+TEMPLATE_kStuff_CFLAGS.linux     = -g
+TEMPLATE_kStuff_CFLAGS.os2       = -g
+TEMPLATE_kStuff_CFLAGS.win       = -Zi -Zl -W3 -GF -GR-
+TEMPLATE_kStuff_CFLAGS.win.x86   = -MD
+TEMPLATE_kStuff_CFLAGS.win.amd64 = -MT
+ifneq ($(BUILD_TYPE),debug)
+TEMPLATE_kStuff_CFLAGS.freebsd  += -O3
+TEMPLATE_kStuff_CFLAGS.linux    += -O3
+TEMPLATE_kStuff_CFLAGS.os2      += -O3
+TEMPLATE_kStuff_CFLAGS.win      += -O2b2
+else
+TEMPLATE_kStuff_CFLAGS.win      += -Od
+endif
+
+TEMPLATE_kStuff_CXXFLAGS.darwin  = -g -fno-exceptions -fno-common
+TEMPLATE_kStuff_CXXFLAGS.freebsd = -g -fno-exceptions
+TEMPLATE_kStuff_CXXFLAGS.linux   = -g -fno-exceptions
+TEMPLATE_kStuff_CXXFLAGS.os2     = -g -fno-exceptions
+TEMPLATE_kStuff_CXXFLAGS.win     = -Zi -Zl -W3 -GF -GR-
+TEMPLATE_kStuff_CXXFLAGS.win.x86 = -MD
+TEMPLATE_kStuff_CXXFLAGS.win.amd64 = -MT
+ifneq ($(BUILD_TYPE),debug)
+TEMPLATE_kStuff_CXXFLAGS.freebsd+= -O3
+TEMPLATE_kStuff_CXXFLAGS.linux  += -O3
+TEMPLATE_kStuff_CXXFLAGS.os2    += -O3
+TEMPLATE_kStuff_CXXFLAGS.win    += -O2b2
+else
+TEMPLATE_kStuff_CXXFLAGS.win    += -Od
+endif
+
+TEMPLATE_kStuff_LDFLAGS.freebsd  = -g
+TEMPLATE_kStuff_LDFLAGS.linux    = -g
+TEMPLATE_kStuff_LDFLAGS.os2      = -g
+TEMPLATE_kStuff_LDFLAGS.win      = /DEBUG /NODEFAULTLIB
+
+TEMPLATE_kStuff_LIBS.freebsd     =
+TEMPLATE_kStuff_LIBS.linux       =
+TEMPLATE_kStuff_LIBS.os2         =
+TEMPLATE_kStuff_LIBS.win         = \
+	$(PATH_SDK_WINPSDK_LIB)/psapi.Lib
+TEMPLATE_kStuff_LIBS.win.x86     = \
+	$(PATH_TOOL_VCC70_LIB)/msvcrt.lib \
+	$(PATH_TOOL_VCC70_LIB)/msvcprt.lib \
+	$(PATH_TOOL_VCC70_LIB)/oldnames.lib \
+	$(PATH_SDK_W2K3DDKX86_LIB)/ntdll.lib
+TEMPLATE_kStuff_LIBS.win.amd64   = \
+	$(PATH_TOOL_VCC80AMD64_LIB)/libcmt.lib \
+	$(PATH_TOOL_VCC80AMD64_LIB)/oldnames.lib \
+	$(PATH_SDK_W2K3DDKAMD64_LIB)/ntdll.lib
+
+TEMPLATE_kStuffEXE = kStuff Executable Template
+TEMPLATE_kStuffEXE_EXTENDS = kStuff
+TEMPLATE_kStuffEXE_DEFS = $(TEMPLATE_kStuff) KS_EXE_TARGET
+
+TEMPLATE_kStuffLIB = kStuff Library Template
+TEMPLATE_kStuffLIB_EXTENDS = kStuff
+TEMPLATE_kStuffLIB_DEFS = $(TEMPLATE_kStuff) KS_LIB_TARGET
+
+TEMPLATE_kStuffDLL = kStuff DLL Template
+TEMPLATE_kStuffDLL_EXTENDS = kStuff
+TEMPLATE_kStuffDLL_DEFS = $(TEMPLATE_kStuff) KS_DLL_TARGET
+TEMPLATE_kStuffDLL_LDFLAGS.os2 = $(TEMPLATE_kStuff_LDFLAGS.os2) -Zdll
+
+
diff --git a/src/lib/kStuff/Copyright b/src/lib/kStuff/Copyright
new file mode 100644
index 0000000..ff0902b
--- /dev/null
+++ b/src/lib/kStuff/Copyright
@@ -0,0 +1,25 @@
+All kStuff files are:
+
+ Copyright (c) 2006-2008 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/src/lib/kStuff/Makefile.kmk b/src/lib/kStuff/Makefile.kmk
new file mode 100644
index 0000000..e06f67a
--- /dev/null
+++ b/src/lib/kStuff/Makefile.kmk
@@ -0,0 +1,55 @@
+# $Id: Makefile.kmk 29 2009-07-01 20:30:29Z bird $
+## @file
+# kStuff - Top-level makefile.
+#
+
+#
+# Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+DEPTH = .
+include $(PATH_KBUILD)/subheader.kmk
+
+include $(PATH_SUB_CURRENT)/kCpu/Makefile.kmk
+include $(PATH_SUB_CURRENT)/kDbg/Makefile.kmk
+include $(PATH_SUB_CURRENT)/kErr/Makefile.kmk
+include $(PATH_SUB_CURRENT)/kLdr/Makefile.kmk
+include $(PATH_SUB_CURRENT)/kRdr/Makefile.kmk
+
+include $(PATH_SUB_CURRENT)/kHlp/Makefile.kmk
+ifn1of ($(KBUILD_TARGET), darwin)
+ include $(PATH_SUB_CURRENT)/kProfiler2/Makefile.kmk
+endif
+
+LIBRARIES += kStuffStatic
+kStuffStatic_TEMPLATE = kStuffLIB
+kStuffStatic_SOURCES = \
+	$(TARGET_kCpuStatic) \
+	$(TARGET_kDbgStatic) \
+	$(TARGET_kErrStatic) \
+	$(TARGET_kLdrStatic) \
+	$(TARGET_kRdrStatic)
+
+include $(PATH_KBUILD)/subfooter.kmk
+
diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlBase.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlBase.h
new file mode 100644
index 0000000..90efdee
--- /dev/null
+++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlBase.h
@@ -0,0 +1,626 @@
+/* $Id: kAvlBase.h 36 2009-11-09 22:49:02Z bird $ */
+/** @file
+ * kAvlTmpl - Templated AVL Trees, The Mandatory Base Code.
+ */
+
+/*
+ * Copyright (c) 2001-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @page pg_kAvlTmpl   Template Configuration.
+ *
+ *  This is a templated implementation of AVL trees in C. The template
+ *  parameters relates to the kind of key used and how duplicates are
+ *  treated.
+ *
+ *  \#define KAVL_EQUAL_ALLOWED
+ *  Define this to tell us that equal keys are allowed.
+ *  Then Equal keys will be put in a list pointed to by KAVLNODE::pList.
+ *  This is by default not defined.
+ *
+ *  \#define KAVL_CHECK_FOR_EQUAL_INSERT
+ *  Define this to enable insert check for equal nodes.
+ *  This is by default not defined.
+ *
+ *  \#define KAVL_MAX_STACK
+ *  Use this to specify the max number of stack entries the stack will use when
+ *  inserting and removing nodes from the tree. The size should be something like
+ *      log2(<max nodes>) + 3
+ *  Must be defined.
+ *
+ *  \#define KAVL_RANGE
+ *  Define this to enable key ranges.
+ *
+ *  \#define KAVL_OFFSET
+ *  Define this to link the tree together using self relative offset
+ *  instead of memory pointers, thus making the entire tree relocatable
+ *  provided all the nodes - including the root node variable - are moved
+ *  the exact same distance.
+ *
+ *  \#define KAVL_LOOKTHRU
+ *  Define this to employ a lookthru cache (direct) to speed up lookup for
+ *  some usage patterns. The value should be the number of members of the
+ *   array.
+ *
+ *  \#define KAVL_LOOKTHRU_HASH(Key)
+ *  Define this to specify a more efficient translation of the key into
+ *  a lookthru array index. The default is key % size.
+ *  For some key types this is required as the default will not compile.
+ *
+ *  \#define KAVL_LOCKED
+ *  Define this if you wish for the tree to be locked via the
+ *  KAVL_WRITE_LOCK,  KAVL_WRITE_UNLOCK, KAVL_READ_LOCK and
+ *  KAVL_READ_UNLOCK macros. If not defined the tree will not be subject
+ *  do any kind of locking and the problem of concurrency is left the user.
+ *
+ *  \#define KAVL_WRITE_LOCK(pRoot)
+ *  Lock the tree for writing.
+ *
+ *  \#define KAVL_WRITE_UNLOCK(pRoot)
+ *  Counteracts KAVL_WRITE_LOCK.
+ *
+ *  \#define KAVL_READ_LOCK(pRoot)
+ *  Lock the tree for reading.
+ *
+ *  \#define KAVL_READ_UNLOCK(pRoot)
+ *  Counteracts KAVL_READ_LOCK.
+ *
+ *  \#define KAVLKEY
+ *  Define this to the name of the AVL key type.
+ *
+ *  \#define KAVL_STD_KEY_COMP
+ *  Define this to use the standard key compare macros. If not set all the
+ *  compare operations for KAVLKEY have to be defined: KAVL_G, KAVL_E, KAVL_NE,
+ *  KAVL_R_IS_IDENTICAL, KAVL_R_IS_INTERSECTING and KAVL_R_IS_IN_RANGE. The
+ *  latter three are only required when KAVL_RANGE is defined.
+ *
+ *  \#define KAVLNODE
+ *  Define this to the name (typedef) of the AVL node structure. This
+ *  structure must have a mpLeft, mpRight, mKey and mHeight member.
+ *  If KAVL_RANGE is defined a mKeyLast is also required.
+ *  If KAVL_EQUAL_ALLOWED is defined a mpList member is required.
+ *  It's possible to use other member names by redefining the names.
+ *
+ *  \#define KAVLTREEPTR
+ *  Define this to the name (typedef) of the tree pointer type. This is
+ *  required when KAVL_OFFSET is defined. When not defined it defaults
+ *  to KAVLNODE *.
+ *
+ *  \#define KAVLROOT
+ *  Define this to the name (typedef) of the AVL root structure. This
+ *  is optional. However, if specified it must at least have a mpRoot
+ *  member of KAVLTREEPTR type. If KAVL_LOOKTHRU is non-zero a
+ *  maLookthru[KAVL_LOOKTHRU] member of the KAVLTREEPTR type is also
+ *  required.
+ *
+ *  \#define KAVL_FN
+ *  Use this to alter the names of the AVL functions.
+ *  Must be defined.
+ *
+ *  \#define KAVL_TYPE(prefix, name)
+ *  Use this to make external type names and unique. The prefix may be empty.
+ *  Must be defined.
+ *
+ *  \#define KAVL_INT(name)
+ *  Use this to make internal type names and unique. The prefix may be empty.
+ *  Must be defined.
+ *
+ *  \#define KAVL_DECL(rettype)
+ *  Function declaration macro that should be set according to the scope
+ *  the instantiated template should have. For instance an inlined scope
+ *  (private or public) should K_DECL_INLINE(rettype) here.
+ *
+ *  This version of the kAVL tree offers the option of inlining the entire
+ *  implementation. This depends on the compiler doing a decent job in both
+ *  making use of the inlined code and to eliminate const variables.
+ */
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+#include <k/kDefs.h>
+#include <k/kTypes.h>
+#include <k/kHlpAssert.h>
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+#define KAVL_HEIGHTOF(pNode) ((KU8)((pNode) != NULL ? (pNode)->mHeight : 0))
+
+/** @def KAVL_GET_POINTER
+ * Reads a 'pointer' value.
+ *
+ * @returns The native pointer.
+ * @param   pp      Pointer to the pointer to read.
+ * @internal
+ */
+
+/** @def KAVL_GET_POINTER_NULL
+ * Reads a 'pointer' value which can be KAVL_NULL.
+ *
+ * @returns The native pointer.
+ * @returns NULL pointer if KAVL_NULL.
+ * @param   pp      Pointer to the pointer to read.
+ * @internal
+ */
+
+/** @def KAVL_SET_POINTER
+ * Writes a 'pointer' value.
+ * For offset-based schemes offset relative to pp is calculated and assigned to *pp.
+ *
+ * @returns stored pointer.
+ * @param   pp      Pointer to where to store the pointer.
+ * @param   p       Native pointer to assign to *pp.
+ * @internal
+ */
+
+/** @def KAVL_SET_POINTER_NULL
+ * Writes a 'pointer' value which can be KAVL_NULL.
+ *
+ * For offset-based schemes offset relative to pp is calculated and assigned to *pp,
+ * if p is not KAVL_NULL of course.
+ *
+ * @returns stored pointer.
+ * @param   pp      Pointer to where to store the pointer.
+ * @param   pp2     Pointer to where to pointer to assign to pp. This can be KAVL_NULL
+ * @internal
+ */
+
+#ifndef KAVLTREEPTR
+# define KAVLTREEPTR                        KAVLNODE *
+#endif
+
+#ifndef KAVLROOT
+# define KAVLROOT                           KAVL_TYPE(,ROOT)
+# define KAVL_NEED_KAVLROOT
+#endif
+
+#ifdef KAVL_LOOKTHRU
+# ifndef KAVL_LOOKTHRU_HASH
+#  define KAVL_LOOKTHRU_HASH(Key)           ( (Key) % (KAVL_LOOKTHRU) )
+# endif
+#elif defined(KAVL_LOOKTHRU_HASH)
+# error "KAVL_LOOKTHRU_HASH without KAVL_LOOKTHRU!"
+#endif
+
+#ifdef KAVL_LOOKTHRU
+# define KAVL_LOOKTHRU_INVALIDATE_NODE(pRoot, pNode, Key) \
+    do { \
+        KAVLTREEPTR **ppEntry = &pRoot->maLookthru[KAVL_LOOKTHRU_HASH(Key)]; \
+        if ((pNode) == KAVL_GET_POINTER_NULL(ppEntry)) \
+            *ppEntry = KAVL_NULL; \
+    } while (0)
+#else
+# define KAVL_LOOKTHRU_INVALIDATE_NODE(pRoot, pNode, Key) do { } while (0)
+#endif
+
+#ifndef KAVL_LOCKED
+# define KAVL_WRITE_LOCK(pRoot)             do { } while (0)
+# define KAVL_WRITE_UNLOCK(pRoot)           do { } while (0)
+# define KAVL_READ_LOCK(pRoot)              do { } while (0)
+# define KAVL_READ_UNLOCK(pRoot)            do { } while (0)
+#endif
+
+#ifdef KAVL_OFFSET
+# define KAVL_GET_POINTER(pp)               ( (KAVLNODE *)((KIPTR)(pp) + *(pp)) )
+# define KAVL_GET_POINTER_NULL(pp)          ( *(pp) != KAVL_NULL ? KAVL_GET_POINTER(pp) : NULL )
+# define KAVL_SET_POINTER(pp, p)            ( (*(pp)) = ((KIPTR)(p) - (KIPTR)(pp)) )
+# define KAVL_SET_POINTER_NULL(pp, pp2)     ( (*(pp)) = *(pp2) != KAVL_NULL ? (KIPTR)KAVL_GET_POINTER(pp2) - (KIPTR)(pp) : KAVL_NULL )
+#else
+# define KAVL_GET_POINTER(pp)               ( *(pp) )
+# define KAVL_GET_POINTER_NULL(pp)          ( *(pp) )
+# define KAVL_SET_POINTER(pp, p)            ( (*(pp)) = (p) )
+# define KAVL_SET_POINTER_NULL(pp, pp2)     ( (*(pp)) = *(pp2) )
+#endif
+
+
+/** @def KAVL_NULL
+ * The NULL 'pointer' equivalent.
+ */
+#ifdef KAVL_OFFSET
+# define KAVL_NULL     0
+#else
+# define KAVL_NULL     NULL
+#endif
+
+#ifdef KAVL_STD_KEY_COMP
+# define KAVL_G(key1, key2)                 ( (key1) >  (key2) )
+# define KAVL_E(key1, key2)                 ( (key1) == (key2) )
+# define KAVL_NE(key1, key2)                ( (key1) != (key2) )
+# ifdef KAVL_RANGE
+#  define KAVL_R_IS_IDENTICAL(key1B, key2B, key1E, key2E)       ( (key1B) == (key2B) && (key1E) == (key2E) )
+#  define KAVL_R_IS_INTERSECTING(key1B, key2B, key1E, key2E)    ( (key1B) <= (key2E) && (key1E) >= (key2B) )
+#  define KAVL_R_IS_IN_RANGE(key1B, key1E, key2)                KAVL_R_IS_INTERSECTING(key1B, key2, key1E, key2)
+# endif
+#endif
+
+#ifndef KAVL_RANGE
+# define KAVL_R_IS_INTERSECTING(key1B, key2B, key1E, key2E)     KAVL_E(key1B, key2B)
+# define KAVL_R_IS_IDENTICAL(key1B, key2B, key1E, key2E)        KAVL_E(key1B, key2B)
+#endif
+
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Stack used to avoid recursive calls during insert and removal.
+ */
+typedef struct
+{
+    unsigned        cEntries;
+    KAVLTREEPTR    *aEntries[KAVL_MAX_STACK];
+} KAVL_INT(STACK);
+
+/**
+ * The callback used by the Destroy and DoWithAll functions.
+ */
+typedef int (* KAVL_TYPE(PFN,CALLBACK))(KAVLNODE *, void *);
+
+#ifdef KAVL_NEED_KAVLROOT
+/**
+ * The AVL root structure.
+ */
+typedef struct
+{
+    KAVLTREEPTR     mpRoot;
+# ifdef KAVL_LOOKTHRU
+    KAVLTREEPTR     maLookthru[KAVL_LOOKTHRU];
+# endif
+} KAVLROOT;
+#endif
+
+
+/**
+ * Rewinds a stack of node pointer pointers, rebalancing the tree.
+ *
+ * @param     pStack  Pointer to stack to rewind.
+ * @sketch    LOOP thru all stack entries
+ *            BEGIN
+ *                Get pointer to pointer to node (and pointer to node) from the stack.
+ *                IF 2 higher left subtree than in right subtree THEN
+ *                BEGIN
+ *                    IF higher (or equal) left-sub-subtree than right-sub-subtree THEN
+ *                                *                       n+2|n+3
+ *                              /   \                     /     \
+ *                            n+2    n       ==>         n+1   n+1|n+2
+ *                           /   \                             /     \
+ *                         n+1 n|n+1                          n|n+1  n
+ *
+ *                         Or with keys:
+ *
+ *                               4                           2
+ *                             /   \                       /   \
+ *                            2     5        ==>          1     4
+ *                           / \                               / \
+ *                          1   3                             3   5
+ *
+ *                    ELSE
+ *                                *                         n+2
+ *                              /   \                      /   \
+ *                            n+2    n                   n+1   n+1
+ *                           /   \           ==>        /  \   /  \
+ *                          n    n+1                    n  L   R   n
+ *                               / \
+ *                              L   R
+ *
+ *                         Or with keys:
+ *                               6                           4
+ *                             /   \                       /   \
+ *                            2     7        ==>          2     6
+ *                          /   \                       /  \  /  \
+ *                          1    4                      1  3  5  7
+ *                              / \
+ *                             3   5
+ *                END
+ *                ELSE IF 2 higher in right subtree than in left subtree THEN
+ *                BEGIN
+ *                    Same as above but left <==> right. (invert the picture)
+ *                ELSE
+ *                    IF correct height THEN break
+ *                    ELSE correct height.
+ *            END
+ */
+K_DECL_INLINE(void) KAVL_FN(Rebalance)(KAVL_INT(STACK) *pStack)
+{
+    while (pStack->cEntries > 0)
+    {
+        KAVLTREEPTR     *ppNode = pStack->aEntries[--pStack->cEntries];
+        KAVLNODE        *pNode = KAVL_GET_POINTER(ppNode);
+        KAVLNODE        *pLeftNode = KAVL_GET_POINTER_NULL(&pNode->mpLeft);
+        KU8              uLeftHeight = KAVL_HEIGHTOF(pLeftNode);
+        KAVLNODE        *pRightNode = KAVL_GET_POINTER_NULL(&pNode->mpRight);
+        KU8              uRightHeight = KAVL_HEIGHTOF(pRightNode);
+
+        if (uRightHeight + 1 < uLeftHeight)
+        {
+            KAVLNODE    *pLeftLeftNode = KAVL_GET_POINTER_NULL(&pLeftNode->mpLeft);
+            KAVLNODE    *pLeftRightNode = KAVL_GET_POINTER_NULL(&pLeftNode->mpRight);
+            KU8          uLeftRightHeight = KAVL_HEIGHTOF(pLeftRightNode);
+
+            if (KAVL_HEIGHTOF(pLeftLeftNode) >= uLeftRightHeight)
+            {
+                KAVL_SET_POINTER_NULL(&pNode->mpLeft, &pLeftNode->mpRight);
+                KAVL_SET_POINTER(&pLeftNode->mpRight, pNode);
+                pLeftNode->mHeight = (KU8)(1 + (pNode->mHeight = (KU8)(1 + uLeftRightHeight)));
+                KAVL_SET_POINTER(ppNode, pLeftNode);
+            }
+            else
+            {
+                KAVL_SET_POINTER_NULL(&pLeftNode->mpRight, &pLeftRightNode->mpLeft);
+                KAVL_SET_POINTER_NULL(&pNode->mpLeft, &pLeftRightNode->mpRight);
+                KAVL_SET_POINTER(&pLeftRightNode->mpLeft, pLeftNode);
+                KAVL_SET_POINTER(&pLeftRightNode->mpRight, pNode);
+                pLeftNode->mHeight = pNode->mHeight = uLeftRightHeight;
+                pLeftRightNode->mHeight = uLeftHeight;
+                KAVL_SET_POINTER(ppNode, pLeftRightNode);
+            }
+        }
+        else if (uLeftHeight + 1 < uRightHeight)
+        {
+            KAVLNODE    *pRightLeftNode = KAVL_GET_POINTER_NULL(&pRightNode->mpLeft);
+            KU8          uRightLeftHeight = KAVL_HEIGHTOF(pRightLeftNode);
+            KAVLNODE    *pRightRightNode = KAVL_GET_POINTER_NULL(&pRightNode->mpRight);
+
+            if (KAVL_HEIGHTOF(pRightRightNode) >= uRightLeftHeight)
+            {
+                KAVL_SET_POINTER_NULL(&pNode->mpRight, &pRightNode->mpLeft);
+                KAVL_SET_POINTER(&pRightNode->mpLeft, pNode);
+                pRightNode->mHeight = (KU8)(1 + (pNode->mHeight = (KU8)(1 + uRightLeftHeight)));
+                KAVL_SET_POINTER(ppNode, pRightNode);
+            }
+            else
+            {
+                KAVL_SET_POINTER_NULL(&pRightNode->mpLeft, &pRightLeftNode->mpRight);
+                KAVL_SET_POINTER_NULL(&pNode->mpRight, &pRightLeftNode->mpLeft);
+                KAVL_SET_POINTER(&pRightLeftNode->mpRight, pRightNode);
+                KAVL_SET_POINTER(&pRightLeftNode->mpLeft, pNode);
+                pRightNode->mHeight = pNode->mHeight = uRightLeftHeight;
+                pRightLeftNode->mHeight = uRightHeight;
+                KAVL_SET_POINTER(ppNode, pRightLeftNode);
+            }
+        }
+        else
+        {
+            KU8 uHeight = (KU8)(K_MAX(uLeftHeight, uRightHeight) + 1);
+            if (uHeight == pNode->mHeight)
+                break;
+            pNode->mHeight = uHeight;
+        }
+    }
+
+}
+
+
+/**
+ * Initializes the root of the AVL-tree.
+ *
+ * @param     pTree     Pointer to the root structure.
+ */
+KAVL_DECL(void) KAVL_FN(Init)(KAVLROOT *pRoot)
+{
+#ifdef KAVL_LOOKTHRU
+    unsigned i;
+#endif
+
+    pRoot->mpRoot = KAVL_NULL;
+#ifdef KAVL_LOOKTHRU
+    for (i = 0; i < (KAVL_LOOKTHRU); i++)
+        pRoot->maLookthru[i] = KAVL_NULL;
+#endif
+}
+
+
+/**
+ * Inserts a node into the AVL-tree.
+ * @returns   K_TRUE if inserted.
+ *            K_FALSE if node exists in tree.
+ * @param     pRoot     Pointer to the AVL-tree root structure.
+ * @param     pNode     Pointer to the node which is to be added.
+ * @sketch    Find the location of the node (using binary tree algorithm.):
+ *            LOOP until NULL leaf pointer
+ *            BEGIN
+ *                Add node pointer pointer to the AVL-stack.
+ *                IF new-node-key < node key THEN
+ *                    left
+ *                ELSE
+ *                    right
+ *            END
+ *            Fill in leaf node and insert it.
+ *            Rebalance the tree.
+ */
+KAVL_DECL(KBOOL) KAVL_FN(Insert)(KAVLROOT *pRoot, KAVLNODE *pNode)
+{
+    KAVL_INT(STACK)     AVLStack;
+    KAVLTREEPTR        *ppCurNode = &pRoot->mpRoot;
+    register KAVLKEY    Key = pNode->mKey;
+#ifdef KAVL_RANGE
+    register KAVLKEY    KeyLast = pNode->mKeyLast;
+#endif
+
+#ifdef KAVL_RANGE
+    if (Key > KeyLast)
+        return K_FALSE;
+#endif
+
+    KAVL_WRITE_LOCK(pRoot);
+
+    AVLStack.cEntries = 0;
+    while (*ppCurNode != KAVL_NULL)
+    {
+        register KAVLNODE *pCurNode = KAVL_GET_POINTER(ppCurNode);
+
+        kHlpAssert(AVLStack.cEntries < KAVL_MAX_STACK);
+        AVLStack.aEntries[AVLStack.cEntries++] = ppCurNode;
+#ifdef KAVL_EQUAL_ALLOWED
+        if (KAVL_R_IS_IDENTICAL(pCurNode->mKey, Key, pCurNode->mKeyLast, KeyLast))
+        {
+            /*
+             * If equal then we'll use a list of equal nodes.
+             */
+            pNode->mpLeft = pNode->mpRight = KAVL_NULL;
+            pNode->mHeight = 0;
+            KAVL_SET_POINTER_NULL(&pNode->mpList, &pCurNode->mpList);
+            KAVL_SET_POINTER(&pCurNode->mpList, pNode);
+            KAVL_WRITE_UNLOCK(pRoot);
+            return K_TRUE;
+        }
+#endif
+#ifdef KAVL_CHECK_FOR_EQUAL_INSERT
+        if (KAVL_R_IS_INTERSECTING(pCurNode->mKey, Key, pCurNode->mKeyLast, KeyLast))
+        {
+            KAVL_WRITE_UNLOCK(pRoot);
+            return K_FALSE;
+        }
+#endif
+        if (KAVL_G(pCurNode->mKey, Key))
+            ppCurNode = &pCurNode->mpLeft;
+        else
+            ppCurNode = &pCurNode->mpRight;
+    }
+
+    pNode->mpLeft = pNode->mpRight = KAVL_NULL;
+#ifdef KAVL_EQUAL_ALLOWED
+    pNode->mpList = KAVL_NULL;
+#endif
+    pNode->mHeight = 1;
+    KAVL_SET_POINTER(ppCurNode, pNode);
+
+    KAVL_FN(Rebalance)(&AVLStack);
+
+    KAVL_WRITE_UNLOCK(pRoot);
+    return K_TRUE;
+}
+
+
+/**
+ * Removes a node from the AVL-tree.
+ * @returns   Pointer to the node.
+ * @param     pRoot     Pointer to the AVL-tree root structure.
+ * @param     Key       Key value of the node which is to be removed.
+ * @sketch    Find the node which is to be removed:
+ *            LOOP until not found
+ *            BEGIN
+ *                Add node pointer pointer to the AVL-stack.
+ *                IF the keys matches THEN break!
+ *                IF remove key < node key THEN
+ *                    left
+ *                ELSE
+ *                    right
+ *            END
+ *            IF found THEN
+ *            BEGIN
+ *                IF left node not empty THEN
+ *                BEGIN
+ *                    Find the right most node in the left tree while adding the pointer to the pointer to it's parent to the stack:
+ *                    Start at left node.
+ *                    LOOP until right node is empty
+ *                    BEGIN
+ *                        Add to stack.
+ *                        go right.
+ *                    END
+ *                    Link out the found node.
+ *                    Replace the node which is to be removed with the found node.
+ *                    Correct the stack entry for the pointer to the left tree.
+ *                END
+ *                ELSE
+ *                BEGIN
+ *                    Move up right node.
+ *                    Remove last stack entry.
+ *                END
+ *                Balance tree using stack.
+ *            END
+ *            return pointer to the removed node (if found).
+ */
+KAVL_DECL(KAVLNODE *) KAVL_FN(Remove)(KAVLROOT *pRoot, KAVLKEY Key)
+{
+    KAVL_INT(STACK)     AVLStack;
+    KAVLTREEPTR        *ppDeleteNode = &pRoot->mpRoot;
+    register KAVLNODE  *pDeleteNode;
+
+    KAVL_WRITE_LOCK(pRoot);
+
+    AVLStack.cEntries = 0;
+    for (;;)
+    {
+        if (*ppDeleteNode == KAVL_NULL)
+        {
+            KAVL_WRITE_UNLOCK(pRoot);
+            return NULL;
+        }
+        pDeleteNode = KAVL_GET_POINTER(ppDeleteNode);
+
+        kHlpAssert(AVLStack.cEntries < KAVL_MAX_STACK);
+        AVLStack.aEntries[AVLStack.cEntries++] = ppDeleteNode;
+        if (KAVL_E(pDeleteNode->mKey, Key))
+            break;
+
+        if (KAVL_G(pDeleteNode->mKey, Key))
+            ppDeleteNode = &pDeleteNode->mpLeft;
+        else
+            ppDeleteNode = &pDeleteNode->mpRight;
+    }
+
+    if (pDeleteNode->mpLeft != KAVL_NULL)
+    {
+        /* find the rightmost node in the left tree. */
+        const unsigned      iStackEntry = AVLStack.cEntries;
+        KAVLTREEPTR        *ppLeftLeast = &pDeleteNode->mpLeft;
+        register KAVLNODE  *pLeftLeast = KAVL_GET_POINTER(ppLeftLeast);
+
+        while (pLeftLeast->mpRight != KAVL_NULL)
+        {
+            kHlpAssert(AVLStack.cEntries < KAVL_MAX_STACK);
+            AVLStack.aEntries[AVLStack.cEntries++] = ppLeftLeast;
+            ppLeftLeast = &pLeftLeast->mpRight;
+            pLeftLeast  = KAVL_GET_POINTER(ppLeftLeast);
+        }
+
+        /* link out pLeftLeast */
+        KAVL_SET_POINTER_NULL(ppLeftLeast, &pLeftLeast->mpLeft);
+
+        /* link it in place of the delete node. */
+        KAVL_SET_POINTER_NULL(&pLeftLeast->mpLeft, &pDeleteNode->mpLeft);
+        KAVL_SET_POINTER_NULL(&pLeftLeast->mpRight, &pDeleteNode->mpRight);
+        pLeftLeast->mHeight = pDeleteNode->mHeight;
+        KAVL_SET_POINTER(ppDeleteNode, pLeftLeast);
+        AVLStack.aEntries[iStackEntry] = &pLeftLeast->mpLeft;
+    }
+    else
+    {
+        KAVL_SET_POINTER_NULL(ppDeleteNode, &pDeleteNode->mpRight);
+        AVLStack.cEntries--;
+    }
+
+    KAVL_FN(Rebalance)(&AVLStack);
+
+    KAVL_LOOKTHRU_INVALIDATE_NODE(pRoot, pDeleteNode, Key);
+
+    KAVL_WRITE_UNLOCK(pRoot);
+    return pDeleteNode;
+}
+
diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlDestroy.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlDestroy.h
new file mode 100644
index 0000000..17115f3
--- /dev/null
+++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlDestroy.h
@@ -0,0 +1,129 @@
+/* $Id: kAvlDestroy.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kAvlTmpl - Templated AVL Trees, Destroy the tree.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Destroys the specified tree, starting with the root node and working our way down.
+ *
+ * @returns 0 on success.
+ * @returns Return value from callback on failure. On failure, the tree will be in
+ *          an unbalanced condition and only further calls to the Destroy should be
+ *          made on it. Note that the node we fail on will be considered dead and
+ *          no action is taken to link it back into the tree.
+ * @param   pRoot           Pointer to the AVL-tree root structure.
+ * @param   pfnCallBack     Pointer to callback function.
+ * @param   pvUser          User parameter passed on to the callback function.
+ */
+KAVL_DECL(int) KAVL_FN(Destroy)(KAVLROOT *pRoot, KAVL_TYPE(PFN,CALLBACK) pfnCallBack, void *pvUser)
+{
+#ifdef KAVL_LOOKTHRU
+    unsigned    i;
+#endif
+    unsigned    cEntries;
+    KAVLNODE   *apEntries[KAVL_MAX_STACK];
+    int         rc;
+
+    KAVL_WRITE_LOCK(pRoot);
+    if (pRoot->mpRoot == KAVL_NULL)
+    {
+        KAVL_WRITE_UNLOCK(pRoot);
+        return 0;
+    }
+
+#ifdef KAVL_LOOKTHRU
+    /*
+     * Kill the lookthru cache.
+     */
+    for (i = 0; i < (KAVL_LOOKTHRU); i++)
+        pRoot->maLookthru[i] = KAVL_NULL;
+#endif
+
+    cEntries = 1;
+    apEntries[0] = KAVL_GET_POINTER(&pRoot->mpRoot);
+    while (cEntries > 0)
+    {
+        /*
+         * Process the subtrees first.
+         */
+        KAVLNODE *pNode = apEntries[cEntries - 1];
+        if (pNode->mpLeft != KAVL_NULL)
+            apEntries[cEntries++] = KAVL_GET_POINTER(&pNode->mpLeft);
+        else if (pNode->mpRight != KAVL_NULL)
+            apEntries[cEntries++] = KAVL_GET_POINTER(&pNode->mpRight);
+        else
+        {
+#ifdef KAVL_EQUAL_ALLOWED
+            /*
+             * Process nodes with the same key.
+             */
+            while (pNode->pList != KAVL_NULL)
+            {
+                KAVLNODE *pEqual = KAVL_GET_POINTER(&pNode->pList);
+                KAVL_SET_POINTER(&pNode->pList, KAVL_GET_POINTER_NULL(&pEqual->pList));
+                pEqual->pList = KAVL_NULL;
+
+                rc = pfnCallBack(pEqual, pvUser);
+                if (rc)
+                {
+                    KAVL_WRITE_UNLOCK(pRoot);
+                    return rc;
+                }
+            }
+#endif
+
+            /*
+             * Unlink the node.
+             */
+            if (--cEntries > 0)
+            {
+                KAVLNODE *pParent = apEntries[cEntries - 1];
+                if (KAVL_GET_POINTER(&pParent->mpLeft) == pNode)
+                    pParent->mpLeft = KAVL_NULL;
+                else
+                    pParent->mpRight = KAVL_NULL;
+            }
+            else
+                pRoot->mpRoot = KAVL_NULL;
+
+            kHlpAssert(pNode->mpLeft == KAVL_NULL);
+            kHlpAssert(pNode->mpRight == KAVL_NULL);
+            rc = pfnCallBack(pNode, pvUser);
+            if (rc)
+            {
+                KAVL_WRITE_UNLOCK(pRoot);
+                return rc;
+            }
+        }
+    } /* while */
+    kHlpAssert(pRoot->mpRoot == KAVL_NULL);
+
+    KAVL_WRITE_UNLOCK(pRoot);
+    return 0;
+}
+
diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlDoWithAll.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlDoWithAll.h
new file mode 100644
index 0000000..f2eaba1
--- /dev/null
+++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlDoWithAll.h
@@ -0,0 +1,166 @@
+/* $Id: kAvlDoWithAll.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kAvlTmpl - Templated AVL Trees, The Callback Iterator.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Stack used by DoWithAll to avoid recusive function calls.
+ */
+typedef struct
+{
+    unsigned        cEntries;
+    KAVLNODE       *aEntries[KAVL_MAX_STACK];
+    char            achFlags[KAVL_MAX_STACK];
+    KAVLROOT        pRoot;
+} KAVL_INT(STACK2);
+
+
+/**
+ * Iterates thru all nodes in the given tree.
+ *
+ * @returns   0 on success. Return from callback on failure.
+ * @param     pRoot        Pointer to the AVL-tree root structure.
+ * @param     fFromLeft    K_TRUE:  Left to right.
+ *                         K_FALSE: Right to left.
+ * @param     pfnCallBack  Pointer to callback function.
+ * @param     pvUser       User parameter passed on to the callback function.
+ */
+KAVL_DECL(int) KAVL_FN(DoWithAll)(KAVLROOT *pRoot, KBOOL fFromLeft, KAVL_TYPE(PFN,CALLBACK) pfnCallBack, void *pvUser)
+{
+    KAVL_INT(STACK2)    AVLStack;
+    KAVLNODE           *pNode;
+#ifdef KAVL_EQUAL_ALLOWED
+    KAVLNODE           *pEqual;
+#endif
+    int                 rc;
+
+    KAVL_READ_LOCK(pRoot);
+    if (pRoot->mpRoot == KAVL_NULL)
+    {
+        KAVL_READ_UNLOCK(pRoot);
+        return 0;
+    }
+
+    AVLStack.cEntries = 1;
+    AVLStack.achFlags[0] = 0;
+    AVLStack.aEntries[0] = KAVL_GET_POINTER(&pRoot->mpRoot);
+
+    if (fFromLeft)
+    {   /* from left */
+        while (AVLStack.cEntries > 0)
+        {
+            pNode = AVLStack.aEntries[AVLStack.cEntries - 1];
+
+            /* left */
+            if (!AVLStack.achFlags[AVLStack.cEntries - 1]++)
+            {
+                if (pNode->mpLeft != KAVL_NULL)
+                {
+                    AVLStack.achFlags[AVLStack.cEntries] = 0; /* 0 first, 1 last */
+                    AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->mpLeft);
+                    continue;
+                }
+            }
+
+            /* center */
+            rc = pfnCallBack(pNode, pvUser);
+            if (rc)
+                return rc;
+#ifdef KAVL_EQUAL_ALLOWED
+            if (pNode->mpList != KAVL_NULL)
+                for (pEqual = KAVL_GET_POINTER(&pNode->mpList); pEqual; pEqual = KAVL_GET_POINTER_NULL(&pEqual->mpList))
+                {
+                    rc = pfnCallBack(pEqual, pvUser);
+                    if (rc)
+                    {
+                        KAVL_READ_UNLOCK(pRoot);
+                        return rc;
+                    }
+                }
+#endif
+
+            /* right */
+            AVLStack.cEntries--;
+            if (pNode->mpRight != KAVL_NULL)
+            {
+                AVLStack.achFlags[AVLStack.cEntries] = 0;
+                AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->mpRight);
+            }
+        } /* while */
+    }
+    else
+    {   /* from right */
+        while (AVLStack.cEntries > 0)
+        {
+            pNode = AVLStack.aEntries[AVLStack.cEntries - 1];
+
+            /* right */
+            if (!AVLStack.achFlags[AVLStack.cEntries - 1]++)
+            {
+                if (pNode->mpRight != KAVL_NULL)
+                {
+                    AVLStack.achFlags[AVLStack.cEntries] = 0;  /* 0 first, 1 last */
+                    AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->mpRight);
+                    continue;
+                }
+            }
+
+            /* center */
+            rc = pfnCallBack(pNode, pvUser);
+            if (rc)
+                return rc;
+#ifdef KAVL_EQUAL_ALLOWED
+            if (pNode->mpList != KAVL_NULL)
+                for (pEqual = KAVL_GET_POINTER(&pNode->mpList); pEqual; pEqual = KAVL_GET_POINTER_NULL(&pEqual->pList))
+                {
+                    rc = pfnCallBack(pEqual, pvUser);
+                    if (rc)
+                    {
+                        KAVL_READ_UNLOCK(pRoot);
+                        return rc;
+                    }
+                }
+#endif
+
+            /* left */
+            AVLStack.cEntries--;
+            if (pNode->mpLeft != KAVL_NULL)
+            {
+                AVLStack.achFlags[AVLStack.cEntries] = 0;
+                AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->mpLeft);
+            }
+        } /* while */
+    }
+
+    KAVL_READ_UNLOCK(pRoot);
+    return 0;
+}
+
diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlEnum.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlEnum.h
new file mode 100644
index 0000000..da151d1
--- /dev/null
+++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlEnum.h
@@ -0,0 +1,187 @@
+/* $Id: kAvlEnum.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kAvlTmpl - Templated AVL Trees, Node Enumeration.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Enumeration control data.
+ *
+ * This is initialized by BeginEnum and used by GetNext to figure out what
+ * to do next.
+ */
+typedef struct KAVL_TYPE(,ENUMDATA)
+{
+    KBOOL               fFromLeft;
+    KI8                 cEntries;
+    KU8                 achFlags[KAVL_MAX_STACK];
+    KAVLNODE *          aEntries[KAVL_MAX_STACK];
+} KAVL_TYPE(,ENUMDATA), *KAVL_TYPE(P,ENUMDATA);
+
+
+/**
+ * Ends an enumeration.
+ *
+ * The purpose of this function is to unlock the tree should the
+ * AVL implementation include locking. It's good practice to call
+ * it anyway even if the tree doesn't do any locking.
+ *
+ * @param   pEnumData   Pointer to enumeration control data.
+ */
+KAVL_DECL(void) KAVL_FN(EndEnum)(KAVL_TYPE(,ENUMDATA) *pEnumData)
+{
+    KAVLROOT pRoot = pEnumData->pRoot;
+    pEnumData->pRoot = NULL;
+    if (pRoot)
+        KAVL_READ_UNLOCK(pEnumData->pRoot);
+}
+
+
+/**
+ * Get the next node in the tree enumeration.
+ *
+ * The current implementation of this function willl not walk the mpList
+ * chain like the DoWithAll function does. This may be changed later.
+ *
+ * @returns Pointer to the next node in the tree.
+ *          NULL is returned when the end of the tree has been reached,
+ *          it is not necessary to call EndEnum in this case.
+ * @param   pEnumData   Pointer to enumeration control data.
+ */
+KAVL_DECL(KAVLNODE *) KAVL_FN(GetNext)(KAVL_TYPE(,ENUMDATA) *pEnumData)
+{
+    if (pEnumData->fFromLeft)
+    {   /* from left */
+        while (pEnumData->cEntries > 0)
+        {
+            KAVLNODE *pNode = pEnumData->aEntries[pEnumData->cEntries - 1];
+
+            /* left */
+            if (pEnumData->achFlags[pEnumData->cEntries - 1] == 0)
+            {
+                pEnumData->achFlags[pEnumData->cEntries - 1]++;
+                if (pNode->mpLeft != KAVL_NULL)
+                {
+                    pEnumData->achFlags[pEnumData->cEntries] = 0; /* 0 left, 1 center, 2 right */
+                    pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->mpLeft);
+                    continue;
+                }
+            }
+
+            /* center */
+            if (pEnumData->achFlags[pEnumData->cEntries - 1] == 1)
+            {
+                pEnumData->achFlags[pEnumData->cEntries - 1]++;
+                return pNode;
+            }
+
+            /* right */
+            pEnumData->cEntries--;
+            if (pNode->mpRight != KAVL_NULL)
+            {
+                pEnumData->achFlags[pEnumData->cEntries] = 0;
+                pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->mpRight);
+            }
+        } /* while */
+    }
+    else
+    {   /* from right */
+        while (pEnumData->cEntries > 0)
+        {
+            KAVLNODE *pNode = pEnumData->aEntries[pEnumData->cEntries - 1];
+
+            /* right */
+            if (pEnumData->achFlags[pEnumData->cEntries - 1] == 0)
+            {
+                pEnumData->achFlags[pEnumData->cEntries - 1]++;
+                if (pNode->mpRight != KAVL_NULL)
+                {
+                    pEnumData->achFlags[pEnumData->cEntries] = 0;  /* 0 right, 1 center, 2 left */
+                    pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->mpRight);
+                    continue;
+                }
+            }
+
+            /* center */
+            if (pEnumData->achFlags[pEnumData->cEntries - 1] == 1)
+            {
+                pEnumData->achFlags[pEnumData->cEntries - 1]++;
+                return pNode;
+            }
+
+            /* left */
+            pEnumData->cEntries--;
+            if (pNode->mpLeft != KAVL_NULL)
+            {
+                pEnumData->achFlags[pEnumData->cEntries] = 0;
+                pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->mpLeft);
+            }
+        } /* while */
+    }
+
+    /*
+     * Call EndEnum.
+     */
+    KAVL_FN(EndEnum)(pEnumData);
+    return NULL;
+}
+
+
+/**
+ * Starts an enumeration of all nodes in the given AVL tree.
+ *
+ * The current implementation of this function will not walk the mpList
+ * chain like the DoWithAll function does. This may be changed later.
+ *
+ * @returns Pointer to the first node in the enumeration.
+ *          If NULL is returned the tree is empty calling EndEnum isn't
+ *          strictly necessary (although it will do no harm).
+ * @param   pRoot           Pointer to the AVL-tree root structure.
+ * @param   pEnumData       Pointer to enumeration control data.
+ * @param   fFromLeft       K_TRUE:  Left to right.
+ *                          K_FALSE: Right to left.
+ */
+KAVL_DECL(KAVLNODE *) KAVL_FN(BeginEnum)(KAVLROOT *pRoot, KAVL_TYPE(,ENUMDATA) *pEnumData, KBOOL fFromLeft)
+{
+    KAVL_READ_LOCK(pRoot);
+    pEnumData->pRoot = pRoot;
+    if (pRoot->mpRoot != KAVL_NULL)
+    {
+        pEnumData->fFromLeft = fFromLeft;
+        pEnumData->cEntries = 1;
+        pEnumData->aEntries[0] = KAVL_GET_POINTER(pRoot->mpRoot);
+        pEnumData->achFlags[0] = 0;
+    }
+    else
+        pEnumData->cEntries = 0;
+
+    return KAVL_FN(GetNext)(pEnumData);
+}
+
diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlGet.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlGet.h
new file mode 100644
index 0000000..a80eb49
--- /dev/null
+++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlGet.h
@@ -0,0 +1,89 @@
+/* $Id: kAvlGet.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kAvlTmpl - Templated AVL Trees, Get a Node.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Gets a node from the tree (does not remove it!)
+ *
+ * @returns Pointer to the node holding the given key.
+ * @param   pRoot       Pointer to the AVL-tree root structure.
+ * @param   Key         Key value of the node which is to be found.
+ */
+KAVL_DECL(KAVLNODE *) KAVL_FN(Get)(KAVLROOT *pRoot, KAVLKEY Key)
+{
+    KAVLNODE *pNode;
+#ifdef KAVL_LOOKTHRU_CACHE
+    KAVLTREEPTR *ppEntry;
+#endif
+
+    KAVL_READ_LOCK(pRoot);
+    if (pRoot->mpRoot == KAVL_NULL)
+    {
+        KAVL_READ_UNLOCK(pRoot);
+        return NULL;
+    }
+
+#ifdef KAVL_LOOKTHRU_CACHE
+    ppEntry = &pRoot->maLookthru[KAVL_LOOKTHRU_HASH(Key)];
+    pNode = KAVL_GET_POINTER_NULL(ppEntry);
+    if (!pNode || KAVL_NE(pNode->mKey, Key))
+#endif
+    {
+        pNode = KAVL_GET_POINTER(&pRoot->mpRoot);
+        while (KAVL_NE(pNode->mKey, Key))
+        {
+            if (KAVL_G(pNode->mKey, Key))
+            {
+                if (pNode->mpLeft == KAVL_NULL)
+                {
+                    KAVL_READ_UNLOCK(pRoot);
+                    return NULL;
+                }
+                pNode = KAVL_GET_POINTER(&pNode->mpLeft);
+            }
+            else
+            {
+                if (pNode->mpRight == KAVL_NULL)
+                {
+                    KAVL_READ_UNLOCK(pRoot);
+                    return NULL;
+                }
+                pNode = KAVL_GET_POINTER(&pNode->mpRight);
+            }
+        }
+
+#ifdef KAVL_LOOKTHRU_CACHE
+        KAVL_SET_POINTER(ppEntry, pNode);
+#endif
+    }
+
+    KAVL_READ_UNLOCK(pRoot);
+    return pNode;
+}
+
diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlGetBestFit.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlGetBestFit.h
new file mode 100644
index 0000000..1d51709
--- /dev/null
+++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlGetBestFit.h
@@ -0,0 +1,112 @@
+/* $Id: kAvlGetBestFit.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kAvlTmpl - Templated AVL Trees, Get Best Fitting Node.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Finds the best fitting node in the tree for the given Key value.
+ *
+ * @returns Pointer to the best fitting node found.
+ * @param   pRoot           Pointer to the AVL-tree root structure.
+ * @param   Key             The Key of which is to be found a best fitting match for..
+ * @param   fAbove          K_TRUE:  Returned node is have the closest key to Key from above.
+ *                          K_FALSE: Returned node is have the closest key to Key from below.
+ * @sketch  The best fitting node is always located in the searchpath above you.
+ *          >= (above): The node where you last turned left.
+ *          <= (below): the node where you last turned right.
+ */
+KAVL_DECL(KAVLNODE *) KAVL_FN(GetBestFit)(KAVLROOT *pRoot, KAVLKEY Key, KBOOL fAbove)
+{
+    register KAVLNODE  *pNode;
+    KAVLNODE           *pNodeLast;
+
+    KAVL_READ_LOCK(pLook);
+    if (pRoot->mpRoot == KAVL_NULL)
+    {
+        KAVL_READ_UNLOCK(pLook);
+        return NULL;
+    }
+
+    pNode = KAVL_GET_POINTER(&pRoot->mpRoot);
+    pNodeLast = NULL;
+    if (fAbove)
+    {   /* pNode->mKey >= Key */
+        while (KAVL_NE(pNode->mKey, Key))
+        {
+            if (KAVL_G(pNode->mKey, Key))
+            {
+                if (pNode->mpLeft == KAVL_NULL)
+                {
+                    KAVL_READ_UNLOCK(pLook);
+                    return pNode;
+                }
+                pNodeLast = pNode;
+                pNode = KAVL_GET_POINTER(&pNode->mpLeft);
+            }
+            else
+            {
+                if (pNode->mpRight == KAVL_NULL)
+                {
+                    KAVL_READ_UNLOCK(pLook);
+                    return pNodeLast;
+                }
+                pNode = KAVL_GET_POINTER(&pNode->mpRight);
+            }
+        }
+    }
+    else
+    {   /* pNode->mKey <= Key */
+        while (KAVL_NE(pNode->mKey, Key))
+        {
+            if (KAVL_G(pNode->mKey, Key))
+            {
+                if (pNode->mpLeft == KAVL_NULL)
+                {
+                    KAVL_READ_UNLOCK(pLook);
+                    return pNodeLast;
+                }
+                pNode = KAVL_GET_POINTER(&pNode->mpLeft);
+            }
+            else
+            {
+                if (pNode->mpRight == KAVL_NULL)
+                {
+                    KAVL_READ_UNLOCK(pLook);
+                    return pNode;
+                }
+                pNodeLast = pNode;
+                pNode = KAVL_GET_POINTER(&pNode->mpRight);
+            }
+        }
+    }
+
+    /* perfect match or nothing. */
+    KAVL_READ_UNLOCK(pLook);
+    return pNode;
+}
+
diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlGetWithParent.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlGetWithParent.h
new file mode 100644
index 0000000..997c394
--- /dev/null
+++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlGetWithParent.h
@@ -0,0 +1,65 @@
+/* $Id: kAvlGetWithParent.h 34 2009-11-08 19:38:40Z bird $ */
+/** @file
+ * kAvlTmpl - Templated AVL Trees, Get Node With Parent.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Gets a node from the tree and its parent node (if any).
+ * The tree remains unchanged.
+ *
+ * @returns Pointer to the node holding the given key.
+ * @param   pRoot       Pointer to the AVL-tree root structure.
+ * @param   ppParent    Pointer to a variable which will hold the pointer to the partent node on
+ *                      return. When no node is found, this will hold the last searched node.
+ * @param   Key         Key value of the node which is to be found.
+ */
+KAVL_DECL(KAVLNODE *) KAVL_FN(GetWithParent)(KAVLROOT *pRoot, KAVLNODE **ppParent, KAVLKEY Key)
+{
+    register KAVLNODE *pNode;
+    register KAVLNODE *pParent;
+
+    KAVL_READ_LOCK(pRoot);
+
+    pParent = NULL;
+    pNode = KAVL_GET_POINTER_NULL(&pRoot->mpRoot);
+    while (     pNode != NULL
+           &&   KAVL_NE(pNode->mKey, Key))
+    {
+        pParent = pNode;
+        if (KAVL_G(pNode->mKey, Key))
+            pNode = KAVL_GET_POINTER_NULL(&pNode->mpLeft);
+        else
+            pNode = KAVL_GET_POINTER_NULL(&pNode->mpRight);
+    }
+
+    KAVL_READ_UNLOCK(pRoot);
+
+    *ppParent = pParent;
+    return pNode;
+}
+
diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlRemove2.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlRemove2.h
new file mode 100644
index 0000000..d027014
--- /dev/null
+++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlRemove2.h
@@ -0,0 +1,133 @@
+/* $Id: kAvlRemove2.h 34 2009-11-08 19:38:40Z bird $ */
+/** @file
+ * kAvlTmpl - Templated AVL Trees, Remove A Specific Node.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Removes the specified node from the tree.
+ *
+ * @returns Pointer to the removed node (NULL if not in the tree)
+ * @param   pRoot       Pointer to the AVL-tree root structure.
+ * @param   Key         The Key of which is to be found a best fitting match for..
+ *
+ * @remark  This implementation isn't the most efficient, but this short and
+ *          easier to manage.
+ */
+KAVL_DECL(KAVLNODE *) KAVL_FN(Remove2)(KAVLROOT *pRoot, KAVLNODE *pNode)
+{
+#ifdef KAVL_EQUAL_ALLOWED
+    /*
+     * Find the right node by key and see if it's what we want.
+     */
+    KAVLNODE *pParent;
+    KAVLNODE *pCurNode = KAVL_FN(GetWithParent)(pRoot, pNode->mKey, &pParent);
+    if (!pCurNode)
+        return NULL;
+    KAVL_WRITE_LOCK(pRoot); /** @todo the locking here isn't 100% sane. The only way to archive that is by no calling worker functions. */
+    if (pCurNode != pNode)
+    {
+        /*
+         * It's not the one we want, but it could be in the duplicate list.
+         */
+        while (pCurNode->mpList != KAVL_NULL)
+        {
+            KAVLNODE *pNext = KAVL_GET_POINTER(&pCurNode->mpList);
+            if (pNext == pNode)
+            {
+                KAVL_SET_POINTER_NULL(&pCurNode->mpList, KAVL_GET_POINTER_NULL(&pNode->mpList));
+                pNode->mpList = KAVL_NULL;
+                KAVL_LOOKTHRU_INVALIDATE_NODE(pRoot, pNode, pNode->mKey);
+                KAVL_WRITE_UNLOCK(pRoot);
+                return pNode;
+            }
+            pCurNode = pNext;
+        }
+        KAVL_WRITE_UNLOCK(pRoot);
+        return NULL;
+    }
+
+    /*
+     * Ok, it's the one we want alright.
+     *
+     * Simply remove it if it's the only one with they Key,
+     * if there are duplicates we'll have to unlink it and
+     * insert the first duplicate in our place.
+     */
+    if (pNode->mpList == KAVL_NULL)
+    {
+        KAVL_WRITE_UNLOCK(pRoot);
+        KAVL_FN(Remove)(pRoot, pNode->mKey);
+    }
+    else
+    {
+        KAVLNODE *pNewUs = KAVL_GET_POINTER(&pNode->mpList);
+
+        pNewUs->mHeight = pNode->mHeight;
+
+        if (pNode->mpLeft != KAVL_NULL)
+            KAVL_SET_POINTER(&pNewUs->mpLeft, KAVL_GET_POINTER(&pNode->mpLeft))
+        else
+            pNewUs->mpLeft = KAVL_NULL;
+
+        if (pNode->mpRight != KAVL_NULL)
+            KAVL_SET_POINTER(&pNewUs->mpRight, KAVL_GET_POINTER(&pNode->mpRight))
+        else
+            pNewUs->mpRight = KAVL_NULL;
+
+        if (pParent)
+        {
+            if (KAVL_GET_POINTER_NULL(&pParent->mpLeft) == pNode)
+                KAVL_SET_POINTER(&pParent->mpLeft, pNewUs);
+            else
+                KAVL_SET_POINTER(&pParent->mpRight, pNewUs);
+        }
+        else
+            KAVL_SET_POINTER(&pRoot->mpRoot, pNewUs);
+
+        KAVL_LOOKTHRU_INVALIDATE_NODE(pRoot, pNode, pNode->mKey);
+        KAVL_WRITE_UNLOCK(pRoot);
+    }
+
+    return pNode;
+
+#else
+    /*
+     * Delete it, if we got the wrong one, reinsert it.
+     *
+     * This ASSUMS that the caller is NOT going to hand us a lot
+     * of wrong nodes but just uses this API for his convenience.
+     */
+    KAVLNODE *pRemovedNode = KAVL_FN(Remove)(pRoot, pNode->mKey);
+    if (pRemovedNode == pNode)
+        return pRemovedNode;
+
+    KAVL_FN(Insert)(pRoot, pRemovedNode);
+    return NULL;
+#endif
+}
+
diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlRemoveBestFit.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlRemoveBestFit.h
new file mode 100644
index 0000000..3c9ed98
--- /dev/null
+++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlRemoveBestFit.h
@@ -0,0 +1,70 @@
+/* $Id: kAvlRemoveBestFit.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kAvlTmpl - Templated AVL Trees, Remove Best Fitting Node.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Finds the best fitting node in the tree for the given Key value and removes the node.
+ *
+ * @returns Pointer to the removed node.
+ * @param   pRoot       Pointer to the AVL-tree root structure.
+ * @param   Key         The Key of which is to be found a best fitting match for..
+ * @param   fAbove      K_TRUE:  Returned node is have the closest key to Key from above.
+ *                      K_FALSE: Returned node is have the closest key to Key from below.
+ *
+ * @remark  This implementation uses GetBestFit and then Remove and might therefore
+ *          not be the most optimal kind of implementation, but it reduces the complexity
+ *          code size, and the likelyhood for bugs.
+ */
+KAVL_DECL(KAVLNODE *) KAVL_FN(RemoveBestFit)(KAVLROOT *pRoot, KAVLKEY Key, KBOOL fAbove)
+{
+    /*
+     * If we find anything we'll have to remove the node and return it.
+     * Now, if duplicate keys are allowed we'll remove a duplicate before
+     * removing the in-tree node as this is way cheaper.
+     */
+    KAVLNODE *pNode = KAVL_FN(GetBestFit)(pRoot, Key, fAbove);
+    if (pNode != NULL)
+    {
+#ifdef KAVL_EQUAL_ALLOWED
+        KAVL_WRITE_LOCK(pRoot); /** @todo the locking isn't quite sane here. :-/ */
+        if (pNode->mpList != KAVL_NULL)
+        {
+            KAVLNODE *pRet = KAVL_GET_POINTER(&pNode->mpList);
+            KAVL_SET_POINTER_NULL(&pNode->mpList, &pRet->mpList);
+            KAVL_LOOKTHRU_INVALIDATE_NODE(pRoot, pNode, pNode->mKey);
+            KAVL_WRITE_UNLOCK(pRoot);
+            return pRet;
+        }
+        KAVL_WRITE_UNLOCK(pRoot);
+#endif
+        pNode = KAVL_FN(Remove)(pRoot, pNode->mKey);
+    }
+    return pNode;
+}
+
diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlUndef.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlUndef.h
new file mode 100644
index 0000000..bd6957f
--- /dev/null
+++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlUndef.h
@@ -0,0 +1,79 @@
+/* $Id: kAvlUndef.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kAvlTmpl - Undefines All Macros (both config and temp).
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The configuration.
+ */
+#undef KAVL_EQUAL_ALLOWED
+#undef KAVL_CHECK_FOR_EQUAL_INSERT
+#undef KAVL_MAX_STACK
+#undef KAVL_RANGE
+#undef KAVL_OFFSET
+#undef KAVL_STD_KEY_COMP
+#undef KAVL_LOOKTHRU
+#undef KAVL_LOOKTHRU_HASH
+#undef KAVL_LOCKED
+#undef KAVL_WRITE_LOCK
+#undef KAVL_WRITE_UNLOCK
+#undef KAVL_READ_LOCK
+#undef KAVL_READ_UNLOCK
+#undef KAVLKEY
+#undef KAVLNODE
+#undef KAVLTREEPTR
+#undef KAVLROOT
+#undef KAVL_FN
+#undef KAVL_TYPE
+#undef KAVL_INT
+#undef KAVL_DECL
+#undef mKey
+#undef mKeyLast
+#undef mHeight
+#undef mpLeft
+#undef mpRight
+#undef mpList
+#undef mpRoot
+#undef maLookthru
+
+/*
+ * The internal macros.
+ */
+#undef KAVL_HEIGHTOF
+#undef KAVL_GET_POINTER
+#undef KAVL_GET_POINTER_NULL
+#undef KAVL_SET_POINTER
+#undef KAVL_SET_POINTER_NULL
+#undef KAVL_NULL
+#undef KAVL_G
+#undef KAVL_E
+#undef KAVL_NE
+#undef KAVL_R_IS_IDENTICAL
+#undef KAVL_R_IS_INTERSECTING
+#undef KAVL_R_IS_IN_RANGE
+
diff --git a/src/lib/kStuff/include/k/kAvlU32.h b/src/lib/kStuff/include/k/kAvlU32.h
new file mode 100644
index 0000000..7aacb15
--- /dev/null
+++ b/src/lib/kStuff/include/k/kAvlU32.h
@@ -0,0 +1,66 @@
+/* $Id: kAvlU32.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kAvl - AVL Tree Implementation, KU32 keys.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kAvlU32_h___
+#define ___k_kAvlU32_h___
+
+typedef struct KAVLU32
+{
+    KU32                mKey;
+    KU8                 mHeight;
+    struct KAVLU32     *mpLeft;
+    struct KAVLU32     *mpRight;
+} KAVLU32, *PKAVLU32, **PPKAVLU32;
+
+/*#define KAVL_EQUAL_ALLOWED*/
+#define KAVL_CHECK_FOR_EQUAL_INSERT
+#define KAVL_MAX_STACK          32
+/*#define KAVL_RANGE */
+/*#define KAVL_OFFSET */
+#define KAVL_STD_KEY_COMP
+#define KAVLKEY                 KU32
+#define KAVLNODE            KAVLU32
+#define KAVL_FN(name)           kAvlU32 ## name
+#define KAVL_TYPE(prefix,name)  prefix ## KAVLU32 ## name
+#define KAVL_INT(name)          KAVLU32INT ## name
+#define KAVL_DECL(rettype)      K_DECL_INLINE(rettype)
+
+#include <k/kAvlTmpl/kAvlBase.h>
+#include <k/kAvlTmpl/kAvlDoWithAll.h>
+#include <k/kAvlTmpl/kAvlEnum.h>
+#include <k/kAvlTmpl/kAvlGet.h>
+#include <k/kAvlTmpl/kAvlGetBestFit.h>
+#include <k/kAvlTmpl/kAvlGetWithParent.h>
+#include <k/kAvlTmpl/kAvlRemove2.h>
+#include <k/kAvlTmpl/kAvlRemoveBestFit.h>
+#include <k/kAvlTmpl/kAvlUndef.h>
+
+#endif
+
diff --git a/src/lib/kStuff/include/k/kAvloU32.h b/src/lib/kStuff/include/k/kAvloU32.h
new file mode 100644
index 0000000..e9ad305
--- /dev/null
+++ b/src/lib/kStuff/include/k/kAvloU32.h
@@ -0,0 +1,75 @@
+/* $Id: kAvloU32.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kAvl - AVL Tree Implementation, KU32 keys, Offset Based.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kAvloU32_h___
+#define ___k_kAvloU32_h___
+
+typedef KI32 KAVLOU32PTR;
+
+typedef struct KAVLOU32
+{
+    KU32                u32;
+    KU8                 cFloorsToGo;
+    KAVLOU32PTR         offLeft;
+    KAVLOU32PTR         offRight;
+} KAVLOU32, *PKAVLOU32, **PPKAVLOU32;
+
+#define mKey                    u32
+#define mHeight                 cFloorsToGo
+#define mpLeft                  offLeft
+#define mpRight                 offRight
+
+/*#define KAVL_EQUAL_ALLOWED*/
+#define KAVL_CHECK_FOR_EQUAL_INSERT
+#define KAVL_MAX_STACK          32
+/*#define KAVL_RANGE */
+#define KAVL_OFFSET
+#define KAVL_STD_KEY_COMP
+#define KAVLKEY                 KU32
+#define KAVLTREEPTR             KAVLOU32PTR
+#define KAVLNODE                KAVLOU32
+#define KAVL_FN(name)           kAvloU32 ## name
+#define KAVL_TYPE(prefix,name)  prefix ## KAVLOU32 ## name
+#define KAVL_INT(name)          KAVLOU32INT ## name
+#define KAVL_DECL(rettype)      K_DECL_INLINE(rettype)
+
+#include <k/kAvlTmpl/kAvlBase.h>
+#include <k/kAvlTmpl/kAvlDoWithAll.h>
+#include <k/kAvlTmpl/kAvlEnum.h>
+#include <k/kAvlTmpl/kAvlGet.h>
+#include <k/kAvlTmpl/kAvlGetBestFit.h>
+#include <k/kAvlTmpl/kAvlGetWithParent.h>
+#include <k/kAvlTmpl/kAvlRemove2.h>
+#include <k/kAvlTmpl/kAvlRemoveBestFit.h>
+#include <k/kAvlTmpl/kAvlUndef.h>
+
+#endif
+
+
diff --git a/src/lib/kStuff/include/k/kAvlrU32.h b/src/lib/kStuff/include/k/kAvlrU32.h
new file mode 100644
index 0000000..532a55d
--- /dev/null
+++ b/src/lib/kStuff/include/k/kAvlrU32.h
@@ -0,0 +1,71 @@
+/* $Id: kAvlrU32.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kAvl - AVL Tree Implementation, KU32 key ranges.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kAvlrU32_h___
+#define ___k_kAvlrU32_h___
+
+typedef struct KAVLRU32
+{
+    KU32                u32Start;
+    KU32                u32Last;
+    struct KAVLRU32    *mpLeft;
+    struct KAVLRU32    *mpRight;
+    KU8                 mHeight;
+} KAVLRU32, *PKAVLRU32, **PPKAVLRU32;
+
+#define mKey                    u32Start
+#define mKeyLast                u32Last
+
+/*#define KAVL_EQUAL_ALLOWED*/
+#define KAVL_CHECK_FOR_EQUAL_INSERT
+#define KAVL_MAX_STACK          32
+#define KAVL_RANGE
+/*#define KAVL_OFFSET */
+#define KAVL_STD_KEY_COMP
+#define KAVLKEY                 KU32
+#define KAVLNODE                KAVLRU32
+#define KAVL_FN(name)           kAvlrU32 ## name
+#define KAVL_TYPE(prefix,name)  prefix ## KAVLRU32 ## name
+#define KAVL_INT(name)          KAVLRU32INT ## name
+#define KAVL_DECL(rettype)      K_DECL_INLINE(rettype)
+
+#include <k/kAvlTmpl/kAvlBase.h>
+#include <k/kAvlTmpl/kAvlDoWithAll.h>
+#include <k/kAvlTmpl/kAvlEnum.h>
+#include <k/kAvlTmpl/kAvlGet.h>
+#include <k/kAvlTmpl/kAvlGetBestFit.h>
+#include <k/kAvlTmpl/kAvlGetWithParent.h>
+#include <k/kAvlTmpl/kAvlRemove2.h>
+#include <k/kAvlTmpl/kAvlRemoveBestFit.h>
+#include <k/kAvlTmpl/kAvlUndef.h>
+
+#endif
+
+
diff --git a/src/lib/kStuff/include/k/kCpu.h b/src/lib/kStuff/include/k/kCpu.h
new file mode 100644
index 0000000..bbbf815
--- /dev/null
+++ b/src/lib/kStuff/include/k/kCpu.h
@@ -0,0 +1,68 @@
+/* $Id: kCpu.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kCpu - The CPU and Architecture API.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kCpu_h___
+#define ___k_kCpu_h___
+
+#include <k/kDefs.h>
+#include <k/kTypes.h>
+#include <k/kCpus.h>
+
+
+/** @defgroup grp_kCpu      kCpu  - The CPU And Architecture API
+ * @{
+ */
+
+/** @def KCPU_DECL
+ * Declares a kCpu function according to build context.
+ * @param type          The return type.
+ */
+#if defined(KCPU_BUILDING_DYNAMIC)
+# define KCPU_DECL(type)        K_DECL_EXPORT(type)
+#elif defined(KCPU_BUILT_DYNAMIC)
+# define KCPU_DECL(type)        K_DECL_IMPORT(type)
+#else
+# define KCPU_DECL(type)        type
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+KCPU_DECL(void) kCpuGetArchAndCpu(PKCPUARCH penmArch, PKCPU penmCpu);
+KCPU_DECL(int)  kCpuCompare(KCPUARCH enmCodeArch, KCPU enmCodeCpu, KCPUARCH enmArch, KCPU enmCpu);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif
diff --git a/src/lib/kStuff/include/k/kCpus.h b/src/lib/kStuff/include/k/kCpus.h
new file mode 100644
index 0000000..6fa8400
--- /dev/null
+++ b/src/lib/kStuff/include/k/kCpus.h
@@ -0,0 +1,157 @@
+/* $Id: kCpus.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kCpus - CPU Identifiers.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kCpus_h___
+#define ___k_kCpus_h___
+
+/** @defgroup grp_kCpus     kCpus - CPU Identifiers
+ * @see the kCpu API for functions operating on the CPU type.
+ * @{
+ */
+
+/**
+ * CPU Architectures.
+ *
+ * The constants used by this enum has the same values as
+ * the K_ARCH_* #defines defined by k/kDefs.h.
+ */
+typedef enum KCPUARCH
+{
+    /** @copydoc K_ARCH_UNKNOWN */
+    KCPUARCH_UNKNOWN = K_ARCH_UNKNOWN,
+    /** @copydoc K_ARCH_X86_16 */
+    KCPUARCH_X86_16 = K_ARCH_X86_16,
+    /** @copydoc K_ARCH_X86_32 */
+    KCPUARCH_X86_32 = K_ARCH_X86_32,
+    /** @copydoc K_ARCH_AMD64 */
+    KCPUARCH_AMD64 = K_ARCH_AMD64,
+    /** @copydoc K_ARCH_IA64 */
+    KCPUARCH_IA64 = K_ARCH_IA64,
+    /** @copydoc K_ARCH_ALPHA */
+    KCPUARCH_ALPHA = K_ARCH_ALPHA,
+    /** @copydoc K_ARCH_ALPHA_32 */
+    KCPUARCH_ALPHA_32 = K_ARCH_ALPHA_32,
+    /** @copydoc K_ARCH_ARM_32 */
+    KCPUARCH_ARM_32 = K_ARCH_ARM_32,
+    /** @copydoc K_ARCH_ARM_64 */
+    KCPUARCH_ARM_64 = K_ARCH_ARM_64,
+    /** @copydoc K_ARCH_MIPS_32 */
+    KCPUARCH_MIPS_32 = K_ARCH_MIPS_32,
+    /** @copydoc K_ARCH_MIPS_64 */
+    KCPUARCH_MIPS_64 = K_ARCH_MIPS_64,
+    /** @copydoc K_ARCH_POWERPC_32 */
+    KCPUARCH_POWERPC_32 = K_ARCH_POWERPC_32,
+    /** @copydoc K_ARCH_POWERPC_64 */
+    KCPUARCH_POWERPC_64 = K_ARCH_POWERPC_64,
+    /** @copydoc K_ARCH_SPARC_32 */
+    KCPUARCH_SPARC_32 = K_ARCH_SPARC_32,
+    /** @copydoc K_ARCH_SPARC_64 */
+    KCPUARCH_SPARC_64 = K_ARCH_SPARC_64,
+
+    /** Hack to blow the type up to 32-bit. */
+    KCPUARCH_32BIT_HACK = 0x7fffffff
+} KCPUARCH;
+
+/** Pointer to a CPU architecture type. */
+typedef KCPUARCH *PKCPUARCH;
+/** Pointer to a const CPU architecture type. */
+typedef const KCPUARCH *PCKCPUARCH;
+
+
+/**
+ * CPU models.
+ */
+typedef enum KCPU
+{
+    /** The usual invalid cpu. */
+    KCPU_INVALID = 0,
+
+    /** @name K_ARCH_X86_16
+     * @{ */
+    KCPU_I8086,
+    KCPU_I8088,
+    KCPU_I80186,
+    KCPU_I80286,
+    KCPU_I386_16,
+    KCPU_I486_16,
+    KCPU_I486SX_16,
+    KCPU_I586_16,
+    KCPU_I686_16,
+    KCPU_P4_16,
+    KCPU_CORE2_16,
+    KCPU_K6_16,
+    KCPU_K7_16,
+    KCPU_K8_16,
+    KCPU_FIRST_X86_16 = KCPU_I8086,
+    KCPU_LAST_X86_16 = KCPU_K8_16,
+    /** @} */
+
+    /** @name K_ARCH_X86_32
+     * @{ */
+    KCPU_X86_32_BLEND,
+    KCPU_I386,
+    KCPU_I486,
+    KCPU_I486SX,
+    KCPU_I586,
+    KCPU_I686,
+    KCPU_P4,
+    KCPU_CORE2_32,
+    KCPU_K6,
+    KCPU_K7,
+    KCPU_K8_32,
+    KCPU_FIRST_X86_32 = KCPU_I386,
+    KCPU_LAST_X86_32 = KCPU_K8_32,
+    /** @} */
+
+    /** @name K_ARCH_AMD64
+     * @{ */
+    KCPU_AMD64_BLEND,
+    KCPU_K8,
+    KCPU_P4_64,
+    KCPU_CORE2,
+    KCPU_FIRST_AMD64 = KCPU_K8,
+    KCPU_LAST_AMD64 = KCPU_CORE2,
+    /** @} */
+
+    /** The end of the valid cpu values (exclusive). */
+    KCPU_END,
+    /** Hack to blow the type up to 32-bit. */
+    KCPU_32BIT_HACK = 0x7fffffff
+} KCPU;
+
+/** Pointer to a CPU type. */
+typedef KCPU *PKCPU;
+/** Pointer to a const CPU type. */
+typedef const KCPU *PCKCPU;
+
+/** @} */
+
+#endif
+
diff --git a/src/lib/kStuff/include/k/kDbg.h b/src/lib/kStuff/include/k/kDbg.h
new file mode 100644
index 0000000..07ee431
--- /dev/null
+++ b/src/lib/kStuff/include/k/kDbg.h
@@ -0,0 +1,243 @@
+/* $Id: kDbg.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kDbg - The Debug Info Reader.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kDbg_h___
+#define ___k_kDbg_h___
+
+#include <k/kDefs.h>
+#include <k/kTypes.h>
+#include <k/kRdr.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup grp_kDbg      Debug Info Reader
+ * @{
+ */
+
+/** @def KDBG_DECL
+ * Declares a kDbg function according to build context.
+ * @param type          The return type.
+ */
+#if defined(KDBG_BUILDING_DYNAMIC)
+# define KDBG_DECL(type)        K_DECL_EXPORT(type)
+#elif defined(KDBG_BUILT_DYNAMIC)
+# define KDBG_DECL(type)        K_DECL_IMPORT(type)
+#else
+# define KDBG_DECL(type)        type
+#endif
+
+
+/** The kDbg address type. */
+typedef KU64                    KDBGADDR;
+/** Pointer to a kDbg address. */
+typedef KDBGADDR               *PKDBGADDR;
+/** Pointer to a const kDbg address. */
+typedef const KDBGADDR         *PCKDBGADDR;
+/** @def KDBGADDR_PRI
+ * printf format type. */
+#define KDBGADDR_PRI            KX64_PRI
+/** @def KDBGADDR_MAX
+ * Max kDbg address value. */
+#define KDBGADDR_MAX            KU64_C(0xfffffffffffffffe)
+/** @def KDBGADDR_C
+ * kDbg address constant.
+ * @param c         The constant value. */
+#define KDBGADDR_C(c)           KU64_C(c)
+/** NIL address. */
+#define NIL_KDBGADDR            KU64_MAX
+
+
+/** @name   Special Segments
+ * @{ */
+/** Relative Virtual Address.
+ * The specified offset is relative to the image base. The image base is the lowest memory
+ * address used by the image when loaded with the address assignments indicated in the image. */
+#define KDBGSEG_RVA             (-1)
+/** Absolute segment. The offset isn't relative to anything. */
+#define KDBGSEG_ABS             (-2)
+/** @} */
+
+
+/** The max filename path length used by the debug reader. */
+#define KDBG_PATH_MAX           260
+
+/**
+ * Line number details.
+ */
+typedef struct KDBGLINE
+{
+    /** The relative virtual address. */
+    KDBGADDR    RVA;
+    /** The offset into the segment. */
+    KDBGADDR    offSegment;
+    /** The segment number. */
+    KI32        iSegment;
+    /** The Line number. */
+    KU32        iLine;
+    /** The actual size of this structure. */
+    KU16        cbSelf;
+    /** The length of the filename. */
+    KU16        cchFile;
+    /** The name of the file this line number relates to. */
+    char        szFile[KDBG_PATH_MAX];
+} KDBGLINE;
+/** Pointer to line number details. */
+typedef KDBGLINE *PKDBGLINE;
+/** Pointer to const line number details. */
+typedef const KDBGLINE *PCKDBGLINE;
+/** Pointer to a pointer to line number details. */
+typedef PKDBGLINE *PPKDBGLINE;
+
+/**
+ * Duplicates a line number.
+ *
+ * To save heap space, the returned line number will not own more heap space
+ * than it strictly need to. So, it's not possible to append stuff to the symbol
+ * or anything of that kind.
+ *
+ * @returns Pointer to the duplicate.
+ *          This must be freed using RTDbgSymbolFree().
+ * @param   pLine       The line number to be duplicated.
+ */
+KDBG_DECL(PKDBGLINE) kDbgLineDup(PCKDBGLINE pLine);
+
+/**
+ * Frees a line number obtained from the RTDbg API.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns KERR_INVALID_POINTER if a NULL pointer or an !KDBG_VALID_PTR() is passed in.
+ *
+ * @param   pLine       The line number to be freed.
+ */
+KDBG_DECL(int) kDbgLineFree(PKDBGLINE pLine);
+
+
+/** @name Symbol Flags.
+ * @{ */
+/** The symbol is weak. */
+#define KDBGSYM_FLAGS_WEAK      KU32_C(0x00000000)
+/** The symbol is absolute.
+ * (This also indicated by the segment number.) */
+#define KDBGSYM_FLAGS_ABS       KU32_C(0x00000001)
+/** The symbol is exported. */
+#define KDBGSYM_FLAGS_EXPORTED  KU32_C(0x00000002)
+/** The symbol is a function/method/procedure/whatever-executable-code. */
+#define KDBGSYM_FLAGS_CODE      KU32_C(0x00000004)
+/** The symbol is some kind of data. */
+#define KDBGSYM_FLAGS_DATA      KU32_C(0x00000008)
+/** @} */
+
+/** The max symbol name length used by the debug reader. */
+#define KDBG_SYMBOL_MAX         384
+
+/**
+ * Symbol details.
+ */
+typedef struct KDBGSYMBOL
+{
+    /** The adddress of this symbol in the relevant space.
+     * This is NIL_KDBGADDR unless the information was
+     * returned by a kDbgSpace API. */
+    KDBGADDR    Address;
+    /** The relative virtual address. */
+    KDBGADDR    RVA;
+    /** The symbol size.
+     * This is not a reliable field, it could be a bad guess. Ignore if zero. */
+    KDBGADDR    cb;
+    /** The offset into the segment. */
+    KDBGADDR    offSegment;
+    /** The segment number. */
+    KI32        iSegment;
+    /** The symbol flags. */
+    KU32        fFlags;
+/** @todo type info. */
+    /** The actual size of this structure. */
+    KU16        cbSelf;
+    /** The length of the symbol name. */
+    KU16        cchName;
+    /** The symbol name. */
+    char        szName[KDBG_SYMBOL_MAX];
+} KDBGSYMBOL;
+/** Pointer to symbol details. */
+typedef KDBGSYMBOL *PKDBGSYMBOL;
+/** Pointer to const symbol details. */
+typedef const KDBGSYMBOL *PCKDBGSYMBOL;
+/** Pointer to a pointer to symbol details. */
+typedef PKDBGSYMBOL *PPKDBGSYMBOL;
+
+/**
+ * Duplicates a symbol.
+ *
+ * To save heap space, the returned symbol will not own more heap space than
+ * it strictly need to. So, it's not possible to append stuff to the symbol
+ * or anything of that kind.
+ *
+ * @returns Pointer to the duplicate.
+ *          This must be freed using kDbgSymbolFree().
+ * @param   pSymbol     The symbol to be freed.
+ */
+KDBG_DECL(PKDBGSYMBOL) kDbgSymbolDup(PCKDBGSYMBOL pSymbol);
+
+/**
+ * Frees a symbol obtained from the kDbg API.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns KERR_INVALID_POINTER if a NULL pointer or an !KDBG_VALID_PTR() is passed in.
+ *
+ * @param   pSymbol     The symbol to be freed.
+ */
+KDBG_DECL(int) kDbgSymbolFree(PKDBGSYMBOL pSymbol);
+
+
+/** Pointer to a debug module. */
+typedef struct KDBGMOD *PKDBGMOD;
+/** Pointer to a debug module pointer. */
+typedef PKDBGMOD *PPKDBGMOD;
+
+
+KDBG_DECL(int) kDbgModuleOpen(PPKDBGMOD ppDbgMod, const char *pszFilename, struct KLDRMOD *pLdrMod);
+KDBG_DECL(int) kDbgModuleOpenFile(PPKDBGMOD ppDbgMod, PKRDR pRdr, struct KLDRMOD *pLdrMod);
+KDBG_DECL(int) kDbgModuleOpenFilePart(PPKDBGMOD ppDbgMod, PKRDR pRdr, KFOFF off, KFOFF cb, struct KLDRMOD *pLdrMod);
+KDBG_DECL(int) kDbgModuleClose(PKDBGMOD pMod);
+KDBG_DECL(int) kDbgModuleQuerySymbol(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PKDBGSYMBOL pSym);
+KDBG_DECL(int) kDbgModuleQuerySymbolA(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PPKDBGSYMBOL ppSym);
+KDBG_DECL(int) kDbgModuleQueryLine(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PKDBGLINE pLine);
+KDBG_DECL(int) kDbgModuleQueryLineA(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PPKDBGLINE ppLine);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/kStuff/include/k/kDbgAll.h b/src/lib/kStuff/include/k/kDbgAll.h
new file mode 100644
index 0000000..fde7c0f
--- /dev/null
+++ b/src/lib/kStuff/include/k/kDbgAll.h
@@ -0,0 +1,168 @@
+/* $Id: kDbgAll.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kDbg - The Debug Info Read, All Details and Dependencies Included.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kDbgAll_h___
+#define ___k_kDbgAll_h___
+
+#include <k/kDefs.h>
+#include <k/kTypes.h>
+#include <k/kRdr.h>
+#include <k/kLdr.h>
+#include <k/kDbg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup grp_kDbgAll   All
+ * @addtogroup grp_kDbg
+ * @{
+ */
+
+/**
+ * The debug module method table.
+ */
+typedef struct KDBGMODOPS
+{
+    /** The name of the reader. */
+    const char *pszName;
+
+    /** Pointer to the next debug module readers.
+     * This is only used for dynamically registered readers. */
+    struct KDBGMODOPS  *pNext;
+
+    /**
+     * Tries to open the module.
+     *
+     * @returns 0 on success, KDBG_ERR on failure.
+     * @param   ppMod           Where to store the module that's been opened.
+     * @param   pRdr            The file provider.
+     * @param   fCloseRdrs       Whether the reader should be closed or not when the module is destroyed.
+     * @param   off             The file offset of the debug info. This is 0 if there isn't
+     *                          any specfic debug info section and the reader should start
+     *                          looking for debug info at the start of the file.
+     * @param   cb              The size of the debug info in the file. INT64_MAX if we don't
+     *                          know or there isn't any particular debug info section in the file.
+     * @param   pLdrMod         The associated loader module. This can be NULL.
+     */
+    int (*pfnOpen)(PKDBGMOD *ppMod, PKRDR pRdr, KBOOL fCloseRdr, KFOFF off, KFOFF cb, struct KLDRMOD *pLdrMod);
+
+    /**
+     * Closes the module.
+     *
+     * This should free all resources associated with the module
+     * except the pMod which is freed by the caller.
+     *
+     * @returns IPRT status code.
+     * @param   pMod        The module.
+     */
+    int (*pfnClose)(PKDBGMOD pMod);
+
+    /**
+     * Gets a symbol by segment:offset.
+     * This will be approximated to the nearest symbol if there is no exact match.
+     *
+     * @returns 0 on success. KLDR_ERR_* on failure.
+     * @param   pMod        The module.
+     * @param   iSegment    The segment this offset is relative to.
+     *                      The -1 segment is special, it means that the addres is relative to
+     *                      the image base. The image base is where the first bit of the image
+     *                      is mapped during load.
+     * @param   off         The offset into the segment.
+     * @param   pSym        Where to store the symbol details.
+     */
+    int (*pfnQuerySymbol)(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PKDBGSYMBOL pSym);
+
+    /**
+     * Gets a line number entry by segment:offset.
+     * This will be approximated to the nearest line number there is no exact match.
+     *
+     * @returns 0 on success. KLDR_ERR_* on failure.
+     * @param   pMod        The module.
+     * @param   iSegment    The segment this offset is relative to.
+     *                      The -1 segment is special, it means that the addres is relative to
+     *                      the image base. The image base is where the first bit of the image
+     *                      is mapped during load.
+     * @param   off         The offset into the segment.
+     * @param   pLine       Where to store the line number details.
+     */
+    int (*pfnQueryLine)(PKDBGMOD pMod, KI32 iSegment, KDBGADDR uOffset, PKDBGLINE pLine);
+
+    /** This is just to make sure you've initialized all the fields.
+     * Must be identical to pszName. */
+    const char *pszName2;
+} KDBGMODOPS;
+/** Pointer to a module method table. */
+typedef KDBGMODOPS *PKDBGMODOPS;
+/** Pointer to a const module method table. */
+typedef const KDBGMODOPS *PCKDBGMODOPS;
+
+/**
+ * Register a debug module reader with the kDbgModule component.
+ *
+ * Dynamically registered readers are kept in FIFO order, and external
+ * readers will be tried after the builtin ones.
+ *
+ * @returns 0 on success.
+ * @returns KERR_INVALID_POINTER if pOps is missing bits.
+ * @returns KERR_INVALID_PARAMETER if pOps is already in the list.
+ * @param   pOps        The reader method table, kDbg takes owner ship of
+ *                      this. This must be writeable as the pNext pointer
+ *                      will be update. It must also stick around for as
+ *                      long as kDbg is in use.
+ */
+KDBG_DECL(int) kDbgModuleRegisterReader(PKDBGMODOPS pOps);
+
+
+
+/**
+ * Internal representation of a debug module.
+ */
+typedef struct KDBGMOD
+{
+    /** Magic value (KDBGMOD_MAGIC). */
+    KI32            u32Magic;
+    /** Pointer to the method table. */
+    PCKDBGMODOPS    pOps;
+    /** The file provider for the file containing the debug info. */
+    PKRDR           pRdr;
+    /** Whether or not to close pRdr. */
+    KBOOL           fCloseRdr;
+    /** The associated kLdr module. This may be NULL. */
+    PKLDRMOD        pLdrMod;
+} KDBGMOD;
+
+/** @}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/kStuff/include/k/kDbgBase.h b/src/lib/kStuff/include/k/kDbgBase.h
new file mode 100644
index 0000000..5ae31fb
--- /dev/null
+++ b/src/lib/kStuff/include/k/kDbgBase.h
@@ -0,0 +1,248 @@
+/* $Id: kDbgBase.h 40 2010-02-02 16:02:15Z bird $ */
+/** @file
+ * kDbg - The Debug Info Reader, Base Definitions and Typedefs.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___kDbgBase_h___
+#define ___kDbgBase_h___
+
+#include <k/kDefs.h>
+#include <k/kTypes.h>
+
+
+/** @defgroup grp_kDbgBase  kDbgBase - Base Definitions And Typedefs
+ * @{ */
+
+/*
+ * kDbg depend on size_t, [u]intNN_t, [u]intptr_t and some related constants.
+ * If KDBG_ALREADY_INCLUDED_STD_TYPES or KCOMMON_ALREADY_INCLUDED_STD_TYPES
+ * is defined, these has already been defined.
+ */
+#if !defined(KDBG_ALREADY_INCLUDED_STD_TYPES) && !defined(KCOMMON_ALREADY_INCLUDED_STD_TYPES)
+# define KCOMMON_ALREADY_INCLUDED_STD_TYPES 1
+# include <sys/types.h>
+# include <stddef.h>
+# ifdef _MSC_VER
+   typedef signed char          int8_t;
+   typedef unsigned char        uint8_t;
+   typedef signed short         int16_t;
+   typedef unsigned short       uint16_t;
+   typedef signed int           int32_t;
+   typedef unsigned int         uint32_t;
+   typedef signed __int64       int64_t;
+   typedef unsigned __int64     uint64_t;
+   typedef int64_t              intmax_t;
+   typedef uint64_t             uintmax_t;
+#  define UINT8_C(c)            (c)
+#  define UINT16_C(c)           (c)
+#  define UINT32_C(c)           (c ## U)
+#  define UINT64_C(c)           (c ## ULL)
+#  define INT8_C(c)             (c)
+#  define INT16_C(c)            (c)
+#  define INT32_C(c)            (c)
+#  define INT64_C(c)            (c ## LL)
+#  define INT8_MIN              (INT8_C(-0x7f) - 1)
+#  define INT16_MIN             (INT16_C(-0x7fff) - 1)
+#  define INT32_MIN             (INT32_C(-0x7fffffff) - 1)
+#  define INT64_MIN             (INT64_C(-0x7fffffffffffffff) - 1)
+#  define INT8_MAX              INT8_C(0x7f)
+#  define INT16_MAX             INT16_C(0x7fff)
+#  define INT32_MAX             INT32_C(0x7fffffff)
+#  define INT64_MAX             INT64_C(0x7fffffffffffffff)
+#  define UINT8_MAX             UINT8_C(0xff)
+#  define UINT16_MAX            UINT16_C(0xffff)
+#  define UINT32_MAX            UINT32_C(0xffffffff)
+#  define UINT64_MAX            UINT64_C(0xffffffffffffffff)
+# else
+#  include <stdint.h>
+# endif
+#endif /* !KDBG_ALREADY_INCLUDED_STD_TYPES && !KCOMMON_ALREADY_INCLUDED_STD_TYPES */
+
+
+/** @def KDBG_CALL
+ * The calling convention used by the kDbg functions. */
+#if defined(_MSC_VER) || defined(__OS2__)
+# define KDBG_CALL  __cdecl
+#else
+# define KDBG_CALL
+#endif
+
+#ifdef DOXYGEN_RUNNING
+/** @def KDBG_BUILDING
+ * Define KDBG_BUILDING to indicate that kDbg is being built.
+ */
+# define KDBG_BUILDING
+/** @def KDBG_RESIDES_IN_DLL
+ * Define KDBG_RESIDES_IN_DLL to indicate that kDbg resides in a DLL.
+ */
+# define KDBG_RESIDES_IN_DLL
+#endif
+
+/** @def KDBG_DECL
+ * Macro for defining public functions. */
+#if defined(KDBG_RESIDES_IN_DLL) \
+ && (defined(_MSC_VER) || defined(__OS2__))
+# ifdef KDBG_BUILDING
+#  define KDBG_DECL(type) __declspec(dllexport) type
+# else
+#  define KDBG_DECL(type) __declspec(dllimport) type
+# endif
+#else
+# define KDBG_DECL(type) type
+#endif
+
+/** @def KDBG_INLINE
+ * Macro for defining an inline function. */
+#ifdef __cplusplus
+# if defined(__GNUC__)
+#  define KDBG_INLINE(type) static inline type
+# else
+#  define KDBG_INLINE(type) inline type
+# endif
+#else
+# if defined(__GNUC__)
+#  define KDBG_INLINE(type) static __inline__ type
+# elif defined(_MSC_VER)
+#  define KDBG_INLINE(type) _inline type
+# else
+#  error "Port me"
+# endif
+#endif
+
+
+/** The kDbg address type. */
+typedef uint64_t KDBGADDR;
+/** Pointer to a kLdr address. */
+typedef KDBGADDR *PKDBGADDR;
+/** Pointer to a const kLdr address. */
+typedef const KDBGADDR *PCKDBGADDR;
+
+/** NIL address. */
+#define NIL_KDBGADDR    (~(uint64_t)0)
+
+/** @def PRI_KDBGADDR
+ * printf format type. */
+#ifdef _MSC_VER
+# define PRI_KDBGADDR    "I64x"
+#else
+# define PRI_KDBGADDR    "llx"
+#endif
+
+
+/** Get the minimum of two values. */
+#define KDBG_MIN(a, b)              ((a) <= (b) ? (a) : (b))
+/** Get the maximum of two values. */
+#define KDBG_MAX(a, b)              ((a) >= (b) ? (a) : (b))
+/** Calculate the offset of a structure member. */
+#define KDBG_OFFSETOF(strct, memb)  ( (size_t)( &((strct *)0)->memb ) )
+/** Align a size_t value. */
+#define KDBG_ALIGN_Z(val, align)    ( ((val) + ((align) - 1)) & ~(size_t)((align) - 1) )
+/** Align a void * value. */
+#define KDBG_ALIGN_P(pv, align)     ( (void *)( ((uintptr_t)(pv) + ((align) - 1)) & ~(uintptr_t)((align) - 1) ) )
+/** Align a size_t value. */
+#define KDBG_ALIGN_ADDR(val, align) ( ((val) + ((align) - 1)) & ~(KDBGADDR)((align) - 1) )
+/** Number of elements in an array. */
+#define KDBG_ELEMENTS(a)            ( sizeof(a) / sizeof((a)[0]) )
+/** @def KDBG_VALID_PTR
+ * Checks if the specified pointer is a valid address or not. */
+#define KDBG_VALID_PTR(ptr)         ( (uintptr_t)(ptr) + 0x1000U >= 0x2000U )
+
+
+/** @def KDBG_LITTLE_ENDIAN
+ * The kDbg build is for a little endian target. */
+/** @def KDBG_BIG_ENDIAN
+ * The kDbg build is for a big endian target. */
+#if !defined(KDBG_LITTLE_ENDIAN) && !defined(KDBG_BIG_ENDIAN)
+# define KDBG_LITTLE_ENDIAN
+#endif
+#ifdef DOXYGEN_RUNNING
+# define KDBG_BIG_ENDIAN
+#endif
+
+
+/** @name Endian Conversion
+ * @{ */
+
+/** @def KDBG_E2E_U16
+ * Convert the endian of an unsigned 16-bit value. */
+# define KDBG_E2E_U16(u16)      ( (uint16_t) (((u16) >> 8) | ((u16) << 8)) )
+/** @def KDBG_E2E_U32
+ * Convert the endian of an unsigned 32-bit value. */
+# define KDBG_E2E_U32(u32)      (   ( ((u32) & UINT32_C(0xff000000)) >> 24 ) \
+                                  | ( ((u32) & UINT32_C(0x00ff0000)) >>  8 ) \
+                                  | ( ((u32) & UINT32_C(0x0000ff00)) <<  8 ) \
+                                  | ( ((u32) & UINT32_C(0x000000ff)) << 24 ) \
+                                )
+/** @def KDBG_E2E_U64
+ * Convert the endian of an unsigned 64-bit value. */
+# define KDBG_E2E_U64(u64)      (   ( ((u64) & UINT64_C(0xff00000000000000)) >> 56 ) \
+                                  | ( ((u64) & UINT64_C(0x00ff000000000000)) >> 40 ) \
+                                  | ( ((u64) & UINT64_C(0x0000ff0000000000)) >> 24 ) \
+                                  | ( ((u64) & UINT64_C(0x000000ff00000000)) >>  8 ) \
+                                  | ( ((u64) & UINT64_C(0x00000000ff000000)) <<  8 ) \
+                                  | ( ((u64) & UINT64_C(0x0000000000ff0000)) << 24 ) \
+                                  | ( ((u64) & UINT64_C(0x000000000000ff00)) << 40 ) \
+                                  | ( ((u64) & UINT64_C(0x00000000000000ff)) << 56 ) \
+                                )
+
+/** @def KDBG_LE2H_U16
+ * Unsigned 16-bit little-endian to host endian. */
+/** @def KDBG_LE2H_U32
+ * Unsigned 32-bit little-endian to host endian. */
+/** @def KDBG_LE2H_U64
+ * Unsigned 64-bit little-endian to host endian. */
+/** @def KDBG_BE2H_U16
+ * Unsigned 16-bit big-endian to host endian. */
+/** @def KDBG_BE2H_U32
+ * Unsigned 32-bit big-endian to host endian. */
+/** @def KDBG_BE2H_U64
+ * Unsigned 64-bit big-endian to host endian. */
+#ifdef KDBG_LITTLE_ENDIAN
+# define KDBG_LE2H_U16(u16)  ((uint16_t)(u16))
+# define KDBG_LE2H_U32(u32)  ((uint32_t)(u32))
+# define KDBG_LE2H_U64(u64)  ((uint32_t)(u32))
+# define KDBG_BE2H_U16(u16)  KDBG_E2E_U16(u16)
+# define KDBG_BE2H_U32(u32)  KDBG_E2E_U32(u32)
+# define KDBG_BE2H_U64(u64)  KDBG_E2E_U64(u64)
+#elif defined(KDBG_BIG_ENDIAN)
+# define KDBG_LE2H_U16(u16)  KDBG_E2E_U16(u16)
+# define KDBG_LE2H_U32(u32)  KDBG_E2E_U32(u32)
+# define KDBG_LE2H_U32(u64)  KDBG_E2E_U64(u64)
+# define KDBG_BE2H_U16(u16)  ((uint16_t)(u16))
+# define KDBG_BE2H_U32(u32)  ((uint32_t)(u32))
+# define KDBG_BE2H_U64(u64)  ((uint32_t)(u32))
+#else
+# error "KDBG_BIG_ENDIAN or KDBG_LITTLE_ENDIAN is supposed to be defined."
+#endif
+
+/** @} */
+
+/** @} */
+
+#endif
+
diff --git a/src/lib/k/kDefs.h b/src/lib/kStuff/include/k/kDefs.h
similarity index 88%
rename from src/lib/k/kDefs.h
rename to src/lib/kStuff/include/k/kDefs.h
index b67886f..f805cc3 100644
--- a/src/lib/k/kDefs.h
+++ b/src/lib/kStuff/include/k/kDefs.h
@@ -1,27 +1,31 @@
-/* $Id: kDefs.h 15 2008-05-05 22:14:33Z bird $ */
+/* $Id: kDefs.h 84 2016-09-04 13:54:11Z bird $ */
 /** @file
- *
  * kTypes - Defines and Macros.
+ */
+
+/*
+ * Copyright (c) 2006-2008 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
  *
- * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
- *
- *
- * This file is part of k*.
- *
- * k* 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.
- *
- * k* 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.
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with k*; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
  *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  */
 
 #ifndef ___k_kDefs_h___
@@ -42,24 +46,22 @@
 #define K_OS_DRAGONFLY  2
 /** FreeBSD. */
 #define K_OS_FREEBSD    3
-/** Haiku. */
-#define K_OS_HAIKU      4
 /** Linux. */
-#define K_OS_LINUX      5
+#define K_OS_LINUX      4
 /** NetBSD. */
-#define K_OS_NETBSD     6
+#define K_OS_NETBSD     5
 /** NT (native). */
-#define K_OS_NT         7
+#define K_OS_NT         6
 /** OpenBSD*/
-#define K_OS_OPENBSD    8
+#define K_OS_OPENBSD    7
 /** OS/2 */
-#define K_OS_OS2        9
+#define K_OS_OS2        8
 /** Solaris */
-#define K_OS_SOLARIS    10
+#define K_OS_SOLARIS    9
 /** Windows. */
-#define K_OS_WINDOWS    11
+#define K_OS_WINDOWS    10
 /** The max K_OS_* value (exclusive). */
-#define K_OS_MAX        12
+#define K_OS_MAX        11
 /** @} */
 
 /** @def K_OS
@@ -80,8 +82,6 @@
 #  define K_OS      K_OS_DRAGONFLY
 # elif defined(__FreeBSD__) /*??*/
 #  define K_OS      K_OS_FREEBSD
-# elif defined(__HAIKU__)
-#  define K_OS      K_OS_HAIKU
 # elif defined(__gnu_linux__)
 #  define K_OS      K_OS_LINUX
 # elif defined(__NetBSD__) /*??*/
@@ -293,12 +293,12 @@
 /** @def K_ENDIAN
  * The value of this \#define indicates the target endianness.
  *
- * @remark  It's necessary to define this (or add the necessary dection here)
+ * @remark  It's necessary to define this (or add the necessary deduction here)
  *          on bi-endian architectures.
  */
 #ifndef K_ENDIAN
   /* use K_ARCH if possible. */
-# if K_ARCH_END != K_ENDIAN_BI
+# if K_ARCH_ENDIAN != K_ENDIAN_BI
 #  define K_ENDIAN K_ARCH_ENDIAN
 # else
 #  error "Port Me or define K_ENDIAN."
@@ -364,34 +364,6 @@
 # define K_BE2H_U64(u64)        ((KU64)(u32))
 #endif
 
-/** @def K_H2LE_U16
- * Unsigned 16-bit host endian to little-endian.. */
-/** @def K_H2LE_U32
- * Unsigned 32-bit host endian to little-endian.. */
-/** @def K_H2LE_U64
- * Unsigned 64-bit host endian to little-endian.. */
-/** @def K_H2BE_U16
- * Unsigned 16-bit host endian to big-endian.. */
-/** @def K_H2BE_U32
- * Unsigned 32-bit host endian to big-endian.. */
-/** @def K_H2BE_U64
- * Unsigned 64-bit host endian to big-endian.. */
-#if K_ENDIAN == K_ENDIAN_LITTLE
-# define K_H2LE_U16(u16)        ((KU16)(u16))
-# define K_H2LE_U32(u32)        ((KU32)(u32))
-# define K_H2LE_U64(u64)        ((KU64)(u32))
-# define K_H2BE_U16(u16)        K_E2E_U16(u16)
-# define K_H2BE_U32(u32)        K_E2E_U32(u32)
-# define K_H2BE_U64(u64)        K_E2E_U64(u64)
-#else
-# define K_H2LE_U16(u16)        K_E2E_U16(u16)
-# define K_H2LE_U32(u32)        K_E2E_U32(u32)
-# define K_H2LE_U64(u64)        K_E2E_U64(u64)
-# define K_H2BE_U16(u16)        ((KU16)(u16))
-# define K_H2BE_U32(u32)        ((KU32)(u32))
-# define K_H2BE_U64(u64)        ((KU64)(u32))
-#endif
-
 
 
 /** @def K_INLINE
@@ -408,7 +380,7 @@
 # if defined(__GNUC__)
 #  define K_INLINE              static __inline__
 # elif defined(_MSC_VER)
-#  define K_INLINE              static _Inline
+#  define K_INLINE              static __inline
 # else
 #  error "Port Me"
 # endif
diff --git a/src/lib/kStuff/include/k/kErr.h b/src/lib/kStuff/include/k/kErr.h
new file mode 100644
index 0000000..f183ef4
--- /dev/null
+++ b/src/lib/kStuff/include/k/kErr.h
@@ -0,0 +1,68 @@
+/* $Id: kErr.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kErr - Status Code API.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kErr_h___
+#define ___k_kErr_h___
+
+/** @defgroup   grp_kErr        kErr - Status Code API
+ * @{
+ */
+
+/** @def KERR_DECL
+ * Declares a kRdr function according to build context.
+ * @param type          The return type.
+ */
+#if defined(KERR_BUILDING_DYNAMIC)
+# define KERR_DECL(type)    K_DECL_EXPORT(type)
+#elif defined(KRDR_BUILT_DYNAMIC)
+# define KERR_DECL(type)    K_DECL_IMPORT(type)
+#else
+# define KERR_DECL(type)    type
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+KERR_DECL(const char *) kErrName(int rc);
+KERR_DECL(int)  kErrFromErrno(int);
+KERR_DECL(int)  kErrFromOS2(unsigned long rcOs2);
+KERR_DECL(int)  kErrFromNtStatus(long rcNtStatus);
+KERR_DECL(int)  kErrFromMach(int rcMach);
+KERR_DECL(int)  kErrFromDarwin(int rcDarwin);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif
+
diff --git a/src/lib/kStuff/include/k/kErrors.h b/src/lib/kStuff/include/k/kErrors.h
new file mode 100644
index 0000000..be179ce
--- /dev/null
+++ b/src/lib/kStuff/include/k/kErrors.h
@@ -0,0 +1,327 @@
+/* $Id: kErrors.h 58 2013-10-12 20:18:21Z bird $ */
+/** @file
+ * kErrors - Status Codes.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kErrors_h___
+#define ___k_kErrors_h___
+
+/** @defgroup grp_kErrors   Status Codes.
+ * @{
+ */
+/** The base of the kErrors status codes. */
+#define KERR_BASE                                       42000
+
+/** @name General
+ * @{
+ */
+/** The base of the general status codes. */
+#define KERR_GENERAL_BASE                               (KERR_BASE)
+/** Generic error. */
+#define KERR_GENERAL_FAILURE                            (KERR_GENERAL_BASE + 1)
+/** Out of memory. */
+#define KERR_NO_MEMORY                                  (KERR_GENERAL_BASE + 2)
+/** Hit some unimplemented functionality - feel free to implement it :-) . */
+#define KERR_NOT_IMPLEMENTED                            (KERR_GENERAL_BASE + 3)
+/** An environment variable wasn't found. */
+#define KERR_ENVVAR_NOT_FOUND                           (KERR_GENERAL_BASE + 4)
+/** Buffer overflow. */
+#define KERR_BUFFER_OVERFLOW                            (KERR_GENERAL_BASE + 5)
+/** @}*/
+
+/** @name Input Validation
+ * @{
+ */
+/** The base of the input validation status codes. */
+#define KERR_INPUT_BASE                                 (KERR_GENERAL_BASE + 6)
+/** An API was given an invalid parameter. */
+#define KERR_INVALID_PARAMETER                          (KERR_INPUT_BASE + 0)
+/** A pointer argument is not valid. */
+#define KERR_INVALID_POINTER                            (KERR_INPUT_BASE + 1)
+/** A handle argument is not valid. */
+#define KERR_INVALID_HANDLE                             (KERR_INPUT_BASE + 2)
+/** An offset argument is not valid. */
+#define KERR_INVALID_OFFSET                             (KERR_INPUT_BASE + 3)
+/** A size argument is not valid. */
+#define KERR_INVALID_SIZE                               (KERR_INPUT_BASE + 4)
+/** A range argument is not valid. */
+#define KERR_INVALID_RANGE                              (KERR_INPUT_BASE + 5)
+/** A parameter is out of range. */
+#define KERR_OUT_OF_RANGE                               (KERR_INPUT_BASE + 6)
+/** @} */
+
+/** @name File System and I/O
+ * @{
+ */
+/** The base of the file system and I/O status cdoes. */
+#define KERR_FILE_SYSTEM_AND_IO_BASE                    (KERR_INPUT_BASE + 7)
+/** The specified file was not found. */
+#define KERR_FILE_NOT_FOUND                             (KERR_FILE_SYSTEM_AND_IO_BASE + 0)
+/** End of file. */
+#define KERR_EOF                                        (KERR_FILE_SYSTEM_AND_IO_BASE + 1)
+/** @} */
+
+/** @name   kDbg Specific
+ * @{
+ */
+/** The base of the kDbg specific status codes. */
+#define KDBG_ERR_BASE                                   (KERR_FILE_SYSTEM_AND_IO_BASE + 2)
+/** The (module) format isn't known to use. */
+#define KDBG_ERR_UNKOWN_FORMAT                          (KDBG_ERR_BASE + 0)
+/** The (module) format isn't supported by this kDbg build. */
+#define KDBG_ERR_FORMAT_NOT_SUPPORTED                   (KDBG_ERR_BASE + 1)
+/** The (module) format isn't supported by this kDbg build. */
+#define KDBG_ERR_BAD_EXE_FORMAT                         (KDBG_ERR_BASE + 2)
+/** A specified address or an address found in the debug info is invalid. */
+#define KDBG_ERR_INVALID_ADDRESS                        (KDBG_ERR_BASE + 3)
+/** The dbghelp.dll is too old or something like that. */
+#define KDBG_ERR_DBGHLP_VERSION_MISMATCH                (KDBG_ERR_BASE + 4)
+/** @} */
+
+/** @name   kRdr Specific
+ * @{
+ */
+/** the base of the kRdr specific status codes. */
+#define KRDR_ERR_BASE                                   (KDBG_ERR_BASE + 5)
+/** The file reader can't take more concurrent mappings. */
+#define KRDR_ERR_TOO_MANY_MAPPINGS                      (KRDR_ERR_BASE + 0)
+/** The pRdr instance passed to a kRdrBuf* API isn't a buffered instance. */
+#define KRDR_ERR_NOT_BUFFERED_RDR                       (KRDR_ERR_BASE + 1)
+/** The line is too long to fit in the buffer passed to kRdrBufLine or kRdrBufLineEx. */
+#define KRDR_ERR_LINE_TOO_LONG                          (KRDR_ERR_BASE + 2)
+/** @} */
+
+/** @name   kLdr Specific
+ * @{
+ */
+/** The base of the kLdr specific status codes. */
+#define KLDR_ERR_BASE                                   (KRDR_ERR_BASE + 3)
+
+/** The image format is unknown. */
+#define KLDR_ERR_UNKNOWN_FORMAT                         (KLDR_ERR_BASE + 0)
+/** The MZ image format isn't supported by this kLdr build. */
+#define KLDR_ERR_MZ_NOT_SUPPORTED                       (KLDR_ERR_BASE + 1)
+/** The NE image format isn't supported by this kLdr build. */
+#define KLDR_ERR_NE_NOT_SUPPORTED                       (KLDR_ERR_BASE + 2)
+/** The LX image format isn't supported by this kLdr build. */
+#define KLDR_ERR_LX_NOT_SUPPORTED                       (KLDR_ERR_BASE + 3)
+/** The LE image format isn't supported by this kLdr build. */
+#define KLDR_ERR_LE_NOT_SUPPORTED                       (KLDR_ERR_BASE + 4)
+/** The PE image format isn't supported by this kLdr build. */
+#define KLDR_ERR_PE_NOT_SUPPORTED                       (KLDR_ERR_BASE + 5)
+/** The ELF image format isn't supported by this kLdr build. */
+#define KLDR_ERR_ELF_NOT_SUPPORTED                      (KLDR_ERR_BASE + 6)
+/** The mach-o image format isn't supported by this kLdr build. */
+#define KLDR_ERR_MACHO_NOT_SUPPORTED                    (KLDR_ERR_BASE + 7)
+/** The FAT image format isn't supported by this kLdr build or
+ * a direct open was attempt without going thru the FAT file provider.
+ * FAT images are also known as Universal Binaries. */
+#define KLDR_ERR_FAT_NOT_SUPPORTED                      (KLDR_ERR_BASE + 8)
+/** The a.out image format isn't supported by this kLdr build. */
+#define KLDR_ERR_AOUT_NOT_SUPPORTED                     (KLDR_ERR_BASE + 9)
+
+/** The module wasn't loaded dynamically. */
+#define KLDR_ERR_NOT_LOADED_DYNAMICALLY                 (KLDR_ERR_BASE + 10)
+/** The module wasn't found. */
+#define KLDR_ERR_MODULE_NOT_FOUND                       (KLDR_ERR_BASE + 11)
+/** A prerequisit module wasn't found. */
+#define KLDR_ERR_PREREQUISITE_MODULE_NOT_FOUND          (KLDR_ERR_BASE + 12)
+/** The module is being terminated and can therefore not be loaded. */
+#define KLDR_ERR_MODULE_TERMINATING                     (KLDR_ERR_BASE + 13)
+/** A prerequisit module is being terminated and can therefore not be loaded. */
+#define KLDR_ERR_PREREQUISITE_MODULE_TERMINATING        (KLDR_ERR_BASE + 14)
+/** The module initialization failed. */
+#define KLDR_ERR_MODULE_INIT_FAILED                     (KLDR_ERR_BASE + 15)
+/** The initialization of a prerequisite module failed. */
+#define KLDR_ERR_PREREQUISITE_MODULE_INIT_FAILED        (KLDR_ERR_BASE + 16)
+/** The module has already failed initialization and can't be attempted reloaded until
+ * after we've finished garbage collection. */
+#define KLDR_ERR_MODULE_INIT_FAILED_ALREADY             (KLDR_ERR_BASE + 17)
+/** A prerequisite module has already failed initialization and can't be attempted
+ * reloaded until after we've finished garbage collection. */
+#define KLDR_ERR_PREREQUISITE_MODULE_INIT_FAILED_ALREADY (KLDR_ERR_BASE + 18)
+/** Prerequisite recursed too deeply. */
+#define KLDR_ERR_PREREQUISITE_RECURSED_TOO_DEEPLY       (KLDR_ERR_BASE + 19)
+/** Failed to allocate the main stack. */
+#define KLDR_ERR_MAIN_STACK_ALLOC_FAILED                (KLDR_ERR_BASE + 20)
+/** Symbol not found. */
+#define KLDR_ERR_SYMBOL_NOT_FOUND                       (KLDR_ERR_BASE + 21)
+/** A forward symbol was encountered but the caller didn't provide any means to resolve it. */
+#define KLDR_ERR_FORWARDER_SYMBOL                       (KLDR_ERR_BASE + 22)
+/** Encountered a bad fixup. */
+#define KLDR_ERR_BAD_FIXUP                              (KLDR_ERR_BASE + 23)
+/** The import ordinal was out of bounds. */
+#define KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS           (KLDR_ERR_BASE + 24)
+/** A forwarder chain was too long. */
+#define KLDR_ERR_TOO_LONG_FORWARDER_CHAIN               (KLDR_ERR_BASE + 25)
+/** The module has no debug info. */
+#define KLDR_ERR_NO_DEBUG_INFO                          (KLDR_ERR_BASE + 26)
+/** The module is already mapped.
+ * kLdrModMap() can only be called once (without kLdrModUnmap() in between). */
+#define KLDR_ERR_ALREADY_MAPPED                         (KLDR_ERR_BASE + 27)
+/** The module was not mapped.
+ * kLdrModUnmap() should not called without being preceeded by a kLdrModMap(). */
+#define KLDR_ERR_NOT_MAPPED                             (KLDR_ERR_BASE + 28)
+/** Couldn't fit the address value into the field. Typically a relocation kind of error. */
+#define KLDR_ERR_ADDRESS_OVERFLOW                       (KLDR_ERR_BASE + 29)
+/** Couldn't fit a calculated size value into the native size type of the host. */
+#define KLDR_ERR_SIZE_OVERFLOW                          (KLDR_ERR_BASE + 30)
+/** Thread attach failed. */
+#define KLDR_ERR_THREAD_ATTACH_FAILED                   (KLDR_ERR_BASE + 31)
+/** The module wasn't a DLL or object file. */
+#define KLDR_ERR_NOT_DLL                                (KLDR_ERR_BASE + 32)
+/** The module wasn't an EXE. */
+#define KLDR_ERR_NOT_EXE                                (KLDR_ERR_BASE + 33)
+/** Not implemented yet. */
+#define KLDR_ERR_TODO                                   (KLDR_ERR_BASE + 34)
+/** No image matching the requested CPU. */
+#define KLDR_ERR_CPU_ARCH_MISMATCH                      (KLDR_ERR_BASE + 35)
+/** Invalid FAT image header. */
+#define KLDR_ERR_FAT_INVALID                            (KLDR_ERR_BASE + 36)
+/** Unsupported CPU subtype found in a FAT entry. */
+#define KLDR_ERR_FAT_UNSUPPORTED_CPU_SUBTYPE            (KLDR_ERR_BASE + 37)
+/** The image has no UUID. */
+#define KLDR_ERR_NO_IMAGE_UUID                          (KLDR_ERR_BASE + 38)
+/** Duplicate segment name. */
+#define KLDR_ERR_DUPLICATE_SEGMENT_NAME                 (KLDR_ERR_BASE + 39)
+/** @} */
+
+/** @name kLdrModPE Specific
+ * @{
+ */
+/** The base of the kLdrModPE specific status codes. */
+#define KLDR_ERR_PE_BASE                                (KLDR_ERR_BASE + 40)
+/** The machine isn't supported by the interpreter. */
+#define KLDR_ERR_PE_UNSUPPORTED_MACHINE                 (KLDR_ERR_PE_BASE + 0)
+/** The file handler isn't valid. */
+#define KLDR_ERR_PE_BAD_FILE_HEADER                     (KLDR_ERR_PE_BASE + 1)
+/** The the optional headers isn't valid. */
+#define KLDR_ERR_PE_BAD_OPTIONAL_HEADER                 (KLDR_ERR_PE_BASE + 2)
+/** One of the section headers aren't valid. */
+#define KLDR_ERR_PE_BAD_SECTION_HEADER                  (KLDR_ERR_PE_BASE + 3)
+/** Bad forwarder entry. */
+#define KLDR_ERR_PE_BAD_FORWARDER                       (KLDR_ERR_PE_BASE + 4)
+/** Forwarder module not found in the import descriptor table. */
+#define KLDR_ERR_PE_FORWARDER_IMPORT_NOT_FOUND          (KLDR_ERR_PE_BASE + 5)
+/** Bad PE fixups. */
+#define KLDR_ERR_PE_BAD_FIXUP                           (KLDR_ERR_PE_BASE + 6)
+/** Bad PE import (thunk). */
+#define KLDR_ERR_PE_BAD_IMPORT                          (KLDR_ERR_PE_BASE + 7)
+/** @} */
+
+/** @name kLdrModLX Specific
+ * @{
+ */
+/** The base of the kLdrModLX specific status codes. */
+#define KLDR_ERR_LX_BASE                                (KLDR_ERR_PE_BASE + 8)
+/** validation of LX header failed. */
+#define KLDR_ERR_LX_BAD_HEADER                          (KLDR_ERR_LX_BASE + 0)
+/** validation of the loader section (in the LX header) failed. */
+#define KLDR_ERR_LX_BAD_LOADER_SECTION                  (KLDR_ERR_LX_BASE + 1)
+/** validation of the fixup section (in the LX header) failed. */
+#define KLDR_ERR_LX_BAD_FIXUP_SECTION                   (KLDR_ERR_LX_BASE + 2)
+/** validation of the LX object table failed. */
+#define KLDR_ERR_LX_BAD_OBJECT_TABLE                    (KLDR_ERR_LX_BASE + 3)
+/** A bad page map entry was encountered. */
+#define KLDR_ERR_LX_BAD_PAGE_MAP                        (KLDR_ERR_LX_BASE + 4)
+/** Bad iterdata (EXEPACK) data. */
+#define KLDR_ERR_LX_BAD_ITERDATA                        (KLDR_ERR_LX_BASE + 5)
+/** Bad iterdata2 (EXEPACK2) data. */
+#define KLDR_ERR_LX_BAD_ITERDATA2                       (KLDR_ERR_LX_BASE + 6)
+/** Bad bundle data. */
+#define KLDR_ERR_LX_BAD_BUNDLE                          (KLDR_ERR_LX_BASE + 7)
+/** No soname. */
+#define KLDR_ERR_LX_NO_SONAME                           (KLDR_ERR_LX_BASE + 8)
+/** Bad soname. */
+#define KLDR_ERR_LX_BAD_SONAME                          (KLDR_ERR_LX_BASE + 9)
+/** Bad forwarder entry. */
+#define KLDR_ERR_LX_BAD_FORWARDER                       (KLDR_ERR_LX_BASE + 10)
+/** internal fixup chain isn't implemented yet. */
+#define KLDR_ERR_LX_NRICHAIN_NOT_SUPPORTED              (KLDR_ERR_LX_BASE + 11)
+/** @} */
+
+/** @name kLdrModMachO Specific
+ * @{
+ */
+/** The base of the kLdrModMachO specific status codes. */
+#define KLDR_ERR_MACHO_BASE                             (KLDR_ERR_LX_BASE + 12)
+/** Only native endian Mach-O files are supported. */
+#define KLDR_ERR_MACHO_OTHER_ENDIAN_NOT_SUPPORTED       (KLDR_ERR_MACHO_BASE + 0)
+/** The Mach-O header is bad or contains new and unsupported features. */
+#define KLDR_ERR_MACHO_BAD_HEADER                       (KLDR_ERR_MACHO_BASE + 1)
+/** The file type isn't supported. */
+#define KLDR_ERR_MACHO_UNSUPPORTED_FILE_TYPE            (KLDR_ERR_MACHO_BASE + 2)
+/** The machine (cputype / cpusubtype combination) isn't supported. */
+#define KLDR_ERR_MACHO_UNSUPPORTED_MACHINE              (KLDR_ERR_MACHO_BASE + 3)
+/** Bad load command(s). */
+#define KLDR_ERR_MACHO_BAD_LOAD_COMMAND                 (KLDR_ERR_MACHO_BASE + 4)
+/** Encountered an unknown load command.*/
+#define KLDR_ERR_MACHO_UNKNOWN_LOAD_COMMAND             (KLDR_ERR_MACHO_BASE + 5)
+/** Encountered a load command that's not implemented.*/
+#define KLDR_ERR_MACHO_UNSUPPORTED_LOAD_COMMAND         (KLDR_ERR_MACHO_BASE + 6)
+/** Bad section. */
+#define KLDR_ERR_MACHO_BAD_SECTION                      (KLDR_ERR_MACHO_BASE + 7)
+/** Encountered a section type that's not implemented.*/
+#define KLDR_ERR_MACHO_UNSUPPORTED_SECTION              (KLDR_ERR_MACHO_BASE + 8)
+/** Encountered a init function section.   */
+#define KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION         (KLDR_ERR_MACHO_BASE + 9)
+/** Encountered a term function section.   */
+#define KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION         (KLDR_ERR_MACHO_BASE + 10)
+/** Encountered a section type that's not known to the loader. (probably invalid) */
+#define KLDR_ERR_MACHO_UNKNOWN_SECTION                  (KLDR_ERR_MACHO_BASE + 11)
+/** The sections aren't ordered by segment as expected by the loader. */
+#define KLDR_ERR_MACHO_BAD_SECTION_ORDER                (KLDR_ERR_MACHO_BASE + 12)
+/** The image is 32-bit and contains 64-bit load commands or vise versa. */
+#define KLDR_ERR_MACHO_BIT_MIX                          (KLDR_ERR_MACHO_BASE + 13)
+/** Bad MH_OBJECT file. */
+#define KLDR_ERR_MACHO_BAD_OBJECT_FILE                  (KLDR_ERR_MACHO_BASE + 14)
+/** Bad symbol table entry. */
+#define KLDR_ERR_MACHO_BAD_SYMBOL                       (KLDR_ERR_MACHO_BASE + 15)
+/** Unsupported fixup type. */
+#define KLDR_ERR_MACHO_UNSUPPORTED_FIXUP_TYPE           (KLDR_ERR_MACHO_BASE + 16)
+/** Both debug and non-debug sections in segment. */
+#define KLDR_ERR_MACHO_MIXED_DEBUG_SECTION_FLAGS        (KLDR_ERR_MACHO_BASE + 17)
+/** The segment bits are non-contiguous in the file. */
+#define KLDR_ERR_MACHO_NON_CONT_SEG_BITS                (KLDR_ERR_MACHO_BASE + 18)
+/** @} */
+
+/** @name kCpu Specific
+ * @{
+ */
+/** The base of the kCpu specific status codes. */
+#define KCPU_ERR_BASE                                   (KLDR_ERR_MACHO_BASE + 19)
+/** The specified ARCH+CPU pairs aren't compatible. */
+#define KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE                (KCPU_ERR_BASE + 0)
+/** @} */
+
+/** End of the valid status codes. */
+#define KERR_END                                        (KCPU_ERR_BASE + 1)
+/** @}*/
+
+#endif
+
diff --git a/src/lib/kStuff/include/k/kHlp.h b/src/lib/kStuff/include/k/kHlp.h
new file mode 100644
index 0000000..7e83b85
--- /dev/null
+++ b/src/lib/kStuff/include/k/kHlp.h
@@ -0,0 +1,53 @@
+/* $Id: kHlp.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlp - Helpers, All Of Them.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kHlp_h___
+#define ___k_kHlp_h___
+
+#include <k/kDefs.h>
+#include <k/kTypes.h>
+#include <k/kErrors.h>
+#include <k/kHlpAlloc.h>
+#include <k/kHlpAssert.h>
+#include <k/kHlpEnv.h>
+#include <k/kHlpPath.h>
+#include <k/kHlpProcess.h>
+#include <k/kHlpSem.h>
+#include <k/kHlpString.h>
+#include <k/kHlpThread.h>
+
+/** @defgroup grp_kHlp  kHlp - Helper Functions
+ * @{ */
+
+/** @} */
+
+#endif
+
+
diff --git a/src/lib/kStuff/include/k/kHlpAlloc.h b/src/lib/kStuff/include/k/kHlpAlloc.h
new file mode 100644
index 0000000..99ae8b6
--- /dev/null
+++ b/src/lib/kStuff/include/k/kHlpAlloc.h
@@ -0,0 +1,78 @@
+/* $Id: kHlpAlloc.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpAlloc - Memory Allocation.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kHlpAlloc_h___
+#define ___k_kHlpAlloc_h___
+
+#include <k/kHlpDefs.h>
+#include <k/kTypes.h>
+
+/** @defgroup grp_kHlpAlloc kHlpAlloc - Memory Allocation
+ * @addtogroup grp_kHlp
+ * @{*/
+
+/** @def kHlpAllocA
+ * The alloca() wrapper. */
+#ifdef __GNUC__
+# define kHlpAllocA(a)      __builtin_alloca(a)
+#elif defined(_MSC_VER)
+# include <malloc.h>
+# define kHlpAllocA(a)      alloca(a)
+#else
+# error "Port Me."
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+KHLP_DECL(void *)   kHlpAlloc(KSIZE cb);
+KHLP_DECL(void *)   kHlpAllocZ(KSIZE cb);
+KHLP_DECL(void *)   kHlpDup(const void *pv, KSIZE cb);
+KHLP_DECL(char *)   kHlpStrDup(const char *psz);
+KHLP_DECL(void *)   kHlpRealloc(void *pv, KSIZE cb);
+KHLP_DECL(void)     kHlpFree(void *pv);
+
+KHLP_DECL(int)      kHlpPageAlloc(void **ppv, KSIZE cb, KPROT enmProt, KBOOL fFixed);
+KHLP_DECL(int)      kHlpPageProtect(void *pv, KSIZE cb, KPROT enmProt);
+KHLP_DECL(int)      kHlpPageFree(void *pv, KSIZE cb);
+
+KHLP_DECL(int)      kHlpHeapInit(void);
+KHLP_DECL(void)     kHlpHeapTerm(void);
+KHLP_DECL(void)     kHlpHeapDonate(void *pv, KSIZE cb);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif
+
diff --git a/src/lib/kStuff/include/k/kHlpAssert.h b/src/lib/kStuff/include/k/kHlpAssert.h
new file mode 100644
index 0000000..70bc526
--- /dev/null
+++ b/src/lib/kStuff/include/k/kHlpAssert.h
@@ -0,0 +1,258 @@
+/* $Id: kHlpAssert.h 70 2015-08-13 09:03:02Z bird $ */
+/** @file
+ * kHlpAssert - Assertion Macros.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#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__) && K_OS == K_OS_SOLARIS && (K_ARCH == K_ARCH_AMD64 || K_ARCH == K_ARCH_X86_32)
+# define kHlpAssertBreakpoint() do { __asm__ __volatile__ ("int $3"); } while (0)
+#elif defined(__GNUC__) && (K_ARCH == K_ARCH_AMD64 || K_ARCH == K_ARCH_X86_32 || K_ARCH == K_ARCH_X86_16)
+# define kHlpAssertBreakpoint() do { __asm__ __volatile__ ("int3"); } while (0)
+#else
+# error "Port Me"
+#endif
+
+/** @def K_FUNCTION
+ * Undecorated function name macro expanded by the compiler.
+ */
+#if defined(__GNUC__)
+# define K_FUNCTION __func__
+#else
+# define K_FUNCTION __FUNCTION__
+#endif
+
+#ifdef K_STRICT
+
+# define kHlpAssert(expr) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kHlpAssertBreakpoint(); \
+        } \
+    } while (0)
+
+# define kHlpAssertStmt(expr, stmt) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kHlpAssertBreakpoint(); \
+            stmt; \
+        } \
+    } while (0)
+
+# define kHlpAssertReturn(expr, rcRet) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kHlpAssertBreakpoint(); \
+            return (rcRet); \
+        } \
+    } while (0)
+
+# define kHlpAssertStmtReturn(expr, stmt, rcRet) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kHlpAssertBreakpoint(); \
+            stmt; \
+            return (rcRet); \
+        } \
+    } while (0)
+
+# define kHlpAssertReturnVoid(expr) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kHlpAssertBreakpoint(); \
+            return; \
+        } \
+    } while (0)
+
+# define kHlpAssertStmtReturnVoid(expr, stmt) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kHlpAssertBreakpoint(); \
+            stmt; \
+            return; \
+        } \
+    } while (0)
+
+# define kHlpAssertMsg(expr, msg) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kHlpAssertMsg2 msg; \
+            kHlpAssertBreakpoint(); \
+        } \
+    } while (0)
+
+# define kHlpAssertMsgStmt(expr, msg, stmt) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kHlpAssertMsg2 msg; \
+            kHlpAssertBreakpoint(); \
+            stmt; \
+        } \
+    } while (0)
+
+# define kHlpAssertMsgReturn(expr, msg, rcRet) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kHlpAssertMsg2 msg; \
+            kHlpAssertBreakpoint(); \
+            return (rcRet); \
+        } \
+    } while (0)
+
+# define kHlpAssertMsgStmtReturn(expr, msg, stmt, rcRet) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kHlpAssertMsg2 msg; \
+            kHlpAssertBreakpoint(); \
+            stmt; \
+            return (rcRet); \
+        } \
+    } while (0)
+
+# define kHlpAssertMsgReturnVoid(expr, msg) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kHlpAssertMsg2 msg; \
+            kHlpAssertBreakpoint(); \
+            return; \
+        } \
+    } while (0)
+
+# define kHlpAssertMsgStmtReturnVoid(expr, msg, stmt) \
+    do { \
+        if (!(expr)) \
+        { \
+            kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kHlpAssertMsg2 msg; \
+            kHlpAssertBreakpoint(); \
+            stmt; \
+            return; \
+        } \
+    } while (0)
+
+#else   /* !K_STRICT */
+# define kHlpAssert(expr)                                   do { } while (0)
+# define kHlpAssertStmt(expr, stmt)                         do { if (!(expr)) { stmt; }  } while (0)
+# define kHlpAssertReturn(expr, rcRet)                      do { if (!(expr)) return (rcRet); } while (0)
+# define kHlpAssertStmtReturn(expr, stmt, rcRet)            do { if (!(expr)) { stmt; return (rcRet); } } while (0)
+# define kHlpAssertReturnVoid(expr)                         do { if (!(expr)) return; } while (0)
+# define kHlpAssertStmtReturnVoid(expr, stmt)               do { if (!(expr)) { stmt; return; } } while (0)
+# define kHlpAssertMsg(expr, msg)                           do { } while (0)
+# define kHlpAssertMsgStmt(expr, msg, stmt)                 do { if (!(expr)) { stmt; } } while (0)
+# define kHlpAssertMsgReturn(expr, msg, rcRet)              do { if (!(expr)) return (rcRet); } while (0)
+# define kHlpAssertMsgStmtReturn(expr, msg, stmt, rcRet)    do { if (!(expr)) { stmt; return (rcRet); } } while (0)
+# define kHlpAssertMsgReturnVoid(expr, msg)                 do { if (!(expr)) return; } while (0)
+# define kHlpAssertMsgStmtReturnVoid(expr, msg, stmt)       do { if (!(expr)) { stmt; return; } } 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 kHlpAssertPtrReturn(ptr, rcRet)         kHlpAssertMsgReturn(K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)), (rcRet))
+#define kHlpAssertPtrReturnVoid(ptr)            kHlpAssertMsgReturnVoid(K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (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 kHlpAssertPtrNullReturnVoid(ptr)        kHlpAssertMsgReturnVoid(!(ptr) || K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (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 kHlpAssertRCReturnVoid(rc)              kHlpAssertMsgReturnVoid((rc) == 0, ("%s = %d -> %d\n", #rc, (rc), (rcRet)))
+#define kHlpAssertFailed()                      kHlpAssert(0)
+#define kHlpAssertFailedReturn(rcRet)           kHlpAssertReturn(0, (rcRet))
+#define kHlpAssertFailedReturnVoid()            kHlpAssertReturnVoid(0)
+#define kHlpAssertMsgFailed(msg)                kHlpAssertMsg(0, msg)
+#define kHlpAssertMsgFailedReturn(msg, rcRet)   kHlpAssertMsgReturn(0, msg, (rcRet))
+#define kHlpAssertMsgFailedReturnVoid(msg)      kHlpAssertMsgReturnVoid(0, msg))
+
+/**
+ * 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
diff --git a/src/lib/kStuff/include/k/kHlpDefs.h b/src/lib/kStuff/include/k/kHlpDefs.h
new file mode 100644
index 0000000..bcda10a
--- /dev/null
+++ b/src/lib/kStuff/include/k/kHlpDefs.h
@@ -0,0 +1,55 @@
+/* $Id: kHlpDefs.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpDefs - Helper Definitions.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#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
+
diff --git a/src/lib/kStuff/include/k/kHlpEnv.h b/src/lib/kStuff/include/k/kHlpEnv.h
new file mode 100644
index 0000000..95c2bda
--- /dev/null
+++ b/src/lib/kStuff/include/k/kHlpEnv.h
@@ -0,0 +1,55 @@
+/* $Id: kHlpEnv.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpEnv - Environment Manipulation.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kHlpEnv_h___
+#define ___k_kHlpEnv_h___
+
+#include <k/kHlpDefs.h>
+#include <k/kTypes.h>
+
+/** @defgroup grp_kHlpEnv kHlpEnv - Environment Manipulation
+ * @addtogroup grp_kHlp
+ * @{*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+KHLP_DECL(int)  kHlpGetEnv(const char *pszVar, char *pszVal, KSIZE cchVal);
+KHLP_DECL(int)  kHlpGetEnvUZ(const char *pszVar, KSIZE *pcb);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif
+
diff --git a/src/lib/kStuff/include/k/kHlpPath.h b/src/lib/kStuff/include/k/kHlpPath.h
new file mode 100644
index 0000000..c9d6ce5
--- /dev/null
+++ b/src/lib/kStuff/include/k/kHlpPath.h
@@ -0,0 +1,57 @@
+/* $Id: kHlpPath.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpPath - Path Manipulation.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kHlpPath_h___
+#define ___k_kHlpPath_h___
+
+#include <k/kHlpDefs.h>
+#include <k/kTypes.h>
+
+/** @defgroup grp_kHlpPath kHlpPath - Path Manipulation
+ * @addtogroup grp_kHlp
+ * @{*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+KHLP_DECL(char *)  kHlpGetFilename(const char *pszFilename);
+KHLP_DECL(char *)  kHlpGetSuff(const char *pszFilename);
+KHLP_DECL(char *)  kHlpGetExt(const char *pszFilename);
+KHLP_DECL(int)     kHlpIsFilenameOnly(const char *pszFilename);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif
+
diff --git a/src/lib/kStuff/include/k/kHlpProcess.h b/src/lib/kStuff/include/k/kHlpProcess.h
new file mode 100644
index 0000000..c637545
--- /dev/null
+++ b/src/lib/kStuff/include/k/kHlpProcess.h
@@ -0,0 +1,54 @@
+/* $Id: kHlpProcess.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpProcess - Process Management.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kHlpProcess_h___
+#define ___k_kHlpProcess_h___
+
+#include <k/kHlpDefs.h>
+#include <k/kTypes.h>
+
+/** @defgroup grp_kHlpProcess   kHlpProcess - Process Management
+ * @addtogroup grp_kHlp
+ * @{*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+KHLP_DECL(void) kHlpExit(int rc);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif
+
diff --git a/src/lib/kStuff/include/k/kHlpSem.h b/src/lib/kStuff/include/k/kHlpSem.h
new file mode 100644
index 0000000..72c6407
--- /dev/null
+++ b/src/lib/kStuff/include/k/kHlpSem.h
@@ -0,0 +1,54 @@
+/* $Id: kHlpSem.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpSem - Semaphores.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kHlpSem_h___
+#define ___k_kHlpSem_h___
+
+#include <k/kHlpDefs.h>
+#include <k/kTypes.h>
+
+/** @defgroup grp_kHlpSem kHlpSem - Semaphore
+ * @addtogroup grp_kHlp
+ * @{*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif
+
+
diff --git a/src/lib/kStuff/include/k/kHlpString.h b/src/lib/kStuff/include/k/kHlpString.h
new file mode 100644
index 0000000..23da03d
--- /dev/null
+++ b/src/lib/kStuff/include/k/kHlpString.h
@@ -0,0 +1,156 @@
+/* $Id: kHlpString.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - String And Memory Routines.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kHlpString_h___
+#define ___k_kHlpString_h___
+
+#include <k/kHlpDefs.h>
+#include <k/kTypes.h>
+
+#if 0 /* optimize / fix this later */
+#ifdef __GNUC__
+/** memchr */
+# define kHlpMemChr(a,b,c)      __builtin_memchr(a,b,c)
+/** memcmp */
+# define kHlpMemComp(a,b,c)     __builtin_memcmp(a,b,c)
+/** memcpy */
+# define kHlpMemCopy(a,b,c)     __builtin_memcpy(a,b,c)
+/** memset */
+# define kHlpMemSet(a,b,c)      __builtin_memset(a,b,c)
+/** strchr */
+# define kHlpStrChr(a, b)       __builtin_strchr(a, b)
+/** strcmp */
+# define kHlpStrComp(a, b)      __builtin_strcmp(a, b)
+/** strncmp */
+# define kHlpStrNComp(a,b,c)    __builtin_strncmp(a, b, c)
+/** strlen */
+# define kHlpStrLen(a)          __builtin_strlen(a)
+
+#elif defined(_MSC_VER)
+# pragma intrinsic(memcmp, memcpy, memset, strcmp, strlen)
+/** memcmp */
+# define kHlpMemComp(a,b,c)     memcmp(a,b,c)
+/** memcpy */
+# define kHlpMemCopy(a,b,c)     memcpy(a,b,c)
+/** memset */
+# define kHlpMemSet(a,b,c)      memset(a,b,c)
+/** strcmp */
+# define kHlpStrComp(a, b)      strcmp(a, b)
+/** strlen */
+# define kHlpStrLen(a)          strlen(a)
+#else
+# error "Port Me"
+#endif
+#endif /* disabled */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef kHlpMemChr
+KHLP_DECL(void *)   kHlpMemChr(const void *pv, int ch, KSIZE cb);
+#endif
+#ifndef kHlpMemComp
+KHLP_DECL(int)      kHlpMemComp(const void *pv1, const void *pv2, KSIZE cb);
+#endif
+#ifndef kHlpMemComp
+KHLP_DECL(void *)   kHlpMemPComp(const void *pv1, const void *pv2, KSIZE cb);
+#endif
+#ifndef kHlpMemCopy
+KHLP_DECL(void *)   kHlpMemCopy(void *pv1, const void *pv2, KSIZE cb);
+#endif
+#ifndef kHlpMemPCopy
+KHLP_DECL(void *)   kHlpMemPCopy(void *pv1, const void *pv2, KSIZE cb);
+#endif
+#ifndef kHlpMemMove
+KHLP_DECL(void *)   kHlpMemMove(void *pv1, const void *pv2, KSIZE cb);
+#endif
+#ifndef kHlpMemPMove
+KHLP_DECL(void *)   kHlpMemPMove(void *pv1, const void *pv2, KSIZE cb);
+#endif
+#ifndef kHlpMemSet
+KHLP_DECL(void *)   kHlpMemSet(void *pv1, int ch, KSIZE cb);
+#endif
+#ifndef kHlpMemPSet
+KHLP_DECL(void *)   kHlpMemPSet(void *pv1, int ch, KSIZE cb);
+#endif
+KHLP_DECL(int)      kHlpMemICompAscii(const void *pv1, const void *pv2, KSIZE cb);
+
+#ifndef kHlpStrCat
+KHLP_DECL(char *)   kHlpStrCat(char *psz1, const char *psz2);
+#endif
+#ifndef kHlpStrPCat
+KHLP_DECL(char *)   kHlpStrPCat(char *psz1, const char *psz2);
+#endif
+#ifndef kHlpStrNCat
+KHLP_DECL(char *)   kHlpStrNCat(char *psz1, const char *psz2, KSIZE cb);
+#endif
+#ifndef kHlpStrPNCat
+KHLP_DECL(char *)   kHlpStrNPCat(char *psz1, const char *psz2, KSIZE cb);
+#endif
+#ifndef kHlpStrChr
+KHLP_DECL(char *)   kHlpStrChr(const char *psz, int ch);
+#endif
+#ifndef kHlpStrRChr
+KHLP_DECL(char *)   kHlpStrRChr(const char *psz, int ch);
+#endif
+#ifndef kHlpStrComp
+KHLP_DECL(int)      kHlpStrComp(const char *psz1, const char *psz2);
+#endif
+KHLP_DECL(char *)   kHlpStrPComp(const char *psz1, const char *psz2);
+#ifndef kHlpStrNComp
+KHLP_DECL(int)      kHlpStrNComp(const char *psz1, const char *psz2, KSIZE cch);
+#endif
+KHLP_DECL(char *)   kHlpStrNPComp(const char *psz1, const char *psz2, KSIZE cch);
+KHLP_DECL(int)      kHlpStrICompAscii(const char *pv1, const char *pv2);
+KHLP_DECL(char *)   kHlpStrIPCompAscii(const char *pv1, const char *pv2);
+KHLP_DECL(int)      kHlpStrNICompAscii(const char *pv1, const char *pv2, KSIZE cch);
+KHLP_DECL(char *)   kHlpStrNIPCompAscii(const char *pv1, const char *pv2, KSIZE cch);
+#ifndef kHlpStrCopy
+KHLP_DECL(char *)   kHlpStrCopy(char *psz1, const char *psz2);
+#endif
+#ifndef kHlpStrPCopy
+KHLP_DECL(char *)   kHlpStrPCopy(char *psz1, const char *psz2);
+#endif
+#ifndef kHlpStrLen
+KHLP_DECL(KSIZE)    kHlpStrLen(const char *psz1);
+#endif
+#ifndef kHlpStrNLen
+KHLP_DECL(KSIZE)    kHlpStrNLen(const char *psz, KSIZE cchMax);
+#endif
+
+KHLP_DECL(char *)   kHlpInt2Ascii(char *psz, KSIZE cch, long lVal, unsigned iBase);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/lib/kStuff/include/k/kHlpSys.h b/src/lib/kStuff/include/k/kHlpSys.h
new file mode 100644
index 0000000..63aeaee
--- /dev/null
+++ b/src/lib/kStuff/include/k/kHlpSys.h
@@ -0,0 +1,79 @@
+/* $Id: kHlpSys.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpSys - System Call Prototypes.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kHlpSys_h___
+#define ___k_kHlpSys_h___
+
+#include <k/kHlpDefs.h>
+#include <k/kTypes.h>
+
+/** @defgroup grp_kHlpSys kHlpSys - System Call Prototypes
+ * @addtogroup grp_kHlp
+ * @{*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* common unix stuff. */
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+KSSIZE      kHlpSys_readlink(const char *pszPath, char *pszBuf, KSIZE cbBuf);
+int         kHlpSys_open(const char *filename, int flags, int mode);
+int         kHlpSys_close(int fd);
+KFOFF       kHlpSys_lseek(int fd, int whench, KFOFF off);
+KSSIZE      kHlpSys_read(int fd, void *pvBuf, KSIZE cbBuf);
+KSSIZE      kHlpSys_write(int fd, const void *pvBuf, KSIZE cbBuf);
+void       *kHlpSys_mmap(void *addr, KSIZE len, int prot, int flags, int fd, KI64 off);
+int         kHlpSys_mprotect(void *addr, KSIZE len, int prot);
+int         kHlpSys_munmap(void *addr, KSIZE len);
+void        kHlpSys_exit(int rc);
+#endif
+
+/* specific */
+#if K_OS == K_OS_DARWIN
+
+#elif K_OS == K_OS_LINUX
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif
+
+
diff --git a/src/lib/kStuff/include/k/kHlpThread.h b/src/lib/kStuff/include/k/kHlpThread.h
new file mode 100644
index 0000000..1b2f233
--- /dev/null
+++ b/src/lib/kStuff/include/k/kHlpThread.h
@@ -0,0 +1,55 @@
+/* $Id: kHlpThread.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpThread - Thread Manipulation.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kHlpThread_h___
+#define ___k_kHlpThread_h___
+
+#include <k/kHlpDefs.h>
+#include <k/kTypes.h>
+
+/** @defgroup grp_kHlpThread kHlpThread - Thread Management
+ * @addtogroup grp_kHlp
+ * @{*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+KHLP_DECL(void)    kHlpSleep(unsigned cMillies);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif
+
+
diff --git a/src/lib/kStuff/include/k/kLdr.h b/src/lib/kStuff/include/k/kLdr.h
new file mode 100644
index 0000000..1c37943
--- /dev/null
+++ b/src/lib/kStuff/include/k/kLdr.h
@@ -0,0 +1,957 @@
+/* $Id: kLdr.h 81 2016-08-18 22:10:38Z bird $ */
+/** @file
+ * kLdr - The Dynamic Loader.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kLdr_h___
+#define ___k_kLdr_h___
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Include the base typedefs and macros.
+ */
+#include <k/kDefs.h>
+#include <k/kTypes.h>
+#include <k/kCpus.h>
+
+
+/** @defgroup grp_kLdrBasic     kLdr Basic Types
+ * @{ */
+
+/** The kLdr address type. */
+typedef KU64 KLDRADDR;
+/** Pointer to a kLdr address. */
+typedef KLDRADDR *PKLDRADDR;
+/** Pointer to a const kLdr address. */
+typedef const KLDRADDR *PCKLDRADDR;
+
+/** NIL address. */
+#define NIL_KLDRADDR    (~(KU64)0)
+
+/** @def PRI_KLDRADDR
+ * printf format type. */
+#ifdef _MSC_VER
+# define PRI_KLDRADDR    "I64x"
+#else
+# define PRI_KLDRADDR    "llx"
+#endif
+
+/** Align a KSIZE value. */
+#define KLDR_ALIGN_ADDR(val, align) ( ((val) + ((align) - 1)) & ~(KLDRADDR)((align) - 1) )
+
+
+/** The kLdr size type. */
+typedef KU64 KLDRSIZE;
+/** Pointer to a kLdr size. */
+typedef KLDRSIZE *PKLDRSIZE;
+/** Pointer to a const kLdr size. */
+typedef const KLDRSIZE *PCKLDRSIZE;
+
+/** @def PRI_KLDRSIZE
+ * printf format type. */
+#ifdef _MSC_VER
+# define PRI_KLDRSIZE    "I64x"
+#else
+# define PRI_KLDRSIZE    "llx"
+#endif
+
+
+/** The kLdr file offset type. */
+typedef long KLDRFOFF;
+/** Pointer to a kLdr file offset type. */
+typedef KLDRFOFF *PKLDRFOFF;
+/** Pointer to a const kLdr file offset type. */
+typedef const KLDRFOFF *PCKLDRFOFF;
+
+/** @def PRI_KLDRFOFF
+ * printf format type. */
+#define PRI_KLDRFOFF     "lx"
+
+
+/**
+ * Union of all the integer types.
+ */
+typedef union KLDRU
+{
+    KI8             i8;     /**< KI8 view. */
+    KU8             u8;     /**< KU8 view. */
+    KI16            i16;    /**< KI16 view. */
+    KU16            u16;    /**< KU16 view. */
+    KI32            i32;    /**< KI32 view. */
+    KU32            u32;    /**< KU32 view. */
+    KI64            i64;    /**< KI64 view. */
+    KU64            u64;    /**< KU64 view. */
+
+    KI8             ai8[8]; /**< KI8 array view . */
+    KU8             au8[8]; /**< KU8 array view. */
+    KI16            ai16[4];/**< KI16 array view . */
+    KU16            au16[4];/**< KU16 array view. */
+    KI32            ai32[2];/**< KI32 array view . */
+    KU32            au32[2];/**< KU32 array view. */
+
+    signed char     ch;     /**< signed char view. */
+    unsigned char   uch;    /**< unsigned char view. */
+    signed short    s;      /**< signed short view. */
+    unsigned short  us;     /**< unsigned short view. */
+    signed int      i;      /**< signed int view. */
+    unsigned int    u;      /**< unsigned int view. */
+    signed long     l;      /**< signed long view. */
+    unsigned long   ul;     /**< unsigned long view. */
+    void           *pv;     /**< void pointer view. */
+
+    KLDRADDR        Addr;   /**< kLdr address view. */
+    KLDRSIZE        Size;   /**< kLdr size view. */
+} KLDRU;
+/** Pointer to an integer union. */
+typedef KLDRU *PKLDRU;
+/** Pointer to a const integer union. */
+typedef const KLDRU *PCKLDRU;
+
+
+/**
+ * Union of pointers to all the integer types.
+ */
+typedef union KLDRPU
+{
+    KI8            *pi8;    /**< KI8 view. */
+    KU8            *pu8;    /**< KU8 view. */
+    KI16           *pi16;   /**< KI16 view. */
+    KU16           *pu16;   /**< KU16 view. */
+    KI32           *pi32;   /**< KI32 view. */
+    KU32           *pu32;   /**< KU32 view. */
+    KI64           *pi64;   /**< KI64 view. */
+    KU64           *pu64;   /**< KU64 view. */
+
+    signed char    *pch;    /**< signed char view. */
+    unsigned char  *puch;   /**< unsigned char view. */
+    signed short   *ps;     /**< signed short view. */
+    unsigned short *pus;    /**< unsigned short view. */
+    signed int     *pi;     /**< signed int view. */
+    unsigned int   *pu;     /**< unsigned int view. */
+    signed long    *pl;     /**< signed long view. */
+    unsigned long  *pul;    /**< unsigned long view. */
+    void           *pv;     /**< void pointer view. */
+} KLDRPU;
+/** Pointer to an integer pointer union. */
+typedef KLDRPU *PKLDRPU;
+/** Pointer to a const integer pointer union. */
+typedef const KLDRPU *PCKLDRPU;
+
+/** @} */
+
+
+/** @defgroup grp_kLdrMod   kLdrMod - The executable image intepreter
+ * @{ */
+
+/**
+ * Debug info type (from the loader point of view).
+ */
+typedef enum KLDRDBGINFOTYPE
+{
+    /** The usual invalid enum value. */
+    KLDRDBGINFOTYPE_INVALID = 0,
+    /** Unknown debug info format. */
+    KLDRDBGINFOTYPE_UNKNOWN,
+    /** Stabs. */
+    KLDRDBGINFOTYPE_STABS,
+    /** Debug With Arbitrary Record Format (DWARF). */
+    KLDRDBGINFOTYPE_DWARF,
+    /** Microsoft Codeview debug info. */
+    KLDRDBGINFOTYPE_CODEVIEW,
+    /** Watcom debug info. */
+    KLDRDBGINFOTYPE_WATCOM,
+    /** IBM High Level Language debug info.. */
+    KLDRDBGINFOTYPE_HLL,
+    /** The end of the valid debug info values (exclusive). */
+    KLDRDBGINFOTYPE_END,
+    /** Blow the type up to 32-bit. */
+    KLDRDBGINFOTYPE_32BIT_HACK = 0x7fffffff
+} KLDRDBGINFOTYPE;
+/** Pointer to a kLdr debug info type. */
+typedef KLDRDBGINFOTYPE *PKLDRDBGINFOTYPE;
+
+
+/**
+ * Stack information.
+ */
+typedef struct KLDRSTACKINFO
+{
+    /** The base address of the stack (sub) segment.
+     * Set this to NIL_KLDRADDR if the module doesn't include any stack segment. */
+    KLDRADDR        Address;
+    /** The base address of the stack (sub) segment, link address.
+     * Set this to NIL_KLDRADDR if the module doesn't include any stack (sub)segment. */
+    KLDRADDR        LinkAddress;
+    /** The stack size of the main thread.
+     * If no stack (sub)segment in the module, this is the stack size of the main thread.
+     * If the module doesn't contain this kind of information this field will be set to 0. */
+    KLDRSIZE        cbStack;
+    /** The stack size of non-main threads.
+     * If the module doesn't contain this kind of information this field will be set to 0. */
+    KLDRSIZE        cbStackThread;
+} KLDRSTACKINFO;
+/** Pointer to stack information. */
+typedef KLDRSTACKINFO *PKLDRSTACKINFO;
+/** Pointer to const stack information. */
+typedef const KLDRSTACKINFO *PCKLDRSTACKINFO;
+
+
+/**
+ * Loader segment.
+ */
+typedef struct KLDRSEG
+{
+    /** Variable free to use for the kLdr user. */
+    void           *pvUser;
+    /** The segment name. (Might not be zero terminated!) */
+    const char     *pchName;
+    /** The length of the segment name. */
+    KU32            cchName;
+    /** The flat selector to use for the segment (i.e. data/code).
+     * Primarily a way for the user to specify selectors for the LX/LE and NE interpreters. */
+    KU16            SelFlat;
+    /** The 16-bit selector to use for the segment.
+     * Primarily a way for the user to specify selectors for the LX/LE and NE interpreters. */
+    KU16            Sel16bit;
+    /** Segment flags. */
+    KU32            fFlags;
+    /** The segment protection. */
+    KPROT           enmProt;
+    /** The size of the segment. */
+    KLDRSIZE        cb;
+    /** 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 or if the image doesn't have link addresses. */
+    KLDRADDR        LinkAddress;
+    /** File offset of the segment.
+     * Set to -1 if no file backing (like BSS). */
+    KLDRFOFF        offFile;
+    /** Size of the file bits of the segment.
+     * Set to -1 if no file backing (like BSS). */
+    KLDRFOFF        cbFile;
+    /** The relative virtual address when mapped.
+     * Set to NIL_KLDRADDR if the segment isn't supposed to be mapped. */
+    KLDRADDR        RVA;
+    /** The size of the segment including the alignment gap up to the next segment when mapped. */
+    KSIZE           cbMapped;
+    /** The address the segment was mapped at by kLdrModMap().
+     * Set to 0 if not mapped. */
+    KUPTR           MapAddress;
+} KLDRSEG;
+
+
+/** @name Segment flags
+ * @{ */
+/** The segment is 16-bit. When not set the default of the target architecture is assumed. */
+#define KLDRSEG_FLAG_16BIT          1
+/** The segment requires a 16-bit selector alias. (OS/2) */
+#define KLDRSEG_FLAG_OS2_ALIAS16    2
+/** Conforming segment (x86 weirdness). (OS/2) */
+#define KLDRSEG_FLAG_OS2_CONFORM    4
+/** IOPL (ring-2) segment. (OS/2) */
+#define KLDRSEG_FLAG_OS2_IOPL       8
+/** @} */
+
+
+/**
+ * Loader module format.
+ */
+typedef enum KLDRFMT
+{
+    /** The usual invalid 0 format. */
+    KLDRFMT_INVALID = 0,
+    /** The native OS loader. */
+    KLDRFMT_NATIVE,
+    /** The AOUT loader. */
+    KLDRFMT_AOUT,
+    /** The ELF loader. */
+    KLDRFMT_ELF,
+    /** The LX loader. */
+    KLDRFMT_LX,
+    /** The Mach-O loader. */
+    KLDRFMT_MACHO,
+    /** The PE loader. */
+    KLDRFMT_PE,
+    /** The end of the valid format values (exclusive). */
+    KLDRFMT_END,
+    /** Hack to blow the type up to 32-bit. */
+    KLDRFMT_32BIT_HACK = 0x7fffffff
+} KLDRFMT;
+
+
+/**
+ * Loader module type.
+ */
+typedef enum KLDRTYPE
+{
+    /** The usual invalid 0 type. */
+    KLDRTYPE_INVALID = 0,
+    /** Object file. */
+    KLDRTYPE_OBJECT,
+    /** Executable module, fixed load address. */
+    KLDRTYPE_EXECUTABLE_FIXED,
+    /** Executable module, relocatable, non-fixed load address. */
+    KLDRTYPE_EXECUTABLE_RELOCATABLE,
+    /** Executable module, position independent code, non-fixed load address. */
+    KLDRTYPE_EXECUTABLE_PIC,
+    /** Shared library, fixed load address.
+     * Typically a system library. */
+    KLDRTYPE_SHARED_LIBRARY_FIXED,
+    /** Shared library, relocatable, non-fixed load address. */
+    KLDRTYPE_SHARED_LIBRARY_RELOCATABLE,
+    /** Shared library, position independent code, non-fixed load address. */
+    KLDRTYPE_SHARED_LIBRARY_PIC,
+    /** DLL that contains no code or data only imports and exports. (Chiefly OS/2.) */
+    KLDRTYPE_FORWARDER_DLL,
+    /** Core or dump. */
+    KLDRTYPE_CORE,
+    /** Debug module (debug info with empty code & data segments). */
+    KLDRTYPE_DEBUG_INFO,
+    /** The end of the valid types values (exclusive). */
+    KLDRTYPE_END,
+    /** Hack to blow the type up to 32-bit. */
+    KLDRTYPE_32BIT_HACK = 0x7fffffff
+} KLDRTYPE;
+
+
+/**
+ * Loader endian indicator.
+ */
+typedef enum KLDRENDIAN
+{
+    /** The usual invalid endian. */
+    KLDRENDIAN_INVALID,
+    /** Little endian. */
+    KLDRENDIAN_LITTLE,
+    /** Bit endian. */
+    KLDRENDIAN_BIG,
+    /** Endianness doesn't have a meaning in the context. */
+    KLDRENDIAN_NA,
+    /** The end of the valid endian values (exclusive). */
+    KLDRENDIAN_END,
+    /** Hack to blow the type up to 32-bit. */
+    KLDRENDIAN_32BIT_HACK = 0x7fffffff
+} KLDRENDIAN;
+
+
+/** @name KLDRMOD::fFlags
+ * @{ */
+/** The link address doesn't form a contiguous image, from the first to the
+ * last segment.   */
+#define KLDRMOD_FLAGS_NON_CONTIGUOUS_LINK_ADDRS         K_BIT32(0)
+/** @} */
+
+/** Pointer to a module interpreter method table. */
+typedef struct KLDRMODOPS *PKLDRMODOPS;
+/** Pointer to const module interpreter methods table. */
+typedef const struct KLDRMODOPS *PCKLDRMODOPS;
+
+/**
+ * Module interpreter instance.
+ * All members are read only unless you're kLdrMod or the module interpreter.
+ */
+typedef struct KLDRMOD
+{
+    /** Magic number (KLDRMOD_MAGIC). */
+    KU32                u32Magic;
+    /** The format of this module. */
+    KLDRFMT             enmFmt;
+    /** The type of module. */
+    KLDRTYPE            enmType;
+    /** The CPU architecture this module was built for. */
+    KCPUARCH            enmArch;
+    /** The minium cpu this module was built for.
+     * This might not be accurate, so use kLdrModCanExecuteOn() to check. */
+    KCPU                enmCpu;
+    /** The endian used by the module. */
+    KLDRENDIAN          enmEndian;
+    /** Module falgs. */
+    KU32                fFlags;
+    /** The filename length (bytes). */
+    KU32                cchFilename;
+    /** The filename. */
+    const char         *pszFilename;
+    /** The module name. */
+    const char         *pszName;
+    /** The module name length (bytes). */
+    KU32                cchName;
+    /** The number of segments in the module. */
+    KU32                cSegments;
+    /** Pointer to the loader methods.
+     * Not meant for calling directly thru! */
+    PCKLDRMODOPS        pOps;
+    /** Pointer to the read instance. (Can be NULL after kLdrModDone().)*/
+    PKRDR               pRdr;
+    /** The module data. */
+    void               *pvData;
+    /** Segments. (variable size, can be zero) */
+    KLDRSEG             aSegments[1];
+} KLDRMOD, *PKLDRMOD, **PPKLDRMOD;
+
+/** The magic for KLDRMOD::u32Magic. (Kosuke Fujishima) */
+#define KLDRMOD_MAGIC   0x19640707
+
+
+/** Special base address value alias for the link address. */
+#define KLDRMOD_BASEADDRESS_LINK            (~(KLDRADDR)1)
+/** Special base address value alias for the actual load address (must be mapped). */
+#define KLDRMOD_BASEADDRESS_MAP             (~(KLDRADDR)2)
+
+/** Special import module ordinal value used to indicate that there is no
+ * specific module associated with the requested symbol. */
+#define NIL_KLDRMOD_IMPORT                  (~(KU32)0)
+
+/** Special symbol ordinal value used to indicate that the symbol
+ * only has a string name. */
+#define NIL_KLDRMOD_SYM_ORDINAL             (~(KU32)0)
+
+
+/** @name Load symbol kind flags.
+ * @{ */
+/** The bitness doesn't matter. */
+#define KLDRSYMKIND_NO_BIT                  0x00000000
+/** 16-bit symbol. */
+#define KLDRSYMKIND_16BIT                   0x00000001
+/** 32-bit symbol. */
+#define KLDRSYMKIND_32BIT                   0x00000002
+/** 64-bit symbol. */
+#define KLDRSYMKIND_64BIT                   0x00000003
+/** Mask out the bit.*/
+#define KLDRSYMKIND_BIT_MASK                0x00000003
+/** We don't know the type of symbol. */
+#define KLDRSYMKIND_NO_TYPE                 0x00000000
+/** The symbol is a code object (method/function/procedure/whateveryouwannacallit). */
+#define KLDRSYMKIND_CODE                    0x00000010
+/** The symbol is a data object. */
+#define KLDRSYMKIND_DATA                    0x00000020
+/** Mask out the symbol type. */
+#define KLDRSYMKIND_TYPE_MASK               0x00000030
+/** Valid symbol kind mask. */
+#define KLDRSYMKIND_MASK                    0x00000033
+/** Weak symbol. */
+#define KLDRSYMKIND_WEAK                    0x00000100
+/** Forwarder symbol. */
+#define KLDRSYMKIND_FORWARDER               0x00000200
+/** Request a flat symbol address. */
+#define KLDRSYMKIND_REQ_FLAT                0x00000000
+/** Request a segmented symbol address. */
+#define KLDRSYMKIND_REQ_SEGMENTED           0x40000000
+/** Request type mask. */
+#define KLDRSYMKIND_REQ_TYPE_MASK           0x40000000
+/** @} */
+
+/** @name kLdrModEnumSymbols flags.
+ * @{ */
+/** Returns ALL kinds of symbols. The default is to only return public/exported symbols. */
+#define KLDRMOD_ENUM_SYMS_FLAGS_ALL         0x00000001
+/** @} */
+
+
+/**
+ * Callback for resolving imported symbols when applying fixups.
+ *
+ * @returns 0 on success and *pValue and *pfKind filled.
+ * @returns Non-zero OS specific or kLdr status code on failure.
+ *
+ * @param   pMod        The module which fixups are begin applied.
+ * @param   iImport     The import module ordinal number or NIL_KLDRMOD_IMPORT.
+ * @param   iSymbol     The symbol ordinal number or NIL_KLDRMOD_SYM_ORDINAL.
+ * @param   pchSymbol   The symbol name. Can be NULL if iSymbol isn't nil. Doesn't have to be null-terminated.
+ * @param   cchSymbol   The length of the symbol.
+ * @param   pszVersion  The symbol version. NULL if not versioned.
+ * @param   puValue     Where to store the symbol value.
+ * @param   pfKind      Where to store the symbol kind flags.
+ * @param   pvUser      The user parameter specified to the relocation function.
+ */
+typedef int FNKLDRMODGETIMPORT(PKLDRMOD pMod, KU32 iImport, KU32 iSymbol, const char *pchSymbol, KSIZE cchSymbol,
+                               const char *pszVersion, PKLDRADDR puValue, KU32 *pfKind, void *pvUser);
+/** Pointer to a import callback. */
+typedef FNKLDRMODGETIMPORT *PFNKLDRMODGETIMPORT;
+
+/**
+ * Symbol enumerator callback.
+ *
+ * @returns 0 if enumeration should continue.
+ * @returns non-zero if the enumeration should stop. This status code will then be returned by kLdrModEnumSymbols().
+ *
+ * @param   pMod        The module which symbols are being enumerated.s
+ * @param   iSymbol     The symbol ordinal number or NIL_KLDRMOD_SYM_ORDINAL.
+ * @param   pchSymbol   The symbol name. This can be NULL if there is a symbol ordinal.
+ *                      This can also be an empty string if the symbol doesn't have a name
+ *                      or it's name has been stripped.
+ *                      Important, this doesn't have to be a null-terminated string.
+ * @param   cchSymbol   The length of the symbol.
+ * @param   pszVersion  The symbol version. NULL if not versioned.
+ * @param   uValue      The symbol value.
+ * @param   fKind       The symbol kind flags.
+ * @param   pvUser      The user parameter specified to kLdrModEnumSymbols().
+ */
+typedef int FNKLDRMODENUMSYMS(PKLDRMOD pMod, KU32 iSymbol, const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion,
+                              KLDRADDR uValue, KU32 fKind, void *pvUser);
+/** Pointer to a symbol enumerator callback. */
+typedef FNKLDRMODENUMSYMS *PFNKLDRMODENUMSYMS;
+
+/**
+ * Debug info enumerator callback.
+ *
+ * @returns 0 to continue the enumeration.
+ * @returns non-zero if the enumeration should stop. This status code will then be returned by kLdrModEnumDbgInfo().
+ *
+ * @param   pMod        The module.
+ * @param   iDbgInfo    The debug info ordinal number / id.
+ * @param   enmType     The debug info type.
+ * @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   pszPartNm   The name of the debug info part, NULL if not applicable.
+ * @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   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, KU32 iDbgInfo, KLDRDBGINFOTYPE enmType, KI16 iMajorVer, KI16 iMinorVer,
+                          const char *pszPartNm, KLDRFOFF offFile, KLDRADDR LinkAddress, KLDRSIZE cb,
+                          const char *pszExtFile, void *pvUser);
+/** Pointer to a debug info enumerator callback. */
+typedef FNKLDRENUMDBG *PFNKLDRENUMDBG;
+
+/**
+ * Resource enumerator callback.
+ *
+ * @returns 0 to continue the enumeration.
+ * @returns non-zero if the enumeration should stop. This status code will then be returned by kLdrModEnumResources().
+ *
+ * @param   pMod        The module.
+ * @param   idType      The resource type id. NIL_KLDRMOD_RSRC_TYPE_ID if no type id.
+ * @param   pszType     The resource type name. NULL if no type name.
+ * @param   idName      The resource id. NIL_KLDRMOD_RSRC_NAME_ID if no id.
+ * @param   pszName     The resource name. NULL if no name.
+ * @param   idLang      The language id.
+ * @param   AddrRsrc    The address value for the resource.
+ * @param   cbRsrc      The size of the resource.
+ * @param   pvUser      The user parameter specified to kLdrModEnumDbgInfo.
+ */
+typedef int FNKLDRENUMRSRC(PKLDRMOD pMod, KU32 idType, const char *pszType, KU32 idName, const char *pszName,
+                           KU32 idLang, KLDRADDR AddrRsrc, KLDRSIZE cbRsrc, void *pvUser);
+/** Pointer to a resource enumerator callback. */
+typedef FNKLDRENUMRSRC *PFNKLDRENUMRSRC;
+
+/** NIL resource name ID. */
+#define NIL_KLDRMOD_RSRC_NAME_ID    ( ~(KU32)0 )
+/** NIL resource type ID. */
+#define NIL_KLDRMOD_RSRC_TYPE_ID    ( ~(KU32)0 )
+/** @name Language ID
+ *
+ * Except for the special IDs #defined here, the values are considered
+ * format specific for now since it's only used by the PE resources.
+ *
+ * @{ */
+/** NIL language ID. */
+#define NIL_KLDR_LANG_ID                ( ~(KU32)0 )
+/** Special language id value for matching any language. */
+#define KLDR_LANG_ID_ANY                ( ~(KU32)1 )
+/** Special language id value indicating language neutral. */
+#define KLDR_LANG_ID_NEUTRAL            ( ~(KU32)2 )
+/** Special language id value indicating user default language. */
+#define KLDR_LANG_ID_USER_DEFAULT       ( ~(KU32)3 )
+/** Special language id value indicating system default language. */
+#define KLDR_LANG_ID_SYS_DEFAULT        ( ~(KU32)4 )
+/** Special language id value indicating default custom locale. */
+#define KLDR_LANG_ID_CUSTOM_DEFAULT     ( ~(KU32)5 )
+/** Special language id value indicating unspecified custom locale. */
+#define KLDR_LANG_ID_CUSTOM_UNSPECIFIED ( ~(KU32)6 )
+/** Special language id value indicating default custom MUI locale. */
+#define KLDR_LANG_ID_UI_CUSTOM_DEFAULT  ( ~(KU32)7 )
+/** @} */
+
+/** @name Module Open Flags
+ * @{ */
+/** Indicates that we won't be loading the module, we're just getting
+ *  information (like symbols and line numbers) out of it. */
+#define KLDRMOD_OPEN_FLAGS_FOR_INFO     K_BIT32(0)
+/** Mask of valid flags.    */
+#define KLDRMOD_OPEN_FLAGS_VALID_MASK   KU32_C(0x00000001)
+/** @} */
+
+int     kLdrModOpen(const char *pszFilename, KU32 fFlags, KCPUARCH enmCpuArch, PPKLDRMOD ppMod);
+int     kLdrModOpenFromRdr(PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch, PPKLDRMOD ppMod);
+int     kLdrModOpenNative(const char *pszFilename, PPKLDRMOD ppMod);
+int     kLdrModOpenNativeByHandle(KUPTR uHandle, PPKLDRMOD ppMod);
+int     kLdrModClose(PKLDRMOD pMod);
+
+int     kLdrModQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 iSymbol,
+                           const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion,
+                           PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind);
+int     kLdrModEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress,
+                           KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser);
+int     kLdrModGetImport(PKLDRMOD pMod, const void *pvBits, KU32 iImport, char *pszName, KSIZE cchName);
+KI32    kLdrModNumberOfImports(PKLDRMOD pMod, const void *pvBits);
+int     kLdrModCanExecuteOn(PKLDRMOD pMod, const void *pvBits, KCPUARCH enmArch, KCPU enmCpu);
+int     kLdrModGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo);
+int     kLdrModQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress);
+int     kLdrModQueryImageUuid(PKLDRMOD pMod, const void *pvBits, void *pvUuid, KSIZE cbUuid);
+int     kLdrModQueryResource(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 idType, const char *pszType,
+                             KU32 idName, const char *pszName, KU32 idLang, PKLDRADDR pAddrRsrc, KSIZE *pcbRsrc);
+int     kLdrModEnumResources(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 idType, const char *pszType,
+                             KU32 idName, const char *pszName, KU32 idLang, PFNKLDRENUMRSRC pfnCallback, void *pvUser);
+int     kLdrModEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser);
+int     kLdrModHasDbgInfo(PKLDRMOD pMod, const void *pvBits);
+int     kLdrModMostlyDone(PKLDRMOD pMod);
+
+
+/** @name Operations On The Internally Managed Mapping
+ * @{ */
+int     kLdrModMap(PKLDRMOD pMod);
+int     kLdrModUnmap(PKLDRMOD pMod);
+int     kLdrModReload(PKLDRMOD pMod);
+int     kLdrModFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
+/** @} */
+
+/** @name Operations On The Externally Managed Mappings
+ * @{ */
+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,
+                            PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
+/** @} */
+
+/** @name Operations on both internally and externally managed mappings.
+ * @{ */
+/** Special pvMapping value to pass to kLdrModAllocTLS,
+ * kLdrModFreeTLS, kLdrModCallInit, kLdrModCallTerm, and kLdrModCallThread that
+ * specifies the internal mapping (kLdrModMap). */
+#define KLDRMOD_INT_MAP    ((void *)~(KUPTR)0)
+int     kLdrModAllocTLS(PKLDRMOD pMod, void *pvMapping);
+void    kLdrModFreeTLS(PKLDRMOD pMod, void *pvMapping);
+int     kLdrModCallInit(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle);
+int     kLdrModCallTerm(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle);
+int     kLdrModCallThread(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle, unsigned fAttachingOrDetaching);
+/** @} */
+
+
+/**
+ * The loader module operation.
+ */
+typedef struct KLDRMODOPS
+{
+    /** The name of this module interpreter. */
+    const char         *pszName;
+    /** Pointer to the next module interpreter. */
+    PCKLDRMODOPS        pNext;
+
+    /**
+     * Create a loader module instance interpreting the executable image found
+     * in the specified file provider instance.
+     *
+     * @returns 0 on success and *ppMod pointing to a module instance.
+     *          On failure, a non-zero OS specific error code is returned.
+     * @param   pOps            Pointer to the registered method table.
+     * @param   pRdr            The file provider instance to use.
+     * @param   fFlags          Flags, MBZ.
+     * @param   enmCpuArch      The desired CPU architecture. KCPUARCH_UNKNOWN means
+     *                          anything goes, but with a preference for the current
+     *                          host architecture.
+     * @param   offNewHdr       The offset of the new header in MZ files. -1 if not found.
+     * @param   ppMod           Where to store the module instance pointer.
+     */
+    int (* pfnCreate)(PCKLDRMODOPS pOps, PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch, KLDRFOFF offNewHdr, PPKLDRMOD ppMod);
+    /**
+     * Destroys an loader module instance.
+     *
+     * The caller is responsible for calling kLdrModUnmap() and kLdrFreeTLS() first.
+     *
+     * @returns 0 on success, non-zero on failure. The module instance state
+     *          is unknown on failure, it's best not to touch it.
+     * @param   pMod    The module.
+     */
+    int (* pfnDestroy)(PKLDRMOD pMod);
+
+    /** @copydoc kLdrModQuerySymbol */
+    int (* pfnQuerySymbol)(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 iSymbol,
+                           const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion,
+                           PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind);
+    /** @copydoc kLdrModEnumSymbols */
+    int (* pfnEnumSymbols)(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 fFlags,
+                           PFNKLDRMODENUMSYMS pfnCallback, void *pvUser);
+    /** @copydoc kLdrModGetImport */
+    int (* pfnGetImport)(PKLDRMOD pMod, const void *pvBits, KU32 iImport, char *pszName, KSIZE cchName);
+    /** @copydoc kLdrModNumberOfImports */
+    KI32 (* pfnNumberOfImports)(PKLDRMOD pMod, const void *pvBits);
+    /** @copydoc kLdrModCanExecuteOn */
+    int (* pfnCanExecuteOn)(PKLDRMOD pMod, const void *pvBits, KCPUARCH enmArch, KCPU enmCpu);
+    /** @copydoc kLdrModGetStackInfo */
+    int (* pfnGetStackInfo)(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo);
+    /** @copydoc kLdrModQueryMainEntrypoint */
+    int (* pfnQueryMainEntrypoint)(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress);
+    /** @copydoc kLdrModQueryImageUuid  */
+    int (* pfnQueryImageUuid)(PKLDRMOD pMod, const void *pvBits, void *pvUuid, KSIZE pcbUuid);
+    /** @copydoc kLdrModQueryResource */
+    int (* pfnQueryResource)(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 idType, const char *pszType,
+                             KU32 idName, const char *pszName, KU32 idLang, PKLDRADDR pAddrRsrc, KSIZE *pcbRsrc);
+    /** @copydoc kLdrModEnumResources */
+    int (* pfnEnumResources)(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 idType, const char *pszType,
+                             KU32 idName, const char *pszName, KU32 idLang, PFNKLDRENUMRSRC pfnCallback, void *pvUser);
+    /** @copydoc kLdrModEnumDbgInfo */
+    int (* pfnEnumDbgInfo)(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser);
+    /** @copydoc kLdrModHasDbgInfo */
+    int (* pfnHasDbgInfo)(PKLDRMOD pMod, const void *pvBits);
+    /** @copydoc kLdrModMap */
+    int (* pfnMap)(PKLDRMOD pMod);
+    /** @copydoc kLdrModUnmap */
+    int (* pfnUnmap)(PKLDRMOD pMod);
+    /** @copydoc kLdrModAllocTLS */
+    int (* pfnAllocTLS)(PKLDRMOD pMod, void *pvMapping);
+    /** @copydoc kLdrModFreeTLS */
+    void (*pfnFreeTLS)(PKLDRMOD pMod, void *pvMapping);
+    /** @copydoc kLdrModReload */
+    int (* pfnReload)(PKLDRMOD pMod);
+    /** @copydoc kLdrModFixupMapping */
+    int (* pfnFixupMapping)(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
+    /** @copydoc kLdrModCallInit */
+    int (* pfnCallInit)(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle);
+    /** @copydoc kLdrModCallTerm */
+    int (* pfnCallTerm)(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle);
+    /** @copydoc kLdrModCallThread */
+    int (* pfnCallThread)(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle, unsigned fAttachingOrDetaching);
+    /** @copydoc kLdrModSize */
+    KLDRADDR (* pfnSize)(PKLDRMOD pMod);
+    /** @copydoc kLdrModGetBits */
+    int (* pfnGetBits)(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
+    /** @copydoc kLdrModRelocateBits */
+    int (* pfnRelocateBits)(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
+                            PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
+    /** @copydoc kLdrModMostlyDone */
+    int (* pfnMostlyDone)(PKLDRMOD pMod);
+    /** Dummy which should be assigned a non-zero value. */
+    KU32 uEndOfStructure;
+} KLDRMODOPS;
+
+
+/** @} */
+
+
+
+
+/** @defgroup grp_kLdrDyld   kLdrDyld - The dynamic loader
+ * @{ */
+
+/** The handle to a dynamic loader module. */
+typedef struct KLDRDYLDMOD *HKLDRMOD;
+/** Pointer to the handle to a dynamic loader module. */
+typedef HKLDRMOD *PHKLDRMOD;
+/** NIL handle value. */
+#define NIL_HKLDRMOD    ((HKLDRMOD)0)
+
+
+/**
+ * File search method.
+ *
+ * In addition to it's own way of finding files, kLdr emulates
+ * the methods employed by the most popular systems.
+ */
+typedef enum KLDRDYLDSEARCH
+{
+    /** The usual invalid file search method. */
+    KLDRDYLD_SEARCH_INVALID = 0,
+    /** Uses the kLdr file search method.
+     * @todo invent me. */
+    KLDRDYLD_SEARCH_KLDR,
+    /** Use the emulation closest to the host system. */
+    KLDRDYLD_SEARCH_HOST,
+    /** Emulate the OS/2 file search method.
+     * On non-OS/2 systems, BEGINLIBPATH, LIBPATH, ENDLIBPATH and LIBPATHSTRICT are
+     * taken form the environment. */
+    KLDRDYLD_SEARCH_OS2,
+    /** Emulate the standard window file search method. */
+    KLDRDYLD_SEARCH_WINDOWS,
+    /** Emulate the alternative window file search method. */
+    KLDRDYLD_SEARCH_WINDOWS_ALTERED,
+    /** Emulate the most common UNIX file search method. */
+    KLDRDYLD_SEARCH_UNIX_COMMON,
+    /** End of the valid file search method values. */
+    KLDRDYLD_SEARCH_END,
+    /** Hack to blow the type up to 32-bit. */
+    KLDRDYLD_SEARCH_32BIT_HACK = 0x7fffffff
+} KLDRDYLDSEARCH;
+
+/** @name kLdrDyldLoad and kLdrDyldFindByName flags.
+ * @{ */
+/** The symbols in the module should be loaded into the global unix namespace.
+ * If not specified, the symbols are local and can only be referenced directly. */
+#define KLDRYDLD_LOAD_FLAGS_GLOBAL_SYMBOLS      0x00000001
+/** The symbols in the module should be loaded into the global unix namespace and
+ * it's symbols should take precedence over all currently loaded modules.
+ * This implies KLDRYDLD_LOAD_FLAGS_GLOBAL_SYMBOLS. */
+#define KLDRYDLD_LOAD_FLAGS_DEEP_SYMBOLS        0x00000002
+/** The module shouldn't be found by a global module search.
+ * If not specified, the module can be found by unspecified module searches,
+ * typical used when loading import/dep modules. */
+#define KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE     0x00000004
+/** Do a recursive initialization calls instead of defering them to the outermost call. */
+#define KLDRDYLD_LOAD_FLAGS_RECURSIVE_INIT      0x00000008
+/** We're loading the executable module.
+ * @internal */
+#define KLDRDYLD_LOAD_FLAGS_EXECUTABLE          0x40000000
+/** @} */
+
+
+int     kLdrDyldLoad(const char *pszDll, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch,
+                     unsigned fFlags, PHKLDRMOD phMod, char *pszErr, KSIZE cchErr);
+int     kLdrDyldUnload(HKLDRMOD hMod);
+int     kLdrDyldFindByName(const char *pszDll, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch,
+                           unsigned fFlags, PHKLDRMOD phMod);
+int     kLdrDyldFindByAddress(KUPTR Address, PHKLDRMOD phMod, KU32 *piSegment, KUPTR *poffSegment);
+int     kLdrDyldGetName(HKLDRMOD hMod, char *pszName, KSIZE cchName);
+int     kLdrDyldGetFilename(HKLDRMOD hMod, char *pszFilename, KSIZE cchFilename);
+int     kLdrDyldQuerySymbol(HKLDRMOD hMod, KU32 uSymbolOrdinal, const char *pszSymbolName,
+                            const char *pszSymbolVersion, KUPTR *pValue, KU32 *pfKind);
+int     kLdrDyldQueryResource(HKLDRMOD hMod, KU32 idType, const char *pszType, KU32 idName,
+                              const char *pszName, KU32 idLang, void **pvRsrc, KSIZE *pcbRsrc);
+int     kLdrDyldEnumResources(HKLDRMOD hMod, KU32 idType, const char *pszType, KU32 idName,
+                              const char *pszName, KU32 idLang, PFNKLDRENUMRSRC pfnCallback, void *pvUser);
+
+
+/** @name OS/2 like API
+ * @{ */
+#if defined(__OS2__)
+# define KLDROS2API _System
+#else
+# define KLDROS2API
+#endif
+int     kLdrDosLoadModule(char *pszObject, KSIZE cbObject, const char *pszModule, PHKLDRMOD phMod);
+int     kLdrDosFreeModule(HKLDRMOD hMod);
+int     kLdrDosQueryModuleHandle(const char *pszModname, PHKLDRMOD phMod);
+int     kLdrDosQueryModuleName(HKLDRMOD hMod, KSIZE cchName, char *pszName);
+int     kLdrDosQueryProcAddr(HKLDRMOD hMod, KU32 iOrdinal, const char *pszProcName, void **ppvProcAddr);
+int     kLdrDosQueryProcType(HKLDRMOD hMod, KU32 iOrdinal, const char *pszProcName, KU32 *pfProcType);
+int     kLdrDosQueryModFromEIP(PHKLDRMOD phMod, KU32 *piObject, KSIZE cbName, char *pszName, KUPTR *poffObject, KUPTR ulEIP);
+int     kLdrDosReplaceModule(const char *pszOldModule, const char *pszNewModule, const char *pszBackupModule);
+int     kLdrDosGetResource(HKLDRMOD hMod, KU32 idType, KU32 idName, void **pvResAddr);
+int     kLdrDosQueryResourceSize(HKLDRMOD hMod, KU32 idType, KU32 idName, KU32 *pcb);
+int     kLdrDosFreeResource(void *pvResAddr);
+/** @} */
+
+/** @name POSIX like API
+ * @{ */
+HKLDRMOD    kLdrDlOpen(const char *pszLibrary, int fFlags);
+const char *kLdrDlError(void);
+void *      kLdrDlSym(HKLDRMOD hMod, const char *pszSymbol);
+int         kLdrDlClose(HKLDRMOD hMod);
+/** @todo GNU extensions */
+/** @} */
+
+/** @name Win32 like API
+ * @{ */
+#if defined(_MSC_VER)
+# define KLDRWINAPI __stdcall
+#else
+# define KLDRWINAPI
+#endif
+HKLDRMOD KLDRWINAPI kLdrWLoadLibrary(const char *pszFilename);
+HKLDRMOD KLDRWINAPI kLdrWLoadLibraryEx(const char *pszFilename, void *hFileReserved, KU32 fFlags);
+KU32     KLDRWINAPI kLdrWGetModuleFileName(HKLDRMOD hMod, char *pszModName, KSIZE cchModName);
+HKLDRMOD KLDRWINAPI kLdrWGetModuleHandle(const char *pszFilename);
+int      KLDRWINAPI kLdrWGetModuleHandleEx(KU32 fFlags, const char *pszFilename, HKLDRMOD hMod);
+void *   KLDRWINAPI kLdrWGetProcAddress(HKLDRMOD hMod, const char *pszProcName);
+KU32     KLDRWINAPI kLdrWGetDllDirectory(KSIZE cchDir, char *pszDir);
+int      KLDRWINAPI kLdrWSetDllDirectory(const char *pszDir);
+int      KLDRWINAPI kLdrWFreeLibrary(HKLDRMOD hMod);
+int      KLDRWINAPI kLdrWDisableThreadLibraryCalls(HKLDRMOD hMod);
+
+/** The handle to a resource that's been found. */
+typedef struct KLDRWRSRCFOUND *HKLDRWRSRCFOUND;
+/** The handle to a loaded resource. */
+typedef struct KLDRWRSRCLOADED *HKLDRWRSRCLOADED;
+HKLDRWRSRCFOUND  KLDRWINAPI kLdrWFindResource(HKLDRMOD hMod, const char *pszType, const char *pszName);
+HKLDRWRSRCFOUND  KLDRWINAPI kLdrWFindResourceEx(HKLDRMOD hMod, const char *pszType, const char *pszName, KU16 idLang);
+KU32             KLDRWINAPI kLdrWSizeofResource(HKLDRMOD hMod, HKLDRWRSRCFOUND hFoundRsrc);
+HKLDRWRSRCLOADED KLDRWINAPI kLdrWLoadResource(HKLDRMOD hMod, HKLDRWRSRCFOUND hFoundRsrc);
+void    *KLDRWINAPI kLdrWLockResource(HKLDRMOD hMod, HKLDRWRSRCLOADED hLoadedRsrc);
+int      KLDRWINAPI kLdrWFreeResource(HKLDRMOD hMod, HKLDRWRSRCLOADED hLoadedRsrc);
+
+typedef int (KLDRWINAPI *PFNKLDRWENUMRESTYPE)(HKLDRMOD hMod, const char *pszType, KUPTR uUser);
+int      KLDRWINAPI kLdrWEnumResourceTypes(HKLDRMOD hMod, PFNKLDRWENUMRESTYPE pfnEnum, KUPTR uUser);
+int      KLDRWINAPI kLdrWEnumResourceTypesEx(HKLDRMOD hMod, PFNKLDRWENUMRESTYPE pfnEnum, KUPTR uUser, KU32 fFlags, KU16 idLang);
+
+typedef int (KLDRWINAPI *PFNKLDRWENUMRESNAME)(HKLDRMOD hMod, const char *pszType, char *pszName, KUPTR uUser);
+int      KLDRWINAPI kLdrWEnumResourceNames(HKLDRMOD hMod, const char *pszType, PFNKLDRWENUMRESNAME pfnEnum, KUPTR uUser);
+int      KLDRWINAPI kLdrWEnumResourceNamesEx(HKLDRMOD hMod, const char *pszType, PFNKLDRWENUMRESNAME pfnEnum, KUPTR uUser, KU32 fFlags, KU16 idLang);
+
+typedef int (KLDRWINAPI *PFNKLDRWENUMRESLANG)(HKLDRMOD hMod, const char *pszType, const char *pszName, KU16 idLang, KUPTR uUser);
+int      KLDRWINAPI kLdrWEnumResourceLanguages(HKLDRMOD hMod, const char *pszType, const char *pszName, PFNKLDRWENUMRESLANG pfnEnum, KUPTR uUser);
+int      KLDRWINAPI kLdrWEnumResourceLanguagesEx(HKLDRMOD hMod, const char *pszType, const char *pszName,
+                                                 PFNKLDRWENUMRESLANG pfnEnum, KUPTR uUser, KU32 fFlags, KU16 idLang);
+/** @} */
+
+
+/** @name Process Bootstrapping
+ * @{ */
+
+/**
+ * Argument package from the stub.
+ */
+typedef struct KLDREXEARGS
+{
+    /** Load & search flags, some which will become defaults. */
+    KU32            fFlags;
+    /** The default search method. */
+    KLDRDYLDSEARCH  enmSearch;
+    /** The executable file that the stub is supposed to load. */
+    char            szExecutable[260];
+    /** The default prefix used when searching for DLLs. */
+    char            szDefPrefix[16];
+    /** The default suffix used when searching for DLLs. */
+    char            szDefSuffix[16];
+    /** The LD_LIBRARY_PATH prefix for the process.. */
+    char            szLibPath[4096 - sizeof(KU32) - sizeof(KLDRDYLDSEARCH) - 16 - 16 - 260];
+} KLDREXEARGS, *PKLDREXEARGS;
+/** Pointer to a const argument package from the stub. */
+typedef const KLDREXEARGS *PCKLDREXEARGS;
+
+void kLdrLoadExe(PCKLDREXEARGS pArgs, void *pvOS); /** @todo fix this mess... */
+void kLdrDyldLoadExe(PCKLDREXEARGS pArgs, void *pvOS);
+/** @} */
+
+/** @} */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/lib/kStuff/include/k/kLdrFmts/lx.h b/src/lib/kStuff/include/k/kLdrFmts/lx.h
new file mode 100644
index 0000000..fc1d1e2
--- /dev/null
+++ b/src/lib/kStuff/include/k/kLdrFmts/lx.h
@@ -0,0 +1,485 @@
+/* $Id $ */
+/** @file
+ * LX structures, types and defines.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kLdrFmts_lx_h___
+#define ___k_kLdrFmts_lx_h___
+
+#include <k/kDefs.h>
+#include <k/kTypes.h>
+
+
+#ifndef IMAGE_OS2_SIGNATURE_LX
+/** LX signature ("LX") */
+# define IMAGE_LX_SIGNATURE  K_LE2H_U16('L' | ('X' << 8))
+#endif
+
+#pragma pack(1)
+
+/**
+ * Linear eXecutable header.
+ * This structure is exactly 196 bytes long.
+ */
+struct e32_exe
+{
+    KU8                 e32_magic[2];
+    KU8                 e32_border;
+    KU8                 e32_worder;
+    KU32                e32_level;
+    KU16                e32_cpu;
+    KU16                e32_os;
+    KU32                e32_ver;
+    KU32                e32_mflags;
+    KU32                e32_mpages;
+    KU32                e32_startobj;
+    KU32                e32_eip;
+    KU32                e32_stackobj;
+    KU32                e32_esp;
+    KU32                e32_pagesize;
+    KU32                e32_pageshift;
+    /** The size of the fixup section.
+     * The fixup section consists of the fixup page table, the fixup record table,
+     * the import module table, and the import procedure name table.
+     */
+    KU32                e32_fixupsize;
+    KU32                e32_fixupsum;
+    /** The size of the resident loader section.
+     * This includes the object table, the object page map table, the resource table, the resident name table,
+     * the entry table, the module format directives table, and the page checksum table (?). */
+    KU32                e32_ldrsize;
+    /** The checksum of the loader section. 0 if not calculated. */
+    KU32                e32_ldrsum;
+    /** The offset of the object table relative to this structure. */
+    KU32                e32_objtab;
+    /** Count of objects. */
+    KU32                e32_objcnt;
+    /** The offset of the object page map table relative to this structure. */
+    KU32                e32_objmap;
+    /** The offset of the object iterated pages (whatever this is used for) relative to the start of the file. */
+    KU32                e32_itermap;
+    /** The offset of the resource table relative to this structure. */
+    KU32                e32_rsrctab;
+    /** The number of entries in the resource table. */
+    KU32                e32_rsrccnt;
+    /** The offset of the resident name table relative to this structure. */
+    KU32                e32_restab;
+    /** The offset of the entry (export) table relative to this structure. */
+    KU32                e32_enttab;
+    /** The offset of the module format directives table relative to this structure. */
+    KU32                e32_dirtab;
+    /** The number of entries in the module format directives table. */
+    KU32                e32_dircnt;
+    /** The offset of the fixup page table relative to this structure. */
+    KU32                e32_fpagetab;
+    /** The offset of the fixup record table relative to this structure. */
+    KU32                e32_frectab;
+    /** The offset of the import module name table relative to this structure. */
+    KU32                e32_impmod;
+    /** The number of entries in the import module name table. */
+    KU32                e32_impmodcnt;
+    /** The offset of the import procedure name table relative to this structure. */
+    KU32                e32_impproc;
+    /** The offset of the page checksum table relative to this structure. */
+    KU32                e32_pagesum;
+    /** The offset of the data pages relative to the start of the file. */
+    KU32                e32_datapage;
+    /** The number of preload pages (ignored). */
+    KU32                e32_preload;
+    /** The offset of the non-resident name table relative to the start of the file. */
+    KU32                e32_nrestab;
+    /** The size of the non-resident name table. */
+    KU32                e32_cbnrestab;
+    KU32                e32_nressum;
+    KU32                e32_autodata;
+    KU32                e32_debuginfo;
+    KU32                e32_debuglen;
+    KU32                e32_instpreload;
+    KU32                e32_instdemand;
+    KU32                e32_heapsize;
+    KU32                e32_stacksize;
+    KU8                 e32_res3[20];
+};
+
+/** e32_magic[0] */
+#define E32MAGIC1       'L'
+/** e32_magic[1] */
+#define E32MAGIC2       'X'
+/** MAKEWORD(e32_magic[0], e32_magic[1]) */
+#define E32MAGIC        0x584c
+/** e32_border - little endian */
+#define E32LEBO         0
+/** e32_border - big endian */
+#define E32BEBO         1
+/** e32_worder - little endian */
+#define E32LEWO         0
+/** e32_worder - big endian */
+#define E32BEWO         1
+/** e32_level */
+#define E32LEVEL        KU32_C(0)
+/** e32_cpu - 80286 */
+#define E32CPU286       1
+/** e32_cpu - 80386 */
+#define E32CPU386       2
+/** e32_cpu - 80486 */
+#define E32CPU486       3
+/** e32_pagesize */
+#define OBJPAGELEN      KU32_C(0x1000)
+
+
+/** @name e32_mflags
+ * @{ */
+/** App Type: Fullscreen only. */
+#define E32NOPMW         KU32_C(0x00000100)
+/** App Type: PM API. */
+#define E32PMAPI         KU32_C(0x00000300)
+/** App Type: PM VIO compatible. */
+#define E32PMW           KU32_C(0x00000200)
+/** Application type mask. */
+#define E32APPMASK       KU32_C(0x00000300)
+/** Executable module. */
+#define E32MODEXE        KU32_C(0x00000000)
+/** Dynamic link library (DLL / library) module. */
+#define E32MODDLL        KU32_C(0x00008000)
+/** Protected memory DLL. */
+#define E32PROTDLL       KU32_C(0x00010000)
+/** Physical Device Driver. */
+#define E32MODPDEV       KU32_C(0x00020000)
+/** Virtual Device Driver. */
+#define E32MODVDEV       KU32_C(0x00028000)
+/** Device driver */
+#define E32DEVICE        E32MODPDEV
+/** Dynamic link library (DLL / library) module. */
+#define E32NOTP          E32MODDLL
+/** Protected memory DLL. */
+#define E32MODPROTDLL    (E32MODDLL | E32PROTDLL)
+/** Module Type mask. */
+#define E32MODMASK       KU32_C(0x00038000)
+/** Not loadable (linker error). */
+#define E32NOLOAD        KU32_C(0x00002000)
+/** No internal fixups. */
+#define E32NOINTFIX      KU32_C(0x00000010)
+/** No external fixups (i.e. imports). */
+#define E32NOEXTFIX      KU32_C(0x00000020)
+/** System DLL, no internal fixups. */
+#define E32SYSDLL        KU32_C(0x00000008)
+/** Global (set) or per instance (cleared) library initialization. */
+#define E32LIBINIT       KU32_C(0x00000004)
+/** Global (set) or per instance (cleared) library termination. */
+#define E32LIBTERM       KU32_C(0x40000000)
+/** Indicates when set in an executable that the process isn't SMP safe. */
+#define E32NOTMPSAFE     KU32_C(0x00080000)
+/** @} */
+
+/** @name Relocations (aka Fixups).
+ * @{ */
+typedef union _offset
+{
+    KU16                offset16;
+    KU32                offset32;
+} offset;
+
+/** A relocation.
+ * @remark this structure isn't very usable since LX relocations comes in too many size variations.
+ */
+struct r32_rlc
+{
+    KU8                 nr_stype;
+    KU8                 nr_flags;
+    KI16                r32_soff;
+    KU16                r32_objmod;
+
+    union targetid
+    {
+        offset          intref;
+        union extfixup
+        {
+            offset      proc;
+            KU32        ord;
+        } extref;
+        struct addfixup
+        {
+            KU16        entry;
+            offset      addval;
+        } addfix;
+    } r32_target;
+    KU16                r32_srccount;
+    KU16                r32_chain;
+};
+
+/** @name Some attempt at size constanstants.
+ * @{
+ */
+#define RINTSIZE16      8
+#define RINTSIZE32      10
+#define RORDSIZE        8
+#define RNAMSIZE16      8
+#define RNAMSIZE32      10
+#define RADDSIZE16      10
+#define RADDSIZE32      12
+/** @} */
+
+/** @name nr_stype (source flags)
+ * @{ */
+#define NRSBYT          0x00
+#define NRSSEG          0x02
+#define NRSPTR          0x03
+#define NRSOFF          0x05
+#define NRPTR48         0x06
+#define NROFF32         0x07
+#define NRSOFF32        0x08
+#define NRSTYP          0x0f
+#define NRSRCMASK       0x0f
+#define NRALIAS         0x10
+#define NRCHAIN         0x20
+/** @} */
+
+/** @name nr_flags (target flags)
+ * @{ */
+#define NRRINT          0x00
+#define NRRORD          0x01
+#define NRRNAM          0x02
+#define NRRENT          0x03
+#define NRRTYP          0x03
+#define NRADD           0x04
+#define NRICHAIN        0x08
+#define NR32BITOFF      0x10
+#define NR32BITADD      0x20
+#define NR16OBJMOD      0x40
+#define NR8BITORD       0x80
+/** @} */
+
+/** @} */
+
+
+/** @name The Object Table (aka segment table)
+ * @{ */
+
+/** The Object Table Entry. */
+struct o32_obj
+{
+    /** The size of the object. */
+    KU32                o32_size;
+    /** The base address of the object. */
+    KU32                o32_base;
+    /** Object flags. */
+    KU32                o32_flags;
+    /** Page map index. */
+    KU32                o32_pagemap;
+    /** Page map size. (doesn't need to be o32_size >> page shift). */
+    KU32                o32_mapsize;
+    /** Reserved */
+    KU32                o32_reserved;
+};
+
+/** @name o32_flags
+ * @{ */
+/** Read access. */
+#define OBJREAD         KU32_C(0x00000001)
+/** Write access. */
+#define OBJWRITE        KU32_C(0x00000002)
+/** Execute access. */
+#define OBJEXEC         KU32_C(0x00000004)
+/** Resource object. */
+#define OBJRSRC         KU32_C(0x00000008)
+/** The object is discarable (i.e. don't swap, just load in pages from the executable).
+ * This overlaps a bit with object type. */
+#define OBJDISCARD      KU32_C(0x00000010)
+/** The object is shared. */
+#define OBJSHARED       KU32_C(0x00000020)
+/** The object has preload pages. */
+#define OBJPRELOAD      KU32_C(0x00000040)
+/** The object has invalid pages. */
+#define OBJINVALID      KU32_C(0x00000080)
+/** Non-permanent, link386 bug. */
+#define LNKNONPERM      KU32_C(0x00000600)
+/** Non-permanent, correct 'value'. */
+#define OBJNONPERM      KU32_C(0x00000000)
+/** Obj Type: The object is permanent and swappable. */
+#define OBJPERM         KU32_C(0x00000100)
+/** Obj Type: The object is permanent and resident (i.e. not swappable). */
+#define OBJRESIDENT     KU32_C(0x00000200)
+/** Obj Type: The object is resident and contigious. */
+#define OBJCONTIG       KU32_C(0x00000300)
+/** Obj Type: The object is permanent and long locable. */
+#define OBJDYNAMIC      KU32_C(0x00000400)
+/** Object type mask. */
+#define OBJTYPEMASK     KU32_C(0x00000700)
+/** x86: The object require an 16:16 alias. */
+#define OBJALIAS16      KU32_C(0x00001000)
+/** x86: Big/Default selector setting, i.e. toggle 32-bit or 16-bit. */
+#define OBJBIGDEF       KU32_C(0x00002000)
+/** x86: conforming selector setting (weird stuff). */
+#define OBJCONFORM      KU32_C(0x00004000)
+/** x86: IOPL. */
+#define OBJIOPL         KU32_C(0x00008000)
+/** @} */
+
+/** A Object Page Map Entry. */
+struct o32_map
+{
+    /** The file offset of the page. */
+    KU32                o32_pagedataoffset;
+    /** The number of bytes of raw page data. */
+    KU16                o32_pagesize;
+    /** Per page flags describing how the page is encoded in the file. */
+    KU16                o32_pageflags;
+};
+
+/** @name o32 o32_pageflags
+ * @{
+ */
+/** Raw page (uncompressed) in the file. */
+#define VALID           KU16_C(0x0000)
+/** RLE encoded page in file. */
+#define ITERDATA        KU16_C(0x0001)
+/** Invalid page, nothing in the file. */
+#define INVALID         KU16_C(0x0002)
+/** Zero page, nothing in file. */
+#define ZEROED          KU16_C(0x0003)
+/** range of pages (what is this?) */
+#define RANGE           KU16_C(0x0004)
+/** Compressed page in file. */
+#define ITERDATA2       KU16_C(0x0005)
+/** @} */
+
+
+/** Iteration Record format (RLE compressed page). */
+struct LX_Iter
+{
+    /** Number of iterations. */
+    KU16                LX_nIter;
+    /** The number of bytes that's being iterated. */
+    KU16                LX_nBytes;
+    /** The bytes. */
+    KU8                 LX_Iterdata;
+};
+
+/** @} */
+
+
+/** A Resource Table Entry */
+struct rsrc32
+{
+    /** Resource Type. */
+    KU16                type;
+    /** Resource ID. */
+    KU16                name;
+    /** Resource size in bytes. */
+    KU32                cb;
+    /** The index of the object containing the resource. */
+    KU16                obj;
+    /** Offset of the resource that within the object. */
+    KU32                offset;
+};
+
+
+/** @name The Entry Table (aka Export Table)
+ * @{ */
+
+/** Entry bundle.
+ * Header descripting up to 255 entries that follows immediatly after this structure. */
+struct b32_bundle
+{
+    /** The number of entries. */
+    KU8                 b32_cnt;
+    /** The type of bundle. */
+    KU8                 b32_type;
+    /** The index of the object containing these entry points. */
+    KU16                b32_obj;
+};
+
+/** @name b32_type
+ * @{ */
+/** Empty bundle, filling up unused ranges of ordinals. */
+#define EMPTY           0x00
+/** 16-bit offset entry point. */
+#define ENTRY16         0x01
+/** 16-bit callgate entry point. */
+#define GATE16          0x02
+/** 32-bit offset entry point. */
+#define ENTRY32         0x03
+/** Forwarder entry point. */
+#define ENTRYFWD        0x04
+/** Typing information present indicator. */
+#define TYPEINFO        0x80
+/** @} */
+
+
+/** Entry point. */
+struct e32_entry
+{
+    /** Entry point flags */
+    KU8                 e32_flags;      /* Entry point flags */
+    union entrykind
+    {
+        /** ENTRY16 or ENTRY32. */
+        offset          e32_offset;
+        /** GATE16 */
+        struct callgate
+        {
+            /** Offset into segment. */
+            KU16        offset;
+            /** The callgate selector */
+            KU16        callgate;
+        } e32_callgate;
+        /** ENTRYFWD */
+        struct fwd
+        {
+            /** Module ordinal number (i.e. into the import module table). */
+            KU16        modord;
+            /** Procedure name or ordinal number. */
+            KU32        value;
+        } e32_fwd;
+    } e32_variant;
+};
+
+/** @name e32_flags
+ * @{ */
+/** Exported entry (set) or private entry (clear). */
+#define E32EXPORT       0x01
+/** Uses shared data. */
+#define E32SHARED       0x02
+/** Parameter word count mask. */
+#define E32PARAMS       0xf8
+/** ENTRYFWD: Imported by ordinal (set) or by name (clear). */
+#define FWD_ORDINAL     0x01
+/** @} */
+
+/** @name dunno
+ * @{ */
+#define FIXENT16        3
+#define FIXENT32        5
+#define GATEENT16       5
+#define FWDENT          7
+/** @} */
+
+#pragma pack()
+
+#endif
+
diff --git a/src/lib/kStuff/include/k/kLdrFmts/mach-o.h b/src/lib/kStuff/include/k/kLdrFmts/mach-o.h
new file mode 100644
index 0000000..61f908c
--- /dev/null
+++ b/src/lib/kStuff/include/k/kLdrFmts/mach-o.h
@@ -0,0 +1,997 @@
+/* $Id: mach-o.h 63 2013-10-30 02:00:14Z bird $ */
+/** @file
+ * Mach-0 structures, types and defines.
+ */
+
+/*
+ * Copyright (c) 2006-2012 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kLdrFmts_mach_o_h___
+#define ___k_kLdrFmts_mach_o_h___
+
+#include <k/kDefs.h>
+#include <k/kTypes.h>
+
+
+/** @defgroup grp_mach_o    The Mach-O Structures, Types, and Defines.
+ * @{
+ */
+
+
+#ifndef IMAGE_FAT_SIGNATURE
+/** The FAT signature (universal binaries). */
+# define IMAGE_FAT_SIGNATURE            KU32_C(0xcafebabe)
+#endif
+#ifndef IMAGE_FAT_SIGNATURE_OE
+/** The FAT signature (universal binaries), other endian. */
+# define IMAGE_FAT_SIGNATURE_OE         KU32_C(0xbebafeca)
+#endif
+
+/**
+ * The fat header found at the start of universal binaries.
+ * It is followed by \a nfat_arch numbers of \a fat_arch structures.
+ */
+typedef struct fat_header
+{
+    KU32            magic;
+    KU32            nfat_arch;
+} fat_header_t;
+
+/**
+ * Description of fat file item.
+ */
+typedef struct fat_arch
+{
+    KI32            cputype;
+    KI32            cpusubtype;
+    KU32            offset;
+    KU32            size;
+    KU32            align;          /**< Power of 2. */
+} fat_arch_t;
+
+
+
+#ifndef IMAGE_MACHO32_SIGNATURE
+/** The 32-bit Mach-O signature. */
+# define IMAGE_MACHO32_SIGNATURE        KU32_C(0xfeedface)
+#endif
+#ifndef IMAGE_MACHO32_SIGNATURE_OE
+/** The 32-bit Mach-O signature, other endian. */
+# define IMAGE_MACHO32_SIGNATURE_OE     KU32_C(0xcefaedfe)
+#endif
+#define MH_MAGIC    IMAGE_MACHO32_SIGNATURE
+#define MH_CIGAM    IMAGE_MACHO32_SIGNATURE_OE
+
+/**
+ * 32-bit Mach-O header.
+ * This is followed by \a ncmds number of load commands.
+ * @see mach_header_64
+ */
+typedef struct mach_header_32
+{
+    KU32            magic;
+    KI32            cputype;
+    KI32            cpusubtype;
+    KU32            filetype;
+    KU32            ncmds;
+    KU32            sizeofcmds;
+    KU32            flags;
+} mach_header_32_t;
+
+
+
+#ifndef IMAGE_MACHO64_SIGNATURE
+/** The 64-bit Mach-O signature. */
+# define IMAGE_MACHO64_SIGNATURE        KU32_C(0xfeedfacf)
+#endif
+#ifndef IMAGE_MACHO64_SIGNATURE_OE
+/** The 64-bit Mach-O signature, other endian. */
+# define IMAGE_MACHO64_SIGNATURE_OE     KU32_C(0xfefaedfe)
+#endif
+#define MH_MAGIC_64 IMAGE_MACHO64_SIGNATURE
+#define MH_CIGAM_64 IMAGE_MACHO64_SIGNATURE_OE
+
+/**
+ * 64-bit Mach-O header.
+ * This is followed by \a ncmds number of load commands.
+ * @see mach_header
+ */
+typedef struct mach_header_64
+{
+    KU32            magic;
+    KI32            cputype;
+    KI32            cpusubtype;
+    KU32            filetype;
+    KU32            ncmds;
+    KU32            sizeofcmds;
+    KU32            flags;
+    KU32            reserved;       /**< (for proper struct and command alignment I guess) */
+} mach_header_64_t;
+
+
+/** @name File types (mach_header_64::filetype, mach_header_32::filetype)
+ * @{
+ */
+#define MH_OBJECT           KU32_C(1) /**< Object (relocatable). */
+#define MH_EXECUTE          KU32_C(2) /**< Executable (demand paged). */
+#define MH_FVMLIB           KU32_C(3) /**< Fixed VM shared library. */
+#define MH_CORE             KU32_C(4) /**< Core file. */
+#define MH_PRELOAD          KU32_C(5) /**< Preloaded executable. */
+#define MH_DYLIB            KU32_C(6) /**< Dynamically bound shared library. */
+#define MH_DYLINKER         KU32_C(7) /**< Dynamic linker. */
+#define MH_BUNDLE           KU32_C(8) /**< Dymamically bound bundle. */
+#define MH_DYLIB_STUB       KU32_C(9) /**< Shared library stub for static linking. */
+#define MH_DSYM             KU32_C(10)/**< Debug symbols. */
+#define MH_KEXT_BUNDLE      KU32_C(11)/**< Kernel extension (introduced with the AMD64 kernel). */
+
+/** @} */
+
+
+/** @name Mach-O Header flags (mach_header_64::flags, mach_header_32::flags)
+ * @{
+ */
+#define MH_NOUNDEFS                 KU32_C(0x00000001) /**< No undefined symbols. */
+#define MH_INCRLINK                 KU32_C(0x00000002) /**< Partial increment link output. */
+#define MH_DYLDLINK                 KU32_C(0x00000004) /**< Food for the dynamic linker, not for ld. */
+#define MH_BINDATLOAD               KU32_C(0x00000008) /**< Bind all undefined symbols at load time. */
+#define MH_PREBOUND                 KU32_C(0x00000010) /**< Contains prebound undefined symbols. */
+#define MH_SPLIT_SEGS               KU32_C(0x00000020) /**< Read-only and read-write segments are split. */
+#define MH_LAZY_INIT                KU32_C(0x00000040) /**< Obsolete flag for doing lazy init when data is written. */
+#define MH_TWOLEVEL                 KU32_C(0x00000080) /**< Uses two-level name space bindings. */
+#define MH_FORCE_FLAT               KU32_C(0x00000100) /**< Task: The executable forces all images to use flat name space bindings. */
+#define MH_NOMULTIDEFS              KU32_C(0x00000200) /**< No multiple symbol definitions, safe to use two-level namespace hints. */
+#define MH_NOFIXPREBINDING          KU32_C(0x00000400) /**< The dynamic linker should not notify the prebinding agent about this executable. */
+#define MH_PREBINDABLE              KU32_C(0x00000800) /**< Not prebound, but it can be. Invalid if MH_PREBOUND is set. */
+#define MH_ALLMODSBOUND             KU32_C(0x00001000) /**< Binds to all two-level namespace modules of preqs. Requires MH_PREBINDABLE and MH_TWOLEVEL to be set. */
+#define MH_SUBSECTIONS_VIA_SYMBOLS  KU32_C(0x00002000) /**< Safe to divide sections into sub-sections via symbols for dead code stripping. */
+#define MH_CANONICAL                KU32_C(0x00004000) /**< Canonicalized via unprebind. */
+#define MH_WEAK_DEFINES             KU32_C(0x00008000) /**< The (finally) linked image has weak symbols. */
+#define MH_BINDS_TO_WEAK            KU32_C(0x00010000) /**< The (finally) linked image uses weak symbols. */
+#define MH_ALLOW_STACK_EXECUTION    KU32_C(0x00020000) /**< Task: allow stack execution. (MH_EXECUTE only) */
+#define MH_ROOT_SAFE                KU32_C(0x00040000) /**< Binary safe for root execution. */
+#define MH_SETUID_SAFE              KU32_C(0x00080000) /**< Binary safe for set-uid execution. */
+#define MH_NO_REEXPORTED_DYLIBS     KU32_C(0x00100000) /**< No reexported dylibs. */
+#define MH_PIE                      KU32_C(0x00200000) /**< Address space randomization. (MH_EXECUTE only) */
+#define MH_DEAD_STRIPPABLE_DYLIB    KU32_C(0x00400000) /**< Drop dylib dependency if not used. (MH_DYLIB only) */
+#define MH_HAS_TLV_DESCRIPTORS      KU32_C(0x00800000) /**< Has a S_TRHEAD_LOCAL_VARIABLES section.  TLS support. */
+#define MH_NO_HEAP_EXECUTION        KU32_C(0x01000000) /**< Task: no heap execution. (MH_EXECUTE only) */
+#define MH_VALID_FLAGS              KU32_C(0x01ffffff) /**< Mask containing the defined flags. */
+/** @} */
+
+
+/** @name CPU types / bits (mach_header_64::cputype, mach_header_32::cputype, fat_arch::cputype)
+ * @{
+ */
+#define CPU_ARCH_MASK               KI32_C(0xff000000)
+#define CPU_ARCH_ABI64              KI32_C(0x01000000)
+#define CPU_TYPE_ANY                KI32_C(-1)
+#define CPU_TYPE_VAX                KI32_C(1)
+#define CPU_TYPE_MC680x0            KI32_C(6)
+#define CPU_TYPE_X86                KI32_C(7)
+#define CPU_TYPE_I386               CPU_TYPE_X86
+#define CPU_TYPE_X86_64             (CPU_TYPE_X86 | CPU_ARCH_ABI64)
+#define CPU_TYPE_MC98000            KI32_C(10)
+#define CPU_TYPE_HPPA               KI32_C(11)
+#define CPU_TYPE_MC88000            KI32_C(13)
+#define CPU_TYPE_SPARC              KI32_C(14)
+#define CPU_TYPE_I860               KI32_C(15)
+#define CPU_TYPE_POWERPC            KI32_C(18)
+#define CPU_TYPE_POWERPC64          (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
+/** @} */
+
+
+/** @name CPU subtypes (mach_header_64::cpusubtype, mach_header_32::cpusubtype, fat_arch::cpusubtype)
+ * @{ */
+#define CPU_SUBTYPE_MULTIPLE        KI32_C(-1)
+#define CPU_SUBTYPE_LITTLE_ENDIAN   KI32_C(0)  /**< figure this one out. */
+#define CPU_SUBTYPE_BIG_ENDIAN      KI32_C(1)  /**< ditto */
+
+/* VAX */
+#define CPU_SUBTYPE_VAX_ALL         KI32_C(0)
+#define CPU_SUBTYPE_VAX780          KI32_C(1)
+#define CPU_SUBTYPE_VAX785          KI32_C(2)
+#define CPU_SUBTYPE_VAX750          KI32_C(3)
+#define CPU_SUBTYPE_VAX730          KI32_C(4)
+#define CPU_SUBTYPE_UVAXI           KI32_C(5)
+#define CPU_SUBTYPE_UVAXII          KI32_C(6)
+#define CPU_SUBTYPE_VAX8200         KI32_C(7)
+#define CPU_SUBTYPE_VAX8500         KI32_C(8)
+#define CPU_SUBTYPE_VAX8600         KI32_C(9)
+#define CPU_SUBTYPE_VAX8650         KI32_C(10)
+#define CPU_SUBTYPE_VAX8800         KI32_C(11)
+#define CPU_SUBTYPE_UVAXIII         KI32_C(12)
+
+/* MC680xx */
+#define CPU_SUBTYPE_MC680x0_ALL     KI32_C(1)
+#define CPU_SUBTYPE_MC68030         KI32_C(1)
+#define CPU_SUBTYPE_MC68040         KI32_C(2)
+#define CPU_SUBTYPE_MC68030_ONLY    KI32_C(3)
+
+/* I386 */
+#define CPU_SUBTYPE_INTEL(fam, model)       ( (KI32)(((model) << 4) | (fam)) )
+#define CPU_SUBTYPE_INTEL_FAMILY(subtype)   ( (subtype) & 0xf )
+#define CPU_SUBTYPE_INTEL_MODEL(subtype)    ( (subtype) >> 4 )
+#define CPU_SUBTYPE_INTEL_FAMILY_MAX        0xf
+#define CPU_SUBTYPE_INTEL_MODEL_ALL         0
+
+#define CPU_SUBTYPE_I386_ALL        CPU_SUBTYPE_INTEL(3, 0)
+#define CPU_SUBTYPE_386             CPU_SUBTYPE_INTEL(3, 0)
+#define CPU_SUBTYPE_486             CPU_SUBTYPE_INTEL(4, 0)
+#define CPU_SUBTYPE_486SX           CPU_SUBTYPE_INTEL(4, 8)
+#define CPU_SUBTYPE_586             CPU_SUBTYPE_INTEL(5, 0)
+#define CPU_SUBTYPE_PENT            CPU_SUBTYPE_INTEL(5, 0)
+#define CPU_SUBTYPE_PENTPRO         CPU_SUBTYPE_INTEL(6, 1)
+#define CPU_SUBTYPE_PENTII_M3       CPU_SUBTYPE_INTEL(6, 3)
+#define CPU_SUBTYPE_PENTII_M5       CPU_SUBTYPE_INTEL(6, 5)
+#define CPU_SUBTYPE_CELERON         CPU_SUBTYPE_INTEL(7, 6)
+#define CPU_SUBTYPE_CELERON_MOBILE  CPU_SUBTYPE_INTEL(7, 7)
+#define CPU_SUBTYPE_PENTIUM_3       CPU_SUBTYPE_INTEL(8, 0)
+#define CPU_SUBTYPE_PENTIUM_3_M     CPU_SUBTYPE_INTEL(8, 1)
+#define CPU_SUBTYPE_PENTIUM_3_XEON  CPU_SUBTYPE_INTEL(8, 2)
+#define CPU_SUBTYPE_PENTIUM_M       CPU_SUBTYPE_INTEL(9, 0)
+#define CPU_SUBTYPE_PENTIUM_4       CPU_SUBTYPE_INTEL(10, 0)
+#define CPU_SUBTYPE_PENTIUM_4_M     CPU_SUBTYPE_INTEL(10, 1)
+#define CPU_SUBTYPE_ITANIUM         CPU_SUBTYPE_INTEL(11, 0)
+#define CPU_SUBTYPE_ITANIUM_2       CPU_SUBTYPE_INTEL(11, 1)
+#define CPU_SUBTYPE_XEON            CPU_SUBTYPE_INTEL(12, 0)
+#define CPU_SUBTYPE_XEON_MP         CPU_SUBTYPE_INTEL(12, 1)
+
+/* X86 */
+#define CPU_SUBTYPE_X86_ALL         KI32_C(3) /* CPU_SUBTYPE_I386_ALL */
+#define CPU_SUBTYPE_X86_64_ALL      KI32_C(3) /* CPU_SUBTYPE_I386_ALL */
+#define CPU_SUBTYPE_X86_ARCH1       KI32_C(4) /* CPU_SUBTYPE_I486_ALL */
+
+/* MIPS */
+#define CPU_SUBTYPE_MIPS_ALL        KI32_C(0)
+#define CPU_SUBTYPE_MIPS_R2300      KI32_C(1)
+#define CPU_SUBTYPE_MIPS_R2600      KI32_C(2)
+#define CPU_SUBTYPE_MIPS_R2800      KI32_C(3)
+#define CPU_SUBTYPE_MIPS_R2000a     KI32_C(4)
+#define CPU_SUBTYPE_MIPS_R2000      KI32_C(5)
+#define CPU_SUBTYPE_MIPS_R3000a     KI32_C(6)
+#define CPU_SUBTYPE_MIPS_R3000      KI32_C(7)
+
+/* MC98000 (PowerPC) */
+#define CPU_SUBTYPE_MC98000_ALL     KI32_C(0)
+#define CPU_SUBTYPE_MC98601         KI32_C(1)
+
+/* HP-PA */
+#define CPU_SUBTYPE_HPPA_ALL        KI32_C(0)
+#define CPU_SUBTYPE_HPPA_7100       KI32_C(0)
+#define CPU_SUBTYPE_HPPA_7100LC     KI32_C(1)
+
+/* MC88000 */
+#define CPU_SUBTYPE_MC88000_ALL     KI32_C(0)
+#define CPU_SUBTYPE_MC88100         KI32_C(1)
+#define CPU_SUBTYPE_MC88110         KI32_C(2)
+
+/* SPARC */
+#define CPU_SUBTYPE_SPARC_ALL       KI32_C(0)
+
+/* I860 */
+#define CPU_SUBTYPE_I860_ALL        KI32_C(0)
+#define CPU_SUBTYPE_I860_860        KI32_C(1)
+
+/* PowerPC */
+#define CPU_SUBTYPE_POWERPC_ALL     KI32_C(0)
+#define CPU_SUBTYPE_POWERPC_601     KI32_C(1)
+#define CPU_SUBTYPE_POWERPC_602     KI32_C(2)
+#define CPU_SUBTYPE_POWERPC_603     KI32_C(3)
+#define CPU_SUBTYPE_POWERPC_603e    KI32_C(4)
+#define CPU_SUBTYPE_POWERPC_603ev   KI32_C(5)
+#define CPU_SUBTYPE_POWERPC_604     KI32_C(6)
+#define CPU_SUBTYPE_POWERPC_604e    KI32_C(7)
+#define CPU_SUBTYPE_POWERPC_620     KI32_C(8)
+#define CPU_SUBTYPE_POWERPC_750     KI32_C(9)
+#define CPU_SUBTYPE_POWERPC_7400    KI32_C(10)
+#define CPU_SUBTYPE_POWERPC_7450    KI32_C(11)
+#define CPU_SUBTYPE_POWERPC_Max     KI32_C(10)
+#define CPU_SUBTYPE_POWERPC_SCVger  KI32_C(11)
+#define CPU_SUBTYPE_POWERPC_970     KI32_C(100)
+
+/* Subtype capability / feature bits, added in 10.5. X86 only? */
+#define CPU_SUBTYPE_MASK            KU32_C(0xff000000)
+#define CPU_SUBTYPE_LIB64           KU32_C(0x8000000)
+
+/** @} */
+
+
+
+/** @defgroup grp_macho_o_lc        Load Commands
+ * @{ */
+
+/**
+ * The load command common core structure.
+ *
+ * After the Mach-O header follows an array of variable sized
+ * load command which all has this header in common.
+ */
+typedef struct load_command
+{
+    KU32            cmd;            /**< The load command id. */
+    KU32            cmdsize;        /**< The size of the command (including this header). */
+} load_command_t;
+
+/** @name Load Command IDs (load_command::cmd)
+ * @{
+ */
+/** Flag that when set requires the dynamic linker to fail if it doesn't
+ * grok the command. The dynamic linker will otherwise ignore commands it
+ * doesn't understand. Introduced with Mac OS X 10.1. */
+#define LC_REQ_DYLD         KU32_C(0x80000000)
+
+#define LC_SEGMENT_32       KU32_C(0x01)  /**< Segment to be mapped (32-bit). See segment_command_32. */
+#define LC_SYMTAB           KU32_C(0x02)  /**< 'stab' symbol table. See symtab_command. */
+#define LC_SYMSEG           KU32_C(0x03)  /**< Obsoleted gdb symbol table. */
+#define LC_THREAD           KU32_C(0x04)  /**< Thread. See thread_command. */
+#define LC_UNIXTHREAD       KU32_C(0x05)  /**< Unix thread (includes stack and stuff). See thread_command. */
+#define LC_LOADFVMLIB       KU32_C(0x06)  /**< Load a specified fixed VM shared library  (obsolete?). See fvmlib_command. */
+#define LC_IDFVMLIB         KU32_C(0x07)  /**< Fixed VM shared library id (obsolete?). See fvmlib_command. */
+#define LC_IDENT            KU32_C(0x08)  /**< Identification info (obsolete). See ident_command. */
+#define LC_FVMFILE          KU32_C(0x09)  /**< Fixed VM file inclusion (internal). See fvmfile_command. */
+#define LC_PREPAGE          KU32_C(0x0a)  /**< Prepage command (internal). See ?? */
+#define LC_DYSYMTAB         KU32_C(0x0b)  /**< Symbol table for dynamic linking. See dysymtab_command. */
+#define LC_LOAD_DYLIB       KU32_C(0x0c)  /**< Load a dynamically linked shared library. See dylib_command. */
+#define LC_ID_DYLIB         KU32_C(0x0d)  /**< Dynamically linked share library ident. See dylib_command. */
+#define LC_LOAD_DYLINKER    KU32_C(0x0e)  /**< Load a dynamical link editor. See dylinker_command. */
+#define LC_ID_DYLINKER      KU32_C(0x0f)  /**< Dynamic link editor ident. See dylinker_command. */
+#define LC_PREBOUND_DYLIB   KU32_C(0x10)  /**< Prebound modules for dynamically linking of a shared lib. See prebound_dylib_command. */
+#define LC_ROUTINES         KU32_C(0x11)  /**< Image routines. See routines_command_32. */
+#define LC_SUB_FRAMEWORK    KU32_C(0x12)  /**< Sub framework. See sub_framework_command. */
+#define LC_SUB_UMBRELLA     KU32_C(0x13)  /**< Sub umbrella. See sub_umbrella_command. */
+#define LC_SUB_CLIENT       KU32_C(0x14)  /**< Sub client. See sub_client_command. */
+#define LC_SUB_LIBRARY      KU32_C(0x15)  /**< Sub library. See sub_library_command. */
+#define LC_TWOLEVEL_HINTS   KU32_C(0x16)  /**< Two-level namespace lookup hints. See twolevel_hints_command. */
+#define LC_PREBIND_CKSUM    KU32_C(0x17)  /**< Prebind checksum. See prebind_cksum_command. */
+#define LC_LOAD_WEAK_DYLIB (KU32_C(0x18) | LC_REQ_DYLD) /**< Dylib that can be missing, all symbols weak. See dylib_command. */
+#define LC_SEGMENT_64       KU32_C(0x19)  /**< segment to be mapped (64-bit). See segment_command_32. */
+#define LC_ROUTINES_64      KU32_C(0x1a)  /**< Image routines (64-bit). See routines_command_32. */
+#define LC_UUID             KU32_C(0x1b)  /**< The UUID of the object module. See uuid_command.  */
+#define LC_RPATH           (KU32_C(0x1c) | LC_REQ_DYLD) /**< Runpth additions. See rpath_command. */
+#define LC_CODE_SIGNATURE   KU32_C(0x1d)  /**< Code signature location. See linkedit_data_command. */
+#define LC_SEGMENT_SPLIT_INFO KU32_C(0x1e)/**< Segment split info location. See linkedit_data_command. */
+#define LC_REEXPORT_DYLIB  (KU32_C(0x1f) | LC_REQ_DYLD)/**< Load and re-export the given dylib - DLL forwarding. See dylib_command. */
+#define LC_LAZY_LOAD_DYLIB  KU32_C(0x20)  /**< Delays loading of the given dylib until used. See dylib_command? */
+#define LC_ENCRYPTION_INFO  KU32_C(0x21)  /**< Segment encryption information. See encryption_info_command. */
+#define LC_DYLD_INFO        KU32_C(0x22)  /**< Compressed dylib relocation information, alternative present. See dyld_info_command. */
+#define LC_DYLD_INFO_ONLY  (KU32_C(0x22) | LC_REQ_DYLD) /**< Compressed dylib relocation information, no alternative. See dyld_info_command. */
+#define LC_LOAD_UPWARD_DYLIB KU32_C(0x23) /**< ???? */
+#define LC_VERSION_MIN_MACOSX KU32_C(0x24)   /**< The image requires the given Mac OS X version. See version_min_command. */
+#define LC_VERSION_MIN_IPHONEOS KU32_C(0x25) /**< The image requires the given iOS version. See version_min_command. */
+#define LC_FUNCTION_STARTS  KU32_C(0x26)  /**< Where to find the compress function start addresses. See linkedit_data_command. */
+#define LC_DYLD_ENVIRONMENT KU32_C(0x27)  /**< Environment variable for the dynamic linker. See dylinker_command. */
+#define LC_MAIN            (KU32_C(0x28) | LC_REQ_DYLD) /**< Simpler alternative to LC_UNIXTHREAD. */
+#define LC_DATA_IN_CODE     KU32_C(0x29)  /**< Table of data in the the text section. */
+#define LC_SOURCE_VERSION   KU32_C(0x2a)  /**< Source code revision / version hint. */
+#define LC_DYLIB_CODE_SIGN_DRS KU32_C(0x2b) /**< Code signing designated requirements copied from dylibs prequisites. */
+/** @} */
+
+
+/**
+ * Load Command String.
+ */
+typedef struct lc_str
+{
+    /** Offset of the string relative to the load_command structure.
+     * The string is zero-terminated. the size of the load command
+     * is zero padded up to a multiple of 4 bytes. */
+    KU32            offset;
+} lc_str_t;
+
+
+/**
+ * Segment load command (32-bit).
+ */
+typedef struct segment_command_32
+{
+    KU32            cmd;            /**< LC_SEGMENT */
+    KU32            cmdsize;        /**< sizeof(self) + sections. */
+    char            segname[16];    /**< The segment name. */
+    KU32            vmaddr;         /**< Memory address of this segment. */
+    KU32            vmsize;         /**< Size of this segment. */
+    KU32            fileoff;        /**< The file location of the segment. */
+    KU32            filesize;       /**< The file size of the segment. */
+    KU32            maxprot;        /**< Maximum VM protection. */
+    KU32            initprot;       /**< Initial VM protection. */
+    KU32            nsects;         /**< Number of section desciptors following this structure. */
+    KU32            flags;          /**< Flags (SG_*). */
+} segment_command_32_t;
+
+
+/**
+ * Segment load command (64-bit).
+ * Same as segment_command_32 except 4 members has been blown up to 64-bit.
+ */
+typedef struct segment_command_64
+{
+    KU32            cmd;            /**< LC_SEGMENT */
+    KU32            cmdsize;        /**< sizeof(self) + sections. */
+    char            segname[16];    /**< The segment name. */
+    KU64            vmaddr;         /**< Memory address of this segment. */
+    KU64            vmsize;         /**< Size of this segment. */
+    KU64            fileoff;        /**< The file location of the segment. */
+    KU64            filesize;       /**< The file size of the segment. */
+    KU32            maxprot;        /**< Maximum VM protection. */
+    KU32            initprot;       /**< Initial VM protection. */
+    KU32            nsects;         /**< Number of section desciptors following this structure. */
+    KU32            flags;          /**< Flags (SG_*). */
+} segment_command_64_t;
+
+/** @name Segment flags (segment_command_64::flags, segment_command_32::flags)
+ * @{ */
+/** Map the file bits in the top end of the memory area for the segment
+ * instead of the low end. Intended for stacks in core dumps.
+ * The part of the segment memory not covered by file bits will be zeroed. */
+#define SG_HIGHVM           KU32_C(0x00000001)
+/** This segment is the virtual memory allocated by a fixed VM library.
+ * (Used for overlap checking in the linker.) */
+#define SG_FVMLIB           KU32_C(0x00000002)
+/** No relocations for or symbols that's relocated to in this segment.
+ * The segment can therefore safely be replaced. */
+#define SG_NORELOC          KU32_C(0x00000004)
+/** The segment is protected.
+ * The first page isn't protected if it starts at file offset 0
+ * (so that the mach header and this load command can be easily mapped). */
+#define SG_PROTECTED_VERSION_1 KU32_C(0x00000008)
+/** @} */
+
+
+/**
+ * 32-bit section (part of a segment load command).
+ */
+typedef struct section_32
+{
+    char            sectname[16];   /**< The section name. */
+    char            segname[16];    /**< The name of the segment this section goes into. */
+    KU32            addr;           /**< The memory address of this section. */
+    KU32            size;           /**< The size of this section. */
+    KU32            offset;         /**< The file offset of this section. */
+    KU32            align;          /**< The section alignment (**2). */
+    KU32            reloff;         /**< The file offset of the relocations. */
+    KU32            nreloc;         /**< The number of relocations. */
+    KU32            flags;          /**< The section flags; section type and attribs */
+    KU32            reserved1;      /**< Reserved / offset / index. */
+    KU32            reserved2;      /**< Reserved / count / sizeof. */
+} section_32_t;
+
+/**
+ * 64-bit section (part of a segment load command).
+ */
+typedef struct section_64
+{
+    char            sectname[16];   /**< The section name. */
+    char            segname[16];    /**< The name of the segment this section goes into. */
+    KU64            addr;           /**< The memory address of this section. */
+    KU64            size;           /**< The size of this section. */
+    KU32            offset;         /**< The file offset of this section. */
+    KU32            align;          /**< The section alignment (**2). */
+    KU32            reloff;         /**< The file offset of the relocations. */
+    KU32            nreloc;         /**< The number of relocations. */
+    KU32            flags;          /**< The section flags; section type and attribs */
+    KU32            reserved1;      /**< Reserved / offset / index. */
+    KU32            reserved2;      /**< Reserved / count / sizeof. */
+    KU32            reserved3;      /**< (Just) Reserved. */
+} section_64_t;
+
+/** @name Section flags (section_64::flags, section_32::flags)
+ * @{
+ */
+/** Section type mask. */
+#define SECTION_TYPE                    KU32_C(0x000000ff)
+/** Regular section. */
+#define S_REGULAR                       0x00
+/** Zero filled section. */
+#define S_ZEROFILL                      0x01
+/** C literals. */
+#define S_CSTRING_LITERALS              0x02
+/** 4 byte literals. */
+#define S_4BYTE_LITERALS                0x03
+/** 8 byte literals. */
+#define S_8BYTE_LITERALS                0x04
+/** Pointer to literals. */
+#define S_LITERAL_POINTERS              0x05
+/** Section containing non-lazy symbol pointers.
+ * Reserved1 == start index in the indirect symbol table. */
+#define S_NON_LAZY_SYMBOL_POINTERS      0x06
+/** Section containing lazy symbol pointers.
+ * Reserved1 == start index in the indirect symbol table. */
+#define S_LAZY_SYMBOL_POINTERS          0x07
+/** Section containing symbol stubs.
+ * Reserved2 == stub size. */
+#define S_SYMBOL_STUBS                  0x08
+/** Section containing function pointers for module initialization. . */
+#define S_MOD_INIT_FUNC_POINTERS        0x09
+/** Section containing function pointers for module termination. . */
+#define S_MOD_TERM_FUNC_POINTERS        0x0a
+/** Section containing symbols that are to be coalesced. */
+#define S_COALESCED                     0x0b
+/** Zero filled section that be larger than 4GB. */
+#define S_GB_ZEROFILL                   0x0c
+/** Section containing pairs of function pointers for interposing. */
+#define S_INTERPOSING                   0x0d
+/** 16 byte literals. */
+#define S_16BYTE_LITERALS               0x0e
+/** DTrace byte code / definitions (DOF = DTrace object format). */
+#define S_DTRACE_DOF                    0x0f
+/** Section containing pointers to symbols in lazily loaded dylibs. */
+#define S_LAZY_DYLIB_SYMBOL_POINTERS    0x10
+
+/** Section attribute mask. */
+#define SECTION_ATTRIBUTES          KU32_C(0xffffff00)
+
+/** User settable attribute mask. */
+#define SECTION_ATTRIBUTES_USR      KU32_C(0xff000000)
+/** Pure instruction (code). */
+#define S_ATTR_PURE_INSTRUCTIONS    KU32_C(0x80000000)
+/** ranlib, ignore my symbols... */
+#define S_ATTR_NO_TOC               KU32_C(0x40000000)
+/** May strip static symbols when linking int a MH_DYLDLINK file. */
+#define S_ATTR_STRIP_STATIC_SYMS    KU32_C(0x20000000)
+/** No dead stripping. */
+#define S_ATTR_NO_DEAD_STRIP        KU32_C(0x10000000)
+/** Live support. */
+#define S_ATTR_LIVE_SUPPORT         KU32_C(0x08000000)
+/** Contains self modifying code (generally i386 code stub for dyld). */
+#define S_ATTR_SELF_MODIFYING_CODE  KU32_C(0x04000000)
+/** Debug info (DWARF usually). */
+#define S_ATTR_DEBUG                KU32_C(0x02000000)
+
+/** System settable attribute mask. */
+#define SECTION_ATTRIBUTES_SYS      KU32_C(0x00ffff00)
+/** Contains some instructions (code). */
+#define S_ATTR_SOME_INSTRUCTIONS    KU32_C(0x00000400)
+/** Has external relocations. */
+#define S_ATTR_EXT_RELOC            KU32_C(0x00000200)
+/** Has internal (local) relocations. */
+#define S_ATTR_LOC_RELOC            KU32_C(0x00000100)
+/** @} */
+
+/** @name Known Segment and Section Names.
+ * Some of these implies special linker behaviour.
+ * @{
+ */
+/** Page zero - not-present page for catching invalid access. (MH_EXECUTE typically) */
+#define SEG_PAGEZERO        "__PAGEZERO"
+/** Traditional UNIX text segment.
+ * Defaults to R-X. */
+#define SEG_TEXT            "__TEXT"
+/** The text part of SEG_TEXT. */
+#define SECT_TEXT               "__text"
+/** The fvmlib initialization. */
+#define SECT_FVMLIB_INIT0       "__fvmlib_init0"
+/** The section following the fvmlib initialization. */
+#define SECT_FVMLIB_INIT1       "__fvmlib_init1"
+/** The traditional UNIX data segment. (DGROUP to DOS and OS/2 people.) */
+#define SEG_DATA            "__DATA"
+/** The initialized data section. */
+#define SECT_DATA               "__data"
+/** The uninitialized data section. */
+#define SECT_BSS                "__bss"
+/** The common symbol section. */
+#define SECT_COMMON             "__common"
+/** Objective-C runtime segment. */
+#define SEG_OBJC            "__OBJC"
+/** Objective-C symbol table section. */
+#define SECT_OBJC_SYMBOLS       "__symbol_table"
+/** Objective-C module information section. */
+#define SECT_OBJC_MODULES       "__module_info"
+/** Objective-C string table section. */
+#define SECT_OBJC_STRINGS       "__selector_strs"
+/** Objective-C string table section. */
+#define SECT_OBJC_REFS          "__selector_refs"
+/** Icon segment. */
+#define SEG_ICON            "__ICON"
+/** The icon headers. */
+#define SECT_ICON_HEADER        "__header"
+/** The icons in the TIFF format. */
+#define SECT_ICON_TIFF          "__tiff"
+/** ld -seglinkedit segment containing all the structs create and maintained
+ * by the linker. MH_EXECUTE and MH_FVMLIB only. */
+#define SEG_LINKEDIT        "__LINKEDIT"
+/** The unix stack segment. */
+#define SEG_UNIXSTACK       "__UNIXSTACK"
+/** The segment for the self modifying code for dynamic linking.
+ * Implies RWX permissions. */
+#define SEG_IMPORT          "__IMPORT"
+/** @} */
+
+
+/** @todo fvmlib */
+/** @todo fvmlib_command (LC_IDFVMLIB or LC_LOADFVMLIB) */
+/** @todo dylib */
+/** @todo dylib_command (LC_ID_DYLIB, LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB,
+ *        LC_REEXPORT_DYLIB, LC_LAZY_LOAD_DYLIB) */
+/** @todo sub_framework_command (LC_SUB_FRAMEWORK) */
+/** @todo sub_client_command (LC_SUB_CLIENT) */
+/** @todo sub_umbrella_command (LC_SUB_UMBRELLA) */
+/** @todo sub_library_command (LC_SUB_LIBRARY) */
+/** @todo prebound_dylib_command (LC_PREBOUND_DYLIB) */
+/** @todo dylinker_command (LC_ID_DYLINKER or LC_LOAD_DYLINKER,
+ *        LC_DYLD_ENVIRONMENT) */
+
+/**
+ * Thread command.
+ *
+ * State description of a thread that is to be created. The description
+ * is made up of a number of state structures preceded by a 32-bit flavor
+ * and 32-bit count field stating the kind of stat structure and it's size
+ * in KU32 items respecitvly.
+ *
+ * LC_UNIXTHREAD differs from LC_THREAD in that it implies stack creation
+ * and that it's started with the typical main(int, char **, char **) frame
+ * on the stack.
+ */
+typedef struct thread_command
+{
+    KU32            cmd;        /**< LC_UNIXTHREAD or LC_THREAD. */
+    KU32            cmdsize;    /**< The size of the command (including this header). */
+} thread_command_t;
+
+
+/** @todo routines_command (LC_ROUTINES) */
+/** @todo routines_command_64 (LC_ROUTINES_64) */
+
+
+/**
+ * Symbol table command.
+ * Contains a.out style symbol table with some tricks.
+ */
+typedef struct symtab_command
+{
+    KU32            cmd;        /**< LC_SYMTAB */
+    KU32            cmdsize;    /** sizeof(symtab_command_t) */
+    KU32            symoff;     /** The file offset of the symbol table. */
+    KU32            nsyms;      /** The number of symbols in the symbol table. */
+    KU32            stroff;     /** The file offset of the string table. */
+    KU32            strsize;    /** The size of the string table. */
+} symtab_command_t;
+
+
+/** @todo dysymtab_command (LC_DYSYMTAB)  */
+/** @todo dylib_table_of_contents */
+/** @todo dylib_module_32 */
+/** @todo dylib_module_64 */
+/** @todo dylib_reference */
+/** @todo twolevel_hints_command (LC_TWOLEVEL_HINTS) */
+/** @todo twolevel_hint */
+/** @todo prebind_cksum_command (LC_PREBIND_CKSUM) */
+
+
+/**
+ * UUID generated by ld.
+ */
+typedef struct uuid_command
+{
+    KU32            cmd;        /**< LC_UUID */
+    KU32            cmdsize;    /**< sizeof(uuid_command_t) */
+    KU8             uuid[16];   /** The UUID bytes. */
+} uuid_command_t;
+
+
+/** @todo symseg_command (LC_SYMSEG) */
+/** @todo ident_command (LC_IDENT) */
+/** @todo fvmfile_command (LC_FVMFILE) */
+/** @todo rpath_command (LC_RPATH) */
+
+typedef struct linkedit_data_command 
+{
+    KU32            cmd;        /**< LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS */
+    KU32            cmdsize;    /**< size of this structure. */
+    KU32            dataoff;    /**< Offset into the file of the data. */
+    KU32            datasize;   /**< The size of the data. */
+} linkedit_data_command_t;
+
+/** @todo encryption_info_command (LC_ENCRYPTION_INFO) */
+/** @todo dyld_info_command (LC_DYLD_INFO, LC_DYLD_INFO_ONLY) */
+
+typedef struct version_min_command
+{
+    KU32            cmd;        /**< LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS */
+    KU32            cmdsize;    /**< size of this structure. */
+    KU32            version;    /**< 31..16=major, 15..8=minor, 7..0=patch. */
+    KU32            reserved;   /**< MBZ. */
+} version_min_command_t;
+
+/** @} */
+
+
+
+/** @defgroup grp_macho_o_syms  Symbol Table
+ * @{ */
+
+/**
+ * The 32-bit Mach-O version of the nlist structure.
+ *
+ * This differs from the a.out nlist struct in that the unused n_other field
+ * was renamed to n_sect and used for keeping the relevant section number.
+ * @remark  This structure is not name mach_nlist_32 in the Apple headers, but nlist.
+ */
+typedef struct macho_nlist_32
+{
+    union
+    {
+        KI32    n_strx;         /**< Offset (index) into the string table. 0 means "". */
+    }           n_un;
+    KU8         n_type;         /**< Symbol type. */
+    KU8         n_sect;         /**< Section number of NO_SECT. */
+    KI16        n_desc;         /**< Type specific, debug info details mostly.*/
+    KU32        n_value;        /**< The symbol value or stab offset. */
+} macho_nlist_32_t;
+
+
+/**
+ * The 64-bit Mach-O version of the nlist structure.
+ * @see macho_nlist_32
+ */
+typedef struct macho_nlist_64
+{
+    union
+    {
+        KU32    n_strx;         /**< Offset (index) into the string table. 0 means "". */
+    }           n_un;
+    KU8         n_type;         /**< Symbol type. */
+    KU8         n_sect;         /**< Section number of NO_SECT. */
+    KI16        n_desc;         /**< Type specific, debug info details mostly.*/
+    KU64        n_value;        /**< The symbol value or stab offset. */
+} macho_nlist_64_t;
+
+
+/** @name Symbol Type Constants (macho_nlist_32_t::n_type, macho_nlist_64_t::n_type)
+ *
+ * In the Mach-O world n_type is somewhat similar to a.out, meaning N_EXT, N_UNDF, N_ABS
+ * and the debug symbols are essentially the same, but the remaining stuff is different.
+ * The main reason for this is that the encoding of section has been moved to n_sect
+ * to permit up to 255 sections instead of the fixed 3 a.out sections (not counting
+ * the abs symbols and set vectors).
+ *
+ * To avoid confusion with a.out the Mach-O constants has been fitted with a MACHO_
+ * prefix here.
+ *
+ * Common symbols (aka communal symbols and comdefs) are represented by
+ * n_type = MACHO_N_EXT | MACHO_N_UNDF, n_sect = NO_SECT and n_value giving
+ * the size.
+ *
+ *
+ * Symbol table entries can be inserted directly in the assembly code using
+ * this notation:
+ * @code
+ *      .stabs "n_name", n_type, n_sect, n_desc, n_value
+ * @endcode
+ *
+ * (1) The line number is optional, GCC doesn't set it.
+ * (2) The type is optional, GCC doesn't set it.
+ * (3) The binutil header is "skeptical" about the line. I'm skeptical about the whole thing... :-)
+ * (M) Mach-O specific?
+ * (S) Sun specific?
+ * @{
+ */
+
+/* Base masks. */
+#define MACHO_N_EXT     KU8_C(0x01)   /**< External symbol (when set) (N_EXT). */
+#define MACHO_N_TYPE    KU8_C(0x0e)   /**< Symbol type (N_TYPE without the 8th bit). */
+#define MACHO_N_PEXT    KU8_C(0x10)   /**< Private extern symbol (when set). (M) */
+#define MACHO_N_STAB    KU8_C(0xe0)   /**< Debug symbol mask (N_STAB). */
+
+/* MACHO_N_TYPE values. */
+#define MACHO_N_UNDF    KU8_C(0x00)   /**< MACHO_N_TYPE: Undefined symbol (N_UNDF). n_sect = NO_SECT. */
+#define MACHO_N_ABS     KU8_C(0x02)   /**< MACHO_N_TYPE: Absolute symbol (N_UNDF). n_sect = NO_SECT. */
+#define MACHO_N_INDR    KU8_C(0x0a)   /**< MACHO_N_TYPE: Indirect symbol, n_value is the index of the symbol. (M) */
+#define MACHO_N_PBUD    KU8_C(0x0c)   /**< MACHO_N_TYPE: Prebound undefined symbo (defined in a dylib). (M) */
+#define MACHO_N_SECT    KU8_C(0x0e)   /**< MACHO_N_TYPE: Defined in the section given by n_sects. (M) */
+
+/* Debug symbols. */
+#define MACHO_N_GSYM    KU8_C(0x20)   /**< Global variable.       "name",, NO_SECT, type, 0       (2) */
+#define MACHO_N_FNAME   KU8_C(0x22)   /**< Function name (F77).   "name",, NO_SECT, 0, 0 */
+#define MACHO_N_FUN     KU8_C(0x24)   /**< Function / text var.   "name",, section, line, address (1) */
+#define MACHO_N_STSYM   KU8_C(0x26)   /**< Static data symbol.    "name",, section, type, address (2) */
+#define MACHO_N_LCSYM   KU8_C(0x28)   /**< static bss symbol.     "name",, section, type, address (2) */
+    /* omits N_MAIN and N_ROSYM. */
+#define MACHO_N_BNSYM   KU8_C(0x2e)   /**< Begin nsect symbol.         0,, section, 0, address (M) */
+#define MACHO_N_PC      KU8_C(0x30)   /**< Global pascal symbol.  "name",, NO_SECT, subtype?, line (3) */
+    /* omits N_NSYMS, N_NOMAP and N_OBJ. */
+#define MACHO_N_OPT     KU8_C(0x3c)   /**< Options for the debugger related to the language of the
+                                             source file.           "options?",,,, */
+#define MACHO_N_RSYM    KU8_C(0x40)   /**< Register variable.     "name",, NO_SECT, type, register */
+    /* omits N_M2C */
+#define MACHO_N_SLINE   KU8_C(0x44)   /**< Source line.                0,, section, line, address */
+    /* omits N_DSLINE, N_BSLINE / N_BROWS, N_DEFD and N_FLINE. */
+#define MACHO_N_ENSYM   KU8_C(0x4e)   /**< End nsect symbol.           0,, section, 0, address (M) */
+    /* omits N_EHDECL / N_MOD2 and N_CATCH. */
+#define MACHO_N_SSYM    KU8_C(0x60)   /**< Struct/union element.  "name",, NO_SECT, type, offset */
+    /* omits N_ENDM */
+#define MACHO_N_SO      KU8_C(0x64)   /**< Source file name.      "fname",, section, 0, address */
+#define MACHO_N_OSO     KU8_C(0x66)   /**< Object file name.      "fname",, 0, 0, st_mtime (M?) */
+    /* omits N_ALIAS */
+#define MACHO_N_LSYM    KU8_C(0x80)   /**< Stack variable.        "name",, NO_SECT, type, frame_offset */
+#define MACHO_N_BINCL   KU8_C(0x82)   /**< Begin #include.        "fname",, NO_SECT, 0, sum? */
+#define MACHO_N_SOL     KU8_C(0x84)   /**< #included file.        "fname",, section, 0, start_address (S) */
+#define MACHO_N_PARAMS  KU8_C(0x86)   /**< Compiler params.       "params",, NO_SECT, 0, 0 */
+#define MACHO_N_VERSION KU8_C(0x88)   /**< Compiler version.      "version",, NO_SECT, 0, 0 */
+#define MACHO_N_OLEVEL  KU8_C(0x8A)   /**< Compiler -O level.     "level",, NO_SECT, 0, 0 */
+#define MACHO_N_PSYM    KU8_C(0xa0)   /**< Parameter variable.    "name",, NO_SECT, type, frame_offset */
+#define MACHO_N_EINCL   KU8_C(0xa2)   /**< End #include.          "fname",, NO_SECT, 0, 0 (S) */
+#define MACHO_N_ENTRY   KU8_C(0xa4)   /**< Alternate entry point. "name",, section, line, address */
+#define MACHO_N_LBRAC   KU8_C(0xc0)   /**< Left bracket.               0,, NO_SECT, nesting_level, address */
+#define MACHO_N_EXCL    KU8_C(0xc2)   /**< Deleted include file.  "fname",, NO_SECT, 0, sum?  (S) */
+    /* omits N_SCOPE */
+#define MACHO_N_RBRAC   KU8_C(0xe0)   /**< Right bracket.              0,, NO_SECT, nesting_level, address */
+#define MACHO_N_BCOMM   KU8_C(0xe2)   /**< Begin common.          "name",, NO_SECT?, 0, 0 */
+#define MACHO_N_ECOMM   KU8_C(0xe4)   /**< End common.            "name",, section, 0, 0 */
+#define MACHO_N_ECOML   KU8_C(0xe8)   /**< End local common.           0,, section, 0, address */
+#define MACHO_N_LENG    KU8_C(0xfe)   /**< Length-value of the preceding entry.
+                                                                    "name",, NO_SECT, 0, length */
+
+/** @} */
+
+/** @name Symbol Description Bits (macho_nlist_32_t::n_desc, macho_nlist_64_t::n_desc)
+ *
+ * Mach-O puts the n_desc field to a number of uses, like lazy binding , library
+ * ordinal numbers for -twolevel_namespace, stripping and weak symbol handling.
+ *
+ * @remark The REFERENCE_FLAGS_* are really not flags in the normal sense (bit),
+ *         they are more like enum values.
+ * @{
+ */
+
+#define REFERENCE_TYPE                  KU16_C(0x000f)    /**< The reference type mask. */
+#define REFERENCE_FLAG_UNDEFINED_NON_LAZY             0     /**< Normal undefined symbol. */
+#define REFERENCE_FLAG_UNDEFINED_LAZY                 1     /**< Lazy undefined symbol. */
+#define REFERENCE_FLAG_DEFINED                        2     /**< Defined symbol (dynamic linking). */
+#define REFERENCE_FLAG_PRIVATE_DEFINED                3     /**< Defined private symbol (dynamic linking). */
+#define REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY     4     /**< Normal undefined private symbol. */
+#define REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY         5     /**< Lazy undefined private symbol. */
+
+#define REFERENCED_DYNAMICALLY          KU16_C(0x0010)    /**< Don't strip. */
+
+
+/** Get the dynamic library ordinal. */
+#define GET_LIBRARY_ORDINAL(n_desc)     \
+    (((n_desc) >> 8) & 0xff)
+/** Set the dynamic library ordinal. */
+#define SET_LIBRARY_ORDINAL(n_desc, ordinal) \
+    (n_desc) = (((n_desc) & 0xff) | (((ordinal) & 0xff) << 8))
+#define SELF_LIBRARY_ORDINAL            0x00                /**< Special ordinal for refering to onself. */
+#define MAX_LIBRARY_ORDINAL             0xfd                /**< Maximum ordinal number. */
+#define DYNAMIC_LOOKUP_ORDINAL          0xfe                /**< Special ordinal number for dynamic lookup. (Mac OS X 10.3 and later) */
+#define EXECUTABLE_ORDINAL              0xff                /**< Special ordinal number for the executable.  */
+
+
+/** Only MH_OBJECT: Never dead strip me! */
+#define N_NO_DEAD_STRIP                 KU16_C(0x0020)
+/** Not MH_OBJECT: Discarded symbol. */
+#define N_DESC_DISCARDED                KU16_C(0x0020)
+/** Weak external symbol. Symbol can be missing, in which case it's will have the value 0. */
+#define N_WEAK_REF                      KU16_C(0x0040)
+/** Weak symbol definition. The symbol can be overridden by another weak
+ * symbol already present or by a non-weak (strong) symbol definition.
+ * Currently only supported for coalesed symbols.
+ * @remark This bit means something differently for undefined symbols, see N_REF_TO_WEAK.
+ */
+#define N_WEAK_DEF                      KU16_C(0x0080)
+/** Reference to a weak symbol, resolve using flat namespace searching.
+ * @remark This bit means something differently for defined symbols, see N_WEAK_DEF. */
+#define N_REF_TO_WEAK                   KU16_C(0x0080)
+
+/** @} */
+
+/** @} */
+
+
+/** @defgroup grp_macho_o_relocs    Relocations
+ * @{ */
+
+/**
+ * Relocation entry.
+ *
+ * Differs from a.out in the meaning of r_symbolnum when r_extern=0 and
+ * that r_pad is made into r_type.
+ *
+ * @remark  This structure and type has been prefixed with macho_ to avoid
+ *          confusion with the original a.out type.
+ */
+typedef struct macho_relocation_info
+{
+    KI32        r_address;          /**< Section relative address of the fixup.
+                                         The top bit (signed) indicates that this is a scattered
+                                         relocation if set, see scattered_relocation_info_t. */
+    KU32        r_symbolnum : 24,   /**< r_extern=1: Symbol table index, relocate with the address of this symbol.
+                                         r_extern=0: Section ordinal, relocate with the address of this section. */
+                r_pcrel : 1,        /**< PC (program counter) relative fixup; subtract the fixup address. */
+                r_length : 2,       /**< Fixup length: 0=KU8, 1=KU16, 2=KU32, 3=KU64. */
+                r_extern : 1,       /**< External or internal fixup, decides the r_symbolnum interpretation.. */
+                r_type : 4;         /**< Relocation type; 0 is standard, non-zero are machine specific. */
+} macho_relocation_info_t;
+
+/** Special section ordinal value for absolute relocations. */
+#define R_ABS           0
+
+/** Flag in r_address indicating that the relocation is of the
+ * scattered_relocation_info_t kind and not macho_relocation_info_t. */
+#define R_SCATTERED     KU32_C(0x80000000)
+
+/**
+ * Scattered relocation.
+ *
+ * This is a hack mainly for RISC machines which restricts section size
+ * to 16MB among other things.
+ *
+ * The reason for the big/little endian differences here is of course because
+ * of the R_SCATTERED mask and the way bitfields are implemented by the
+ * C/C++ compilers.
+ */
+typedef struct scattered_relocation_info
+{
+#if K_ENDIAN == K_ENDIAN_LITTLE
+    KU32        r_address : 24,     /**< Section relative address of the fixup. (macho_relocation_info_t::r_address) */
+                r_type : 4,         /**< Relocation type; 0 is standard, non-zero are machine specific. (macho_relocation_info_t::r_type) */
+                r_length : 2,       /**< Fixup length: 0=KU8, 1=KU16, 2=KU32, 3=KU64. (macho_relocation_info_t::r_length) */
+                r_pcrel : 1,        /**< PC (program counter) relative fixup; subtract the fixup address. (macho_relocation_info_t::r_pcrel) */
+                r_scattered : 1;    /**< Set if scattered relocation, clear if normal relocation. */
+#elif K_ENDIAN == K_ENDIAN_BIG
+    KU32        r_scattered : 1,    /**< Set if scattered relocation, clear if normal relocation. */
+                r_pcrel : 1,        /**< PC (program counter) relative fixup; subtract the fixup address. (macho_relocation_info_t::r_pcrel) */
+                r_length : 2,       /**< Fixup length: 0=KU8, 1=KU16, 2=KU32, 3=KU64. (macho_relocation_info_t::r_length) */
+                r_type : 4,         /**< Relocation type; 0 is standard, non-zero are machine specific. (macho_relocation_info_t::r_type) */
+                r_address : 24;     /**< Section relative address of the fixup. (macho_relocation_info_t::r_address) */
+#else
+# error "Neither K_ENDIAN isn't LITTLE or BIG!"
+#endif
+    KI32        r_value;            /**< The value the fixup is refering to (without offset added). */
+} scattered_relocation_info_t;
+
+/**
+ * Relocation type values for a generic implementation (for r_type).
+ */
+typedef enum reloc_type_generic
+{
+    GENERIC_RELOC_VANILLA = 0,      /**< Standard relocation. */
+    GENERIC_RELOC_PAIR,             /**< Follows GENERIC_RELOC_SECTDIFF. */
+    GENERIC_RELOC_SECTDIFF,         /**< ??? */
+    GENERIC_RELOC_PB_LA_PTR,        /**< Prebound lazy pointer whatever that. */
+    GENERIC_RELOC_LOCAL_SECTDIFF    /**< ??? */
+} reloc_type_generic_t;
+
+/**
+ * Relocation type values for AMD64 (for r_type).
+ */
+typedef enum reloc_type_x86_64
+{
+    X86_64_RELOC_UNSIGNED = 0,      /**< Absolute address. */
+    X86_64_RELOC_SIGNED,            /**< Signed displacement. */
+    X86_64_RELOC_BRANCH,            /**< Branch displacement (jmp/call, adj by size). */
+    X86_64_RELOC_GOT_LOAD,          /**< GOT entry load. */
+    X86_64_RELOC_GOT,               /**< GOT reference. */
+    X86_64_RELOC_SUBTRACTOR,        /**< ??. */
+    X86_64_RELOC_SIGNED_1,          /**< Signed displacement with a -1 added. */
+    X86_64_RELOC_SIGNED_2,          /**< Signed displacement with a -2 added. */
+    X86_64_RELOC_SIGNED_4           /**< Signed displacement with a -4 added. */
+} reloc_type_x86_64_t;
+
+/** @} */
+
+
+/** @} */
+#endif
+
diff --git a/src/lib/kStuff/include/k/kLdrFmts/mz.h b/src/lib/kStuff/include/k/kLdrFmts/mz.h
new file mode 100644
index 0000000..b159cac
--- /dev/null
+++ b/src/lib/kStuff/include/k/kLdrFmts/mz.h
@@ -0,0 +1,70 @@
+/* $Id: mz.h 31 2009-07-01 21:08:06Z bird $ */
+/** @file
+ * MZ structures, types and defines.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kLdrFmts_mz_h___
+#define ___k_kLdrFmts_mz_h___
+
+#include <k/kDefs.h>
+#include <k/kTypes.h>
+
+#pragma pack(1) /* not required */
+
+typedef struct _IMAGE_DOS_HEADER
+{
+    KU16       e_magic;
+    KU16       e_cblp;
+    KU16       e_cp;
+    KU16       e_crlc;
+    KU16       e_cparhdr;
+    KU16       e_minalloc;
+    KU16       e_maxalloc;
+    KU16       e_ss;
+    KU16       e_sp;
+    KU16       e_csum;
+    KU16       e_ip;
+    KU16       e_cs;
+    KU16       e_lfarlc;
+    KU16       e_ovno;
+    KU16       e_res[4];
+    KU16       e_oemid;
+    KU16       e_oeminfo;
+    KU16       e_res2[10];
+    KU32       e_lfanew;
+} IMAGE_DOS_HEADER;
+typedef IMAGE_DOS_HEADER *PIMAGE_DOS_HEADER;
+
+#ifndef IMAGE_DOS_SIGNATURE
+# define IMAGE_DOS_SIGNATURE K_LE2H_U16('M' | ('Z' << 8))
+#endif
+
+#pragma pack()
+
+#endif
+
diff --git a/src/lib/k/kLdrFmts/pe.h b/src/lib/kStuff/include/k/kLdrFmts/pe.h
similarity index 92%
rename from src/lib/k/kLdrFmts/pe.h
rename to src/lib/kStuff/include/k/kLdrFmts/pe.h
index 4b044d0..3523226 100644
--- a/src/lib/k/kLdrFmts/pe.h
+++ b/src/lib/kStuff/include/k/kLdrFmts/pe.h
@@ -1,8 +1,33 @@
-/* $Id: pe.h 2 2007-11-16 16:07:14Z bird $ */
+/* $Id: pe.h 82 2016-08-22 21:01:51Z bird $ */
 /** @file
  * PE structures, types and defines.
  */
 
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
 #ifndef ___k_kLdrFmts_pe_h___
 #define ___k_kLdrFmts_pe_h___
 
@@ -349,7 +374,7 @@ typedef IMAGE_IMPORT_DESCRIPTOR *PIMAGE_IMPORT_DESCRIPTOR;
 typedef struct _IMAGE_IMPORT_BY_NAME
 {
     KU16      Hint;
-    KU8      Name[1];
+    KU8       Name[1];
 } IMAGE_IMPORT_BY_NAME;
 typedef IMAGE_IMPORT_BY_NAME *PIMAGE_IMPORT_BY_NAME;
 
diff --git a/src/lib/kStuff/include/k/kMagics.h b/src/lib/kStuff/include/k/kMagics.h
new file mode 100644
index 0000000..9690b9b
--- /dev/null
+++ b/src/lib/kStuff/include/k/kMagics.h
@@ -0,0 +1,43 @@
+/* $Id: kMagics.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kMagics - Various Magic Constants.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef ___k_kMagics_h___
+#define ___k_kMagics_h___
+
+/** The magic for KRDR::u32Magic. (Katsu Aki (Katsuaki Nakamura))
+ * @ingroup grp_kRdrAll */
+#define KRDR_MAGIC          0x19610919
+/** The magic value for the debug module structure. (Some manga artist)
+ * @ingroup grp_kDbgAll */
+#define KDBGMOD_MAGIC       0x19200501
+
+#endif
+
diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbAssert.h b/src/lib/kStuff/include/k/kRbTmpl/kRbAssert.h
new file mode 100644
index 0000000..03c17a4
--- /dev/null
+++ b/src/lib/kStuff/include/k/kRbTmpl/kRbAssert.h
@@ -0,0 +1,136 @@
+/* $Id: kRbAssert.h 38 2009-11-10 00:01:38Z bird $ */
+/** @file
+ * kRbTmpl - Templated Red-Black Trees, Assert Valid Tree.
+ */
+
+/*
+ * Copyright (c) 2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * Internal helper for KRB_FN(Assert)
+ *
+ * @returns The number of black nodes. -1 is return if the tree is invalid.
+ * @param   pRoot       The root of the (sub-)tree to assert.
+ */
+K_DECL_INLINE(int) KRB_FN(AssertRecurse)(KRBNODE *pRoot)
+{
+    int cLeft;
+    int cRight;
+
+    if (!pRoot)
+        /* leafs are black. */
+        return 1;
+
+#ifdef KRB_EQUAL_ALLOWED
+    /* equal nodes are equal :) */
+    if (pNode->mpList != KRB_NULL)
+    {
+        KRBROOT *pEqual;
+        for (pEqual = KRB_GET_POINTER(&pNode->mpList); pEqual; pEqual = KRB_GET_POINTER_NULL(&pEqual->mpList))
+            kHlpAssertReturn(K_CMP_E(pEqual->mKey, pNode->mKey), -1);
+    }
+#endif
+
+    /* binary tree. */
+    kHlpAssertReturn(pRoot->mpLeft  != KRB_NULL && KRB_CMP_G(KRB_GET_POINTER(&pRoot->mpLeft)->mpKey, pRoot->mKey), -1);
+    kHlpAssertReturn(pRoot->mpRight != KRB_NULL && KRB_CMP_G(pRoot->mKey, KRB_GET_POINTER(&pRoot->mpRigth)->mpKey), -1);
+
+    /* both children of red nodes are black. */
+    kHlpAssertReturn(!KRB_IS_RED(pRoot) || (!KRB_IS_RED(pRoot->mpLeft) && !KRB_IS_RED(pRoot->mpRight)), -1);
+
+    /* all paths to leafs contains the same number of black nodes. */
+    cLeft  = KRB_FN(AssertRecurse)(KRB_GET_POINTER_NULL(&pRoot->mpLeft));
+    cRight = KRB_FN(AssertRecurse)(KRB_GET_POINTER_NULL(&pRoot->mpRight));
+    kHlpAssertMsgReturn(cLeft == cRight || cLeft == -1 || cRight == -1, ("%d vs. %d\n", cLeft, cRight), -1);
+
+    return cLeft + !KRB_IS_RED(pRoot);
+}
+
+
+/**
+ * Asserts the validity of the Red-Black tree.
+ *
+ * This method is using recursion and may therefore consume quite a bit of stack
+ * on a large tree.
+ *
+ * @returns K_TRUE if valid.
+ * @returns K_FALSE if invalid, assertion raised on each violation.
+ * @param   pRoot           Pointer to the Red-Back tree's root structure.
+ */
+KRB_DECL(KBOOL) KRB_FN(Assert)(KRBROOT *pRoot)
+{
+    KBOOL       fRc = K_TRUE;
+#ifdef KRB_CACHE_SIZE
+    unsigned    i;
+#endif
+    KRBNODE    *pNode;
+
+    KRB_READ_LOCK(pRoot);
+    if (pRoot->mpRoot == KRB_NULL)
+    {
+        KRB_READ_UNLOCK(pRoot);
+        return 0;
+    }
+
+#ifdef KRB_CACHE_SIZE
+    /*
+     * Validate the cache.
+     */
+    for (i = 0; i < (KRB_CACHE_SIZE); i++)
+        if (pRoot->maLookthru[i] != KRB_NULL)
+        {
+            KRBNODE pCache = KRB_GET_POINTER(&pRoot->maLookthru[i]);
+
+            /** @todo ranges */
+            kHlpAssertMsgStmt(i == KRB_CACHE_HASH(pCache->Key), ("Invalid cache entry %u, hashed to %u\n", i, KRB_CACHE_HASH(pCache->Key)), fRc = K_FALSE);
+
+            pNode = KRB_GET_POINTER(&pRoot->mpRoot);
+            while (pNode)
+            {
+                if (KRB_CMP_E(pCache->mKey, pNode->mKey))
+                {
+                    kHlpAssertMsgStmt(pNode == pCache, ("Invalid cache entry %u=%p, found %p\n", i, pCache, pNode), fRc = K_FALSE);
+                    break;
+                }
+                if (KRB_CMP_G(pCache->mKey, pNode->mKey))
+                    pNode = KRB_GET_POINTER_NULL(&pNode->mRight);
+                else
+                    pNode = KRB_GET_POINTER_NULL(&pNode->mLeft);
+            }
+            kHlpAssertMsgStmt(pNode, ("Invalid cache entry %u/%p - not found\n", i, pCache), fRc = K_FALSE);
+        }
+#endif
+
+    /*
+     * Recurse thru the tree.
+     */
+    if (KRB_FN(AssertRecurse)(KRB_GET_POINTER(&pRoot->mpRoot)) == -1)
+        fRc = K_FALSE;
+
+    KRB_READ_UNLOCK(pRoot);
+    return fRc;
+}
+
diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbBase.h b/src/lib/kStuff/include/k/kRbTmpl/kRbBase.h
new file mode 100644
index 0000000..c79f7ce
--- /dev/null
+++ b/src/lib/kStuff/include/k/kRbTmpl/kRbBase.h
@@ -0,0 +1,609 @@
+/* $Id: kRbBase.h 38 2009-11-10 00:01:38Z bird $ */
+/** @file
+ * kRbTmpl - Templated Red-Black Trees, The Mandatory Base Code.
+ */
+
+/*
+ * Copyright (c) 2001-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @page pg_kAvlTmpl   Template Configuration.
+ *
+ *  This is a templated implementation of Red-Black trees in C.  The template
+ *  parameters relates to the kind of key used and how duplicates are treated.
+ *
+ *  \#define KRB_EQUAL_ALLOWED
+ *  Define this to tell us that equal keys are allowed.
+ *  Then Equal keys will be put in a list pointed to by KRBNODE::pList.
+ *  This is by default not defined.
+ *
+ *  \#define KRB_CHECK_FOR_EQUAL_INSERT
+ *  Define this to enable insert check for equal nodes.
+ *  This is by default not defined.
+ *
+ *  \#define KRB_MAX_STACK
+ *  Use this to specify the max number of stack entries the stack will use when
+ *  inserting and removing nodes from the tree. The size should be something like
+ *      log2(<max nodes>) + 3
+ *  Must be defined.
+ *
+ *  \#define KRB_RANGE
+ *  Define this to enable key ranges.
+ *
+ *  \#define KRB_OFFSET
+ *  Define this to link the tree together using self relative offset
+ *  instead of memory pointers, thus making the entire tree relocatable
+ *  provided all the nodes - including the root node variable - are moved
+ *  the exact same distance.
+ *
+ *  \#define KRB_CACHE_SIZE
+ *  Define this to employ a lookthru cache (direct) to speed up lookup for
+ *  some usage patterns. The value should be the number of members of the array.
+ *
+ *  \#define KRB_CACHE_HASH(Key)
+ *  Define this to specify a more efficient translation of the key into
+ *  a lookthru array index. The default is key % size.
+ *  For some key types this is required as the default will not compile.
+ *
+ *  \#define KRB_LOCKED
+ *  Define this if you wish for the tree to be locked via the
+ *  KRB_WRITE_LOCK,  KRB_WRITE_UNLOCK, KRB_READ_LOCK and
+ *  KRB_READ_UNLOCK macros. If not defined the tree will not be subject
+ *  do any kind of locking and the problem of concurrency is left the user.
+ *
+ *  \#define KRB_WRITE_LOCK(pRoot)
+ *  Lock the tree for writing.
+ *
+ *  \#define KRB_WRITE_UNLOCK(pRoot)
+ *  Counteracts KRB_WRITE_LOCK.
+ *
+ *  \#define KRB_READ_LOCK(pRoot)
+ *  Lock the tree for reading.
+ *
+ *  \#define KRB_READ_UNLOCK(pRoot)
+ *  Counteracts KRB_READ_LOCK.
+ *
+ *  \#define KRBKEY
+ *  Define this to the name of the AVL key type.
+ *
+ *  \#define KRB_STD_KEY_COMP
+ *  Define this to use the standard key compare macros. If not set all the
+ *  compare operations for KRBKEY have to be defined: KRB_CMP_G, KRB_CMP_E, KRB_CMP_NE,
+ *  KRB_R_IS_IDENTICAL, KRB_R_IS_INTERSECTING and KRB_R_IS_IN_RANGE. The
+ *  latter three are only required when KRB_RANGE is defined.
+ *
+ *  \#define KRBNODE
+ *  Define this to the name (typedef) of the AVL node structure. This
+ *  structure must have a mpLeft, mpRight, mKey and mHeight member.
+ *  If KRB_RANGE is defined a mKeyLast is also required.
+ *  If KRB_EQUAL_ALLOWED is defined a mpList member is required.
+ *  It's possible to use other member names by redefining the names.
+ *
+ *  \#define KRBTREEPTR
+ *  Define this to the name (typedef) of the tree pointer type. This is
+ *  required when KRB_OFFSET is defined. When not defined it defaults
+ *  to KRBNODE *.
+ *
+ *  \#define KRBROOT
+ *  Define this to the name (typedef) of the AVL root structure. This
+ *  is optional. However, if specified it must at least have a mpRoot
+ *  member of KRBTREEPTR type. If KRB_CACHE_SIZE is non-zero a
+ *  maLookthru[KRB_CACHE_SIZE] member of the KRBTREEPTR type is also
+ *  required.
+ *
+ *  \#define KRB_FN
+ *  Use this to alter the names of the AVL functions.
+ *  Must be defined.
+ *
+ *  \#define KRB_TYPE(prefix, name)
+ *  Use this to make external type names and unique. The prefix may be empty.
+ *  Must be defined.
+ *
+ *  \#define KRB_INT(name)
+ *  Use this to make internal type names and unique. The prefix may be empty.
+ *  Must be defined.
+ *
+ *  \#define KRB_DECL(rettype)
+ *  Function declaration macro that should be set according to the scope
+ *  the instantiated template should have. For instance an inlined scope
+ *  (private or public) should K_DECL_INLINE(rettype) here.
+ *
+ *  This version of the kAVL tree offers the option of inlining the entire
+ *  implementation. This depends on the compiler doing a decent job in both
+ *  making use of the inlined code and to eliminate const variables.
+ */
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+#include <k/kDefs.h>
+#include <k/kTypes.h>
+#include <k/kHlpAssert.h>
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** @def KRB_GET_POINTER
+ * Reads a 'pointer' value.
+ *
+ * @returns The native pointer.
+ * @param   pp      Pointer to the pointer to read.
+ * @internal
+ */
+
+/** @def KRB_GET_POINTER_NULL
+ * Reads a 'pointer' value which can be KRB_NULL.
+ *
+ * @returns The native pointer.
+ * @returns NULL pointer if KRB_NULL.
+ * @param   pp      Pointer to the pointer to read.
+ * @internal
+ */
+
+/** @def KRB_SET_POINTER
+ * Writes a 'pointer' value.
+ * For offset-based schemes offset relative to pp is calculated and assigned to *pp.
+ *
+ * @returns stored pointer.
+ * @param   pp      Pointer to where to store the pointer.
+ * @param   p       Native pointer to assign to *pp.
+ * @internal
+ */
+
+/** @def KRB_SET_POINTER_NULL
+ * Writes a 'pointer' value which can be KRB_NULL.
+ *
+ * For offset-based schemes offset relative to pp is calculated and assigned to *pp,
+ * if p is not KRB_NULL of course.
+ *
+ * @returns stored pointer.
+ * @param   pp      Pointer to where to store the pointer.
+ * @param   pp2     Pointer to where to pointer to assign to pp. This can be KRB_NULL
+ * @internal
+ */
+
+#ifndef KRBTREEPTR
+# define KRBTREEPTR                         KRBNODE *
+#endif
+
+#ifndef KRBROOT
+# define KRBROOT                            KRB_TYPE(,ROOT)
+# define KRB_NEED_KRBROOT
+#endif
+
+#ifdef KRB_CACHE_SIZE
+# ifndef KRB_CACHE_HASH
+#  define KRB_CACHE_HASH(Key)               ( (Key) % (KRB_CACHE_SIZE) )
+# endif
+#elif defined(KRB_CACHE_HASH)
+# error "KRB_CACHE_HASH without KRB_CACHE_SIZE!"
+#endif
+
+#ifdef KRB_CACHE_SIZE
+# define KRB_CACHE_INVALIDATE_NODE(pRoot, pNode, Key) \
+    do { \
+        KRBTREEPTR **ppEntry = &pRoot->maLookthru[KRB_CACHE_HASH(Key)]; \
+        if ((pNode) == KRB_GET_POINTER_NULL(ppEntry)) \
+            *ppEntry = KRB_NULL; \
+    } while (0)
+#else
+# define KRB_CACHE_INVALIDATE_NODE(pRoot, pNode, Key) do { } while (0)
+#endif
+
+#ifndef KRB_LOCKED
+# define KRB_WRITE_LOCK(pRoot)              do { } while (0)
+# define KRB_WRITE_UNLOCK(pRoot)            do { } while (0)
+# define KRB_READ_LOCK(pRoot)               do { } while (0)
+# define KRB_READ_UNLOCK(pRoot)             do { } while (0)
+#endif
+
+#ifdef KRB_OFFSET
+# define KRB_GET_POINTER(pp)                ( (KRBNODE *)((KIPTR)(pp) + *(pp)) )
+# define KRB_GET_POINTER_NULL(pp)           ( *(pp) != KRB_NULL ? KRB_GET_POINTER(pp) : NULL )
+# define KRB_SET_POINTER(pp, p)             ( (*(pp)) = ((KIPTR)(p) - (KIPTR)(pp)) )
+# define KRB_SET_POINTER_NULL(pp, pp2)      ( (*(pp)) = *(pp2) != KRB_NULL ? (KIPTR)KRB_GET_POINTER(pp2) - (KIPTR)(pp) : KRB_NULL )
+#else
+# define KRB_GET_POINTER(pp)                ( *(pp) )
+# define KRB_GET_POINTER_NULL(pp)           ( *(pp) )
+# define KRB_SET_POINTER(pp, p)             ( (*(pp)) = (p) )
+# define KRB_SET_POINTER_NULL(pp, pp2)      ( (*(pp)) = *(pp2) )
+#endif
+
+
+/** @def KRB_NULL
+ * The NULL 'pointer' equivalent.
+ */
+#ifdef KRB_OFFSET
+# define KRB_NULL     0
+#else
+# define KRB_NULL     NULL
+#endif
+
+#ifdef KRB_STD_KEY_COMP
+# define KRB_CMP_G(key1, key2)              ( (key1) >  (key2) )
+# define KRB_CMP_E(key1, key2)              ( (key1) == (key2) )
+# define KRB_CMP_NE(key1, key2)             ( (key1) != (key2) )
+# ifdef KRB_RANGE
+#  define KRB_R_IS_IDENTICAL(key1B, key2B, key1E, key2E)       ( (key1B) == (key2B) && (key1E) == (key2E) )
+#  define KRB_R_IS_INTERSECTING(key1B, key2B, key1E, key2E)    ( (key1B) <= (key2E) && (key1E) >= (key2B) )
+#  define KRB_R_IS_IN_RANGE(key1B, key1E, key2)                KRB_R_IS_INTERSECTING(key1B, key2, key1E, key2)
+# endif
+#endif
+
+#ifndef KRB_RANGE
+# define KRB_R_IS_INTERSECTING(key1B, key2B, key1E, key2E)     KRB_CMP_E(key1B, key2B)
+# define KRB_R_IS_IDENTICAL(key1B, key2B, key1E, key2E)        KRB_CMP_E(key1B, key2B)
+#endif
+
+
+/** Is the node red or black?
+ * @returns true / false
+ * @param   pNode       Pointer to the node in question.
+ * @remarks All NULL pointers are considered black leaf nodes.
+ */
+#define KRB_IS_RED(pNode)                   ( (pNode) != NULL && (pNode)->mfIsRed )
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Stack used to avoid recursive calls during insert and removal.
+ */
+typedef struct
+{
+    unsigned        cEntries;
+    KRBTREEPTR    *aEntries[KRB_MAX_STACK];
+} KRB_INT(STACK);
+
+/**
+ * The callback used by the Destroy and DoWithAll functions.
+ */
+typedef int (* KRB_TYPE(PFN,CALLBACK))(KRBNODE *, void *);
+
+#ifdef KRB_NEED_KRBROOT
+/**
+ * The Red-Black tree root structure.
+ */
+typedef struct
+{
+    KRBTREEPTR     mpRoot;
+# ifdef KRB_CACHE_SIZE
+    KRBTREEPTR     maLookthru[KRB_CACHE_SIZE];
+# endif
+} KRBROOT;
+#endif
+
+
+
+/**
+ * Initializes the root of the Red-Black tree.
+ *
+ * @param     pTree     Pointer to the root structure.
+ */
+KRB_DECL(void) KRB_FN(Init)(KRBROOT *pRoot)
+{
+#ifdef KRB_CACHE_SIZE
+    unsigned i;
+#endif
+
+    pRoot->mpRoot = KRB_NULL;
+#ifdef KRB_CACHE_SIZE
+    for (i = 0; i < (KRB_CACHE_SIZE); i++)
+        pRoot->maLookthru[i] = KRB_NULL;
+#endif
+}
+
+
+/**
+ * Rotates the tree to the left (shift direction) and recolors the nodes.
+ *
+ * @pre
+ *
+ *       2                 4
+ *      / \               / \
+ *     1   4     ==>     2   5
+ *        / \           / \
+ *       3   5         1   3
+ *
+ * @endpre
+ *
+ * @returns The new root node.
+ * @param   pRoot           The root node.
+ *
+ * @remarks This will not update any pointer <tt>to</tt> the root node!
+ */
+K_DECL_INLINE(KRBNODE *) KAVL_FN(RotateLeft)(KRBNODE *pRoot)
+{
+    KRBNODE *pNewRoot = pRoot->mRight;
+    pRoot->mRight     = pNewRoot->mLeft;
+    pNewRoot->mLeft   = pRoot;
+
+    pRoot->mfIsRed    = 1;
+    pNewRoot->mfIsRed = 0;
+    return pNewRoot;
+}
+
+
+/**
+ * Rotates the tree to the right (shift direction) and recolors the nodes.
+ *
+ * @pre
+ *
+ *         4             2
+ *        / \           / \
+ *       2   5   ==>   1   4
+ *      / \               / \
+ *     1   3             3   5
+ *
+ * @endpre
+ *
+ * @returns The new root node.
+ * @param   pRoot           The root node.
+ *
+ * @remarks This will not update any pointer <tt>to</tt> the root node!
+ */
+K_DECL_INLINE(KRBNODE *) KAVL_FN(RotateRight)(KRBNODE *pRoot)
+{
+    KRBNODE *pNewRoot = pRoot->mLeft;
+    pRoot->mLeft      = pNewRoot->mRight;
+    pNewRoot->mRight  = pRoot;
+
+    pRoot->mfIsRed    = 1;
+    pNewRoot->mfIsRed = 0;
+    return pNewRoot;
+}
+
+
+/**
+ * Performs a double left rotation with recoloring.
+ *
+ * @pre
+ *
+ *       2               2                    4
+ *      / \             / \                 /   \
+ *     1   6     ==>   1   4       ==>     2     6
+ *        / \             / \             / \   / \
+ *       4   7           3   6           1   3 5   7
+ *      / \                 / \
+ *     3   5               5   7
+ * @endpre
+ *
+ * @returns The new root node.
+ * @param   pRoot           The root node.
+ *
+ * @remarks This will not update any pointer <tt>to</tt> the root node!
+ */
+K_DECL_INLINE(KRBNODE *) KAVL_FN(DoubleRotateLeft)(KRBNODE *pRoot)
+{
+    pRoot->mRight = KAVL_FN(RotateRight)(pRoot->mRight);
+    return KAVL_FN(RotateLeft)(pRoot);
+}
+
+
+/**
+ * Performs a double right rotation with recoloring.
+ *
+ * @pre
+ *         6                 6                4
+ *        / \               / \             /   \
+ *       2   7             4   7           2     6
+ *      / \      ==>      / \      ==>    / \   / \
+ *     1   4             2   5           1   3 5   7
+ *        / \           / \
+ *       3   5         1   3
+ *
+ * @endpre
+ *
+ * @returns The new root node.
+ * @param   pRoot           The root node.
+ *
+ * @remarks This will not update any pointer <tt>to</tt> the root node!
+ */
+K_DECL_INLINE(KRBNODE *) KAVL_FN(DoubleRotateRight)(KRBNODE *pRoot)
+{
+    pRoot->mLeft = KAVL_FN(RotateLeft)(pRoot->mLeft);
+    return KAVL_FN(RotateRight)(pRoot);
+}
+
+
+/**
+ * Inserts a node into the Red-Black tree.
+ * @returns   K_TRUE if inserted.
+ *            K_FALSE if node exists in tree.
+ * @param     pRoot     Pointer to the Red-Back tree's root structure.
+ * @param     pNode     Pointer to the node which is to be added.
+ */
+KRB_DECL(KBOOL) KRB_FN(Insert)(KRBROOT *pRoot, KRBNODE *pNode)
+{
+    KRBTREEPTR        *ppCurNode = &pRoot->mpRoot;
+    register KRBKEY    Key       = pNode->mKey;
+#ifdef KRB_RANGE
+    register KRBKEY    KeyLast   = pNode->mKeyLast;
+#endif
+
+#ifdef KRB_RANGE
+    if (Key > KeyLast)
+        return K_FALSE;
+#endif
+
+    KRB_WRITE_LOCK(pRoot);
+
+    Stack.cEntries = 0;
+    while (*ppCurNode != KRB_NULL)
+    {
+        register KRBNODE *pCurNode = KRB_GET_POINTER(ppCurNode);
+
+        kHlpAssert(Stack.cEntries < KRB_MAX_STACK);
+        Stack.aEntries[Stack.cEntries++] = ppCurNode;
+#ifdef KRB_EQUAL_ALLOWED
+        if (KRB_R_IS_IDENTICAL(pCurNode->mKey, Key, pCurNode->mKeyLast, KeyLast))
+        {
+            /*
+             * If equal then we'll use a list of equal nodes.
+             */
+            pNode->mpLeft = pNode->mpRight = KRB_NULL;
+            pNode->mHeight = 0;
+            KRB_SET_POINTER_NULL(&pNode->mpList, &pCurNode->mpList);
+            KRB_SET_POINTER(&pCurNode->mpList, pNode);
+            KRB_WRITE_UNLOCK(pRoot);
+            return K_TRUE;
+        }
+#endif
+#ifdef KRB_CHECK_FOR_EQUAL_INSERT
+        if (KRB_R_IS_INTERSECTING(pCurNode->mKey, Key, pCurNode->mKeyLast, KeyLast))
+        {
+            KRB_WRITE_UNLOCK(pRoot);
+            return K_FALSE;
+        }
+#endif
+        if (KRB_CMP_G(pCurNode->mKey, Key))
+            ppCurNode = &pCurNode->mpLeft;
+        else
+            ppCurNode = &pCurNode->mpRight;
+    }
+
+    pNode->mpLeft = pNode->mpRight = KRB_NULL;
+#ifdef KRB_EQUAL_ALLOWED
+    pNode->mpList = KRB_NULL;
+#endif
+    pNode->mHeight = 1;
+    KRB_SET_POINTER(ppCurNode, pNode);
+
+    KRB_FN(Rebalance)(&Stack);
+
+    KRB_WRITE_UNLOCK(pRoot);
+    return K_TRUE;
+}
+
+
+/**
+ * Removes a node from the Red-Black tree.
+ * @returns   Pointer to the node.
+ * @param     pRoot     Pointer to the Red-Back tree's root structure.
+ * @param     Key       Key value of the node which is to be removed.
+ * @sketch    Find the node which is to be removed:
+ *            LOOP until not found
+ *            BEGIN
+ *                Add node pointer pointer to the AVL-stack.
+ *                IF the keys matches THEN break!
+ *                IF remove key < node key THEN
+ *                    left
+ *                ELSE
+ *                    right
+ *            END
+ *            IF found THEN
+ *            BEGIN
+ *                IF left node not empty THEN
+ *                BEGIN
+ *                    Find the right most node in the left tree while adding the pointer to the pointer to it's parent to the stack:
+ *                    Start at left node.
+ *                    LOOP until right node is empty
+ *                    BEGIN
+ *                        Add to stack.
+ *                        go right.
+ *                    END
+ *                    Link out the found node.
+ *                    Replace the node which is to be removed with the found node.
+ *                    Correct the stack entry for the pointer to the left tree.
+ *                END
+ *                ELSE
+ *                BEGIN
+ *                    Move up right node.
+ *                    Remove last stack entry.
+ *                END
+ *                Balance tree using stack.
+ *            END
+ *            return pointer to the removed node (if found).
+ */
+KRB_DECL(KRBNODE *) KRB_FN(Remove)(KRBROOT *pRoot, KRBKEY Key)
+{
+    KRB_INT(STACK)     Stack;
+    KRBTREEPTR        *ppDeleteNode = &pRoot->mpRoot;
+    register KRBNODE  *pDeleteNode;
+
+    KRB_WRITE_LOCK(pRoot);
+
+    Stack.cEntries = 0;
+    for (;;)
+    {
+        if (*ppDeleteNode == KRB_NULL)
+        {
+            KRB_WRITE_UNLOCK(pRoot);
+            return NULL;
+        }
+        pDeleteNode = KRB_GET_POINTER(ppDeleteNode);
+
+        kHlpAssert(Stack.cEntries < KRB_MAX_STACK);
+        Stack.aEntries[Stack.cEntries++] = ppDeleteNode;
+        if (KRB_CMP_E(pDeleteNode->mKey, Key))
+            break;
+
+        if (KRB_CMP_G(pDeleteNode->mKey, Key))
+            ppDeleteNode = &pDeleteNode->mpLeft;
+        else
+            ppDeleteNode = &pDeleteNode->mpRight;
+    }
+
+    if (pDeleteNode->mpLeft != KRB_NULL)
+    {
+        /* find the rightmost node in the left tree. */
+        const unsigned      iStackEntry = Stack.cEntries;
+        KRBTREEPTR        *ppLeftLeast = &pDeleteNode->mpLeft;
+        register KRBNODE  *pLeftLeast = KRB_GET_POINTER(ppLeftLeast);
+
+        while (pLeftLeast->mpRight != KRB_NULL)
+        {
+            kHlpAssert(Stack.cEntries < KRB_MAX_STACK);
+            Stack.aEntries[Stack.cEntries++] = ppLeftLeast;
+            ppLeftLeast = &pLeftLeast->mpRight;
+            pLeftLeast  = KRB_GET_POINTER(ppLeftLeast);
+        }
+
+        /* link out pLeftLeast */
+        KRB_SET_POINTER_NULL(ppLeftLeast, &pLeftLeast->mpLeft);
+
+        /* link it in place of the delete node. */
+        KRB_SET_POINTER_NULL(&pLeftLeast->mpLeft, &pDeleteNode->mpLeft);
+        KRB_SET_POINTER_NULL(&pLeftLeast->mpRight, &pDeleteNode->mpRight);
+        pLeftLeast->mHeight = pDeleteNode->mHeight;
+        KRB_SET_POINTER(ppDeleteNode, pLeftLeast);
+        Stack.aEntries[iStackEntry] = &pLeftLeast->mpLeft;
+    }
+    else
+    {
+        KRB_SET_POINTER_NULL(ppDeleteNode, &pDeleteNode->mpRight);
+        Stack.cEntries--;
+    }
+
+    KRB_FN(Rebalance)(&Stack);
+
+    KRB_CACHE_INVALIDATE_NODE(pRoot, pDeleteNode, Key);
+
+    KRB_WRITE_UNLOCK(pRoot);
+    return pDeleteNode;
+}
+
diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbDestroy.h b/src/lib/kStuff/include/k/kRbTmpl/kRbDestroy.h
new file mode 100644
index 0000000..0300a9a
--- /dev/null
+++ b/src/lib/kStuff/include/k/kRbTmpl/kRbDestroy.h
@@ -0,0 +1,129 @@
+/* $Id: kRbDestroy.h 35 2009-11-08 19:39:03Z bird $ */
+/** @file
+ * kRbTmpl - Templated Red-Black Trees, Destroy the tree.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Destroys the specified tree, starting with the root node and working our way down.
+ *
+ * @returns 0 on success.
+ * @returns Return value from callback on failure. On failure, the tree will be in
+ *          an unbalanced condition and only further calls to the Destroy should be
+ *          made on it. Note that the node we fail on will be considered dead and
+ *          no action is taken to link it back into the tree.
+ * @param   pRoot           Pointer to the Red-Back tree's root structure.
+ * @param   pfnCallBack     Pointer to callback function.
+ * @param   pvUser          User parameter passed on to the callback function.
+ */
+KRB_DECL(int) KRB_FN(Destroy)(KRBROOT *pRoot, KRB_TYPE(PFN,CALLBACK) pfnCallBack, void *pvUser)
+{
+#ifdef KRB_CACHE_SIZE
+    unsigned    i;
+#endif
+    unsigned    cEntries;
+    KRBNODE    *apEntries[KRB_MAX_STACK];
+    int         rc;
+
+    KRB_WRITE_LOCK(pRoot);
+    if (pRoot->mpRoot == KRB_NULL)
+    {
+        KRB_WRITE_UNLOCK(pRoot);
+        return 0;
+    }
+
+#ifdef KRB_CACHE_SIZE
+    /*
+     * Kill the lookthru cache.
+     */
+    for (i = 0; i < (KRB_CACHE_SIZE); i++)
+        pRoot->maLookthru[i] = KRB_NULL;
+#endif
+
+    cEntries = 1;
+    apEntries[0] = KRB_GET_POINTER(&pRoot->mpRoot);
+    while (cEntries > 0)
+    {
+        /*
+         * Process the subtrees first.
+         */
+        KRBNODE *pNode = apEntries[cEntries - 1];
+        if (pNode->mpLeft != KRB_NULL)
+            apEntries[cEntries++] = KRB_GET_POINTER(&pNode->mpLeft);
+        else if (pNode->mpRight != KRB_NULL)
+            apEntries[cEntries++] = KRB_GET_POINTER(&pNode->mpRight);
+        else
+        {
+#ifdef KRB_EQUAL_ALLOWED
+            /*
+             * Process nodes with the same key.
+             */
+            while (pNode->pList != KRB_NULL)
+            {
+                KRBNODE *pEqual = KRB_GET_POINTER(&pNode->pList);
+                KRB_SET_POINTER(&pNode->pList, KRB_GET_POINTER_NULL(&pEqual->pList));
+                pEqual->pList = KRB_NULL;
+
+                rc = pfnCallBack(pEqual, pvUser);
+                if (rc)
+                {
+                    KRB_WRITE_UNLOCK(pRoot);
+                    return rc;
+                }
+            }
+#endif
+
+            /*
+             * Unlink the node.
+             */
+            if (--cEntries > 0)
+            {
+                KRBNODE *pParent = apEntries[cEntries - 1];
+                if (KRB_GET_POINTER(&pParent->mpLeft) == pNode)
+                    pParent->mpLeft = KRB_NULL;
+                else
+                    pParent->mpRight = KRB_NULL;
+            }
+            else
+                pRoot->mpRoot = KRB_NULL;
+
+            kHlpAssert(pNode->mpLeft == KRB_NULL);
+            kHlpAssert(pNode->mpRight == KRB_NULL);
+            rc = pfnCallBack(pNode, pvUser);
+            if (rc)
+            {
+                KRB_WRITE_UNLOCK(pRoot);
+                return rc;
+            }
+        }
+    } /* while */
+    kHlpAssert(pRoot->mpRoot == KRB_NULL);
+
+    KRB_WRITE_UNLOCK(pRoot);
+    return 0;
+}
+
diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbDoWithAll.h b/src/lib/kStuff/include/k/kRbTmpl/kRbDoWithAll.h
new file mode 100644
index 0000000..a9de71c
--- /dev/null
+++ b/src/lib/kStuff/include/k/kRbTmpl/kRbDoWithAll.h
@@ -0,0 +1,166 @@
+/* $Id: kRbDoWithAll.h 35 2009-11-08 19:39:03Z bird $ */
+/** @file
+ * kRbTmpl - Templated Red-Black Trees, The Callback Iterator.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Stack used by DoWithAll to avoid recusive function calls.
+ */
+typedef struct
+{
+    unsigned        cEntries;
+    KRBNODE        *aEntries[KRB_MAX_STACK];
+    char            achFlags[KRB_MAX_STACK];
+    KRBROOT        pRoot;
+} KRB_INT(STACK2);
+
+
+/**
+ * Iterates thru all nodes in the given tree.
+ *
+ * @returns   0 on success. Return from callback on failure.
+ * @param     pRoot        Pointer to the Red-Back tree's root structure.
+ * @param     fFromLeft    K_TRUE:  Left to right.
+ *                         K_FALSE: Right to left.
+ * @param     pfnCallBack  Pointer to callback function.
+ * @param     pvUser       User parameter passed on to the callback function.
+ */
+KRB_DECL(int) KRB_FN(DoWithAll)(KRBROOT *pRoot, KBOOL fFromLeft, KRB_TYPE(PFN,CALLBACK) pfnCallBack, void *pvUser)
+{
+    KRB_INT(STACK2)     Stack;
+    KRBNODE            *pNode;
+#ifdef KRB_EQUAL_ALLOWED
+    KRBNODE            *pEqual;
+#endif
+    int                 rc;
+
+    KRB_READ_LOCK(pRoot);
+    if (pRoot->mpRoot == KRB_NULL)
+    {
+        KRB_READ_UNLOCK(pRoot);
+        return 0;
+    }
+
+    Stack.cEntries = 1;
+    Stack.achFlags[0] = 0;
+    Stack.aEntries[0] = KRB_GET_POINTER(&pRoot->mpRoot);
+
+    if (fFromLeft)
+    {   /* from left */
+        while (Stack.cEntries > 0)
+        {
+            pNode = Stack.aEntries[Stack.cEntries - 1];
+
+            /* left */
+            if (!Stack.achFlags[Stack.cEntries - 1]++)
+            {
+                if (pNode->mpLeft != KRB_NULL)
+                {
+                    Stack.achFlags[Stack.cEntries] = 0; /* 0 first, 1 last */
+                    Stack.aEntries[Stack.cEntries++] = KRB_GET_POINTER(&pNode->mpLeft);
+                    continue;
+                }
+            }
+
+            /* center */
+            rc = pfnCallBack(pNode, pvUser);
+            if (rc)
+                return rc;
+#ifdef KRB_EQUAL_ALLOWED
+            if (pNode->mpList != KRB_NULL)
+                for (pEqual = KRB_GET_POINTER(&pNode->mpList); pEqual; pEqual = KRB_GET_POINTER_NULL(&pEqual->mpList))
+                {
+                    rc = pfnCallBack(pEqual, pvUser);
+                    if (rc)
+                    {
+                        KRB_READ_UNLOCK(pRoot);
+                        return rc;
+                    }
+                }
+#endif
+
+            /* right */
+            Stack.cEntries--;
+            if (pNode->mpRight != KRB_NULL)
+            {
+                Stack.achFlags[Stack.cEntries] = 0;
+                Stack.aEntries[Stack.cEntries++] = KRB_GET_POINTER(&pNode->mpRight);
+            }
+        } /* while */
+    }
+    else
+    {   /* from right */
+        while (Stack.cEntries > 0)
+        {
+            pNode = Stack.aEntries[Stack.cEntries - 1];
+
+            /* right */
+            if (!Stack.achFlags[Stack.cEntries - 1]++)
+            {
+                if (pNode->mpRight != KRB_NULL)
+                {
+                    Stack.achFlags[Stack.cEntries] = 0;  /* 0 first, 1 last */
+                    Stack.aEntries[Stack.cEntries++] = KRB_GET_POINTER(&pNode->mpRight);
+                    continue;
+                }
+            }
+
+            /* center */
+            rc = pfnCallBack(pNode, pvUser);
+            if (rc)
+                return rc;
+#ifdef KRB_EQUAL_ALLOWED
+            if (pNode->mpList != KRB_NULL)
+                for (pEqual = KRB_GET_POINTER(&pNode->mpList); pEqual; pEqual = KRB_GET_POINTER_NULL(&pEqual->pList))
+                {
+                    rc = pfnCallBack(pEqual, pvUser);
+                    if (rc)
+                    {
+                        KRB_READ_UNLOCK(pRoot);
+                        return rc;
+                    }
+                }
+#endif
+
+            /* left */
+            Stack.cEntries--;
+            if (pNode->mpLeft != KRB_NULL)
+            {
+                Stack.achFlags[Stack.cEntries] = 0;
+                Stack.aEntries[Stack.cEntries++] = KRB_GET_POINTER(&pNode->mpLeft);
+            }
+        } /* while */
+    }
+
+    KRB_READ_UNLOCK(pRoot);
+    return 0;
+}
+
diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbEnum.h b/src/lib/kStuff/include/k/kRbTmpl/kRbEnum.h
new file mode 100644
index 0000000..d022410
--- /dev/null
+++ b/src/lib/kStuff/include/k/kRbTmpl/kRbEnum.h
@@ -0,0 +1,187 @@
+/* $Id: kRbEnum.h 35 2009-11-08 19:39:03Z bird $ */
+/** @file
+ * kRbTmpl - Templated Red-Black Trees, Node Enumeration.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Enumeration control data.
+ *
+ * This is initialized by BeginEnum and used by GetNext to figure out what
+ * to do next.
+ */
+typedef struct KRB_TYPE(,ENUMDATA)
+{
+    KBOOL               fFromLeft;
+    KI8                 cEntries;
+    KU8                 achFlags[KRB_MAX_STACK];
+    KRBNODE *           aEntries[KRB_MAX_STACK];
+} KRB_TYPE(,ENUMDATA), *KRB_TYPE(P,ENUMDATA);
+
+
+/**
+ * Ends an enumeration.
+ *
+ * The purpose of this function is to unlock the tree should the Red-Black tree
+ * implementation include locking.  It's good practice to call it anyway even if
+ * the tree doesn't do any locking.
+ *
+ * @param   pEnumData   Pointer to enumeration control data.
+ */
+KRB_DECL(void) KRB_FN(EndEnum)(KRB_TYPE(,ENUMDATA) *pEnumData)
+{
+    KRBROOT pRoot = pEnumData->pRoot;
+    pEnumData->pRoot = NULL;
+    if (pRoot)
+        KRB_READ_UNLOCK(pEnumData->pRoot);
+}
+
+
+/**
+ * Get the next node in the tree enumeration.
+ *
+ * The current implementation of this function willl not walk the mpList
+ * chain like the DoWithAll function does. This may be changed later.
+ *
+ * @returns Pointer to the next node in the tree.
+ *          NULL is returned when the end of the tree has been reached,
+ *          it is not necessary to call EndEnum in this case.
+ * @param   pEnumData   Pointer to enumeration control data.
+ */
+KRB_DECL(KRBNODE *) KRB_FN(GetNext)(KRB_TYPE(,ENUMDATA) *pEnumData)
+{
+    if (pEnumData->fFromLeft)
+    {   /* from left */
+        while (pEnumData->cEntries > 0)
+        {
+            KRBNODE *pNode = pEnumData->aEntries[pEnumData->cEntries - 1];
+
+            /* left */
+            if (pEnumData->achFlags[pEnumData->cEntries - 1] == 0)
+            {
+                pEnumData->achFlags[pEnumData->cEntries - 1]++;
+                if (pNode->mpLeft != KRB_NULL)
+                {
+                    pEnumData->achFlags[pEnumData->cEntries] = 0; /* 0 left, 1 center, 2 right */
+                    pEnumData->aEntries[pEnumData->cEntries++] = KRB_GET_POINTER(&pNode->mpLeft);
+                    continue;
+                }
+            }
+
+            /* center */
+            if (pEnumData->achFlags[pEnumData->cEntries - 1] == 1)
+            {
+                pEnumData->achFlags[pEnumData->cEntries - 1]++;
+                return pNode;
+            }
+
+            /* right */
+            pEnumData->cEntries--;
+            if (pNode->mpRight != KRB_NULL)
+            {
+                pEnumData->achFlags[pEnumData->cEntries] = 0;
+                pEnumData->aEntries[pEnumData->cEntries++] = KRB_GET_POINTER(&pNode->mpRight);
+            }
+        } /* while */
+    }
+    else
+    {   /* from right */
+        while (pEnumData->cEntries > 0)
+        {
+            KRBNODE *pNode = pEnumData->aEntries[pEnumData->cEntries - 1];
+
+            /* right */
+            if (pEnumData->achFlags[pEnumData->cEntries - 1] == 0)
+            {
+                pEnumData->achFlags[pEnumData->cEntries - 1]++;
+                if (pNode->mpRight != KRB_NULL)
+                {
+                    pEnumData->achFlags[pEnumData->cEntries] = 0;  /* 0 right, 1 center, 2 left */
+                    pEnumData->aEntries[pEnumData->cEntries++] = KRB_GET_POINTER(&pNode->mpRight);
+                    continue;
+                }
+            }
+
+            /* center */
+            if (pEnumData->achFlags[pEnumData->cEntries - 1] == 1)
+            {
+                pEnumData->achFlags[pEnumData->cEntries - 1]++;
+                return pNode;
+            }
+
+            /* left */
+            pEnumData->cEntries--;
+            if (pNode->mpLeft != KRB_NULL)
+            {
+                pEnumData->achFlags[pEnumData->cEntries] = 0;
+                pEnumData->aEntries[pEnumData->cEntries++] = KRB_GET_POINTER(&pNode->mpLeft);
+            }
+        } /* while */
+    }
+
+    /*
+     * Call EndEnum.
+     */
+    KRB_FN(EndEnum)(pEnumData);
+    return NULL;
+}
+
+
+/**
+ * Starts an enumeration of all nodes in the given tree.
+ *
+ * The current implementation of this function will not walk the mpList
+ * chain like the DoWithAll function does. This may be changed later.
+ *
+ * @returns Pointer to the first node in the enumeration.
+ *          If NULL is returned the tree is empty calling EndEnum isn't
+ *          strictly necessary (although it will do no harm).
+ * @param   pRoot           Pointer to the Red-Back tree's root structure.
+ * @param   pEnumData       Pointer to enumeration control data.
+ * @param   fFromLeft       K_TRUE:  Left to right.
+ *                          K_FALSE: Right to left.
+ */
+KRB_DECL(KRBNODE *) KRB_FN(BeginEnum)(KRBROOT *pRoot, KRB_TYPE(,ENUMDATA) *pEnumData, KBOOL fFromLeft)
+{
+    KRB_READ_LOCK(pRoot);
+    pEnumData->pRoot = pRoot;
+    if (pRoot->mpRoot != KRB_NULL)
+    {
+        pEnumData->fFromLeft = fFromLeft;
+        pEnumData->cEntries = 1;
+        pEnumData->aEntries[0] = KRB_GET_POINTER(pRoot->mpRoot);
+        pEnumData->achFlags[0] = 0;
+    }
+    else
+        pEnumData->cEntries = 0;
+
+    return KRB_FN(GetNext)(pEnumData);
+}
+
diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbGet.h b/src/lib/kStuff/include/k/kRbTmpl/kRbGet.h
new file mode 100644
index 0000000..b03d4e1
--- /dev/null
+++ b/src/lib/kStuff/include/k/kRbTmpl/kRbGet.h
@@ -0,0 +1,89 @@
+/* $Id: kRbGet.h 35 2009-11-08 19:39:03Z bird $ */
+/** @file
+ * kRbTmpl - Templated Red-Black Trees, Get a Node.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Gets a node from the tree (does not remove it!)
+ *
+ * @returns Pointer to the node holding the given key.
+ * @param   pRoot       Pointer to the Red-Back tree's root structure.
+ * @param   Key         Key value of the node which is to be found.
+ */
+KRB_DECL(KRBNODE *) KRB_FN(Get)(KRBROOT *pRoot, KRBKEY Key)
+{
+    KRBNODE *pNode;
+#ifdef KRB_CACHE_SIZE
+    KRBTREEPTR *ppEntry;
+#endif
+
+    KRB_READ_LOCK(pRoot);
+    if (pRoot->mpRoot == KRB_NULL)
+    {
+        KRB_READ_UNLOCK(pRoot);
+        return NULL;
+    }
+
+#ifdef KRB_CACHE_SIZE
+    ppEntry = &pRoot->maLookthru[KRB_CACHE_HASH(Key)];
+    pNode = KRB_GET_POINTER_NULL(ppEntry);
+    if (!pNode || KRB_CMP_NE(pNode->mKey, Key))
+#endif
+    {
+        pNode = KRB_GET_POINTER(&pRoot->mpRoot);
+        while (KRB_CMP_NE(pNode->mKey, Key))
+        {
+            if (KRB_CMP_G(pNode->mKey, Key))
+            {
+                if (pNode->mpLeft == KRB_NULL)
+                {
+                    KRB_READ_UNLOCK(pRoot);
+                    return NULL;
+                }
+                pNode = KRB_GET_POINTER(&pNode->mpLeft);
+            }
+            else
+            {
+                if (pNode->mpRight == KRB_NULL)
+                {
+                    KRB_READ_UNLOCK(pRoot);
+                    return NULL;
+                }
+                pNode = KRB_GET_POINTER(&pNode->mpRight);
+            }
+        }
+
+#ifdef KRB_CACHE_SIZE
+        KRB_SET_POINTER(ppEntry, pNode);
+#endif
+    }
+
+    KRB_READ_UNLOCK(pRoot);
+    return pNode;
+}
+
diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbGetBestFit.h b/src/lib/kStuff/include/k/kRbTmpl/kRbGetBestFit.h
new file mode 100644
index 0000000..bfda27a
--- /dev/null
+++ b/src/lib/kStuff/include/k/kRbTmpl/kRbGetBestFit.h
@@ -0,0 +1,112 @@
+/* $Id: kRbGetBestFit.h 35 2009-11-08 19:39:03Z bird $ */
+/** @file
+ * kRbTmpl - Templated Red-Black Trees, Get Best Fitting Node.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Finds the best fitting node in the tree for the given Key value.
+ *
+ * @returns Pointer to the best fitting node found.
+ * @param   pRoot           Pointer to the Red-Back tree's root structure.
+ * @param   Key             The Key of which is to be found a best fitting match for..
+ * @param   fAbove          K_TRUE:  Returned node is have the closest key to Key from above.
+ *                          K_FALSE: Returned node is have the closest key to Key from below.
+ * @sketch  The best fitting node is always located in the searchpath above you.
+ *          >= (above): The node where you last turned left.
+ *          <= (below): the node where you last turned right.
+ */
+KRB_DECL(KRBNODE *) KRB_FN(GetBestFit)(KRBROOT *pRoot, KRBKEY Key, KBOOL fAbove)
+{
+    register KRBNODE  *pNode;
+    KRBNODE           *pNodeLast;
+
+    KRB_READ_LOCK(pLook);
+    if (pRoot->mpRoot == KRB_NULL)
+    {
+        KRB_READ_UNLOCK(pLook);
+        return NULL;
+    }
+
+    pNode = KRB_GET_POINTER(&pRoot->mpRoot);
+    pNodeLast = NULL;
+    if (fAbove)
+    {   /* pNode->mKey >= Key */
+        while (KRB_CMP_NE(pNode->mKey, Key))
+        {
+            if (KRB_CMP_G(pNode->mKey, Key))
+            {
+                if (pNode->mpLeft == KRB_NULL)
+                {
+                    KRB_READ_UNLOCK(pLook);
+                    return pNode;
+                }
+                pNodeLast = pNode;
+                pNode = KRB_GET_POINTER(&pNode->mpLeft);
+            }
+            else
+            {
+                if (pNode->mpRight == KRB_NULL)
+                {
+                    KRB_READ_UNLOCK(pLook);
+                    return pNodeLast;
+                }
+                pNode = KRB_GET_POINTER(&pNode->mpRight);
+            }
+        }
+    }
+    else
+    {   /* pNode->mKey <= Key */
+        while (KRB_CMP_NE(pNode->mKey, Key))
+        {
+            if (KRB_CMP_G(pNode->mKey, Key))
+            {
+                if (pNode->mpLeft == KRB_NULL)
+                {
+                    KRB_READ_UNLOCK(pLook);
+                    return pNodeLast;
+                }
+                pNode = KRB_GET_POINTER(&pNode->mpLeft);
+            }
+            else
+            {
+                if (pNode->mpRight == KRB_NULL)
+                {
+                    KRB_READ_UNLOCK(pLook);
+                    return pNode;
+                }
+                pNodeLast = pNode;
+                pNode = KRB_GET_POINTER(&pNode->mpRight);
+            }
+        }
+    }
+
+    /* perfect match or nothing. */
+    KRB_READ_UNLOCK(pLook);
+    return pNode;
+}
+
diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbGetWithParent.h b/src/lib/kStuff/include/k/kRbTmpl/kRbGetWithParent.h
new file mode 100644
index 0000000..05a7d8c
--- /dev/null
+++ b/src/lib/kStuff/include/k/kRbTmpl/kRbGetWithParent.h
@@ -0,0 +1,65 @@
+/* $Id: kRbGetWithParent.h 35 2009-11-08 19:39:03Z bird $ */
+/** @file
+ * kRbTmpl - Templated Red-Black Trees, Get Node With Parent.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Gets a node from the tree and its parent node (if any).
+ * The tree remains unchanged.
+ *
+ * @returns Pointer to the node holding the given key.
+ * @param   pRoot       Pointer to the Red-Back tree's root structure.
+ * @param   ppParent    Pointer to a variable which will hold the pointer to the partent node on
+ *                      return. When no node is found, this will hold the last searched node.
+ * @param   Key         Key value of the node which is to be found.
+ */
+KRB_DECL(KRBNODE *) KRB_FN(GetWithParent)(KRBROOT *pRoot, KRBNODE **ppParent, KRBKEY Key)
+{
+    register KRBNODE *pNode;
+    register KRBNODE *pParent;
+
+    KRB_READ_LOCK(pRoot);
+
+    pParent = NULL;
+    pNode = KRB_GET_POINTER_NULL(&pRoot->mpRoot);
+    while (     pNode != NULL
+           &&   KRB_CMP_NE(pNode->mKey, Key))
+    {
+        pParent = pNode;
+        if (KRB_CMP_G(pNode->mKey, Key))
+            pNode = KRB_GET_POINTER_NULL(&pNode->mpLeft);
+        else
+            pNode = KRB_GET_POINTER_NULL(&pNode->mpRight);
+    }
+
+    KRB_READ_UNLOCK(pRoot);
+
+    *ppParent = pParent;
+    return pNode;
+}
+
diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbRemove2.h b/src/lib/kStuff/include/k/kRbTmpl/kRbRemove2.h
new file mode 100644
index 0000000..deed81d
--- /dev/null
+++ b/src/lib/kStuff/include/k/kRbTmpl/kRbRemove2.h
@@ -0,0 +1,133 @@
+/* $Id: kRbRemove2.h 35 2009-11-08 19:39:03Z bird $ */
+/** @file
+ * kRbTmpl - Templated Red-Black Trees, Remove A Specific Node.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Removes the specified node from the tree.
+ *
+ * @returns Pointer to the removed node (NULL if not in the tree)
+ * @param   pRoot       Pointer to the Red-Back tree's root structure.
+ * @param   Key         The Key of which is to be found a best fitting match for..
+ *
+ * @remark  This implementation isn't the most efficient, but this short and
+ *          easier to manage.
+ */
+KRB_DECL(KRBNODE *) KRB_FN(Remove2)(KRBROOT *pRoot, KRBNODE *pNode)
+{
+#ifdef KRB_EQUAL_ALLOWED
+    /*
+     * Find the right node by key and see if it's what we want.
+     */
+    KRBNODE *pParent;
+    KRBNODE *pCurNode = KRB_FN(GetWithParent)(pRoot, pNode->mKey, &pParent);
+    if (!pCurNode)
+        return NULL;
+    KRB_WRITE_LOCK(pRoot); /** @todo the locking here isn't 100% sane. The only way to archive that is by no calling worker functions. */
+    if (pCurNode != pNode)
+    {
+        /*
+         * It's not the one we want, but it could be in the duplicate list.
+         */
+        while (pCurNode->mpList != KRB_NULL)
+        {
+            KRBNODE *pNext = KRB_GET_POINTER(&pCurNode->mpList);
+            if (pNext == pNode)
+            {
+                KRB_SET_POINTER_NULL(&pCurNode->mpList, KRB_GET_POINTER_NULL(&pNode->mpList));
+                pNode->mpList = KRB_NULL;
+                KRB_CACHE_INVALIDATE_NODE(pRoot, pNode, pNode->mKey);
+                KRB_WRITE_UNLOCK(pRoot);
+                return pNode;
+            }
+            pCurNode = pNext;
+        }
+        KRB_WRITE_UNLOCK(pRoot);
+        return NULL;
+    }
+
+    /*
+     * Ok, it's the one we want alright.
+     *
+     * Simply remove it if it's the only one with they Key,
+     * if there are duplicates we'll have to unlink it and
+     * insert the first duplicate in our place.
+     */
+    if (pNode->mpList == KRB_NULL)
+    {
+        KRB_WRITE_UNLOCK(pRoot);
+        KRB_FN(Remove)(pRoot, pNode->mKey);
+    }
+    else
+    {
+        KRBNODE *pNewUs = KRB_GET_POINTER(&pNode->mpList);
+
+        pNewUs->mHeight = pNode->mHeight;
+
+        if (pNode->mpLeft != KRB_NULL)
+            KRB_SET_POINTER(&pNewUs->mpLeft, KRB_GET_POINTER(&pNode->mpLeft))
+        else
+            pNewUs->mpLeft = KRB_NULL;
+
+        if (pNode->mpRight != KRB_NULL)
+            KRB_SET_POINTER(&pNewUs->mpRight, KRB_GET_POINTER(&pNode->mpRight))
+        else
+            pNewUs->mpRight = KRB_NULL;
+
+        if (pParent)
+        {
+            if (KRB_GET_POINTER_NULL(&pParent->mpLeft) == pNode)
+                KRB_SET_POINTER(&pParent->mpLeft, pNewUs);
+            else
+                KRB_SET_POINTER(&pParent->mpRight, pNewUs);
+        }
+        else
+            KRB_SET_POINTER(&pRoot->mpRoot, pNewUs);
+
+        KRB_CACHE_INVALIDATE_NODE(pRoot, pNode, pNode->mKey);
+        KRB_WRITE_UNLOCK(pRoot);
+    }
+
+    return pNode;
+
+#else
+    /*
+     * Delete it, if we got the wrong one, reinsert it.
+     *
+     * This ASSUMS that the caller is NOT going to hand us a lot
+     * of wrong nodes but just uses this API for his convenience.
+     */
+    KRBNODE *pRemovedNode = KRB_FN(Remove)(pRoot, pNode->mKey);
+    if (pRemovedNode == pNode)
+        return pRemovedNode;
+
+    KRB_FN(Insert)(pRoot, pRemovedNode);
+    return NULL;
+#endif
+}
+
diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbRemoveBestFit.h b/src/lib/kStuff/include/k/kRbTmpl/kRbRemoveBestFit.h
new file mode 100644
index 0000000..17fc66d
--- /dev/null
+++ b/src/lib/kStuff/include/k/kRbTmpl/kRbRemoveBestFit.h
@@ -0,0 +1,70 @@
+/* $Id: kRbRemoveBestFit.h 35 2009-11-08 19:39:03Z bird $ */
+/** @file
+ * kRbTmpl - Templated Red-Black Trees, Remove Best Fitting Node.
+ */
+
+/*
+ * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Finds the best fitting node in the tree for the given Key value and removes the node.
+ *
+ * @returns Pointer to the removed node.
+ * @param   pRoot       Pointer to the Red-Back tree's root structure.
+ * @param   Key         The Key of which is to be found a best fitting match for..
+ * @param   fAbove      K_TRUE:  Returned node is have the closest key to Key from above.
+ *                      K_FALSE: Returned node is have the closest key to Key from below.
+ *
+ * @remark  This implementation uses GetBestFit and then Remove and might therefore
+ *          not be the most optimal kind of implementation, but it reduces the complexity
+ *          code size, and the likelyhood for bugs.
+ */
+KRB_DECL(KRBNODE *) KRB_FN(RemoveBestFit)(KRBROOT *pRoot, KRBKEY Key, KBOOL fAbove)
+{
+    /*
+     * If we find anything we'll have to remove the node and return it.
+     * Now, if duplicate keys are allowed we'll remove a duplicate before
+     * removing the in-tree node as this is way cheaper.
+     */
+    KRBNODE *pNode = KRB_FN(GetBestFit)(pRoot, Key, fAbove);
+    if (pNode != NULL)
+    {
+#ifdef KRB_EQUAL_ALLOWED
+        KRB_WRITE_LOCK(pRoot); /** @todo the locking isn't quite sane here. :-/ */
+        if (pNode->mpList != KRB_NULL)
+        {
+            KRBNODE *pRet = KRB_GET_POINTER(&pNode->mpList);
+            KRB_SET_POINTER_NULL(&pNode->mpList, &pRet->mpList);
+            KRB_CACHE_INVALIDATE_NODE(pRoot, pNode, pNode->mKey);
+            KRB_WRITE_UNLOCK(pRoot);
+            return pRet;
+        }
+        KRB_WRITE_UNLOCK(pRoot);
+#endif
+        pNode = KRB_FN(Remove)(pRoot, pNode->mKey);
+    }
+    return pNode;
+}
+
diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbUndef.h b/src/lib/kStuff/include/k/kRbTmpl/kRbUndef.h
new file mode 100644
index 0000000..793108b
--- /dev/null
+++ b/src/lib/kStuff/include/k/kRbTmpl/kRbUndef.h
@@ -0,0 +1,79 @@
+/* $Id: kRbUndef.h 35 2009-11-08 19:39:03Z bird $ */
+/** @file
+ * kRbTmpl - Undefines All Macros (both config and temp).
+ */
+
+/*
+ * Copyright (c) 2006-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The configuration.
+ */
+#undef KRB_EQUAL_ALLOWED
+#undef KRB_CHECK_FOR_EQUAL_INSERT
+#undef KRB_MAX_STACK
+#undef KRB_RANGE
+#undef KRB_OFFSET
+#undef KRB_STD_KEY_COMP
+#undef KRB_CACHE_SIZE
+#undef KRB_CACHE_HASH
+#undef KRB_LOCKED
+#undef KRB_WRITE_LOCK
+#undef KRB_WRITE_UNLOCK
+#undef KRB_READ_LOCK
+#undef KRB_READ_UNLOCK
+#undef KRBKEY
+#undef KRBNODE
+#undef KRBTREEPTR
+#undef KRBROOT
+#undef KRB_FN
+#undef KRB_TYPE
+#undef KRB_INT
+#undef KRB_DECL
+#undef mKey
+#undef mKeyLast
+#undef mfIsRed
+#undef mpLeft
+#undef mpRight
+#undef mpList
+#undef mpRoot
+#undef maLookthru
+#undef KRB_CMP_G
+#undef KRB_CMP_E
+#undef KRB_CMP_NE
+#undef KRB_R_IS_IDENTICAL
+#undef KRB_R_IS_INTERSECTING
+#undef KRB_R_IS_IN_RANGE
+
+/*
+ * Internal ones.
+ */
+#undef KRB_IS_RED
+#undef KRB_NULL
+#undef KRB_GET_POINTER
+#undef KRB_GET_POINTER_NULL
+#undef KRB_SET_POINTER
+#undef KRB_SET_POINTER_NULL
+
diff --git a/src/lib/kStuff/include/k/kRbU32.h b/src/lib/kStuff/include/k/kRbU32.h
new file mode 100644
index 0000000..3b68b5e
--- /dev/null
+++ b/src/lib/kStuff/include/k/kRbU32.h
@@ -0,0 +1,68 @@
+/* $Id: kRbU32.h 35 2009-11-08 19:39:03Z bird $ */
+/** @file
+ * kRb - Red-Black Tree Implementation, KU32 keys.
+ */
+
+/*
+ * Copyright (c) 2006-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kRbU32_h___
+#define ___k_kRbU32_h___
+
+typedef struct KRBU32
+{
+    KU32                mKey;
+    KBOOL               mfRed;
+    struct KRBU32      *mpLeft;
+    struct KRBU32      *mpRight;
+} KRBU32;
+typedef KRBU32  *PRBU32;
+typedef KRBU32 **PPRBU32;
+
+/*#define KRB_EQUAL_ALLOWED*/
+#define KRB_CHECK_FOR_EQUAL_INSERT
+/*#define KRB_RANGE */
+/*#define KRB_OFFSET */
+#define KRB_MAX_STACK           48
+#define KRB_STD_KEY_COMP
+#define KRBKEY                  KU32
+#define KRBNODE                 KRBU32
+#define KRB_FN(name)            kRbU32 ## name
+#define KRB_TYPE(prefix,name)   prefix ## KRBU32 ## name
+#define KRB_INT(name)           KRBU32INT ## name
+#define KRB_DECL(rettype)       K_DECL_INLINE(rettype)
+
+#include <k/kRbTmpl/kRbBase.h>
+#include <k/kRbTmpl/kRbDoWithAll.h>
+#include <k/kRbTmpl/kRbEnum.h>
+#include <k/kRbTmpl/kRbGet.h>
+#include <k/kRbTmpl/kRbGetBestFit.h>
+#include <k/kRbTmpl/kRbGetWithParent.h>
+#include <k/kRbTmpl/kRbRemove2.h>
+#include <k/kRbTmpl/kRbRemoveBestFit.h>
+#include <k/kRbTmpl/kRbUndef.h>
+
+#endif
+
diff --git a/src/lib/kStuff/include/k/kRdr.h b/src/lib/kStuff/include/k/kRdr.h
new file mode 100644
index 0000000..7e0b5e8
--- /dev/null
+++ b/src/lib/kStuff/include/k/kRdr.h
@@ -0,0 +1,86 @@
+/* $Id: kRdr.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kRdr - The File Provider.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___kRdr_h___
+#define ___kRdr_h___
+
+#include <k/kDefs.h>
+#include <k/kTypes.h>
+
+/** @defgroup grp_kRdr      kRdr - The File Provider
+ * @{ */
+
+/** @def KRDR_DECL
+ * Declares a kRdr function according to build context.
+ * @param type          The return type.
+ */
+#if defined(KRDR_BUILDING_DYNAMIC)
+# define KRDR_DECL(type)    K_DECL_EXPORT(type)
+#elif defined(KRDR_BUILT_DYNAMIC)
+# define KRDR_DECL(type)    K_DECL_IMPORT(type)
+#else
+# define KRDR_DECL(type)    type
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+KRDR_DECL(int)      kRdrOpen(   PPKRDR ppRdr, const char *pszFilename);
+KRDR_DECL(int)      kRdrClose(    PKRDR pRdr);
+KRDR_DECL(int)      kRdrRead(     PKRDR pRdr, void *pvBuf, KSIZE cb, KFOFF off);
+KRDR_DECL(int)      kRdrAllMap(   PKRDR pRdr, const void **ppvBits);
+KRDR_DECL(int)      kRdrAllUnmap( PKRDR pRdr, const void *pvBits);
+KRDR_DECL(KFOFF)    kRdrSize(     PKRDR pRdr);
+KRDR_DECL(KFOFF)    kRdrTell(     PKRDR pRdr);
+KRDR_DECL(const char *) kRdrName( PKRDR pRdr);
+KRDR_DECL(KIPTR)    kRdrNativeFH( PKRDR pRdr);
+KRDR_DECL(KSIZE)    kRdrPageSize( PKRDR pRdr);
+KRDR_DECL(int)      kRdrMap(      PKRDR pRdr, void **ppvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fFixed);
+KRDR_DECL(int)      kRdrRefresh(  PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments);
+KRDR_DECL(int)      kRdrProtect(  PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fUnprotectOrProtect);
+KRDR_DECL(int)      kRdrUnmap(    PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments);
+KRDR_DECL(void)     kRdrDone(     PKRDR pRdr);
+
+KRDR_DECL(int)      kRdrBufOpen(PPKRDR ppRdr, const char *pszFilename);
+KRDR_DECL(int)      kRdrBufWrap(PPKRDR ppRdr, PKRDR pRdr, KBOOL fCloseIt);
+KRDR_DECL(KBOOL)    kRdrBufIsBuffered(PKRDR pRdr);
+KRDR_DECL(int)      kRdrBufLine(PKRDR pRdr, char *pszLine, KSIZE cbLine);
+KRDR_DECL(int)      kRdrBufLineEx(PKRDR pRdr, char *pszLine, KSIZE *pcbLine);
+KRDR_DECL(const char *) kRdrBufLineQ(PKRDR pRdr);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif
+
diff --git a/src/lib/kStuff/include/k/kRdrAll.h b/src/lib/kStuff/include/k/kRdrAll.h
new file mode 100644
index 0000000..78f946f
--- /dev/null
+++ b/src/lib/kStuff/include/k/kRdrAll.h
@@ -0,0 +1,127 @@
+/* $Id: kRdrAll.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kRdr - The File Provider, All Details and Dependencies Included.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___k_kRdrAll_h___
+#define ___k_kRdrAll_h___
+
+#include <k/kDefs.h>
+#include <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, KSIZE 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, KBOOL 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, KBOOL 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
+
diff --git a/src/lib/k/kTypes.h b/src/lib/kStuff/include/k/kTypes.h
similarity index 93%
rename from src/lib/k/kTypes.h
rename to src/lib/kStuff/include/k/kTypes.h
index 4178f37..d79f295 100644
--- a/src/lib/k/kTypes.h
+++ b/src/lib/kStuff/include/k/kTypes.h
@@ -1,27 +1,31 @@
-/* $Id: kTypes.h 3610 2007-10-29 03:33:14Z bird $ */
+/* $Id: kTypes.h 29 2009-07-01 20:30:29Z bird $ */
 /** @file
- *
  * kTypes - Typedefs And Related Constants And Macros.
+ */
+
+/*
+ * Copyright (c) 2006-2009 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
  *
- * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx at 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.
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
  *
- * 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
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
  *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  */
 
 #ifndef ___k_kTypes_h___
diff --git a/src/lib/kStuff/kCpu/Makefile.kmk b/src/lib/kStuff/kCpu/Makefile.kmk
new file mode 100644
index 0000000..505d438
--- /dev/null
+++ b/src/lib/kStuff/kCpu/Makefile.kmk
@@ -0,0 +1,42 @@
+# $Id: Makefile.kmk 29 2009-07-01 20:30:29Z bird $
+## @file
+# kCpu - The CPU and Architecture API, sub-makefile.
+#
+
+#
+# Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+DEPTH ?= ..
+SUB_DEPTH = ..
+include $(PATH_KBUILD)/subheader.kmk
+
+LIBRARIES += kCpuStatic
+kCpuStatic_TEMPLATE = kStuffLIB
+kCpuStatic_SOURCES = \
+	kCpuCompare.c \
+	kCpuGetArchAndCpu.c
+
+include $(PATH_KBUILD)/subfooter.kmk
+
diff --git a/src/lib/kStuff/kCpu/kCpuCompare.c b/src/lib/kStuff/kCpu/kCpuCompare.c
new file mode 100644
index 0000000..0d351a0
--- /dev/null
+++ b/src/lib/kStuff/kCpu/kCpuCompare.c
@@ -0,0 +1,131 @@
+/* $Id: kCpuCompare.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kCpu - kCpuCompare.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kCpu.h>
+#include <k/kErrors.h>
+
+
+/**
+ * Compares arch+cpu some code was generated for with a arch+cpu for executing it
+ * to see if it'll work out fine or not.
+ *
+ * @returns 0 if the code is compatible with the cpu.
+ * @returns KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE if the arch+cpu isn't compatible with the code.
+ *
+ * @param   enmCodeArch The architecture the code was generated for.
+ * @param   enmCodeCpu  The cpu the code was generated for.
+ * @param   enmArch     The architecture to run it on.
+ * @param   enmCpu      The cpu to run it on.
+ */
+KCPU_DECL(int) kCpuCompare(KCPUARCH enmCodeArch, KCPU enmCodeCpu, KCPUARCH enmArch, KCPU enmCpu)
+{
+    /*
+     * Compare arch and cpu.
+     */
+    if (enmCodeArch != enmArch)
+        return KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE;
+
+    /* exact match is nice. */
+    if (enmCodeCpu == enmCpu)
+        return 0;
+
+    switch (enmArch)
+    {
+        case K_ARCH_X86_16:
+            if (enmCpu < KCPU_FIRST_X86_16 || enmCpu > KCPU_LAST_X86_16)
+                return KERR_INVALID_PARAMETER;
+
+            /* intel? */
+            if (enmCodeCpu <= KCPU_CORE2_16)
+            {
+                /* also intel? */
+                if (enmCpu <= KCPU_CORE2_16)
+                    return enmCodeCpu <= enmCpu ? 0 : KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE;
+                switch (enmCpu)
+                {
+                    case KCPU_K6_16:
+                        return enmCodeCpu <= KCPU_I586 ? 0 : KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE;
+                    case KCPU_K7_16:
+                    case KCPU_K8_16:
+                    default:
+                        return enmCodeCpu <= KCPU_I686 ? 0 : KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE;
+                }
+            }
+            /* amd */
+            return enmCpu >= KCPU_K6_16 && enmCpu <= KCPU_K8_16
+                    ? 0 : KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE;
+
+        case K_ARCH_X86_32:
+            if (enmCpu < KCPU_FIRST_X86_32 || enmCpu > KCPU_LAST_X86_32)
+                return KERR_INVALID_PARAMETER;
+
+            /* blend? */
+            if (enmCodeCpu == KCPU_X86_32_BLEND)
+                return 0;
+
+            /* intel? */
+            if (enmCodeCpu <= KCPU_CORE2_32)
+            {
+                /* also intel? */
+                if (enmCpu <= KCPU_CORE2_32)
+                    return enmCodeCpu <= enmCpu ? 0 : KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE;
+                switch (enmCpu)
+                {
+                    case KCPU_K6:
+                        return enmCodeCpu <= KCPU_I586 ? 0 : KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE;
+                    case KCPU_K7:
+                    case KCPU_K8_32:
+                    default:
+                        return enmCodeCpu <= KCPU_I686 ? 0 : KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE;
+                }
+            }
+            /* amd */
+            return enmCpu >= KCPU_K6 && enmCpu <= KCPU_K8_32
+                    ? 0 : KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE;
+
+        case K_ARCH_AMD64:
+            if (enmCpu < KCPU_FIRST_AMD64 || enmCpu > KCPU_LAST_AMD64)
+                return KERR_INVALID_PARAMETER;
+
+            /* blend? */
+            if (enmCodeCpu == KCPU_AMD64_BLEND)
+                return 0;
+            /* this is simple for now. */
+            return KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE;
+
+        default:
+            break;
+    }
+    return KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE;
+}
+
diff --git a/src/lib/kStuff/kCpu/kCpuGetArchAndCpu.c b/src/lib/kStuff/kCpu/kCpuGetArchAndCpu.c
new file mode 100644
index 0000000..8e0c00b
--- /dev/null
+++ b/src/lib/kStuff/kCpu/kCpuGetArchAndCpu.c
@@ -0,0 +1,57 @@
+/* $Id: kCpuGetArchAndCpu.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kCpu - kCpuGetArchAndCpu.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kCpu.h>
+
+
+/**
+ * Gets the arch+cpu of the calling cpu.
+ *
+ * @param   penmArch    Where to store the cpu architecture.
+ * @param   penmCpu     Where to store the cpu brand/model.
+ */
+KCPU_DECL(void) kCpuGetArchAndCpu(PKCPUARCH penmArch, PKCPU penmCpu)
+{
+#if K_ARCH == K_ARCH_AMD64
+    *penmArch = KCPUARCH_AMD64;
+    *penmCpu = KCPU_AMD64_BLEND; /** @todo check it using cpu. */
+
+#elif K_ARCH == K_ARCH_X86_32
+    *penmArch = KCPUARCH_X86_32;
+    *penmCpu = KCPU_X86_32_BLEND; /** @todo check it using cpu. */
+
+#else
+# error "Port me"
+#endif
+}
+
diff --git a/src/lib/kStuff/kDbg/Makefile.kmk b/src/lib/kStuff/kDbg/Makefile.kmk
new file mode 100644
index 0000000..af8bed3
--- /dev/null
+++ b/src/lib/kStuff/kDbg/Makefile.kmk
@@ -0,0 +1,73 @@
+# $Id: Makefile.kmk 29 2009-07-01 20:30:29Z bird $
+## @file
+# kDbg - The Debug Info Reader, sub-makefile.
+#
+
+#
+# Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+DEPTH ?= ..
+SUB_DEPTH = ..
+include $(PATH_KBUILD)/subheader.kmk
+
+#
+# kDbg - The profiler module.
+#
+#DLLS += kDbg - disabled for now.
+kDbg_TEMPLATE = kStuffDLL
+kDbg_DEFS = KDBG_BUILDING KDBG_RESIDES_IN_DLL
+kDbg_SOURCES := \
+	kDbgModule.cpp \
+	kDbgModLdr.cpp \
+	kDbgLine.cpp \
+	kDbgSymbol.cpp
+
+kDbg_SOURCES.win += \
+	kDbgModWinDbgHelp.cpp
+
+#
+# kDbgStatic - The profiler module.
+#
+LIBRARIES += kDbgStatic
+kDbgStatic_TEMPLATE = kStuffLIB
+kDbgStatic_DEFS = KDBG_BUILDING
+kDbgStatic_SOURCES = $(kDbg_SOURCES)
+kDbgStatic_SOURCES.win = $(kDbg_SOURCES.win)
+
+#
+# kDbgDump - Test program which dumps whatever is thrown at it.
+#
+PROGRAMS += kDbgDump
+kDbgDump_TEMPLATE = kStuffEXE
+kDbgDump_SOURCES = kDbgDump.cpp
+kDbgDump_LIBS = \
+	$(TARGET_kDbgStatic) \
+	$(subst kDbg,kLdr,$(TARGET_kDbgStatic)) \
+	$(subst kDbg,kRdr,$(TARGET_kDbgStatic)) \
+	$(subst kDbg,kHlpCRT,$(TARGET_kDbgStatic))
+
+# Generate the rules
+include $(PATH_KBUILD)/subfooter.kmk
+
diff --git a/src/lib/kStuff/kDbg/kDbgDump.cpp b/src/lib/kStuff/kDbg/kDbgDump.cpp
new file mode 100644
index 0000000..83cb36b
--- /dev/null
+++ b/src/lib/kStuff/kDbg/kDbgDump.cpp
@@ -0,0 +1,174 @@
+/* $Id: kDbgDump.cpp 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kDbgDump - Debug Info Dumper.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kDbg.h>
+#include <string.h>
+#include <stdio.h>
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** @name Options
+ * @{ */
+static int g_fGlobalSyms = 1;
+static int g_fPrivateSyms = 1;
+static int g_fLineNumbers = 0;
+/** @} */
+
+
+/**
+ * Dumps one file.
+ *
+ * @returns main exit status.
+ * @param   pszFile     The file to dump (path to it).
+ */
+static int DumpFile(const char *pszFile)
+{
+    PKDBGMOD pDbgMod;
+    int rc = kDbgModuleOpen(&pDbgMod, pszFile, NULL);
+    if (rc)
+    {
+        printf("kDbgDump: error: kDbgModuleOpen('%s',) failed with rc=%d.\n", pszFile, rc);
+        return 1;
+    }
+
+
+
+    return 0;
+}
+
+
+/**
+ * Prints the version number
+ * @return 0
+ */
+static int ShowVersion()
+{
+    printf("kDbgDump v0.0.1\n");
+    return 0;
+}
+
+
+/**
+ * Prints the program syntax.
+ *
+ * @returns 1
+ * @param   argv0   The program name.
+ */
+static int ShowSyntax(const char *argv0)
+{
+    ShowVersion();
+    printf("syntax: %s [options] <files>\n"
+           "\n",
+           argv0);
+    return 1;
+}
+
+int main(int argc, char **argv)
+{
+    int rcRet = 0;
+
+    /*
+     * Parse arguments.
+     */
+    int fArgsDone = 0;
+    for (int i = 1; i < argc; i++)
+    {
+        const char *psz = argv[i];
+
+        if (!fArgsDone && psz[0] == '-' && psz[1])
+        {
+            /* convert long option to short. */
+            if (*++psz == '-')
+            {
+                psz++;
+                if (!*psz) /* -- */
+                {
+                    fArgsDone = 1;
+                    continue;
+                }
+                if (!strcmp(psz, "line-numbers"))
+                    psz = "l";
+                else if (!strcmp(psz, "no-line-numbers"))
+                    psz = "L";
+                else if (!strcmp(psz, "global-syms")    || !strcmp(psz, "public-syms"))
+                    psz = "g";
+                else if (!strcmp(psz, "no-global-syms") || !strcmp(psz, "no-public-syms"))
+                    psz = "G";
+                else if (!strcmp(psz, "privat-syms")    || !strcmp(psz, "local-syms"))
+                    psz = "p";
+                else if (!strcmp(psz, "no-privat-syms") || !strcmp(psz, "no-local-syms"))
+                    psz = "P";
+                else if (!strcmp(psz, "version"))
+                    psz = "v";
+                else if (!strcmp(psz, "help"))
+                    psz = "h";
+                else
+                {
+                    fprintf(stderr, "%s: syntax error: unknown option '--%s'\n", argv[0], psz);
+                    return 1;
+                }
+            }
+
+            /* eat short options. */
+            while (*psz)
+                switch (*psz++)
+                {
+                    case 'l': g_fLineNumbers = 1; break;
+                    case 'L': g_fLineNumbers = 0; break;
+                    case 'p': g_fPrivateSyms = 1; break;
+                    case 'P': g_fPrivateSyms = 0; break;
+                    case 'g': g_fGlobalSyms = 1; break;
+                    case 'G': g_fGlobalSyms = 0; break;
+                    case '?':
+                    case 'H':
+                    case 'h': return ShowSyntax(argv[0]);
+                    case 'v': return ShowVersion();
+                    default:
+                        fprintf(stderr, "%s: syntax error: unknown option '-%c'.\n", argv[0], psz[-1]);
+                        return 1;
+                }
+        }
+        else
+        {
+            /* Dump does it's own bitching if something goes wrong. */
+            int rc = DumpFile(psz);
+            if (rc && !rcRet)
+                rc = rcRet;
+        }
+    }
+
+    return rcRet;
+}
+
diff --git a/src/lib/kStuff/kDbg/kDbgHlp.h b/src/lib/kStuff/kDbg/kDbgHlp.h
new file mode 100644
index 0000000..cd5116d
--- /dev/null
+++ b/src/lib/kStuff/kDbg/kDbgHlp.h
@@ -0,0 +1,306 @@
+/* $Id: kDbgHlp.h 78 2016-07-13 15:52:04Z bird $ */
+/** @file
+ * kDbg - The Debug Info Reader, Internal Header.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___kDbgHlp_h___
+#define ___kDbgHlp_h___
+
+#include <k/kDbgBase.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** @defgroup grp_kDbgHlpHeap   kDbg Internal Heap APIs.
+ * @internal
+ * @{
+ */
+
+/**
+ * Allocates memory.
+ *
+ * @returns Pointer to the allocated memory.
+ *          NULL on failure.
+ * @param   cb      The number of bytes to allocate.
+ */
+void *kDbgHlpAlloc(size_t cb);
+
+/**
+ * Allocates memory like kDbgHlpAlloc, except that it's zeroed.
+ *
+ * @returns Pointer to the allocated memory.
+ *          NULL on failure.
+ * @param   cb      The number of bytes to allocate.
+ */
+void *kDbgHlpAllocZ(size_t cb);
+
+/**
+ * Combination of kDbgHlpAlloc and memcpy.
+ *
+ * @returns Pointer to the duplicate.
+ *          NULL on failure.
+ *
+ * @param   pv      The memory to be duplicate.
+ * @param   cb      The size of the block.
+ */
+void *kDbgHlpAllocDup(const void *pv, size_t cb);
+
+/**
+ * Reallocates a memory block returned by kDbgHlpAlloc, kDbgHlpAllocZ
+ * kDbgHlpAllocDup or this function.
+ *
+ * The content of new memory added to the memory block is undefined.
+ *
+ * @returns Pointer to the allocated memory.
+ *          NULL on failure, the old block remains intact.
+ * @param   pv      The memory block to reallocate.
+ *                  If NULL this function will work like kDbgHlpAlloc.
+ * @param   cb      The number of bytes to allocate.
+ *                  If 0 this function will work like kDbgHlpFree.
+ */
+void *kDbgHlpRealloc(void *pv, size_t cb);
+
+/**
+ * Frees memory allocated by kDbgHlpAlloc, kDbgHlpAllocZ
+ * kDbgHlpAllocDup, or kDbgHlpRealloc.
+ *
+ * @param pv
+ */
+void kDbgHlpFree(void *pv);
+
+/** @} */
+
+
+/** @defgroup grp_kDbgHlpFile   kDbg Internal File Access APIs.
+ * @internal
+ * @{
+ */
+/**
+ * Opens the specified file as read-only, buffered if possible.
+ *
+ * @returns 0 on success, or the appropriate KDBG_ERR_* on failure.
+ *
+ * @param   pszFilename     The file to open.
+ * @param   ppFile          Where to store the handle to the open file.
+ */
+int kDbgHlpOpenRO(const char *pszFilename, PKDBGHLPFILE *ppFile);
+
+
+/**
+ * Closes a file opened by kDbgHlpOpenRO.
+ *
+ * @param   pFile           The file handle.
+ */
+void kDbgHlpClose(PKDBGHLPFILE pFile);
+
+/**
+ * Gets the native file handle.
+ *
+ * @return  The native file handle.
+ *          -1 on failure.
+ * @param   pFile           The file handle.
+ */
+uintptr_t kDbgHlpNativeFileHandle(PKDBGHLPFILE pFile);
+
+/**
+ * Gets the size of an open file.
+ *
+ * @returns The file size in bytes on success.
+ *          On failure -1 is returned.
+ * @param   pFile           The file handle.
+ */
+int64_t kDbgHlpFileSize(PKDBGHLPFILE pFile);
+
+/**
+ * Reads a number of bytes at a specified file location.
+ *
+ * This will change the current file position to off + cb on success,
+ * while on failure the position will be undefined.
+ *
+ * @returns The file size in bytes on success.
+ *          On failure -1 is returned.
+ * @param   pFile           The file handle.
+ * @param   off             Where to read.
+ * @param   pv              Where to store the data.
+ * @param   cb              How much to read.
+ */
+int kDbgHlpReadAt(PKDBGHLPFILE pFile, int64_t off, void *pv, size_t cb);
+
+/**
+ * Reads a number of bytes at the current file position.
+ *
+ * This will advance the current file position by cb bytes on success
+ * while on failure the position will be undefined.
+ *
+ * @returns The file size in bytes on success.
+ *          On failure -1 is returned.
+ * @param   pFile           The file handle.
+ * @param   pv              Where to store the data.
+ * @param   cb              How much to read.
+ * @param   off             Where to read.
+ */
+int kDbgHlpRead(PKDBGHLPFILE pFile, void *pv, size_t cb);
+
+/**
+ * Sets the current file position.
+ *
+ * @returns 0 on success, and KDBG_ERR_* on failure.
+ * @param   pFile           The file handle.
+ * @param   off             The desired file position.
+ */
+int kDbgHlpSeek(PKDBGHLPFILE pFile, int64_t off);
+
+/**
+ * Move the file position relative to the current one.
+ *
+ * @returns 0 on success, and KDBG_ERR_* on failure.
+ * @param   pFile           The file handle.
+ * @param   off             How much to move the file position by.
+ */
+int kDbgHlpSeekByCur(PKDBGHLPFILE pFile, int64_t off);
+
+/**
+ * Move the file position relative to the end of the file.
+ *
+ * @returns 0 on success, and KDBG_ERR_* on failure.
+ * @param   pFile           The file handle.
+ * @param   off             The offset relative to the end, positive number.
+ */
+int kDbgHlpSeekByEnd(PKDBGHLPFILE pFile, int64_t off);
+
+/**
+ * Gets the current file position.
+ *
+ * @returns The current file position on success.
+ *          -1 on failure.
+ * @param   pFile           The file handle.
+ */
+int64_t kDbgHlpTell(PKDBGHLPFILE pFile);
+
+/** @} */
+
+/** @defgroup grp_kDbgHlpAssert     kDbg Internal Assertion Macros.
+ * @internal
+ * @{
+ */
+
+#ifdef _MSC_VER
+# define kDbgAssertBreakpoint() do { __debugbreak(); } while (0)
+#else
+# define kDbgAssertBreakpoint() do { __asm__ __volatile__ ("int3"); } while (0)
+#endif
+
+/**
+ * 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.
+ */
+void kDbgAssertMsg1(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.
+ */
+void kDbgAssertMsg2(const char *pszFormat, ...);
+
+
+#ifdef KDBG_STRICT
+
+# define kDbgAssert(expr) \
+    do { \
+        if (!(expr)) \
+        { \
+            kDbgAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kDbgAssertBreakpoint(); \
+        } \
+    } while (0)
+
+# define kDbgAssertReturn(expr, rcRet) \
+    do { \
+        if (!(expr)) \
+        { \
+            kDbgAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kDbgAssertBreakpoint(); \
+            return (rcRet); \
+        } \
+    } while (0)
+
+# define kDbgAssertMsg(expr, msg) \
+    do { \
+        if (!(expr)) \
+        { \
+            kDbgAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kDbgAssertMsg2 msg; \
+            kDbgAssertBreakpoint(); \
+        } \
+    } while (0)
+
+# define kDbgAssertMsgReturn(expr, msg, rcRet) \
+    do { \
+        if (!(expr)) \
+        { \
+            kDbgAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
+            kDbgAssertMsg2 msg; \
+            kDbgAssertBreakpoint(); \
+            return (rcRet); \
+        } \
+    } while (0)
+
+#else   /* !KDBG_STRICT */
+# define kDbgAssert(expr)                       do { } while (0)
+# define kDbgAssertReturn(expr, rcRet)          do { if (!(expr)) return (rcRet); } while (0)
+# define kDbgAssertMsg(expr, msg)               do { } while (0)
+# define kDbgAssertMsgReturn(expr, msg, rcRet)  do { if (!(expr)) return (rcRet); } while (0)
+#endif  /* !KDBG_STRICT */
+
+#define kDbgAssertPtr(ptr)                      kDbgAssertMsg(KDBG_VALID_PTR(ptr), ("%s = %p\n", #ptr, (ptr)))
+#define kDbgAssertPtrReturn(ptr, rcRet)         kDbgAssertMsgReturn(KDBG_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)), (rcRet))
+#define kDbgAssertPtrNull(ptr)                  kDbgAssertMsg(!(ptr) || KDBG_VALID_PTR(ptr), ("%s = %p\n", #ptr, (ptr)))
+#define kDbgAssertPtrNullReturn(ptr, rcRet)     kDbgAssertMsgReturn(!(ptr) || KDBG_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)), (rcRet))
+#define kDbgAssertRC(rc)                        kDbgAssertMsg((rc) == 0, ("%s = %d\n", #rc, (rc)))
+#define kDbgAssertRCReturn(rc, rcRet)           kDbgAssertMsgReturn((rc) == 0, ("%s = %d -> %d\n", #rc, (rc), (rcRet)), (rcRet))
+#define kDbgAssertFailed()                      kDbgAssert(0)
+#define kDbgAssertFailedReturn(rcRet)           kDbgAssertReturn(0, (rcRet))
+#define kDbgAssertMsgFailed(msg)                kDbgAssertMsg(0, msg)
+#define kDbgAssertMsgFailedReturn(msg, rcRet)   kDbgAssertMsgReturn(0, msg, (rcRet))
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/lib/kStuff/kDbg/kDbgHlpCrt.cpp b/src/lib/kStuff/kDbg/kDbgHlpCrt.cpp
new file mode 100644
index 0000000..a218404
--- /dev/null
+++ b/src/lib/kStuff/kDbg/kDbgHlpCrt.cpp
@@ -0,0 +1,239 @@
+/* $Id: kDbgHlpCrt.cpp 77 2016-06-22 17:03:55Z bird $ */
+/** @file
+ * kDbg - The Debug Info Reader, Helpers, CRT Based Implementation.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "kDbgHlp.h"
+#include "kDbg.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#ifdef _MSC_VER
+# include <io.h>
+#endif
+
+
+
+/**
+ * The stdio base implementation of KDBGHLPFILE.
+ */
+typedef struct KDBGHLPFILE
+{
+    /** Pointer to the stdio file stream. */
+    FILE *pStrm;
+} KDBGHLPFILE;
+
+/** @def HAVE_FSEEKO
+ * Define HAVE_FSEEKO to indicate that fseeko and ftello should be used. */
+#if !defined(_MSC_VER)
+# define HAVE_FSEEKO
+#endif
+
+
+void *kDbgHlpAlloc(size_t cb)
+{
+    return malloc(cb);
+}
+
+
+void *kDbgHlpAllocZ(size_t cb)
+{
+    return calloc(1, cb);
+}
+
+
+void *kDbgHlpAllocDup(const void *pv, size_t cb)
+{
+    void *pvNew = malloc(cb);
+    if (pvNew)
+        memcpy(pvNew, pv, cb);
+    return pvNew;
+}
+
+
+void *kDbgHlpReAlloc(void *pv, size_t cb)
+{
+    return realloc(pv, cb);
+}
+
+
+void kDbgHlpFree(void *pv)
+{
+    free(pv);
+}
+
+
+int kDbgHlpCrtConvErrno(int rc)
+{
+    switch (rc)
+    {
+        case 0:             return 0;
+        case EINVAL:        return KERR_INVALID_PARAMETER;
+        case ENOMEM:        return KERR_NO_MEMORY;
+        case EISDIR:
+        case ENOENT:        return KERR_FILE_NOT_FOUND;
+        default:            return KERR_GENERAL_FAILURE;
+    }
+}
+
+
+int kDbgHlpOpenRO(const char *pszFilename, PKDBGHLPFILE *ppFile)
+{
+    PKDBGHLPFILE pFile = (PKDBGHLPFILE)kDbgHlpAlloc(sizeof(*pFile));
+    if (!pFile)
+        return KERR_NO_MEMORY;
+
+    pFile->pStrm = fopen(pszFilename, "rb");
+    if (pFile->pStrm)
+    {
+        *ppFile = pFile;
+        return 0;
+    }
+    return kDbgHlpCrtConvErrno(errno);
+}
+
+
+void kDbgHlpClose(PKDBGHLPFILE pFile)
+{
+    if (pFile)
+    {
+        fclose(pFile->pStrm);
+        pFile->pStrm = NULL;
+        kDbgHlpFree(pFile);
+    }
+}
+
+
+uintptr_t kDbgHlpNativeFileHandle(PKDBGHLPFILE pFile)
+{
+    int fd = fileno(pFile->pStrm);
+#ifdef _MSC_VER
+    return _get_osfhandle(fd);
+#else
+    return fd;
+#endif
+}
+
+
+int64_t kDbgHlpFileSize(PKDBGHLPFILE pFile)
+{
+    int64_t cbFile;
+    int64_t offCur = kDbgHlpTell(pFile);
+    if (offCur >= 0)
+    {
+        if (kDbgHlpSeekByEnd(pFile, 0) == 0)
+            cbFile = kDbgHlpTell(pFile);
+        else
+            cbFile = -1;
+        kDbgHlpSeek(pFile, offCur);
+    }
+    else
+        cbFile = -1;
+    return cbFile;
+}
+
+
+int kDbgHlpReadAt(PKDBGHLPFILE pFile, int64_t off, void *pv, size_t cb)
+{
+    int rc  = kDbgHlpSeek(pFile, off);
+    if (!rc)
+        rc = kDbgHlpRead(pFile, pv, cb);
+    return rc;
+}
+
+
+int kDbgHlpRead(PKDBGHLPFILE pFile, void *pv, size_t cb)
+{
+    if (fread(pv, cb, 1, pFile->pStrm) == 1)
+        return 0;
+    return -1;
+}
+
+
+int kDbgHlpSeek(PKDBGHLPFILE pFile, int64_t off)
+{
+#ifdef HAVE_FSEEKO
+    if (!fseeko(pFile->pStrm, off, SEEK_SET))
+        return 0;
+#else
+    long l = (long)off;
+    if (l != off)
+        return KERR_OUT_OF_RANGE;
+    if (!fseek(pFile->pStrm, l, SEEK_SET))
+        return 0;
+#endif
+    return kDbgHlpCrtConvErrno(errno);
+}
+
+
+int kDbgHlpSeekByCur(PKDBGHLPFILE pFile, int64_t off)
+{
+#ifdef HAVE_FSEEKO
+    if (!fseeko(pFile->pStrm, off, SEEK_CUR))
+        return 0;
+#else
+    long l = (long)off;
+    if (l != off)
+        return KERR_OUT_OF_RANGE;
+    if (!fseek(pFile->pStrm, l, SEEK_CUR))
+        return 0;
+#endif
+    return kDbgHlpCrtConvErrno(errno);
+}
+
+
+int kDbgHlpSeekByEnd(PKDBGHLPFILE pFile, int64_t off)
+{
+#ifdef HAVE_FSEEKO
+    if (!fseeko(pFile->pStrm, -off, SEEK_END))
+        return 0;
+#else
+    long l = (long)off;
+    if (l != off)
+        return KERR_OUT_OF_RANGE;
+    if (!fseek(pFile->pStrm, -l, SEEK_END))
+        return 0;
+#endif
+    return kDbgHlpCrtConvErrno(errno);
+}
+
+
+int64_t kDbgHlpTell(PKDBGHLPFILE pFile)
+{
+#ifdef HAVE_FSEEKO
+    return ftello(pFile->pStrm);
+#else
+    return ftell(pFile->pStrm);
+#endif
+}
+
diff --git a/src/lib/kStuff/kDbg/kDbgInternal.h b/src/lib/kStuff/kDbg/kDbgInternal.h
new file mode 100644
index 0000000..fdb3fcd
--- /dev/null
+++ b/src/lib/kStuff/kDbg/kDbgInternal.h
@@ -0,0 +1,137 @@
+/* $Id: kDbgInternal.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kDbg - The Debug Info Reader, Internal Header.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___kDbgInternal_h___
+#define ___kDbgInternal_h___
+
+#include <k/kHlpAssert.h>
+#include <k/kMagics.h>
+#include <k/kErrors.h>
+#include <k/kDbgAll.h>
+
+
+/** @defgroup grp_kDbgInternal  Internal
+ * @internal
+ * @addtogroup grp_kDbg
+ * @{
+ */
+
+/** @def KDBG_STRICT
+ * If defined the kDbg assertions and other runtime checks will be enabled. */
+#ifdef K_ALL_STRICT
+# undef KDBG_STRICT
+# define KDBG_STRICT
+#endif
+
+/** @name Our Assert macros
+ * @{ */
+#ifdef KDBG_STRICT
+# define kDbgAssert(expr)                       kHlpAssert(expr)
+# define kDbgAssertReturn(expr, rcRet)          kHlpAssertReturn(expr, rcRet)
+# define kDbgAssertReturnVoid(expr)             kHlpAssertReturnVoid(expr)
+# define kDbgAssertMsg(expr, msg)               kHlpAssertMsg(expr, msg)
+# define kDbgAssertMsgReturn(expr, msg, rcRet)  kHlpAssertMsgReturn(expr, msg, rcRet)
+# define kDbgAssertMsgReturnVoid(expr, msg)     kHlpAssertMsgReturnVoid(expr, msg)
+#else   /* !KDBG_STRICT */
+# define kDbgAssert(expr)                       do { } while (0)
+# define kDbgAssertReturn(expr, rcRet)          do { if (!(expr)) return (rcRet); } while (0)
+# define kDbgAssertMsg(expr, msg)               do { } while (0)
+# define kDbgAssertMsgReturn(expr, msg, rcRet)  do { if (!(expr)) return (rcRet); } while (0)
+#endif  /* !KDBG_STRICT */
+
+#define kDbgAssertPtr(ptr)                      kDbgAssertMsg(K_VALID_PTR(ptr), ("%s = %p\n", #ptr, (ptr)))
+#define kDbgAssertPtrReturn(ptr, rcRet)         kDbgAssertMsgReturn(K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)), (rcRet))
+#define kDbgAssertPtrReturnVoid(ptr)            kDbgAssertMsgReturnVoid(K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)))
+#define kDbgAssertPtrNull(ptr)                  kDbgAssertMsg(!(ptr) || K_VALID_PTR(ptr), ("%s = %p\n", #ptr, (ptr)))
+#define kDbgAssertPtrNullReturn(ptr, rcRet)     kDbgAssertMsgReturn(!(ptr) || K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)), (rcRet))
+#define kDbgAssertPtrNullReturnVoid(ptr)        kDbgAssertMsgReturnVoid(!(ptr) || K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)))
+#define kDbgAssertRC(rc)                        kDbgAssertMsg((rc) == 0, ("%s = %d\n", #rc, (rc)))
+#define kDbgAssertRCReturn(rc, rcRet)           kDbgAssertMsgReturn((rc) == 0, ("%s = %d -> %d\n", #rc, (rc), (rcRet)), (rcRet))
+#define kDbgAssertRCReturnVoid(rc)              kDbgAssertMsgReturnVoid((rc) == 0, ("%s = %d -> %d\n", #rc, (rc), (rcRet)))
+#define kDbgAssertFailed()                      kDbgAssert(0)
+#define kDbgAssertFailedReturn(rcRet)           kDbgAssertReturn(0, (rcRet))
+#define kDbgAssertFailedReturnVoid()            kDbgAssertReturnVoid(0)
+#define kDbgAssertMsgFailed(msg)                kDbgAssertMsg(0, msg)
+#define kDbgAssertMsgFailedReturn(msg, rcRet)   kDbgAssertMsgReturn(0, msg, (rcRet))
+#define kDbgAssertMsgFailedReturnVoid(msg)      kDbgAssertMsgReturnVoid(0, msg)
+/** @} */
+
+/** Return / crash validation of a reader argument. */
+#define KDBGMOD_VALIDATE_EX(pDbgMod, rc) \
+    do  { \
+        kDbgAssertPtrReturn((pDbgMod), (rc)); \
+        kDbgAssertReturn((pDbgMod)->u32Magic == KDBGMOD_MAGIC, (rc)); \
+        kDbgAssertReturn((pDbgMod)->pOps != NULL, (rc)); \
+    } while (0)
+
+/** Return / crash validation of a reader argument. */
+#define KDBGMOD_VALIDATE(pDbgMod) \
+    do  { \
+        kDbgAssertPtrReturn((pDbgMod), KERR_INVALID_POINTER); \
+        kDbgAssertReturn((pDbgMod)->u32Magic == KDBGMOD_MAGIC, KERR_INVALID_HANDLE); \
+        kDbgAssertReturn((pDbgMod)->pOps != NULL, KERR_INVALID_HANDLE); \
+    } while (0)
+
+/** Return / crash validation of a reader argument. */
+#define KDBGMOD_VALIDATE_VOID(pDbgMod) \
+    do  { \
+        kDbgAssertPtrReturnVoid((pDbgMod)); \
+        kDbgAssertReturnVoid((pDbgMod)->u32Magic == KDBGMOD_MAGIC); \
+        kDbgAssertReturnVoid((pDbgMod)->pOps != NULL); \
+    } while (0)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @name Built-in Debug Module Readers
+ * @{ */
+extern KDBGMODOPS const g_kDbgModWinDbgHelpOpen;
+extern KDBGMODOPS const g_kDbgModLdr;
+extern KDBGMODOPS const g_kDbgModCv8;
+extern KDBGMODOPS const g_kDbgModDwarf;
+extern KDBGMODOPS const g_kDbgModHll;
+extern KDBGMODOPS const g_kDbgModStabs;
+extern KDBGMODOPS const g_kDbgModSym;
+extern KDBGMODOPS const g_kDbgModMapILink;
+extern KDBGMODOPS const g_kDbgModMapMSLink;
+extern KDBGMODOPS const g_kDbgModMapNm;
+extern KDBGMODOPS const g_kDbgModMapWLink;
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif
+
diff --git a/src/lib/kStuff/kDbg/kDbgLine.cpp b/src/lib/kStuff/kDbg/kDbgLine.cpp
new file mode 100644
index 0000000..52e573f
--- /dev/null
+++ b/src/lib/kStuff/kDbg/kDbgLine.cpp
@@ -0,0 +1,78 @@
+/* $Id: kDbgLine.cpp 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kDbg - The Debug Info Read, Line Numbers.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "kDbgInternal.h"
+#include <k/kHlpAlloc.h>
+
+
+/**
+ * Duplicates a line number.
+ *
+ * To save heap space, the returned line number will not own more heap space
+ * than it strictly need to. So, it's not possible to append stuff to the symbol
+ * or anything of that kind.
+ *
+ * @returns Pointer to the duplicate.
+ *          This must be freed using kDbgSymbolFree().
+ * @param   pLine       The line number to be duplicated.
+ */
+KDBG_DECL(PKDBGLINE) kDbgLineDup(PCKDBGLINE pLine)
+{
+    kDbgAssertPtrReturn(pLine, NULL);
+    KSIZE cb = K_OFFSETOF(KDBGLINE, szFile[pLine->cchFile + 1]);
+    PKDBGLINE pNewLine = (PKDBGLINE)kHlpDup(pLine, cb);
+    if (pNewLine)
+        pNewLine->cbSelf = cb;
+    return pNewLine;
+}
+
+
+/**
+ * Frees a line number obtained from the kDbg API.
+ *
+ * @returns 0 on success.
+ * @returns KERR_INVALID_POINTER if pLine isn't a valid pointer.
+ *
+ * @param   pLine       The line number to be freed. The null pointer is ignored.
+ */
+KDBG_DECL(int) kDbgLineFree(PKDBGLINE pLine)
+{
+    if (pLine)
+    {
+        kDbgAssertPtrReturn(pLine, KERR_INVALID_POINTER);
+        pLine->cbSelf = 0;
+        kHlpFree(pLine);
+    }
+    return 0;
+}
+
diff --git a/src/lib/kStuff/kDbg/kDbgModLdr.cpp b/src/lib/kStuff/kDbg/kDbgModLdr.cpp
new file mode 100644
index 0000000..5e77095
--- /dev/null
+++ b/src/lib/kStuff/kDbg/kDbgModLdr.cpp
@@ -0,0 +1,109 @@
+/* $Id: kDbgModLdr.cpp 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kDbg - The Debug Info Reader, kLdr Based.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kDbg.h>
+#include <k/kLdr.h>
+#include "kDbgInternal.h"
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * A kLdr based debug reader.
+ */
+typedef struct KDBGMODLDR
+{
+    /** The common module core. */
+    KDBGMOD     Core;
+    /** Pointer to the loader module. */
+    PKLDRMOD    pLdrMod;
+} KDBGMODLDR, *PKDBGMODLDR;
+
+
+/**
+ * @copydoc KDBGMODOPS::pfnQueryLine
+ */
+static int kDbgModLdrQueryLine(PKDBGMOD pMod, KI32 iSegment, KDBGADDR uOffset, PKDBGLINE pLine)
+{
+    //PKDBGMODLDR pThis = (PKDBGMODLDR)pMod;
+    return KERR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * @copydoc KDBGMODOPS::pfnQuerySymbol
+ */
+static int kDbgModLdrQuerySymbol(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PKDBGSYMBOL pSym)
+{
+    //PKDBGMODLDR pThis = (PKDBGMODLDR)pMod;
+    return KERR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * @copydoc KDBGMODOPS::pfnClose
+ */
+static int kDbgModLdrClose(PKDBGMOD pMod)
+{
+    //PKDBGMODLDr pThis = (PKDBGMODLDR)pMod;
+    return KERR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * @copydocs  KDBGMODOPS::pfnOpen.
+ */
+static int kDbgModLdrOpen(PKDBGMOD *ppMod, PKRDR pRdr, KBOOL fCloseRdr, KFOFF off, KFOFF cb, struct KLDRMOD *pLdrMod)
+{
+    return KERR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * Methods for a PE module.
+ */
+const KDBGMODOPS g_kDbgModLdr =
+{
+    "kLdr",
+    NULL,
+    kDbgModLdrOpen,
+    kDbgModLdrClose,
+    kDbgModLdrQuerySymbol,
+    kDbgModLdrQueryLine,
+    "kLdr"
+};
+
+
+
+
diff --git a/src/lib/kStuff/kDbg/kDbgModPE.cpp b/src/lib/kStuff/kDbg/kDbgModPE.cpp
new file mode 100644
index 0000000..85de91c
--- /dev/null
+++ b/src/lib/kStuff/kDbg/kDbgModPE.cpp
@@ -0,0 +1,384 @@
+/* $Id: kDbgModPE.cpp 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kDbg - The Debug Info Reader, PE Module (Generic).
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "kDbg.h"
+#include "kDbgInternal.h"
+#include <kLdrModPE.h>
+#include <string.h>
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * A dbghelp based PE debug reader.
+ */
+typedef struct KDBGMODPE
+{
+    /** The common module core. */
+    KDBGMOD     Core;
+    /** The image size. */
+    uint32_t    cbImage;
+    /** The number of sections. (We've added the implicit header section.) */
+    int32_t     cSections;
+    /** The section headers (variable size). The first section is the
+     * implicit header section.*/
+    IMAGE_SECTION_HEADER aSections[1];
+} KDBGMODPE, *PKDBGMODPE;
+
+
+/**
+ * Calcs the RVA for a segment:offset address.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   pModPe      The PE debug module instance.
+ * @param   iSegment    The segment number. Special segments are dealt with as well.
+ * @param   off         The segment offset.
+ * @param   puRVA       Where to store the RVA on success.
+ */
+static int kDbgModPeSegOffToRVA(PKDBGMODPE pModPe, int32_t iSegment, KDBGADDR off, uint32_t *puRVA)
+{
+    if (iSegment >= 0)
+    {
+        kDbgAssertMsgReturn(iSegment < pModPe->cSections, ("iSegment=%x cSections=%x\n", iSegment, pModPe->cSections),
+                        KDBG_ERR_INVALID_ADDRESS);
+        kDbgAssertMsgReturn(off < pModPe->aSections[iSegment].Misc.VirtualSize,
+                        ("off=" PRI_KDBGADDR " VirtualSize=%x\n", off, pModPe->aSections[iSegment].Misc.VirtualSize),
+                        KDBG_ERR_INVALID_ADDRESS);
+        *puRVA = pModPe->aSections[iSegment].VirtualAddress + (uint32_t)off;
+        return 0;
+    }
+
+    if (iSegment == KDBGSEG_RVA)
+    {
+        kDbgAssertMsgReturn(off < pModPe->cbImage, ("off=" PRI_KDBGADDR ", cbImage=%x\n", off, pModPe->cbImage),
+                            KDBG_ERR_INVALID_ADDRESS);
+        *puRVA = (uint32_t)off;
+        return 0;
+    }
+    kDbgAssertMsgFailedReturn(("iSegment=%d\n", iSegment), KDBG_ERR_INVALID_ADDRESS);
+}
+
+
+/**
+ * Calcs the segment:offset address for a RVA.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   pModPe      The PE debug module instance.
+ * @param   uRVA        The RVA.
+ * @param   piSegment   Where to store the segment number.
+ * @param   poff        Where to store the segment offset.
+ */
+static int kDbgModPeRVAToSegOff(PKDBGMODPE pModPe, uint32_t uRVA, int32_t *piSegment, KDBGADDR *poff)
+{
+    kDbgAssertMsgReturn(uRVA < pModPe->cbImage, ("uRVA=%x, cbImage=%x\n", uRVA, pModPe->cbImage),
+                        KDBG_ERR_INVALID_ADDRESS);
+    for (int32_t iSegment = 0; iSegment < pModPe->cSections; iSegment++)
+    {
+        /** @todo should probably be less strict about address in the alignment gaps. */
+        uint32_t off = uRVA - pModPe->aSections[iSegment].VirtualAddress;
+        if (off < pModPe->aSections[iSegment].Misc.VirtualSize)
+        {
+            *poff = off;
+            *piSegment = iSegment;
+            return 0;
+        }
+    }
+    kDbgAssertMsgFailedReturn(("uRVA=%x\n", uRVA), KDBG_ERR_INVALID_ADDRESS);
+}
+
+
+/**
+ * @copydoc KDBGMODOPS::pfnQueryLine
+ */
+static int kDbgModPeQueryLine(PKDBGMOD pMod, int32_t iSegment, KDBGADDR off, PKDBGLINE pLine)
+{
+    PKDBGMODPE pModPe = (PKDBGMODPE)pMod;
+
+    /*
+     * Translate the address to an RVA.
+     */
+    uint32_t uRVA;
+    int rc = kDbgModPeSegOffToRVA(pModPe, iSegment, off, &uRVA);
+    if (!rc)
+    {
+#if 0
+        DWORD64 off;
+        IMAGEHLP_LINE64 Line;
+        Line.SizeOfStruct = sizeof(Line);
+        if (g_pfnSymGetLineFromAddr64(pModPe->hSymInst, pModPe->ImageBase + uRVA, &off, &Line))
+        {
+            pLine->RVA = (KDBGADDR)(Line.Address - pModPe->ImageBase);
+            rc = kDbgModPeRVAToSegOff(pModPe, pLine->RVA, &pLine->iSegment, &pLine->offSegment);
+            pLine->iLine = Line.LineNumber;
+            pLine->cchFile = strlen(Line.FileName);
+            if (pLine->cchFile >= sizeof(pLine->szFile))
+                pLine->cchFile = sizeof(pLine->szFile) - 1;
+            memcpy(pLine->szFile, Line.FileName, pLine->cchFile + 1);
+        }
+        else
+        {
+            DWORD Err = GetLastError();
+            rc = kDbgModPeConvWinError(Err);
+        }
+#endif
+        rc = KERR_NOT_IMPLEMENTED;
+    }
+    return rc;
+}
+
+
+/**
+ * @copydoc KDBGMODOPS::pfnQuerySymbol
+ */
+static int kDbgModPeQuerySymbol(PKDBGMOD pMod, int32_t iSegment, KDBGADDR off, PKDBGSYMBOL pSym)
+{
+    PKDBGMODPE pModPe = (PKDBGMODPE)pMod;
+
+    /*
+     * Translate the address to an RVA.
+     */
+    uint32_t uRVA;
+    int rc = kDbgModPeSegOffToRVA(pModPe, iSegment, off, &uRVA);
+    if (!rc)
+    {
+#if 0
+        DWORD64 off;
+        union
+        {
+            SYMBOL_INFO Sym;
+            char        achBuffer[sizeof(SYMBOL_INFO) + KDBG_SYMBOL_MAX];
+        } Buf;
+        Buf.Sym.SizeOfStruct = sizeof(SYMBOL_INFO);
+        Buf.Sym.MaxNameLen = KDBG_SYMBOL_MAX;
+        if (g_pfnSymFromAddr(pModPe->hSymInst, pModPe->ImageBase + uRVA, &off, &Buf.Sym))
+        {
+            pSym->cb     = Buf.Sym.Size;
+            pSym->fFlags = 0;
+            if (Buf.Sym.Flags & SYMFLAG_FUNCTION)
+                pSym->fFlags |= KDBGSYM_FLAGS_CODE;
+            else if (Buf.Sym.Flags & SYMFLAG_CONSTANT)
+                pSym->fFlags |= KDBGSYM_FLAGS_ABS; /** @todo SYMFLAG_CONSTANT must be tested - documentation is too brief to say what is really meant here.*/
+            else
+                pSym->fFlags |= KDBGSYM_FLAGS_DATA;
+            if (Buf.Sym.Flags & SYMFLAG_EXPORT)
+                pSym->fFlags |= KDBGSYM_FLAGS_EXPORTED;
+            if ((Buf.Sym.Flags & (SYMFLAG_VALUEPRESENT | SYMFLAG_CONSTANT)) == (SYMFLAG_VALUEPRESENT | SYMFLAG_CONSTANT))
+            {
+                pSym->iSegment   = KDBGSEG_ABS;
+                pSym->offSegment = (KDBGADDR)Buf.Sym.Value;
+                pSym->RVA        = (KDBGADDR)Buf.Sym.Value;
+            }
+            else
+            {
+                pSym->RVA        = (KDBGADDR)(Buf.Sym.Address - pModPe->ImageBase);
+                rc = kDbgModPeRVAToSegOff(pModPe, pSym->RVA, &pSym->iSegment, &pSym->offSegment);
+            }
+            pSym->cchName = (uint16_t)Buf.Sym.NameLen;
+            if (pSym->cchName >= sizeof(pSym->szName))
+                pSym->cchName = sizeof(pSym->szName) - 1;
+            memcpy(pSym->szName, Buf.Sym.Name, Buf.Sym.NameLen);
+            pSym->szName[Buf.Sym.NameLen] = '\0';
+        }
+        else
+        {
+            DWORD Err = GetLastError();
+            rc = kDbgModPeConvWinError(Err);
+        }
+#endif
+        rc = KERR_NOT_IMPLEMENTED;
+    }
+    return rc;
+}
+
+
+/**
+ * @copydoc KDBGMODOPS::pfnClose
+ */
+static int kDbgModPeClose(PKDBGMOD pMod)
+{
+    PKDBGMODPE pModPe = (PKDBGMODPE)pMod;
+
+    //if (g_pfnSymCleanup(pModPe->hSymInst))
+    //    return 0;
+    //
+    //DWORD Err = GetLastError();
+    //int rc = kDbgModPeConvWinError(Err);
+    //kDbgAssertMsgFailed(("SymInitialize failed: Err=%d rc=%Rrc\n", Err, rc));
+    //return rc;
+    return KERR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * Opens the debug info for a PE image using the windows dbghelp library.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   pFile               The handle to the module.
+ * @param   offHdr              The offset of the PE header.
+ * @param   pszModulePath       The path to the module.
+ * @param   ppDbgMod            Where to store the module handle.
+ *
+ */
+int kdbgModPEOpen(PKDBGHLPFILE pFile, int64_t offHdr, const char *pszModulePath, PKDBGMOD *ppDbgMod)
+{
+    /*
+     * We need to read the section headers and get the image size.
+     */
+    IMAGE_FILE_HEADER FHdr;
+    int rc = kDbgHlpReadAt(pFile, offHdr + KDBG_OFFSETOF(IMAGE_NT_HEADERS32, FileHeader), &FHdr, sizeof(FHdr));
+    kDbgAssertRCReturn(rc, rc);
+
+    uint32_t cbImage;
+    if (FHdr.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32))
+        rc = kDbgHlpReadAt(pFile, offHdr + KDBG_OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader.SizeOfImage),
+                           &cbImage, sizeof(cbImage));
+    else if (FHdr.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER64))
+        rc = kDbgHlpReadAt(pFile, offHdr + KDBG_OFFSETOF(IMAGE_NT_HEADERS64, OptionalHeader.SizeOfImage),
+                           &cbImage, sizeof(cbImage));
+    else
+        kDbgAssertFailedReturn(KDBG_ERR_BAD_EXE_FORMAT);
+    kDbgAssertRCReturn(rc, rc);
+
+    /*
+     * Allocate the module and read/construct the section headers.
+     */
+    PKDBGMODPE pModPe = (PKDBGMODPE)kDbgHlpAlloc(KDBG_OFFSETOF(KDBGMODPE, aSections[FHdr.NumberOfSections + 2]));
+    kDbgAssertReturn(pModPe, KERR_NO_MEMORY);
+    pModPe->Core.u32Magic   = KDBGMOD_MAGIC;
+    pModPe->Core.pOps       = &g_kDbgModPeOps;
+    pModPe->Core.pFile      = pFile;
+    pModPe->cbImage         = cbImage;
+    pModPe->cSections       = 1 + FHdr.NumberOfSections;
+    rc = kDbgHlpReadAt(pFile, offHdr + KDBG_OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader) + FHdr.SizeOfOptionalHeader,
+                       &pModPe->aSections[1], sizeof(pModPe->aSections[0]) * FHdr.NumberOfSections);
+    if (!rc)
+    {
+        PIMAGE_SECTION_HEADER pSH = &pModPe->aSections[0];
+        memcpy(pSH->Name, "headers", sizeof(pSH->Name));
+        pSH->Misc.VirtualSize       = pModPe->aSections[1].VirtualAddress;
+        pSH->VirtualAddress         = 0;
+        pSH->SizeOfRawData          = pSH->Misc.VirtualSize;
+        pSH->PointerToRawData       = 0;
+        pSH->PointerToRelocations   = 0;
+        pSH->PointerToLinenumbers   = 0;
+        pSH->NumberOfRelocations    = 0;
+        pSH->NumberOfLinenumbers    = 0;
+        pSH->Characteristics        = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ;
+
+        uint32_t uTheEnd = pModPe->aSections[FHdr.NumberOfSections].VirtualAddress
+                         + pModPe->aSections[FHdr.NumberOfSections].Misc.VirtualSize;
+        if (uTheEnd < cbImage)
+        {
+            pSH = &pModPe->aSections[pModPe->cSections++];
+            memcpy(pSH->Name, "tail\0\0\0", sizeof(pSH->Name));
+            pSH->Misc.VirtualSize       = cbImage - uTheEnd;
+            pSH->VirtualAddress         = uTheEnd;
+            pSH->SizeOfRawData          = pSH->Misc.VirtualSize;
+            pSH->PointerToRawData       = 0;
+            pSH->PointerToRelocations   = 0;
+            pSH->PointerToLinenumbers   = 0;
+            pSH->NumberOfRelocations    = 0;
+            pSH->NumberOfLinenumbers    = 0;
+            pSH->Characteristics        = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_MEM_READ;
+        }
+
+#if 0
+        /*
+         * Find a new dbghelp handle.
+         *
+         * We assume 4GB of handles outlast most debugging sessions, or in anyways that
+         * when we start reusing handles they are no longer in use. :-)
+         */
+        static volatile uint32_t s_u32LastHandle = 1;
+        HANDLE hSymInst = (HANDLE)ASMAtomicIncU32(&s_u32LastHandle);
+        while (     hSymInst == INVALID_HANDLE_VALUE
+               ||   hSymInst == (HANDLE)0
+               ||   hSymInst == GetCurrentProcess())
+            hSymInst = (HANDLE)ASMAtomicIncU32(&s_u32LastHandle);
+
+        /*
+         * Initialize dbghelp and try open the specified module.
+         */
+        if (g_pfnSymInitialize(hSymInst, NULL, FALSE))
+        {
+            g_pfnSymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_AUTO_PUBLICS | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS);
+
+            kDbgHlpSeek(pFile, 0); /* don't know if this is required or not... */
+            DWORD64 ImageBase = g_pfnSymLoadModule64(hSymInst, (HANDLE)File, pszModulePath, NULL, 0x00400000, 0);
+            if (ImageBase)
+            {
+                pModPe->hSymInst    = hSymInst;
+                pModPe->ImageBase   = ImageBase;
+                *ppDbgMod = &pModPe->Core;
+                return rc;
+            }
+
+            DWORD Err = GetLastError();
+            rc = kDbgModPeConvWinError(Err);
+            kDbgAssertMsgFailed(("SymLoadModule64 failed: Err=%d rc=%Rrc\n", Err, rc));
+            g_pfnSymCleanup(hSymInst);
+        }
+        else
+        {
+            DWORD Err = GetLastError();
+            rc = kDbgModPeConvWinError(Err);
+            kDbgAssertMsgFailed(("SymInitialize failed: Err=%d rc=%Rrc\n", Err, rc));
+        }
+#endif
+        rc = KERR_NOT_IMPLEMENTED;
+    }
+    else
+        kDbgAssertRC(rc);
+
+    kDbgHlpFree(pModPe);
+    return rc;
+}
+
+
+/**
+ * Methods for a PE module.
+ */
+const KDBGMODOPS g_kDbgModPeOps =
+{
+    "PE",
+    kDbgModPeClose,
+    kDbgModPeQuerySymbol,
+    kDbgModPeQueryLine
+};
+
+
+
diff --git a/src/lib/kStuff/kDbg/kDbgModWinDbgHelp.cpp b/src/lib/kStuff/kDbg/kDbgModWinDbgHelp.cpp
new file mode 100644
index 0000000..3c30773
--- /dev/null
+++ b/src/lib/kStuff/kDbg/kDbgModWinDbgHelp.cpp
@@ -0,0 +1,724 @@
+/* $Id: kDbgModWinDbgHelp.cpp 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kDbg - The Debug Info Reader, DbgHelp Based Reader.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <Windows.h>
+#define _IMAGEHLP64
+#include <DbgHelp.h>
+
+#include "kDbgInternal.h"
+#include <k/kHlpAlloc.h>
+#include <k/kHlpString.h>
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** The dbghelp.dll module handle. */
+static HMODULE g_hDbgHelp = NULL;
+/** Pointer to the dbhelp.dll SymInitialize function. */
+static BOOL (WINAPI *g_pfnSymInitialize)(IN HANDLE,IN LPSTR,IN BOOL);
+/** Pointer to the dbhelp.dll SymCleanup function. */
+static BOOL (WINAPI *g_pfnSymCleanup)(IN HANDLE);
+/** Pointer to the dbhelp.dll SymSetOptions function. */
+static DWORD (WINAPI *g_pfnSymSetOptions)(IN DWORD);
+/** Pointer to the dbhelp.dll SymLoadModule64 function. */
+static DWORD64 (WINAPI *g_pfnSymLoadModule64)(IN HANDLE, IN HANDLE, IN PCSTR, IN PCSTR ModuleName, IN DWORD64, IN DWORD);
+/** Pointer to the dbhelp.dll SymFromAddr function. */
+static DWORD (WINAPI *g_pfnSymFromAddr)(IN HANDLE, IN DWORD64, OUT PDWORD64, OUT PSYMBOL_INFO);
+/** Pointer to the dbhelp.dll SymGetLineFromAddr64 function. */
+static DWORD (WINAPI *g_pfnSymGetLineFromAddr64)(IN HANDLE, IN DWORD64, OUT PDWORD64, OUT PIMAGEHLP_LINE64);
+
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * A dbghelp based PE debug reader.
+ */
+typedef struct KDBGMODDBGHELP
+{
+    /** The common module core. */
+    KDBGMOD     Core;
+    /** The image base. */
+    DWORD64     ImageBase;
+    /** The "process" handle we present dbghelp. */
+    HANDLE      hSymInst;
+    /** The image size. */
+    KU32        cbImage;
+    /** The number of sections. (We've added the implicit header section.) */
+    KI32        cSections;
+    /** The section headers (variable size). The first section is the
+     * implicit header section.*/
+    IMAGE_SECTION_HEADER    aSections[1];
+} KDBGMODDBGHELP, *PKDBGMODDBGHELP;
+
+
+/**
+ * Convers a Windows error to kDbg error code.
+ *
+ * @returns kDbg status code.
+ * @param   rc          The Windows error.
+ */
+static int kdbgModDHConvWinError(DWORD rc)
+{
+    switch (rc)
+    {
+        case 0:                     return 0;
+        default:                    return KERR_GENERAL_FAILURE;
+    }
+}
+
+
+/**
+ * Calcs the RVA for a segment:offset address.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   pModDH      The PE debug module instance.
+ * @param   iSegment    The segment number. Special segments are dealt with as well.
+ * @param   off         The segment offset.
+ * @param   puRVA       Where to store the RVA on success.
+ */
+static int kdbgModDHSegOffToRVA(PKDBGMODDBGHELP pModDH, KI32 iSegment, KDBGADDR off, KU32 *puRVA)
+{
+    if (iSegment >= 0)
+    {
+        kDbgAssertMsgReturn(iSegment < pModDH->cSections, ("iSegment=%x cSections=%x\n", iSegment, pModDH->cSections),
+                            KDBG_ERR_INVALID_ADDRESS);
+        kDbgAssertMsgReturn(off < pModDH->aSections[iSegment].Misc.VirtualSize,
+                            ("off=" PRI_KDBGADDR " VirtualSize=%x\n", off, pModDH->aSections[iSegment].Misc.VirtualSize),
+                            KDBG_ERR_INVALID_ADDRESS);
+        *puRVA = pModDH->aSections[iSegment].VirtualAddress + (KU32)off;
+        return 0;
+    }
+
+    if (iSegment == KDBGSEG_RVA)
+    {
+        kDbgAssertMsgReturn(off < pModDH->cbImage, ("off=" PRI_KDBGADDR ", cbImage=%x\n", off, pModDH->cbImage),
+                            KDBG_ERR_INVALID_ADDRESS);
+        *puRVA = (KU32)off;
+        return 0;
+    }
+    kDbgAssertMsgFailedReturn(("iSegment=%d\n", iSegment), KDBG_ERR_INVALID_ADDRESS);
+}
+
+
+/**
+ * Calcs the segment:offset address for a RVA.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   pModDH      The PE debug module instance.
+ * @param   uRVA        The RVA.
+ * @param   piSegment   Where to store the segment number.
+ * @param   poff        Where to store the segment offset.
+ */
+static int kdbgModDHRVAToSegOff(PKDBGMODDBGHELP pModDH, KU32 uRVA, KI32 *piSegment, KDBGADDR *poff)
+{
+    kDbgAssertMsgReturn(uRVA < pModDH->cbImage, ("uRVA=%x, cbImage=%x\n", uRVA, pModDH->cbImage),
+                        KDBG_ERR_INVALID_ADDRESS);
+    for (KI32 iSegment = 0; iSegment < pModDH->cSections; iSegment++)
+    {
+        /** @todo should probably be less strict about address in the alignment gaps. */
+        KU32 off = uRVA - pModDH->aSections[iSegment].VirtualAddress;
+        if (off < pModDH->aSections[iSegment].Misc.VirtualSize)
+        {
+            *poff = off;
+            *piSegment = iSegment;
+            return 0;
+        }
+    }
+    kDbgAssertMsgFailedReturn(("uRVA=%x\n", uRVA), KDBG_ERR_INVALID_ADDRESS);
+}
+
+
+/**
+ * @copydoc KDBGMODOPS::pfnQueryLine
+ */
+static int kdbgModDHQueryLine(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PKDBGLINE pLine)
+{
+    PKDBGMODDBGHELP pModDH = (PKDBGMODDBGHELP)pMod;
+
+    /*
+     * Translate the address to an RVA.
+     */
+    KU32 uRVA;
+    int rc = kdbgModDHSegOffToRVA(pModDH, iSegment, off, &uRVA);
+    if (!rc)
+    {
+        DWORD64 off;
+        IMAGEHLP_LINE64 Line;
+        Line.SizeOfStruct = sizeof(Line);
+        if (g_pfnSymGetLineFromAddr64(pModDH->hSymInst, pModDH->ImageBase + uRVA, &off, &Line))
+        {
+            pLine->RVA = (KDBGADDR)(Line.Address - pModDH->ImageBase);
+            rc = kdbgModDHRVAToSegOff(pModDH, (KU32)pLine->RVA, &pLine->iSegment, &pLine->offSegment);
+            pLine->iLine = Line.LineNumber;
+            KSIZE cchFile = kHlpStrLen(Line.FileName);
+            pLine->cchFile = cchFile < sizeof(pLine->szFile)
+                           ? (KU16)cchFile
+                           : (KU16)sizeof(pLine->szFile) - 1;
+            kHlpMemCopy(pLine->szFile, Line.FileName, pLine->cchFile);
+            pLine->szFile[pLine->cchFile] = '\0';
+        }
+        else
+        {
+            DWORD Err = GetLastError();
+            rc = kdbgModDHConvWinError(Err);
+        }
+    }
+    return rc;
+}
+
+
+/**
+ * @copydoc KDBGMODOPS::pfnQuerySymbol
+ */
+static int kdbgModDHQuerySymbol(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PKDBGSYMBOL pSym)
+{
+    PKDBGMODDBGHELP pModDH = (PKDBGMODDBGHELP)pMod;
+
+    /*
+     * Translate the address to an RVA.
+     */
+    KU32 uRVA;
+    int rc = kdbgModDHSegOffToRVA(pModDH, iSegment, off, &uRVA);
+    if (!rc)
+    {
+        DWORD64 off;
+        union
+        {
+            SYMBOL_INFO Sym;
+            char        achBuffer[sizeof(SYMBOL_INFO) + KDBG_SYMBOL_MAX];
+        } Buf;
+        Buf.Sym.SizeOfStruct = sizeof(SYMBOL_INFO);
+        Buf.Sym.MaxNameLen = KDBG_SYMBOL_MAX;
+        if (g_pfnSymFromAddr(pModDH->hSymInst, pModDH->ImageBase + uRVA, &off, &Buf.Sym))
+        {
+            pSym->cb      = Buf.Sym.Size;
+            pSym->Address = NIL_KDBGADDR;
+            pSym->fFlags  = 0;
+            if (Buf.Sym.Flags & SYMFLAG_FUNCTION)
+                pSym->fFlags |= KDBGSYM_FLAGS_CODE;
+            else if (Buf.Sym.Flags & SYMFLAG_CONSTANT)
+                pSym->fFlags |= KDBGSYM_FLAGS_ABS; /** @todo SYMFLAG_CONSTANT must be tested - documentation is too brief to say what is really meant here.*/
+            else
+                pSym->fFlags |= KDBGSYM_FLAGS_DATA;
+            if (Buf.Sym.Flags & SYMFLAG_EXPORT)
+                pSym->fFlags |= KDBGSYM_FLAGS_EXPORTED;
+            if ((Buf.Sym.Flags & (SYMFLAG_VALUEPRESENT | SYMFLAG_CONSTANT)) == (SYMFLAG_VALUEPRESENT | SYMFLAG_CONSTANT))
+            {
+                pSym->iSegment   = KDBGSEG_ABS;
+                pSym->offSegment = (KDBGADDR)Buf.Sym.Value;
+                pSym->RVA        = (KDBGADDR)Buf.Sym.Value;
+            }
+            else
+            {
+                pSym->RVA        = (KDBGADDR)(Buf.Sym.Address - pModDH->ImageBase);
+                rc = kdbgModDHRVAToSegOff(pModDH, (KU32)pSym->RVA, &pSym->iSegment, &pSym->offSegment);
+            }
+            pSym->cchName = (KU16)Buf.Sym.NameLen;
+            if (pSym->cchName >= sizeof(pSym->szName))
+                pSym->cchName = sizeof(pSym->szName) - 1;
+            kHlpMemCopy(pSym->szName, Buf.Sym.Name, Buf.Sym.NameLen);
+            pSym->szName[Buf.Sym.NameLen] = '\0';
+        }
+        else
+        {
+            DWORD Err = GetLastError();
+            rc = kdbgModDHConvWinError(Err);
+        }
+    }
+    return rc;
+}
+
+
+/**
+ * @copydoc KDBGMODOPS::pfnClose
+ */
+static int kdbgModDHClose(PKDBGMOD pMod)
+{
+    PKDBGMODDBGHELP pModDH = (PKDBGMODDBGHELP)pMod;
+
+    if (g_pfnSymCleanup(pModDH->hSymInst))
+        return 0;
+
+    DWORD Err = GetLastError();
+    int rc = kdbgModDHConvWinError(Err);
+    kDbgAssertMsgFailed(("SymInitialize failed: Err=%d rc=%d\n", Err, rc));
+    return rc;
+}
+
+
+/**
+ * Checks if the specified dbghelp.dll is usable.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   pszPath     the path to the dbghelp.dll.
+ */
+static int kdbgModDHTryDbgHelp(const char *pszPath, KU32 *pu32FileVersionMS, KU32 *pu32FileVersionLS)
+{
+    int rc;
+    DWORD dwHandle = 0;
+    DWORD cb = GetFileVersionInfoSize(pszPath, &dwHandle);
+    if (cb > 0)
+    {
+        void *pvBuf = alloca(cb);
+        if (GetFileVersionInfo(pszPath, dwHandle, cb, pvBuf))
+        {
+            UINT cbValue = 0;
+            VS_FIXEDFILEINFO *pFileInfo;
+            if (VerQueryValue(pvBuf, "\\", (void **)&pFileInfo, &cbValue))
+            {
+                /** @todo somehow reject 64-bit .dlls when in 32-bit mode... dwFileOS is completely useless. */
+                if (    *pu32FileVersionMS < pFileInfo->dwFileVersionMS
+                    ||  (   *pu32FileVersionMS == pFileInfo->dwFileVersionMS
+                         && *pu32FileVersionLS  > pFileInfo->dwFileVersionLS))
+                {
+                    *pu32FileVersionMS = pFileInfo->dwFileVersionMS;
+                    *pu32FileVersionLS = pFileInfo->dwFileVersionLS;
+                }
+                if (pFileInfo->dwFileVersionMS >= 0x60004)
+                    rc = 0;
+                else
+                    rc = KDBG_ERR_DBGHLP_VERSION_MISMATCH;
+            }
+            else
+                rc = KERR_GENERAL_FAILURE;
+        }
+        else
+            rc = kdbgModDHConvWinError(GetLastError());
+    }
+    else
+        rc = kdbgModDHConvWinError(GetLastError());
+    return rc;
+}
+
+
+/**
+ * Find the dbghelp.dll
+ */
+static int kdbgModDHFindDbgHelp(char *pszPath, KSIZE cchPath)
+{
+    /*
+     * Try the current directory.
+     */
+    KU32 FileVersionMS = 0;
+    KU32 FileVersionLS = 0;
+    int rc = KERR_GENERAL_FAILURE;
+    static char s_szDbgHelp[] = "\\dbghelp.dll";
+    if (GetCurrentDirectory((DWORD)(cchPath - sizeof(s_szDbgHelp) + 1), pszPath))
+    {
+        strcat(pszPath, s_szDbgHelp);
+        int rc2 = kdbgModDHTryDbgHelp(pszPath, &FileVersionMS, &FileVersionLS);
+        if (!rc2)
+            return rc2;
+        if (rc != KDBG_ERR_DBGHLP_VERSION_MISMATCH)
+            rc = rc2;
+    }
+
+    /*
+     * Try the application directory.
+     */
+    if (GetModuleFileName(NULL, pszPath, (DWORD)(cchPath - sizeof(s_szDbgHelp) + 1)))
+    {
+        kHlpStrCat(kHlpStrRChr(pszPath, '\\'), s_szDbgHelp);
+        int rc2 = kdbgModDHTryDbgHelp(pszPath, &FileVersionMS, &FileVersionLS);
+        if (!rc)
+            return rc2;
+        if (rc != KDBG_ERR_DBGHLP_VERSION_MISMATCH)
+            rc = rc2;
+    }
+
+    /*
+     * Try the windows directory.
+     */
+    if (GetSystemDirectory(pszPath, (DWORD)(cchPath - sizeof(s_szDbgHelp) + 1)))
+    {
+        kHlpStrCat(pszPath, s_szDbgHelp);
+        int rc2 = kdbgModDHTryDbgHelp(pszPath, &FileVersionMS, &FileVersionLS);
+        if (!rc2)
+            return rc2;
+        if (rc != KDBG_ERR_DBGHLP_VERSION_MISMATCH)
+            rc = rc2;
+    }
+
+    /*
+     * Try the windows directory.
+     */
+    if (GetWindowsDirectory(pszPath, (DWORD)(cchPath - sizeof(s_szDbgHelp) + 1)))
+    {
+        kHlpStrCat(pszPath, s_szDbgHelp);
+        int rc2 = kdbgModDHTryDbgHelp(pszPath, &FileVersionMS, &FileVersionLS);
+        if (!rc2)
+            return rc2;
+        if (rc != KDBG_ERR_DBGHLP_VERSION_MISMATCH)
+            rc = rc2;
+    }
+
+    /*
+     * Try the path.
+     */
+    /** @todo find the actual path specs, I'm probably not doing this 100% correctly here. */
+    DWORD cb = GetEnvironmentVariable("PATH", NULL, 0) + 64;
+    char *pszSearchPath = (char *) alloca(cb);
+    if (GetEnvironmentVariable("PATH", pszSearchPath, cb) < cb)
+    {
+        char *psz = pszSearchPath;
+        while (*psz)
+        {
+            /* find the end of the path. */
+            char *pszEnd = kHlpStrChr(psz, ';');
+            if (!pszEnd)
+                pszEnd = kHlpStrChr(psz, '\0');
+            if (pszEnd != psz)
+            {
+                /* construct filename and try it out */
+                kHlpMemCopy(pszPath, psz, pszEnd - psz);
+                kHlpMemCopy(&pszPath[pszEnd - psz], s_szDbgHelp, sizeof(s_szDbgHelp));
+                int rc2 = kdbgModDHTryDbgHelp(pszPath, &FileVersionMS, &FileVersionLS);
+                if (!rc2)
+                    return rc2;
+                if (rc != KDBG_ERR_DBGHLP_VERSION_MISMATCH)
+                    rc = rc2;
+            }
+
+            /* next path */
+            if (!*pszEnd)
+                break;
+            psz = pszEnd + 1;
+        }
+    }
+
+    if (rc == KDBG_ERR_DBGHLP_VERSION_MISMATCH)
+        kDbgAssertMsgFailed(("dbghelp.dll found, but it was ancient! The highest file version found was 0x%08x'%08x.\n"
+                             "This program require a file version of at least 0x00060004'00000000. Please download\n"
+                             "the latest windbg and use the dbghelp.dll from that package. Just put it somewhere in\n"
+                             "the PATH and we'll find it.\n", FileVersionMS, FileVersionLS));
+    else
+        kDbgAssertMsgFailed(("dbghelp.dll was not found! Download the latest windbg and use the dbghelp.dll\n"
+                             "from that package - just put it somewhere in the PATH and we'll find it.\n"));
+    return rc;
+}
+
+
+/**
+ * Loads the dbghelp.dll, check that it's the right version, and
+ * resolves all the symbols we need.
+ *
+ * @returns IPRT status code.
+ */
+static int kdbgModDHLoadDbgHelp(void)
+{
+    if (g_hDbgHelp)
+        return 0;
+
+    /* primitive locking - make some useful API for this kind of spinning! */
+    static volatile long s_lLock = 0;
+    while (InterlockedCompareExchange(&s_lLock, 1, 0))
+        while (s_lLock)
+            Sleep(1);
+    if (g_hDbgHelp)
+    {
+        InterlockedExchange(&s_lLock, 0);
+        return 0;
+    }
+
+    /*
+     * Load it - try current dir first.
+     */
+    char szPath[260];
+    int rc = kdbgModDHFindDbgHelp(szPath, sizeof(szPath));
+    if (rc)
+    {
+        InterlockedExchange(&s_lLock, 0);
+        return rc;
+    }
+
+    HMODULE hmod = LoadLibraryEx(szPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+    if (!hmod)
+    {
+        DWORD Err = GetLastError();
+        int rc = kdbgModDHConvWinError(Err);
+        InterlockedExchange(&s_lLock, 0);
+        kDbgAssertMsgFailedReturn(("Failed to load '%s', Err=%d rc=%d\n", szPath, Err, rc), rc);
+    }
+
+    /*
+     * Check the API version (too).
+     */
+    LPAPI_VERSION (WINAPI *pfnImagehlpApiVersion)(VOID);
+    FARPROC *ppfn = (FARPROC *)&pfnImagehlpApiVersion;
+    *ppfn = GetProcAddress(hmod, "ImagehlpApiVersion");
+    if (*ppfn)
+    {
+        LPAPI_VERSION pVersion = pfnImagehlpApiVersion();
+        if (    pVersion
+            &&  (   pVersion->MajorVersion > 4
+                 || (pVersion->MajorVersion == 4 && pVersion->MinorVersion > 0)
+                 || (pVersion->MajorVersion == 4 && pVersion->MinorVersion == 0 && pVersion->Revision >= 5)
+                )
+           )
+        {
+            /*
+             * Resolve the entrypoints we need.
+             */
+            static const struct
+            {
+                const char *pszName;
+                FARPROC *ppfn;
+            }   s_aFunctions[] =
+            {
+                { "SymInitialize",      (FARPROC *)&g_pfnSymInitialize },
+                { "SymCleanup",         (FARPROC *)&g_pfnSymCleanup },
+                { "SymSetOptions",      (FARPROC *)&g_pfnSymSetOptions },
+                { "SymLoadModule64",    (FARPROC *)&g_pfnSymLoadModule64 },
+                { "SymFromAddr",        (FARPROC *)&g_pfnSymFromAddr },
+                { "SymFromAddr",        (FARPROC *)&g_pfnSymFromAddr },
+                { "SymGetLineFromAddr64", (FARPROC *)&g_pfnSymGetLineFromAddr64 },
+            };
+            for (unsigned i = 0; i < K_ELEMENTS(s_aFunctions); i++)
+            {
+                FARPROC pfn = GetProcAddress(hmod, s_aFunctions[i].pszName);
+                if (!pfn)
+                {
+                    DWORD Err = GetLastError();
+                    rc = kdbgModDHConvWinError(Err);
+                    kDbgAssertMsgFailed(("Failed to resolve %s in dbghelp, Err=%d rc=%d\n",
+                                         s_aFunctions[i].pszName, Err, rc));
+                    break;
+                }
+                *s_aFunctions[i].ppfn = pfn;
+            }
+            if (!rc)
+            {
+                g_hDbgHelp = hmod;
+                Sleep(1);
+                InterlockedExchange(&s_lLock, 0);
+                return 0;
+            }
+        }
+        else
+        {
+            rc = KDBG_ERR_DBGHLP_VERSION_MISMATCH;
+            kDbgAssertMsgFailed(("ImagehlpApiVersion -> %p and MajorVersion=%d.\n", pVersion, pVersion ? pVersion->MajorVersion : 0));
+        }
+    }
+    else
+    {
+        DWORD Err = GetLastError();
+        rc = kdbgModDHConvWinError(Err);
+        kDbgAssertMsgFailed(("Failed to resolve ImagehlpApiVersionEx in dbghelp, Err=%d rc=%d\n", Err, rc));
+    }
+    FreeLibrary(hmod);
+    InterlockedExchange(&s_lLock, 0);
+    return rc;
+}
+
+
+/**
+ * @copydoc KDBGMODOPS::pfnOpen
+ */
+static int kdbgModDHOpen(PKDBGMOD *ppMod, PKRDR pRdr, KBOOL fCloseRdr, KFOFF off, KFOFF cb, struct KLDRMOD *pLdrMod)
+{
+    /*
+     * This reader doesn't support partial files.
+     * Also weed out small files early on as they cannot be
+     * PE images and will only cause read errors
+     */
+    if (    off != 0
+        ||  cb != KFOFF_MAX)
+        return KDBG_ERR_UNKOWN_FORMAT;
+    if (kRdrSize(pRdr) < sizeof(IMAGE_NT_HEADERS32) + sizeof(IMAGE_SECTION_HEADER))
+        return KDBG_ERR_UNKOWN_FORMAT;
+
+    /*
+     * We need to read the section headers and get the image size.
+     */
+    /* Find the PE header magic. */
+    KU32 offHdr = 0;
+    KU32 u32Magic;
+    int rc = kRdrRead(pRdr, &u32Magic, sizeof(u32Magic), 0);
+    kDbgAssertRCReturn(rc, rc);
+    if ((KU16)u32Magic == IMAGE_DOS_SIGNATURE)
+    {
+        rc = kRdrRead(pRdr, &offHdr, sizeof(offHdr), K_OFFSETOF(IMAGE_DOS_HEADER, e_lfanew));
+        kDbgAssertRCReturn(rc, rc);
+        if (!offHdr)
+            return KDBG_ERR_FORMAT_NOT_SUPPORTED;
+        if (    offHdr < sizeof(IMAGE_DOS_SIGNATURE)
+            ||  offHdr >= kRdrSize(pRdr) - 4)
+            return KDBG_ERR_BAD_EXE_FORMAT;
+
+        rc = kRdrRead(pRdr, &u32Magic, sizeof(u32Magic), offHdr);
+        kDbgAssertRCReturn(rc, rc);
+    }
+    if (u32Magic != IMAGE_NT_SIGNATURE)
+        return KDBG_ERR_FORMAT_NOT_SUPPORTED;
+
+    /* read the file header and the image size in the optional header.. */
+    IMAGE_FILE_HEADER FHdr;
+    rc = kRdrRead(pRdr, &FHdr, sizeof(FHdr), offHdr + K_OFFSETOF(IMAGE_NT_HEADERS32, FileHeader));
+    kDbgAssertRCReturn(rc, rc);
+
+    KU32 cbImage;
+    if (FHdr.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32))
+        rc = kRdrRead(pRdr, &cbImage, sizeof(cbImage),
+                      offHdr + K_OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader.SizeOfImage));
+    else if (FHdr.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER64))
+        rc = kRdrRead(pRdr, &cbImage, sizeof(cbImage),
+                      offHdr + K_OFFSETOF(IMAGE_NT_HEADERS64, OptionalHeader.SizeOfImage));
+    else
+        kDbgAssertFailedReturn(KDBG_ERR_BAD_EXE_FORMAT);
+    kDbgAssertRCReturn(rc, rc);
+
+    /*
+     * Load dbghelp.dll.
+     */
+    rc = kdbgModDHLoadDbgHelp();
+    if (rc)
+        return rc;
+
+    /*
+     * Allocate the module and read/construct the section headers.
+     */
+    PKDBGMODDBGHELP pModDH = (PKDBGMODDBGHELP)kHlpAlloc(K_OFFSETOF(KDBGMODDBGHELP, aSections[FHdr.NumberOfSections + 2]));
+    kDbgAssertReturn(pModDH, KERR_NO_MEMORY);
+    pModDH->Core.u32Magic   = KDBGMOD_MAGIC;
+    pModDH->Core.pOps       = &g_kDbgModWinDbgHelpOpen;
+    pModDH->Core.pRdr       = pRdr;
+    pModDH->Core.fCloseRdr  = fCloseRdr;
+    pModDH->Core.pLdrMod    = pLdrMod;
+    pModDH->cbImage         = cbImage;
+    pModDH->cSections       = 1 + FHdr.NumberOfSections;
+
+    rc = kRdrRead(pRdr, &pModDH->aSections[1], sizeof(pModDH->aSections[0]) * FHdr.NumberOfSections,
+                  offHdr + K_OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader) + FHdr.SizeOfOptionalHeader);
+    if (!rc)
+    {
+        PIMAGE_SECTION_HEADER pSH = &pModDH->aSections[0];
+        kHlpMemCopy(pSH->Name, "headers", sizeof(pSH->Name));
+        pSH->Misc.VirtualSize       = pModDH->aSections[1].VirtualAddress;
+        pSH->VirtualAddress         = 0;
+        pSH->SizeOfRawData          = pSH->Misc.VirtualSize;
+        pSH->PointerToRawData       = 0;
+        pSH->PointerToRelocations   = 0;
+        pSH->PointerToLinenumbers   = 0;
+        pSH->NumberOfRelocations    = 0;
+        pSH->NumberOfLinenumbers    = 0;
+        pSH->Characteristics        = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ;
+
+        KU32 uTheEnd = pModDH->aSections[FHdr.NumberOfSections].VirtualAddress
+                     + pModDH->aSections[FHdr.NumberOfSections].Misc.VirtualSize;
+        if (uTheEnd < cbImage)
+        {
+            pSH = &pModDH->aSections[pModDH->cSections++];
+            kHlpMemCopy(pSH->Name, "tail\0\0\0", sizeof(pSH->Name));
+            pSH->Misc.VirtualSize       = cbImage - uTheEnd;
+            pSH->VirtualAddress         = uTheEnd;
+            pSH->SizeOfRawData          = pSH->Misc.VirtualSize;
+            pSH->PointerToRawData       = 0;
+            pSH->PointerToRelocations   = 0;
+            pSH->PointerToLinenumbers   = 0;
+            pSH->NumberOfRelocations    = 0;
+            pSH->NumberOfLinenumbers    = 0;
+            pSH->Characteristics        = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_MEM_READ;
+        }
+
+        /*
+         * Find a new dbghelp handle.
+         *
+         * We assume 4GB of handles outlast most debugging sessions, or in anyways that
+         * when we start reusing handles they are no longer in use. :-)
+         */
+        static volatile long s_u32LastHandle = 1;
+        HANDLE hSymInst = (HANDLE)InterlockedIncrement(&s_u32LastHandle);
+        while (     hSymInst == INVALID_HANDLE_VALUE
+               ||   hSymInst == (HANDLE)0
+               ||   hSymInst == GetCurrentProcess())
+            hSymInst = (HANDLE)InterlockedIncrement(&s_u32LastHandle);
+
+        /*
+         * Initialize dbghelp and try open the specified module.
+         */
+        if (g_pfnSymInitialize(hSymInst, NULL, FALSE))
+        {
+            g_pfnSymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_AUTO_PUBLICS | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS);
+
+            KIPTR NativeFH = kRdrNativeFH(pRdr);
+            DWORD64 ImageBase = g_pfnSymLoadModule64(hSymInst, NativeFH == -1 ? NULL : (HANDLE)NativeFH,
+                                                     kRdrName(pRdr), NULL, 0x00400000, 0);
+            if (ImageBase)
+            {
+                pModDH->hSymInst        = hSymInst;
+                pModDH->ImageBase       = ImageBase;
+                *ppMod = &pModDH->Core;
+                return rc;
+            }
+
+            DWORD Err = GetLastError();
+            rc = kdbgModDHConvWinError(Err);
+            kDbgAssertMsgFailed(("SymLoadModule64 failed: Err=%d rc=%d\n", Err, rc));
+            g_pfnSymCleanup(hSymInst);
+        }
+        else
+        {
+            DWORD Err = GetLastError();
+            rc = kdbgModDHConvWinError(Err);
+            kDbgAssertMsgFailed(("SymInitialize failed: Err=%d rc=%d\n", Err, rc));
+        }
+    }
+    else
+        kDbgAssertRC(rc);
+
+    kHlpFree(pModDH);
+    return rc;
+}
+
+
+/**
+ * Methods for a PE module.
+ */
+KDBGMODOPS const g_kDbgModWinDbgHelpOpen =
+{
+    "Windows DbgHelp",
+    NULL,
+    kdbgModDHOpen,
+    kdbgModDHClose,
+    kdbgModDHQuerySymbol,
+    kdbgModDHQueryLine,
+    "Windows DbgHelp"
+};
+
diff --git a/src/lib/kStuff/kDbg/kDbgModule.cpp b/src/lib/kStuff/kDbg/kDbgModule.cpp
new file mode 100644
index 0000000..c43fb16
--- /dev/null
+++ b/src/lib/kStuff/kDbg/kDbgModule.cpp
@@ -0,0 +1,440 @@
+/* $Id: kDbgModule.cpp 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kDbg - The Debug Info Reader, Module API.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "kDbgInternal.h"
+#include <k/kHlpString.h>
+#include <k/kHlpAlloc.h>
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/**
+ * The built-in debug module readers.
+ */
+static PCKDBGMODOPS const g_aBuiltIns[] =
+{
+#if K_OS == K_OS_WINDOWS
+    &g_kDbgModWinDbgHelpOpen,
+#endif
+    &g_kDbgModLdr,
+//    &g_kDbgModCv8,
+//    &g_kDbgModDwarf,
+//    &g_kDbgModHll,
+//    &g_kDbgModStabs,
+//    &g_kDbgModSym,
+//    &g_kDbgModMapILink,
+//    &g_kDbgModMapMSLink,
+//    &g_kDbgModMapNm,
+//    &g_kDbgModMapWLink
+};
+
+/**
+ * The debug module readers registered at runtime.
+ */
+static PKDBGMODOPS g_pHead = NULL;
+
+
+/**
+ * Register a debug module reader with the kDbgModule component.
+ *
+ * Dynamically registered readers are kept in FIFO order, and external
+ * readers will be tried after the builtin ones.
+ *
+ * Like all other kDbg APIs serializing is left to the caller.
+ *
+ * @returns 0 on success.
+ * @returns KERR_INVALID_POINTER if pOps is missing bits.
+ * @returns KERR_INVALID_PARAMETER if pOps is already in the list.
+ * @param   pOps        The reader method table, kDbg takes owner ship of
+ *                      this. This must be writeable as the pNext pointer
+ *                      will be update. It must also stick around for as
+ *                      long as kDbg is in use.
+ */
+KDBG_DECL(int) kDbgModuleRegisterReader(PKDBGMODOPS pOps)
+{
+    /*
+     * Validate input.
+     */
+    kDbgAssertPtrReturn(pOps, KERR_INVALID_POINTER);
+    kDbgAssertPtrReturn(pOps->pszName, KERR_INVALID_POINTER);
+    kDbgAssertPtrReturn(pOps->pfnOpen, KERR_INVALID_POINTER);
+    kDbgAssertPtrReturn(pOps->pfnClose, KERR_INVALID_POINTER);
+    kDbgAssertPtrReturn(pOps->pfnQuerySymbol, KERR_INVALID_POINTER);
+    kDbgAssertPtrReturn(pOps->pfnQueryLine, KERR_INVALID_POINTER);
+    kDbgAssertPtrReturn(pOps->pszName2, KERR_INVALID_POINTER);
+    if (kHlpStrComp(pOps->pszName, pOps->pszName2))
+        return KERR_INVALID_PARAMETER;
+    kDbgAssertReturn(pOps->pNext == NULL, KERR_INVALID_PARAMETER);
+
+    /*
+     * Link it into the list.
+     */
+    if (!g_pHead)
+        g_pHead = pOps;
+    else
+    {
+        PKDBGMODOPS pPrev = g_pHead;
+        while (pPrev->pNext)
+            pPrev = pPrev->pNext;
+        kDbgAssertReturn(pPrev != pOps, KERR_INVALID_PARAMETER);
+        pPrev->pNext = pOps;
+    }
+    return 0;
+}
+
+
+/**
+ * Deregister a debug module reader previously registered using
+ * the kDbgModuleRegisterReader API.
+ *
+ * Deregistering a reader does not mean that non of its functions
+ * will be called after successful return, it only means that it
+ * will no longer be subjected to new module.
+ *
+ * @returns 0 on success.
+ * @returns KERR_INVALID_POINTER if pOps isn't a valid pointer.
+ * @returns KERR_INVALID_PARAMETER if pOps wasn't registered.
+ * @param   pOps    The debug module method table to deregister.
+ */
+KDBG_DECL(int) kDbgModuleDeregisterReader(PKDBGMODOPS pOps)
+{
+    /*
+     * Validate the pointer.
+     */
+    kDbgAssertPtrReturn(pOps, KERR_INVALID_POINTER);
+
+    /*
+     * Find it in the list and unlink it.
+     */
+    if (g_pHead == pOps)
+        g_pHead = pOps->pNext;
+    else
+    {
+        PKDBGMODOPS pPrev = g_pHead;
+        while (pPrev && pPrev->pNext != pOps)
+            pPrev = pPrev->pNext;
+        if (!pPrev)
+            return KERR_INVALID_PARAMETER;
+        pPrev->pNext = pOps->pNext;
+    }
+    pOps->pNext = NULL;
+    return 0;
+}
+
+
+
+/**
+ * Worker for the kDbgModuleOpen* APIs.
+ *
+ * This will make sure the reader is buffered. I will also take care of
+ * closing the reader opened by kDbgModuleOpen on failure.
+ *
+ * @returns 0 on success. An appropriate kErrors status code on failure.
+ * @param   ppDbgMod        Where to store the new debug module reader instance.
+ * @param   pRdr            The file provider.
+ * @param   fCloseRdr       Whether pRdr should be close or not. This applies both
+ *                          to the failure path and to the success path, where it'll
+ *                          be close when the module is closed by kDbgModuleClose().
+ * @param   off             The offset into the file where the debug info is supposed
+ *                          to be found.
+ *                          This is 0 if the entire file is the subject.
+ * @param   cb              The size of the debug info part of the file.
+ *                          This is KFOFF_MAX if the entire file is the subject.
+ * @param   pLdrMod         An optional kLdrMod association.
+ */
+static int kdbgModuleOpenWorker(PPKDBGMOD ppDbgMod, PKRDR pRdr, KBOOL fCloseRdr, KFOFF off, KFOFF cb, struct KLDRMOD *pLdrMod)
+{
+    /*
+     * If the reader isn't buffered create a buffered wrapper for it.
+     */
+    int rc;
+    PKRDR pRdrWrapped = NULL;
+    if (!kRdrBufIsBuffered(pRdr))
+    {
+        rc = kRdrBufWrap(&pRdrWrapped, pRdr, fCloseRdr);
+        if (rc)
+        {
+            if (fCloseRdr)
+                kRdrClose(pRdr);
+            return rc;
+        }
+        pRdr = pRdrWrapped;
+    }
+
+    /*
+     * Walk the built-in table and the list of registered readers
+     * and let each of them have a go at the file. Stop and return
+     * on the first one returning successfully.
+     */
+    rc = KDBG_ERR_UNKOWN_FORMAT;
+    for (KSIZE i = 0; i < K_ELEMENTS(g_aBuiltIns); i++)
+        if (g_aBuiltIns[i]->pfnOpen)
+        {
+            int rc2 = g_aBuiltIns[i]->pfnOpen(ppDbgMod, pRdr, fCloseRdr, off, cb, pLdrMod);
+            if (!rc2)
+                return 0;
+            if (rc2 != KDBG_ERR_UNKOWN_FORMAT && rc == KDBG_ERR_UNKOWN_FORMAT)
+                rc = rc2;
+        }
+
+    for (PKDBGMODOPS pCur = g_pHead; pCur; pCur = pCur->pNext)
+        if (pCur->pfnOpen)
+        {
+            int rc2 = pCur->pfnOpen(ppDbgMod, pRdr, fCloseRdr, off, cb, pLdrMod);
+            if (!rc2)
+                return 0;
+            if (rc2 != KDBG_ERR_UNKOWN_FORMAT && rc == KDBG_ERR_UNKOWN_FORMAT)
+                rc = rc2;
+        }
+
+    if (pRdrWrapped)
+        kRdrClose(pRdrWrapped);
+    else if (fCloseRdr)
+        kRdrClose(pRdr);
+    return rc;
+}
+
+
+/**
+ * Opens a debug module reader for the specified file or file section
+ *
+ * @returns kStuff status code.
+ * @param   ppDbgMod            Where to store the debug module reader handle.
+ * @param   pRdr                The file reader.
+ * @param   off                 The offset of the file section. If the entire file, pass 0.
+ * @param   cb                  The size of the file section. If the entire file, pass KFOFF_MAX.
+ * @param   pLdrMod             Associated kLdr module that the kDbg component can use to
+ *                              verify and suplement the debug info found in the file specified
+ *                              by pszFilename. The module will be used by kDbg for as long as
+ *                              the returned kDbg module remains open.
+ *                              This is an optional parameter, pass NULL if no kLdr module at hand.
+ */
+KDBG_DECL(int) kDbgModuleOpenFilePart(PPKDBGMOD ppDbgMod, PKRDR pRdr, KFOFF off, KFOFF cb, struct KLDRMOD *pLdrMod)
+{
+    /*
+     * Validate input.
+     */
+    kDbgAssertPtrReturn(ppDbgMod, KERR_INVALID_POINTER);
+    kDbgAssertPtrReturn(pRdr, KERR_INVALID_POINTER);
+    kDbgAssertPtrNullReturn(pLdrMod, KERR_INVALID_POINTER);
+    kDbgAssertMsgReturn(off >= 0 && off < KFOFF_MAX, (KFOFF_PRI "\n", off), KERR_INVALID_OFFSET);
+    kDbgAssertMsgReturn(cb >= 0 && cb <= KFOFF_MAX, (KFOFF_PRI "\n", cb), KERR_INVALID_SIZE);
+    kDbgAssertMsgReturn(off + cb > off, ("off=" KFOFF_PRI " cb=" KFOFF_PRI "\n", off, cb), KERR_INVALID_RANGE);
+    *ppDbgMod = NULL;
+
+    /*
+     * Hand it over to the internal worker.
+     */
+    return kdbgModuleOpenWorker(ppDbgMod, pRdr, K_FALSE /* fCloseRdr */, off, cb, pLdrMod);
+}
+
+
+/**
+ * Opens a debug module reader for the specified file.
+ *
+ * @returns kStuff status code.
+ * @param   ppDbgMod            Where to store the debug module reader handle.
+ * @param   pRdr                The file reader.
+ * @param   pLdrMod             Associated kLdr module that the kDbg component can use to
+ *                              verify and suplement the debug info found in the file specified
+ *                              by pszFilename. The module will be used by kDbg for as long as
+ *                              the returned kDbg module remains open.
+ *                              This is an optional parameter, pass NULL if no kLdr module at hand.
+ */
+KDBG_DECL(int) kDbgModuleOpenFile(PPKDBGMOD ppDbgMod, PKRDR pRdr, struct KLDRMOD *pLdrMod)
+{
+    return kDbgModuleOpenFilePart(ppDbgMod, pRdr, 0, KFOFF_MAX, pLdrMod);
+}
+
+
+/**
+ * Opens the debug info for a specified executable module.
+ *
+ * @returns kStuff status code.
+ * @param   ppDbgMod            Where to store the debug module handle.
+ * @param   pszFilename         The name of the file containing debug info and/or which
+ *                              debug info is wanted.
+ * @param   pLdrMod             Associated kLdr module that the kDbg component can use to
+ *                              verify and suplement the debug info found in the file specified
+ *                              by pszFilename. The module will be used by kDbg for as long as
+ *                              the returned kDbg module remains open.
+ *                              This is an optional parameter, pass NULL if no kLdr module at hand.
+ */
+KDBG_DECL(int) kDbgModuleOpen(PPKDBGMOD ppDbgMod, const char *pszFilename, struct KLDRMOD *pLdrMod)
+{
+    /*
+     * Validate input.
+     */
+    kDbgAssertPtrReturn(ppDbgMod, KERR_INVALID_POINTER);
+    kDbgAssertPtrReturn(pszFilename, KERR_INVALID_POINTER);
+    kDbgAssertMsgReturn(*pszFilename, ("%p\n", pszFilename), KERR_INVALID_PARAMETER);
+    kDbgAssertPtrNullReturn(pLdrMod, KERR_INVALID_POINTER);
+    *ppDbgMod = NULL;
+
+    /*
+     * Open the file and see if we can read it.
+     */
+    PKRDR pRdr;
+    int rc = kRdrBufOpen(&pRdr, pszFilename);
+    if (rc)
+        return rc;
+    rc = kdbgModuleOpenWorker(ppDbgMod, pRdr, K_TRUE /* fCloseRdr */, 0, KFOFF_MAX, pLdrMod);
+    return rc;
+}
+
+
+/**
+ * Closes the module.
+ *
+ * @returns IPRT status code.
+ * @param   pMod        The module handle.
+ */
+KDBG_DECL(int) kDbgModuleClose(PKDBGMOD pMod)
+{
+    KDBGMOD_VALIDATE(pMod);
+    int rc = pMod->pOps->pfnClose(pMod);
+    if (!rc)
+    {
+        pMod->u32Magic++;
+        kHlpFree(pMod);
+    }
+    return rc;
+}
+
+
+/**
+ * Gets a symbol by segment:offset.
+ * This will be approximated to the nearest symbol if there is no exact match.
+ *
+ * @returns IPRT status code.
+ * @param   pMod        The module.
+ * @param   iSegment    The segment this offset is relative to.
+ *                      The -1 segment is special, it means that the addres is relative to
+ *                      the image base. The image base is where the first bit of the image
+ *                      is mapped during load.
+ * @param   off         The offset into the segment.
+ * @param   pSym        Where to store the symbol details.
+ */
+KDBG_DECL(int) kDbgModuleQuerySymbol(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PKDBGSYMBOL pSym)
+{
+    KDBGMOD_VALIDATE(pMod);
+    kDbgAssertPtrReturn(pSym, KERR_INVALID_POINTER);
+    return pMod->pOps->pfnQuerySymbol(pMod, iSegment, off, pSym);
+}
+
+
+/**
+ * Gets & allocates a symbol by segment:offset.
+ * This will be approximated to the nearest symbol if there is no exact match.
+ *
+ * @returns IPRT status code.
+ * @param   pMod        The module.
+ * @param   iSegment    The segment this offset is relative to.
+ *                      The -1 segment is special, it means that the addres is relative to
+ *                      the image base. The image base is where the first bit of the image
+ *                      is mapped during load.
+ * @param   off         The offset into the segment.
+ * @param   ppSym       Where to store the pointer to the symbol info.
+ *                      Free the returned symbol using kDbgSymbolFree().
+ */
+KDBG_DECL(int) kDbgModuleQuerySymbolA(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PPKDBGSYMBOL ppSym)
+{
+    kDbgAssertPtrReturn(ppSym, KERR_INVALID_POINTER);
+
+    KDBGSYMBOL Sym;
+    int rc = kDbgModuleQuerySymbol(pMod, iSegment, off, &Sym);
+    if (!rc)
+    {
+        *ppSym = kDbgSymbolDup(&Sym);
+        if (!*ppSym)
+            rc = KERR_NO_MEMORY;
+    }
+    else
+        *ppSym = NULL;
+    return rc;
+}
+
+
+/**
+ * Gets a line number entry by segment:offset.
+ * This will be approximated to the nearest line number there is no exact match.
+ *
+ * @returns IPRT status code.
+ * @param   pMod        The module.
+ * @param   iSegment    The segment this offset is relative to.
+ *                      The -1 segment is special, it means that the addres is relative to
+ *                      the image base. The image base is where the first bit of the image
+ *                      is mapped during load.
+ * @param   off         The offset into the segment.
+ * @param   pLine       Where to store the line number details.
+ */
+KDBG_DECL(int) kDbgModuleQueryLine(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PKDBGLINE pLine)
+{
+    KDBGMOD_VALIDATE(pMod);
+    kDbgAssertPtrReturn(pLine, KERR_INVALID_POINTER);
+    return pMod->pOps->pfnQueryLine(pMod, iSegment, off, pLine);
+}
+
+
+/**
+ * Gets & allocates a line number entry by segment:offset.
+ * This will be approximated to the nearest line number there is no exact match.
+ *
+ * @returns IPRT status code.
+ * @param   pMod        The module.
+ * @param   iSegment    The segment this offset is relative to.
+ *                      The -1 segment is special, it means that the addres is relative to
+ *                      the image base. The image base is where the first bit of the image
+ *                      is mapped during load.
+ * @param   off         The offset into the segment.
+ * @param   ppLine      Where to store the pointer to the line number info.
+ *                      Free the returned line number using kDbgLineFree().
+ */
+KDBG_DECL(int) kDbgModuleQueryLineA(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PPKDBGLINE ppLine)
+{
+    kDbgAssertPtrReturn(ppLine, KERR_INVALID_POINTER);
+
+    KDBGLINE Line;
+    int rc = kDbgModuleQueryLine(pMod, iSegment, off, &Line);
+    if (!rc)
+    {
+        *ppLine = kDbgLineDup(&Line);
+        if (!*ppLine)
+            rc = KERR_NO_MEMORY;
+    }
+    else
+        *ppLine = NULL;
+    return rc;
+}
+
diff --git a/src/lib/kStuff/kDbg/kDbgSpace.cpp b/src/lib/kStuff/kDbg/kDbgSpace.cpp
new file mode 100644
index 0000000..2d6f1c0
--- /dev/null
+++ b/src/lib/kStuff/kDbg/kDbgSpace.cpp
@@ -0,0 +1,192 @@
+/* $Id: kDbgSpace.cpp 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kDbg - The Debug Info Reader, Address Space Manager.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "kDbgInternal.h"
+#include <k/kHlpAlloc.h>
+#include <k/kHlpString.h>
+#include <k/kAvl.h>
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/** Pointer to a name space module. */
+typedef struct KDBGSPACEMOD *PKDBGSPACEMOD;
+
+/**
+ * Tracks a module segment in the address space.
+ *
+ * These segments are organized in two trees, by address in the
+ * KDBGSPACE::pSegRoot tree and by selector value in the
+ * KDBGSPACE::pSegSelRoot tree.
+ *
+ * While the debug module reader could easily provide us with
+ * segment names and it could perhaps be interesting to lookup
+ * a segment by its name in some situations, this has been
+ * considered too much bother for now. :-)
+ */
+typedef struct KDBGSPACESEG
+{
+    /** The module segment index. */
+    KI32                    iSegment;
+    /** The address space module structure this segment belongs to. */
+    PKDBGSPACEMOD           pSpaceMod;
+} KDBGSPACESEG;
+typedef KDBGSPACESEG *PKDBGSPACESEG;
+
+
+/**
+ * Track a module in the name space.
+ *
+ * Each module in the address space can be addressed efficiently
+ * by module name. The module name has to be unique.
+ */
+typedef struct KDBGSPACEMOD
+{
+    /** The module name hash. */
+    KU32                    u32Hash;
+    /** The length of the module name. */
+    KU32                    cchName;
+    /** The module name. */
+    char                   *pszName;
+    /** The next module in the same bucket. */
+    PKDBGSPACEMOD           pNext;
+    /** Pointer to the debug module reader. */
+    PKDBGMOD                pMod;
+    /** The number of segments. */
+    KU32                    cSegs;
+    /** The segment array. (variable length) */
+    KDBGSPACESEG            aSegs[1];
+} KDBGSPACEMOD;
+
+
+typedef struct KDBGCACHEDSYM *PKDBGCACHEDSYM;
+/**
+ * A cached symbol.
+ */
+typedef struct KDBGCACHEDSYM
+{
+    /** The symbol name hash. */
+    KU32                    u32Hash;
+    /** The next symbol in the same bucket. */
+    PKDBGCACHEDSYM          pNext;
+    /** The next symbol belonging to the same module as this. */
+    PKDBGCACHEDSYM          pNextMod;
+    /** The cached symbol information. */
+    KDBGSYMBOL              Sym;
+} KDBGCACHEDSYM;
+
+
+/**
+ * A symbol cache.
+ */
+typedef struct KDBGSYMCACHE
+{
+    /** The symbol cache magic. (KDBGSYMCACHE_MAGIC) */
+    KU32                    u32Magic;
+    /** The maximum number of symbols.*/
+    KU32                    cMax;
+    /** The current number of symbols.*/
+    KU32                    cCur;
+    /** The number of hash buckets. */
+    KU32                    cBuckets;
+    /** The address lookup tree. */
+    PKDBGADDRAVL            pAddrTree;
+    /** Array of hash buckets.
+     * The size is selected according to the cache size. */
+    PKDBGCACHEDSYM         *paBuckets[1];
+} KDBGSYMCACHE;
+typedef KDBGSYMCACHE *PKDBGSYMCACHE;
+
+
+/**
+ * A user symbol record.
+ *
+ * The user symbols are organized in the KDBGSPACE::pUserRoot tree
+ * and form an overlay that overrides the debug info retrieved from
+ * the KDBGSPACE::pSegRoot tree.
+ *
+ * In the current implementation the user symbols are unique and
+ * one would have to first delete a symbol in order to add another
+ * at the same address. This may be changed later, perhaps.
+ */
+typedef struct KDBGSPACEUSERSYM
+{
+
+} KDBGSPACEUSERSYM;
+typedef KDBGSPACEUSERSYM *PKDBGSPACEUSERSYM;
+
+
+
+/**
+ * Address space.
+ */
+typedef struct KDBGSPACE
+{
+    /** The addresspace magic. (KDBGSPACE_MAGIC) */
+    KU32            u32Magic;
+    /** User defined address space identifier or data pointer. */
+    KUPTR           uUser;
+    /** The name of the address space. (Optional) */
+    const char     *pszName;
+
+
+} KDBGSPACE;
+/** Pointer to an address space. */
+typedef struct KDBGSPACE *PKDBGSPACE;
+/** Pointer to an address space pointer. */
+typedef PKDBGSPACE *PPKDBGSPACE;
+
+
+KDBG_DECL(int) kDbgSpaceCreate(PPDBGSPACE ppSpace, KDBGADDR LowAddr, DBGADDR HighAddr,
+                               KUPTR uUser, const char *pszName)
+{
+    /*
+     * Validate input.
+     */
+    kDbgAssertPtrReturn(ppSpace);
+    *ppSpace = NULL;
+    kDbgAssertPtrNullReturn(pszName);
+    kDbgAssertReturn(LowAddr < HighAddr);
+
+    /*
+     * Create and initialize the address space.
+     */
+    PKDBGSPACE pSpace = (PKDBGSPACE)kHlpAlloc(sizeof(*pSpace));
+    if (!pSpace)
+        return KERR_NO_MEMORY;
+    pSpace->u32Magic = KDBGSPACE_MAGIC;
+    pSpace->uUser = uUser;
+    pSpace->pszName = pszName;
+
+}
diff --git a/src/lib/kStuff/kDbg/kDbgSymbol.cpp b/src/lib/kStuff/kDbg/kDbgSymbol.cpp
new file mode 100644
index 0000000..d542807
--- /dev/null
+++ b/src/lib/kStuff/kDbg/kDbgSymbol.cpp
@@ -0,0 +1,78 @@
+/* $Id: kDbgSymbol.cpp 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kDbg - The Debug Info Reader, Symbols.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "kDbgInternal.h"
+#include <k/kHlpAlloc.h>
+
+
+/**
+ * Duplicates a symbol.
+ *
+ * To save heap space, the returned symbol will not own more heap space than
+ * it strictly need to. So, it's not possible to append stuff to the symbol
+ * or anything of that kind.
+ *
+ * @returns Pointer to the duplicate.
+ *          This must be freed using kDbgSymbolFree().
+ * @param   pSymbol     The symbol to be duplicated.
+ */
+KDBG_DECL(PKDBGSYMBOL) kDbgSymbolDup(PCKDBGSYMBOL pSymbol)
+{
+    kDbgAssertPtrReturn(pSymbol, NULL);
+    KSIZE cb = K_OFFSETOF(KDBGSYMBOL, szName[pSymbol->cchName + 1]);
+    PKDBGSYMBOL pNewSymbol = (PKDBGSYMBOL)kHlpDup(pSymbol, cb);
+    if (pNewSymbol)
+        pNewSymbol->cbSelf = cb;
+    return pNewSymbol;
+}
+
+
+/**
+ * Frees a symbol obtained from the kDbg API.
+ *
+ * @returns 0 on success.
+ * @returns KERR_INVALID_POINTER if pSymbol isn't a valid pointer.
+ *
+ * @param   pSymbol     The symbol to be freed. The null pointer is ignored.
+ */
+KDBG_DECL(int) kDbgSymbolFree(PKDBGSYMBOL pSymbol)
+{
+    if (!pSymbol)
+    {
+        kDbgAssertPtrReturn(pSymbol, KERR_INVALID_POINTER);
+        pSymbol->cbSelf = 0;
+        kHlpFree(pSymbol);
+    }
+    return 0;
+}
+
diff --git a/src/lib/kStuff/kErr/Makefile.kmk b/src/lib/kStuff/kErr/Makefile.kmk
new file mode 100644
index 0000000..de11e20
--- /dev/null
+++ b/src/lib/kStuff/kErr/Makefile.kmk
@@ -0,0 +1,61 @@
+# $Id: Makefile.kmk 29 2009-07-01 20:30:29Z bird $
+## @file
+# kErr - The Status Code API, sub-makefile.
+#
+
+#
+# Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+DEPTH ?= ..
+SUB_DEPTH = ..
+include $(PATH_KBUILD)/subheader.kmk
+
+#
+# kHlpBaseStatic
+#
+LIBRARIES += kErrStatic
+kErrStatic_TEMPLATE = kStuffLIB
+kErrStatic_SOURCES = \
+	kErrName.c
+
+kErrName.c_DEPS = $(PATH_TARGET)/kErrNameConsts.h
+kErrName.c_INCS = $(PATH_TARGET)
+
+#
+# Generate case statements for kErrName().
+#
+$(PATH_TARGET)/kErrNameConsts.h: $(PATH_SUB_ROOT)/include/k/kErrors.h $(MAKEFILE_CURRENT) | $(call DIRDEP,$(PATH_TARGET))
+	$(RM) -f $@
+	$(SED) \
+		-e '/^#define  *\(K[A-Z_]*ERR_[^ ()]*\) .*$$/!d' \
+		-e 's/^#define  *\(K[A-Z_]*ERR_[^ ()]*\) .*$$/ERR_CONST(\1)/' \
+		-e '/K[A-Z_]*ERR_[A-Z0-9_]*BASE/d' \
+		-e '/K[A-Z_]*ERR_[A-Z0-9_]*END/d' \
+		$< > $@
+
+
+# Generate the rules
+include $(PATH_KBUILD)/subfooter.kmk
+
diff --git a/src/lib/kStuff/kErr/kErrName.c b/src/lib/kStuff/kErr/kErrName.c
new file mode 100644
index 0000000..a412e2a
--- /dev/null
+++ b/src/lib/kStuff/kErr/kErrName.c
@@ -0,0 +1,57 @@
+/* $Id: kErrName.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kErr - Status Code API, kErrName.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kErr.h>
+#include <k/kErrors.h>
+
+
+/**
+ * Translate the error code into a string containing
+ * the error constant.
+ *
+ * @returns Read only string with the constant name.
+ * @param   rc      The kErrors status code.
+ */
+KERR_DECL(const char *) kErrName(int rc)
+{
+    switch (rc)
+    {
+        case 0: return "SUCCESS";
+#define ERR_CONST(c) case c: return #c;
+#include "kErrNameConsts.h"
+#undef ERR_CONST
+        default:
+            return "KERR_UNKNOWN_ERROR";
+    }
+}
+
diff --git a/src/lib/kStuff/kHlp/Bare/Makefile.kup b/src/lib/kStuff/kHlp/Bare/Makefile.kup
new file mode 100644
index 0000000..e69de29
diff --git a/src/lib/kStuff/kHlp/Bare/kHlpBare-gcc.c b/src/lib/kStuff/kHlp/Bare/kHlpBare-gcc.c
new file mode 100644
index 0000000..889e48f
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Bare/kHlpBare-gcc.c
@@ -0,0 +1,223 @@
+/* $Id: kHlpBare-gcc.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpBare - The Dynamic Loader, Helper Functions for GCC.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <k/kLdr.h>
+#include "kHlp.h"
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+
+
+void *memchr(const void *pv, int ch, KSIZE cb)
+{
+    const char *pb = pv;
+    while (cb-- > 0)
+    {
+        if (*pb == ch)
+            return (void *)pb;
+        pb++;
+    }
+    return 0;
+}
+
+
+int memcmp(const void *pv1, const void *pv2, KSIZE cb)
+{
+    /*
+     * Pointer size pointer size.
+     */
+    if (    cb > 16
+        &&  !((KUPTR)pv1 & (sizeof(void *) - 1))
+        &&  !((KUPTR)pv2 & (sizeof(void *) - 1)) )
+    {
+        const KUPTR *pu1 = pv1;
+        const KUPTR *pu2 = pv2;
+        while (cb >= sizeof(KUPTR))
+        {
+            const KUPTR u1 = *pu1++;
+            const KUPTR u2 = *pu2++;
+            if (u1 != u2)
+                return u1 > u2 ? 1 : -1;
+            cb -= sizeof(KUPTR);
+        }
+        if (!cb)
+            return 0;
+        pv1 = (const void *)pu1;
+        pv2 = (const void *)pu2;
+    }
+
+    /*
+     * Byte by byte.
+     */
+    if (cb)
+    {
+        const unsigned char *pb1 = pv1;
+        const unsigned char *pb2 = pv2;
+        while (cb-- > 0)
+        {
+            const unsigned char b1 = *pb1++;
+            const unsigned char b2 = *pb2++;
+            if (b1 != b2)
+                return b1 > b2 ? 1 : -1;
+        }
+    }
+    return 0;
+}
+
+
+void *memcpy(void *pv1, const void *pv2, KSIZE cb)
+{
+    void *pv1Start = pv1;
+
+    /*
+     * Pointer size pointer size.
+     */
+    if (    cb > 16
+        &&  !((KUPTR)pv1 & (sizeof(void *) - 1))
+        &&  !((KUPTR)pv2 & (sizeof(void *) - 1)) )
+    {
+        KUPTR       *pu1 = pv1;
+        const KUPTR *pu2 = pv2;
+        while (cb >= sizeof(KUPTR))
+        {
+            cb -= sizeof(KUPTR);
+            *pu1++ = *pu2++;
+        }
+        if (!cb)
+            return 0;
+        pv1 = (void *)pu1;
+        pv2 = (const void *)pu2;
+    }
+
+    /*
+     * byte by byte
+     */
+    if (cb)
+    {
+        unsigned char       *pb1 = pv1;
+        const unsigned char *pb2 = pv2;
+        while (cb-- > 0)
+            *pb1++ = *pb2++;
+    }
+
+    return pv1Start;
+}
+
+void *memset(void *pv, int ch, KSIZE cb)
+{
+    void *pvStart = pv;
+
+    /*
+     * Pointer size pointer size.
+     */
+    if (    cb > 16
+        &&  !((KUPTR)pv & (sizeof(void *) - 1)))
+    {
+        KUPTR  *pu = pv;
+        KUPTR   u = ch | (ch << 8);
+        u |= u << 16;
+#if K_ARCH_BITS >= 64
+        u |= u << 32;
+#endif
+#if K_ARCH_BITS >= 128
+        u |= u << 64;
+#endif
+
+        while (cb >= sizeof(KUPTR))
+        {
+            cb -= sizeof(KUPTR);
+            *pu++ = u;
+        }
+    }
+
+    /*
+     * Byte by byte
+     */
+    if (cb)
+    {
+        unsigned char *pb = pv;
+        while (cb-- > 0)
+            *pb++ = ch;
+    }
+    return pvStart;
+}
+
+
+int strcmp(const char *psz1, const char *psz2)
+{
+    for (;;)
+    {
+        const char ch1 = *psz1++;
+        const char ch2 = *psz2++;
+        if (ch1 != ch2)
+            return (int)ch1 - (int)ch2;
+        if (!ch1)
+            return 0;
+    }
+}
+
+
+int strncmp(const char *psz1, const char *psz2, KSIZE cch)
+{
+    while (cch-- > 0)
+    {
+        const char ch1 = *psz1++;
+        const char ch2 = *psz2++;
+        if (ch1 != ch2)
+            return (int)ch1 - (int)ch2;
+        if (!ch1)
+            break;
+    }
+    return 0;
+}
+
+char *strchr(const char *psz, int ch)
+{
+    for (;;)
+    {
+        const char chCur = *psz;
+        if (chCur == ch)
+            return (char *)psz;
+        if (!chCur)
+            return 0;
+        psz++;
+    }
+}
+
+KSIZE strlen(const char *psz)
+{
+    const char *pszStart = psz;
+    while (*psz)
+        psz++;
+    return psz - pszStart;
+}
+
diff --git a/src/lib/kStuff/kHlp/Bare/kHlpBareAssert.c b/src/lib/kStuff/kHlp/Bare/kHlpBareAssert.c
new file mode 100644
index 0000000..138e73e
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Bare/kHlpBareAssert.c
@@ -0,0 +1,138 @@
+/* $Id: kHlpBareAssert.c 82 2016-08-22 21:01:51Z bird $ */
+/** @file
+ * kHlpBare - Assert Backend.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpAssert.h>
+#include <k/kHlpString.h>
+
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+# include <k/kHlpSys.h>
+
+#elif K_OS == K_OS_OS2
+# define INCL_BASE
+# define INCL_ERRORS
+# include <os2.h>
+
+#elif  K_OS == K_OS_WINDOWS
+# include <Windows.h>
+
+#else
+# error "port me"
+#endif
+
+
+/**
+ * Writes a assert string with unix lineendings.
+ *
+ * @param   pszMsg  The string.
+ */
+static void kHlpAssertWrite(const char *pszMsg)
+{
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+    KSIZE cchMsg = kHlpStrLen(pszMsg);
+    kHlpSys_write(2 /* stderr */, pszMsg, cchMsg);
+
+#elif K_OS == K_OS_OS2 ||  K_OS == K_OS_WINDOWS
+    /*
+     * Line by line.
+     */
+    ULONG       cbWritten;
+    const char *pszNl = kHlpStrChr(pszMsg, '\n');
+    while (pszNl)
+    {
+        cbWritten = pszNl - pszMsg;
+
+# if K_OS == K_OS_OS2
+        if (cbWritten)
+            DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
+        DosWrite((HFILE)2, "\r\n", 2, &cbWritten);
+# else /* K_OS == K_OS_WINDOWS */
+        if (cbWritten)
+            WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
+        WriteFile((HANDLE)STD_ERROR_HANDLE, "\r\n", 2, &cbWritten, NULL);
+# endif
+
+        /* next */
+        pszMsg = pszNl + 1;
+        pszNl = kHlpStrChr(pszMsg, '\n');
+    }
+
+    /*
+     * Remaining incomplete line.
+     */
+    if (*pszMsg)
+    {
+        cbWritten = kHlpStrLen(pszMsg);
+# if K_OS == K_OS_OS2
+        DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
+# else /* K_OS == K_OS_WINDOWS */
+        WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
+# endif
+    }
+
+#else
+# error "port me"
+#endif
+}
+
+
+KHLP_DECL(void) kHlpAssertMsg1(const char *pszExpr, const char *pszFile, unsigned iLine, const char *pszFunction)
+{
+    char szLine[16];
+
+    kHlpAssertWrite("\n!!!kLdr Assertion Failed!!!\nExpression: ");
+    kHlpAssertWrite(pszExpr);
+    kHlpAssertWrite("\nAt: ");
+    kHlpAssertWrite(pszFile);
+    kHlpAssertWrite("(");
+    kHlpAssertWrite(kHlpInt2Ascii(szLine, sizeof(szLine), iLine, 10));
+    kHlpAssertWrite(") ");
+    kHlpAssertWrite(pszFunction);
+    kHlpAssertWrite("\n");
+}
+
+
+KHLP_DECL(void) kHlpAssertMsg2(const char *pszFormat, ...)
+{
+    kHlpAssertWrite(pszFormat);
+}
+
diff --git a/src/lib/kStuff/kHlp/Bare/kHlpBareEnv.c b/src/lib/kStuff/kHlp/Bare/kHlpBareEnv.c
new file mode 100644
index 0000000..353c19e
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Bare/kHlpBareEnv.c
@@ -0,0 +1,102 @@
+/* $Id: kHlpBareEnv.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpBare - Environment Manipulation.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpEnv.h>
+#include <k/kHlpString.h>
+#include <k/kErrors.h>
+
+#if K_OS == K_OS_DARWIN
+
+#elif K_OS == K_OS_LINUX
+
+#elif K_OS == K_OS_OS2
+# define INCL_BASE
+# define INCL_ERRORS
+# include <os2.h>
+
+#elif  K_OS == K_OS_WINDOWS
+# include <Windows.h>
+
+#else
+# error "port me"
+#endif
+
+
+KHLP_DECL(int) kHlpGetEnv(const char *pszVar, char *pszVal, KSIZE cchVal)
+{
+#if K_OS == K_OS_DARWIN
+    /** @todo need to figure out where the stuff is or how it's inherited on darwin ... */
+    return KERR_ENVVAR_NOT_FOUND;
+
+#elif K_OS == K_OS_LINUX
+    /** @todo either read /proc/self/environ or figure out where in the memory the initial environment is... */
+    return KERR_ENVVAR_NOT_FOUND;
+
+#elif K_OS == K_OS_OS2
+    PSZ pszValue = NULL;
+    int rc;
+
+    *pszVal = '\0';
+    rc = DosScanEnv((PCSZ)pszVar, &pszValue);
+    if (!rc)
+    {
+        KSIZE  cch = kHlpStrLen((const char *)pszValue);
+        if (cchVal > cch)
+            kHlpMemCopy(pszVal, pszValue, cch + 1);
+        else
+            rc = KERR_BUFFER_OVERFLOW;
+    }
+    else
+        rc = KERR_ENVVAR_NOT_FOUND;
+    return rc;
+
+#elif K_OS == K_OS_WINDOWS
+    DWORD cch;
+
+    SetLastError(0);
+    cch = GetEnvironmentVariable(pszVar, pszVal, cchVal);
+    if (cch > 0 && cch < cchVal)
+        return 0;
+
+    *pszVal = '\0';
+    if (cch >= cchVal)
+        return KERR_BUFFER_OVERFLOW;
+    if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
+        return KERR_ENVVAR_NOT_FOUND;
+    return GetLastError();
+
+#else
+# error "Port me"
+#endif
+}
+
diff --git a/src/lib/kStuff/kHlp/Bare/kHlpBareHeap.c b/src/lib/kStuff/kHlp/Bare/kHlpBareHeap.c
new file mode 100644
index 0000000..d5e44b4
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Bare/kHlpBareHeap.c
@@ -0,0 +1,763 @@
+/* $Id: kHlpBareHeap.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpBare - Heap.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define KHLPHEAP_STRICT
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpAlloc.h>
+#include <k/kHlpString.h>
+#include <k/kHlpAssert.h>
+
+#if K_OS == K_OS_OS2
+# define INCL_BASE
+# define INCL_ERRORS
+# include <os2.h>
+
+#elif  K_OS == K_OS_WINDOWS
+# include <Windows.h>
+
+#else
+# include <k/kHlpAlloc.h>
+#endif
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * A heap block.
+ */
+typedef struct KHLPHEAPBLOCK
+{
+    /** Next block in the global list. */
+    struct KHLPHEAPBLOCK   *pNext;
+    /** Previous block in the global list. */
+    struct KHLPHEAPBLOCK   *pPrev;
+    /** The size of this block including this header. */
+    KSIZE                   cb;
+    /** The flags. */
+    KSIZE                   fFlags;
+} KHLPHEAPBLOCK, *PKHLPHEAPBLOCK;
+
+/** Indicates whether the block is free (set) or allocated (clear). */
+#define KHLPHEAPBLOCK_FLAG_FREE     ((KSIZE)1)
+/** Valid flag mask. */
+#define KHLPHEAPBLOCK_FLAG_MASK     ((KSIZE)1)
+
+/** Checks if the block is freed. */
+#define KHLPHEAPBLOCK_IS_FREE(pB)       ( (pB)->fFlags & KHLPHEAPBLOCK_FLAG_FREE )
+/** Check if the block is allocated. */
+#define KHLPHEAPBLOCK_IS_ALLOCATED(pB)  !KHLPHEAPBLOCK_IS_FREE(pB)
+/** Checks if the two blocks are adjacent.
+ * Assumes pB1 < pB2. */
+#define KHLPHEAPBLOCK_IS_ADJACENT(pB1, pB2) \
+    ( ((KUPTR)(pB1) + (pB1)->cb) == (KUPTR)(pB2) )
+
+/** The block alignment. */
+#define KHLPHEAPBLOCK_ALIGNMENT     sizeof(KHLPHEAPBLOCK)
+
+/** @def KHLPHEAP_ASSERT
+ * Heap assertion. */
+/** @def KHLPHEAP_ASSERT_BLOCK
+ * Assert that a heap block is valid. */
+/** @def KHLPHEAP_ASSERT_FREE
+ * Assert that a heap free block is valid. */
+#ifdef KHLPHEAP_STRICT
+# define KHLPHEAP_ASSERT(expr)      kHlpAssert(expr)
+
+# define KHLPHEAP_ASSERT_BLOCK(pHeap, pBlock) \
+    do { \
+        KHLPHEAP_ASSERT(!((pBlock)->fFlags & ~KHLPHEAPBLOCK_FLAG_MASK)); \
+        KHLPHEAP_ASSERT(!((pBlock)->cb & (KHLPHEAPBLOCK_ALIGNMENT - 1))); \
+        KHLPHEAP_ASSERT((KUPTR)(pBlock)->pPrev < (KUPTR)(pBlock)); \
+        KHLPHEAP_ASSERT((KUPTR)(pBlock)->pNext > (KUPTR)(pBlock) || !(pBlock)->pNext); \
+    } while (0)
+
+# define KHLPHEAP_ASSERT_FREE(pHeap, pFree) \
+    do { \
+        KHLPHEAP_ASSERT_BLOCK(pHeap, &(pFree)->Core); \
+        KHLPHEAP_ASSERT((KUPTR)(pFree)->pPrev < (KUPTR)(pFree)); \
+        KHLPHEAP_ASSERT((KUPTR)(pFree)->pNext > (KUPTR)(pFree) || !(pFree)->pNext); \
+    } while (0)
+
+#else
+# define KHLPHEAP_ASSERT(expr)          do { } while (0)
+# define KHLPHEAP_ASSERT_BLOCK(pH, pB)  do { } while (0)
+# define KHLPHEAP_ASSERT_FREE(pH, pF)   do { } while (0)
+#endif
+
+
+/**
+ * A free heap block.
+ */
+typedef struct KHLPHEAPFREE
+{
+    /** The core bit which we have in common with used blocks. */
+    KHLPHEAPBLOCK           Core;
+    /** The next free block. */
+    struct KHLPHEAPFREE    *pNext;
+    /** The previous free block. */
+    struct KHLPHEAPFREE    *pPrev;
+} KHLPHEAPFREE, *PKHLPHEAPFREE;
+
+
+/**
+ * A heap segment.
+ */
+typedef struct KHLPHEAPSEG
+{
+    /** The base address of the segment. */
+    void                   *pvBase;
+    /** The length of the segment (in bytes). */
+    KSIZE                   cb;
+} KHLPHEAPSEG, *PKHLPHEAPSEG;
+
+/**
+ * Bundle of heap segments.
+ */
+typedef struct KHLPHEAPSEGS
+{
+    /** Pointer to the next segment bundle. */
+    struct KHLPHEAPSEGS    *pNext;
+    /** The number of segments used. */
+    KU32                    cSegs;
+    /** Array of chunks. */
+    KHLPHEAPSEG             aSegs[64];
+} KHLPHEAPSEGS, *PKHLPHEAPSEGS;
+
+
+/**
+ * Heap anchor block.
+ */
+typedef struct KHLPHEAPANCHOR
+{
+    /** Head of the block list. */
+    PKHLPHEAPBLOCK          pHead;
+    /** Tail of the block list. */
+    PKHLPHEAPBLOCK          pTail;
+    /** Head of the free list. */
+    PKHLPHEAPFREE           pFreeHead;
+    /** Head segment bundle.
+     * The order of this list is important, but a bit peculiar.
+     * Logically, SegsHead::pNext is the tail pointer. */
+    KHLPHEAPSEGS            SegsHead;
+} KHLPHEAPANCHOR, *PKHLPHEAPANCHOR;
+
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** The heap anchor block. */
+static KHLPHEAPANCHOR       g_Heap;
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static int      khlpHeapInit(PKHLPHEAPANCHOR pHeap);
+static void     khlpHeapDelete(PKHLPHEAPANCHOR pHeap);
+static void *   khlpHeapAlloc(PKHLPHEAPANCHOR pHeap, KSIZE cb);
+static void     khlpHeapFree(PKHLPHEAPANCHOR pHeap, void *pv);
+static KSIZE    khlpHeapBlockSize(PKHLPHEAPANCHOR pHeap, void *pv);
+static void     khlpHeapDonate(PKHLPHEAPANCHOR pHeap, void *pv, KSIZE cb);
+static int      khlpHeapSegAlloc(PKHLPHEAPSEG pSeg, KSIZE cb);
+static void     khlpHeapSegFree(PKHLPHEAPSEG pSeg);
+
+
+/**
+ * Initializes the kLdr heap.
+ *
+ * @returns 0 on success, non-zero OS specific status code on failure.
+ */
+KHLP_DECL(int) kHlpHeapInit(void)
+{
+    return khlpHeapInit(&g_Heap);
+}
+
+
+/**
+ * Terminates the kLdr heap.
+ */
+KHLP_DECL(void) kHlpHeapTerm(void)
+{
+    khlpHeapDelete(&g_Heap);
+}
+
+
+KHLP_DECL(void *) kHlpAlloc(KSIZE cb)
+{
+    return khlpHeapAlloc(&g_Heap, cb);
+}
+
+
+KHLP_DECL(void *) kHlpAllocZ(KSIZE cb)
+{
+    void *pv = khlpHeapAlloc(&g_Heap, cb);
+    if (pv)
+        kHlpMemSet(pv, 0, cb);
+    return pv;
+}
+
+
+KHLP_DECL(void *) kHlpDup(const void *pv, KSIZE cb)
+{
+    void *pvNew = khlpHeapAlloc(&g_Heap, cb);
+    if (pvNew)
+        kHlpMemCopy(pvNew, pv, cb);
+    return pvNew;
+}
+
+
+KHLP_DECL(char *) kHlpStrDup(const char *psz)
+{
+    return (char *)kHlpDup(psz, kHlpStrLen(psz) + 1);
+}
+
+
+KHLP_DECL(void *) kHlpRealloc(void *pv, KSIZE cb)
+{
+    void *pvNew;
+    if (!cb)
+    {
+        kHlpFree(pv);
+        pvNew = NULL;
+    }
+    else if (!pv)
+        pvNew = khlpHeapAlloc(&g_Heap, cb);
+    else
+    {
+        KSIZE cbToCopy = khlpHeapBlockSize(&g_Heap, pv);
+        pvNew = khlpHeapAlloc(&g_Heap, cb);
+        if (pvNew)
+        {
+            kHlpMemCopy(pvNew, pv, cb);
+            kHlpFree(pv);
+        }
+    }
+    return pvNew;
+}
+
+
+KHLP_DECL(void) kHlpFree(void *pv)
+{
+    khlpHeapFree(&g_Heap, pv);
+}
+
+
+/**
+ * Donates memory to the heap.
+ *
+ * @param   pv      The address of the memory.
+ * @param   cb      The amount of memory.
+ */
+KHLP_DECL(void) kHlpHeapDonate(void *pv, KSIZE cb)
+{
+    khlpHeapDonate(&g_Heap, pv, cb);
+}
+
+
+
+/**
+ * Initializes the heap anchor.
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param   pHeap   The heap anchor to be initialized.
+ */
+static int khlpHeapInit(PKHLPHEAPANCHOR pHeap)
+{
+    pHeap->pHead = NULL;
+    pHeap->pTail = NULL;
+    pHeap->pFreeHead = NULL;
+    pHeap->SegsHead.pNext = NULL;
+    pHeap->SegsHead.cSegs = 0;
+    return 0;
+}
+
+
+/**
+ * Deletes a heap.
+ * This will free all resources (memory) associated with the heap.
+ *
+ * @param   pHeap   The heap to be deleted.
+ */
+static void khlpHeapDelete(PKHLPHEAPANCHOR pHeap)
+{
+    /*
+     * Free the segments, LIFO order.
+     * The head element is the last to be free, while the
+     * head.pNext is really the tail pointer - neat or what?
+     */
+    while (     pHeap->SegsHead.cSegs
+           ||   pHeap->SegsHead.pNext)
+    {
+        /* find the tail. */
+        KU32            iSeg;
+        PKHLPHEAPSEGS   pSegs = pHeap->SegsHead.pNext;
+        if (!pSegs)
+            pSegs = &pHeap->SegsHead;
+        else
+        {
+            pHeap->SegsHead.pNext = pSegs->pNext;
+            pSegs->pNext = NULL;
+        }
+
+        /* free the segments */
+        iSeg = pSegs->cSegs;
+        while (iSeg-- > 0)
+            khlpHeapSegFree(&pSegs->aSegs[iSeg]);
+        pSegs->cSegs = 0;
+    }
+
+    /* Zap the anchor. */
+    pHeap->pHead = NULL;
+    pHeap->pTail = NULL;
+    pHeap->pFreeHead = NULL;
+    pHeap->SegsHead.pNext = NULL;
+    pHeap->SegsHead.cSegs = 0;
+}
+
+
+/**
+ * Internal heap block allocator.
+ */
+static void *   kldrHeapAllocSub(PKHLPHEAPANCHOR pHeap, KSIZE cb)
+{
+    /*
+     * Find a fitting free block.
+     */
+    const KSIZE     cbReq = K_ALIGN_Z(cb + sizeof(KHLPHEAPBLOCK), KHLPHEAPBLOCK_ALIGNMENT);
+    PKHLPHEAPFREE   pCur = pHeap->pFreeHead;
+    while (pCur)
+    {
+        if (pCur->Core.cb >= cbReq)
+        {
+            if (pCur->Core.cb != cbReq)
+            {
+                /* check and see if there is a better match close by. */
+                PKHLPHEAPFREE pCur2 = pCur->pNext;
+                unsigned i = 16;
+                while (i-- > 0 && pCur2)
+                {
+                    if (pCur2->Core.cb >= cbReq)
+                    {
+                        if (pCur2->Core.cb == cbReq)
+                        {
+                            pCur = pCur2;
+                            break;
+                        }
+                        if (pCur2->Core.cb < pCur->Core.cb)
+                            pCur = pCur2;
+                    }
+
+                    /* next */
+                    KHLPHEAP_ASSERT_FREE(pHeap, pCur2);
+                    pCur2 = pCur2->pNext;
+                }
+            }
+            break;
+        }
+
+        /* next */
+        KHLPHEAP_ASSERT_FREE(pHeap, pCur);
+        pCur = pCur->pNext;
+    }
+    if (!pCur)
+        return NULL;
+    KHLPHEAP_ASSERT_FREE(pHeap, pCur);
+
+    /*
+     * Do we need to split out a block?
+     */
+    if (pCur->Core.cb - cbReq >= KHLPHEAPBLOCK_ALIGNMENT * 2)
+    {
+        PKHLPHEAPBLOCK pNew;
+
+        pCur->Core.cb -= cbReq;
+
+        pNew = (PKHLPHEAPBLOCK)((KUPTR)pCur + pCur->Core.cb);
+        pNew->fFlags = 0;
+        pNew->cb = cbReq;
+        pNew->pNext = pCur->Core.pNext;
+        if (pNew->pNext)
+            pNew->pNext->pPrev = pNew;
+        else
+            pHeap->pTail = pNew;
+        pNew->pPrev = &pCur->Core;
+        pCur->Core.pNext = pNew;
+
+        KHLPHEAP_ASSERT_FREE(pHeap, pCur);
+        KHLPHEAP_ASSERT_BLOCK(pHeap, pNew);
+        return pNew + 1;
+    }
+
+    /*
+     * No, just unlink it from the free list and return.
+     */
+    if (pCur->pNext)
+        pCur->pNext->pPrev = pCur->pPrev;
+    if (pCur->pPrev)
+        pCur->pPrev->pNext = pCur->pNext;
+    else
+        pHeap->pFreeHead = pCur->pNext;
+    pCur->Core.fFlags &= ~KHLPHEAPBLOCK_FLAG_FREE;
+
+    KHLPHEAP_ASSERT_BLOCK(pHeap, &pCur->Core);
+    return &pCur->Core + 1;
+}
+
+
+/**
+ * Allocate a heap block.
+ *
+ * @returns Pointer to the allocated heap block on success. On failure NULL is returned.
+ * @param   pHeap   The heap.
+ * @param   cb      The requested heap block size.
+ */
+static void *   khlpHeapAlloc(PKHLPHEAPANCHOR pHeap, KSIZE cb)
+{
+    void *pv;
+
+    /* adjust the requested block size. */
+    cb = K_ALIGN_Z(cb, KHLPHEAPBLOCK_ALIGNMENT);
+    if (!cb)
+        cb = KHLPHEAPBLOCK_ALIGNMENT;
+
+    /* try allocate the block. */
+    pv = kldrHeapAllocSub(pHeap, cb);
+    if (!pv)
+    {
+        /*
+         * Failed, add another segment and try again.
+         */
+        KHLPHEAPSEG Seg;
+        if (khlpHeapSegAlloc(&Seg, cb + sizeof(KHLPHEAPSEGS) + sizeof(KHLPHEAPBLOCK) * 16))
+            return NULL;
+
+        /* donate before insterting the segment, this makes sure we got heap to expand the segment list. */
+        khlpHeapDonate(pHeap, Seg.pvBase, Seg.cb);
+
+        /* insert the segment. */
+        if (pHeap->SegsHead.cSegs < sizeof(pHeap->SegsHead.aSegs) / sizeof(pHeap->SegsHead.aSegs[0]))
+            pHeap->SegsHead.aSegs[pHeap->SegsHead.cSegs++] = Seg;
+        else if (   pHeap->SegsHead.pNext
+                 && pHeap->SegsHead.pNext->cSegs < sizeof(pHeap->SegsHead.aSegs) / sizeof(pHeap->SegsHead.aSegs[0]))
+            pHeap->SegsHead.pNext->aSegs[pHeap->SegsHead.pNext->cSegs++] = Seg;
+        else
+        {
+            PKHLPHEAPSEGS pSegs = (PKHLPHEAPSEGS)kldrHeapAllocSub(pHeap, sizeof(*pSegs));
+            KHLPHEAP_ASSERT(pSegs);
+            pSegs->pNext = pHeap->SegsHead.pNext;
+            pHeap->SegsHead.pNext = pSegs;
+            pSegs->aSegs[0] = Seg;
+            pSegs->cSegs = 1;
+        }
+
+        /* retry (should succeed) */
+        pv = kldrHeapAllocSub(pHeap, cb);
+        KHLPHEAP_ASSERT(pv);
+    }
+
+    return pv;
+}
+
+
+/**
+ * Frees a heap block.
+ *
+ * @param   pHeap   The heap.
+ * @param   pv      The pointer returned by khlpHeapAlloc().
+ */
+static void     khlpHeapFree(PKHLPHEAPANCHOR pHeap, void *pv)
+{
+    PKHLPHEAPFREE pFree, pLeft, pRight;
+
+    /* ignore NULL pointers. */
+    if (!pv)
+        return;
+
+    pFree = (PKHLPHEAPFREE)((PKHLPHEAPBLOCK)pv - 1);
+    KHLPHEAP_ASSERT_BLOCK(pHeap, &pFree->Core);
+    KHLPHEAP_ASSERT(KHLPHEAPBLOCK_IS_ALLOCATED(&pFree->Core));
+
+    /*
+     * Merge or link with left node?
+     */
+    pLeft = (PKHLPHEAPFREE)pFree->Core.pPrev;
+    if (    pLeft
+        &&  KHLPHEAPBLOCK_IS_FREE(&pLeft->Core)
+        &&  KHLPHEAPBLOCK_IS_ADJACENT(&pLeft->Core, &pFree->Core)
+       )
+    {
+        /* merge left */
+        pLeft->Core.pNext = pFree->Core.pNext;
+        if (pFree->Core.pNext)
+            pFree->Core.pNext->pPrev = &pLeft->Core;
+        else
+            pHeap->pTail = &pLeft->Core;
+
+        pLeft->Core.cb += pFree->Core.cb;
+        pFree->Core.fFlags = ~0;
+        pFree = pLeft;
+    }
+    else
+    {
+        /* link left */
+        while (pLeft && !KHLPHEAPBLOCK_IS_FREE(&pLeft->Core))
+            pLeft = (PKHLPHEAPFREE)pLeft->Core.pPrev;
+        if (pLeft)
+        {
+            pFree->pPrev = pLeft;
+            pFree->pNext = pLeft->pNext;
+            if (pLeft->pNext)
+                pLeft->pNext->pPrev = pFree;
+            pLeft->pNext  = pFree;
+        }
+        else
+        {
+            pFree->pPrev = NULL;
+            pFree->pNext = pHeap->pFreeHead;
+            if (pHeap->pFreeHead)
+                pHeap->pFreeHead->pPrev = pFree;
+            pHeap->pFreeHead = pFree;
+        }
+        pFree->Core.fFlags |= KHLPHEAPBLOCK_FLAG_FREE;
+    }
+    KHLPHEAP_ASSERT_FREE(pHeap, pFree);
+
+    /*
+     * Merge right?
+     */
+    pRight = (PKHLPHEAPFREE)pFree->Core.pNext;
+    if (    pRight
+        &&  KHLPHEAPBLOCK_IS_FREE(&pRight->Core)
+        &&  KHLPHEAPBLOCK_IS_ADJACENT(&pFree->Core, pRight)
+       )
+    {
+        /* unlink pRight from the global list. */
+        pFree->Core.pNext = pRight->Core.pNext;
+        if (pRight->Core.pNext)
+            pRight->Core.pNext->pPrev = &pFree->Core;
+        else
+            pHeap->pTail = &pFree->Core;
+
+        /* unlink pRight from the free list. */
+        pFree->pNext = pRight->pNext;
+        if (pRight->pNext)
+            pRight->pNext->pPrev = pFree;
+
+        /* update size and invalidate pRight. */
+        pFree->Core.cb += pRight->Core.cb;
+        pRight->Core.fFlags = ~0;
+    }
+}
+
+
+/**
+ * Calcs the size of a heap block.
+ *
+ * @returns The block size (in bytes).
+ * @param   pHeap       The heap.
+ * @param   pv          Pointer to an in-use heap block.
+ */
+static KSIZE khlpHeapBlockSize(PKHLPHEAPANCHOR pHeap, void *pv)
+{
+    PKHLPHEAPBLOCK pBlock  = (PKHLPHEAPBLOCK)pv - 1;
+    KHLPHEAP_ASSERT_BLOCK(pHeap, pBlock);
+    KHLPHEAP_ASSERT(KHLPHEAPBLOCK_IS_ALLOCATED(pBlock));
+    return (KU8 *)pBlock->pNext - (KU8 *)pv;
+}
+
+
+/**
+ * Donates memory to the heap.
+ *
+ * The donated memory is returned to the donator when the heap is deleted.
+ *
+ * @param pHeap The heap
+ * @param pv    The pointer to the donated memory.
+ * @param cb    Size of the donated memory.
+ */
+static void     khlpHeapDonate(PKHLPHEAPANCHOR pHeap, void *pv, KSIZE cb)
+{
+    PKHLPHEAPBLOCK pBlock;
+
+    /*
+     * Don't bother with small donations.
+     */
+    if (cb < KHLPHEAPBLOCK_ALIGNMENT * 4)
+        return;
+
+    /*
+     * Align the donation on a heap block boundrary.
+     */
+    if ((KUPTR)pv & (KHLPHEAPBLOCK_ALIGNMENT - 1))
+    {
+        cb -= (KUPTR)pv & 31;
+        pv = K_ALIGN_P(pv, KHLPHEAPBLOCK_ALIGNMENT);
+    }
+    cb &= ~(KSIZE)(KHLPHEAPBLOCK_ALIGNMENT - 1);
+
+    /*
+     * Create an allocated block, link it and free it.
+     */
+    pBlock = (PKHLPHEAPBLOCK)pv;
+    pBlock->pNext = NULL;
+    pBlock->pPrev = NULL;
+    pBlock->cb = cb;
+    pBlock->fFlags = 0;
+
+    /* insert */
+    if ((KUPTR)pBlock < (KUPTR)pHeap->pHead)
+    {
+        /* head */
+        pBlock->pNext = pHeap->pHead;
+        pHeap->pHead->pPrev = pBlock;
+        pHeap->pHead = pBlock;
+    }
+    else if ((KUPTR)pBlock > (KUPTR)pHeap->pTail)
+    {
+        if (pHeap->pTail)
+        {
+            /* tail */
+            pBlock->pPrev = pHeap->pTail;
+            pHeap->pTail->pNext = pBlock;
+            pHeap->pTail = pBlock;
+        }
+        else
+        {
+            /* first */
+            pHeap->pHead = pBlock;
+            pHeap->pTail = pBlock;
+        }
+    }
+    else
+    {
+        /* in list (unlikely) */
+        PKHLPHEAPBLOCK pPrev = pHeap->pHead;
+        PKHLPHEAPBLOCK pCur = pPrev->pNext;
+        for (;;)
+        {
+            KHLPHEAP_ASSERT_BLOCK(pHeap, pCur);
+            if ((KUPTR)pCur > (KUPTR)pBlock)
+                break;
+            pPrev = pCur;
+            pCur = pCur->pNext;
+        }
+
+        pBlock->pNext = pCur;
+        pBlock->pPrev = pPrev;
+        pPrev->pNext = pBlock;
+        pCur->pPrev = pBlock;
+    }
+    KHLPHEAP_ASSERT_BLOCK(pHeap, pBlock);
+
+    /* free it */
+    khlpHeapFree(pHeap, pBlock + 1);
+}
+
+
+
+/**
+ * Allocates a new segment.
+ *
+ * @returns 0 on success, non-zero OS status code on failure.
+ * @param   pSeg    Where to put the info about the allocated segment.
+ * @param   cbMin   The minimum segment size.
+ */
+static int khlpHeapSegAlloc(PKHLPHEAPSEG pSeg, KSIZE cbMin)
+{
+#if K_OS == K_OS_OS2
+    APIRET rc;
+
+    pSeg->cb = (cbMin + 0xffff) & ~(KSIZE)0xffff;
+    pSeg->pvBase = NULL;
+    rc = DosAllocMem(&pSeg->pvBase, pSeg->cb, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_ANY);
+    if (rc == ERROR_INVALID_PARAMETER)
+        rc = DosAllocMem(&pSeg->pvBase, pSeg->cb, PAG_COMMIT | PAG_READ | PAG_WRITE);
+    if (rc)
+    {
+        pSeg->pvBase = NULL;
+        pSeg->cb = 0;
+        return rc;
+    }
+
+#elif  K_OS == K_OS_WINDOWS
+    pSeg->cb = (cbMin + 0xffff) & ~(KSIZE)0xffff;
+    pSeg->pvBase = VirtualAlloc(NULL, pSeg->cb, MEM_COMMIT, PAGE_READWRITE);
+    if (!pSeg->pvBase)
+    {
+        pSeg->cb = 0;
+        return GetLastError();
+    }
+
+#else
+    int rc;
+
+    pSeg->cb = (cbMin + 0xffff) & ~(KSIZE)0xffff;
+    pSeg->pvBase = NULL;
+    rc = kHlpPageAlloc(&pSeg->pvBase, pSeg->cb, KPROT_READWRITE, K_FALSE);
+    if (rc)
+    {
+        pSeg->pvBase = NULL;
+        pSeg->cb = 0;
+        return rc;
+    }
+
+#endif
+
+    return 0;
+}
+
+
+/**
+ * Frees a segment.
+ *
+ * @param   pSeg    The segment to be freed.
+ */
+static void khlpHeapSegFree(PKHLPHEAPSEG pSeg)
+{
+#if K_OS == K_OS_OS2
+    APIRET rc = DosFreeMem(pSeg->pvBase);
+    KHLPHEAP_ASSERT(!rc); (void)rc;
+
+#elif  K_OS == K_OS_WINDOWS
+    BOOL fRc = VirtualFree(pSeg->pvBase, 0 /*pSeg->cb*/, MEM_RELEASE);
+    KHLPHEAP_ASSERT(fRc); (void)fRc;
+
+#else
+    int rc = kHlpPageFree(pSeg->pvBase, pSeg->cb);
+    KHLPHEAP_ASSERT(!rc); (void)rc;
+
+#endif
+}
+
diff --git a/src/lib/kStuff/kHlp/Bare/kHlpBareProcess.c b/src/lib/kStuff/kHlp/Bare/kHlpBareProcess.c
new file mode 100644
index 0000000..f7db3ff
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Bare/kHlpBareProcess.c
@@ -0,0 +1,85 @@
+/* $Id: kHlpBareProcess.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpBare - Process Management
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpProcess.h>
+#include <k/kHlpAssert.h>
+
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+# include <k/kHlpSys.h>
+
+#elif K_OS == K_OS_OS2
+# define INCL_BASE
+# define INCL_ERRORS
+# include <os2.h>
+#elif  K_OS == K_OS_WINDOWS
+# include <Windows.h>
+#else
+# error "port me"
+#endif
+
+
+/**
+ * Terminate the process.
+ *
+ * @param   rc      The exit status.
+ */
+void    kHlpExit(int rc)
+{
+    for (;;)
+    {
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+        kHlpSys_exit(rc);
+
+#elif K_OS == K_OS_OS2
+        DosExit(EXIT_PROCESS, rc);
+
+#elif  K_OS == K_OS_WINDOWS
+        TerminateProcess(GetCurrentProcess(), rc);
+
+#else
+# error "Port me"
+#endif
+        kHlpAssert(!"Impossible");
+    }
+}
+
diff --git a/src/lib/kStuff/kHlp/Bare/kHlpBareThread.c b/src/lib/kStuff/kHlp/Bare/kHlpBareThread.c
new file mode 100644
index 0000000..b484676
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Bare/kHlpBareThread.c
@@ -0,0 +1,93 @@
+/* $Id: kHlpBareThread.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpBare - Thread Manipulation.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpThread.h>
+
+#if K_OS == K_OS_DARWIN
+# include <mach/mach_time.h>
+
+#elif K_OS == K_OS_LINUX
+# include <k/kHlpSys.h>
+
+#elif K_OS == K_OS_OS2
+# define INCL_BASE
+# define INCL_ERRORS
+# include <os2.h>
+#elif  K_OS == K_OS_WINDOWS
+# include <Windows.h>
+#else
+# error "port me"
+#endif
+
+
+/**
+ * Sleep for a number of milliseconds.
+ * @param   cMillies    Number of milliseconds to sleep.
+ */
+void kHlpSleep(unsigned cMillies)
+{
+#if K_OS == K_OS_DARWIN
+    static struct mach_timebase_info   s_Info;
+    static KBOOL                s_fNanoseconds = K_UNKNOWN;
+    KU64 uNow = mach_absolute_time();
+    KU64 uDeadline;
+    KU64 uPeriod;
+
+    if (s_fNanoseconds == K_UNKNOWN)
+    {
+        if (mach_timebase_info(&s_Info))
+            s_fNanoseconds = K_TRUE; /* the easy way out */
+        else if (s_Info.denom == s_Info.numer)
+            s_fNanoseconds = K_TRUE;
+        else
+            s_fNanoseconds = K_FALSE;
+    }
+
+    uPeriod = (KU64)cMillies * 1000 * 1000;
+    if (!s_fNanoseconds)
+        uPeriod = (double)uPeriod * s_Info.denom / s_Info.numer; /* Use double to avoid 32-bit trouble. */
+    uDeadline = uNow + uPeriod;
+    mach_wait_until(uDeadline);
+
+#elif K_OS == K_OS_LINUX
+    /** @todo find the right syscall... */
+
+#elif K_OS == K_OS_OS2
+    DosSleep(cMillies);
+#elif  K_OS == K_OS_WINDOWS
+    Sleep(cMillies);
+#else
+    usleep(cMillies * 1000);
+#endif
+}
+
diff --git a/src/lib/kStuff/kHlp/Bare/kHlpSys-darwin.c b/src/lib/kStuff/kHlp/Bare/kHlpSys-darwin.c
new file mode 100644
index 0000000..b4153f2
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Bare/kHlpSys-darwin.c
@@ -0,0 +1,345 @@
+/* $Id: kHlpSys-darwin.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpBare -
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <k/kHlpSys.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dlfcn.h>
+#include <sys/mman.h>
+#include <mach/mach_time.h>
+
+
+#define USE_DARWIN_SYSCALLS
+
+#if K_ARCH == K_ARCH_X86_32
+# define DARWIN_SYSCALL(name, code) \
+    asm("\
+    .text                                   \n\
+    .globl _" #name "                       \n\
+    _" #name ":                             \n\
+        mov     $ " #code ", %eax           \n\
+        call    1f                          \n\
+    1:                                      \n\
+        pop     %edx                        \n\
+        mov     %esp, %ecx                  \n\
+        sysenter                            \n\
+        jnae    2f                          \n\
+        ret                                 \n\
+    2:                                      \n\
+        neg     %eax                        \n\
+        ret                                 \n\
+    ")
+
+# define DARWIN_SYSCALL_RET64(name, code) \
+    asm("\
+    .text                                   \n\
+    .globl _" #name "                       \n\
+    _" #name ":                             \n\
+        mov     $ " #code ", %eax           \n\
+        int     $0x80                       \n\
+        jnae    2f                          \n\
+        ret                                 \n\
+    2:                                      \n\
+        neg     %eax                        \n\
+        mov     $0xffffffff, %edx           \n\
+        ret                                 \n\
+    ")
+
+# define DARWIN_SYSCALL_NOERR(name, code) \
+    asm("\
+    .text                                   \n\
+    .globl _" #name "                       \n\
+    _" #name ":                             \n\
+        mov     $ " #code ", %eax           \n\
+        call    1f                          \n\
+    1:                                      \n\
+        pop     %edx                        \n\
+        mov     %esp, %ecx                  \n\
+        sysenter                            \n\
+        ret                                 \n\
+    ")
+
+#elif K_ARCH == K_ARCH_AMD64
+# define DARWIN_SYSCALL(name, code) \
+    asm("\
+    .text                                   \n\
+    .globl _" #name "                       \n\
+    _" #name ":                             \n\
+        mov     $ " #code ", %eax           \n\
+        mov     %rcx, %r10                  \n\
+        sysenter                            \n\
+        jnae    2f                          \n\
+        ret                                 \n\
+    2:                                      \n\
+        neg     %eax                        \n\
+        movsx   %eax, %rax                  \n\
+        ret                                 \n\
+    ")
+
+# define DARWIN_SYSCALL_RET64(name, code) DARWIN_SYSCALL_RET(name, code)
+
+# define DARWIN_SYSCALL_NOERR(name, code) \
+    asm("\
+    .text                                   \n\
+    .globl _" #name "                       \n\
+    _" #name ":                             \n\
+        mov     $ " #code ", %eax           \n\
+        mov     %rcx, %r10                  \n\
+        sysenter                            \n\
+        ret                                 \n\
+    ")
+
+
+#else
+# error later...
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_readlink, 0x000c003a);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_readlink, 0x0200003a);
+#else
+KSSIZE      kHlpSys_readlink(const char *pszPath, char *pszBuf, KSIZE cbBuf)
+{
+    KSSIZE cbRet = readlink(pszPath, pszBuf, cbBuf);
+    return cbRet >= 0 ? cbRet : -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_open, 0x000c0005);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_open, 0x02000005);
+#else
+int         kHlpSys_open(const char *filename, int flags, int mode)
+{
+    int fd = open(filename, flags, mode);
+    return fd >= 0 ? fd : -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_close, 0x000c0006);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_close, 0x02000006);
+#else
+int         kHlpSys_close(int fd)
+{
+   if (!close(fd))
+       return 0;
+   return -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL_RET64(kHlpSys_lseek, 0x000000c7);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL_RET64(kHlpSys_lseek, 0x020000c7);
+#else
+KFOFF       kHlpSys_lseek(int fd, int whench, KFOFF off)
+{
+    KFOFF offRet = lseek(fd, whench, off);
+    return offRet >= 0 ? offRet : -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_read, 0x000c0003);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_read, 0x02000003);
+#else
+KSSIZE      kHlpSys_read(int fd, void *pvBuf, KSIZE cbBuf)
+{
+    KSSIZE cbRead = read(fd, pvBuf, cbBuf);
+    return cbRead >= 0 ? cbRead : -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_write, 0x000c0004);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_write, 0x02000004);
+#else
+KSSIZE      kHlpSys_write(int fd, const void *pvBuf, KSIZE cbBuf)
+{
+    KSSIZE cbWritten = write(fd, pvBuf, cbBuf);
+    return cbWritten >= 0 ? cbWritten : -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_mmap, 0x020000c5);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_mmap, 0x020000c5);
+#else
+void       *kHlpSys_mmap(void *addr, KSIZE len, int prot, int flags, int fd, KI64 off)
+{
+    void *pv = mmap(addr, len, prot, flags, fd, off);
+    return pv != (void *)-1
+        ? pv
+        : errno < 256 ? (void *)(long)errno : (void *)(long)ENOMEM;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_mprotect, 0x000c004a);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_mprotect, 0x0200004a);
+#else
+int         kHlpSys_mprotect(void *addr, KSIZE len, int prot)
+{
+    if (!mprotect(addr, len, prot))
+        return 0;
+    return -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_munmap, 0x00080049);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_munmap, 0x02000049);
+#else
+int         kHlpSys_munmap(void *addr, KSIZE len)
+{
+    if (!munmap(addr, len))
+        return 0;
+    return -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_exit, 0x00040001);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_exit, 0x02000001);
+#else
+void        kHlpSys_exit(int rc)
+{
+    _Exit(rc);
+}
+#endif
+
+
+/*
+ * Some other stuff we'll be needing - Move to an appropriate place?
+ */
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL_NOERR(mach_task_self, 0xffffffe4);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL_NOERR(mach_task_self, 0xffffffe4);
+#endif
+
+//#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+//DARWIN_SYSCALL(semaphore_create, 0x00040001);
+//#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+//DARWIN_SYSCALL(semaphore_create, 0x02000001);
+//#endif
+#ifdef USE_DARWIN_SYSCALLS
+kern_return_t semaphore_create(task_t t, semaphore_t *ps, int p, int v)
+{
+    return 0;
+}
+#endif
+
+//#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+//DARWIN_SYSCALL(semaphore_destroy, 0x00040001);
+//#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+//DARWIN_SYSCALL(semaphore_destroy, 0x02000001);
+//#endif
+#ifdef USE_DARWIN_SYSCALLS
+kern_return_t semaphore_destroy(task_t t, semaphore_t s)
+{
+    return 0;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(semaphore_wait, 0xffffffdc);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(semaphore_wait, 0xffffffdc);
+#endif
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(semaphore_signal, 0xffffffdf);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(semaphore_signal, 0xffffffdf);
+#endif
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(mach_wait_until, 0xffffffa6);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(mach_wait_until, 0xffffffa6);
+#endif
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(mach_timebase_info, 0xffffffa7);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(mach_timebase_info, 0xffffffa7);
+#endif
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+asm("\n\
+.text                           \n\
+.globl _mach_absolute_time      \n\
+_mach_absolute_time:            \n\
+    mov     $0xffff1700, %edx   \n\
+    jmp     *%edx\n"); /* common page stuff. */
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+#endif
+
+
+void *dlopen(const char *pszModule, int fFlags)
+{
+    return NULL;
+}
+
+
+int dlclose(void *pvMod)
+{
+
+}
+
+
+void *dlsym(void *pvMod, const char *pszSymbol)
+{
+    return NULL;
+}
+
diff --git a/src/lib/kStuff/kHlp/CRT/kHlpCRTAlloc.cpp b/src/lib/kStuff/kHlp/CRT/kHlpCRTAlloc.cpp
new file mode 100644
index 0000000..fa5f2af
--- /dev/null
+++ b/src/lib/kStuff/kHlp/CRT/kHlpCRTAlloc.cpp
@@ -0,0 +1,78 @@
+/* $Id: kHlpCRTAlloc.cpp 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpAlloc - Memory Allocation, CRT based implementation.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpAlloc.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+KHLP_DECL(void *) kHlpAlloc(KSIZE cb)
+{
+    return malloc(cb);
+}
+
+
+KHLP_DECL(void *) kHlpAllocZ(KSIZE cb)
+{
+    return calloc(1, cb);
+}
+
+
+KHLP_DECL(void *) kHlpDup(const void *pv, KSIZE cb)
+{
+    void *pvDup = kHlpAlloc(cb);
+    if (pvDup)
+        return memcpy(pvDup, pv, cb);
+    return NULL;
+}
+
+
+KHLP_DECL(char *) kHlpStrDup(const char *psz)
+{
+    size_t cb = strlen(psz) + 1;
+    return (char *)kHlpDup(psz, cb);
+}
+
+
+KHLP_DECL(void *) kHlpRealloc(void *pv, KSIZE cb)
+{
+    return realloc(pv, cb);
+}
+
+
+KHLP_DECL(void) kHlpFree(void *pv)
+{
+    if (pv)
+        free(pv);
+}
+
diff --git a/src/lib/kStuff/kHlp/CRT/kHlpCRTEnv.cpp b/src/lib/kStuff/kHlp/CRT/kHlpCRTEnv.cpp
new file mode 100644
index 0000000..108c9f1
--- /dev/null
+++ b/src/lib/kStuff/kHlp/CRT/kHlpCRTEnv.cpp
@@ -0,0 +1,56 @@
+/* $Id: kHlpCRTEnv.cpp 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpEnv - Environment Manipulation.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpEnv.h>
+#include <k/kHlpString.h>
+#include <k/kErrors.h>
+#include <stdlib.h>
+
+
+KHLP_DECL(int) kHlpGetEnv(const char *pszVar, char *pszVal, KSIZE cchVal)
+{
+    int rc = 0;
+    const char *pszValue = getenv(pszVar);
+    if (pszValue)
+    {
+        KSIZE  cch = kHlpStrLen((const char *)pszValue);
+        if (cchVal > cch)
+            kHlpMemCopy(pszVal, pszValue, cch + 1);
+        else
+            rc = KERR_BUFFER_OVERFLOW;
+    }
+    else
+        rc = KERR_ENVVAR_NOT_FOUND;
+    return rc;
+}
+
diff --git a/src/lib/kStuff/kHlp/CRT/kHlpCRTString.cpp b/src/lib/kStuff/kHlp/CRT/kHlpCRTString.cpp
new file mode 100644
index 0000000..401b378
--- /dev/null
+++ b/src/lib/kStuff/kHlp/CRT/kHlpCRTString.cpp
@@ -0,0 +1,164 @@
+/* $Id: kHlpCRTString.cpp 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - String And Memory Routines, CRT based implementation.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+#include <string.h>
+
+
+#ifndef kHlpMemChr
+void   *kHlpMemChr(const void *pv, int ch, KSIZE cb)
+{
+    return (void *)memchr(pv, ch, cb);
+}
+#endif
+
+
+#ifndef kHlpMemComp
+int     kHlpMemComp(const void *pv1, const void *pv2, KSIZE cb)
+{
+    return memcmp(pv1, pv2, cb);
+}
+#endif
+
+
+#ifndef kHlpMemCopy
+void   *kHlpMemCopy(void *pv1, const void *pv2, KSIZE cb)
+{
+    return memcpy(pv1, pv2, cb);
+}
+#endif
+
+
+#ifndef kHlpMemPCopy
+void   *kHlpMemPCopy(void *pv1, const void *pv2, KSIZE cb)
+{
+    return (KU8 *)memcpy(pv1, pv2, cb) + cb;
+}
+#endif
+
+
+#ifndef kHlpMemMove
+void   *kHlpMemMove(void *pv1, const void *pv2, KSIZE cb)
+{
+    return memmove(pv1, pv2, cb);
+}
+#endif
+
+
+#ifndef kHlpMemPMove
+void   *kHlpMemPMove(void *pv1, const void *pv2, KSIZE cb)
+{
+    return (KU8 *)memmove(pv1, pv2, cb) + cb;
+}
+#endif
+
+
+#ifndef kHlpMemSet
+void   *kHlpMemSet(void *pv1, int ch, KSIZE cb)
+{
+    return memset(pv1, ch, cb);
+}
+#endif
+
+
+#ifndef kHlpMemPSet
+void   *kHlpMemPSet(void *pv1, int ch, KSIZE cb)
+{
+    return (KU8 *)memset(pv1, ch, cb) + cb;
+}
+#endif
+
+
+#ifndef kHlpStrCat
+char   *kHlpStrCat(char *psz1, const char *psz2)
+{
+    return strcat(psz1, psz2);
+}
+#endif
+
+
+#ifndef kHlpStrNCat
+char   *kHlpStrNCat(char *psz1, const char *psz2, KSIZE cb)
+{
+    return strncat(psz1, psz2, cb);
+}
+#endif
+
+
+#ifndef kHlpStrChr
+char   *kHlpStrChr(const char *psz, int ch)
+{
+    return (char *)strchr(psz, ch);
+}
+#endif
+
+
+#ifndef kHlpStrRChr
+char   *kHlpStrRChr(const char *psz, int ch)
+{
+    return (char *)strrchr(psz, ch);
+}
+#endif
+
+
+#ifndef kHlpStrComp
+int     kHlpStrComp(const char *psz1, const char *psz2)
+{
+    return strcmp(psz1, psz2);
+}
+#endif
+
+
+#ifndef kHlpStrNComp
+int     kHlpStrNComp(const char *psz1, const char *psz2, KSIZE cch)
+{
+    return strncmp(psz1, psz2, cch);
+}
+#endif
+
+
+#ifndef kHlpStrCopy
+char   *kHlpStrCopy(char *psz1, const char *psz2)
+{
+    return strcpy(psz1, psz2);
+}
+#endif
+
+
+#ifndef kHlpStrLen
+KSIZE   kHlpStrLen(const char *psz1)
+{
+    return strlen(psz1);
+}
+#endif
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpGetEnvUZ.c b/src/lib/kStuff/kHlp/Generic/kHlpGetEnvUZ.c
new file mode 100644
index 0000000..4721af7
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpGetEnvUZ.c
@@ -0,0 +1,108 @@
+/* $Id: kHlpGetEnvUZ.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpEnv - kHlpGetEnvUZ.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpEnv.h>
+#include <k/kHlpString.h>
+
+
+/**
+ * Gets an environment variable and converts it to a KSIZE.
+ *
+ * @returns 0 and *pcb on success.
+ * @returns On failure see kHlpGetEnv.
+ * @param   pszVar  The name of the variable.
+ * @param   pcb     Where to put the value.
+ */
+KHLP_DECL(int) kHlpGetEnvUZ(const char *pszVar, KSIZE *pcb)
+{
+    KSIZE       cb;
+    unsigned    uBase;
+    char        szVal[64];
+    KSIZE       cchVal = sizeof(szVal);
+    const char *psz;
+    int         rc;
+
+    *pcb = 0;
+    rc = kHlpGetEnv(pszVar, szVal, cchVal);
+    if (rc)
+        return rc;
+
+    /* figure out the base. */
+    uBase = 10;
+    psz = szVal;
+    if (    *psz == '0'
+        &&  (psz[1] == 'x' || psz[1] == 'X'))
+    {
+        uBase = 16;
+        psz += 2;
+    }
+
+    /* convert it up to the first unknown char. */
+    cb = 0;
+    for(;;)
+    {
+        const char ch = *psz;
+        unsigned uDigit;
+        if (!ch)
+            break;
+        else if (ch >= '0' && ch <= '9')
+            uDigit = ch - '0';
+        else if (ch >= 'a' && ch <= 'z')
+            uDigit = ch - 'a' + 10;
+        else if (ch >= 'A' && ch <= 'Z')
+            uDigit = ch - 'A' + 10;
+        else
+            break;
+        if (uDigit >= uBase)
+            break;
+
+        /* add the digit */
+        cb *= uBase;
+        cb += uDigit;
+
+        psz++;
+    }
+
+    /* check for unit */
+    if (*psz == 'm' || *psz == 'M')
+        cb *= 1024*1024;
+    else if (*psz == 'k' ||*psz == 'K')
+        cb *= 1024;
+    else if (*psz == 'g' || *psz == 'G')
+        cb *= 1024*1024*1024;
+
+    *pcb = cb;
+    return 0;
+}
+
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpGetExt.c b/src/lib/kStuff/kHlp/Generic/kHlpGetExt.c
new file mode 100644
index 0000000..7e338fa
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpGetExt.c
@@ -0,0 +1,78 @@
+/* $Id: kHlpGetExt.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpPath - kHlpGetExt and kHlpGetSuff.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpPath.h>
+#include <k/kHlpString.h>
+
+
+/**
+ * Gets the filename suffix.
+ *
+ * @returns Pointer to where the suffix starts within the string pointed to by pszFilename.
+ * @returns Pointer to the terminator char if no suffix.
+ * @param   pszFilename     The filename to parse.
+ */
+KHLP_DECL(char *) kHlpGetSuff(const char *pszFilename)
+{
+    const char *pszDot = NULL;
+    pszFilename = kHlpGetFilename(pszFilename);
+    for (;;)
+    {
+        char ch = *pszFilename;
+        if (ch == '.')
+        {
+            while ((ch = *++pszFilename) == '.')
+                /* nothing */;
+            if (ch)
+                pszDot = pszFilename - 1;
+        }
+        if (!ch)
+            return (char *)(pszDot ? pszDot : pszFilename);
+        pszFilename++;
+    }
+}
+
+
+/**
+ * Gets the filename extention.
+ *
+ * @returns Pointer to where the extension starts within the string pointed to by pszFilename.
+ * @returns Pointer to the terminator char if no extension.
+ * @param   pszFilename     The filename to parse.
+ */
+KHLP_DECL(char *) kHlpGetExt(const char *pszFilename)
+{
+    char *psz = kHlpGetSuff(pszFilename);
+    return *psz ? psz + 1 : psz;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpGetFilename.c b/src/lib/kStuff/kHlp/Generic/kHlpGetFilename.c
new file mode 100644
index 0000000..c04293e
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpGetFilename.c
@@ -0,0 +1,72 @@
+/* $Id: kHlpGetFilename.c 85 2016-09-06 03:21:04Z bird $ */
+/** @file
+ * kHlpPath - kHlpGetFilename.
+ */
+
+/*
+ * Copyright (c) 2006-2016 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpPath.h>
+#include <k/kHlpString.h>
+
+
+/**
+ * Get the pointer to the filename part of the name.
+ *
+ * @returns Pointer to where the filename starts within the string pointed to by pszFilename.
+ * @returns Pointer to the terminator char if no filename.
+ * @param   pszFilename     The filename to parse.
+ */
+KHLP_DECL(char *) kHlpGetFilename(const char *pszFilename)
+{
+    const char *pszLast = pszFilename;
+    for (;;)
+    {
+        char ch = *pszFilename;
+#if K_OS == K_OS_OS2 || K_OS == K_OS_WINDOWS
+        if (ch == '/' || ch == '\\' || ch == ':')
+        {
+            while ((ch = *++pszFilename) == '/' || ch == '\\' || ch == ':')
+                /* nothing */;
+            pszLast = pszFilename;
+        }
+#else
+        if (ch == '/')
+        {
+            while ((ch = *++pszFilename) == '/')
+                /* betsuni */;
+            pszLast = pszFilename;
+        }
+#endif
+        if (ch)
+            pszFilename++;
+        else
+            return (char *)pszLast;
+    }
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpInt2Ascii.c b/src/lib/kStuff/kHlp/Generic/kHlpInt2Ascii.c
new file mode 100644
index 0000000..411342b
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpInt2Ascii.c
@@ -0,0 +1,83 @@
+/* $Id: kHlpInt2Ascii.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpInt2Ascii.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+/**
+ * Converts an signed integer to an ascii string.
+ *
+ * @returns psz.
+ * @param   psz         Pointer to the output buffer.
+ * @param   cch         The size of the output buffer.
+ * @param   lVal        The value.
+ * @param   iBase       The base to format it. (2,8,10 or 16)
+ */
+KHLP_DECL(char *) kHlpInt2Ascii(char *psz, KSIZE cch, long lVal, unsigned iBase)
+{
+    static const char s_szDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+    char *pszRet = psz;
+
+    if (cch >= (lVal < 0 ? 3U : 2U) && psz)
+    {
+        /* prefix */
+        if (lVal < 0)
+        {
+            *psz++ = '-';
+            cch--;
+            lVal = -lVal;
+        }
+
+        /* the digits */
+        do
+        {
+            *psz++ = s_szDigits[lVal % iBase];
+            cch--;
+            lVal /= iBase;
+        } while (lVal && cch > 1);
+
+        /* overflow indicator */
+        if (lVal)
+            psz[-1] = '+';
+    }
+    else if (!pszRet)
+        return pszRet;
+    else if (cch < 1 || !pszRet)
+        return pszRet;
+    else
+        *psz++ = '+';
+    *psz = '\0';
+
+    return pszRet;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpIsFilenameOnly.c b/src/lib/kStuff/kHlp/Generic/kHlpIsFilenameOnly.c
new file mode 100644
index 0000000..1cefa61
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpIsFilenameOnly.c
@@ -0,0 +1,61 @@
+/* $Id: kHlpIsFilenameOnly.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpPath - kHlpIsFilenameOnly.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpPath.h>
+#include <k/kHlpString.h>
+
+
+/**
+ * Checks if this is only a filename or if it contains any kind
+ * of drive, directory, or server specs.
+ *
+ * @returns 1 if this is a filename only.
+ * @returns 0 of it's isn't only a filename.
+ * @param   pszFilename     The filename to parse.
+ */
+KHLP_DECL(int) kHlpIsFilenameOnly(const char *pszFilename)
+{
+    for (;;)
+    {
+        const char ch = *pszFilename++;
+#if K_OS == K_OS_OS2 || K_OS == K_OS_WINDOWS
+        if (ch == '/' || ch == '\\' || ch == ':')
+#else
+        if (ch == '/')
+#endif
+            return 0;
+        if (!ch)
+            return 1;
+    }
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpMemChr.c b/src/lib/kStuff/kHlp/Generic/kHlpMemChr.c
new file mode 100644
index 0000000..060916d
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpMemChr.c
@@ -0,0 +1,51 @@
+/* $Id: kHlpMemChr.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpMemChr.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(void *) kHlpMemChr(const void *pv1, int ch, KSIZE cb)
+{
+    const KU8 b = ch;
+    const KU8 *pb = (const KU8 *)pv1;
+
+    while (cb-- > 0)
+    {
+        if (*pb == b)
+            return (void *)pb;
+        pb++;
+    }
+
+    return NULL;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpMemComp.c b/src/lib/kStuff/kHlp/Generic/kHlpMemComp.c
new file mode 100644
index 0000000..54d1999
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpMemComp.c
@@ -0,0 +1,71 @@
+/* $Id: kHlpMemComp.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpMemComp.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(int) kHlpMemComp(const void *pv1, const void *pv2, KSIZE cb)
+{
+    union
+    {
+        const void *pv;
+        const KU8 *pb;
+        const KUPTR *pu;
+    } u1, u2;
+
+    u1.pv = pv1;
+    u2.pv = pv2;
+
+    if (cb >= 32)
+    {
+        while (cb > sizeof(KUPTR))
+        {
+            cb -= sizeof(KUPTR);
+            if (*u1.pu != *u2.pu)
+                return *u1.pu > *u2.pu ? 1 : -1;
+            u1.pu++;
+            u2.pu++;
+        }
+    }
+
+    while (cb-- > 0)
+    {
+        if (u1.pb != u2.pb)
+            return u1.pb > u2.pb ? 1 : -1;
+        u1.pb++;
+        u2.pb++;
+    }
+
+    return 0;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpMemCopy.c b/src/lib/kStuff/kHlp/Generic/kHlpMemCopy.c
new file mode 100644
index 0000000..8674674
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpMemCopy.c
@@ -0,0 +1,69 @@
+/* $Id: kHlpMemCopy.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpMemCopy.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(void *) kHlpMemCopy(void *pv1, const void *pv2, KSIZE cb)
+{
+    union
+    {
+        void *pv;
+        KU8 *pb;
+        KUPTR *pu;
+    } u1;
+    union
+    {
+        const void *pv;
+        const KU8 *pb;
+        const KUPTR *pu;
+    } u2;
+
+    u1.pv = pv1;
+    u2.pv = pv2;
+
+    if (cb >= 32)
+    {
+        while (cb > sizeof(KUPTR))
+        {
+            cb -= sizeof(KUPTR);
+            *u1.pu++ = *u2.pu++;
+        }
+    }
+
+    while (cb-- > 0)
+        *u1.pb++ = *u2.pb++;
+
+    return pv1;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpMemICompAscii.c b/src/lib/kStuff/kHlp/Generic/kHlpMemICompAscii.c
new file mode 100644
index 0000000..6df5767
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpMemICompAscii.c
@@ -0,0 +1,80 @@
+/* $Id: kHlpMemICompAscii.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpMemICompAscii.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(int) kHlpMemICompAscii(const void *pv1, const void *pv2, KSIZE cb)
+{
+    union
+    {
+        const void *pv;
+        const KU8 *pb;
+        const KUPTR *pu;
+    } u1, u2;
+
+    u1.pv = pv1;
+    u2.pv = pv2;
+
+    if (cb >= 32)
+    {
+        while (cb > sizeof(KUPTR))
+        {
+            if (*u1.pu != *u2.pu)
+                break; /* hand it on to the byte-by-byte routine. */
+            u1.pu++;
+            u2.pu++;
+            cb -= sizeof(KUPTR);
+        }
+    }
+
+    while (cb-- > 0)
+    {
+        if (u1.pb != u2.pb)
+        {
+            KU8 ch1 = *u1.pb;
+            KU8 ch2 = *u2.pb;
+            if (ch1 <= 'Z' && ch1 >= 'A')
+                ch1 += 'a' - 'A';
+            if (ch2 <= 'Z' && ch2 >= 'A')
+                ch2 += 'a' - 'A';
+            if (ch1 != ch2)
+                return ch1 > ch2 ? 1 : -1;
+        }
+        u1.pb++;
+        u2.pb++;
+    }
+
+    return 0;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpMemMove.c b/src/lib/kStuff/kHlp/Generic/kHlpMemMove.c
new file mode 100644
index 0000000..438a299
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpMemMove.c
@@ -0,0 +1,100 @@
+/* $Id: kHlpMemMove.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpMemMove.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(void *) kHlpMemMove(void *pv1, const void *pv2, KSIZE cb)
+{
+    union
+    {
+        void *pv;
+        KU8 *pb;
+        KUPTR *pu;
+    } u1;
+    union
+    {
+        const void *pv;
+        volatile KU8 *pb;
+        volatile KUPTR *pu;
+    } u2;
+
+    u1.pv = pv1;
+    u2.pv = pv2;
+
+    if ((KUPTR)u1.pb <= (KUPTR)u2.pb)
+    {
+        /* forward copy */
+        if (cb >= 32)
+        {
+            while (cb > sizeof(KUPTR))
+            {
+                KUPTR u = *u2.pu++;
+                *u1.pu++ = u;
+                cb -= sizeof(KUPTR);
+            }
+        }
+
+        while (cb-- > 0)
+        {
+            KU8 b = *u2.pb++;
+            *u1.pb++ = b;
+        }
+    }
+    else
+    {
+        /* backwards copy */
+        u1.pb += cb;
+        u2.pb += cb;
+
+        if (cb >= 32)
+        {
+            while (cb > sizeof(KUPTR))
+            {
+                KUPTR u = *--u2.pu;
+                *--u1.pu = u;
+                cb -= sizeof(KUPTR);
+            }
+        }
+
+        while (cb-- > 0)
+        {
+            KU8 b = *--u2.pb;
+            *--u1.pb = b;
+        }
+    }
+
+    return pv1;
+}
+
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpMemPComp.c b/src/lib/kStuff/kHlp/Generic/kHlpMemPComp.c
new file mode 100644
index 0000000..d678517
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpMemPComp.c
@@ -0,0 +1,71 @@
+/* $Id: kHlpMemPComp.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpMemPComp.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(void *) kHlpMemPComp(const void *pv1, const void *pv2, KSIZE cb)
+{
+    union
+    {
+        const void *pv;
+        const KU8 *pb;
+        const KUPTR *pu;
+    } u1, u2;
+
+    u1.pv = pv1;
+    u2.pv = pv2;
+
+    if (cb >= 32)
+    {
+        while (cb > sizeof(KUPTR))
+        {
+            if (*u1.pu != *u2.pu)
+                break; /* over to mr. byte-by-byte */
+            u1.pu++;
+            u2.pu++;
+            cb -= sizeof(KUPTR);
+        }
+    }
+
+    while (cb-- > 0)
+    {
+        if (u1.pb != u2.pb)
+            return (void *)u1.pb;
+        u1.pb++;
+        u2.pb++;
+    }
+
+    return NULL;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpMemPCopy.c b/src/lib/kStuff/kHlp/Generic/kHlpMemPCopy.c
new file mode 100644
index 0000000..0b7945e
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpMemPCopy.c
@@ -0,0 +1,69 @@
+/* $Id: kHlpMemPCopy.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpMemPCopy.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(void *) kHlpMemPCopy(void *pv1, const void *pv2, KSIZE cb)
+{
+    union
+    {
+        void *pv;
+        KU8 *pb;
+        KUPTR *pu;
+    } u1;
+    union
+    {
+        const void *pv;
+        const KU8 *pb;
+        const KUPTR *pu;
+    } u2;
+
+    u1.pv = pv1;
+    u2.pv = pv2;
+
+    if (cb >= 32)
+    {
+        while (cb > sizeof(KUPTR))
+        {
+            cb -= sizeof(KUPTR);
+            *u1.pu++ = *u2.pu++;
+        }
+    }
+
+    while (cb-- > 0)
+        *u1.pb++ = *u2.pb++;
+
+    return u1.pb;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpMemPMove.c b/src/lib/kStuff/kHlp/Generic/kHlpMemPMove.c
new file mode 100644
index 0000000..6276519
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpMemPMove.c
@@ -0,0 +1,99 @@
+/* $Id: kHlpMemPMove.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpMemPMove.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(void *) kHlpMemPMove(void *pv1, const void *pv2, KSIZE cb)
+{
+    union
+    {
+        void *pv;
+        KU8 *pb;
+        KUPTR *pu;
+    } u1;
+    union
+    {
+        const void *pv;
+        volatile KU8 *pb;
+        volatile KUPTR *pu;
+    } u2;
+
+    u1.pv = pv1;
+    u2.pv = pv2;
+
+    if ((KUPTR)u1.pb <= (KUPTR)u2.pb)
+    {
+        /* forwards copy */
+        if (cb >= 32)
+        {
+            while (cb > sizeof(KUPTR))
+            {
+                KUPTR u = *u2.pu++;
+                *u1.pu++ = u;
+                cb -= sizeof(KUPTR);
+            }
+        }
+
+        while (cb-- > 0)
+        {
+            KU8 b = *u2.pb++;
+            *u1.pb++ = b;
+        }
+
+        return u1.pb;
+    }
+
+    /* backwards copy */
+    u1.pb += cb;
+    u2.pb += cb;
+
+    if (cb >= 32)
+    {
+        while (cb > sizeof(KUPTR))
+        {
+            KUPTR u = *--u2.pu;
+            *--u1.pu = u;
+            cb -= sizeof(KUPTR);
+        }
+    }
+
+    while (cb-- > 0)
+    {
+        KU8 b = *--u2.pb;
+        *--u1.pb = b;
+    }
+
+    return (KU8 *)pv1 + cb;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpMemPSet.c b/src/lib/kStuff/kHlp/Generic/kHlpMemPSet.c
new file mode 100644
index 0000000..0a77e1a
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpMemPSet.c
@@ -0,0 +1,77 @@
+/* $Id: kHlpMemPSet.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpMemPSet.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(void *) kHlpMemPSet(void *pv1, int ch, KSIZE cb)
+{
+    union
+    {
+        void *pv;
+        KU8 *pb;
+        KUPTR *pu;
+    } u1;
+
+    u1.pv = pv1;
+
+    if (cb >= 32)
+    {
+        KUPTR u = ch & 0xff;
+#if K_ARCH_BITS > 8
+        u |= u << 8;
+#endif
+#if K_ARCH_BITS > 16
+        u |= u << 16;
+#endif
+#if K_ARCH_BITS > 32
+        u |= u << 32;
+#endif
+#if K_ARCH_BITS > 64
+        u |= u << 64;
+#endif
+
+        while (cb > sizeof(KUPTR))
+        {
+            cb -= sizeof(KUPTR);
+            *u1.pu++ = u;
+        }
+    }
+
+    while (cb-- > 0)
+        *u1.pb++ = ch;
+
+    return u1.pb;
+}
+
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpMemSet.c b/src/lib/kStuff/kHlp/Generic/kHlpMemSet.c
new file mode 100644
index 0000000..4e986ae
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpMemSet.c
@@ -0,0 +1,76 @@
+/* $Id: kHlpMemSet.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpMemSet.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(void *) kHlpMemSet(void *pv1, int ch, KSIZE cb)
+{
+    union
+    {
+        void *pv;
+        KU8 *pb;
+        KUPTR *pu;
+    } u1;
+
+    u1.pv = pv1;
+
+    if (cb >= 32)
+    {
+        KUPTR u = ch & 0xff;
+#if K_ARCH_BITS > 8
+        u |= u << 8;
+#endif
+#if K_ARCH_BITS > 16
+        u |= u << 16;
+#endif
+#if K_ARCH_BITS > 32
+        u |= u << 32;
+#endif
+#if K_ARCH_BITS > 64
+        u |= u << 64;
+#endif
+
+        while (cb > sizeof(KUPTR))
+        {
+            cb -= sizeof(KUPTR);
+            *u1.pu++ = u;
+        }
+    }
+
+    while (cb-- > 0)
+        *u1.pb++ = ch;
+
+    return pv1;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpPage.c b/src/lib/kStuff/kHlp/Generic/kHlpPage.c
new file mode 100644
index 0000000..f915f58
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpPage.c
@@ -0,0 +1,371 @@
+/* $Id: kHlpPage.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlp - Generic Page Memory Functions.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpAlloc.h>
+#include <k/kHlpAssert.h>
+
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+# include <k/kHlpSys.h>
+# include <sys/mman.h>
+
+#elif K_OS == K_OS_OS2
+# define INCL_BASE
+# define INCL_ERRORS
+# include <os2.h>
+
+#elif  K_OS == K_OS_WINDOWS
+# include <Windows.h>
+
+#else
+# error "port me"
+#endif
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+/* nothing */
+#elif K_OS == K_OS_OS2
+/** The base of the loader stub object. <kLdr Hack>
+ * The OS/2 exe stub consists of a single data object. When allocating memory
+ * for an executable, we'll have to reuse this. */
+static void            *g_pvStub = NULL;
+/** The size of the stub object - 0 if no stub. <kLdr Hack> */
+static KSIZE            g_cbStub = 0;
+
+#elif  K_OS == K_OS_WINDOWS
+/** The system info. */
+static SYSTEM_INFO      g_SystemInfo;
+#else
+# error "port me"
+#endif
+
+
+
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+static int kHlpPageProtToNative(KPROT enmProt)
+{
+    switch (enmProt)
+    {
+        case KPROT_NOACCESS:             return PROT_NONE;
+        case KPROT_READONLY:             return PROT_READ;
+        case KPROT_READWRITE:            return PROT_READ | PROT_WRITE;
+        case KPROT_EXECUTE:              return PROT_EXEC;
+        case KPROT_EXECUTE_READ:         return PROT_EXEC | PROT_READ;
+        case KPROT_EXECUTE_READWRITE:    return PROT_EXEC | PROT_READ | PROT_WRITE;
+        default:
+            kHlpAssert(0);
+            return ~0U;
+    }
+}
+
+#elif K_OS == K_OS_OS2
+static ULONG kHlpPageProtToNative(KPROT enmProt)
+{
+    switch (enmProt)
+    {
+        case KPROT_NOACCESS:             return PAG_EXECUTE | PAG_READ | PAG_WRITE;
+        case KPROT_READONLY:             return PAG_COMMIT | PAG_READ;
+        case KPROT_READWRITE:            return PAG_COMMIT | PAG_READ | PAG_WRITE;
+        case KPROT_EXECUTE:              return PAG_COMMIT | PAG_EXECUTE;
+        case KPROT_EXECUTE_READ:         return PAG_COMMIT | PAG_EXECUTE | PAG_READ;
+        case KPROT_EXECUTE_READWRITE:    return PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE;
+        default:
+            kHlpAssert(0);
+            return ~0U;
+    }
+}
+#elif  K_OS == K_OS_WINDOWS
+static DWORD kHlpPageProtToNative(KPROT enmProt)
+{
+    switch (enmProt)
+    {
+        case KPROT_NOACCESS:             return PAGE_NOACCESS;
+        case KPROT_READONLY:             return PAGE_READONLY;
+        case KPROT_READWRITE:            return PAGE_READWRITE;
+        case KPROT_EXECUTE:              return PAGE_EXECUTE;
+        case KPROT_EXECUTE_READ:         return PAGE_EXECUTE_READ;
+        case KPROT_EXECUTE_READWRITE:    return PAGE_EXECUTE_READWRITE;
+        default:
+            kHlpAssert(0);
+            return ~0U;
+    }
+}
+#endif
+
+
+
+/**
+ * Allocate a chunk of memory with page granularity.
+ *
+ * @returns 0 on success, non-zero OS status code on failure.
+ * @param   ppv         Where to store the address of the allocated memory.
+ *                      If fFixed is set, *ppv will on entry contain the desired address (page aligned).
+ * @param   cb          Number of bytes. Page aligned.
+ * @param   enmProt     The new protection. Copy-on-write is invalid.
+ */
+KHLP_DECL(int) kHlpPageAlloc(void **ppv, KSIZE cb, KPROT enmProt, KBOOL fFixed)
+{
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+    void *pv;
+
+    pv = kHlpSys_mmap(fFixed ? *ppv : NULL, cb, kHlpPageProtToNative(enmProt),
+                      fFixed ? MAP_FIXED | MAP_ANON: MAP_ANON, -1, 0);
+    if ((KIPTR)pv < 256)
+    {
+        kHlpAssert(0);
+        return (int)(KIPTR)pv; /** @todo convert errno to kErrors */
+    }
+    *ppv = pv;
+    return 0;
+
+#elif K_OS == K_OS_OS2
+    APIRET  rc;
+    ULONG   fFlags = kHlpPageProtToNative(enmProt);
+
+    if (!fFixed)
+    {
+        /* simple */
+        rc = DosAllocMem(ppv, cb, fFlags | OBJ_ANY);
+        if (rc == ERROR_INVALID_PARAMETER)
+            rc = DosAllocMem(ppv, cb, fFlags);
+    }
+    else
+    {
+        /* not so simple. */
+        /** @todo I've got code for this in libc somewhere. */
+        rc = -1;
+    }
+    if (!rc)
+        return 0;
+    kHlpAssert(0);
+    return rc;
+
+#elif  K_OS == K_OS_WINDOWS
+    /* (We don't have to care about the stub here, because the stub will be unmapped before we get here.) */
+    int     rc;
+    DWORD   fProt = kHlpPageProtToNative(enmProt);
+
+    if (!g_SystemInfo.dwPageSize)
+        GetSystemInfo(&g_SystemInfo);
+
+    *ppv = VirtualAlloc(fFixed ? *ppv : NULL, cb, MEM_COMMIT, fProt);
+    if (*ppv != NULL)
+        return 0;
+    rc = GetLastError();
+    kHlpAssert(0);
+    return rc;
+
+#else
+# error "port me"
+#endif
+}
+
+
+/**
+ * Change the protection of one or more pages in an allocation.
+ *
+ * (This will of course only work correctly on memory allocated by kHlpPageAlloc().)
+ *
+ * @returns 0 on success, non-zero OS status code on failure.
+ * @param   pv          First page. Page aligned.
+ * @param   cb          Number of bytes. Page aligned.
+ * @param   enmProt     The new protection. Copy-on-write is invalid.
+ */
+KHLP_DECL(int) kHlpPageProtect(void *pv, KSIZE cb, KPROT enmProt)
+{
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+    int rc;
+
+    rc = kHlpSys_mprotect(pv, cb, kHlpPageProtToNative(enmProt));
+    if (!rc)
+        return 0;
+    /** @todo convert errno -> kErrors */
+    kHlpAssert(0);
+    return rc;
+
+#elif K_OS == K_OS_OS2
+    APIRET      rc;
+    ULONG       fFlags = kHlpPageProtToNative(enmProt);
+
+    /*
+     * The non-stub pages.
+     */
+    rc = DosSetMem(pv, cb, fFlags);
+    if (rc && fFlags != PAG_DECOMMIT)
+        rc = DosSetMem(pv, cb, fFlags | PAG_COMMIT);
+    if (rc)
+    {
+        /* Try page by page. */
+        while (cb > 0)
+        {
+            rc = DosSetMem(pv, 0x1000, fFlags);
+            if (rc && fFlags != PAG_DECOMMIT)
+                rc = DosSetMem(pv, 0x1000, fFlags | PAG_COMMIT);
+            if (rc)
+                return rc;
+            pv = (void *)((KUPTR)pv + 0x1000);
+            cb -= 0x1000;
+        }
+    }
+    kHlpAssert(!rc);
+    return rc;
+
+#elif  K_OS == K_OS_WINDOWS
+    DWORD fOldProt = 0;
+    DWORD fProt = kHlpPageProtToNative(enmProt);
+    int rc = 0;
+
+    if (!VirtualProtect(pv, cb, fProt, &fOldProt))
+    {
+        rc = GetLastError();
+        kHlpAssert(0);
+    }
+    return rc;
+#else
+# error "port me"
+#endif
+}
+
+
+/**
+ * Free memory allocated by kHlpPageAlloc().
+ *
+ * @returns 0 on success, non-zero OS status code on failure.
+ * @param   pv          The address returned by kHlpPageAlloc().
+ * @param   cb          The byte count requested from kHlpPageAlloc().
+ */
+KHLP_DECL(int) kHlpPageFree(void *pv, KSIZE cb)
+{
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+    int rc;
+
+    rc = kHlpSys_munmap(pv, cb);
+    if (!rc)
+        return 0;
+    /** @todo convert errno -> kErrors */
+    return rc;
+
+#elif K_OS == K_OS_OS2
+    APIRET rc;
+
+    /*
+     * Deal with any portion overlapping with the stub.
+     */
+    KUPTR offStub = (KUPTR)pv - (KUPTR)g_pvStub;
+    if (offStub < g_cbStub)
+    {
+        /* decommit the pages in the stub. */
+        KSIZE cbStub = K_MIN(g_cbStub - offStub, cb);
+        rc = DosSetMem(pv, cbStub, PAG_DECOMMIT);
+        if (rc)
+        {
+            /* Page by page, ignoring errors after the first success. */
+            while (cbStub > 0)
+            {
+                if (!DosSetMem(pv, 0x1000, PAG_DECOMMIT))
+                    rc = 0;
+                pv = (void *)((KUPTR)pv + 0x1000);
+                cbStub -= 0x1000;
+                cb -= 0x1000;
+            }
+            if (rc)
+            {
+                kHlpAssert(!rc);
+                return rc;
+            }
+        }
+        else
+        {
+            cb -= cbStub;
+            if (!cb)
+                return 0;
+            pv = (void *)((KUPTR)pv + cbStub);
+        }
+    }
+
+    /*
+     * Free the object.
+     */
+    rc = DosFreeMem(pv);
+    kHlpAssert(!rc);
+    return rc;
+
+#elif  K_OS == K_OS_WINDOWS
+    /*
+     * Free the object.
+     */
+    int rc = 0;
+    if (!VirtualFree(pv, 0 /*cb*/, MEM_RELEASE))
+    {
+        rc = GetLastError();
+        kHlpAssert(0);
+    }
+    return rc;
+
+#else
+# error "port me"
+#endif
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrCat.c b/src/lib/kStuff/kHlp/Generic/kHlpStrCat.c
new file mode 100644
index 0000000..82900ea
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrCat.c
@@ -0,0 +1,52 @@
+/* $Id: kHlpStrCat.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrCat.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(char *) kHlpStrCat(char *psz1, const char *psz2)
+{
+    char ch;
+    char *pszDst = psz1;
+
+    while (*pszDst != '\0')
+        pszDst++;
+    do
+    {
+        ch = *psz2++;
+        *pszDst++ = ch;
+    } while (ch != '\0');
+
+    return psz1;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrChr.c b/src/lib/kStuff/kHlp/Generic/kHlpStrChr.c
new file mode 100644
index 0000000..acff27c
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrChr.c
@@ -0,0 +1,56 @@
+/* $Id: kHlpStrChr.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrChr.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(char *) kHlpStrChr(const char *psz, int ch)
+{
+    if (!ch)
+    {
+        while (*psz)
+            psz++;
+        return (char *)psz;
+    }
+
+    for (;;)
+    {
+        int chCur = *psz;
+        if (chCur == ch)
+            return (char *)psz;
+        if (!chCur)
+            return NULL;
+        psz++;
+    }
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrComp.c b/src/lib/kStuff/kHlp/Generic/kHlpStrComp.c
new file mode 100644
index 0000000..12bdaaf
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrComp.c
@@ -0,0 +1,52 @@
+/* $Id: kHlpStrComp.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrComp.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(int) kHlpStrComp(const char *psz1, const char *psz2)
+{
+    for (;;)
+    {
+        char ch1 = *psz1;
+        char ch2 = *psz2;
+        if (ch1 != ch2)
+            return ch1 > ch2 ? 1 : -1;
+        if (!ch1)
+            return 0;
+        psz1++;
+        psz2++;
+    }
+}
+
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrCopy.c b/src/lib/kStuff/kHlp/Generic/kHlpStrCopy.c
new file mode 100644
index 0000000..86efbab
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrCopy.c
@@ -0,0 +1,46 @@
+/* $Id: kHlpStrCopy.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrCopy.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(char *) kHlpStrCopy(char *pszDst, const char *pszSrc)
+{
+    char ch;
+    char *psz = pszDst;
+    do
+        *psz++ = ch = *pszSrc;
+    while (ch);
+    return pszDst;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrICompAscii.c b/src/lib/kStuff/kHlp/Generic/kHlpStrICompAscii.c
new file mode 100644
index 0000000..446f61f
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrICompAscii.c
@@ -0,0 +1,58 @@
+/* $Id: kHlpStrICompAscii.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrICompAscii.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(int) kHlpStrICompAscii(const char *psz1, const char *psz2)
+{
+    for (;;)
+    {
+        char ch1 = *psz1;
+        char ch2 = *psz2;
+        if (ch1 != ch2)
+        {
+            if (ch1 <= 'Z' && ch1 >= 'A')
+                ch1 += 'a' - 'A';
+            if (ch2 <= 'Z' && ch2 >= 'A')
+                ch2 += 'a' - 'A';
+            if (ch1 != ch2)
+                return ch1 > ch2 ? 1 : -1;
+        }
+        if (!ch1)
+            return 0;
+        psz1++;
+        psz2++;
+    }
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrIPCompAscii.c b/src/lib/kStuff/kHlp/Generic/kHlpStrIPCompAscii.c
new file mode 100644
index 0000000..40d28f7
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrIPCompAscii.c
@@ -0,0 +1,59 @@
+/* $Id: kHlpStrIPCompAscii.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrIPCompAscii.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(char *) kHlpStrIPCompAscii(const char *psz1, const char *psz2)
+{
+    for (;;)
+    {
+        char ch1 = *psz1;
+        char ch2 = *psz2;
+        if (ch1 != ch2)
+        {
+            if (ch1 <= 'Z' && ch1 >= 'A')
+                ch1 += 'a' - 'A';
+            if (ch2 <= 'Z' && ch2 >= 'A')
+                ch2 += 'a' - 'A';
+            if (ch1 != ch2)
+                return (char *)psz1;
+        }
+        if (!ch1)
+            return (char *)psz1;
+        psz1++;
+        psz2++;
+    }
+}
+
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrLen.c b/src/lib/kStuff/kHlp/Generic/kHlpStrLen.c
new file mode 100644
index 0000000..714c703
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrLen.c
@@ -0,0 +1,44 @@
+/* $Id: kHlpStrLen.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrLen.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(KSIZE) kHlpStrLen(const char *psz)
+{
+    const char *pszEnd = psz;
+    while (*pszEnd)
+        pszEnd++;
+    return pszEnd - psz;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrNCat.c b/src/lib/kStuff/kHlp/Generic/kHlpStrNCat.c
new file mode 100644
index 0000000..a311cb0
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrNCat.c
@@ -0,0 +1,55 @@
+/* $Id: kHlpStrNCat.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrNCat.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(char *) kHlpStrNCat(char *psz1, const char *psz2, KSIZE cb)
+{
+    char ch;
+    char *pszDst = psz1;
+
+    while (*pszDst != '\0')
+        pszDst++;
+    while (cb-- > 0)
+    {
+        ch = *psz2++;
+        if (!ch)
+            break;
+        *pszDst++ = ch;
+    }
+    *pszDst = '\0';
+
+    return psz1;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrNComp.c b/src/lib/kStuff/kHlp/Generic/kHlpStrNComp.c
new file mode 100644
index 0000000..f46aa8a
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrNComp.c
@@ -0,0 +1,52 @@
+/* $Id: kHlpStrNComp.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrNComp.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(int) kHlpStrNComp(const char *psz1, const char *psz2, KSIZE cb)
+{
+    while (cb-- > 0)
+    {
+        char ch1 = *psz1;
+        char ch2 = *psz2;
+        if (ch1 != ch2)
+            return ch1 > ch2 ? 1 : -1;
+        if (!ch1)
+            break;
+        psz1++;
+        psz2++;
+    }
+    return 0;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrNICompAscii.c b/src/lib/kStuff/kHlp/Generic/kHlpStrNICompAscii.c
new file mode 100644
index 0000000..d9670a0
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrNICompAscii.c
@@ -0,0 +1,59 @@
+/* $Id: kHlpStrNICompAscii.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrNICompAscii.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(int) kHlpStrNICompAscii(const char *psz1, const char *psz2, KSIZE cb)
+{
+    while (cb-- > 0)
+    {
+        char ch1 = *psz1;
+        char ch2 = *psz2;
+        if (ch1 != ch2)
+        {
+            if (ch1 <= 'Z' && ch1 >= 'A')
+                ch1 += 'a' - 'A';
+            if (ch2 <= 'Z' && ch2 >= 'A')
+                ch2 += 'a' - 'A';
+            if (ch1 != ch2)
+                return ch1 > ch2 ? 1 : -1;
+        }
+        if (!ch1)
+            break;
+        psz1++;
+        psz2++;
+    }
+    return 0;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrNIPCompAscii.c b/src/lib/kStuff/kHlp/Generic/kHlpStrNIPCompAscii.c
new file mode 100644
index 0000000..976f197
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrNIPCompAscii.c
@@ -0,0 +1,61 @@
+/* $Id: kHlpStrNIPCompAscii.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrNIPCompAscii.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(char *) kHlpStrNIPCompAscii(const char *psz1, const char *psz2, KSIZE cb)
+{
+    while (cb-- > 0)
+    {
+        char ch1 = *psz1;
+        char ch2 = *psz2;
+        if (ch1 != ch2)
+        {
+            if (ch1 <= 'Z' && ch1 >= 'A')
+                ch1 += 'a' - 'A';
+            if (ch2 <= 'Z' && ch2 >= 'A')
+                ch2 += 'a' - 'A';
+            if (ch1 != ch2)
+                return (char *)psz1;
+        }
+        if (!ch1)
+            break;
+        psz1++;
+        psz2++;
+    }
+    return NULL;
+}
+
+
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrNLen.c b/src/lib/kStuff/kHlp/Generic/kHlpStrNLen.c
new file mode 100644
index 0000000..bf1db6c
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrNLen.c
@@ -0,0 +1,44 @@
+/* $Id: kHlpStrNLen.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrNLen.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(KSIZE) kHlpStrNLen(const char *psz, KSIZE cchMax)
+{
+    const char *pszEnd = psz;
+    while (cchMax-- > 0 && *pszEnd)
+        pszEnd++;
+    return pszEnd - psz;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrNPCat.c b/src/lib/kStuff/kHlp/Generic/kHlpStrNPCat.c
new file mode 100644
index 0000000..cec0921
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrNPCat.c
@@ -0,0 +1,54 @@
+/* $Id: kHlpStrNPCat.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrNPCat.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(char *) kHlpStrNPCat(char *pszDst, const char *pszSrc, KSIZE cb)
+{
+    char ch;
+
+    while (*pszDst != '\0')
+        pszDst++;
+    while (cb-- > 0)
+    {
+        ch = *pszSrc++;
+        if (!ch)
+            break;
+        *pszDst++ = ch;
+    }
+    *pszDst = '\0';
+
+    return pszDst;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrNPComp.c b/src/lib/kStuff/kHlp/Generic/kHlpStrNPComp.c
new file mode 100644
index 0000000..bafd05e
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrNPComp.c
@@ -0,0 +1,53 @@
+/* $Id: kHlpStrNPComp.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrNPComp.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(char *) kHlpStrNPComp(const char *psz1, const char *psz2, KSIZE cb)
+{
+    while (cb-- > 0)
+    {
+        char ch1 = *psz1;
+        char ch2 = *psz2;
+        if (ch1 != ch2)
+            return (char *)psz1;
+        if (!ch1)
+            break;
+        psz1++;
+        psz2++;
+    }
+    return NULL;
+}
+
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrPCat.c b/src/lib/kStuff/kHlp/Generic/kHlpStrPCat.c
new file mode 100644
index 0000000..fc80f9c
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrPCat.c
@@ -0,0 +1,51 @@
+/* $Id: kHlpStrPCat.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrPCat.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(char *) kHlpStrPCat(char *pszDst, const char *psz2)
+{
+    char ch;
+
+    while (*pszDst != '\0')
+        pszDst++;
+    do
+    {
+        ch = *psz2++;
+        *pszDst++ = ch;
+    } while (ch != '\0');
+
+    return pszDst - 1;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrPComp.c b/src/lib/kStuff/kHlp/Generic/kHlpStrPComp.c
new file mode 100644
index 0000000..3572427
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrPComp.c
@@ -0,0 +1,53 @@
+/* $Id: kHlpStrPComp.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrPComp.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(char *) kHlpStrPComp(const char *psz1, const char *psz2)
+{
+    for (;;)
+    {
+        char ch1 = *psz1;
+        char ch2 = *psz2;
+        if (ch1 != ch2)
+            return (char *)psz1;
+        if (!ch1)
+            return NULL;
+        psz1++;
+        psz2++;
+    }
+}
+
+
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrPCopy.c b/src/lib/kStuff/kHlp/Generic/kHlpStrPCopy.c
new file mode 100644
index 0000000..821258c
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrPCopy.c
@@ -0,0 +1,45 @@
+/* $Id: kHlpStrPCopy.c 83 2016-08-30 18:38:12Z bird $ */
+/** @file
+ * kHlpString - kHlpStrPCopy.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(char *) kHlpStrPCopy(char *pszDst, const char *pszSrc)
+{
+    char ch;
+    do
+        *pszDst++ = ch = *pszSrc++;
+    while (ch);
+    return pszDst - 1;
+}
+
diff --git a/src/lib/kStuff/kHlp/Generic/kHlpStrRChr.c b/src/lib/kStuff/kHlp/Generic/kHlpStrRChr.c
new file mode 100644
index 0000000..a712840
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Generic/kHlpStrRChr.c
@@ -0,0 +1,59 @@
+/* $Id: kHlpStrRChr.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpString - kHlpStrRChr.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kHlpString.h>
+
+
+KHLP_DECL(char *) kHlpStrRChr(const char *psz, int ch)
+{
+    char *pszLast;
+
+    if (!ch)
+    {
+        while (*psz)
+            psz++;
+        return (char *)psz;
+    }
+
+    pszLast = NULL;
+    for (;;)
+    {
+        int chCur = *psz;
+        if (chCur == ch)
+            pszLast = (char *)psz;
+        else if (!chCur)
+            return pszLast;
+        psz++;
+    }
+}
+
diff --git a/src/lib/kStuff/kHlp/Makefile.kmk b/src/lib/kStuff/kHlp/Makefile.kmk
new file mode 100644
index 0000000..3ba9882
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Makefile.kmk
@@ -0,0 +1,126 @@
+# $Id: Makefile.kmk 29 2009-07-01 20:30:29Z bird $
+## @file
+# kHlp - The Helper API, sub-makefile.
+#
+
+#
+# Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+DEPTH ?= ..
+SUB_DEPTH = ..
+include $(PATH_KBUILD)/subheader.kmk
+
+#
+# kHlpBaseStatic
+#
+LIBRARIES += kHlpBareStatic
+kHlpBareStatic_TEMPLATE = kStuffLIB
+kHlpBareStatic_SOURCES = \
+	Generic/kHlpMemChr.c \
+	Generic/kHlpMemComp.c \
+	Generic/kHlpMemPComp.c \
+	Generic/kHlpMemICompAscii.c \
+	Generic/kHlpMemCopy.c \
+	Generic/kHlpMemPCopy.c \
+	Generic/kHlpMemMove.c \
+	Generic/kHlpMemPMove.c \
+	Generic/kHlpMemSet.c \
+	Generic/kHlpMemPSet.c \
+	Generic/kHlpStrCat.c \
+	Generic/kHlpStrPCat.c \
+	Generic/kHlpStrNCat.c \
+	Generic/kHlpStrNPCat.c \
+	Generic/kHlpStrChr.c \
+	Generic/kHlpStrRChr.c \
+	Generic/kHlpStrComp.c \
+	Generic/kHlpStrPComp.c \
+	Generic/kHlpStrNComp.c \
+	Generic/kHlpStrNPComp.c \
+	Generic/kHlpStrICompAscii.c \
+	Generic/kHlpStrIPCompAscii.c \
+	Generic/kHlpStrNICompAscii.c \
+	Generic/kHlpStrNIPCompAscii.c \
+	Generic/kHlpStrCopy.c \
+	Generic/kHlpStrPCopy.c \
+	Generic/kHlpStrLen.c \
+	Generic/kHlpStrNLen.c \
+	Generic/kHlpInt2Ascii.c \
+	\
+	Generic/kHlpGetEnvUZ.c \
+	\
+	Generic/kHlpGetExt.c \
+	Generic/kHlpGetFilename.c \
+	Generic/kHlpIsFilenameOnly.c \
+	\
+	Generic/kHlpPage.c \
+	\
+	Bare/kHlpBareAssert.c \
+	Bare/kHlpBareHeap.c \
+	Bare/kHlpBareEnv.c \
+	Bare/kHlpBareProcess.c \
+	Bare/kHlpBareThread.c \
+
+kHlpBareStatic_SOURCES.darwin = \
+	Bare/kHlpSys-darwin.c
+
+#
+# kCrtStatic
+#
+LIBRARIES += kHlpCRTStatic
+kHlpCRTStatic_TEMPLATE = kStuffLIB
+kHlpCRTStatic_SOURCES = \
+	Generic/kHlpMemPComp.c \
+	Generic/kHlpMemICompAscii.c \
+	Generic/kHlpStrPCat.c \
+	Generic/kHlpStrNPCat.c \
+	Generic/kHlpStrPComp.c \
+	Generic/kHlpStrNPComp.c \
+	Generic/kHlpStrICompAscii.c \
+	Generic/kHlpStrIPCompAscii.c \
+	Generic/kHlpStrNICompAscii.c \
+	Generic/kHlpStrNIPCompAscii.c \
+	Generic/kHlpStrPCopy.c \
+	Generic/kHlpStrNLen.c \
+	Generic/kHlpInt2Ascii.c \
+	\
+	Generic/kHlpGetEnvUZ.c \
+	\
+	Generic/kHlpGetExt.c \
+	Generic/kHlpGetFilename.c \
+	Generic/kHlpIsFilenameOnly.c \
+	\
+	Generic/kHlpPage.c \
+	\
+	CRT/kHlpCRTAlloc.cpp \
+	CRT/kHlpCRTEnv.cpp \
+	CRT/kHlpCRTString.cpp \
+
+kHlpCRTStatic_SOURCES.darwin = \
+	Bare/kHlpSys-darwin.c
+
+
+# Generate the rules
+include $(PATH_KBUILD)/subfooter.kmk
+
diff --git a/src/lib/kStuff/kLdr/Doxyfile b/src/lib/kStuff/kLdr/Doxyfile
new file mode 100644
index 0000000..d54c1f5
--- /dev/null
+++ b/src/lib/kStuff/kLdr/Doxyfile
@@ -0,0 +1,1252 @@
+# Doxyfile 1.5.0
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = kLdr
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER         =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = docs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING   = YES
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT                  =
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS          = *.c *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = tst*
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH             = tg
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.  Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.  The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.  Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = NO
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE               =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = YES
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.  This is useful
+# if you want to understand what is going on.  On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#   TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#   TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS         = NO
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH           = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS           =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that a graph may be further truncated if the graph's
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/src/lib/kStuff/kLdr/Makefile.kmk b/src/lib/kStuff/kLdr/Makefile.kmk
new file mode 100644
index 0000000..fc8455b
--- /dev/null
+++ b/src/lib/kStuff/kLdr/Makefile.kmk
@@ -0,0 +1,224 @@
+# $Id: Makefile.kmk 29 2009-07-01 20:30:29Z bird $
+## @file
+# kLdr - The Dynamic Loader, sub-makefile.
+#
+
+#
+# Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+DEPTH ?= ..
+SUB_DEPTH = ..
+include $(PATH_KBUILD)/subheader.kmk
+
+#todo: include $(PATH_SUB_CURRENT)/testcase/Makefile.kmk
+
+#
+# Template for testcases.
+#
+TEMPLATE_TST = Testcase template
+ifeq ($(BUILD_TARGET),win)
+ ifeq ($(BUILD_TARGET_ARCH), x86)
+  TEMPLATE_TST_TOOL = VCC70
+  TEMPLATE_TST_CFLAGS = -W3 -Zi -Zl -MD
+  TEMPLATE_TST_LIBS = $(PATH_TOOL_VCC70_LIB)/msvcrt.lib
+ else
+  TEMPLATE_TST_TOOL = VCC80AMD64
+  TEMPLATE_TST_CFLAGS = -W3 -Zi -Zl -MD
+  TEMPLATE_TST_LIBS = $(PATH_TOOL_VCC80AMD64_LIB)/msvcrt.lib
+ endif
+ TEMPLATE_TST_CFLAGS.release = -O2
+ TEMPLATE_TST_ASFLAGS = -f win
+ TEMPLATE_TST_DEFS = __WIN__
+ TEMPLATE_TST_SDKS = WINPSDK W2K3DDK
+
+else
+ ifeq ($(BUILD_TARGET),os2)
+  TEMPLATE_TST_TOOL = GCC3OMF
+  TEMPLATE_TST_ASFLAGS = -f obj
+  TEMPLATE_TST_LIBS = os2 gcc end
+ else ifeq ($(BUILD_TARGET),darwin)
+  TEMPLATE_TST_TOOL = GCC4MACHO
+  TEMPLATE_TST_ASFLAGS = -f macho
+  TEMPLATE_TST_LIBS = #os2 gcc end
+ else
+  TEMPLATE_TST_TOOL = GCC3
+  TEMPLATE_TST_ASFLAGS = -f elf
+  TEMPLATE_TST_LIBS = gcc
+ endif
+ TEMPLATE_TST_CFLAGS = -Wall -pedantic -g -std=gnu99
+ TEMPLATE_TST_CFLAGS.release = -O2
+ TEMPLATE_TST_LDFLAGS =
+endif
+TEMPLATE_TST_INCS := $(PATH_SUB_CURRENT) $(PATH_SUB_ROOT)/include
+
+
+#
+# The kLdr DLL.
+#
+DLLS += kLdr
+kLdr_ASTOOL = NASM
+ifeq ($(BUILD_TARGET),win)
+ ifeq ($(BUILD_TARGET_ARCH),x86)
+  kLdr_TOOL = VCC70
+  kLdr_CFLAGS = -W3 -Zl -ML
+  kLdr_LDFLAGS = -Entry:DllMain at 12 -Debug
+  kLdr_LIBS = \
+   	$(PATH_TOOL_VCC70_LIB)/LIBC.lib \
+	$(PATH_SDK_W2K3DDKX86_LIB)/ntdll.lib
+ else
+  kLdr_TOOL = VCC80AMD64
+  kLdr_ASTOOL = YASM
+  kLdr_CFLAGS = -W3 -Zl -MT
+  kLdr_LDFLAGS = -Entry:DllMain -Debug
+  kLdr_LIBS = \
+   	$(PATH_TOOL_VCC80AMD64_LIB)/LIBCMT.lib \
+	$(PATH_SDK_W2K3DDKAMD64_LIB)/ntdll.lib
+ endif
+ kLdr_ASFLAGS = -f win
+ kLdr_DEFS = __WIN__
+ kLdr_SDKS.x86 = WIN32SDK W2K3DDKX86
+ kLdr_SDKS.amd64 = WIN64SDK W2K3DDKAMD64
+else
+ ifeq ($(BUILD_TARGET),os2)
+  kLdr_TOOL = GCC3OMF
+  kLdr_ASFLAGS = -f obj
+  kLdr_LIBS = os2 gcc end
+ else ifeq ($(BUILD_TARGET),darwin)
+  kLdr_TOOL = GCC4MACHO
+  kLdr_ASFLAGS = -f macho
+  kLdr_LIBS = #os2 gcc end
+ else
+  kLdr_TOOL = GCC3
+  kLdr_ASFLAGS = -f elf
+  kLdr_LIBS = gcc
+ endif
+ kLdr_CFLAGS = -Wall -pedantic
+ kLdr_LDFLAGS = -nostdlib
+endif
+kLdr_INCS := $(PATH_SUB_CURRENT) $(PATH_SUB_ROOT)/include
+kLdr_SOURCES = \
+	kLdr.c \
+	kLdrDyld.c \
+	kLdrDyldFind.c \
+	kLdrDyldMod.c \
+	kLdrDyldOS.c \
+	kLdrDyLdSem.c \
+	kLdrMod.c \
+	kLdrModLX.c \
+	kLdrModMachO.c \
+	kLdrModNative.c \
+	kLdrModPE.c
+kLdr_SOURCES.os2 = \
+	kLdr-os2.def \
+	kLdr-os2.c \
+	kLdrA-os2.asm
+kLdr_SOURCES.win = \
+	kLdr-win.def \
+	kLdr-win.c
+kLdr_LIBS += \
+	$(PATH_LIB)/kRdrStatic$(SUFF_LIB) \
+	$(PATH_LIB)/kCpuStatic$(SUFF_LIB) \
+	$(PATH_LIB)/kHlpBareStatic$(SUFF_LIB) \
+	$(PATH_LIB)/kErrStatic$(SUFF_LIB)
+
+#
+# A static edition of kLdr.
+#
+LIBRARIES += kLdrStatic
+kLdrStatic_TEMPLATE = kStuffLIB
+kLdrStatic_SDKS.win = WINPSDK W2K3DDK
+kLdrStatic_INCS := $(PATH_SUB_CURRENT) $(PATH_SUB_ROOT)/include
+kLdrStatic_DEFS.darwin = __DARWIN__
+kLdrStatic_DEFS.os2 = __OS2__
+kLdrStatic_DEFS.win = __WIN__
+kLdrStatic_SOURCES = $(kLdr_SOURCES)
+
+#
+# The OS/2 stub program.
+#
+PROGRAMS.os2 = kLdrExeStub-os2
+kLdrExeStub-os2_TOOL = GCC3OMF
+kLdrExeStub-os2_ASTOOL = NASM
+kLdrExeStub-os2_ASFLAGS = -f obj
+#kLdrExeStub-os2_LDFLAGS = -nostdlib
+kLdrExeStub-os2_LDFLAGS = -nostdlib -Zstack 64
+kLdrExeStub-os2_LIBS = $(TARGET_kLdr)
+#kLdrExeStub-os2_SOURCES = kLdrExeStub-os2.asm
+kLdrExeStub-os2_SOURCES =  kLdrExeStub-os2A.asm kLdrExeStub-os2.c
+
+#
+# The Windows stub program.
+#
+PROGRAMS.win = kLdrExeStub-win
+kLdrExeStub-win_TOOL.win.x86 = VCC70
+kLdrExeStub-win_TOOL.win.amd64 = VCC80AMD64
+kLdrExeStub-win_SDKS.x86 = WIN32SDK
+kLdrExeStub-win_SDKS.amd64 = WIN64SDK
+kLdrExeStub-win_INCS := $(PATH_SUB_CURRENT) $(PATH_SUB_ROOT)/include
+kLdrExeStub-win_DEFS = __WIN__
+kLdrExeStub-win_CFLAGS = -W3 -Zl
+kLdrExeStub-win_CFLAGS.debug = -Zi
+kLdrExeStub-win_LDFLAGS = -Entry:WindowsMain -SubSystem:Console -FIXED:NO
+kLdrExeStub-win_LIBS = $(TARGET_kLdr:.dll=.lib)
+kLdrExeStub-win_SOURCES = kLdrExeStub-win.c
+
+
+##
+## The (stub) utility.
+##
+#PROGRAMS = kLdrUtil
+
+
+#
+# Heap testcase.
+#
+#PROGRAMS += tstkLdrHeap
+tstkLdrHeap_TEMPLATE = TST
+tstkLdrHeap_SOURCES = \
+	tstkLdrHeap.c \
+	kHlp.c \
+	kHlpHeap.c \
+	kHlpMem.c \
+	kHlpPath.c \
+	kHlpSem.c \
+	kHlpStr.c \
+
+#
+# Heap testcase.
+#
+PROGRAMS += tstkLdrMod
+tstkLdrMod_TEMPLATE = TST
+tstkLdrMod_SOURCES = \
+	tstkLdrMod.c
+ifeq ($(BUILD_TARGET),win)
+tstkLdrMod_LIBS = $(TARGET_kLdr:.dll=.lib)
+else
+tstkLdrMod_LIBS = $(TARGET_kLdr)
+endif
+
+
+# Generate rules.
+include $(PATH_KBUILD)/subfooter.kmk
+
diff --git a/src/lib/kStuff/kLdr/kLdr-os2.c b/src/lib/kStuff/kLdr/kLdr-os2.c
new file mode 100644
index 0000000..62835ac
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdr-os2.c
@@ -0,0 +1,66 @@
+/* $Id: kLdr-os2.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - The Dynamic Loader, OS/2 Specifics.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define INCL_BASE
+#include <os2.h>
+
+#include <k/kLdr.h>
+#include "kLdrInternal.h"
+
+
+/**
+ * The DLL main function.
+ *
+ * @returns TRUE / FALSE.
+ * @param   hmod        The dll handle.
+ * @param   fFlags      Flags.
+ */
+ULONG _System _DLL_InitTerm(HMODULE hmod, ULONG fFlags)
+{
+    switch (fFlags)
+    {
+        case 0:
+        {
+            int rc = kldrInit();
+            return rc == 0;
+        }
+
+        case 1:
+            kldrTerm();
+            return TRUE;
+
+        default:
+            return FALSE;
+    }
+}
+
diff --git a/src/lib/kStuff/kLdr/kLdr-os2.def b/src/lib/kStuff/kLdr/kLdr-os2.def
new file mode 100644
index 0000000..e9895f7
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdr-os2.def
@@ -0,0 +1,115 @@
+; $Id: kLdr-os2.def 29 2009-07-01 20:30:29Z bird $
+;; @file
+; kLdr - The Dynamic Loader, OS/2 Linker Definition File.
+;
+
+;
+; Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+;
+; Permission is hereby granted, free of charge, to any person
+; obtaining a copy of this software and associated documentation
+; files (the "Software"), to deal in the Software without
+; restriction, including without limitation the rights to use,
+; copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of the Software, and to permit persons to whom the
+; Software is furnished to do so, subject to the following
+; conditions:
+;
+; The above copyright notice and this permission notice shall be
+; included in all copies or substantial portions of the Software.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+; OTHER DEALINGS IN THE SOFTWARE.
+;
+
+LIBRARY kLdr INITINSTANCE TERMINSTANCE
+DATA MULTIPLE
+EXPORTS
+    ; The file reader API
+    _kRdrAddProvider
+    _kRdrOpen
+    _kRdrClose
+    _kRdrRead
+    _kRdrAllMap
+    _kRdrAllUnmap
+    _kRdrSize
+    _kRdrTell
+    _kRdrName
+    _kRdrPageSize
+    _kRdrMap
+    _kRdrRefresh
+    _kRdrProtect
+    _kRdrUnmap
+    _kRdrDone
+
+    ; The module interpreter API
+    _kLdrModOpen
+    _kLdrModOpenFromRdr
+    _kLdrModOpenNative
+    _kLdrModOpenNativeByHandle
+    _kLdrModClose
+    _kLdrModQuerySymbol
+    _kLdrModEnumSymbols
+    _kLdrModGetImport
+    _kLdrModNumberOfImports
+    _kLdrModCanExecuteOn
+    _kLdrModGetStackInfo
+    _kLdrModQueryMainEntrypoint
+    _kLdrModEnumDbgInfo
+    _kLdrModHasDbgInfo
+    _kLdrModMap
+    _kLdrModUnmap
+    _kLdrModAllocTLS
+    _kLdrModFreeTLS
+    _kLdrModReload
+    _kLdrModFixupMapping
+    _kLdrModCallInit
+    _kLdrModCallTerm
+    _kLdrModCallThread
+    _kLdrModSize
+    _kLdrModGetBits
+    _kLdrModRelocateBits
+
+    ; Process Bootstrapping
+    _kLdrDyldLoadExe
+
+    ; Dynamic loading
+    _kLdrDyldLoad
+    _kLdrDyldUnload
+    _kLdrDyldFindByName
+    _kLdrDyldFindByAddress
+    _kLdrDyldGetName
+    _kLdrDyldGetFilename
+    _kLdrDyldQuerySymbol
+
+
+    ; OS/2 API wrappers:
+;    kLdrLoadModule
+;    kLdrFreeModule
+;    kLdrQueryModuleHandle
+;    kLdrQueryModuleName
+;    kLdrQueryProcAddr
+;    kLdrQueryProcType
+;    kLdrQueryModFromEIP
+;    kLdrReplaceModule
+;    kLdrGetResource
+;    kLdrFreeResource
+;    kLdrQueryResourceSize
+
+    ; dlfcn API wrappers:
+;    _kLdrDlOpen
+;    _kLdrDlClose
+;    _kLdrDlError
+;    _kLdrDlSym
+;    _kLdrDlFunc
+
+    ; Error APIs:
+    _kErrStr
+
+
diff --git a/src/lib/kStuff/kLdr/kLdr-win.c b/src/lib/kStuff/kLdr/kLdr-win.c
new file mode 100644
index 0000000..1fe7e59
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdr-win.c
@@ -0,0 +1,77 @@
+/* $Id: kLdr-win.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - The Dynamic Loader, Windows Specifics.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <Windows.h>
+
+#include <k/kLdr.h>
+#include "kLdrInternal.h"
+
+
+/**
+ * The DLL main function.
+ *
+ * @returns TRUE / FALSE.
+ * @param   hDllHandle  The dll handle.
+ * @param   dwReason    The reason we're being called.
+ * @param   lpReserved  Reserved.
+ */
+BOOL __stdcall DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved)
+{
+    switch (dwReason)
+    {
+        case DLL_PROCESS_ATTACH:
+        {
+            int rc = kldrInit();
+            return rc == 0;
+        }
+
+        case DLL_PROCESS_DETACH:
+            kldrTerm();
+            return TRUE;
+
+        case DLL_THREAD_ATTACH:
+        {
+            //int rc = kLdrDyldThreadAttach();
+            //return rc == 0;
+            return TRUE;
+        }
+
+        case DLL_THREAD_DETACH:
+            //kLdrDyldThreadDetach();
+            return TRUE;
+
+        default:
+            return FALSE;
+    }
+}
+
diff --git a/src/lib/kStuff/kLdr/kLdr-win.def b/src/lib/kStuff/kLdr/kLdr-win.def
new file mode 100644
index 0000000..fc36e59
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdr-win.def
@@ -0,0 +1,113 @@
+; $Id: kLdr-win.def 29 2009-07-01 20:30:29Z bird $
+;; @file
+; kLdr - The Dynamic Loader, Windows Linker Definition File.
+;
+
+;
+; Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+;
+; Permission is hereby granted, free of charge, to any person
+; obtaining a copy of this software and associated documentation
+; files (the "Software"), to deal in the Software without
+; restriction, including without limitation the rights to use,
+; copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of the Software, and to permit persons to whom the
+; Software is furnished to do so, subject to the following
+; conditions:
+;
+; The above copyright notice and this permission notice shall be
+; included in all copies or substantial portions of the Software.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+; OTHER DEALINGS IN THE SOFTWARE.
+;
+
+LIBRARY kLdr
+EXPORTS
+    ; The file reader API
+    kRdrAddProvider
+    kRdrOpen
+    kRdrClose
+    kRdrRead
+    kRdrAllMap
+    kRdrAllUnmap
+    kRdrSize
+    kRdrTell
+    kRdrName
+    kRdrPageSize
+    kRdrMap
+    kRdrRefresh
+    kRdrProtect
+    kRdrUnmap
+    kRdrDone
+
+    ; The module interpreter API
+    kLdrModOpen
+    kLdrModOpenFromRdr
+    kLdrModOpenNative
+    kLdrModOpenNativeByHandle
+    kLdrModClose
+    kLdrModQuerySymbol
+    kLdrModEnumSymbols
+    kLdrModGetImport
+    kLdrModNumberOfImports
+    kLdrModCanExecuteOn
+    kLdrModGetStackInfo
+    kLdrModQueryMainEntrypoint
+    kLdrModEnumDbgInfo
+    kLdrModHasDbgInfo
+    kLdrModMap
+    kLdrModUnmap
+    kLdrModAllocTLS
+    kLdrModFreeTLS
+    kLdrModReload
+    kLdrModFixupMapping
+    kLdrModCallInit
+    kLdrModCallTerm
+    kLdrModCallThread
+    kLdrModSize
+    kLdrModGetBits
+    kLdrModRelocateBits
+
+    ; Process Bootstrapping
+    kLdrDyldLoadExe
+
+    ; Dynamic loading
+    kLdrDyldLoad
+    kLdrDyldUnload
+    kLdrDyldFindByName
+    kLdrDyldFindByAddress
+    kLdrDyldGetName
+    kLdrDyldGetFilename
+    kLdrDyldQuerySymbol
+
+
+    ; OS/2 API wrappers:
+;    kLdrLoadModule
+;    kLdrFreeModule
+;    kLdrQueryModuleHandle
+;    kLdrQueryModuleName
+;    kLdrQueryProcAddr
+;    kLdrQueryProcType
+;    kLdrQueryModFromEIP
+;    kLdrReplaceModule
+;    kLdrGetResource
+;    kLdrFreeResource
+;    kLdrQueryResourceSize
+
+    ; dlfcn API wrappers:
+;    _kLdrDlOpen
+;    _kLdrDlClose
+;    _kLdrDlError
+;    _kLdrDlSym
+;    _kLdrDlFunc
+
+    ; Error APIs:
+    kErrName
+
diff --git a/src/lib/kStuff/kLdr/kLdr.c b/src/lib/kStuff/kLdr/kLdr.c
new file mode 100644
index 0000000..38f4cfa
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdr.c
@@ -0,0 +1,145 @@
+/* $Id: kLdr.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - The Dynamic Loader.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/** @mainpage   kLdr - The Dynamic Loader
+ *
+ * The purpose of kLdr is to provide a generic interface for querying
+ * information about and loading executable image modules.
+ *
+ * kLdr defines the term executable image to include all kinds of files that contains
+ * binary code that can be executed on a CPU - linker objects (OBJs/Os), shared
+ * objects (SOs), dynamic link libraries (DLLs), executables (EXEs), and all kinds
+ * of kernel modules / device drivers (SYSs).
+ *
+ * kLdr provides two types of services:
+ *      -# Inspect or/and load individual modules (kLdrMod).
+ *      -# Work as a dynamic loader - construct and maintain an address space (kLdrDy).
+ *
+ * The kLdrMod API works on KLDRMOD structures where all the internals are exposed, while
+ * the kLdrDy API works opque KLDRDY structures. KLDRDY are in reality simple wrappers
+ * around KLDRMOD with some extra linking and attributes.
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kLdr.h>
+#include "kLdrInternal.h"
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** Flag indicating whether we've initialized the loader or not.
+ *
+ * 0 if not initialized.
+ * -1 if we're initializing or terminating.
+ * 1 if we've successfully initialized it.
+ * -2 if initialization failed.
+ */
+static int volatile g_fInitialized;
+
+
+
+/**
+ * Initializes the loader.
+ * @returns 0 on success, non-zero OS status code on failure.
+ */
+int kldrInit(void)
+{
+    int rc;
+
+    /* check we're already good. */
+    if (g_fInitialized == 1)
+        return 0;
+
+    /* a tiny serialization effort. */
+    for (;;)
+    {
+        if (g_fInitialized == 1)
+            return 0;
+        if (g_fInitialized == -2)
+            return -1;
+        /** @todo atomic test and set if we care. */
+        if (g_fInitialized == 0)
+        {
+            g_fInitialized = -1;
+            break;
+        }
+        kHlpSleep(1);
+    }
+
+    /*
+     * Do the initialization.
+     */
+    rc = kHlpHeapInit();
+    if (!rc)
+    {
+        rc = kLdrDyldSemInit();
+        if (!rc)
+        {
+            rc = kldrDyldInit();
+            if (!rc)
+            {
+                g_fInitialized = 1;
+                return 0;
+            }
+            kLdrDyldSemTerm();
+        }
+        kHlpHeapTerm();
+    }
+    g_fInitialized = -2;
+    return rc;
+}
+
+
+/**
+ * Terminates the loader.
+ */
+void kldrTerm(void)
+{
+    /* can't terminate unless it's initialized. */
+    if (g_fInitialized != 1)
+        return;
+    g_fInitialized = -1;
+
+    /*
+     * Do the termination.
+     */
+    kLdrDyldSemTerm();
+    kHlpHeapTerm();
+
+    /* done */
+    g_fInitialized = 0;
+}
+
diff --git a/src/lib/kStuff/kLdr/kLdrA-os2.asm b/src/lib/kStuff/kLdr/kLdrA-os2.asm
new file mode 100644
index 0000000..cc9784a
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrA-os2.asm
@@ -0,0 +1,66 @@
+; $Id: kLdrA-os2.asm 29 2009-07-01 20:30:29Z bird $
+;; @file
+; kLdr - The Dynamic Loader, OS/2 Assembly Helpers.
+;
+
+;
+; Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+;
+; Permission is hereby granted, free of charge, to any person
+; obtaining a copy of this software and associated documentation
+; files (the "Software"), to deal in the Software without
+; restriction, including without limitation the rights to use,
+; copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of the Software, and to permit persons to whom the
+; Software is furnished to do so, subject to the following
+; conditions:
+;
+; The above copyright notice and this permission notice shall be
+; included in all copies or substantial portions of the Software.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+; OTHER DEALINGS IN THE SOFTWARE.
+;
+
+segment TEXT32 public align=16 CLASS=CODE use32
+
+;
+; _DLL_InitTerm
+;
+..start:
+extern _DLL_InitTerm
+    jmp _DLL_InitTerm
+
+
+;
+; kLdrLoadExe wrapper which loads the bootstrap stack.
+;
+global _kLdrDyldLoadExe
+_kLdrDyldLoadExe:
+    push    ebp
+    mov     ebp, esp
+
+    ; switch stack.
+;    extern _abStack
+;    lea     esp, [_abStack + 8192 - 4]
+    push    dword [ebp + 8 + 20]
+    push    dword [ebp + 8 + 16]
+    push    dword [ebp + 8 + 12]
+    push    dword [ebp + 8 +  8]
+
+    ; call worker on the new stack.
+    extern  _kldrDyldLoadExe
+    call    _kldrDyldLoadExe
+
+    ; we shouldn't return!
+we_re_not_supposed_to_get_here:
+    int3
+    int3
+    jmp short we_re_not_supposed_to_get_here
+
diff --git a/src/lib/kStuff/kLdr/kLdrDyld.c b/src/lib/kStuff/kLdr/kLdrDyld.c
new file mode 100644
index 0000000..9ff3dd8
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrDyld.c
@@ -0,0 +1,1509 @@
+/* $Id: kLdrDyld.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - The Dynamic Loader.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kLdr.h>
+#include "kLdrInternal.h"
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** @def KLDRDYLD_STRICT
+ * Define KLDRDYLD_STRICT to enabled strict checks in kLdrDyld. */
+#define KLDRDYLD_STRICT 1
+
+/** @def KLDRDYLD_ASSERT
+ * Assert that an expression is true when KLDRDYLD_STRICT is defined.
+ */
+#ifdef KLDRDYLD_STRICT
+# define KLDRDYLD_ASSERT(expr)  kHlpAssert(expr)
+#else
+# define KLDRDYLD_ASSERT(expr)  do {} while (0)
+#endif
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** Pointer to the executable module.
+ * (This is exported, so no prefix.) */
+PKLDRDYLDMOD    kLdrDyldExe = NULL;
+/** Pointer to the head module (the executable).
+ * (This is exported, so no prefix.) */
+PKLDRDYLDMOD    kLdrDyldHead = NULL;
+/** Pointer to the tail module.
+ * (This is exported, so no prefix.) */
+PKLDRDYLDMOD    kLdrDyldTail = NULL;
+/** Pointer to the head module of the initialization list.
+ * The outermost load call will pop elements from this list in LIFO order (i.e.
+ * from the tail). The list is only used during non-recursive initialization
+ * and may therefore share the pNext/pPrev members with the termination list
+ * since we don't push a module onto the termination list untill it has been
+ * successfully initialized. */
+PKLDRDYLDMOD    g_pkLdrDyldInitHead;
+/** Pointer to the tail module of the initalization list.*/
+PKLDRDYLDMOD    g_pkLdrDyldInitTail;
+/** Pointer to the head module of the termination order list.
+ * This is a LIFO just like the the init list. */
+PKLDRDYLDMOD    g_pkLdrDyldTermHead;
+/** Pointer to the tail module of the termination order list. */
+PKLDRDYLDMOD    g_pkLdrDyldTermTail;
+/** Pointer to the head module of the bind order list.
+ * The modules in this list makes up the global namespace used when binding symbol unix fashion. */
+PKLDRDYLDMOD    g_pkLdrDyldBindHead;
+/** Pointer to the tail module of the bind order list. */
+PKLDRDYLDMOD    g_pkLdrDyldBindTail;
+
+/** Flag indicating bootstrap time.
+ * When set the error behaviour changes. Any kind of serious failure
+ * is fatal and will terminate the process. */
+int             g_fBootstrapping;
+/** The global error buffer. */
+char            g_szkLdrDyldError[1024];
+
+/** The default flags. */
+KU32            kLdrDyldFlags = 0;
+/** The default search method. */
+KLDRDYLDSEARCH  kLdrDyldSearch = KLDRDYLD_SEARCH_HOST;
+
+
+/** @name The main stack.
+ * @{ */
+/** Indicates that the other MainStack globals have been filled in. */
+unsigned        g_fkLdrDyldDoneMainStack = 0;
+/** Whether the stack was allocated seperatly or was part of the executable. */
+unsigned        g_fkLdrDyldMainStackAllocated = 0;
+/** Pointer to the main stack object. */
+void           *g_pvkLdrDyldMainStack = NULL;
+/** The size of the main stack object. */
+KSIZE           g_cbkLdrDyldMainStack = 0;
+/** @} */
+
+
+/** The load stack.
+ * This contains frames with modules affected by active loads.
+ *
+ * Each kLdrDyldLoad and kLdrDyldLoadExe call will create a new stack frame containing
+ * all the modules involved in the operation. The modules will be ordered in recursive
+ * init order within the frame.
+ */
+static PPKLDRDYLDMOD    g_papStackMods;
+/** The number of used entries in the g_papStackMods array. */
+static KU32             g_cStackMods;
+/** The number of entries allocated for the g_papStackMods array. */
+static KU32             g_cStackModsAllocated;
+/** Number of active load calls. */
+static KU32             g_cActiveLoadCalls;
+/** Number of active unload calls. */
+static KU32             g_cActiveUnloadCalls;
+/** Total number of load calls. */
+static KU32             g_cTotalLoadCalls;
+/** Total mumber of unload calls. */
+static KU32             g_cTotalUnloadCalls;
+/** Boolean flag indicating that GC is active. */
+static KU32             g_fActiveGC;
+
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+/** @name API worker routines.
+ * @internal
+ * @{ */
+void       kldrDyldDoLoadExeStackSwitch(PKLDRDYLDMOD pExe, void *pvStack, KSIZE cbStack);
+static int kldrDyldDoLoad(const char *pszDll, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch,
+                          unsigned fFlags, PPKLDRDYLDMOD ppMod, char *pszErr, KSIZE cchErr);
+static int kldrDyldDoLoad2(PKLDRDYLDMOD pLoadedMod, const char *pszPrefix, const char *pszSuffix,
+                           KLDRDYLDSEARCH enmSearch, unsigned fFlags);
+static int kldrDyldDoLoadPrerequisites(PKLDRDYLDMOD pMod, const char *pszPrefix, const char *pszSuffix,
+                                       KLDRDYLDSEARCH enmSearch, unsigned fFlags);
+static int kldrDyldDoUnload(PKLDRDYLDMOD pMod);
+static int kldrDyldDoFindByName(const char *pszDll, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch,
+                              unsigned fFlags, PPKLDRDYLDMOD ppMod);
+static int kldrDyldDoFindByAddress(KUPTR Address, PPKLDRDYLDMOD ppMod, KU32 *piSegment, KUPTR *poffSegment);
+static int kldrDyldDoGetName(PKLDRDYLDMOD pMod, char *pszName, KSIZE cchName);
+static int kldrDyldDoGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, KSIZE cchFilename);
+static int kldrDyldDoQuerySymbol(PKLDRDYLDMOD pMod, KU32 uSymbolOrdinal, const char *pszSymbolName, KUPTR *pValue, KU32 *pfKind);
+/** @} */
+
+/** @name Misc load/unload workers
+ * @internal
+ * @{
+ */
+static void         kldrDyldDoModuleTerminationAndGarabageCollection(void);
+/** @} */
+
+/** @name The load stack.
+ * @internal
+ * @{ */
+static KU32         kldrDyldStackNewFrame(PKLDRDYLDMOD pMod);
+static int          kldrDyldStackAddModule(PKLDRDYLDMOD pMod);
+static int          kldrDyldStackFrameCompleted(void);
+static void         kldrDyldStackCleanupOne(PKLDRDYLDMOD pMod, int rc);
+static void         kldrDyldStackDropFrame(KU32 iLoad1st, KU32 iLoadEnd, int rc);
+/** @} */
+
+static int          kldrDyldCopyError(int rc, char *pszErr, KSIZE cchErr);
+
+
+
+/**
+ * Initialize the dynamic loader.
+ */
+int kldrDyldInit(void)
+{
+    kLdrDyldHead = kLdrDyldTail = NULL;
+    g_pkLdrDyldTermHead = g_pkLdrDyldTermTail = NULL;
+    g_pkLdrDyldBindHead = g_pkLdrDyldBindTail = NULL;
+    kLdrDyldFlags = 0;
+    g_szkLdrDyldError[0] = '\0';
+
+    g_fkLdrDyldDoneMainStack = 0;
+    g_fkLdrDyldMainStackAllocated = 0;
+    g_pvkLdrDyldMainStack = NULL;
+    g_cbkLdrDyldMainStack = 0;
+
+    return kldrDyldFindInit();
+}
+
+
+/**
+ * Terminate the dynamic loader.
+ */
+void kldrDyldTerm(void)
+{
+
+}
+
+
+/**
+ * Bootstrap an executable.
+ *
+ * This is called from the executable stub to replace the stub and run the
+ * executable specified in the argument package.
+ *
+ * Since this is boostrap time there isn't anything to return to. So, instead
+ * the process will be terminated upon failure.
+ *
+ * We also have to keep in mind that this function is called on a small, small,
+ * stack and therefore any kind of large stack objects or deep recursions must
+ * be avoided. Since loading the executable will involve more or less all
+ * operations in the loader, this restriction really applies everywhere.
+ *
+ * @param   pArgs       Pointer to the argument package residing in the executable stub.
+ * @param   pvOS        OS specific argument.
+ */
+#ifndef __OS2__  /* kLdrDyldLoadExe is implemented in assembly on OS/2. */
+void kLdrDyldLoadExe(PCKLDREXEARGS pArgs, void *pvOS)
+#else
+void kldrDyldLoadExe(PCKLDREXEARGS pArgs, void *pvOS)
+#endif
+{
+    void *pvStack;
+    KSIZE  cbStack;
+    PKLDRDYLDMOD pExe;
+    int rc;
+
+    /*
+     * Indicate that we're boostrapping and ensure that initialization was successful.
+     */
+    g_fBootstrapping = 1;
+    rc = kldrInit();
+    if (rc)
+        kldrDyldFailure(rc, "Init failure, rc=%d", rc);
+
+    /*
+     * Validate the argument package.
+     */
+    if (pArgs->fFlags & ~(  KLDRYDLD_LOAD_FLAGS_GLOBAL_SYMBOLS
+                          | KLDRYDLD_LOAD_FLAGS_DEEP_SYMBOLS
+                          | KLDRDYLD_LOAD_FLAGS_RECURSIVE_INIT
+                          | KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE))
+        kldrDyldFailure(KERR_INVALID_PARAMETER, "Bad fFlags=%#x", pArgs->fFlags);
+    if (    pArgs->enmSearch <= KLDRDYLD_SEARCH_INVALID
+        ||  pArgs->enmSearch >= KLDRDYLD_SEARCH_END)
+        kldrDyldFailure(KERR_INVALID_PARAMETER, "Bad enmSearch=%d", pArgs->enmSearch);
+
+    /*
+     * Set defaults.
+     */
+    kLdrDyldFlags |= (pArgs->fFlags & KLDRDYLD_LOAD_FLAGS_RECURSIVE_INIT);
+    kLdrDyldSearch = pArgs->enmSearch;
+
+    /** @todo make sense of this default prefix/suffix stuff. */
+    if (pArgs->szDefPrefix[0] != '\0')
+        kHlpMemCopy(kLdrDyldDefPrefix, pArgs->szDefPrefix, K_MIN(sizeof(pArgs->szDefPrefix), sizeof(kLdrDyldDefPrefix)));
+    if (pArgs->szDefSuffix[0] != '\0')
+        kHlpMemCopy(kLdrDyldDefSuffix, pArgs->szDefSuffix, K_MIN(sizeof(pArgs->szDefSuffix), sizeof(kLdrDyldDefSuffix)));
+
+    /** @todo append that path to the one for the specified search method. */
+    /** @todo create a function for doing this, an exposed api preferably. */
+    /* append path */
+    cbStack = sizeof(kLdrDyldLibraryPath) - kHlpStrLen(kLdrDyldLibraryPath); /* borrow cbStack for a itty bit. */
+    kHlpMemCopy(kLdrDyldLibraryPath, pArgs->szLibPath, K_MIN(sizeof(pArgs->szLibPath), cbStack));
+    kLdrDyldLibraryPath[sizeof(kLdrDyldLibraryPath) - 1] = '\0';
+
+    /*
+     * Make sure we own the loader semaphore (necessary for init).
+     */
+    rc = kLdrDyldSemRequest();
+    if (rc)
+        kldrDyldFailure(rc, "Sem req. failure, rc=%d", rc);
+
+    /*
+     * Open and map the executable module before we join paths with kLdrDyldLoad().
+     */
+    rc = kldrDyldFindNewModule(pArgs->szExecutable, NULL, NULL, pArgs->enmSearch,
+                               pArgs->fFlags | KLDRDYLD_LOAD_FLAGS_EXECUTABLE, &pExe);
+    if (rc)
+        kldrDyldFailure(rc, "Can't find/open the executable '%s', rc=%d", pArgs->szExecutable, rc);
+    rc = kldrDyldModMap(pExe);
+    if (rc)
+        kldrDyldFailure(rc, "Failed to map the executable '%s', rc=%d", pExe->pMod->pszFilename, rc);
+
+    kLdrDyldExe = pExe;
+
+    /*
+     * Query the stack and go to OS specific code to
+     * setup and switch stack. The OS specific code will call us
+     * back at kldrDyldDoLoadExe.
+     */
+    rc = kldrDyldModGetMainStack(pExe, &pvStack, &cbStack);
+    if (rc)
+        kldrDyldFailure(rc, "Failed to map the executable '%s', rc=%d", pExe->pMod->pszFilename, rc);
+    kldrDyldDoLoadExeStackSwitch(pExe, pvStack, cbStack);
+    kldrDyldFailure(-1, "Failed to setup the stack for '%s'.", pExe->pMod->pszFilename);
+}
+
+
+/**
+ * Loads a module into the current process.
+ *
+ * @returns 0 on success, non-zero native OS status code or kLdr status code on failure.
+ * @param   pszDll          The name of the dll to open.
+ * @param   pszPrefix       Prefix to use when searching.
+ * @param   pszSuffix       Suffix to use when searching.
+ * @param   enmSearch       Method to use when locating the module and any modules it may depend on.
+ * @param   fFlags          Flags, a combintation of the KLDRYDLD_LOAD_FLAGS_* \#defines.
+ * @param   phMod           Where to store the handle to the loaded module.
+ * @param   pszErr          Where to store extended error information. (optional)
+ * @param   cchErr          The size of the buffer pointed to by pszErr.
+ */
+int     kLdrDyldLoad(const char *pszDll, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch,
+                     unsigned fFlags, PHKLDRMOD phMod, char *pszErr, KSIZE cchErr)
+{
+    int rc;
+
+    /* validate arguments and initialize return values. */
+    if (pszErr && cchErr)
+        *pszErr = '\0';
+    *phMod = NIL_HKLDRMOD;
+    K_VALIDATE_STRING(pszDll);
+    K_VALIDATE_OPTIONAL_STRING(pszPrefix);
+    K_VALIDATE_OPTIONAL_STRING(pszSuffix);
+    K_VALIDATE_ENUM(enmSearch, KLDRDYLD_SEARCH);
+    K_VALIDATE_OPTIONAL_BUFFER(pszErr, cchErr);
+
+    /* get the semaphore and do the job. */
+    rc = kLdrDyldSemRequest();
+    if (!rc)
+    {
+        PKLDRDYLDMOD pMod = NULL;
+        g_cTotalLoadCalls++;
+        g_cActiveLoadCalls++;
+        rc = kldrDyldDoLoad(pszDll, pszPrefix, pszSuffix, enmSearch, fFlags, &pMod, pszErr, cchErr);
+        g_cActiveLoadCalls--;
+        kldrDyldDoModuleTerminationAndGarabageCollection();
+        kLdrDyldSemRelease();
+        *phMod = pMod ? pMod->hMod : NIL_HKLDRMOD;
+    }
+    return rc;
+}
+
+
+/**
+ * Unloads a module loaded by kLdrDyldLoad.
+ *
+ * @returns 0 on success, non-zero native OS status code or kLdr status code on failure.
+ * @param   hMod            Module handle.
+ */
+int     kLdrDyldUnload(HKLDRMOD hMod)
+{
+    int rc;
+
+    /* validate */
+    KLDRDYLD_VALIDATE_HKLDRMOD(hMod);
+
+    /* get sem & do work */
+    rc = kLdrDyldSemRequest();
+    if (!rc)
+    {
+        g_cTotalUnloadCalls++;
+        g_cActiveUnloadCalls++;
+        rc = kldrDyldDoUnload(hMod);
+        g_cActiveUnloadCalls--;
+        kldrDyldDoModuleTerminationAndGarabageCollection();
+        kLdrDyldSemRelease();
+    }
+    return rc;
+}
+
+
+/**
+ * Finds a module by name or filename.
+ *
+ * This call does not increase any reference counters and must not be
+ * paired with kLdrDyldUnload() like kLdrDyldLoad().
+ *
+ * @returns 0 on success.
+ * @returns KLDR_ERR_MODULE_NOT_FOUND or some I/O error on failure.
+ * @param   pszDll          The name of the dll to look for.
+ * @param   pszPrefix       Prefix than can be used when searching.
+ * @param   pszSuffix       Suffix than can be used when searching.
+ * @param   enmSearch       Method to use when locating the module.
+ * @param   fFlags          Flags, a combintation of the KLDRYDLD_LOAD_FLAGS_* \#defines.
+ * @param   phMod           Where to store the handle of the module on success.
+ */
+int     kLdrDyldFindByName(const char *pszDll, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch,
+                           unsigned fFlags, PHKLDRMOD phMod)
+{
+    int rc;
+
+    /* validate & initialize */
+    *phMod = NIL_HKLDRMOD;
+    K_VALIDATE_STRING(pszDll);
+
+    /* get sem & do work */
+    rc = kLdrDyldSemRequest();
+    if (!rc)
+    {
+        PKLDRDYLDMOD pMod = NULL;
+        rc = kldrDyldDoFindByName(pszDll, pszPrefix, pszSuffix, enmSearch, fFlags, &pMod);
+        kLdrDyldSemRelease();
+        *phMod = pMod ? pMod->hMod : NIL_HKLDRMOD;
+    }
+    return rc;
+}
+
+
+/**
+ * Finds a module by address.
+ *
+ * This call does not increase any reference counters and must not be
+ * paired with kLdrDyldUnload() like kLdrDyldLoad().
+ *
+ * @returns 0 on success.
+ * @returns KLDR_ERR_MODULE_NOT_FOUND on failure.
+ * @param   Address         The address believed to be within some module.
+ * @param   phMod           Where to store the module handle on success.
+ * @param   piSegment       Where to store the segment number. (optional)
+ * @param   poffSegment     Where to store the offset into the segment. (optional)
+ */
+int     kLdrDyldFindByAddress(KUPTR Address, PHKLDRMOD phMod, KU32 *piSegment, KUPTR *poffSegment)
+{
+    int rc;
+
+    /* validate & initialize */
+    *phMod = NIL_HKLDRMOD;
+    if (piSegment)
+        *piSegment = ~(KU32)0;
+    if (poffSegment)
+        *poffSegment = ~(KUPTR)0;
+
+    /* get sem & do work */
+    rc = kLdrDyldSemRequest();
+    if (!rc)
+    {
+        PKLDRDYLDMOD pMod = NULL;
+        rc = kldrDyldDoFindByAddress(Address, &pMod, piSegment, poffSegment);
+        kLdrDyldSemRelease();
+        *phMod = pMod ? pMod->hMod : NIL_HKLDRMOD;
+    }
+    return rc;
+}
+
+
+/**
+ * Gets the module name.
+ *
+ * @returns 0 on success and pszName filled with the name.
+ * @returns KERR_INVALID_HANDLE or KERR_BUFFER_OVERFLOW on failure.
+ * @param   hMod        The module handle.
+ * @param   pszName     Where to put the name.
+ * @param   cchName     The size of the name buffer.
+ * @see kLdrDyldGetFilename
+ */
+int     kLdrDyldGetName(HKLDRMOD hMod, char *pszName, KSIZE cchName)
+{
+    int rc;
+
+    /* validate */
+    if (pszName && cchName)
+        *pszName = '\0';
+    KLDRDYLD_VALIDATE_HKLDRMOD(hMod);
+    K_VALIDATE_BUFFER(pszName, cchName);
+
+    /* get sem & do work */
+    rc = kLdrDyldSemRequest();
+    if (!rc)
+    {
+        rc = kldrDyldDoGetName(hMod, pszName, cchName);
+        kLdrDyldSemRelease();
+    }
+    return rc;
+}
+
+
+/**
+ * Gets the module filename.
+ *
+ * @returns 0 on success and pszFilename filled with the name.
+ * @returns KERR_INVALID_HANDLE or KERR_BUFFER_OVERFLOW on failure.
+ * @param   hMod            The module handle.
+ * @param   pszFilename     Where to put the filename.
+ * @param   cchFilename     The size of the filename buffer.
+ * @see kLdrDyldGetName
+ */
+int     kLdrDyldGetFilename(HKLDRMOD hMod, char *pszFilename, KSIZE cchFilename)
+{
+    int rc;
+
+    /* validate & initialize */
+    if  (pszFilename && cchFilename);
+        *pszFilename = '\0';
+    KLDRDYLD_VALIDATE_HKLDRMOD(hMod);
+    K_VALIDATE_BUFFER(pszFilename, cchFilename);
+
+    /* get sem & do work */
+    rc = kLdrDyldSemRequest();
+    if (!rc)
+    {
+        rc = kldrDyldDoGetFilename(hMod, pszFilename, cchFilename);
+        kLdrDyldSemRelease();
+    }
+    return rc;
+}
+
+
+/**
+ * Queries the value and type of a symbol.
+ *
+ * @returns 0 on success and pValue and pfKind set.
+ * @returns KERR_INVALID_HANDLE or KLDR_ERR_SYMBOL_NOT_FOUND on failure.
+ * @param   hMod                The module handle.
+ * @param   uSymbolOrdinal      The symbol ordinal. This is ignored if pszSymbolName is non-zero.
+ * @param   pszSymbolName       The symbol name.
+ * @param   pszSymbolVersion    The symbol version. Optional.
+ * @param   pValue              Where to put the symbol value. Optional if pfKind is non-zero.
+ * @param   pfKind              Where to put the symbol kind flags. Optional if pValue is non-zero.
+ */
+int     kLdrDyldQuerySymbol(HKLDRMOD hMod, KU32 uSymbolOrdinal, const char *pszSymbolName,
+                            const char *pszSymbolVersion, KUPTR *pValue, KU32 *pfKind)
+{
+    int rc;
+
+    /* validate & initialize */
+    if (pfKind)
+        *pfKind = 0;
+    if (pValue)
+        *pValue = 0;
+    if (!pfKind && !pValue)
+        return KERR_INVALID_PARAMETER;
+    KLDRDYLD_VALIDATE_HKLDRMOD(hMod);
+    K_VALIDATE_OPTIONAL_STRING(pszSymbolName);
+
+    /* get sem & do work */
+    rc = kLdrDyldSemRequest();
+    if (!rc)
+    {
+        rc = kldrDyldDoQuerySymbol(hMod, uSymbolOrdinal, pszSymbolName, pValue, pfKind);
+        kLdrDyldSemRelease();
+    }
+    return rc;
+}
+
+
+/**
+ * Worker kLdrDoLoadExe().
+ * Used after we've switch to the final process stack.
+ *
+ * @param   pExe    The executable module.
+ * @internal
+ */
+void kldrDyldDoLoadExe(PKLDRDYLDMOD pExe)
+{
+    int rc;
+
+    /*
+     * Load the executable module with its prerequisites and initialize them.
+     */
+    g_cActiveLoadCalls++;
+    rc = kldrDyldDoLoad2(pExe, NULL, NULL, kLdrDyldSearch, kLdrDyldFlags | KLDRDYLD_LOAD_FLAGS_EXECUTABLE);
+    if (rc)
+        kldrDyldFailure(rc, "load 2 failed for '%s', rc=%d", pExe->pMod->pszFilename);
+    g_cActiveLoadCalls--;
+    kldrDyldDoModuleTerminationAndGarabageCollection();
+
+    /*
+     * Invoke the executable entry point.
+     */
+    kldrDyldModStartExe(pExe);
+    kldrDyldFailure(-1, "failed to invoke main!");
+}
+
+
+/**
+ * Worker for kLdrDyldLoad() and helper for kLdrDyldLoadExe().
+ * @internal
+ */
+static int kldrDyldDoLoad(const char *pszDll, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch,
+                          unsigned fFlags, PPKLDRDYLDMOD ppMod, char *pszErr, KSIZE cchErr)
+{
+    int rc;
+
+    /*
+     * Try find the module among the ones that's already loaded.
+     */
+    rc = kldrDyldFindExistingModule(pszDll, pszPrefix, pszSuffix, enmSearch, fFlags, ppMod);
+    if (!rc)
+    {
+        switch ((*ppMod)->enmState)
+        {
+            /*
+             * Prerequisites are ok, so nothing to do really.
+             */
+            case KLDRSTATE_GOOD:
+            case KLDRSTATE_INITIALIZING:
+                return kldrDyldModDynamicLoad(*ppMod);
+
+            /*
+             * The module can't be loaded because it failed to initialize.
+             */
+            case KLDRSTATE_INITIALIZATION_FAILED:
+                return KLDR_ERR_MODULE_INIT_FAILED_ALREADY;
+
+            /*
+             * Prerequisites needs loading / reattaching and the module
+             * (may depending on fFlags) needs to be initialized.
+             */
+            case KLDRSTATE_PENDING_INITIALIZATION:
+                break;
+
+            /*
+             * Prerequisites needs to be loaded again
+             */
+            case KLDRSTATE_PENDING_TERMINATION:
+                break;
+
+            /*
+             * The module has been terminated so it need to be reloaded, have it's
+             * prereqs loaded, fixed up and initialized before we can use it again.
+             */
+            case KLDRSTATE_PENDING_GC:
+                rc = kldrDyldModReload(*ppMod);
+                if (rc)
+                    return kldrDyldCopyError(rc, pszErr, cchErr);
+                break;
+
+            /*
+             * Forget it, we don't know how to deal with re-initialization here.
+             */
+            case KLDRSTATE_TERMINATING:
+                KLDRDYLD_ASSERT(!"KLDR_ERR_MODULE_TERMINATING");
+                return KLDR_ERR_MODULE_TERMINATING;
+
+            /*
+             * Invalid state.
+             */
+            default:
+                KLDRDYLD_ASSERT(!"invalid state");
+                break;
+        }
+    }
+    else
+    {
+        /*
+         * We'll have to load it from file.
+         */
+        rc = kldrDyldFindNewModule(pszDll, pszPrefix, pszSuffix, enmSearch, fFlags, ppMod);
+        if (rc)
+            return kldrDyldCopyError(rc, pszErr, cchErr);
+        rc = kldrDyldModMap(*ppMod);
+    }
+
+    /*
+     * Join cause with kLdrDyldLoadExe.
+     */
+    if (!rc)
+        rc = kldrDyldDoLoad2(*ppMod, pszPrefix, pszSuffix, enmSearch, fFlags);
+    else
+        kldrDyldStackCleanupOne(*ppMod, rc);
+
+    /*
+     * Copy any error or warning to the error buffer.
+     */
+    return kldrDyldCopyError(rc, pszErr, cchErr);
+}
+
+
+/**
+ * 2nd half of kLdrDyldLoad() and kLdrDyldLoadExe().
+ *
+ * @internal
+ */
+static int kldrDyldDoLoad2(PKLDRDYLDMOD pLoadedMod, const char *pszPrefix, const char *pszSuffix,
+                           KLDRDYLDSEARCH enmSearch, unsigned fFlags)
+{
+    /*
+     * Load prerequisites.
+     */
+    KU32 i;
+    KU32 iLoad1st = kldrDyldStackNewFrame(pLoadedMod);
+    int rc = kldrDyldDoLoadPrerequisites(pLoadedMod, pszPrefix, pszSuffix, enmSearch, fFlags);
+    KU32 iLoadEnd = kldrDyldStackFrameCompleted();
+    if (rc)
+    {
+        kldrDyldModAddRef(pLoadedMod);
+        kldrDyldStackCleanupOne(pLoadedMod, rc); /* in case it didn't get pushed onto the stack. */
+        kldrDyldModDeref(pLoadedMod);
+    }
+
+    /*
+     * Apply fixups.
+     */
+    for (i = iLoad1st; !rc && i < iLoadEnd; i++)
+    {
+        PKLDRDYLDMOD pMod = g_papStackMods[i];
+        if (    pMod->enmState == KLDRSTATE_LOADED_PREREQUISITES
+            ||  pMod->enmState == KLDRSTATE_RELOADED_LOADED_PREREQUISITES)
+            rc = kldrDyldModFixup(pMod);
+    }
+
+    /*
+     * Advance fixed up module onto initialization.
+     */
+    for (i = iLoad1st; !rc && i < iLoadEnd; i++)
+    {
+        PKLDRDYLDMOD pMod = g_papStackMods[i];
+        if (    pMod->enmState == KLDRSTATE_FIXED_UP
+            ||  pMod->enmState == KLDRSTATE_RELOADED_FIXED_UP)
+            pMod->enmState = KLDRSTATE_PENDING_INITIALIZATION;
+        KLDRDYLD_ASSERT(    pMod->enmState == KLDRSTATE_PENDING_INITIALIZATION
+                        ||  pMod->enmState == KLDRSTATE_GOOD);
+    }
+
+    /*
+     * Call the initializers if we're loading in recursive mode or
+     * if we're the outermost load call.
+     */
+    if (fFlags & KLDRDYLD_LOAD_FLAGS_RECURSIVE_INIT)
+    {
+        for (i = iLoad1st; !rc && i < iLoadEnd; i++)
+        {
+            PKLDRDYLDMOD pMod = g_papStackMods[i];
+            if (pMod->enmState == KLDRSTATE_PENDING_INITIALIZATION)
+                rc = kldrDyldModCallInit(pMod);
+            else if (pMod->enmState == KLDRSTATE_INITIALIZATION_FAILED)
+                rc = KLDR_ERR_PREREQUISITE_MODULE_INIT_FAILED_ALREADY;
+            else
+                KLDRDYLD_ASSERT(g_papStackMods[i]->enmState == KLDRSTATE_GOOD);
+        }
+#ifdef KLDRDYLD_STRICT
+        for (i = iLoad1st; !rc && i < iLoadEnd; i++)
+            KLDRDYLD_ASSERT(g_papStackMods[i]->enmState == KLDRSTATE_GOOD);
+#endif
+    }
+    else if (g_cActiveLoadCalls <= 1)
+    {
+        while (!rc && g_pkLdrDyldInitHead)
+        {
+            PKLDRDYLDMOD pMod = g_pkLdrDyldInitHead;
+            g_pkLdrDyldInitHead = pMod->InitTerm.pNext;
+            if (pMod->InitTerm.pNext)
+                pMod->InitTerm.pNext->InitTerm.pPrev = NULL;
+            else
+                g_pkLdrDyldInitTail = NULL;
+            pMod->fInitList = 0;
+            rc = kldrDyldModCallInit(pMod);
+        }
+    }
+
+    /*
+     * Complete the load by incrementing the dynamic load count of the
+     * requested module (return handle is already set).
+     */
+    if (!rc)
+    {
+        if (fFlags & KLDRDYLD_LOAD_FLAGS_EXECUTABLE)
+        {
+            pLoadedMod->cDepRefs++; /* just make it stick. */
+            pLoadedMod->cRefs++;
+        }
+        else
+            rc = kldrDyldModDynamicLoad(pLoadedMod);
+    }
+
+    kldrDyldStackDropFrame(iLoad1st, iLoadEnd, rc);
+    return rc;
+}
+
+
+/**
+ * kldrDyldDoLoad() helper which will load prerequisites and
+ * build the initialization array / list.
+ *
+ * @returns 0 on success, non-zero error code on failure.
+ * @param   pMod            The module to start at.
+ * @param   pszPrefix       Prefix to use when searching.
+ * @param   pszSuffix       Suffix to use when searching.
+ * @param   enmSearch       Method to use when locating the module and any modules it may depend on.
+ * @param   fFlags          Flags, a combintation of the KLDRYDLD_LOAD_FLAGS_* \#defines.
+ */
+static int kldrDyldDoLoadPrerequisites(PKLDRDYLDMOD pMod, const char *pszPrefix, const char *pszSuffix,
+                                       KLDRDYLDSEARCH enmSearch, unsigned fFlags)
+{
+    static struct
+    {
+        /** The module. */
+        PKLDRDYLDMOD    pMod;
+        /** The number of prerequisite modules left to process.
+         * This starts at ~0U to inidicate that we need to load/check prerequisistes. */
+        unsigned        cLeft;
+    }               s_aEntries[64];
+    unsigned        cEntries;
+    int             rc = 0;
+
+    /* Prerequisites are always global and they just aren't executables. */
+    fFlags &= ~(KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE | KLDRDYLD_LOAD_FLAGS_EXECUTABLE);
+
+    /* push the first entry. */
+    s_aEntries[0].pMod = pMod;
+    s_aEntries[0].cLeft = ~0U;
+    cEntries = 1;
+
+    /*
+     * The recursion loop.
+     */
+    while (!rc && cEntries > 0)
+    {
+        const unsigned i = cEntries - 1;
+        pMod = s_aEntries[i].pMod;
+        if (s_aEntries[i].cLeft == ~0U)
+        {
+            /*
+             * Load prerequisite modules.
+             */
+            switch (pMod->enmState)
+            {
+                /*
+                 * Load immediate prerequisite modules and push the ones needing
+                 * attention onto the stack.
+                 */
+                case KLDRSTATE_MAPPED:
+                case KLDRSTATE_RELOADED:
+                case KLDRSTATE_PENDING_TERMINATION:
+                    rc = kldrDyldModLoadPrerequisites(pMod, pszPrefix, pszSuffix, enmSearch, fFlags);
+                    KLDRDYLD_ASSERT(    pMod->enmState == KLDRSTATE_GOOD
+                                    ||  pMod->enmState == KLDRSTATE_RELOADED_LOADED_PREREQUISITES
+                                    ||  pMod->enmState == KLDRSTATE_LOADED_PREREQUISITES
+                                    ||  rc);
+                    if (!rc)
+                        s_aEntries[i].cLeft = pMod->cPrereqs;
+                    break;
+
+                /*
+                 * Check its prerequisite modules the first time around.
+                 */
+                case KLDRSTATE_PENDING_INITIALIZATION:
+                    if (pMod->fAlreadySeen)
+                        break;
+                    pMod->fAlreadySeen = 1;
+                    s_aEntries[i].cLeft = pMod->cPrereqs;
+                    break;
+
+                /*
+                 * These are ok.
+                 */
+                case KLDRSTATE_LOADED_PREREQUISITES:
+                case KLDRSTATE_RELOADED_LOADED_PREREQUISITES:
+                case KLDRSTATE_INITIALIZING:
+                case KLDRSTATE_GOOD:
+                    s_aEntries[i].cLeft = 0;
+                    break;
+
+                /*
+                 * All other stats are invalid.
+                 */
+                default:
+                    KLDRDYLD_ASSERT(!"invalid state");
+                    break;
+            }
+        }
+        else if (s_aEntries[i].cLeft > 0)
+        {
+            /*
+             * Recurse down into the next prereq.
+             */
+            KLDRDYLD_ASSERT(s_aEntries[i].cLeft <= pMod->cPrereqs);
+            if (cEntries < sizeof(s_aEntries) / sizeof(s_aEntries[0]))
+            {
+                s_aEntries[cEntries].cLeft = ~(KU32)0;
+                s_aEntries[cEntries].pMod = pMod->papPrereqs[pMod->cPrereqs - s_aEntries[i].cLeft];
+                s_aEntries[i].cLeft--;
+                cEntries++;
+            }
+            else
+                rc = KLDR_ERR_PREREQUISITE_RECURSED_TOO_DEEPLY;
+        }
+        else
+        {
+            /*
+             * We're done with this module, record it for init/cleanup.
+             */
+            cEntries--;
+            if (pMod->enmState != KLDRSTATE_GOOD)
+            {
+                kldrDyldStackAddModule(pMod);
+                if  (   !(fFlags & KLDRDYLD_LOAD_FLAGS_RECURSIVE_INIT)
+                     && !pMod->fInitList)
+                {
+                    pMod->fInitList = 1;
+                    pMod->InitTerm.pNext = NULL;
+                    pMod->InitTerm.pPrev = g_pkLdrDyldInitTail;
+                    if (g_pkLdrDyldInitTail)
+                        g_pkLdrDyldInitTail->InitTerm.pNext = pMod;
+                    else
+                        g_pkLdrDyldInitHead = pMod;
+                    g_pkLdrDyldInitTail = pMod;
+                }
+            }
+        }
+    }
+
+    return rc;
+}
+
+
+/**
+ * Gets prerequisite module.
+ *
+ * This will try load the requested module if necessary, returning it in the MAPPED state.
+ *
+ * @returns 0 on success.
+ * @returns KLDR_ERR_MODULE_NOT_FOUND or I/O error on failure.
+ * @param   pszDll          The name of the dll to look for.
+ * @param   pszPrefix    Prefix than can be used when searching.
+ * @param   pszSuffix    Suffix than can be used when searching.
+ * @param   enmSearch       Method to use when locating the module.
+ * @param   fFlags          Flags, a combintation of the KLDRYDLD_LOAD_FLAGS_* \#defines.
+ * @param   pDep            The depentant module.
+ * @param   ppMod           Where to put the module we get.
+ */
+int kldrDyldGetPrerequisite(const char *pszDll, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch,
+                            unsigned fFlags, PKLDRDYLDMOD pDep, PPKLDRDYLDMOD ppMod)
+{
+    int             rc;
+    PKLDRDYLDMOD    pMod;
+
+    *ppMod = NULL;
+
+    /*
+     * Try find the module among the ones that's already loaded.
+     *
+     * This is very similar to the kldrDyldDoLoad code, except it has to deal with
+     * a couple of additional states and occurs only during prerequisite loading
+     * and the action taken is a little bit different.
+     */
+    rc = kldrDyldFindExistingModule(pszDll, pszPrefix, pszSuffix, enmSearch, fFlags, &pMod);
+    if (!rc)
+    {
+        switch (pMod->enmState)
+        {
+            /*
+             * These are good.
+             */
+            case KLDRSTATE_MAPPED:
+            case KLDRSTATE_RELOADED:
+            case KLDRSTATE_LOADED_PREREQUISITES:
+            case KLDRSTATE_RELOADED_LOADED_PREREQUISITES:
+            case KLDRSTATE_PENDING_INITIALIZATION:
+            case KLDRSTATE_INITIALIZING:
+            case KLDRSTATE_GOOD:
+            case KLDRSTATE_PENDING_TERMINATION:
+                break;
+
+            /*
+             * The module has been terminated so it need to be reloaded, have it's
+             * prereqs loaded, fixed up and initialized before we can use it again.
+             */
+            case KLDRSTATE_PENDING_GC:
+                rc = kldrDyldModReload(pMod);
+                break;
+
+            /*
+             * The module can't be loaded because it failed to initialize already.
+             */
+            case KLDRSTATE_INITIALIZATION_FAILED:
+                rc = KLDR_ERR_PREREQUISITE_MODULE_INIT_FAILED;
+                break;
+
+            /*
+             * Forget it, no idea how to deal with re-initialization.
+             */
+            case KLDRSTATE_TERMINATING:
+                return KLDR_ERR_PREREQUISITE_MODULE_TERMINATING;
+
+            /*
+             * Invalid state.
+             */
+            default:
+                KLDRDYLD_ASSERT(!"invalid state");
+                break;
+        }
+    }
+    else
+    {
+        /*
+         * We'll have to load it from file.
+         */
+        rc = kldrDyldFindNewModule(pszDll, pszPrefix, pszSuffix, enmSearch, fFlags, &pMod);
+        if (!rc)
+            rc = kldrDyldModMap(pMod);
+    }
+
+    /*
+     * On success add dependency.
+     */
+    if (!rc)
+    {
+        kldrDyldModAddDep(pMod, pDep);
+        *ppMod = pMod;
+    }
+    return rc;
+}
+
+
+/**
+ * Starts a new load stack frame.
+ *
+ * @returns Where the new stack frame starts.
+ * @param   pLoadMod        The module being loaded (only used for asserting).
+ */
+static KU32 kldrDyldStackNewFrame(PKLDRDYLDMOD pLoadMod)
+{
+    /*
+     * Clear the fAlreadySeen flags.
+     */
+    PKLDRDYLDMOD pMod = kLdrDyldHead;
+    while (pMod)
+    {
+        pMod->fAlreadySeen = 0;
+
+#ifdef KLDRDYLD_ASSERT
+        switch (pMod->enmState)
+        {
+            case KLDRSTATE_MAPPED:
+            case KLDRSTATE_RELOADED:
+                /* only the just loaded module can be in this state. */
+                KLDRDYLD_ASSERT(pMod == pLoadMod);
+                break;
+
+            case KLDRSTATE_PENDING_INITIALIZATION:
+            case KLDRSTATE_INITIALIZING:
+            case KLDRSTATE_PENDING_TERMINATION:
+            case KLDRSTATE_PENDING_GC:
+            case KLDRSTATE_TERMINATING:
+            case KLDRSTATE_INITIALIZATION_FAILED:
+            case KLDRSTATE_PENDING_DESTROY:
+                /* requires recursion. */
+                KLDRDYLD_ASSERT(g_cActiveLoadCalls + g_cActiveLoadCalls + g_fActiveGC > 1);
+                break;
+
+            case KLDRSTATE_GOOD:
+                /* requires nothing. */
+                break;
+
+            default:
+                KLDRDYLD_ASSERT(!"Invalid state");
+                break;
+        }
+#endif
+
+        /* next */
+        pMod = pMod->Load.pNext;
+    }
+    return g_cStackMods;
+}
+
+
+/**
+ * Records the module.
+ *
+ * @return 0 on success, KERR_NO_MEMORY if we can't expand the table.
+ * @param   pMod        The module to record.
+ */
+static int kldrDyldStackAddModule(PKLDRDYLDMOD pMod)
+{
+    /*
+     * Grow the stack if necessary.
+     */
+    if (g_cStackMods + 1 > g_cStackModsAllocated)
+    {
+        KU32 cNew = g_cStackModsAllocated ? g_cStackModsAllocated * 2 : 128;
+        void *pvOld = g_papStackMods;
+        void *pvNew = kHlpAlloc(cNew * sizeof(g_papStackMods[0]));
+        if (!pvNew)
+            return KERR_NO_MEMORY;
+        kHlpMemCopy(pvNew, pvOld, g_cStackMods * sizeof(g_papStackMods[0]));
+        g_papStackMods = (PPKLDRDYLDMOD)pvNew;
+        kHlpFree(pvOld);
+    }
+
+    /*
+     * Add a reference and push the module onto the stack.
+     */
+    kldrDyldModAddRef(pMod);
+    g_papStackMods[g_cStackMods++] = pMod;
+    return 0;
+}
+
+
+/**
+ * The frame has been completed.
+ *
+ * @returns Where the frame ends.
+ */
+static int kldrDyldStackFrameCompleted(void)
+{
+    return g_cStackMods;
+}
+
+
+/**
+ * Worker routine for kldrDyldStackDropFrame() and kldrDyldDoLoad().
+ *
+ * @param   pMod            The module to perform cleanups on.
+ * @param   rc              Used for state verification.
+ */
+static void kldrDyldStackCleanupOne(PKLDRDYLDMOD pMod, int rc)
+{
+    switch (pMod->enmState)
+    {
+        /*
+         * Just push it along to the PENDING_DESTROY state.
+         */
+        case KLDRSTATE_MAPPED:
+            KLDRDYLD_ASSERT(rc);
+            kldrDyldModUnmap(pMod);
+            KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY);
+            break;
+
+        /*
+         * Move back to PENDING_GC.
+         */
+        case KLDRSTATE_RELOADED:
+            KLDRDYLD_ASSERT(rc);
+            pMod->enmState = KLDRSTATE_PENDING_GC;
+            break;
+
+        /*
+         * Unload prerequisites and unmap the modules.
+         */
+        case KLDRSTATE_LOADED_PREREQUISITES:
+        case KLDRSTATE_FIXED_UP:
+            KLDRDYLD_ASSERT(rc);
+            kldrDyldModUnloadPrerequisites(pMod);
+            KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY);
+            kldrDyldModUnmap(pMod);
+            KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY);
+            break;
+
+        /*
+         * Unload prerequisites and push it back to PENDING_GC.
+         */
+        case KLDRSTATE_RELOADED_LOADED_PREREQUISITES:
+        case KLDRSTATE_RELOADED_FIXED_UP:
+            kldrDyldModUnloadPrerequisites(pMod);
+            KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_GC);
+            break;
+
+        /*
+         * Nothing to do, just asserting sanity.
+         */
+        case KLDRSTATE_INITIALIZING:
+            /* Implies there is another load going on. */
+            KLDRDYLD_ASSERT(g_cActiveLoadCalls > 1);
+            break;
+        case KLDRSTATE_TERMINATING:
+            /* GC in progress. */
+            KLDRDYLD_ASSERT(g_fActiveGC);
+            break;
+        case KLDRSTATE_PENDING_TERMINATION:
+        case KLDRSTATE_PENDING_INITIALIZATION:
+        case KLDRSTATE_PENDING_GC:
+        case KLDRSTATE_PENDING_DESTROY:
+            KLDRDYLD_ASSERT(rc);
+            break;
+        case KLDRSTATE_GOOD:
+            break;
+
+        /*
+         * Bad states.
+         */
+        default:
+            KLDRDYLD_ASSERT(!"drop frame bad state (a)");
+            break;
+    }
+}
+
+
+/**
+ * Done with the stack frame, dereference all the modules in it.
+ *
+ * @param   iLoad1st        The start of the stack frame.
+ * @param   iLoadEnd        The end of the stack frame.
+ * @param   rc              Used for state verification.
+ */
+static void kldrDyldStackDropFrame(KU32 iLoad1st, KU32 iLoadEnd, int rc)
+{
+    KU32 i;
+    KLDRDYLD_ASSERT(iLoad1st <= g_cStackMods);
+    KLDRDYLD_ASSERT(iLoadEnd == g_cStackMods);
+
+    /*
+     * First pass: Do all the cleanups we can, but don't destroy anything just yet.
+     */
+    i = iLoadEnd;
+    while (i-- > iLoad1st)
+    {
+        PKLDRDYLDMOD pMod = g_papStackMods[i];
+        kldrDyldStackCleanupOne(pMod, rc);
+    }
+
+    /*
+     * Second pass: Release the references so modules pending destruction
+     *              can be completely removed.
+     */
+    for (i = iLoad1st; i < iLoadEnd ; i++)
+    {
+        PKLDRDYLDMOD pMod = g_papStackMods[i];
+
+        /*
+         * Revalidate the module state.
+         */
+        switch (pMod->enmState)
+        {
+            case KLDRSTATE_INITIALIZING:
+            case KLDRSTATE_TERMINATING:
+            case KLDRSTATE_PENDING_TERMINATION:
+            case KLDRSTATE_PENDING_INITIALIZATION:
+            case KLDRSTATE_PENDING_GC:
+            case KLDRSTATE_PENDING_DESTROY:
+            case KLDRSTATE_GOOD:
+                break;
+            default:
+                KLDRDYLD_ASSERT(!"drop frame bad state (b)");
+                break;
+        }
+
+        /*
+         * Release it.
+         */
+        kldrDyldModDeref(pMod);
+    }
+
+    /*
+     * Drop the stack frame.
+     */
+    g_cStackMods = iLoad1st;
+}
+
+
+/**
+ * Do garbage collection.
+ *
+ * This isn't doing anything unless it's called from the last
+ * load or unload call.
+ */
+static void kldrDyldDoModuleTerminationAndGarabageCollection(void)
+{
+    PKLDRDYLDMOD pMod;
+
+    /*
+     * We don't do anything until we're got rid of all recursive calls.
+     * This will ensure that we get the most optimal termination order and
+     * that we don't unload anything too early.
+     */
+    if (g_cActiveLoadCalls || g_cActiveUnloadCalls || g_fActiveGC)
+        return;
+    g_fActiveGC = 1;
+
+    do
+    {
+        /*
+         * 1. Release prerequisites for any left over modules.
+         */
+        for (pMod = kLdrDyldHead; pMod; pMod = pMod->Load.pNext)
+        {
+            kldrDyldModAddRef(pMod);
+
+            switch (pMod->enmState)
+            {
+                case KLDRSTATE_GOOD:
+                case KLDRSTATE_PENDING_GC:
+                case KLDRSTATE_PENDING_TERMINATION:
+                    break;
+
+                case KLDRSTATE_INITIALIZATION_FAILED: /* just in case */
+                case KLDRSTATE_PENDING_INITIALIZATION:
+                    kldrDyldModUnloadPrerequisites(pMod);
+                    break;
+
+                default:
+                    KLDRDYLD_ASSERT(!"invalid GC state (a)");
+                    break;
+            }
+
+            kldrDyldModDeref(pMod);
+        }
+
+        /*
+         * 2. Do init calls until we encounter somebody calling load/unload.
+         */
+        for (pMod = g_pkLdrDyldTermHead; pMod; pMod = pMod->InitTerm.pNext)
+        {
+            int fRestart = 0;
+            kldrDyldModAddRef(pMod);
+
+            switch (pMod->enmState)
+            {
+                case KLDRSTATE_GOOD:
+                case KLDRSTATE_PENDING_GC:
+                    break;
+
+                case KLDRSTATE_PENDING_TERMINATION:
+                {
+                    const KU32 cTotalLoadCalls = g_cTotalLoadCalls;
+                    const KU32 cTotalUnloadCalls = g_cTotalUnloadCalls;
+                    kldrDyldModCallTerm(pMod);
+                    fRestart = cTotalLoadCalls != g_cTotalLoadCalls
+                            || cTotalUnloadCalls != g_cTotalUnloadCalls;
+                    break;
+                }
+
+                default:
+                    KLDRDYLD_ASSERT(!"invalid GC state (b)");
+                    break;
+            }
+
+            kldrDyldModDeref(pMod);
+            if (fRestart)
+                break;
+        }
+    } while (pMod);
+
+    /*
+     * Unmap and destroy modules pending for GC.
+     */
+    pMod = kLdrDyldHead;
+    while (pMod)
+    {
+        PKLDRDYLDMOD pNext = pMod->Load.pNext;
+        kldrDyldModAddRef(pMod);
+
+        switch (pMod->enmState)
+        {
+            case KLDRSTATE_INITIALIZATION_FAILED:
+            case KLDRSTATE_PENDING_GC:
+                KLDRDYLD_ASSERT(!pMod->cDepRefs);
+                KLDRDYLD_ASSERT(!pMod->cDynRefs);
+                pMod->enmState = KLDRSTATE_GC;
+                kldrDyldModUnmap(pMod);
+                KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY);
+                kldrDyldModDestroy(pMod);
+                KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_DESTROYED);
+                break;
+
+            case KLDRSTATE_GOOD:
+                break;
+            default:
+                KLDRDYLD_ASSERT(!"invalid GC state (c)");
+                break;
+        }
+
+        kldrDyldModDeref(pMod);
+
+        /* next */
+        pMod = pNext;
+    }
+
+    g_fActiveGC = 0;
+}
+
+
+/**
+ * Worker for kLdrDyldUnload().
+ * @internal
+ */
+static int kldrDyldDoUnload(PKLDRDYLDMOD pMod)
+{
+    return kldrDyldModDynamicUnload(pMod);
+}
+
+
+/**
+ * Worker for kLdrDyldFindByName().
+ * @internal
+ */
+static int kldrDyldDoFindByName(const char *pszDll, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch,
+                                unsigned fFlags, PPKLDRDYLDMOD ppMod)
+{
+    return kldrDyldFindExistingModule(pszDll, pszPrefix, pszSuffix, enmSearch, fFlags, ppMod);
+}
+
+
+/**
+ * Worker for kLdrDyldFindByAddress().
+ * @internal
+ */
+static int kldrDyldDoFindByAddress(KUPTR Address, PPKLDRDYLDMOD ppMod, KU32 *piSegment, KUPTR *poffSegment)
+{
+    /* Scan the segments of each module in the load list. */
+    PKLDRDYLDMOD pMod = kLdrDyldHead;
+    while (pMod)
+    {
+        KU32 iSeg;
+        for (iSeg = 0; iSeg < pMod->pMod->cSegments; iSeg++)
+        {
+            KLDRADDR off = (KLDRADDR)Address - pMod->pMod->aSegments[iSeg].MapAddress;
+            if (off < pMod->pMod->aSegments[iSeg].cb)
+            {
+                *ppMod = pMod->hMod;
+                if (piSegment)
+                    *piSegment = iSeg;
+                if (poffSegment)
+                    *poffSegment = (KUPTR)off;
+                return 0;
+            }
+        }
+
+        /* next */
+        pMod = pMod->Load.pNext;
+    }
+
+    return KLDR_ERR_MODULE_NOT_FOUND;
+}
+
+
+/**
+ * Worker for kLdrDyldGetName().
+ * @internal
+ */
+static int kldrDyldDoGetName(PKLDRDYLDMOD pMod, char *pszName, KSIZE cchName)
+{
+    return kldrDyldModGetName(pMod, pszName, cchName);
+}
+
+
+/**
+ * Worker for kLdrDyldGetFilename().
+ * @internal
+ */
+static int kldrDyldDoGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, KSIZE cchFilename)
+{
+    return kldrDyldModGetFilename(pMod, pszFilename, cchFilename);
+}
+
+
+/**
+ * Worker for kLdrDyldQuerySymbol().
+ * @internal
+ */
+static int kldrDyldDoQuerySymbol(PKLDRDYLDMOD pMod, KU32 uSymbolOrdinal, const char *pszSymbolName, KUPTR *pValue, KU32 *pfKind)
+{
+    return kldrDyldModQuerySymbol(pMod, uSymbolOrdinal, pszSymbolName, pValue, pfKind);
+}
+
+
+/**
+ * Panic / failure
+ *
+ * @returns rc if we're in a position where we can return.
+ * @param   rc              Return code.
+ * @param   pszFormat       Message string. Limited fprintf like formatted.
+ * @param   ...             Message string arguments.
+ */
+int kldrDyldFailure(int rc, const char *pszFilename, ...)
+{
+    /** @todo print it. */
+    if (g_fBootstrapping);
+        kHlpExit(1);
+    return rc;
+}
+
+
+/**
+ * Copies the error string to the user buffer.
+ *
+ * @returns rc.
+ * @param   rc      The status code.
+ * @param   pszErr  Where to copy the error string to.
+ * @param   cchErr  The size of the destination buffer.
+ */
+static int kldrDyldCopyError(int rc, char *pszErr, KSIZE cchErr)
+{
+    KSIZE  cchToCopy;
+
+    /* if no error string, format the rc into a string. */
+    if (!g_szkLdrDyldError[0] && rc)
+        kHlpInt2Ascii(g_szkLdrDyldError, sizeof(g_szkLdrDyldError), rc, 10);
+
+    /* copy it if we got something. */
+    if (cchErr && pszErr && g_szkLdrDyldError[0])
+    {
+        cchToCopy = kHlpStrLen(g_szkLdrDyldError);
+        if (cchToCopy >= cchErr)
+            cchToCopy = cchErr - 1;
+        kHlpMemCopy(pszErr, g_szkLdrDyldError, cchToCopy);
+        pszErr[cchToCopy] = '\0';
+    }
+
+    return rc;
+}
+
diff --git a/src/lib/kStuff/kLdr/kLdrDyldFind.c b/src/lib/kStuff/kLdr/kLdrDyldFind.c
new file mode 100644
index 0000000..9d6562e
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrDyldFind.c
@@ -0,0 +1,1086 @@
+/* $Id: kLdrDyldFind.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - The Dynamic Loader, File Searching Methods.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kLdr.h>
+#include "kLdrInternal.h"
+
+#if K_OS == K_OS_LINUX
+# include <k/kHlpSys.h>
+
+#elif K_OS == K_OS_OS2
+# define INCL_BASE
+# define INCL_ERRORS
+# include <os2.h>
+# ifndef LIBPATHSTRICT
+#  define LIBPATHSTRICT 3
+# endif
+  extern APIRET APIENTRY DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction);
+# define QHINF_EXEINFO       1 /* NE exeinfo. */
+# define QHINF_READRSRCTBL   2 /* Reads from the resource table. */
+# define QHINF_READFILE      3 /* Reads from the executable file. */
+# define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */
+# define QHINF_LIBPATH       5 /* Gets the entire libpath. */
+# define QHINF_FIXENTRY      6 /* NE only */
+# define QHINF_STE           7 /* NE only */
+# define QHINF_MAPSEL        8 /* NE only */
+
+#elif K_OS == K_OS_WINDOWS
+# undef IMAGE_DOS_SIGNATURE
+# undef IMAGE_NT_SIGNATURE
+# include <Windows.h>
+
+#endif
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** @def KLDRDYLDFIND_STRICT
+ * Define KLDRDYLDFIND_STRICT to enabled strict checks in kLdrDyldFind. */
+#define KLDRDYLDFIND_STRICT 1
+
+/** @def KLDRDYLDFIND_ASSERT
+ * Assert that an expression is true when KLDRDYLDFIND_STRICT is defined.
+ */
+#ifdef KLDRDYLDFIND_STRICT
+# define KLDRDYLDFIND_ASSERT(expr)  kHlpAssert(expr)
+#else
+# define KLDRDYLDFIND_ASSERT(expr)  do {} while (0)
+#endif
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Search arguments.
+ * This avoids a bunch of unnecessary string lengths and calculations.
+ */
+typedef struct KLDRDYLDFINDARGS
+{
+    const char *pszName;
+    KSIZE       cchName;
+
+    const char *pszPrefix;
+    KSIZE       cchPrefix;
+
+    const char *pszSuffix;
+    KSIZE       cchSuffix;
+
+    KSIZE       cchMaxLength;
+
+    KLDRDYLDSEARCH  enmSearch;
+    KU32            fFlags;
+    PPKRDR          ppRdr;
+} KLDRDYLDFINDARGS, *PKLDRDYLDFINDARGS;
+
+typedef const KLDRDYLDFINDARGS *PCKLDRDYLDFINDARGS;
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** @name The kLdr search method parameters.
+ * @{ */
+/** The kLdr EXE search path.
+ * During EXE searching the it's initialized with the values of the KLDR_PATH and
+ * the PATH env.vars. Both ';' and ':' can be used as separators.
+ */
+char            kLdrDyldExePath[8192];
+/** The kLdr DLL search path.
+ * During initialization the KLDR_LIBRARY_PATH env.var. and the path in the
+ * executable stub is appended. Both ';' and ':' can be used as separators.
+ */
+char            kLdrDyldLibraryPath[8192];
+/** The kLdr application directory.
+ * This is initialized when the executable is 'loaded' or by a kLdr user.
+ */
+char            kLdrDyldAppDir[260];
+/** The default kLdr DLL prefix.
+ * This is initialized with the KLDR_DEF_PREFIX env.var. + the prefix in the executable stub.
+ */
+char            kLdrDyldDefPrefix[16];
+/** The default kLdr DLL suffix.
+ * This is initialized with the KLDR_DEF_SUFFIX env.var. + the prefix in the executable stub.
+ */
+char            kLdrDyldDefSuffix[16];
+/** @} */
+
+
+/** @name The OS/2 search method parameters.
+ * @{
+ */
+/** The OS/2 LIBPATH.
+ * This is queried from the os2krnl on OS/2, while on other systems initialized using
+ * the KLDR_OS2_LIBPATH env.var.
+ */
+char            kLdrDyldOS2Libpath[2048];
+/** The OS/2 LIBPATHSTRICT ("T" or '\0').
+ * This is queried from the os2krnl on OS/2, while on other systems initialized using
+ * the KLDR_OS2_LIBPATHSTRICT env.var.
+ */
+char            kLdrDyldOS2LibpathStrict[8];
+/** The OS/2 BEGINLIBPATH.
+ * This is queried from the os2krnl on OS/2, while on other systems initialized using
+ * the KLDR_OS2_BEGINLIBPATH env.var.
+ */
+char            kLdrDyldOS2BeginLibpath[2048];
+/** The OS/2 ENDLIBPATH.
+ * This is queried from the os2krnl on OS/2, while on other systems initialized using
+ * the KLDR_OS2_ENDLIBPATH env.var.
+ */
+char            kLdrDyldOS2EndLibpath[2048];
+/** @} */
+
+
+/** @name The Windows search method parameters.
+ * @{ */
+/** The Windows application directory.
+ * This is initialized when the executable is 'loaded' or by a kLdr user.
+ */
+char            kLdrDyldWindowsAppDir[260];
+/** The Windows system directory.
+ * This is queried from the Win32/64 subsystem on Windows, while on other systems
+ * initialized using the KLDR_WINDOWS_SYSTEM_DIR env.var.
+ */
+char            kLdrDyldWindowsSystemDir[260];
+/** The Windows directory.
+ * This is queried from the Win32/64 subsystem on Windows, while on other systems
+ * initialized using the KLDR_WINDOWS_DIR env.var.
+ */
+char            kLdrDyldWindowsDir[260];
+/** The Windows path.
+ * This is queried from the PATH env.var. on Windows, while on other systems
+ * initialized using the KLDR_WINDOWS_PATH env.var. and falling back on
+ * the PATH env.var. if it wasn't found.
+ */
+char            kLdrDyldWindowsPath[8192];
+/** @} */
+
+
+/** @name The Common Unix search method parameters.
+ * @{
+ */
+/** The Common Unix library path.
+ * Initialized from the env.var. KLDR_UNIX_LIBRARY_PATH or LD_LIBRARY_PATH or the
+ * former wasn't found.
+ */
+char            kLdrDyldUnixLibraryPath[8192];
+/** The Common Unix system library path. */
+char            kLdrDyldUnixSystemLibraryPath[1024] = "/lib;/usr/lib";
+/** @} */
+
+/** @todo Deal with DT_RUNPATH and DT_RPATH. */
+/** @todo ld.so.cache? */
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static int kldrDyldFindDoDllSearch(const char *pszName, const char *pszPrefix, const char *pszSuffix,
+                                KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKRDR ppRdr);
+static int kldrDyldFindDoExeSearch(const char *pszName, const char *pszPrefix, const char *pszSuffix,
+                                   KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKRDR ppRdr);
+static int kldrDyldFindTryOpen(const char *pszFilename, PPKRDR ppRdr);
+static int kldrDyldFindTryOpenPath(const char *pchPath, KSIZE cchPath, PCKLDRDYLDFINDARGS pArgs);
+static int kldrDyldFindEnumeratePath(const char *pszSearchPath, PCKLDRDYLDFINDARGS pArgs);
+static int kldrDyldFindGetDefaults(KLDRDYLDSEARCH *penmSearch, const char **pszPrefix,
+                                   const char **pszSuffix, const char *pszName, KU32 fFlags);
+
+
+/**
+ * Initializes the find paths.
+ *
+ * @returns 0 on success, non-zero on failure.
+ */
+int kldrDyldFindInit(void)
+{
+    KSIZE   cch;
+    int     rc;
+    char    szTmp[sizeof(kLdrDyldDefSuffix)];
+
+    /*
+     * The kLdr search parameters.
+     */
+    rc = kHlpGetEnv("KLDR_LIBRARY_PATH", kLdrDyldLibraryPath, sizeof(kLdrDyldLibraryPath));
+    rc = kHlpGetEnv("KLDR_DEF_PREFIX", szTmp, sizeof(szTmp));
+    if (!rc)
+        kHlpMemCopy(kLdrDyldDefPrefix, szTmp, sizeof(szTmp));
+    rc = kHlpGetEnv("KLDR_DEF_SUFFIX", szTmp, sizeof(szTmp));
+    if (!rc)
+        kHlpMemCopy(kLdrDyldDefSuffix, szTmp, sizeof(szTmp));
+
+    /*
+     * The OS/2 search parameters.
+     */
+#if K_OS == K_OS_OS2
+    rc = DosQueryHeaderInfo(NULLHANDLE, 0, kLdrDyldOS2Libpath, sizeof(kLdrDyldOS2Libpath), QHINF_LIBPATH);
+    if (rc)
+        return rc;
+    rc = DosQueryExtLIBPATH((PSZ)kLdrDyldOS2LibpathStrict, LIBPATHSTRICT);
+    if (rc)
+        kLdrDyldOS2LibpathStrict[0] = '\0';
+    rc = DosQueryExtLIBPATH((PSZ)kLdrDyldOS2BeginLibpath, BEGIN_LIBPATH);
+    if (rc)
+        kLdrDyldOS2BeginLibpath[0] = '\0';
+    rc = DosQueryExtLIBPATH((PSZ)kLdrDyldOS2EndLibpath, END_LIBPATH);
+    if (rc)
+        kLdrDyldOS2EndLibpath[0] = '\0';
+
+#else
+    kHlpGetEnv("KLDR_OS2_LIBPATH", kLdrDyldOS2Libpath, sizeof(kLdrDyldOS2Libpath));
+    kHlpGetEnv("KLDR_OS2_LIBPATHSTRICT", kLdrDyldOS2LibpathStrict, sizeof(kLdrDyldOS2LibpathStrict));
+    if (    kLdrDyldOS2LibpathStrict[0] == 'T'
+        ||  kLdrDyldOS2LibpathStrict[0] == 't')
+        kLdrDyldOS2LibpathStrict[0] = 'T';
+    else
+        kLdrDyldOS2LibpathStrict[0] = '\0';
+    kLdrDyldOS2LibpathStrict[1] = '\0';
+    kHlpGetEnv("KLDR_OS2_BEGINLIBPATH", kLdrDyldOS2BeginLibpath, sizeof(kLdrDyldOS2BeginLibpath));
+    kHlpGetEnv("KLDR_OS2_ENDLIBPATH", kLdrDyldOS2EndLibpath, sizeof(kLdrDyldOS2EndLibpath));
+#endif
+
+    /*
+     * The windows search parameters.
+     */
+#if K_OS == K_OS_WINDOWS
+    cch = GetSystemDirectory(kLdrDyldWindowsSystemDir, sizeof(kLdrDyldWindowsSystemDir));
+    if (cch >= sizeof(kLdrDyldWindowsSystemDir))
+        return (rc = GetLastError()) ? rc : -1;
+    cch = GetWindowsDirectory(kLdrDyldWindowsDir, sizeof(kLdrDyldWindowsDir));
+    if (cch >= sizeof(kLdrDyldWindowsDir))
+        return (rc = GetLastError()) ? rc : -1;
+    kHlpGetEnv("PATH", kLdrDyldWindowsPath, sizeof(kLdrDyldWindowsPath));
+#else
+    kHlpGetEnv("KLDR_WINDOWS_SYSTEM_DIR", kLdrDyldWindowsSystemDir, sizeof(kLdrDyldWindowsSystemDir));
+    kHlpGetEnv("KLDR_WINDOWS_DIR", kLdrDyldWindowsDir, sizeof(kLdrDyldWindowsDir));
+    rc = kHlpGetEnv("KLDR_WINDOWS_PATH", kLdrDyldWindowsPath, sizeof(kLdrDyldWindowsPath));
+    if (rc)
+        kHlpGetEnv("PATH", kLdrDyldWindowsPath, sizeof(kLdrDyldWindowsPath));
+#endif
+
+    /*
+     * The Unix search parameters.
+     */
+    rc = kHlpGetEnv("KLDR_UNIX_LIBRARY_PATH", kLdrDyldUnixLibraryPath, sizeof(kLdrDyldUnixLibraryPath));
+    if (rc)
+        kHlpGetEnv("LD_LIBRARY_PATH", kLdrDyldUnixLibraryPath, sizeof(kLdrDyldUnixLibraryPath));
+
+    (void)cch;
+    return 0;
+}
+
+
+/**
+ * Lazily initialize the two application directory paths.
+ */
+static void kldrDyldFindLazyInitAppDir(void)
+{
+    if (!kLdrDyldAppDir[0])
+    {
+#if K_OS == K_OS_DARWIN
+        /** @todo implement this! */
+        kLdrDyldWindowsAppDir[0] = kLdrDyldAppDir[0] = '.';
+        kLdrDyldWindowsAppDir[1] = kLdrDyldAppDir[1] = '\0';
+
+#elif K_OS == K_OS_LINUX
+        KSSIZE cch = kHlpSys_readlink("/proc/self/exe", kLdrDyldAppDir, sizeof(kLdrDyldAppDir) - 1);
+        if (cch > 0)
+        {
+            kLdrDyldAppDir[cch] = '\0';
+            *kHlpGetFilename(kLdrDyldAppDir) = '\0';
+            kHlpMemCopy(kLdrDyldWindowsAppDir, kLdrDyldAppDir, sizeof(kLdrDyldAppDir));
+        }
+        else
+        {
+            kLdrDyldWindowsAppDir[0] = kLdrDyldAppDir[0] = '.';
+            kLdrDyldWindowsAppDir[1] = kLdrDyldAppDir[1] = '\0';
+        }
+
+#elif K_OS == K_OS_OS2
+        PPIB pPib;
+        PTIB pTib;
+        APIRET rc;
+
+        DosGetInfoBlocks(&pTib, &pPib);
+        rc = DosQueryModuleName(pPib->pib_hmte, sizeof(kLdrDyldAppDir), kLdrDyldAppDir);
+        if (!rc)
+        {
+            *kHlpGetFilename(kLdrDyldAppDir) = '\0';
+             kHlpMemCopy(kLdrDyldWindowsAppDir, kLdrDyldAppDir, sizeof(kLdrDyldAppDir));
+        }
+        else
+        {
+            kLdrDyldWindowsAppDir[0] = kLdrDyldAppDir[0] = '.';
+            kLdrDyldWindowsAppDir[1] = kLdrDyldAppDir[1] = '\0';
+        }
+
+#elif K_OS == K_OS_WINDOWS
+        DWORD dwSize = GetModuleFileName(NULL /* the executable */, kLdrDyldAppDir, sizeof(kLdrDyldAppDir));
+        if (dwSize > 0)
+        {
+            *kHlpGetFilename(kLdrDyldAppDir) = '\0';
+            kHlpMemCopy(kLdrDyldWindowsAppDir, kLdrDyldAppDir, sizeof(kLdrDyldAppDir));
+        }
+        else
+        {
+            kLdrDyldWindowsAppDir[0] = kLdrDyldAppDir[0] = '.';
+            kLdrDyldWindowsAppDir[1] = kLdrDyldAppDir[1] = '\0';
+        }
+
+#else
+# error "Port me"
+#endif
+    }
+}
+
+
+/**
+ * Locates and opens a module using the specified search method.
+ *
+ * @returns 0 and *ppMod on success, non-zero OS specific error on failure.
+ *
+ * @param   pszName         Partial or complete name, it's specific to the search method to determin which.
+ * @param   pszPrefix       Prefix than can be used when searching.
+ * @param   pszSuffix       Suffix than can be used when searching.
+ * @param   enmSearch       The file search method to apply.
+ * @param   fFlags          Search flags.
+ * @param   ppMod           Where to store the file provider instance on success.
+ */
+int kldrDyldFindNewModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
+                          KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod)
+{
+    int rc;
+    PKRDR pRdr = NULL;
+
+    *ppMod = NULL;
+
+    /*
+     * If this isn't just a filename, we the caller has specified a file
+     * that should be opened directly and not a module name to be searched for.
+     */
+    if (!kHlpIsFilenameOnly(pszName))
+        rc = kldrDyldFindTryOpen(pszName, &pRdr);
+    else if (!(fFlags & KLDRDYLD_LOAD_FLAGS_EXECUTABLE))
+        rc = kldrDyldFindDoDllSearch(pszName, pszPrefix, pszSuffix, enmSearch, fFlags, &pRdr);
+    else
+        rc = kldrDyldFindDoExeSearch(pszName, pszPrefix, pszSuffix, enmSearch, fFlags, &pRdr);
+    if (!rc)
+    {
+#ifdef KLDRDYLDFIND_STRICT
+        /* Sanity check of kldrDyldFindExistingModule. */
+        if (fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE)
+        {
+            const char     *pszFilename = kRdrName(pRdr);
+            const KSIZE     cchFilename = kHlpStrLen(pszFilename);
+            PKLDRDYLDMOD    pCur;
+            for (pCur = kLdrDyldHead; pCur; pCur = pCur->Load.pNext)
+                KLDRDYLDFIND_ASSERT(    pCur->pMod->cchFilename != cchFilename
+                                    ||  kHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename));
+        }
+#endif
+
+        /*
+         * Check for matching non-global modules that should be promoted.
+         */
+        if (!(fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE))
+        {
+            const char     *pszFilename = kRdrName(pRdr);
+            const KSIZE     cchFilename = kHlpStrLen(pszFilename);
+            PKLDRDYLDMOD    pCur;
+            for (pCur = kLdrDyldHead; pCur; pCur = pCur->Load.pNext)
+            {
+                if (    !pCur->fGlobalOrSpecific
+                    &&  pCur->pMod->cchFilename == cchFilename
+                    &&  !kHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename))
+                {
+                    kRdrClose(pRdr);
+                    kldrDyldModMarkGlobal(pCur);
+                    *ppMod = pCur;
+                    return 0;
+                }
+                KLDRDYLDFIND_ASSERT(    pCur->pMod->cchFilename != cchFilename
+                                    ||  kHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename));
+            }
+        }
+
+        /*
+         * Create a new module.
+         */
+        rc = kldrDyldModCreate(pRdr, fFlags, ppMod);
+        if (rc)
+            kRdrClose(pRdr);
+    }
+    return rc;
+}
+
+
+/**
+ * Searches for a DLL file using the specified method.
+ *
+ * @returns 0 on success and *ppMod pointing to the new module.
+ * @returns KLDR_ERR_MODULE_NOT_FOUND if the specified file couldn't be opened.
+ * @returns non-zero kLdr or OS specific status code on other failures.
+ * @param   pszName     The name.
+ * @param   pszPrefix   The prefix, optional.
+ * @param   pszSuffix   The suffix, optional.
+ * @param   enmSearch   The search method.
+ * @param   fFlags      The load/search flags.
+ * @param   ppRdr       Where to store the pointer to the file provider instance on success.
+ */
+static int kldrDyldFindDoDllSearch(const char *pszName, const char *pszPrefix, const char *pszSuffix,
+                                   KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKRDR ppRdr)
+{
+    int rc;
+    KLDRDYLDFINDARGS Args;
+
+    /*
+     * Initialize the argument structure and resolve defaults.
+     */
+    Args.enmSearch = enmSearch;
+    Args.pszPrefix = pszPrefix;
+    Args.pszSuffix = pszSuffix;
+    rc = kldrDyldFindGetDefaults(&Args.enmSearch, &Args.pszPrefix, &Args.pszSuffix, pszName, fFlags);
+    if (rc)
+        return rc;
+    Args.pszName = pszName;
+    Args.cchName = kHlpStrLen(pszName);
+    Args.cchPrefix = Args.pszPrefix ? kHlpStrLen(Args.pszPrefix) : 0;
+    Args.cchSuffix = Args.pszSuffix ? kHlpStrLen(Args.pszSuffix) : 0;
+    Args.cchMaxLength = Args.cchName + Args.cchSuffix + Args.cchPrefix;
+    Args.fFlags = fFlags;
+    Args.ppRdr = ppRdr;
+
+    /*
+     * Apply the specified search method.
+     */
+/** @todo get rid of the strlen() on the various paths here! */
+    switch (Args.enmSearch)
+    {
+        case KLDRDYLD_SEARCH_KLDR:
+        {
+            kldrDyldFindLazyInitAppDir();
+            if (kLdrDyldAppDir[0] != '\0')
+            {
+                rc = kldrDyldFindTryOpenPath(kLdrDyldAppDir, kHlpStrLen(kLdrDyldAppDir), &Args);
+                if (rc != KLDR_ERR_MODULE_NOT_FOUND)
+                    break;
+            }
+            rc = kldrDyldFindTryOpenPath(".", 1, &Args);
+            if (rc != KLDR_ERR_MODULE_NOT_FOUND)
+                break;
+            rc = kldrDyldFindEnumeratePath(kLdrDyldLibraryPath, &Args);
+            break;
+        }
+
+        case KLDRDYLD_SEARCH_OS2:
+        {
+            rc = kldrDyldFindEnumeratePath(kLdrDyldOS2BeginLibpath, &Args);
+            if (rc != KLDR_ERR_MODULE_NOT_FOUND)
+                break;
+            rc = kldrDyldFindEnumeratePath(kLdrDyldOS2Libpath, &Args);
+            if (rc != KLDR_ERR_MODULE_NOT_FOUND)
+                break;
+            rc = kldrDyldFindEnumeratePath(kLdrDyldOS2EndLibpath, &Args);
+            break;
+        }
+
+        case KLDRDYLD_SEARCH_WINDOWS:
+        case KLDRDYLD_SEARCH_WINDOWS_ALTERED:
+        {
+            kldrDyldFindLazyInitAppDir();
+            rc = kldrDyldFindTryOpenPath(kLdrDyldWindowsAppDir, kHlpStrLen(kLdrDyldWindowsAppDir), &Args);
+            if (rc != KLDR_ERR_MODULE_NOT_FOUND)
+                break;
+            if (Args.enmSearch == KLDRDYLD_SEARCH_WINDOWS_ALTERED)
+            {
+                rc = kldrDyldFindTryOpenPath(".", 1, &Args);
+                if (rc != KLDR_ERR_MODULE_NOT_FOUND)
+                    break;
+            }
+            rc = kldrDyldFindTryOpenPath(kLdrDyldWindowsSystemDir, kHlpStrLen(kLdrDyldWindowsSystemDir), &Args);
+            if (rc != KLDR_ERR_MODULE_NOT_FOUND)
+                break;
+            rc = kldrDyldFindTryOpenPath(kLdrDyldWindowsDir, kHlpStrLen(kLdrDyldWindowsDir), &Args);
+            if (rc != KLDR_ERR_MODULE_NOT_FOUND)
+                break;
+            if (Args.enmSearch == KLDRDYLD_SEARCH_WINDOWS)
+            {
+                rc = kldrDyldFindTryOpenPath(".", 1, &Args);
+                if (rc != KLDR_ERR_MODULE_NOT_FOUND)
+                    break;
+            }
+            rc = kldrDyldFindEnumeratePath(kLdrDyldWindowsPath, &Args);
+            break;
+        }
+
+        case KLDRDYLD_SEARCH_UNIX_COMMON:
+        {
+            rc = kldrDyldFindEnumeratePath(kLdrDyldUnixLibraryPath, &Args);
+            if (rc == KLDR_ERR_MODULE_NOT_FOUND)
+                break;
+            rc = kldrDyldFindEnumeratePath(kLdrDyldUnixSystemLibraryPath, &Args);
+            break;
+        }
+
+        default: kHlpAssert(!"internal error"); return -1;
+    }
+    return rc;
+}
+
+
+/**
+ * Searches for an EXE file using the specified method.
+ *
+ * @returns 0 on success and *ppMod pointing to the new module.
+ * @returns KLDR_ERR_MODULE_NOT_FOUND if the specified file couldn't be opened.
+ * @returns non-zero kLdr or OS specific status code on other failures.
+ * @param   pszName     The name.
+ * @param   pszPrefix   The prefix, optional.
+ * @param   pszSuffix   The suffix, optional.
+ * @param   enmSearch   The search method.
+ * @param   fFlags      The load/search flags.
+ * @param   ppRdr       Where to store the pointer to the file provider instance on success.
+ */
+static int kldrDyldFindDoExeSearch(const char *pszName, const char *pszPrefix, const char *pszSuffix,
+                                   KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKRDR ppRdr)
+{
+    int rc;
+    KLDRDYLDFINDARGS Args;
+
+    /*
+     * Initialize the argument structure and resolve defaults.
+     */
+    Args.enmSearch = enmSearch;
+    Args.pszPrefix = pszPrefix;
+    Args.pszSuffix = pszSuffix;
+    rc = kldrDyldFindGetDefaults(&Args.enmSearch, &Args.pszPrefix, &Args.pszSuffix, pszName, fFlags);
+    if (rc)
+        return rc;
+    Args.pszName = pszName;
+    Args.cchName = kHlpStrLen(pszName);
+    Args.cchPrefix = Args.pszPrefix ? kHlpStrLen(Args.pszPrefix) : 0;
+    Args.cchSuffix = Args.pszSuffix ? kHlpStrLen(Args.pszSuffix) : 0;
+    Args.cchMaxLength = Args.cchName + Args.cchSuffix + Args.cchPrefix;
+    Args.fFlags = fFlags;
+    Args.ppRdr = ppRdr;
+
+    /*
+     * If we're bootstrapping a process, we'll start by looking in the
+     * application directory and the check out the path.
+     */
+    if (g_fBootstrapping)
+    {
+        kldrDyldFindLazyInitAppDir();
+        if (kLdrDyldAppDir[0] != '\0')
+        {
+            rc = kldrDyldFindTryOpenPath(kLdrDyldAppDir, kHlpStrLen(kLdrDyldAppDir), &Args);
+            if (rc != KLDR_ERR_MODULE_NOT_FOUND)
+                return rc;
+        }
+    }
+
+    /*
+     * Search the EXE search path. Initialize it the first time around.
+     */
+    if (!kLdrDyldExePath[0])
+    {
+        KSIZE cch;
+        kHlpGetEnv("KLDR_EXE_PATH", kLdrDyldExePath, sizeof(kLdrDyldExePath) - 10);
+        cch = kHlpStrLen(kLdrDyldExePath);
+        kLdrDyldExePath[cch++] = ';';
+        kHlpGetEnv("PATH", &kLdrDyldExePath[cch], sizeof(kLdrDyldExePath) - cch);
+    }
+    return kldrDyldFindEnumeratePath(kLdrDyldExePath, &Args);
+}
+
+
+/**
+ * Try open the specfied file.
+ *
+ * @returns 0 on success and *ppMod pointing to the new module.
+ * @returns KLDR_ERR_MODULE_NOT_FOUND if the specified file couldn't be opened.
+ * @returns non-zero kLdr or OS specific status code on other failures.
+ * @param   pszFilename     The filename.
+ * @param   ppRdr           Where to store the pointer to the new module.
+ */
+static int kldrDyldFindTryOpen(const char *pszFilename, PPKRDR ppRdr)
+{
+    int rc;
+
+    /*
+     * Try open the file.
+     */
+    rc = kRdrOpen(ppRdr, pszFilename);
+    if (!rc)
+        return 0;
+    /** @todo deal with return codes properly. */
+    if (rc >= KERR_BASE && rc <= KERR_END)
+        return rc;
+
+    return KLDR_ERR_MODULE_NOT_FOUND;
+}
+
+
+/**
+ * Composes a filename from the specified directory path,
+ * prefix (optional), name and suffix (optional, will try with and without).
+ *
+ * @param   pchPath     The directory path - this doesn't have to be null terminated.
+ * @param   cchPath     The length of the path.
+ * @param   pArgs       The search argument structure.
+ *
+ * @returns See kldrDyldFindTryOpen
+ */
+static int kldrDyldFindTryOpenPath(const char *pchPath, KSIZE cchPath, PCKLDRDYLDFINDARGS pArgs)
+{
+    static char s_szFilename[1024];
+    char *psz;
+    int rc;
+
+    /*
+     * Ignore any attempts at opening empty paths.
+     * This can happen when a *Dir globals is empty.
+     */
+    if (!cchPath)
+        return KLDR_ERR_MODULE_NOT_FOUND; /* ignore */
+
+    /*
+     * Limit check first.
+     */
+    if (cchPath + 1 + pArgs->cchMaxLength >= sizeof(s_szFilename))
+    {
+        KLDRDYLDFIND_ASSERT(!"too long");
+        return KLDR_ERR_MODULE_NOT_FOUND; /* ignore */
+    }
+
+    /*
+     * The directory path.
+     */
+    kHlpMemCopy(s_szFilename, pchPath, cchPath);
+    psz = &s_szFilename[cchPath];
+    if (psz[-1] != '/'
+#if K_OS == K_OS_OS2 || K_OS == K_OS_WINDOWS
+        && psz[-1] != '\\'
+        && psz[-1] != ':'
+#endif
+        )
+        *psz++ = '/';
+
+    /*
+     * The name.
+     */
+    if (pArgs->cchPrefix)
+    {
+        kHlpMemCopy(psz, pArgs->pszPrefix, pArgs->cchPrefix);
+        psz += pArgs->cchPrefix;
+    }
+    kHlpMemCopy(psz, pArgs->pszName, pArgs->cchName);
+    psz += pArgs->cchName;
+    if (pArgs->cchSuffix)
+    {
+        kHlpMemCopy(psz, pArgs->pszSuffix, pArgs->cchSuffix);
+        psz += pArgs->cchSuffix;
+    }
+    *psz = '\0';
+
+
+    /*
+     * Try open it.
+     */
+    rc = kldrDyldFindTryOpen(s_szFilename, pArgs->ppRdr);
+    /* If we're opening an executable, try again without the suffix.*/
+    if (    rc
+        &&  pArgs->cchSuffix
+        &&  (pArgs->fFlags & KLDRDYLD_LOAD_FLAGS_EXECUTABLE))
+    {
+        psz -= pArgs->cchSuffix;
+        *psz = '\0';
+        rc = kldrDyldFindTryOpen(s_szFilename, pArgs->ppRdr);
+    }
+    return rc;
+}
+
+
+/**
+ * Enumerates the specfied path.
+ *
+ * @returns Any return code from the kldrDyldFindTryOpenPath() which isn't KLDR_ERR_MODULE_NOT_FOUND.
+ * @returns KLDR_ERR_MODULE_NOT_FOUND if the end of the search path was reached.
+ * @param   pszSearchPath   The search path to enumeare.
+ * @param   pArgs       The search argument structure.
+ */
+static int kldrDyldFindEnumeratePath(const char *pszSearchPath, PCKLDRDYLDFINDARGS pArgs)
+{
+    const char *psz = pszSearchPath;
+    for (;;)
+    {
+        const char *pszEnd;
+        KSIZE       cchPath;
+
+        /*
+         * Trim.
+         */
+        while (*psz == ';' || *psz == ':')
+            psz++;
+        if (*psz == '\0')
+            return KLDR_ERR_MODULE_NOT_FOUND;
+
+        /*
+         * Find the end.
+         */
+        pszEnd = psz + 1;
+        while (     *pszEnd != '\0'
+               &&   *pszEnd != ';'
+#if K_OS == K_OS_OS2 || K_OS == K_OS_WINDOWS
+               && (     *pszEnd != ':'
+                   ||   (   pszEnd - psz == 1
+                         && (   (*psz >= 'A' && *psz <= 'Z')
+                             || (*psz >= 'a' && *psz <= 'z')
+                            )
+                        )
+                  )
+#else
+               && *pszEnd != ':'
+#endif
+              )
+            pszEnd++;
+
+        /*
+         * If not empty path, try open the module using it.
+         */
+        cchPath = pszEnd - psz;
+        if (cchPath > 0)
+        {
+            int rc;
+            rc = kldrDyldFindTryOpenPath(psz, cchPath, pArgs);
+            if (rc != KLDR_ERR_MODULE_NOT_FOUND)
+                return rc;
+        }
+
+        /* next */
+        psz = pszEnd;
+    }
+}
+
+
+/**
+ * Resolve default search method, prefix and suffix.
+ *
+ * @returns 0 on success, KERR_INVALID_PARAMETER on failure.
+ * @param   penmSearch  The search method. In/Out.
+ * @param   ppszPrefix  The prefix. In/Out.
+ * @param   ppszSuffix  The suffix. In/Out.
+ * @param   pszName     The name. In.
+ * @param   fFlags      The load/search flags.
+ */
+static int kldrDyldFindGetDefaults(KLDRDYLDSEARCH *penmSearch, const char **ppszPrefix, const char **ppszSuffix,
+                                   const char *pszName, KU32 fFlags)
+{
+    unsigned fCaseSensitive;
+
+    /*
+     * Fixup search method alias.
+     */
+    if (*penmSearch == KLDRDYLD_SEARCH_HOST)
+#if K_OS == K_OS_DARWIN
+        /** @todo *penmSearch = KLDRDYLD_SEARCH_DARWIN; */
+        *penmSearch = KLDRDYLD_SEARCH_UNIX_COMMON;
+#elif K_OS == K_OS_FREEBSD \
+   || K_OS == K_OS_LINUX \
+   || K_OS == K_OS_NETBSD \
+   || K_OS == K_OS_OPENBSD \
+   || K_OS == K_OS_SOLARIS
+        *penmSearch = KLDRDYLD_SEARCH_UNIX_COMMON;
+#elif K_OS == K_OS_OS2
+        *penmSearch = KLDRDYLD_SEARCH_OS2;
+#elif K_OS == K_OS_WINDOWS
+        *penmSearch = KLDRDYLD_SEARCH_WINDOWS;
+#else
+# error "Port me"
+#endif
+
+    /*
+     * Apply search method specific prefix/suffix.
+     */
+    switch (*penmSearch)
+    {
+        case KLDRDYLD_SEARCH_KLDR:
+            if (!*ppszPrefix && kLdrDyldDefPrefix[0])
+                *ppszPrefix = kLdrDyldDefPrefix;
+            if (!*ppszSuffix && kLdrDyldDefSuffix[0])
+                *ppszSuffix = kLdrDyldDefSuffix;
+            fCaseSensitive = 1;
+            break;
+
+        case KLDRDYLD_SEARCH_OS2:
+            if (!*ppszSuffix)
+                *ppszSuffix = !(fFlags & KLDRDYLD_LOAD_FLAGS_EXECUTABLE) ? ".dll" : ".exe";
+            fCaseSensitive = 0;
+            break;
+
+        case KLDRDYLD_SEARCH_WINDOWS:
+        case KLDRDYLD_SEARCH_WINDOWS_ALTERED:
+            if (!*ppszSuffix)
+                *ppszSuffix = !(fFlags & KLDRDYLD_LOAD_FLAGS_EXECUTABLE) ? ".dll" : ".exe";
+            fCaseSensitive = 0;
+            break;
+
+        case KLDRDYLD_SEARCH_UNIX_COMMON:
+            fCaseSensitive = 1;
+            break;
+
+        default:
+            KLDRDYLDFIND_ASSERT(!"invalid search method");
+            return KERR_INVALID_PARAMETER;
+    }
+
+    /*
+     * Drop the suffix if it's already included in the name.
+     */
+    if (*ppszSuffix)
+    {
+        const KSIZE cchName = kHlpStrLen(pszName);
+        const KSIZE cchSuffix = kHlpStrLen(*ppszSuffix);
+        if (    cchName > cchSuffix
+            &&  (   fCaseSensitive
+                 ?  !kHlpMemComp(pszName + cchName - cchSuffix, *ppszSuffix, cchSuffix)
+                 :  !kHlpMemICompAscii(pszName + cchName - cchSuffix, *ppszSuffix, cchSuffix))
+           )
+            *ppszSuffix = NULL;
+    }
+
+    return 0;
+}
+
+
+/**
+ * Locates an already open module using the specified search method.
+ *
+ * @returns 0 and *ppMod on success, non-zero OS specific error on failure.
+ *
+ * @param   pszName         Partial or complete name, it's specific to the search method to determin which.
+ * @param   pszPrefix       Prefix than can be used when searching.
+ * @param   pszSuffix       Suffix than can be used when searching.
+ * @param   enmSearch       The file search method to apply.
+ * @param   fFlags          Search flags.
+ * @param   ppMod           Where to store the file provider instance on success.
+ */
+int kldrDyldFindExistingModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
+                               KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod)
+{
+
+    int rc;
+    unsigned fOS2LibpathStrict;
+    *ppMod = NULL;
+
+    /*
+     * Don't bother if no modules are loaded yet.
+     */
+    if (!kLdrDyldHead)
+        return KLDR_ERR_MODULE_NOT_FOUND;
+
+    /*
+     * Defaults.
+     */
+    rc = kldrDyldFindGetDefaults(&enmSearch, &pszPrefix, &pszSuffix, pszName, fFlags);
+    if (rc)
+        return rc;
+
+    /*
+     * If this isn't just a filename, the caller has specified a file
+     * that should be opened directly and not a module name to be searched for.
+     *
+     * In order to do the right thing we'll have to open the file and get the
+     * correct filename for it.
+     *
+     * The OS/2 libpath strict method require us to find the correct DLL first.
+     */
+    fOS2LibpathStrict = 0;
+    if (    !kHlpIsFilenameOnly(pszName)
+        ||  (fOS2LibpathStrict = (   enmSearch == KLDRDYLD_SEARCH_OS2
+                                  && kLdrDyldOS2LibpathStrict[0] == 'T')
+            )
+       )
+    {
+        PKRDR pRdr;
+        if (fOS2LibpathStrict)
+            rc = kldrDyldFindDoDllSearch(pszName, pszPrefix, pszSuffix, enmSearch, fFlags, &pRdr);
+        else
+            rc = kldrDyldFindTryOpen(pszName, &pRdr);
+        if (!rc)
+        {
+            /* do a filename based search. */
+            const char     *pszFilename = kRdrName(pRdr);
+            const KSIZE     cchFilename = kHlpStrLen(pszFilename);
+            PKLDRDYLDMOD    pCur;
+            rc = KLDR_ERR_MODULE_NOT_FOUND;
+            for (pCur = kLdrDyldHead; pCur; pCur = pCur->Load.pNext)
+            {
+                if (    pCur->pMod->cchFilename == cchFilename
+                    &&  !kHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename))
+                {
+                    *ppMod = pCur;
+                    rc = 0;
+                    break;
+                }
+            }
+            kRdrClose(pRdr);
+        }
+    }
+    else
+    {
+        const KSIZE     cchName = kHlpStrLen(pszName);
+        const KSIZE     cchPrefix = pszPrefix ? kHlpStrLen(pszPrefix) : 0;
+        const KSIZE     cchSuffix = pszSuffix ? kHlpStrLen(pszSuffix) : 0;
+        const char     *pszNameSuffix = kHlpGetSuff(pszName);
+        PKLDRDYLDMOD    pCur = kLdrDyldHead;
+
+        /*
+         * Some of the methods are case insensitive (ASCII), others are case sensitive.
+         * To avoid having todo indirect calls to the compare functions here, we split
+         * ways even if it means a lot of duplicate code.
+         */
+        if (   enmSearch == KLDRDYLD_SEARCH_OS2
+            || enmSearch == KLDRDYLD_SEARCH_WINDOWS
+            || enmSearch == KLDRDYLD_SEARCH_WINDOWS_ALTERED)
+        {
+            const unsigned fNameHasSuffix = pszNameSuffix
+                                         && kHlpStrLen(pszNameSuffix) == cchSuffix
+                                         && !kHlpMemICompAscii(pszNameSuffix, pszName + cchName - cchSuffix, cchSuffix);
+            for (; pCur; pCur = pCur->Load.pNext)
+            {
+                /* match global / specific */
+                if (    !pCur->fGlobalOrSpecific
+                    &&  !(fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE))
+                    continue;
+
+                /* match name */
+                if (    pCur->pMod->cchName == cchName
+                    &&  !kHlpMemICompAscii(pCur->pMod->pszName, pszName, cchName))
+                    break;
+                if (cchPrefix)
+                {
+                    if (    pCur->pMod->cchName == cchName + cchPrefix
+                        &&  !kHlpMemICompAscii(pCur->pMod->pszName, pszPrefix, cchPrefix)
+                        &&  !kHlpMemICompAscii(pCur->pMod->pszName + cchPrefix, pszName, cchName))
+                    break;
+                }
+                if (cchSuffix)
+                {
+                    if (    pCur->pMod->cchName == cchName + cchSuffix
+                        &&  !kHlpMemICompAscii(pCur->pMod->pszName + cchName, pszSuffix, cchSuffix)
+                        &&  !kHlpMemICompAscii(pCur->pMod->pszName, pszName, cchName))
+                    break;
+                    if (    fNameHasSuffix
+                        &&  pCur->pMod->cchName == cchName - cchSuffix
+                        &&  !kHlpMemICompAscii(pCur->pMod->pszName, pszName, cchName - cchSuffix))
+                    break;
+                    if (cchPrefix)
+                    {
+                        if (    pCur->pMod->cchName == cchName + cchPrefix + cchSuffix
+                            &&  !kHlpMemICompAscii(pCur->pMod->pszName, pszPrefix, cchPrefix)
+                            &&  !kHlpMemICompAscii(pCur->pMod->pszName + cchPrefix, pszName, cchName)
+                            &&  !kHlpMemICompAscii(pCur->pMod->pszName + cchPrefix + cchName, pszSuffix, cchSuffix))
+                        break;
+                        if (    fNameHasSuffix
+                            &&  pCur->pMod->cchName == cchName + cchPrefix - cchSuffix
+                            &&  !kHlpMemICompAscii(pCur->pMod->pszName, pszPrefix, cchPrefix)
+                            &&  !kHlpMemICompAscii(pCur->pMod->pszName + cchPrefix, pszName, cchName - cchSuffix))
+                        break;
+                    }
+                }
+            }
+        }
+        else
+        {
+            const unsigned fNameHasSuffix = pszNameSuffix
+                                         && kHlpStrLen(pszNameSuffix) == cchSuffix
+                                         && kHlpMemComp(pszNameSuffix, pszName + cchName - cchSuffix, cchSuffix);
+            for (; pCur; pCur = pCur->Load.pNext)
+            {
+                /* match global / specific */
+                if (    !pCur->fGlobalOrSpecific
+                    &&  !(fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE))
+                    continue;
+
+                /* match name */
+                if (    pCur->pMod->cchName == cchName
+                    &&  !kHlpMemComp(pCur->pMod->pszName, pszName, cchName))
+                    break;
+                if (cchPrefix)
+                {
+                    if (    pCur->pMod->cchName == cchName + cchPrefix
+                        &&  !kHlpMemComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
+                        &&  !kHlpMemComp(pCur->pMod->pszName + cchPrefix, pszName, cchName))
+                    break;
+                }
+                if (cchSuffix)
+                {
+                    if (    pCur->pMod->cchName == cchName + cchSuffix
+                        &&  !kHlpMemComp(pCur->pMod->pszName + cchName, pszSuffix, cchSuffix)
+                        &&  !kHlpMemComp(pCur->pMod->pszName, pszName, cchName))
+                    break;
+                    if (    fNameHasSuffix
+                        &&  pCur->pMod->cchName == cchName - cchSuffix
+                        &&  !kHlpMemComp(pCur->pMod->pszName, pszName, cchName - cchSuffix))
+                    break;
+                    if (cchPrefix)
+                    {
+                        if (    pCur->pMod->cchName == cchName + cchPrefix + cchSuffix
+                            &&  !kHlpMemComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
+                            &&  !kHlpMemComp(pCur->pMod->pszName + cchPrefix, pszName, cchName)
+                            &&  !kHlpMemComp(pCur->pMod->pszName + cchPrefix + cchName, pszSuffix, cchSuffix))
+                        break;
+                        if (    pCur->pMod->cchName == cchName + cchPrefix - cchSuffix
+                            &&  !kHlpMemComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
+                            &&  !kHlpMemComp(pCur->pMod->pszName + cchPrefix, pszName, cchName - cchSuffix))
+                        break;
+                    }
+                }
+            }
+        }
+
+        /* search result. */
+        if (pCur)
+        {
+            *ppMod = pCur;
+            rc = 0;
+        }
+        else
+            rc = KLDR_ERR_MODULE_NOT_FOUND;
+    }
+
+    return rc;
+}
+
diff --git a/src/lib/kStuff/kLdr/kLdrDyldMod.c b/src/lib/kStuff/kLdr/kLdrDyldMod.c
new file mode 100644
index 0000000..b25f6fc
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrDyldMod.c
@@ -0,0 +1,1300 @@
+/* $Id: kLdrDyldMod.c 81 2016-08-18 22:10:38Z bird $ */
+/** @file
+ * kLdr - The Dynamic Loader, Dyld module methods.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kLdr.h>
+#include "kLdrInternal.h"
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** @def KLDRDYLDMOD_STRICT
+ * Define KLDRDYLDMOD_STRICT to enabled strict checks in kLdrDyld. */
+#define KLDRDYLDMOD_STRICT 1
+
+/** @def KLDRDYLDMOD_ASSERT
+ * Assert that an expression is true when KLDRDYLD_STRICT is defined.
+ */
+#ifdef KLDRDYLDMOD_STRICT
+# define KLDRDYLDMOD_ASSERT(expr)  kHlpAssert(expr)
+#else
+# define KLDRDYLDMOD_ASSERT(expr)  do {} while (0)
+#endif
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static void kldrDyldModUnlink(PKLDRDYLDMOD pMod);
+
+
+
+/**
+ * Creates a module from the specified file provider instance.
+ *
+ * @returns 0 on success and *ppMod pointing to the new instance.
+ *          On failure a non-zero kLdr status code is returned.
+ * @param   pRdr    The file provider instance.
+ * @param   fFlags  Load/search flags.
+ * @param   ppMod   Where to put the pointer to the new module on success.
+ */
+int kldrDyldModCreate(PKRDR pRdr, KU32 fFlags, PPKLDRDYLDMOD ppMod)
+{
+    PKLDRDYLDMOD pMod;
+    PKLDRMOD pRawMod;
+    int rc;
+
+    *ppMod = NULL;
+
+/** @todo deal with fFlags (exec/dll) */
+/** @todo Check up the cpu architecture. */
+
+    /*
+     * Try open an module interpreter.
+     */
+    rc = kLdrModOpenFromRdr(pRdr, 0 /*fFlags*/, KCPUARCH_UNKNOWN, &pRawMod);
+    if (rc)
+        return kldrDyldFailure(rc, "%s: %rc", kRdrName(pRdr), rc);
+
+    /*
+     * Match the module aginst the load flags.
+     */
+    switch (pRawMod->enmType)
+    {
+        case KLDRTYPE_EXECUTABLE_FIXED:
+        case KLDRTYPE_EXECUTABLE_RELOCATABLE:
+        case KLDRTYPE_EXECUTABLE_PIC:
+            if (!(fFlags & KLDRDYLD_LOAD_FLAGS_EXECUTABLE))
+            {
+                kLdrModClose(pRawMod);
+                return KLDR_ERR_NOT_EXE;
+            }
+            break;
+
+        case KLDRTYPE_OBJECT: /* We can handle these as DLLs. */
+        case KLDRTYPE_SHARED_LIBRARY_FIXED:
+        case KLDRTYPE_SHARED_LIBRARY_RELOCATABLE:
+        case KLDRTYPE_SHARED_LIBRARY_PIC:
+        case KLDRTYPE_FORWARDER_DLL:
+            if (fFlags & KLDRDYLD_LOAD_FLAGS_EXECUTABLE)
+            {
+                kLdrModClose(pRawMod);
+                return KLDR_ERR_NOT_DLL;
+            }
+            break;
+
+        default:
+            KLDRDYLDMOD_ASSERT(!"Bad enmType!");
+        case KLDRTYPE_CORE:
+            return fFlags & KLDRDYLD_LOAD_FLAGS_EXECUTABLE ? KLDR_ERR_NOT_EXE : KLDR_ERR_NOT_DLL;
+    }
+
+    /*
+     * Allocate a new dyld module.
+     */
+    pMod = (PKLDRDYLDMOD)kHlpAlloc(sizeof(*pMod));
+    if (pMod)
+    {
+        pMod->enmState = KLDRSTATE_OPEN;
+        pMod->pMod = pRawMod;
+        pMod->hMod = pMod;
+        pMod->cDepRefs = pMod->cDynRefs = pMod->cRefs = 0;
+        switch (pRawMod->enmType)
+        {
+            case KLDRTYPE_EXECUTABLE_FIXED:
+            case KLDRTYPE_EXECUTABLE_RELOCATABLE:
+            case KLDRTYPE_EXECUTABLE_PIC:
+                pMod->fExecutable = 1;
+                break;
+            default:
+                pMod->fExecutable = 0;
+                break;
+        }
+        pMod->fGlobalOrSpecific = 0;
+        pMod->fBindable = 0;
+        pMod->fInitList = 0;
+        pMod->fAlreadySeen = 0;
+        pMod->fMapped = 0;
+        pMod->fAllocatedTLS = 0;
+        pMod->f25Reserved = 0;
+        pMod->InitTerm.pNext = NULL;
+        pMod->InitTerm.pPrev = NULL;
+        pMod->Bind.pNext = NULL;
+        pMod->Bind.pPrev = NULL;
+        pMod->cPrereqs = 0;
+        pMod->papPrereqs = NULL;
+        pMod->u32MagicHead = KLDRDYMOD_MAGIC;
+        pMod->u32MagicTail = KLDRDYMOD_MAGIC;
+
+        /* it. */
+        pMod->Load.pNext = NULL;
+        pMod->Load.pPrev = kLdrDyldTail;
+        if (kLdrDyldTail)
+            kLdrDyldTail->Load.pNext = pMod;
+        else
+            kLdrDyldHead = pMod;
+        kLdrDyldTail = pMod;
+
+        /* deal with the remaining flags. */
+        if (fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE)
+            kldrDyldModMarkSpecific(pMod);
+        else
+            kldrDyldModMarkGlobal(pMod);
+
+        if (fFlags & KLDRYDLD_LOAD_FLAGS_GLOBAL_SYMBOLS)
+            kldrDyldModSetBindable(pMod, 0 /* not deep binable */);
+        else
+            kldrDyldModClearBindable(pMod);
+
+        /*
+         * We're good.
+         */
+        *ppMod = pMod;
+        rc = 0;
+    }
+    else
+    {
+        kLdrModClose(pRawMod);
+        rc = KERR_NO_MEMORY;
+    }
+    return rc;
+}
+
+
+/**
+ * Creates a module for a native module.
+ *
+ * @returns 0 on success and *ppMod pointing to the new instance.
+ *          On failure a non-zero kLdr status code is returned.
+ * @param   hNativeModule   The native handle.
+ * @param   ppMod           Where to put the pointer to the new module on success.
+ * @remark  This function ain't finalized yet.
+ */
+int kldrDyldModCreateNative(KUPTR hNativeModule)
+{
+#if 0
+    /*
+     * Check if this module is already loaded by the native OS loader.
+     */
+    rc = kld
+    {
+#if K_OS == K_OS_OS2
+    HMODULE hmod = NULLHANDLE;
+    APIRET rc = DosQueryModuleHandle(kRdrName(pRdr), &hmod);
+    if (!rc)
+
+#elif K_OS == K_OS_WINDOWS
+    HMODULE hmod = NULL;
+    if (GetModuleHandle(kRdrName(pRdr))
+
+#else
+# error "Port me"
+#endif
+    }
+#endif
+    return -1;
+}
+
+
+/**
+ * Destroys a module pending destruction.
+ *
+ * @param   pMod        The module in question.
+ */
+void kldrDyldModDestroy(PKLDRDYLDMOD pMod)
+{
+    int rc;
+
+    /*
+     * Validate the state.
+     */
+    switch (pMod->enmState)
+    {
+        case KLDRSTATE_PENDING_DESTROY:
+        case KLDRSTATE_GC:
+            break;
+        default:
+            KLDRDYLDMOD_ASSERT(!"Invalid state");
+            break;
+    }
+    KLDRDYLDMOD_ASSERT(!pMod->fInitList);
+    KLDRDYLDMOD_ASSERT(!pMod->cDynRefs);
+    KLDRDYLDMOD_ASSERT(!pMod->cDepRefs);
+
+    /*
+     * Ensure that the module is unmapped.
+     */
+    if (pMod->fAllocatedTLS)
+    {
+        kLdrModFreeTLS(pMod->pMod, KLDRMOD_INT_MAP);
+        pMod->fAllocatedTLS = 0;
+    }
+    if (pMod->fMapped)
+    {
+        rc = kLdrModUnmap(pMod->pMod); KLDRDYLDMOD_ASSERT(!rc);
+        pMod->fMapped = 0;
+    }
+
+    /*
+     * Ensure it's unlinked from all chains.
+     */
+    if (pMod->enmState < KLDRSTATE_PENDING_DESTROY)
+        kldrDyldModUnlink(pMod);
+
+    /*
+     * Free everything associated with the module.
+     */
+    /* the prerequisite array. */
+    if (pMod->papPrereqs)
+    {
+        KU32 i = pMod->cPrereqs;
+        while (i-- > 0)
+        {
+            KLDRDYLDMOD_ASSERT(pMod->papPrereqs[i] == NULL);
+            pMod->papPrereqs[i] = NULL;
+        }
+
+        kHlpFree(pMod->papPrereqs);
+        pMod->papPrereqs = NULL;
+        pMod->cPrereqs = 0;
+    }
+
+    /* the module interpreter.  */
+    if (pMod->pMod)
+    {
+        rc = kLdrModClose(pMod->pMod); KLDRDYLDMOD_ASSERT(!rc);
+        pMod->pMod = NULL;
+    }
+
+
+    /*
+     * Finally, change the module state and free the module if
+     * there are not more references to it. If somebody is still
+     * referencing it, postpone the freeing to Deref.
+     */
+    pMod->enmState = KLDRSTATE_DESTROYED;
+    if (!pMod->cRefs)
+    {
+        pMod->u32MagicHead = 1;
+        pMod->u32MagicTail = 2;
+        kHlpFree(pMod);
+    }
+}
+
+
+/**
+ * Unlinks the module from any list it might be in.
+ * It is assumed that the module is at least linked into the load list.
+ *
+ * @param   pMod    The moduel.
+ */
+static void kldrDyldModUnlink(PKLDRDYLDMOD pMod)
+{
+    /* load list */
+    if (pMod->Load.pNext)
+        pMod->Load.pNext->Load.pPrev = pMod->Load.pPrev;
+    else
+        kLdrDyldTail = pMod->Load.pPrev;
+    if (pMod->Load.pPrev)
+        pMod->Load.pPrev->Load.pNext = pMod->Load.pNext;
+    else
+        kLdrDyldHead = pMod->Load.pNext;
+
+    /* bind list */
+    if (pMod->fBindable)
+        kldrDyldModClearBindable(pMod);
+
+    /* init term */
+    if (pMod->fInitList)
+    {
+        KLDRDYLDMOD_ASSERT(pMod->enmState < KLDRSTATE_INITIALIZATION_FAILED);
+        pMod->fInitList = 0;
+        if (pMod->InitTerm.pNext)
+            pMod->InitTerm.pNext->InitTerm.pPrev = pMod->InitTerm.pPrev;
+        else
+            g_pkLdrDyldInitTail = pMod->InitTerm.pPrev;
+        if (pMod->InitTerm.pPrev)
+            pMod->InitTerm.pPrev->InitTerm.pNext = pMod->InitTerm.pNext;
+        else
+            g_pkLdrDyldInitHead = pMod->InitTerm.pNext;
+    }
+    else if (pMod->enmState > KLDRSTATE_INITIALIZATION_FAILED)
+    {
+        KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_GOOD);
+        if (pMod->InitTerm.pNext)
+            pMod->InitTerm.pNext->InitTerm.pPrev = pMod->InitTerm.pPrev;
+        else
+            g_pkLdrDyldTermTail = pMod->InitTerm.pPrev;
+        if (pMod->InitTerm.pPrev)
+            pMod->InitTerm.pPrev->InitTerm.pNext = pMod->InitTerm.pNext;
+        else
+            g_pkLdrDyldTermHead = pMod->InitTerm.pNext;
+    }
+    pMod->InitTerm.pNext = NULL;
+    pMod->InitTerm.pPrev = NULL;
+}
+
+
+/**
+ * Marks a module as bindable, i.e. it'll be considered when
+ * resolving names the unix way.
+ *
+ * @param   pMod    The module.
+ * @param   fDeep   When set the module will be inserted at the head of the
+ *                  module list used to resolve symbols. This means that the
+ *                  symbols in this module will be prefered of all the other
+ *                  modules.
+ */
+void kldrDyldModSetBindable(PKLDRDYLDMOD pMod, unsigned fDeep)
+{
+    KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_OPEN && pMod->enmState < KLDRSTATE_PENDING_GC);
+    if (!pMod->fBindable)
+    {
+        pMod->fBindable = 1;
+        if (!fDeep)
+        {
+            pMod->Bind.pNext = NULL;
+            pMod->Bind.pPrev = g_pkLdrDyldBindTail;
+            if (g_pkLdrDyldBindTail)
+                g_pkLdrDyldBindTail->Bind.pNext = pMod;
+            else
+                g_pkLdrDyldBindHead = pMod;
+            g_pkLdrDyldBindTail = pMod;
+        }
+        else
+        {
+            pMod->Bind.pPrev = NULL;
+            pMod->Bind.pNext = g_pkLdrDyldBindHead;
+            if (g_pkLdrDyldBindHead)
+                g_pkLdrDyldBindHead->Bind.pPrev = pMod;
+            else
+                g_pkLdrDyldBindTail = pMod;
+            g_pkLdrDyldBindHead = pMod;
+        }
+    }
+}
+
+
+/**
+ * Marks a module as not bindable, i.e. it will not be considered when
+ * resolving names the unix way.
+ *
+ * @param   pMod    The module.
+ */
+void kldrDyldModClearBindable(PKLDRDYLDMOD pMod)
+{
+    KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_OPEN && pMod->enmState < KLDRSTATE_PENDING_DESTROY);
+    if (pMod->fBindable)
+    {
+        pMod->fBindable = 0;
+        if (pMod->Bind.pPrev)
+            pMod->Bind.pPrev->Bind.pNext = pMod->Bind.pNext;
+        else
+            g_pkLdrDyldBindHead = pMod->Bind.pNext;
+        if (pMod->Bind.pNext)
+            pMod->Bind.pNext->Bind.pPrev = pMod->Bind.pPrev;
+        else
+            g_pkLdrDyldBindTail = pMod->Bind.pPrev;
+        pMod->Bind.pNext = NULL;
+        pMod->Bind.pPrev = NULL;
+    }
+}
+
+
+/**
+ * Marks the module as global instead of being specific.
+ *
+ * A global module can be a matching result when the request
+ * doesn't specify a path. A specific module will not match
+ * unless the path also matches.
+ *
+ * @param   pMod    The module.
+ */
+void kldrDyldModMarkGlobal(PKLDRDYLDMOD pMod)
+{
+    pMod->fGlobalOrSpecific = 1;
+}
+
+
+/**
+ * Marks the module as specific instead of global.
+ *
+ * See kldrDyldModMarkGlobal for an explanation of the two terms.
+ *
+ * @param   pMod    The module.
+ */
+void kldrDyldModMarkSpecific(PKLDRDYLDMOD pMod)
+{
+    pMod->fGlobalOrSpecific = 0;
+}
+
+
+/**
+ * Adds a reference to the module making sure it won't be freed just yet.
+ *
+ * @param   pMod    The module.
+ */
+void kldrDyldModAddRef(PKLDRDYLDMOD pMod)
+{
+    pMod->cRefs++;
+}
+
+
+/**
+ * Dereference a module.
+ *
+ * @param   pMod
+ */
+void kldrDyldModDeref(PKLDRDYLDMOD pMod)
+{
+    /* validate input */
+    KLDRDYLDMOD_ASSERT(pMod->cRefs > 0);
+    KLDRDYLDMOD_ASSERT(pMod->cRefs >= pMod->cDepRefs + pMod->cDynRefs);
+    KLDRDYLDMOD_ASSERT(pMod->enmState > KLDRSTATE_INVALID && pMod->enmState <= KLDRSTATE_END);
+
+    /* decrement. */
+    if (pMod->cRefs > 0)
+        pMod->cRefs--;
+
+    /* execute delayed freeing. */
+    if (    pMod->enmState == KLDRSTATE_DESTROYED
+        &&  !pMod->cRefs)
+    {
+        pMod->u32MagicHead = 1;
+        pMod->u32MagicTail = 2;
+        kHlpFree(pMod);
+    }
+}
+
+
+/**
+ * Increment the count of modules depending on this module.
+ *
+ * @param   pMod    The module.
+ * @param   pDep    The module which depends on us.
+ */
+void kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep)
+{
+    (void)pDep;
+
+    /* validate state */
+    switch (pMod->enmState)
+    {
+        case KLDRSTATE_MAPPED:
+        case KLDRSTATE_RELOADED:
+        case KLDRSTATE_LOADED_PREREQUISITES:
+        case KLDRSTATE_RELOADED_LOADED_PREREQUISITES:
+        case KLDRSTATE_PENDING_INITIALIZATION:
+        case KLDRSTATE_INITIALIZING:
+        case KLDRSTATE_GOOD:
+            break;
+        default:
+            KLDRDYLDMOD_ASSERT(!"invalid state");
+            break;
+
+    }
+    KLDRDYLDMOD_ASSERT(pMod->enmState > KLDRSTATE_INVALID && pMod->enmState <= KLDRSTATE_END);
+    pMod->cRefs++;
+    pMod->cDepRefs++;
+}
+
+
+/**
+ * Drop a dependency.
+ *
+ * @param   pMod    The module.
+ * @param   pDep    The module which depends on us.
+ */
+void kldrDyldModRemoveDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep)
+{
+    KLDRDYLDMOD_ASSERT(pMod->cDepRefs > 0);
+    if (pMod->cDepRefs == 0)
+        return;
+    KLDRDYLDMOD_ASSERT(pMod->cDepRefs <= pMod->cRefs);
+    KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_MAPPED && pMod->enmState <= KLDRSTATE_PENDING_DESTROY);
+
+    pMod->cRefs--;
+    pMod->cDepRefs--;
+    if (    pMod->cDepRefs > 0
+        ||  pMod->cDynRefs > 0)
+        return;
+
+    /*
+     * The module should be unloaded.
+     */
+    kldrDyldModUnloadPrerequisites(pMod);
+}
+
+
+/**
+ * Increment the dynamic load count.
+ *
+ * @returns 0
+ * @param   pMod    The module.
+ */
+int kldrDyldModDynamicLoad(PKLDRDYLDMOD pMod)
+{
+    KLDRDYLDMOD_ASSERT(     pMod->enmState == KLDRSTATE_GOOD
+                       ||   pMod->enmState == KLDRSTATE_PENDING_INITIALIZATION
+                       ||   pMod->enmState == KLDRSTATE_INITIALIZING);
+    pMod->cRefs++;
+    pMod->cDynRefs++;
+    return 0;
+}
+
+
+/**
+ * Decrement the dynamic load count of the module and unload the module
+ * if the total reference count reaches zero.
+ *
+ * This may cause a cascade of unloading to occure. See kldrDyldModUnloadPrerequisites().
+ *
+ * @returns status code.
+ * @retval  0 on success.
+ * @retval  KLDR_ERR_NOT_LOADED_DYNAMICALLY if the module wasn't loaded dynamically.
+ * @param   pMod        The module to unload.
+ */
+int kldrDyldModDynamicUnload(PKLDRDYLDMOD pMod)
+{
+    if (pMod->cDynRefs == 0)
+        return KLDR_ERR_NOT_LOADED_DYNAMICALLY;
+    KLDRDYLDMOD_ASSERT(pMod->cDynRefs <= pMod->cRefs);
+    KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_GOOD);
+
+    pMod->cRefs--;
+    pMod->cDynRefs--;
+    if (    pMod->cDynRefs > 0
+        ||  pMod->cDepRefs > 0)
+        return 0;
+
+    /*
+     * The module should be unloaded.
+     */
+    kldrDyldModUnloadPrerequisites(pMod);
+    return 0;
+}
+
+
+/**
+ * Worker for kldrDyldModUnloadPrerequisites.
+ *
+ * @returns The number of modules that now can be unloaded.
+ * @param   pMod    The module in  question.
+ */
+static KU32 kldrDyldModUnloadPrerequisitesOne(PKLDRDYLDMOD pMod)
+{
+    PKLDRDYLDMOD    pMod2;
+    KU32            cToUnload = 0;
+    KU32            i;
+
+    KLDRDYLDMOD_ASSERT(pMod->papPrereqs || !pMod->cPrereqs);
+
+    /*
+     * Release the one in this module.
+     */
+    for (i = 0; i < pMod->cPrereqs; i++)
+    {
+        pMod2 = pMod->papPrereqs[i];
+        if (pMod2)
+        {
+            pMod->papPrereqs[i] = NULL;
+
+            /* do the derefering ourselves or we'll end up in a recursive loop here. */
+            KLDRDYLDMOD_ASSERT(pMod2->cDepRefs > 0);
+            KLDRDYLDMOD_ASSERT(pMod2->cRefs >= pMod2->cDepRefs);
+            pMod2->cDepRefs--;
+            pMod2->cRefs--;
+            cToUnload += !pMod2->cDepRefs && !pMod2->cDynRefs;
+        }
+    }
+
+    /*
+     * Change the state
+     */
+    switch (pMod->enmState)
+    {
+        case KLDRSTATE_LOADED_PREREQUISITES:
+        case KLDRSTATE_FIXED_UP:
+            pMod->enmState = KLDRSTATE_PENDING_DESTROY;
+            kldrDyldModUnlink(pMod);
+            break;
+
+        case KLDRSTATE_PENDING_INITIALIZATION:
+            pMod->enmState = KLDRSTATE_PENDING_GC;
+            break;
+
+        case KLDRSTATE_RELOADED_FIXED_UP:
+        case KLDRSTATE_RELOADED_LOADED_PREREQUISITES:
+        case KLDRSTATE_GOOD:
+            pMod->enmState = KLDRSTATE_PENDING_TERMINATION;
+            break;
+
+        case KLDRSTATE_INITIALIZATION_FAILED:
+            break;
+
+        default:
+            KLDRDYLDMOD_ASSERT(!"invalid state");
+            break;
+    }
+
+    return cToUnload;
+}
+
+
+/**
+ * This is the heart of the unload code.
+ *
+ * It will recursivly (using the load list) initiate module unloading
+ * of all affected modules.
+ *
+ * This function will cause a state transition to PENDING_DESTROY, PENDING_GC
+ * or PENDING_TERMINATION depending on the module state. There is one exception
+ * to this, and that's INITIALIZATION_FAILED, where the state will not be changed.
+ *
+ * @param   pMod        The module which prerequisites should be unloaded.
+ */
+void kldrDyldModUnloadPrerequisites(PKLDRDYLDMOD pMod)
+{
+    KU32            cToUnload;
+
+    /* sanity */
+#ifdef KLDRDYLD_STRICT
+    {
+    PKLDRDYLDMOD pMod2;
+    for (pMod2 = kLdrDyldHead; pMod2; pMod2 = pMod2->Load.pNext)
+        KLDRDYLDMOD_ASSERT(pMod2->enmState != KLDRSTATE_GOOD || pMod2->cRefs);
+    }
+#endif
+    KLDRDYLDMOD_ASSERT(pMod->papPrereqs);
+
+    /*
+     * Unload prereqs of the module we're called on first.
+     */
+    cToUnload = kldrDyldModUnloadPrerequisitesOne(pMod);
+
+    /*
+     * Iterate the load list in a cyclic manner until there are no more
+     * modules that can be pushed on into unloading.
+     */
+    while (cToUnload)
+    {
+        cToUnload = 0;
+        for (pMod = kLdrDyldHead; pMod; pMod = pMod->Load.pNext)
+        {
+            if (    pMod->cDepRefs
+                ||  pMod->cDynRefs
+                ||  pMod->enmState >= KLDRSTATE_PENDING_TERMINATION
+                ||  pMod->enmState < KLDRSTATE_LOADED_PREREQUISITES)
+                continue;
+            cToUnload += kldrDyldModUnloadPrerequisitesOne(pMod);
+        }
+    }
+}
+
+
+/**
+ * Loads the prerequisite modules this module depends on.
+ *
+ * To find each of the prerequisite modules this method calls
+ * kldrDyldGetPrerequisite() and it will make sure the modules
+ * are added to the load stack frame.
+ *
+ * @returns 0 on success, non-zero native OS or kLdr status code on failure.
+ *          The state is changed to LOADED_PREREQUISITES or RELOADED_LOADED_PREREQUISITES.
+ * @param   pMod            The module.
+ * @param   pszPrefix       Prefix to use when searching.
+ * @param   pszSuffix       Suffix to use when searching.
+ * @param   enmSearch       Method to use when locating the module and any modules it may depend on.
+ * @param   fFlags          Flags, a combintation of the KLDRYDLD_LOAD_FLAGS_* \#defines.
+ */
+int kldrDyldModLoadPrerequisites(PKLDRDYLDMOD pMod, const char *pszPrefix, const char *pszSuffix,
+                                 KLDRDYLDSEARCH enmSearch, unsigned fFlags)
+{
+    KI32    cPrereqs;
+    KU32    i;
+    int     rc = 0;
+
+    /* sanity */
+    switch (pMod->enmState)
+    {
+        case KLDRSTATE_MAPPED:
+        case KLDRSTATE_RELOADED:
+            break;
+        default:
+            KLDRDYLDMOD_ASSERT(!"invalid state");
+            return -1;
+    }
+
+    /*
+     * Query number of prerequiste modules and allocate the array.
+     */
+    cPrereqs = kLdrModNumberOfImports(pMod->pMod, NULL);
+    kHlpAssert(cPrereqs >= 0);
+    if (pMod->cPrereqs != cPrereqs)
+    {
+        KLDRDYLDMOD_ASSERT(!pMod->papPrereqs);
+        pMod->papPrereqs = (PPKLDRDYLDMOD)kHlpAllocZ(sizeof(pMod->papPrereqs[0]) * cPrereqs);
+        if (!pMod->papPrereqs)
+            return KERR_NO_MEMORY;
+        pMod->cPrereqs = cPrereqs;
+    }
+    else
+        KLDRDYLDMOD_ASSERT(pMod->papPrereqs || !pMod->cPrereqs);
+
+    /*
+     * Iterate the prerequisites and load them.
+     */
+    for (i = 0; i < pMod->cPrereqs; i++)
+    {
+        static char s_szPrereq[260];
+        PKLDRDYLDMOD pPrereqMod;
+
+        KLDRDYLDMOD_ASSERT(pMod->papPrereqs[i] == NULL);
+        rc = kLdrModGetImport(pMod->pMod, NULL, i, s_szPrereq, sizeof(s_szPrereq));
+        if (rc)
+            break;
+        rc = kldrDyldGetPrerequisite(s_szPrereq, pszPrefix, pszSuffix, enmSearch, fFlags, pMod, &pPrereqMod);
+        if (rc)
+            break;
+        pMod->papPrereqs[i] = pPrereqMod;
+    }
+
+    /* change the state regardless of what happend. */
+    if (pMod->enmState == KLDRSTATE_MAPPED)
+        pMod->enmState = KLDRSTATE_LOADED_PREREQUISITES;
+    else
+        pMod->enmState = KLDRSTATE_RELOADED_LOADED_PREREQUISITES;
+    return rc;
+}
+
+
+/**
+ * Maps an open module.
+ *
+ * On success the module will be in the MAPPED state.
+ *
+ * @returns 0 on success, non-zero native OS or kLdr status code on failure.
+ * @param   pMod    The module which needs to be unmapped and set pending for destruction.
+ */
+int kldrDyldModMap(PKLDRDYLDMOD pMod)
+{
+    int rc;
+
+    /* sanity */
+    KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_OPEN);
+    KLDRDYLDMOD_ASSERT(!pMod->fMapped);
+    if (pMod->fMapped)
+        return 0;
+
+    /* do the job. */
+    rc = kLdrModMap(pMod->pMod);
+    if (!rc)
+    {
+        rc = kLdrModAllocTLS(pMod->pMod, KLDRMOD_INT_MAP);
+        if (!rc)
+        {
+            /** @todo TLS */
+            pMod->fMapped = 1;
+            pMod->enmState = KLDRSTATE_MAPPED;
+        }
+        else
+            kLdrModUnmap(pMod->pMod);
+    }
+    return rc;
+}
+
+
+/**
+ * Unmaps the module, unlinks it from everywhere marks it PENDING_DESTROY.
+ *
+ * @returns 0 on success, non-zero native OS or kLdr status code on failure.
+ * @param   pMod    The module which needs to be unmapped and set pending for destruction.
+ */
+int kldrDyldModUnmap(PKLDRDYLDMOD pMod)
+{
+    int rc;
+
+    /* sanity */
+    KLDRDYLDMOD_ASSERT(pMod->cRefs > 0);
+    KLDRDYLDMOD_ASSERT(pMod->fMapped);
+    switch (pMod->enmState)
+    {
+        case KLDRSTATE_MAPPED:
+        case KLDRSTATE_GC:
+        case KLDRSTATE_PENDING_DESTROY:
+            break;
+        default:
+            KLDRDYLDMOD_ASSERT(!"invalid state");
+            return -1;
+    }
+
+    /* do the job. */
+    if (pMod->fAllocatedTLS)
+    {
+        kLdrModFreeTLS(pMod->pMod, KLDRMOD_INT_MAP);
+        pMod->fAllocatedTLS = 0;
+    }
+    rc = kLdrModUnmap(pMod->pMod);
+    if (!rc)
+    {
+        pMod->fMapped = 0;
+        if (pMod->enmState < KLDRSTATE_PENDING_DESTROY)
+        {
+            pMod->enmState = KLDRSTATE_PENDING_DESTROY;
+            kldrDyldModUnlink(pMod);
+        }
+    }
+
+    return rc;
+}
+
+
+/**
+ * Reloads the module.
+ *
+ * Reloading means that all modified pages are restored to their original
+ * state. Whether this includes the code segments depends on whether the fixups
+ * depend on the addend in the place they are fixing up - so it's format specific.
+ *
+ * @returns 0 on success, non-zero native OS or kLdr status code on failure.
+ * @param   pMod    The module which needs to be unmapped and set pending for destruction.
+ */
+int kldrDyldModReload(PKLDRDYLDMOD pMod)
+{
+    int rc;
+
+    /* sanity */
+    KLDRDYLDMOD_ASSERT(pMod->cRefs > 0);
+    KLDRDYLDMOD_ASSERT(pMod->fMapped);
+
+    switch (pMod->enmState)
+    {
+        case KLDRSTATE_MAPPED:
+        case KLDRSTATE_GC:
+        case KLDRSTATE_PENDING_DESTROY:
+            break;
+        default:
+            KLDRDYLDMOD_ASSERT(!"invalid state");
+            return -1;
+    }
+
+    /* Free TLS before reloading. */
+    if (pMod->fAllocatedTLS)
+    {
+        kLdrModFreeTLS(pMod->pMod, KLDRMOD_INT_MAP);
+        pMod->fAllocatedTLS = 0;
+    }
+
+    /* Let the module interpreter do the reloading of the mapping. */
+    rc = kLdrModReload(pMod->pMod);
+    if (!rc)
+    {
+        rc = kLdrModAllocTLS(pMod->pMod, KLDRMOD_INT_MAP);
+        if (!rc)
+        {
+            pMod->fAllocatedTLS = 1;
+            pMod->enmState = KLDRSTATE_RELOADED;
+        }
+    }
+    return rc;
+}
+
+
+/**
+ * @copydoc FNKLDRMODGETIMPORT
+ * pvUser points to the KLDRDYLDMOD.
+ */
+static int kldrDyldModFixupGetImportCallback(PKLDRMOD pMod, KU32 iImport, KU32 iSymbol,
+                                             const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion,
+                                             PKLDRADDR puValue, KU32 *pfKind, void *pvUser)
+{
+    static int s_cRecursiveCalls = 0;
+    PKLDRDYLDMOD pDyldMod = (PKLDRDYLDMOD)pvUser;
+    int rc;
+
+    /* guard against too deep forwarder recursion. */
+    if (s_cRecursiveCalls >= 5)
+        return KLDR_ERR_TOO_LONG_FORWARDER_CHAIN;
+    s_cRecursiveCalls++;
+
+    if (iImport != NIL_KLDRMOD_IMPORT)
+    {
+        /* specific import module search. */
+        PKLDRDYLDMOD pPrereqMod;
+
+        KLDRDYLDMOD_ASSERT(iImport < pDyldMod->cPrereqs);
+        pPrereqMod = pDyldMod->papPrereqs[iImport];
+
+        KLDRDYLDMOD_ASSERT(pPrereqMod);
+        KLDRDYLDMOD_ASSERT(pPrereqMod->u32MagicHead == KLDRDYMOD_MAGIC);
+        KLDRDYLDMOD_ASSERT(pPrereqMod->u32MagicTail == KLDRDYMOD_MAGIC);
+        KLDRDYLDMOD_ASSERT(pPrereqMod->enmState < KLDRSTATE_TERMINATING);
+
+        rc = kLdrModQuerySymbol(pPrereqMod->pMod, NULL, KLDRMOD_BASEADDRESS_MAP,
+                                iSymbol, pchSymbol, cchSymbol, pszVersion,
+                                kldrDyldModFixupGetImportCallback, pPrereqMod, puValue, pfKind);
+        if (rc)
+        {
+            if (pchSymbol)
+                kldrDyldFailure(rc, "%s[%d]->%s.%.*s%s", pDyldMod->pMod->pszName, iImport,
+                                pPrereqMod->pMod->pszName, cchSymbol, pchSymbol, pszVersion ? pszVersion : "");
+            else
+                kldrDyldFailure(rc, "%s[%d]->%s.%d%s", pDyldMod->pMod->pszName, iImport,
+                                pPrereqMod->pMod->pszName, iSymbol, pszVersion ? pszVersion : "");
+        }
+    }
+    else
+    {
+        /* bind list search. */
+        unsigned fFound = 0;
+        PKLDRDYLDMOD pBindMod = g_pkLdrDyldBindHead;
+        rc = 0;
+        while (pBindMod)
+        {
+            KU32 fKind;
+            KLDRADDR uValue;
+            rc = kLdrModQuerySymbol(pBindMod->pMod, NULL, KLDRMOD_BASEADDRESS_MAP,
+                                    iSymbol, pchSymbol, cchSymbol, pszVersion,
+                                    kldrDyldModFixupGetImportCallback, pBindMod, &uValue, &fKind);
+            if (    !rc
+                &&  (   !fFound
+                     || !(fKind & KLDRSYMKIND_WEAK)
+                    )
+               )
+            {
+                *pfKind = fKind;
+                *puValue = uValue;
+                fFound = 1;
+                if (!(fKind & KLDRSYMKIND_WEAK))
+                    break;
+            }
+
+            /* next */
+            pBindMod = pBindMod->Bind.pNext;
+        }
+        rc = fFound ? 0 : KLDR_ERR_SYMBOL_NOT_FOUND;
+        if (!fFound)
+        {
+            if (pchSymbol)
+                kldrDyldFailure(rc, "%s->%.*s%s", pDyldMod->pMod->pszName, cchSymbol, pchSymbol, pszVersion ? pszVersion : "");
+            else
+                kldrDyldFailure(rc, "%s->%d%s", pDyldMod->pMod->pszName, iSymbol, pszVersion ? pszVersion : "");
+        }
+    }
+
+    s_cRecursiveCalls--;
+    return rc;
+}
+
+
+/**
+ * Applies fixups to a module which prerequisistes has been
+ * successfully loaded.
+ *
+ * @returns 0 on success, non-zero native OS or kLdr status code on failure.
+ * @param   pMod    The module which needs to be unmapped and set pending for destruction.
+ */
+int kldrDyldModFixup(PKLDRDYLDMOD pMod)
+{
+    int rc;
+
+    /* sanity */
+    KLDRDYLDMOD_ASSERT(pMod->cRefs > 0);
+    KLDRDYLDMOD_ASSERT(     pMod->enmState == KLDRSTATE_LOADED_PREREQUISITES
+                       ||   pMod->enmState == KLDRSTATE_RELOADED_LOADED_PREREQUISITES);
+
+    /* do the job */
+    rc = kLdrModFixupMapping(pMod->pMod, kldrDyldModFixupGetImportCallback, pMod);/** @todo fixme. */
+    if (!rc)
+        pMod->enmState = KLDRSTATE_FIXED_UP;
+    return rc;
+}
+
+
+/**
+ * Calls the module initialization entry point if any.
+ *
+ * This is considered to be a module specific thing and leave if
+ * to the module interpreter. They will have to deal with different
+ * module init practices between platforms should there be any.
+ *
+ * @returns 0 and state changed to GOOD on success.
+ *          Non-zero OS or kLdr status code and status changed to INITIALIZATION_FAILED on failure.
+ * @param   pMod        The module that should be initialized.
+ */
+int kldrDyldModCallInit(PKLDRDYLDMOD pMod)
+{
+    int rc;
+
+    KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_INITIALIZATION);
+    KLDRDYLDMOD_ASSERT(!pMod->fInitList);
+
+    pMod->enmState = KLDRSTATE_INITIALIZING;
+    rc = kLdrModCallInit(pMod->pMod, KLDRMOD_INT_MAP, (KUPTR)pMod->hMod);
+    if (!rc)
+    {
+        pMod->enmState = KLDRSTATE_GOOD;
+        /* push it onto the termination list.*/
+        pMod->InitTerm.pPrev = NULL;
+        pMod->InitTerm.pNext = g_pkLdrDyldTermHead;
+        if (g_pkLdrDyldTermHead)
+            g_pkLdrDyldTermHead->InitTerm.pPrev = pMod;
+        else
+            g_pkLdrDyldTermTail = pMod;
+        g_pkLdrDyldTermHead = pMod;
+    }
+    else
+        pMod->enmState = KLDRSTATE_INITIALIZATION_FAILED;
+
+    return rc;
+}
+
+
+/**
+ * Calls the module termination entry point if any.
+ *
+ * This'll change the module status to PENDING_GC.
+ *
+ * @param   pMod        The module that should be initialized.
+ */
+void kldrDyldModCallTerm(PKLDRDYLDMOD pMod)
+{
+    KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_TERMINATION);
+
+    pMod->enmState = KLDRSTATE_TERMINATING;
+    kLdrModCallTerm(pMod->pMod, KLDRMOD_INT_MAP, (KUPTR)pMod->hMod);
+    pMod->enmState = KLDRSTATE_PENDING_GC;
+    /* unlinking on destruction. */
+}
+
+
+/**
+ * Calls the thread attach entry point if any.
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param   pMod        The module.
+ */
+int kldrDyldModAttachThread(PKLDRDYLDMOD pMod)
+{
+    KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_GOOD);
+
+    return kLdrModCallThread(pMod->pMod, KLDRMOD_INT_MAP, (KUPTR)pMod->hMod, 1 /* attach */);
+}
+
+
+/**
+ * Calls the thread detach entry point if any.
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param   pMod        The module.
+ */
+void kldrDyldModDetachThread(PKLDRDYLDMOD pMod)
+{
+    KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_GOOD);
+
+    kLdrModCallThread(pMod->pMod, KLDRMOD_INT_MAP, (KUPTR)pMod->hMod, 0 /* detach */);
+}
+
+
+/**
+ * Gets the main stack, allocate it if necessary.
+ *
+ * @returns 0 on success, non-zero native OS or kLdr status code on failure.
+ * @param   pMod        The module.
+ * @param   ppvStack    Where to store the address of the stack (lowest address).
+ * @param   pcbStack    Where to store the size of the stack.
+ */
+int kldrDyldModGetMainStack(PKLDRDYLDMOD pMod, void **ppvStack, KSIZE *pcbStack)
+{
+    int rc = 0;
+    KLDRSTACKINFO StackInfo;
+    KLDRDYLDMOD_ASSERT(pMod->fExecutable);
+
+    /*
+     * Since we might have to allocate the stack ourselves, and there will only
+     * ever be one main stack, we'll be keeping the main stack info in globals.
+     */
+    if (!g_fkLdrDyldDoneMainStack)
+    {
+        rc = kLdrModGetStackInfo(pMod->pMod, NULL, KLDRMOD_BASEADDRESS_MAP, &StackInfo);
+        if (!rc)
+        {
+            /* check if there is a stack size override/default. */
+            KSIZE cbDefOverride;
+            if (kHlpGetEnvUZ("KLDR_MAIN_STACK_SIZE", &cbDefOverride))
+                cbDefOverride = 0;
+
+
+            /* needs allocating? */
+            if (    StackInfo.LinkAddress == NIL_KLDRADDR
+                ||  StackInfo.cbStack < cbDefOverride)
+            {
+                KSIZE cbStack = (KSIZE)K_MAX(StackInfo.cbStack, cbDefOverride);
+
+                g_pvkLdrDyldMainStack = kldrDyldOSAllocStack(cbStack);
+                if (g_pvkLdrDyldMainStack)
+                {
+                    g_cbkLdrDyldMainStack = cbStack;
+                    g_fkLdrDyldMainStackAllocated = 1;
+                }
+                else
+                    rc = KLDR_ERR_MAIN_STACK_ALLOC_FAILED;
+            }
+            else
+            {
+                KLDRDYLDMOD_ASSERT(StackInfo.Address != NIL_KLDRADDR);
+                KLDRDYLDMOD_ASSERT(StackInfo.cbStack > 0);
+
+                g_fkLdrDyldMainStackAllocated = 0;
+                g_pvkLdrDyldMainStack = (void *)(KUPTR)StackInfo.Address;
+                KLDRDYLDMOD_ASSERT((KUPTR)g_pvkLdrDyldMainStack == StackInfo.Address);
+
+                g_cbkLdrDyldMainStack = (KSIZE)StackInfo.cbStack;
+                KLDRDYLDMOD_ASSERT(StackInfo.cbStack == g_cbkLdrDyldMainStack);
+            }
+        }
+        if (!rc)
+            g_fkLdrDyldDoneMainStack = 1;
+    }
+
+    if (!rc)
+    {
+        if (ppvStack)
+            *ppvStack = g_pvkLdrDyldMainStack;
+        if (pcbStack)
+            *pcbStack = g_cbkLdrDyldMainStack;
+    }
+
+    return rc;
+}
+
+
+/**
+ * This starts the executable module.
+ *
+ * @returns non-zero OS or kLdr status code on failure.
+ *          (won't return on success.)
+ * @param   pMod    The executable module.
+ */
+int kldrDyldModStartExe(PKLDRDYLDMOD pMod)
+{
+    int         rc;
+    KLDRADDR    MainEPAddress;
+    void       *pvStack;
+    KSIZE      cbStack;
+    KLDRDYLDMOD_ASSERT(pMod->fExecutable);
+
+    rc = kLdrModQueryMainEntrypoint(pMod->pMod, NULL, KLDRMOD_BASEADDRESS_MAP, &MainEPAddress);
+    if (rc)
+        return rc;
+    rc = kldrDyldModGetMainStack(pMod, &pvStack, &cbStack);
+    if (rc)
+        return rc;
+    return kldrDyldOSStartExe((KUPTR)MainEPAddress, pvStack, cbStack);
+}
+
+
+/**
+ * Gets the module name.
+ *
+ * @returns 0 on success, KERR_BUFFER_OVERFLOW on failure.
+ * @param   pMod            The module.
+ * @param   pszName         Where to store the name.
+ * @param   cchName         The size of the name buffer.
+ */
+int kldrDyldModGetName(PKLDRDYLDMOD pMod, char *pszName, KSIZE cchName)
+{
+    KSIZE cch = K_MIN(cchName, pMod->pMod->cchName + 1);
+    if (cch)
+    {
+        kHlpMemCopy(pszName, pMod->pMod->pszName, cch - 1);
+        pszName[cch - 1] = '\0';
+    }
+    return cchName <= pMod->pMod->cchName ? KERR_BUFFER_OVERFLOW : 0;
+}
+
+
+/**
+ * Gets the module filename.
+ *
+ * @returns 0 on success, KERR_BUFFER_OVERFLOW on failure.
+ * @param   pMod            The module.
+ * @param   pszFilename     Where to store the filename.
+ * @param   cchFilename     The size of the filename buffer.
+ */
+int kldrDyldModGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, KSIZE cchFilename)
+{
+    KSIZE cch = K_MIN(cchFilename, pMod->pMod->cchFilename + 1);
+    if (cch)
+    {
+        kHlpMemCopy(pszFilename, pMod->pMod->pszFilename, cch - 1);
+        pszFilename[cch - 1] = '\0';
+    }
+    return cchFilename <= pMod->pMod->cchFilename ? KERR_BUFFER_OVERFLOW : 0;
+}
+
+
+/**
+ * Gets the address/value of a symbol in the specified module.
+ *
+ * @returns 0 on success, KLDR_ERR_SYMBOL_NOT_FOUND on failure.
+ * @param   pMod            The module.
+ * @param   uSymbolOrdinal  The symbol ordinal 0. This is ignored if the name is non-zero.
+ * @param   pszSymbolName   The symbol name. Can be NULL.
+ * @param   puValue         Where to store the value. optional.
+ * @param   pfKind          Where to store the symbol kind. optional.
+ */
+int kldrDyldModQuerySymbol(PKLDRDYLDMOD pMod, KU32 uSymbolOrdinal, const char *pszSymbolName,
+                           KUPTR *puValue, KU32 *pfKind)
+{
+    int         rc;
+    KLDRADDR    uValue = 0;
+    KU32        fKind = 0;
+
+    rc = kLdrModQuerySymbol(pMod->pMod, NULL, KLDRMOD_BASEADDRESS_MAP,
+                            uSymbolOrdinal, pszSymbolName, kHlpStrLen(pszSymbolName), NULL,
+                            kldrDyldModFixupGetImportCallback, pMod,
+                            &uValue, &fKind);
+    if (!rc)
+    {
+        if (puValue)
+        {
+            *puValue = (KUPTR)uValue;
+            KLDRDYLDMOD_ASSERT(*puValue == uValue);
+        }
+        if (pfKind)
+            *pfKind = fKind;
+    }
+
+    return rc;
+}
+
diff --git a/src/lib/kStuff/kLdr/kLdrDyldOS.c b/src/lib/kStuff/kLdr/kLdrDyldOS.c
new file mode 100644
index 0000000..ed47561
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrDyldOS.c
@@ -0,0 +1,133 @@
+/* $Id: kLdrDyldOS.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - The Dynamic Loader, OS specific operations.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kLdr.h>
+#include "kLdrInternal.h"
+
+#if K_OS == K_OS_OS2
+# define INCL_BASE
+# define INCL_ERRORS
+# include <os2.h>
+
+#elif K_OS == K_OS_WINDOWS
+# undef IMAGE_DOS_SIGNATURE
+# undef IMAGE_NT_SIGNATURE
+# include <Windows.h>
+
+#else
+# include <k/kHlpAlloc.h>
+
+#endif
+
+
+/**
+ * Allocates a stack.
+ *
+ * @returns Pointer to the stack. NULL on allocation failure (assumes out of memory).
+ * @param   cb      The size of the stack. This shall be page aligned.
+ *                  If 0, a OS specific default stack size will be employed.
+ */
+void *kldrDyldOSAllocStack(KSIZE cb)
+{
+#if K_OS == K_OS_OS2
+    APIRET rc;
+    PVOID pv;
+
+    if (!cb)
+        cb = 1 * 1024*1024; /* 1MB */
+
+    rc = DosAllocMem(&pv, cb, OBJ_TILE | PAG_COMMIT | PAG_WRITE | PAG_READ);
+    if (rc == NO_ERROR)
+        return pv;
+    return NULL;
+
+#elif K_OS == K_OS_WINDOWS
+
+    if (!cb)
+        cb = 1 *1024*1024; /* 1MB */
+
+    return VirtualAlloc(NULL, cb, MEM_COMMIT, PAGE_READWRITE);
+
+#else
+    void *pv;
+
+    if (!cb)
+        cb = 1 * 1024*1024; /* 1MB */
+
+    if (!kHlpPageAlloc(&pv, cb, KPROT_READWRITE, K_FALSE))
+        return pv;
+    return NULL;
+#endif
+}
+
+
+/**
+ * Invokes the main executable entry point with whatever
+ * parameters specific to the host OS and/or module format.
+ *
+ * @returns
+ * @param   uMainEPAddress  The address of the main entry point.
+ * @param   pvStack         Pointer to the stack object.
+ * @param   cbStack         The size of the stack object.
+ */
+int kldrDyldOSStartExe(KUPTR uMainEPAddress, void *pvStack, KSIZE cbStack)
+{
+#if K_OS == K_OS_WINDOWS
+    /*
+     * Invoke the entrypoint on the current stack for now.
+     * Deal with other formats and stack switching another day.
+     */
+    int rc;
+    int (*pfnEP)(void);
+    pfnEP = (int (*)(void))uMainEPAddress;
+
+    rc = pfnEP();
+
+    TerminateProcess(GetCurrentProcess(), rc);
+    kHlpAssert(!"TerminateProcess failed");
+    for (;;)
+        TerminateProcess(GetCurrentProcess(), rc);
+#endif
+
+    return -1;
+}
+
+
+void kldrDyldDoLoadExeStackSwitch(PKLDRDYLDMOD pExe, void *pvStack, KSIZE cbStack)
+{
+    /*kHlpAssert(!"not implemented");*/
+
+    /** @todo implement this properly! */
+    kldrDyldDoLoadExe(pExe);
+}
+
diff --git a/src/lib/kStuff/kLdr/kLdrDyldSem.c b/src/lib/kStuff/kLdr/kLdrDyldSem.c
new file mode 100644
index 0000000..9ffa497
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrDyldSem.c
@@ -0,0 +1,198 @@
+/* $Id: kLdrDyldSem.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - The Dynamic Loader, Semaphore Helper Functions.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kDefs.h>
+#include <k/kHlpSem.h>
+#include <k/kHlpAssert.h>
+
+#if K_OS == K_OS_DARWIN
+# include <mach/mach.h>
+# undef mach_task_self  /* don't use the macro (if we're using bare helpers ) */
+
+#elif K_OS == K_OS_OS2
+# define INCL_BASE
+# define INCL_ERRORS
+# include <os2.h>
+
+#elif  K_OS == K_OS_WINDOWS
+# include <Windows.h>
+
+#else
+# error "port me"
+#endif
+
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+#if K_OS == K_OS_DARWIN
+/** The loader sempahore. */
+static semaphore_t      g_Semaphore = MACH_PORT_NULL;
+
+#elif K_OS == K_OS_OS2
+/** The loader sempahore. */
+static HMTX             g_hmtx;
+
+#elif  K_OS == K_OS_WINDOWS
+/** The loader sempahore. */
+static CRITICAL_SECTION g_CritSect;
+
+#else
+# error "port me"
+#endif
+
+
+/**
+ * Initializes the loader semaphore.
+ *
+ * @returns 0 on success, non-zero OS status code on failure.
+ */
+int kLdrDyldSemInit(void)
+{
+#if K_OS == K_OS_DARWIN
+    kern_return_t krc;
+
+    krc = semaphore_create(mach_task_self(), &g_Semaphore, SYNC_POLICY_FIFO, 0);
+    if (krc != KERN_SUCCESS)
+        return krc;
+
+#elif K_OS == K_OS_OS2
+    APIRET rc;
+    g_hmtx = NULLHANDLE;
+    rc = DosCreateMutexSem(NULL, &g_hmtx, 0, FALSE);
+    if (rc)
+        return rc;
+
+#elif  K_OS == K_OS_WINDOWS
+    InitializeCriticalSection(&g_CritSect);
+
+#else
+# error "port me"
+#endif
+    return 0;
+}
+
+
+/**
+ * Terminates the loader semaphore.
+ */
+void kLdrDyldSemTerm(void)
+{
+#if K_OS == K_OS_DARWIN
+    kern_return_t krc;
+    semaphore_t Semaphore = g_Semaphore;
+    g_Semaphore = MACH_PORT_NULL;
+    krc = semaphore_destroy(mach_task_self(), Semaphore);
+    kHlpAssert(krc == KERN_SUCCESS); (void)krc;
+
+#elif K_OS == K_OS_OS2
+    HMTX hmtx = g_hmtx;
+    g_hmtx = NULLHANDLE;
+    DosCloseMutexSem(hmtx);
+
+#elif  K_OS == K_OS_WINDOWS
+    DeleteCriticalSection(&g_CritSect);
+
+#else
+# error "port me"
+#endif
+}
+
+
+/**
+ * Requests the loader sempahore ownership.
+ * This can be done recursivly.
+ *
+ * @returns 0 on success, non-zero OS status code on failure.
+ */
+int kLdrDyldSemRequest(void)
+{
+#if K_OS == K_OS_DARWIN
+    /* not sure about this... */
+    kern_return_t krc;
+    do krc = semaphore_wait(g_Semaphore);
+    while (krc == KERN_ABORTED);
+    if (krc == KERN_SUCCESS)
+        return 0;
+    return krc;
+
+#elif K_OS == K_OS_OS2
+    APIRET rc = DosRequestMutexSem(g_hmtx, 5000);
+    if (rc == ERROR_TIMEOUT || rc == ERROR_SEM_TIMEOUT || rc == ERROR_INTERRUPT)
+    {
+        unsigned i = 0;
+        do
+        {
+            /** @todo check for deadlocks etc. */
+            rc = DosRequestMutexSem(g_hmtx, 1000);
+        } while (   (   rc == ERROR_TIMEOUT
+                     || rc == ERROR_SEM_TIMEOUT
+                     || rc == ERROR_INTERRUPT)
+                 && i++ < 120);
+    }
+    return rc;
+
+#elif  K_OS == K_OS_WINDOWS
+    EnterCriticalSection(&g_CritSect);
+    return 0;
+
+#else
+# error "port me"
+#endif
+}
+
+
+/**
+ * Releases the loader semaphore ownership.
+ * The caller is responsible for making sure it's the semaphore owner!
+ */
+void kLdrDyldSemRelease(void)
+{
+#if K_OS == K_OS_DARWIN
+    /* not too sure about this... */
+    kern_return_t krc = semaphore_signal(g_Semaphore);
+    kHlpAssert(krc == KERN_SUCCESS); (void)krc;
+
+#elif K_OS == K_OS_OS2
+    APIRET rc = DosReleaseMutexSem(g_hmtx);
+    kHlpAssert(!rc); (void)rc;
+
+#elif  K_OS == K_OS_WINDOWS
+    LeaveCriticalSection(&g_CritSect);
+
+#else
+# error "port me"
+#endif
+}
+
diff --git a/src/lib/kStuff/kLdr/kLdrExeStub-os2.asm b/src/lib/kStuff/kLdr/kLdrExeStub-os2.asm
new file mode 100644
index 0000000..ad897e3
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrExeStub-os2.asm
@@ -0,0 +1,72 @@
+; $Id: kLdrExeStub-os2.asm 29 2009-07-01 20:30:29Z bird $
+;; @file
+; kLdr - OS/2 Loader Stub.
+;
+; This file contains a 64kb code/data/stack segment which is used to kick off
+; the loader dll that loads the process.
+;
+
+;
+; Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+;
+; Permission is hereby granted, free of charge, to any person
+; obtaining a copy of this software and associated documentation
+; files (the "Software"), to deal in the Software without
+; restriction, including without limitation the rights to use,
+; copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of the Software, and to permit persons to whom the
+; Software is furnished to do so, subject to the following
+; conditions:
+;
+; The above copyright notice and this permission notice shall be
+; included in all copies or substantial portions of the Software.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+; OTHER DEALINGS IN THE SOFTWARE.
+;
+
+struc KLDRARGS
+    .fFlags         resd 1
+    .enmSearch      resd 1
+    .szExecutable   resb 260
+    .szDefPrefix    resb 16
+    .szDefSuffix    resb 16
+    .szLibPath      resb (4096 - (4 + 4 + 16 + 16 + 260))
+endstruc
+
+extern _kLdrDyldLoadExe
+
+
+segment DATA32 stack CLASS=DATA align=16 use32
+..start:
+    push    args
+    jmp     _kLdrDyldLoadExe
+
+;
+; Argument structure.
+;
+align 4
+args:
+istruc KLDRARGS
+    at KLDRARGS.fFlags,         dd 0
+    at KLDRARGS.enmSearch,      dd 2 ;KLDRDYLD_SEARCH_HOST
+    at KLDRARGS.szDefPrefix,    db ''
+    at KLDRARGS.szDefSuffix,    db '.dll'
+;    at KLDRARGS.szExecutable,   db 'tst-0.exe'
+    at KLDRARGS.szLibPath,      db ''
+iend
+
+segment STACK32 stack CLASS=STACK align=16 use32
+; pad up to 64KB.
+resb 60*1024
+
+global WEAK$ZERO
+WEAK$ZERO EQU 0
+group DGROUP, DATA32  STACK32
+
diff --git a/src/lib/kStuff/kLdr/kLdrExeStub-os2.c b/src/lib/kStuff/kLdr/kLdrExeStub-os2.c
new file mode 100644
index 0000000..17a4b1c
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrExeStub-os2.c
@@ -0,0 +1,59 @@
+/* $Id: kLdrExeStub-os2.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - OS/2 C Loader Stub.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kLdr.h>
+#include <os2.h>
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** The stub arguments. */
+static const KLDREXEARGS g_Args =
+{
+    /* .fFlags       = */ KLDRDYLD_LOAD_FLAGS_RECURSIVE_INIT,
+    /* .enmSearch    = */ KLDRDYLD_SEARCH_OS2,
+    /* .szExecutable = */ "tst-0", /* just while testing */
+    /* .szDefPrefix  = */ "",
+    /* .szDefSuffix  = */ ".dll",
+    /* .szLibPath    = */ ""
+};
+
+/**
+ * OS/2 'main'.
+ */
+int _System OS2Main(HMODULE hmod, ULONG ulReserved, PCH pszzEnv, PCH pszzCmdLine)
+{
+    return kLdrDyldLoadExe(&g_Args, &hmod);
+}
+
diff --git a/src/lib/kStuff/kLdr/kLdrExeStub-os2A.asm b/src/lib/kStuff/kLdr/kLdrExeStub-os2A.asm
new file mode 100644
index 0000000..b3d692c
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrExeStub-os2A.asm
@@ -0,0 +1,41 @@
+; $Id: kLdrExeStub-os2A.asm 29 2009-07-01 20:30:29Z bird $
+;; @file
+; kLdr - OS/2 Loader Stub, entry point thingy...
+;
+
+;
+; Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+;
+; Permission is hereby granted, free of charge, to any person
+; obtaining a copy of this software and associated documentation
+; files (the "Software"), to deal in the Software without
+; restriction, including without limitation the rights to use,
+; copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of the Software, and to permit persons to whom the
+; Software is furnished to do so, subject to the following
+; conditions:
+;
+; The above copyright notice and this permission notice shall be
+; included in all copies or substantial portions of the Software.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+; OTHER DEALINGS IN THE SOFTWARE.
+;
+
+
+segment TEXT32 public CLASS=CODE align=16 use32
+extern OS2Main
+..start:
+    jmp OS2Main
+
+segment DATA32 stack CLASS=DATA align=16 use32
+
+global WEAK$ZERO
+WEAK$ZERO EQU 0
+
diff --git a/src/lib/kStuff/kLdr/kLdrExeStub-win.c b/src/lib/kStuff/kLdr/kLdrExeStub-win.c
new file mode 100644
index 0000000..55920e5
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrExeStub-win.c
@@ -0,0 +1,62 @@
+/* $Id: kLdrExeStub-win.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - Windows Loader Stub.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kLdr.h>
+#include <Windows.h>
+#include "kLdrInternal.h"
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** The stub arguments. */
+static const KLDREXEARGS g_Args =
+{
+    /* .fFlags       = */ KLDRDYLD_LOAD_FLAGS_RECURSIVE_INIT,
+    /* .enmSearch    = */ KLDRDYLD_SEARCH_WINDOWS,
+    /* .szExecutable = */ "tst-0", /* just while testing */
+    /* .szDefPrefix  = */ "",
+    /* .szDefSuffix  = */ "",
+    /* .szLibPath    = */ ""
+};
+
+/**
+ * Windows 'main'.
+ */
+int WindowsMain(void)
+{
+    kLdrDyldLoadExe(&g_Args, NULL);
+    /* won't happen */
+    return 0;
+}
+
diff --git a/src/lib/kStuff/kLdr/kLdrHlp.h b/src/lib/kStuff/kLdr/kLdrHlp.h
new file mode 100644
index 0000000..ab54f10
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrHlp.h
@@ -0,0 +1,9 @@
+
+int     kldrHlpGetEnv(const char *pszVar, char *pszVal, KSIZE cchVal);
+int     kldrHlpGetEnvUZ(const char *pszVar, KSIZE *pcb);
+
+void    kldrHlpExit(int rc);
+void    kldrHlpSleep(unsigned cMillies);
+
+char   *kldrHlpInt2Ascii(char *psz, KSIZE cch, long lVal, unsigned iBase);
+
diff --git a/src/lib/kStuff/kLdr/kLdrInternal.h b/src/lib/kStuff/kLdr/kLdrInternal.h
new file mode 100644
index 0000000..508f3ab
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrInternal.h
@@ -0,0 +1,461 @@
+/* $Id: kLdrInternal.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - The Dynamic Loader, internal header.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___kLdrInternal_h___
+#define ___kLdrInternal_h___
+
+#include <k/kHlp.h>
+#include <k/kRdr.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(__X86__) && !defined(__AMD64__)
+# if defined(__i386__) || defined(_M_IX86)
+#  define __X86__
+# elif defined(__x86_64__) || defined(_M_X64) || defined(__AMD64__) || defined(_M_AMD64)
+#  define __AMD64__
+# else
+#  error "can't figure out the target arch."
+# endif
+#endif
+
+/* ignore definitions in winnt.h */
+#undef IMAGE_DOS_SIGNATURE
+#undef IMAGE_NT_SIGNATURE
+
+/** @name Signatures we know
+ * @{ */
+/** ELF signature ("\x7fELF"). */
+#define IMAGE_ELF_SIGNATURE         K_LE2H_U32(0x7f | ('E' << 8) | ((KU32)'L' << 16) | ((KU32)'F' << 24))
+/** PE signature ("PE\0\0"). */
+#define IMAGE_NT_SIGNATURE          K_LE2H_U32('P' | ('E' << 8))
+/** LX signature ("LX") */
+#define IMAGE_LX_SIGNATURE          K_LE2H_U16('L' | ('X' << 8))
+/** LE signature ("LE") */
+#define IMAGE_LE_SIGNATURE          K_LE2H_U16('L' | ('E' << 8))
+/** NE signature ("NE") */
+#define IMAGE_NE_SIGNATURE          K_LE2H_U16('N' | ('E' << 8))
+/** MZ signature ("MZ"). */
+#define IMAGE_DOS_SIGNATURE         K_LE2H_U16('M' | ('Z' << 8))
+/** The FAT signature (universal binaries). */
+#define IMAGE_FAT_SIGNATURE         KU32_C(0xcafebabe)
+/** The FAT signature (universal binaries), other endian. */
+#define IMAGE_FAT_SIGNATURE_OE      KU32_C(0xbebafeca)
+/** The 32-bit Mach-O signature. */
+#define IMAGE_MACHO32_SIGNATURE     KU32_C(0xfeedface)
+/** The 32-bit Mach-O signature, other endian. */
+#define IMAGE_MACHO32_SIGNATURE_OE  KU32_C(0xcefaedfe)
+/** The 64-bit Mach-O signature. */
+#define IMAGE_MACHO64_SIGNATURE     KU32_C(0xfeedfacf)
+/** The 64-bit Mach-O signature, other endian. */
+#define IMAGE_MACHO64_SIGNATURE_OE  KU32_C(0xfefaedfe)
+/** @} */
+
+/** @defgroup grp_kLdrInternal  Internals
+ * @internal
+ * @{
+ */
+
+
+/**
+ * The state of a dynamic loader module.
+ * @image html KLDRSTATE.gif "The state diagram"
+ */
+typedef enum KLDRSTATE
+{
+    /** The usual invalid 0 enum. */
+    KLDRSTATE_INVALID = 0,
+
+    /** The module has just been opened and linked into the load list.
+     *
+     * Prev state: -
+     * Next state: MAPPED, PENDING_DESTROY
+     */
+    KLDRSTATE_OPEN,
+
+    /** The module segments has been mapped into the process memory.
+     *
+     * Prev state: OPEN
+     * Next state: LOADED_PREREQUISITES, PENDING_DESTROY
+     */
+    KLDRSTATE_MAPPED,
+    /** The module has been reloaded and needs to be fixed up again.
+     * This can occure when the loader is called recursivly.
+     *
+     * The reason RELOADED modules must go back to the PENDING_GC state is
+     * because we want to guard against uninit order issues, and therefore
+     * doesn't unmap modules untill all pending termintation callbacks has
+     * been executed.
+     *
+     * Prev state: PENDING_GC
+     * Next state: RELOADED_LOADED_PREREQUISITES, PENDING_GC
+     */
+    KLDRSTATE_RELOADED,
+
+    /** The immediate prerequisites have been loaded.
+     *
+     * Prev state: MAPPED
+     * Next state: FIXED_UP, PENDING_DESTROY
+     */
+    KLDRSTATE_LOADED_PREREQUISITES,
+    /** The immediate prerequisites have been loaded for a reloaded module.
+     *
+     * Prev state: RELOADED
+     * Next state: RELOADED_FIXED_UP, PENDING_GC
+     */
+    KLDRSTATE_RELOADED_LOADED_PREREQUISITES,
+
+    /** Fixups has been applied.
+     *
+     * Prev state: LOADED_PREREQUISITES
+     * Next state: PENDING_INITIALIZATION, PENDING_DESTROY
+     */
+    KLDRSTATE_FIXED_UP,
+    /** Fixups has been applied.
+     *
+     * Prev state: RELOADED_LOADED_PREREQUISITES
+     * Next state: PENDING_INITIALIZATION, PENDING_GC
+     */
+    KLDRSTATE_RELOADED_FIXED_UP,
+
+    /** Pending initialization.
+     * While the module is in this state the loader is in reentrant mode.
+     *
+     * Prev state: FIXED_UP, RELOADED_FIXED_UP
+     * Next state: INITIALIZATION, PENDING_GC
+     */
+    KLDRSTATE_PENDING_INITIALIZATION,
+
+    /** Initializing.
+     * While the module is in this state the loader is in reentrant mode.
+     *
+     * Prev state: PENDING_INITIALIZATION
+     * Next state: GOOD, PENDING_GC
+     */
+    KLDRSTATE_INITIALIZING,
+
+    /** Initialization failed.
+     *
+     * This is somewhat similar to PENDING_GC except that, a module
+     * in this state cannot be reloaded untill we've done GC. This ensures
+     * that a init failure during recursive loading is propagated up.
+     *
+     * While the module is in this state the loader is in reentrant mode.
+     *
+     * Prev state: INITIALIZING
+     * Next state: GC
+     */
+    KLDRSTATE_INITIALIZATION_FAILED,
+
+    /** The module has been successfully loaded and initialized.
+     * While the module is in this state the loader can be in reentrant
+     * or 'unused' mode.
+     *
+     * Prev state: INITIALIZING
+     * Next state: PENDING_TERMINATION
+     */
+    KLDRSTATE_GOOD,
+
+    /** Pending termination, reference count is 0.
+     * While the module is in this state the loader is in reentrant mode.
+     * Prerequisite modules are dropped when a module enters this state.
+     *
+     * Prev state: GOOD
+     * Next state: TERMINATING, GOOD
+     */
+    KLDRSTATE_PENDING_TERMINATION,
+
+    /** Terminating, reference count is still 0.
+     * While the module is in this state the loader is in reentrant mode.
+     *
+     * Prev state: PENDING_TERMINATION
+     * Next state: PENDING_GC
+     */
+    KLDRSTATE_TERMINATING,
+
+    /** Pending garbage collection.
+     * Prerequisite modules are dropped when a module enters this state (if not done already).
+     *
+     * Prev state: TERMINATING, PENDING_INITIALIZATION, INITIALIZATION_FAILED
+     * Next state: GC, RELOADED
+     */
+    KLDRSTATE_PENDING_GC,
+
+    /** Being garbage collected.
+     *
+     * Prev state: PENDING_GC, INITIALIZATION_FAILED
+     * Next state: PENDING_DESTROY, DESTROYED
+     */
+    KLDRSTATE_GC,
+
+    /** The module has be unlinked, but there are still stack references to it.
+     *
+     * Prev state: GC, FIXED_UP, LOADED_PREREQUISITES, MAPPED, OPEN
+     * Next state: DESTROYED
+     */
+    KLDRSTATE_PENDING_DESTROY,
+
+    /** The module has been destroyed but not freed yet.
+     *
+     * This happens when a module ends up being destroyed when cRefs > 0. The
+     * module structure will be freed when cRefs reaches 0.
+     *
+     * Prev state: GC, PENDING_DESTROY
+     */
+    KLDRSTATE_DESTROYED,
+
+    /** The end of valid states (exclusive) */
+    KLDRSTATE_END = KLDRSTATE_DESTROYED,
+    /** The usual 32-bit blowup. */
+    KLDRSTATE_32BIT_HACK = 0x7fffffff
+} KLDRSTATE;
+
+
+/**
+ * Dynamic loader module.
+ */
+typedef struct KLDRDYLDMOD
+{
+    /** Magic number. */
+    KU32                u32MagicHead;
+    /** The module state. */
+    KLDRSTATE           enmState;
+    /** The module. */
+    PKLDRMOD            pMod;
+    /** The module handle. */
+    HKLDRMOD            hMod;
+    /** The total number of references. */
+    KU32                cRefs;
+    /** The number of dependency references. */
+    KU32                cDepRefs;
+    /** The number of dynamic load references. */
+    KU32                cDynRefs;
+    /** Set if this is the executable module.
+     * When clear, the module is a shared object or relocatable object. */
+    KU32                fExecutable : 1;
+    /** Global DLL (set) or specific DLL (clear). */
+    KU32                fGlobalOrSpecific : 1;
+    /** Whether the module contains bindable symbols in the global unix namespace. */
+    KU32                fBindable : 1;
+    /** Set if linked into the global init list. */
+    KU32                fInitList : 1;
+    /** Already loaded or checked prerequisites.
+     * This flag is used when loading prerequisites, when set it means that
+     * this module is already seen and shouldn't be processed again. */
+    KU32                fAlreadySeen : 1;
+    /** Set if the module is currently mapped.
+     * This is used to avoid unnecessary calls to kLdrModUnmap during cleanup. */
+    KU32                fMapped : 1;
+    /** Set if TLS allocation has been done. (part of the mapping). */
+    KU32                fAllocatedTLS : 1;
+    /** Reserved for future use. */
+    KU32                f25Reserved : 25;
+    /** The load list linkage. */
+    struct
+    {
+        /** The next module in the list. */
+        struct KLDRDYLDMOD *pNext;
+        /** The prev module in the list. */
+        struct KLDRDYLDMOD *pPrev;
+    } Load;
+    /** The initialization and termination list linkage.
+     * If non-recursive initialization is used, the module will be pushed on
+     * the initialization list.
+     * A module will be linked into the termination list upon a successful
+     * return from module initialization. */
+    struct
+    {
+        /** The next module in the list. */
+        struct KLDRDYLDMOD *pNext;
+        /** The prev module in the list. */
+        struct KLDRDYLDMOD *pPrev;
+    } InitTerm;
+    /** The bind order list linkage.
+     * The module is not in this list when fBindable is clear. */
+    struct
+    {
+        /** The next module in the list. */
+        struct KLDRDYLDMOD *pNext;
+        /** The prev module in the list. */
+        struct KLDRDYLDMOD *pPrev;
+    } Bind;
+
+    /** The number of prerequisite modules in the prereq array. */
+    KU32                cPrereqs;
+    /** Pointer to an array of prerequisite module pointers.
+     * This array is only filled when in the states starting with
+     * KLDRSTATE_LOADED_PREREQUISITES thru KLDRSTATE_GOOD.
+     */
+    struct KLDRDYLDMOD **papPrereqs;
+
+    /** Magic number. */
+    KU32                u32MagicTail;
+} KLDRDYLDMOD, *PKLDRDYLDMOD, **PPKLDRDYLDMOD;
+
+/** KLDRDYLDMOD magic value. (Fuyumi Soryo) */
+#define KLDRDYMOD_MAGIC     0x19590106
+
+/** Return / crash validation of a module handle argument. */
+#define KLDRDYLD_VALIDATE_HKLDRMOD(hMod) \
+    do  { \
+        if (    (hMod) == NIL_HKLDRMOD \
+            ||  (hMod)->u32MagicHead != KLDRDYMOD_MAGIC \
+            ||  (hMod)->u32MagicTail != KLDRDYMOD_MAGIC) \
+        { \
+            return KERR_INVALID_HANDLE; \
+        } \
+    } while (0)
+
+
+int kldrInit(void);
+void kldrTerm(void);
+
+int kldrDyldInit(void);
+void kldrDyldTerm(void);
+
+void kldrDyldDoLoadExe(PKLDRDYLDMOD pExe);
+int kldrDyldFailure(int rc, const char *pszFormat, ...);
+
+int kldrDyldOSStartExe(KUPTR uMainEntrypoint, void *pvStack, KSIZE cbStack);
+void *kldrDyldOSAllocStack(KSIZE cb);
+
+int kldrDyldFindInit(void);
+int kldrDyldFindNewModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
+                          KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod);
+int kldrDyldFindExistingModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
+                               KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod);
+
+int kldrDyldGetPrerequisite(const char *pszDll, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch,
+                            unsigned fFlags, PKLDRDYLDMOD pDep, PPKLDRDYLDMOD ppMod);
+
+
+int kldrDyldModCreate(PKRDR pRdr, KU32 fFlags, PPKLDRDYLDMOD ppMod);
+void kldrDyldModDestroy(PKLDRDYLDMOD pMod);
+void kldrDyldModAddRef(PKLDRDYLDMOD pMod);
+void kldrDyldModDeref(PKLDRDYLDMOD pMod);
+void kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep);
+void kldrDyldModRemoveDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep);
+int kldrDyldModDynamicLoad(PKLDRDYLDMOD pMod);
+int kldrDyldModDynamicUnload(PKLDRDYLDMOD pMod);
+void kldrDyldModMarkGlobal(PKLDRDYLDMOD pMod);
+void kldrDyldModMarkSpecific(PKLDRDYLDMOD pMod);
+void kldrDyldModSetBindable(PKLDRDYLDMOD pMod, unsigned fDeep);
+void kldrDyldModClearBindable(PKLDRDYLDMOD pMod);
+int kldrDyldModMap(PKLDRDYLDMOD pMod);
+int kldrDyldModUnmap(PKLDRDYLDMOD pMod);
+int kldrDyldModLoadPrerequisites(PKLDRDYLDMOD pMod, const char *pszPrefix, const char *pszSuffix,
+                                 KLDRDYLDSEARCH enmSearch, unsigned fFlags);
+int kldrDyldModCheckPrerequisites(PKLDRDYLDMOD pMod);
+void kldrDyldModUnloadPrerequisites(PKLDRDYLDMOD pMod);
+int kldrDyldModFixup(PKLDRDYLDMOD pMod);
+int kldrDyldModCallInit(PKLDRDYLDMOD pMod);
+void kldrDyldModCallTerm(PKLDRDYLDMOD pMod);
+int kldrDyldModReload(PKLDRDYLDMOD pMod);
+int kldrDyldModAttachThread(PKLDRDYLDMOD pMod);
+void kldrDyldModDetachThread(PKLDRDYLDMOD pMod);
+int kldrDyldModGetMainStack(PKLDRDYLDMOD pMod, void **ppvStack, KSIZE *pcbStack);
+int kldrDyldModStartExe(PKLDRDYLDMOD pMod);
+
+int kldrDyldModGetName(PKLDRDYLDMOD pMod, char *pszName, KSIZE cchName);
+int kldrDyldModGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, KSIZE cchFilename);
+int kldrDyldModQuerySymbol(PKLDRDYLDMOD pMod, KU32 uSymbolOrdinal, const char *pszSymbolName, KUPTR *puValue, KU32 *pfKind);
+
+
+/** Pointer to the head module (the executable).
+ * (This is exported, so no prefix.) */
+extern PKLDRDYLDMOD     kLdrDyldHead;
+/** Pointer to the tail module.
+ * (This is exported, so no prefix.) */
+extern PKLDRDYLDMOD     kLdrDyldTail;
+/** Pointer to the head module of the initialization list.
+ * The outermost load call will pop elements from this list in LIFO order (i.e.
+ * from the tail). The list is only used during non-recursive initialization
+ * and may therefore share the pNext/pPrev members with the termination list
+ * since we don't push a module onto the termination list untill it has been
+ * successfully initialized. */
+extern PKLDRDYLDMOD     g_pkLdrDyldInitHead;
+/** Pointer to the tail module of the initalization list. */
+extern PKLDRDYLDMOD     g_pkLdrDyldInitTail;
+/** Pointer to the head module of the termination order list. */
+extern PKLDRDYLDMOD     g_pkLdrDyldTermHead;
+/** Pointer to the tail module of the termination order list. */
+extern PKLDRDYLDMOD     g_pkLdrDyldTermTail;
+/** Pointer to the head module of the bind order list.
+ * The modules in this list makes up the global namespace used when binding symbol unix fashion. */
+extern PKLDRDYLDMOD     g_pkLdrDyldBindHead;
+/** Pointer to the tail module of the bind order list. */
+extern PKLDRDYLDMOD     g_pkLdrDyldBindTail;
+
+/** Indicates that the other MainStack globals have been filled in. */
+extern unsigned         g_fkLdrDyldDoneMainStack;
+/** Whether the stack was allocated seperatly or was part of the executable. */
+extern unsigned         g_fkLdrDyldMainStackAllocated;
+/** Pointer to the main stack object. */
+extern void            *g_pvkLdrDyldMainStack;
+/** The size of the main stack object. */
+extern KSIZE            g_cbkLdrDyldMainStack;
+
+/** The global error buffer. */
+extern char             g_szkLdrDyldError[1024];
+
+extern char             kLdrDyldExePath[8192];
+extern char             kLdrDyldLibraryPath[8192];
+extern char             kLdrDyldDefPrefix[16];
+extern char             kLdrDyldDefSuffix[16];
+
+extern int              g_fBootstrapping;
+
+
+/** @name The Loader semaphore
+ * @{ */
+int     kLdrDyldSemInit(void);
+void    kLdrDyldSemTerm(void);
+int     kLdrDyldSemRequest(void);
+void    kLdrDyldSemRelease(void);
+/** @} */
+
+
+/** @name Module interpreter method tables
+ * @{ */
+extern KLDRMODOPS       g_kLdrModLXOps;
+extern KLDRMODOPS       g_kLdrModMachOOps;
+extern KLDRMODOPS       g_kLdrModNativeOps;
+extern KLDRMODOPS       g_kLdrModPEOps;
+/** @} */
+
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/kStuff/kLdr/kLdrMod.c b/src/lib/kStuff/kLdr/kLdrMod.c
new file mode 100644
index 0000000..5c11260
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrMod.c
@@ -0,0 +1,914 @@
+/* $Id: kLdrMod.c 81 2016-08-18 22:10:38Z bird $ */
+/** @file
+ * kLdr - The Module Interpreter.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kLdr.h>
+#include "kLdrInternal.h"
+#include <k/kCpu.h>
+#include <k/kLdrFmts/mz.h>
+#if 1 /* testing headers */
+# include <k/kLdrFmts/pe.h>
+# include <k/kLdrFmts/lx.h>
+# include <k/kLdrFmts/mach-o.h>
+#endif
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** @def KLDRMOD_STRICT
+ * Define KLDRMOD_STRICT to enabled strict checks in KLDRMOD. */
+#define KLDRMOD_STRICT 1
+
+/** @def KLDRMOD_ASSERT
+ * Assert that an expression is true when KLDR_STRICT is defined.
+ */
+#ifdef KLDRMOD_STRICT
+# define KLDRMOD_ASSERT(expr)  kHlpAssert(expr)
+#else
+# define KLDRMOD_ASSERT(expr)  do {} while (0)
+#endif
+
+/** Return / crash validation of a module argument. */
+#define KLDRMOD_VALIDATE_EX(pMod, rc) \
+    do  { \
+        if (    (pMod)->u32Magic != KLDRMOD_MAGIC \
+            ||  (pMod)->pOps == NULL \
+           )\
+        { \
+            return (rc); \
+        } \
+    } while (0)
+
+/** Return / crash validation of a module argument. */
+#define KLDRMOD_VALIDATE(pMod) \
+    KLDRMOD_VALIDATE_EX(pMod, KERR_INVALID_PARAMETER)
+
+/** Return / crash validation of a module argument. */
+#define KLDRMOD_VALIDATE_VOID(pMod) \
+    do  { \
+        if (    (pMod)->u32Magic != KLDRMOD_MAGIC \
+            ||  (pMod)->pOps == NULL \
+           )\
+        { \
+            return; \
+        } \
+    } while (0)
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** The list of module interpreters. */
+static PCKLDRMODOPS g_pModInterpreterHead = NULL;
+
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+
+
+
+/**
+ * Open a executable image by file name.
+ *
+ * @returns 0 on success and *ppMod pointing to a module instance.
+ *          On failure, a non-zero OS specific error code is returned.
+ * @param   pszFilename     The filename to open.
+ * @param   fFlags          Flags, MBZ.
+ * @param   enmCpuArch      The desired CPU architecture. KCPUARCH_UNKNOWN means
+ *                          anything goes, but with a preference for the current
+ *                          host architecture.
+ * @param   ppMod           Where to store the module handle.
+ */
+int kLdrModOpen(const char *pszFilename, KU32 fFlags, KCPUARCH enmCpuArch, PPKLDRMOD ppMod)
+{
+    /*
+     * Open the file using a bit provider.
+     */
+    PKRDR pRdr;
+    int rc = kRdrOpen(&pRdr, pszFilename);
+    if (!rc)
+    {
+        rc = kLdrModOpenFromRdr(pRdr, fFlags, enmCpuArch, ppMod);
+        if (!rc)
+            return 0;
+       kRdrClose(pRdr);
+    }
+    return rc;
+}
+
+
+/**
+ * Select image from the FAT according to the enmCpuArch and fFlag.
+ *
+ * @returns 0 on success and *poffHdr set to the image header.
+ *          On failure, a non-zero error code is returned.
+ *
+ * @param   pRdr            The file provider instance to use.
+ * @param   fFlags          Flags, MBZ.
+ * @param   enmCpuArch      The desired CPU architecture. KCPUARCH_UNKNOWN means
+ *                          anything goes, but with a preference for the current
+ *                          host architecture.
+ * @param   u32Magic        The FAT magic.
+ * @param   poffHdr         Where to store the offset of the selected image.
+ */
+static int kldrModOpenFromRdrSelectImageFromFAT(PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch, KU32 u32Magic, KLDRFOFF *poffHdr)
+{
+    int         rcRet = KLDR_ERR_CPU_ARCH_MISMATCH;
+    KLDRFOFF    off = *poffHdr + sizeof(KU32);
+    KLDRFOFF    offEndFAT;
+    KBOOL       fCpuArchWhatever;
+    KU32        cArchs;
+    KU32        iArch;
+    int         rc;
+    K_NOREF(fFlags);
+
+    /* Read fat_header_t::nfat_arch. */
+    rc = kRdrRead(pRdr, &cArchs, sizeof(cArchs), off);
+    if (rc)
+        return rc;
+    off += sizeof(KU32);
+    if (u32Magic == IMAGE_FAT_SIGNATURE_OE)
+        cArchs = K_E2E_U32(cArchs);
+    if (cArchs == 0)
+        return KLDR_ERR_FAT_INVALID;
+
+    /* Deal with KCPUARCH_UNKNOWN. */
+    fCpuArchWhatever = enmCpuArch == KCPUARCH_UNKNOWN;
+    if (fCpuArchWhatever)
+    {
+        KCPU enmCpuIgnored;
+        kCpuGetArchAndCpu(&enmCpuArch, &enmCpuIgnored);
+    }
+
+    /*
+     * Iterate the architecture list.
+     */
+    offEndFAT = off + cArchs * sizeof(fat_arch_t);
+    for (iArch = 0; iArch < cArchs; iArch++)
+    {
+        KCPUARCH    enmEntryArch;
+        fat_arch_t  Arch;
+        rc = kRdrRead(pRdr, &Arch, sizeof(Arch), off);
+        if (rc)
+            return rc;
+        off += sizeof(Arch);
+
+        if (u32Magic == IMAGE_FAT_SIGNATURE_OE)
+        {
+            Arch.cputype    = K_E2E_U32(Arch.cputype);
+            Arch.cpusubtype = K_E2E_U32(Arch.cpusubtype);
+            Arch.offset     = K_E2E_U32(Arch.offset);
+            Arch.size       = K_E2E_U32(Arch.size);
+            Arch.align      = K_E2E_U32(Arch.align);
+        }
+
+        /* Simple validation. */
+        if (    (KLDRFOFF)Arch.offset < offEndFAT
+            ||  (KLDRFOFF)Arch.offset >= kRdrSize(pRdr)
+            ||  Arch.align >= 32
+            ||  Arch.offset & ((KU32_C(1) << Arch.align) - KU32_C(1)))
+            return KLDR_ERR_FAT_INVALID;
+
+        /* deal with the cputype and cpusubtype. (See similar code in kLdrModMachO.c.) */
+        switch (Arch.cputype)
+        {
+            case CPU_TYPE_X86:
+                enmEntryArch = KCPUARCH_X86_32;
+                switch (Arch.cpusubtype)
+                {
+                    case CPU_SUBTYPE_I386_ALL:
+                    /*case CPU_SUBTYPE_386: ^^ ;*/
+                    case CPU_SUBTYPE_486:
+                    case CPU_SUBTYPE_486SX:
+                    /*case CPU_SUBTYPE_586: vv */
+                    case CPU_SUBTYPE_PENT:
+                    case CPU_SUBTYPE_PENTPRO:
+                    case CPU_SUBTYPE_PENTII_M3:
+                    case CPU_SUBTYPE_PENTII_M5:
+                    case CPU_SUBTYPE_CELERON:
+                    case CPU_SUBTYPE_CELERON_MOBILE:
+                    case CPU_SUBTYPE_PENTIUM_3:
+                    case CPU_SUBTYPE_PENTIUM_3_M:
+                    case CPU_SUBTYPE_PENTIUM_3_XEON:
+                    case CPU_SUBTYPE_PENTIUM_M:
+                    case CPU_SUBTYPE_PENTIUM_4:
+                    case CPU_SUBTYPE_PENTIUM_4_M:
+                    case CPU_SUBTYPE_XEON:
+                    case CPU_SUBTYPE_XEON_MP:
+                        break;
+                    default:
+                        return KLDR_ERR_FAT_UNSUPPORTED_CPU_SUBTYPE;
+                }
+                break;
+
+            case CPU_TYPE_X86_64:
+                enmEntryArch = KCPUARCH_AMD64;
+                switch (Arch.cpusubtype & ~CPU_SUBTYPE_MASK)
+                {
+                    case CPU_SUBTYPE_X86_64_ALL:
+                        break;
+                    default:
+                        return KLDR_ERR_FAT_UNSUPPORTED_CPU_SUBTYPE;
+                }
+                break;
+
+            default:
+                enmEntryArch = KCPUARCH_UNKNOWN;
+                break;
+        }
+
+        /*
+         * Finally the actual image selecting.
+         *
+         * Return immediately on a perfect match. Otherwise continue looking,
+         * if we're none too picky, remember the first image in case we don't
+         * get lucky.
+         */
+        if (enmEntryArch == enmCpuArch)
+        {
+            *poffHdr = Arch.offset;
+            return 0;
+        }
+
+        if (    fCpuArchWhatever
+            &&  rcRet == KLDR_ERR_CPU_ARCH_MISMATCH)
+        {
+            *poffHdr = Arch.offset;
+            rcRet = 0;
+        }
+    }
+
+    return rcRet;
+}
+
+
+/**
+ * Open a executable image from a file provider instance.
+ *
+ * @returns 0 on success and *ppMod pointing to a module instance.
+ *          On failure, a non-zero OS specific error code is returned.
+ * @param   pRdr            The file provider instance to use.
+ *                          On success, the ownership of the instance is taken by the
+ *                          module and the caller must not ever touch it again.
+ *                          (The instance is not closed on failure, the call has to do that.)
+ * @param   fFlags          Flags, MBZ.
+ * @param   enmCpuArch      The desired CPU architecture. KCPUARCH_UNKNOWN means
+ *                          anything goes, but with a preference for the current
+ *                          host architecture.
+ * @param   ppMod           Where to store the module handle.
+ */
+int kLdrModOpenFromRdr(PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch, PPKLDRMOD ppMod)
+{
+    union
+    {
+        KU32        u32;
+        KU16        u16;
+        KU16        au16[2];
+        KU8         au8[4];
+    }           u;
+    KLDRFOFF    offHdr = 0;
+    int         rc;
+
+    kHlpAssertReturn(!(fFlags & ~KLDRMOD_OPEN_FLAGS_VALID_MASK), KERR_INVALID_PARAMETER);
+
+    for (;;)
+    {
+        /*
+         * Try figure out what kind of image this is.
+         * Always read the 'new header' if we encounter MZ.
+         */
+        rc = kRdrRead(pRdr, &u, sizeof(u), offHdr);
+        if (rc)
+            return rc;
+        if (    u.u16 == IMAGE_DOS_SIGNATURE
+            &&  kRdrSize(pRdr) > (KFOFF)sizeof(IMAGE_DOS_HEADER))
+        {
+            rc = kRdrRead(pRdr, &u, sizeof(u.u32), K_OFFSETOF(IMAGE_DOS_HEADER, e_lfanew));
+            if (rc)
+                return rc;
+            if ((KLDRFOFF)u.u32 < kRdrSize(pRdr))
+            {
+                offHdr = u.u32;
+                rc = kRdrRead(pRdr, &u, sizeof(u.u32), offHdr);
+                if (rc)
+                    return rc;
+            }
+            else
+                u.u16 = IMAGE_DOS_SIGNATURE;
+        }
+
+        /*
+         * Handle FAT images too here (one only).
+         */
+        if (    (   u.u32 == IMAGE_FAT_SIGNATURE
+                 || u.u32 == IMAGE_FAT_SIGNATURE_OE)
+            &&  offHdr == 0)
+        {
+            rc = kldrModOpenFromRdrSelectImageFromFAT(pRdr, fFlags, enmCpuArch, u.u32, &offHdr);
+            if (rc)
+                return rc;
+            if (offHdr)
+                continue;
+        }
+        break;
+    }
+
+
+    /*
+     * Use the magic to select the appropriate image interpreter head on.
+     */
+    if (u.u16 == IMAGE_DOS_SIGNATURE)
+        rc = KLDR_ERR_MZ_NOT_SUPPORTED;
+    else if (u.u16 == IMAGE_NE_SIGNATURE)
+        rc = KLDR_ERR_NE_NOT_SUPPORTED;
+    else if (u.u16 == IMAGE_LX_SIGNATURE)
+        rc = g_kLdrModLXOps.pfnCreate(&g_kLdrModLXOps, pRdr, fFlags, enmCpuArch, offHdr, ppMod);
+    else if (u.u16 == IMAGE_LE_SIGNATURE)
+        rc = KLDR_ERR_LE_NOT_SUPPORTED;
+    else if (u.u32 == IMAGE_NT_SIGNATURE)
+        rc = g_kLdrModPEOps.pfnCreate(&g_kLdrModPEOps, pRdr, fFlags, enmCpuArch, offHdr, ppMod);
+    else if (   u.u32 == IMAGE_MACHO32_SIGNATURE
+             || u.u32 == IMAGE_MACHO32_SIGNATURE_OE
+             || u.u32 == IMAGE_MACHO64_SIGNATURE
+             || u.u32 == IMAGE_MACHO64_SIGNATURE_OE)
+        rc = g_kLdrModMachOOps.pfnCreate(&g_kLdrModMachOOps, pRdr, fFlags, enmCpuArch, offHdr, ppMod);
+    else if (u.u32 == IMAGE_ELF_SIGNATURE)
+        rc = KLDR_ERR_ELF_NOT_SUPPORTED;
+    else
+        rc = KLDR_ERR_UNKNOWN_FORMAT;
+
+    /*
+     * If no head on hit, let each interpreter have a go.
+     */
+    if (rc)
+    {
+        PCKLDRMODOPS pOps;
+        for (pOps = g_pModInterpreterHead; pOps; pOps = pOps->pNext)
+        {
+            int rc2 = pOps->pfnCreate(pOps, pRdr, fFlags, enmCpuArch, offHdr, ppMod);
+            if (!rc2)
+                return rc;
+        }
+        *ppMod = NULL;
+    }
+    return rc;
+}
+
+
+/**
+ * Closes an open module.
+ *
+ * The caller is responsible for calling kLdrModUnmap() and kLdrFreeTLS()
+ * before closing the module.
+ *
+ * @returns 0 on success, non-zero on failure. The module instance state
+ *          is unknown on failure, it's best not to touch it.
+ * @param   pMod    The module.
+ */
+int     kLdrModClose(PKLDRMOD pMod)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnDestroy(pMod);
+}
+
+
+/**
+ * Queries a symbol by name or ordinal number.
+ *
+ * @returns 0 and *puValue and *pfKind on success.
+ *          KLDR_ERR_SYMBOL_NOT_FOUND is returned if the symbol wasn't found.
+ *          Other failures could stem from bad executable format failures,
+ *          read failure in case pvBits isn't specified and no mapping should be used.
+ * @param   pMod            The module.
+ * @param   pvBits          Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
+ *                          This can be used by some module interpreters to reduce memory consumption.
+ * @param   BaseAddress     The module base address to use when calculating the symbol value.
+ *                          There are two special values that can be used:
+ *                              KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
+ * @param   iSymbol         The symbol ordinal. (optional)
+ * @param   pchSymbol       The symbol name. (optional)
+ *                          Important, this doesn't have to be a null-terminated string.
+ * @param   cchSymbol       The length of the symbol name.
+ * @param   pszVersion      The symbol version. NULL if not versioned.
+ * @param   pfnGetForwarder The callback to use when resolving a forwarder symbol. This is optional
+ *                          and if not specified KLDR_ERR_FORWARDER is returned instead.
+ * @param   pvUser          The user argument for the pfnGetForwarder callback.
+ * @param   puValue         Where to store the symbol value. (optional)
+ * @param   pfKind          On input one of the KLDRSYMKIND_REQ_* #defines.
+ *                          On output the symbol kind. (optional)
+ */
+int     kLdrModQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 iSymbol,
+                           const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion,
+                           PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind)
+{
+    KLDRMOD_VALIDATE(pMod);
+    if (!puValue && !pfKind)
+        return KERR_INVALID_PARAMETER;
+    if (puValue)
+        *puValue = 0;
+    if (pfKind)
+        K_VALIDATE_FLAGS(*pfKind, KLDRSYMKIND_REQ_SEGMENTED);
+    return pMod->pOps->pfnQuerySymbol(pMod, pvBits, BaseAddress, iSymbol, pchSymbol, cchSymbol, pszVersion,
+                                      pfnGetForwarder, pvUser, puValue, pfKind);
+}
+
+
+/**
+ * Enumerate the symbols in the module.
+ *
+ * @returns 0 on success and non-zero a status code on failure.
+ * @param   pMod            The module which symbols should be enumerated.
+ * @param   pvBits          Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
+ *                          This can be used by some module interpreters to reduce memory consumption.
+ * @param   BaseAddress     The module base address to use when calculating the symbol values.
+ *                          There are two special values that could be can:
+ *                              KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
+ * @param   fFlags          The enumeration flags. A combination of the KLDRMOD_ENUM_SYMS_FLAGS_* \#defines.
+ * @param   pfnCallback     The enumeration callback function.
+ * @param   pvUser          The user argument to the callback function.
+ */
+int     kLdrModEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 fFlags,
+                           PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
+{
+    KLDRMOD_VALIDATE(pMod);
+    K_VALIDATE_FLAGS(fFlags, KLDRMOD_ENUM_SYMS_FLAGS_ALL);
+    return pMod->pOps->pfnEnumSymbols(pMod, pvBits, BaseAddress, fFlags, pfnCallback, pvUser);
+}
+
+
+/**
+ * Get the name of an import module by ordinal number.
+ *
+ * @returns 0 and name in pszName on success.
+ *          On buffer overruns KERR_BUFFER_OVERFLOW will be returned.
+ *          On other failures and appropriate error code is returned.
+ * @param   pMod            The module.
+ * @param   pvBits          Optional pointer to bits returned by kLdrModGetBits().
+ *                          This can be used by some module interpreters to reduce memory consumption.
+ * @param   iImport         The import module ordinal number.
+ * @param   pszName         Where to store the name.
+ * @param   cchName         The size of the name buffer.
+ */
+int     kLdrModGetImport(PKLDRMOD pMod, const void *pvBits, KU32 iImport, char *pszName, KSIZE cchName)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnGetImport(pMod, pvBits, iImport, pszName, cchName);
+}
+
+
+/**
+ * Get the number of import modules.
+ *
+ * @returns The number of import modules. -1 if something really bad happens.
+ * @param   pMod            The module.
+ * @param   pvBits          Optional pointer to bits returned by kLdrModGetBits().
+ *                          This can be used by some module interpreters to reduce memory consumption.
+ */
+KI32 kLdrModNumberOfImports(PKLDRMOD pMod, const void *pvBits)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnNumberOfImports(pMod, pvBits);
+}
+
+
+/**
+ * Checks if this module can be executed by the specified arch+cpu.
+ *
+ * @returns 0 if it can, KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE if it can't.
+ *          Other failures may occur and cause other return values.
+ * @param   pMod            The module.
+ * @param   pvBits          Optional pointer to bits returned by kLdrModGetBits().
+ *                          This can be used by some module interpreters to reduce memory consumption.
+ * @param   enmArch         The CPU architecture.
+ * @param   enmCpu          The CPU series/model.
+ */
+int     kLdrModCanExecuteOn(PKLDRMOD pMod, const void *pvBits, KCPUARCH enmArch, KCPU enmCpu)
+{
+    KLDRMOD_VALIDATE(pMod);
+    if (pMod->pOps->pfnCanExecuteOn)
+        return pMod->pOps->pfnCanExecuteOn(pMod, pvBits, enmArch, enmCpu);
+    return kCpuCompare(pMod->enmArch, pMod->enmCpu, enmArch, enmCpu);
+}
+
+
+/**
+ * Gets the image stack info.
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param   pMod
+ * @param   pvBits          Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
+ *                          This can be used by some module interpreters to reduce memory consumption.
+ * @param   BaseAddress     The module base address to use when calculating the stack address.
+ *                          There are two special values that can be used:
+ *                              KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
+ * @param   pStackInfo      The stack information.
+ */
+int     kLdrModGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnGetStackInfo(pMod, pvBits, BaseAddress, pStackInfo);
+}
+
+
+/**
+ * Queries the main entrypoint of the module.
+ *
+ * Only executable are supposed to have an main entrypoint, though some object and DLL
+ * formats will also allow this.
+ *
+ * @returns 0 and *pMainEPAddress on success. Non-zero status code on failure.
+ * @param   pMod            The module.
+ * @param   pvBits          Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
+ *                          This can be used by some module interpreters to reduce memory consumption.
+ * @param   BaseAddress     The module base address to use when calculating the entrypoint address.
+ *                          There are two special values that can be used:
+ *                              KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
+ * @param   pMainEPAddress  Where to store the entry point address.
+ */
+int     kLdrModQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress)
+{
+    KLDRMOD_VALIDATE(pMod);
+    *pMainEPAddress = 0;
+    return pMod->pOps->pfnQueryMainEntrypoint(pMod, pvBits, BaseAddress, pMainEPAddress);
+}
+
+
+/**
+ * Queries the image UUID, if the image has one.
+ *
+ * @returns 0 and *pvUuid. Non-zero status code on failure.
+ * @param   pMod            The module.
+ * @param   pvBits          Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
+ *                          This can be used by some module interpreters to reduce memory consumption.
+ * @param   pvUuid          Where to store the UUID.
+ * @param   cbUuid          Size of the UUID buffer, must be at least 16 bytes.
+ */
+int     kLdrModQueryImageUuid(PKLDRMOD pMod, const void *pvBits, void *pvUuid, KSIZE cbUuid)
+{
+    KLDRMOD_VALIDATE(pMod);
+    if (cbUuid < 16)
+        return KERR_INVALID_SIZE;
+    if (pMod->pOps->pfnQueryImageUuid)
+        return pMod->pOps->pfnQueryImageUuid(pMod, pvBits, pvUuid, cbUuid);
+    return KLDR_ERR_NO_IMAGE_UUID;
+}
+
+
+/**
+ * Queries info about a resource.
+ *
+ * If there are multiple resources matching the criteria, the best or
+ * first match will be return.
+ *
+ *
+ * @returns 0 on success.
+ * @returns Whatever non-zero status returned by pfnCallback (enumeration was stopped).
+ * @returns non-zero kLdr or native status code on failure.
+ *
+ * @param   pMod            The module.
+ * @param   pvBits          Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
+ *                          This can be used by some module interpreters to reduce memory consumption.
+ * @param   BaseAddress     The module base address to use when calculating the resource addresses.
+ *                          There are two special values that can be used:
+ *                              KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
+ * @param   idType          The resource type id to match if not NIL_KLDRMOD_RSRC_TYPE_ID.
+ * @param   pszType         The resource type name to match if no NULL.
+ * @param   idName          The resource name id to match if not NIL_KLDRMOD_RSRC_NAME_ID.
+ * @param   pszName         The resource name to match if not NULL.
+ * @param   idLang          The language id to match.
+ * @param   pfnCallback     The callback function.
+ * @param   pvUser          The user argument for the callback.
+ */
+int     kLdrModQueryResource(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 idType, const char *pszType,
+                             KU32 idName, const char *pszName, KU32 idLang, PKLDRADDR pAddrRsrc, KSIZE *pcbRsrc)
+{
+    KLDRMOD_VALIDATE(pMod);
+    if (!pAddrRsrc && !pcbRsrc)
+        return KERR_INVALID_PARAMETER;
+    if (pAddrRsrc)
+        *pAddrRsrc = NIL_KLDRADDR;
+    if (pcbRsrc)
+        *pcbRsrc = 0;
+    return pMod->pOps->pfnQueryResource(pMod, pvBits, BaseAddress, idType, pszType, idName, pszName, idLang, pAddrRsrc, pcbRsrc);
+}
+
+
+/**
+ * Enumerates the resources matching the specfied criteria.
+ *
+ *
+ * @returns 0 on success.
+ * @returns Whatever non-zero status returned by pfnCallback (enumeration was stopped).
+ * @returns non-zero kLdr or native status code on failure.
+ *
+ * @param   pMod            The module.
+ * @param   pvBits          Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
+ *                          This can be used by some module interpreters to reduce memory consumption.
+ * @param   BaseAddress     The module base address to use when calculating the resource addresses.
+ *                          There are two special values that can be used:
+ *                              KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
+ * @param   idType          The resource type id to match if not NIL_KLDRMOD_RSRC_TYPE_ID.
+ * @param   pszType         The resource type name to match if no NULL.
+ * @param   idName          The resource name id to match if not NIL_KLDRMOD_RSRC_NAME_ID.
+ * @param   pszName         The resource name to match if not NULL.
+ * @param   idLang          The language id to match.
+ * @param   pfnCallback     The callback function.
+ * @param   pvUser          The user argument for the callback.
+ */
+int     kLdrModEnumResources(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 idType, const char *pszType,
+                             KU32 idName, const char *pszName, KU32 idLang, PFNKLDRENUMRSRC pfnCallback, void *pvUser)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnEnumResources(pMod, pvBits, BaseAddress, idType, pszType, idName, pszName, idLang, pfnCallback, pvUser);
+}
+
+
+/**
+ * Enumerate the debug info formats contained in the executable image.
+ *
+ * @returns 0 on success, non-zero OS or kLdr status code on failure, or non-zero callback status.
+ * @param   pMod            The module.
+ * @param   pvBits          Optional pointer to bits returned by kLdrModGetBits().
+ *                          This can be used by some module interpreters to reduce memory consumption.
+ * @param   pfnCallback     The callback function.
+ * @param   pvUser          The user argument.
+ * @see pg_kDbg for the debug info reader.
+ */
+int     kLdrModEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnEnumDbgInfo(pMod, pvBits, pfnCallback, pvUser);
+}
+
+
+/**
+ * Checks if the module has debug info embedded or otherwise associated with it.
+ *
+ * @returns 0 if it has debug info, KLDR_ERR_NO_DEBUG_INFO if no debug info,
+ *          and non-zero OS or kLdr status code on failure.
+ * @param   pMod            The module.
+ * @param   pvBits          Optional pointer to bits returned by kLdrModGetBits().
+ *                          This can be used by some module interpreters to reduce memory consumption.
+ */
+int     kLdrModHasDbgInfo(PKLDRMOD pMod, const void *pvBits)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnHasDbgInfo(pMod, pvBits);
+}
+
+
+/**
+ * May free up some resources held by the module.
+ *
+ * @todo define exactly what it possible to do after this call.
+ *
+ * @returns 0 on success, KLDR_ERR_* on failure.
+ * @param   pMod    The module.
+ */
+int     kLdrModMostlyDone(PKLDRMOD pMod)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnMostlyDone(pMod);
+}
+
+
+/**
+ * Maps the module into the memory of the caller.
+ *
+ * On success the actual addresses for the segments can be found in MapAddress
+ * member of each segment in the segment array.
+ *
+ * @returns 0 on success, non-zero OS or kLdr status code on failure.
+ * @param   pMod            The module to be mapped.
+ * @remark  kLdr only supports one mapping at a time of a module.
+ */
+int     kLdrModMap(PKLDRMOD pMod)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnMap(pMod);
+}
+
+
+/**
+ * Unmaps a module previously mapped by kLdrModMap().
+ *
+ * @returns 0 on success, non-zero OS or kLdr status code on failure.
+ * @param   pMod            The module to unmap.
+ */
+int     kLdrModUnmap(PKLDRMOD pMod)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnUnmap(pMod);
+}
+
+
+/**
+ * Reloads all dirty pages in a module previously mapped by kLdrModMap().
+ *
+ * The module interpreter may omit code pages if it can safely apply code
+ * fixups again in a subsequent kLdrModFixupMapping() call.
+ *
+ * The caller is responsible for freeing TLS before calling this function.
+ *
+ * @returns 0 on success, non-zero OS or kLdr status code on failure.
+ * @param   pMod            The module.
+ */
+int     kLdrModReload(PKLDRMOD pMod)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnReload(pMod);
+}
+
+
+/**
+ * Fixup the mapping made by kLdrModMap().
+ *
+ * The caller is only responsible for not calling this function more than
+ * once without doing kLDrModReload() inbetween.
+ *
+ * @returns 0 on success, non-zero OS or kLdr status code on failure.
+ * @param   pMod            The module.
+ * @param   pfnGetImport    The callback for resolving external (imported) symbols.
+ * @param   pvUser          The callback user argument.
+ */
+int     kLdrModFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnFixupMapping(pMod, pfnGetImport, pvUser);
+}
+
+
+/**
+ * Get the size of the mapped module.
+ *
+ * @returns The size of the mapped module (in bytes).
+ * @param   pMod            The module.
+ */
+KLDRADDR kLdrModSize(PKLDRMOD pMod)
+{
+    KLDRMOD_VALIDATE_EX(pMod, 0);
+    return pMod->pOps->pfnSize(pMod);
+}
+
+
+/**
+ * Gets the module bits.
+ *
+ * The module interpreter will fill a mapping allocated by the caller with the
+ * module bits reallocated to the specified address.
+ *
+ * @returns 0 on succes, non-zero OS or kLdr status code on failure.
+ * @param   pMod            The module.
+ * @param   pvBits          Where to put the bits.
+ * @param   BaseAddress     The base address that should correspond to the first byte in pvBits
+ *                          upon return.
+ * @param   pfnGetImport    The callback ufor resolving external (imported) symbols.
+ * @param   pvUser          The callback user argument.
+ */
+int     kLdrModGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnGetBits(pMod, pvBits, BaseAddress, pfnGetImport, pvUser);
+}
+
+
+/**
+ * Relocates the module bits previously obtained by kLdrModGetBits().
+ *
+ * @returns 0 on succes, non-zero OS or kLdr status code on failure.
+ * @param   pMod            The module.
+ * @param   pvBits          Where to put the bits.
+ * @param   NewBaseAddress  The new base address.
+ * @param   OldBaseAddress  The old base address (i.e. the one specified to kLdrModGetBits() or as
+ *                          NewBaseAddressto the previous kLdrModRelocateBits() call).
+ * @param   pfnGetImport    The callback ufor resolving external (imported) symbols.
+ * @param   pvUser          The callback user argument.
+ */
+int     kLdrModRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
+                            PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnRelocateBits(pMod, pvBits, NewBaseAddress, OldBaseAddress, pfnGetImport, pvUser);
+}
+
+
+/**
+ * Allocates Thread Local Storage for module mapped by kLdrModMap().
+ *
+ * Calling kLdrModAllocTLS() more than once without calling kLdrModFreeTLS()
+ * between each invocation is not supported.
+ *
+ * @returns 0 on success, non-zero OS or kLdr status code on failure.
+ * @param   pMod            The module.
+ * @param   pvMapping       The external mapping address or RTLDRMOD_INT_MAP.
+ */
+int     kLdrModAllocTLS(PKLDRMOD pMod, void *pvMapping)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnAllocTLS(pMod, pvMapping);
+}
+
+
+/**
+ * Frees Thread Local Storage previously allocated by kLdrModAllocTLS().
+ *
+ * The caller is responsible for only calling kLdrModFreeTLS() once
+ * after calling kLdrModAllocTLS().
+ *
+ * @returns 0 on success, non-zero OS or kLdr status code on failure.
+ * @param   pMod            The module.
+ * @param   pvMapping       The external mapping address or RTLDRMOD_INT_MAP.
+ */
+void    kLdrModFreeTLS(PKLDRMOD pMod, void *pvMapping)
+{
+    KLDRMOD_VALIDATE_VOID(pMod);
+    pMod->pOps->pfnFreeTLS(pMod, pvMapping);
+}
+
+
+
+
+/**
+ * Call the module initializiation function of a mapped module (if any).
+ *
+ * @returns 0 on success or no init function, non-zero on init function failure or invalid pMod.
+ * @param   pMod            The module.
+ * @param   pvMapping       The external mapping address or RTLDRMOD_INT_MAP.
+ * @param   uHandle         The module handle to use if any of the init functions requires the module handle.
+ */
+int     kLdrModCallInit(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnCallInit(pMod, pvMapping, uHandle);
+}
+
+
+/**
+ * Call the module termination function of a mapped module (if any).
+ *
+ * @returns 0 on success or no term function, non-zero on invalid pMod.
+ * @param   pMod            The module.
+ * @param   pvMapping       The external mapping address or RTLDRMOD_INT_MAP.
+ * @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, void *pvMapping, KUPTR uHandle)
+{
+    KLDRMOD_VALIDATE(pMod);
+    return pMod->pOps->pfnCallTerm(pMod, pvMapping, uHandle);
+}
+
+
+/**
+ * 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   pvMapping       The external mapping address or RTLDRMOD_INT_MAP.
+ * @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, void *pvMapping, KUPTR uHandle, unsigned fAttachingOrDetaching)
+{
+    KLDRMOD_VALIDATE(pMod);
+    K_VALIDATE_FLAGS(fAttachingOrDetaching, 1);
+    return pMod->pOps->pfnCallThread(pMod, pvMapping, uHandle, fAttachingOrDetaching);
+}
+
diff --git a/src/lib/kStuff/kLdr/kLdrModLX.c b/src/lib/kStuff/kLdr/kLdrModLX.c
new file mode 100644
index 0000000..b05dd15
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrModLX.c
@@ -0,0 +1,2698 @@
+/* $Id: kLdrModLX.c 81 2016-08-18 22:10:38Z bird $ */
+/** @file
+ * kLdr - The Module Interpreter for the Linear eXecutable (LX) Format.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kLdr.h>
+#include "kLdrInternal.h"
+#include <k/kLdrFmts/lx.h>
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** @def KLDRMODLX_STRICT
+ * Define KLDRMODLX_STRICT to enabled strict checks in KLDRMODLX. */
+#define KLDRMODLX_STRICT 1
+
+/** @def KLDRMODLX_ASSERT
+ * Assert that an expression is true when KLDR_STRICT is defined.
+ */
+#ifdef KLDRMODLX_STRICT
+# define KLDRMODLX_ASSERT(expr)  kHlpAssert(expr)
+#else
+# define KLDRMODLX_ASSERT(expr)  do {} while (0)
+#endif
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Instance data for the LX module interpreter.
+ */
+typedef struct KLDRMODLX
+{
+    /** Pointer to the module. (Follows the section table.) */
+    PKLDRMOD                pMod;
+    /** Pointer to the user mapping. */
+    const void             *pvMapping;
+    /** The size of the mapped LX image. */
+    KSIZE                   cbMapped;
+    /** Reserved flags. */
+    KU32                    f32Reserved;
+
+    /** The offset of the LX header. */
+    KLDRFOFF                offHdr;
+    /** Copy of the LX header. */
+    struct e32_exe          Hdr;
+
+    /** Pointer to the loader section.
+     * Allocated together with this strcture. */
+    const KU8              *pbLoaderSection;
+    /** Pointer to the last byte in the loader section. */
+    const KU8              *pbLoaderSectionLast;
+    /** Pointer to the object table in the loader section. */
+    const struct o32_obj   *paObjs;
+    /** Pointer to the object page map table in the loader section. */
+    const struct o32_map   *paPageMappings;
+    /** Pointer to the resource table in the loader section. */
+    const struct rsrc32    *paRsrcs;
+    /** Pointer to the resident name table in the loader section. */
+    const KU8              *pbResNameTab;
+    /** Pointer to the entry table in the loader section. */
+    const KU8              *pbEntryTab;
+
+    /** Pointer to the non-resident name table. */
+    KU8                    *pbNonResNameTab;
+    /** Pointer to the last byte in the non-resident name table. */
+    const KU8              *pbNonResNameTabLast;
+
+    /** Pointer to the fixup section. */
+    KU8                    *pbFixupSection;
+    /** Pointer to the last byte in the fixup section. */
+    const KU8              *pbFixupSectionLast;
+    /** Pointer to the fixup page table within pvFixupSection. */
+    const KU32             *paoffPageFixups;
+    /** Pointer to the fixup record table within pvFixupSection. */
+    const KU8              *pbFixupRecs;
+    /** Pointer to the import module name table within pvFixupSection. */
+    const KU8              *pbImportMods;
+    /** Pointer to the import module name table within pvFixupSection. */
+    const KU8              *pbImportProcs;
+} KLDRMODLX, *PKLDRMODLX;
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static int kldrModLXHasDbgInfo(PKLDRMOD pMod, const void *pvBits);
+static int kldrModLXRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
+                                 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
+static int kldrModLXDoCreate(PKRDR pRdr, KLDRFOFF offNewHdr, PKLDRMODLX *ppModLX);
+static const KU8 *kldrModLXDoNameTableLookupByOrdinal(const KU8 *pbNameTable, KI32 cbNameTable, KU32 iOrdinal);
+static int kldrModLXDoNameLookup(PKLDRMODLX pModLX, const char *pchSymbol, KU32 cchSymbol, KU32 *piSymbol);
+static const KU8 *kldrModLXDoNameTableLookupByName(const KU8 *pbNameTable, KI32 cbNameTable,
+                                                       const char *pchSymbol, KSIZE cchSymbol);
+static int kldrModLXDoLoadBits(PKLDRMODLX pModLX, void *pvBits);
+static int kldrModLXDoIterDataUnpacking(KU8 *pbDst, const KU8 *pbSrc, int cbSrc);
+static int kldrModLXDoIterData2Unpacking(KU8 *pbDst, const KU8 *pbSrc, int cbSrc);
+static void kLdrModLXMemCopyW(KU8 *pbDst, const KU8 *pbSrc, int cb);
+static int kldrModLXDoProtect(PKLDRMODLX pModLX, void *pvBits, unsigned fUnprotectOrProtect);
+static int kldrModLXDoCallDLL(PKLDRMODLX pModLX, void *pvMapping, unsigned uOp, KUPTR uHandle);
+static int kldrModLXDoForwarderQuery(PKLDRMODLX pModLX, const struct e32_entry *pEntry,
+                                     PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind);
+static int kldrModLXDoLoadFixupSection(PKLDRMODLX pModLX);
+static KI32 kldrModLXDoCall(KUPTR uEntrypoint, KUPTR uHandle, KU32 uOp, void *pvReserved);
+static int kldrModLXDoReloc(KU8 *pbPage, int off, KLDRADDR PageAddress, const struct r32_rlc *prlc,
+                            int iSelector, KLDRADDR uValue, KU32 fKind);
+
+
+/**
+ * Create a loader module instance interpreting the executable image found
+ * in the specified file provider instance.
+ *
+ * @returns 0 on success and *ppMod pointing to a module instance.
+ *          On failure, a non-zero OS specific error code is returned.
+ * @param   pOps            Pointer to the registered method table.
+ * @param   pRdr            The file provider instance to use.
+ * @param   fFlags          Flags, MBZ.
+ * @param   enmCpuArch      The desired CPU architecture. KCPUARCH_UNKNOWN means
+ *                          anything goes, but with a preference for the current
+ *                          host architecture.
+ * @param   offNewHdr       The offset of the new header in MZ files. -1 if not found.
+ * @param   ppMod           Where to store the module instance pointer.
+ */
+static int kldrModLXCreate(PCKLDRMODOPS pOps, PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch, KLDRFOFF offNewHdr, PPKLDRMOD ppMod)
+{
+    PKLDRMODLX pModLX;
+    int rc;
+    K_NOREF(fFlags);
+
+    /*
+     * Create the instance data and do a minimal header validation.
+     */
+    rc = kldrModLXDoCreate(pRdr, offNewHdr, &pModLX);
+    if (!rc)
+    {
+        /*
+         * Match up against the requested CPU architecture.
+         */
+        if (    enmCpuArch == KCPUARCH_UNKNOWN
+            ||  pModLX->pMod->enmArch == enmCpuArch)
+        {
+            pModLX->pMod->pOps = pOps;
+            pModLX->pMod->u32Magic = KLDRMOD_MAGIC;
+            *ppMod = pModLX->pMod;
+            return 0;
+        }
+        rc = KLDR_ERR_CPU_ARCH_MISMATCH;
+    }
+    kHlpFree(pModLX);
+    return rc;
+}
+
+
+/**
+ * Separate function for reading creating the LX module instance to
+ * simplify cleanup on failure.
+ */
+static int kldrModLXDoCreate(PKRDR pRdr, KLDRFOFF offNewHdr, PKLDRMODLX *ppModLX)
+{
+    struct e32_exe Hdr;
+    PKLDRMODLX pModLX;
+    PKLDRMOD pMod;
+    KSIZE cb;
+    KSIZE cchFilename;
+    KU32 off, offEnd;
+    KU32 i;
+    int rc;
+    int fCanOptimizeMapping;
+    KU32 NextRVA;
+    *ppModLX = NULL;
+
+    /*
+     * Read the signature and file header.
+     */
+    rc = kRdrRead(pRdr, &Hdr, sizeof(Hdr), offNewHdr > 0 ? offNewHdr : 0);
+    if (rc)
+        return rc;
+    if (    Hdr.e32_magic[0] != E32MAGIC1
+        ||  Hdr.e32_magic[1] != E32MAGIC2)
+        return KLDR_ERR_UNKNOWN_FORMAT;
+
+    /* We're not interested in anything but x86 images. */
+    if (    Hdr.e32_level != E32LEVEL
+        ||  Hdr.e32_border != E32LEBO
+        ||  Hdr.e32_worder != E32LEWO
+        ||  Hdr.e32_cpu < E32CPU286
+        ||  Hdr.e32_cpu > E32CPU486
+        ||  Hdr.e32_pagesize != OBJPAGELEN
+        )
+        return KLDR_ERR_LX_BAD_HEADER;
+
+    /* Some rough sanity checks. */
+    offEnd = kRdrSize(pRdr) >= (KLDRFOFF)~(KU32)16 ? ~(KU32)16 : (KU32)kRdrSize(pRdr);
+    if (    Hdr.e32_itermap > offEnd
+        ||  Hdr.e32_datapage > offEnd
+        ||  Hdr.e32_nrestab > offEnd
+        ||  Hdr.e32_nrestab + Hdr.e32_cbnrestab > offEnd
+        ||  Hdr.e32_ldrsize > offEnd - offNewHdr - sizeof(Hdr)
+        ||  Hdr.e32_fixupsize > offEnd - offNewHdr - sizeof(Hdr)
+        ||  Hdr.e32_fixupsize + Hdr.e32_ldrsize > offEnd - offNewHdr - sizeof(Hdr))
+        return KLDR_ERR_LX_BAD_HEADER;
+
+    /* Verify the loader section. */
+    offEnd = Hdr.e32_objtab + Hdr.e32_ldrsize;
+    if (Hdr.e32_objtab < sizeof(Hdr))
+        return KLDR_ERR_LX_BAD_LOADER_SECTION;
+    off = Hdr.e32_objtab + sizeof(struct o32_obj) * Hdr.e32_objcnt;
+    if (off > offEnd)
+        return KLDR_ERR_LX_BAD_LOADER_SECTION;
+    if (    Hdr.e32_objmap
+        &&  (Hdr.e32_objmap < off || Hdr.e32_objmap > offEnd))
+        return KLDR_ERR_LX_BAD_LOADER_SECTION;
+    if (    Hdr.e32_rsrccnt
+        && (   Hdr.e32_rsrctab < off
+            || Hdr.e32_rsrctab > offEnd
+            || Hdr.e32_rsrctab + sizeof(struct rsrc32) * Hdr.e32_rsrccnt > offEnd))
+        return KLDR_ERR_LX_BAD_LOADER_SECTION;
+    if (    Hdr.e32_restab
+        &&  (Hdr.e32_restab < off || Hdr.e32_restab > offEnd - 2))
+        return KLDR_ERR_LX_BAD_LOADER_SECTION;
+    if (    Hdr.e32_enttab
+        &&  (Hdr.e32_enttab < off || Hdr.e32_enttab >= offEnd))
+        return KLDR_ERR_LX_BAD_LOADER_SECTION;
+    if (    Hdr.e32_dircnt
+        && (Hdr.e32_dirtab < off || Hdr.e32_dirtab > offEnd - 2))
+        return KLDR_ERR_LX_BAD_LOADER_SECTION;
+
+    /* Verify the fixup section. */
+    off = offEnd;
+    offEnd = off + Hdr.e32_fixupsize;
+    if (    Hdr.e32_fpagetab
+        &&  (Hdr.e32_fpagetab < off || Hdr.e32_fpagetab > offEnd))
+    {
+        /*
+         * wlink mixes the fixup section and the loader section.
+         */
+        off = Hdr.e32_fpagetab;
+        offEnd = off + Hdr.e32_fixupsize;
+        Hdr.e32_ldrsize = off - Hdr.e32_objtab;
+    }
+    if (    Hdr.e32_frectab
+        &&  (Hdr.e32_frectab < off || Hdr.e32_frectab > offEnd))
+        return KLDR_ERR_LX_BAD_FIXUP_SECTION;
+    if (    Hdr.e32_impmod
+        &&  (Hdr.e32_impmod < off || Hdr.e32_impmod > offEnd || Hdr.e32_impmod + Hdr.e32_impmodcnt > offEnd))
+        return KLDR_ERR_LX_BAD_FIXUP_SECTION;
+    if (    Hdr.e32_impproc
+        &&  (Hdr.e32_impproc < off || Hdr.e32_impproc > offEnd))
+        return KLDR_ERR_LX_BAD_FIXUP_SECTION;
+
+    /*
+     * Calc the instance size, allocate and initialize it.
+     */
+    cchFilename = kHlpStrLen(kRdrName(pRdr));
+    cb = K_ALIGN_Z(sizeof(KLDRMODLX), 8)
+       + K_ALIGN_Z(K_OFFSETOF(KLDRMOD, aSegments[Hdr.e32_objcnt + 1]), 8)
+       + K_ALIGN_Z(cchFilename + 1, 8)
+       + Hdr.e32_ldrsize + 2; /* +2 for two extra zeros. */
+    pModLX = (PKLDRMODLX)kHlpAlloc(cb);
+    if (!pModLX)
+        return KERR_NO_MEMORY;
+    *ppModLX = pModLX;
+
+    /* KLDRMOD */
+    pMod = (PKLDRMOD)((KU8 *)pModLX + K_ALIGN_Z(sizeof(KLDRMODLX), 8));
+    pMod->pvData = pModLX;
+    pMod->pRdr = pRdr;
+    pMod->pOps = NULL;      /* set upon success. */
+    pMod->cSegments = Hdr.e32_objcnt;
+    pMod->cchFilename = cchFilename;
+    pMod->pszFilename = (char *)K_ALIGN_P(&pMod->aSegments[pMod->cSegments], 8);
+    kHlpMemCopy((char *)pMod->pszFilename, kRdrName(pRdr), cchFilename + 1);
+    pMod->pszName = NULL; /* finalized further down */
+    pMod->cchName = 0;
+    pMod->fFlags = 0;
+    switch (Hdr.e32_cpu)
+    {
+        case E32CPU286:
+            pMod->enmCpu = KCPU_I80286;
+            pMod->enmArch = KCPUARCH_X86_16;
+            break;
+        case E32CPU386:
+            pMod->enmCpu = KCPU_I386;
+            pMod->enmArch = KCPUARCH_X86_32;
+            break;
+        case E32CPU486:
+            pMod->enmCpu = KCPU_I486;
+            pMod->enmArch = KCPUARCH_X86_32;
+            break;
+    }
+    pMod->enmEndian = KLDRENDIAN_LITTLE;
+    pMod->enmFmt = KLDRFMT_LX;
+    switch (Hdr.e32_mflags & E32MODMASK)
+    {
+        case E32MODEXE:
+            pMod->enmType = !(Hdr.e32_mflags & E32NOINTFIX)
+                ? KLDRTYPE_EXECUTABLE_RELOCATABLE
+                : KLDRTYPE_EXECUTABLE_FIXED;
+            break;
+
+        case E32MODDLL:
+        case E32PROTDLL:
+        case E32MODPROTDLL:
+            pMod->enmType = !(Hdr.e32_mflags & E32SYSDLL)
+                ? KLDRTYPE_SHARED_LIBRARY_RELOCATABLE
+                : KLDRTYPE_SHARED_LIBRARY_FIXED;
+            break;
+
+        case E32MODPDEV:
+        case E32MODVDEV:
+            pMod->enmType = KLDRTYPE_SHARED_LIBRARY_RELOCATABLE;
+            break;
+    }
+    pMod->u32Magic = 0;     /* set upon success. */
+
+    /* KLDRMODLX */
+    pModLX->pMod = pMod;
+    pModLX->pvMapping = 0;
+    pModLX->cbMapped = 0;
+    pModLX->f32Reserved = 0;
+
+    pModLX->offHdr = offNewHdr >= 0 ? offNewHdr : 0;
+    kHlpMemCopy(&pModLX->Hdr, &Hdr, sizeof(Hdr));
+
+    pModLX->pbLoaderSection = K_ALIGN_P(pMod->pszFilename + pMod->cchFilename + 1, 16);
+    pModLX->pbLoaderSectionLast = pModLX->pbLoaderSection + pModLX->Hdr.e32_ldrsize - 1;
+    pModLX->paObjs = NULL;
+    pModLX->paPageMappings = NULL;
+    pModLX->paRsrcs = NULL;
+    pModLX->pbResNameTab = NULL;
+    pModLX->pbEntryTab = NULL;
+
+    pModLX->pbNonResNameTab = NULL;
+    pModLX->pbNonResNameTabLast = NULL;
+
+    pModLX->pbFixupSection = NULL;
+    pModLX->pbFixupSectionLast = NULL;
+    pModLX->paoffPageFixups = NULL;
+    pModLX->pbFixupRecs = NULL;
+    pModLX->pbImportMods = NULL;
+    pModLX->pbImportProcs = NULL;
+
+    /*
+     * Read the loader data.
+     */
+    rc = kRdrRead(pRdr, (void *)pModLX->pbLoaderSection, pModLX->Hdr.e32_ldrsize, pModLX->Hdr.e32_objtab + pModLX->offHdr);
+    if (rc)
+        return rc;
+    ((KU8 *)pModLX->pbLoaderSectionLast)[1] = 0;
+    ((KU8 *)pModLX->pbLoaderSectionLast)[2] = 0;
+    if (pModLX->Hdr.e32_objcnt)
+        pModLX->paObjs = (const struct o32_obj *)pModLX->pbLoaderSection;
+    if (pModLX->Hdr.e32_objmap)
+        pModLX->paPageMappings = (const struct o32_map *)(pModLX->pbLoaderSection + pModLX->Hdr.e32_objmap - pModLX->Hdr.e32_objtab);
+    if (pModLX->Hdr.e32_rsrccnt)
+        pModLX->paRsrcs = (const struct rsrc32 *)(pModLX->pbLoaderSection + pModLX->Hdr.e32_rsrctab - pModLX->Hdr.e32_objtab);
+    if (pModLX->Hdr.e32_restab)
+        pModLX->pbResNameTab = pModLX->pbLoaderSection + pModLX->Hdr.e32_restab - pModLX->Hdr.e32_objtab;
+    if (pModLX->Hdr.e32_enttab)
+        pModLX->pbEntryTab = pModLX->pbLoaderSection + pModLX->Hdr.e32_enttab - pModLX->Hdr.e32_objtab;
+
+    /*
+     * Get the soname from the resident name table.
+     * Very convenient that it's the 0 ordinal, because then we get a
+     * free string terminator.
+     * (The table entry consists of a pascal string followed by a 16-bit ordinal.)
+     */
+    if (pModLX->pbResNameTab)
+        pMod->pszName = (const char *)kldrModLXDoNameTableLookupByOrdinal(pModLX->pbResNameTab,
+                                                                          pModLX->pbLoaderSectionLast - pModLX->pbResNameTab + 1,
+                                                                          0);
+    if (!pMod->pszName)
+        return KLDR_ERR_LX_NO_SONAME;
+    pMod->cchName = *(const KU8 *)pMod->pszName++;
+    if (pMod->cchName != kHlpStrLen(pMod->pszName))
+        return KLDR_ERR_LX_BAD_SONAME;
+
+    /*
+     * Quick validation of the object table.
+     */
+    cb = 0;
+    for (i = 0; i < pMod->cSegments; i++)
+    {
+        if (pModLX->paObjs[i].o32_base & (OBJPAGELEN - 1))
+            return KLDR_ERR_LX_BAD_OBJECT_TABLE;
+        if (pModLX->paObjs[i].o32_base + pModLX->paObjs[i].o32_size <= pModLX->paObjs[i].o32_base)
+            return KLDR_ERR_LX_BAD_OBJECT_TABLE;
+        if (pModLX->paObjs[i].o32_mapsize > (pModLX->paObjs[i].o32_size + (OBJPAGELEN - 1)))
+            return KLDR_ERR_LX_BAD_OBJECT_TABLE;
+        if (    pModLX->paObjs[i].o32_mapsize
+            &&  (   (KU8 *)&pModLX->paPageMappings[pModLX->paObjs[i].o32_pagemap] > pModLX->pbLoaderSectionLast
+                 || (KU8 *)&pModLX->paPageMappings[pModLX->paObjs[i].o32_pagemap + pModLX->paObjs[i].o32_mapsize]
+                     > pModLX->pbLoaderSectionLast))
+            return KLDR_ERR_LX_BAD_OBJECT_TABLE;
+        if (i > 0 && !(pModLX->paObjs[i].o32_flags & OBJRSRC))
+        {
+            if (pModLX->paObjs[i].o32_base <= pModLX->paObjs[i - 1].o32_base)
+                return KLDR_ERR_LX_BAD_OBJECT_TABLE;
+            if (pModLX->paObjs[i].o32_base < pModLX->paObjs[i - 1].o32_base + pModLX->paObjs[i - 1].o32_mapsize)
+                return KLDR_ERR_LX_BAD_OBJECT_TABLE;
+        }
+    }
+
+    /*
+     * Check if we can optimize the mapping by using a different
+     * object alignment. The linker typically uses 64KB alignment,
+     * we can easily get away with page alignment in most cases.
+     */
+    fCanOptimizeMapping = !(Hdr.e32_mflags & (E32NOINTFIX | E32SYSDLL));
+    NextRVA = 0;
+
+    /*
+     * Setup the KLDRMOD segment array.
+     */
+    for (i = 0; i < pMod->cSegments; i++)
+    {
+        /* unused */
+        pMod->aSegments[i].pvUser = NULL;
+        pMod->aSegments[i].MapAddress = 0;
+        pMod->aSegments[i].pchName = NULL;
+        pMod->aSegments[i].cchName = 0;
+        pMod->aSegments[i].offFile = -1;
+        pMod->aSegments[i].cbFile = -1;
+        pMod->aSegments[i].SelFlat = 0;
+        pMod->aSegments[i].Sel16bit = 0;
+
+        /* flags */
+        pMod->aSegments[i].fFlags = 0;
+        if (pModLX->paObjs[i].o32_flags & OBJBIGDEF)
+            pMod->aSegments[i].fFlags = KLDRSEG_FLAG_16BIT;
+        if (pModLX->paObjs[i].o32_flags & OBJALIAS16)
+            pMod->aSegments[i].fFlags = KLDRSEG_FLAG_OS2_ALIAS16;
+        if (pModLX->paObjs[i].o32_flags & OBJCONFORM)
+            pMod->aSegments[i].fFlags = KLDRSEG_FLAG_OS2_CONFORM;
+        if (pModLX->paObjs[i].o32_flags & OBJIOPL)
+            pMod->aSegments[i].fFlags = KLDRSEG_FLAG_OS2_IOPL;
+
+        /* size and addresses */
+        pMod->aSegments[i].Alignment   = OBJPAGELEN;
+        pMod->aSegments[i].cb          = pModLX->paObjs[i].o32_size;
+        pMod->aSegments[i].LinkAddress = pModLX->paObjs[i].o32_base;
+        pMod->aSegments[i].RVA         = NextRVA;
+        if (    fCanOptimizeMapping
+            ||  i + 1 >= pMod->cSegments
+            ||  (pModLX->paObjs[i].o32_flags & OBJRSRC)
+            ||  (pModLX->paObjs[i + 1].o32_flags & OBJRSRC))
+            pMod->aSegments[i].cbMapped = K_ALIGN_Z(pModLX->paObjs[i].o32_size, OBJPAGELEN);
+        else
+            pMod->aSegments[i].cbMapped = pModLX->paObjs[i + 1].o32_base - pModLX->paObjs[i].o32_base;
+        NextRVA += pMod->aSegments[i].cbMapped;
+
+        /* protection */
+        switch (  pModLX->paObjs[i].o32_flags
+                & (OBJSHARED | OBJREAD | OBJWRITE | OBJEXEC))
+        {
+            case 0:
+            case OBJSHARED:
+                pMod->aSegments[i].enmProt = KPROT_NOACCESS;
+                break;
+            case OBJREAD:
+            case OBJREAD | OBJSHARED:
+                pMod->aSegments[i].enmProt = KPROT_READONLY;
+                break;
+            case OBJWRITE:
+            case OBJWRITE | OBJREAD:
+                pMod->aSegments[i].enmProt = KPROT_WRITECOPY;
+                break;
+            case OBJWRITE | OBJSHARED:
+            case OBJWRITE | OBJSHARED | OBJREAD:
+                pMod->aSegments[i].enmProt = KPROT_READWRITE;
+                break;
+            case OBJEXEC:
+            case OBJEXEC | OBJSHARED:
+                pMod->aSegments[i].enmProt = KPROT_EXECUTE;
+                break;
+            case OBJEXEC | OBJREAD:
+            case OBJEXEC | OBJREAD | OBJSHARED:
+                pMod->aSegments[i].enmProt = KPROT_EXECUTE_READ;
+                break;
+            case OBJEXEC | OBJWRITE:
+            case OBJEXEC | OBJWRITE | OBJREAD:
+                pMod->aSegments[i].enmProt = KPROT_EXECUTE_WRITECOPY;
+                break;
+            case OBJEXEC | OBJWRITE | OBJSHARED:
+            case OBJEXEC | OBJWRITE | OBJSHARED | OBJREAD:
+                pMod->aSegments[i].enmProt = KPROT_EXECUTE_READWRITE;
+                break;
+        }
+        if ((pModLX->paObjs[i].o32_flags & (OBJREAD | OBJWRITE | OBJEXEC | OBJRSRC)) == OBJRSRC)
+            pMod->aSegments[i].enmProt = KPROT_READONLY;
+        /*pMod->aSegments[i].f16bit = !(pModLX->paObjs[i].o32_flags & OBJBIGDEF)
+        pMod->aSegments[i].fIOPL = !(pModLX->paObjs[i].o32_flags & OBJIOPL)
+        pMod->aSegments[i].fConforming = !(pModLX->paObjs[i].o32_flags & OBJCONFORM) */
+    }
+
+    /* set the mapping size */
+    pModLX->cbMapped = NextRVA;
+
+    /*
+     * We're done.
+     */
+    *ppModLX = pModLX;
+    return 0;
+}
+
+
+/** @copydoc KLDRMODOPS::pfnDestroy */
+static int kldrModLXDestroy(PKLDRMOD pMod)
+{
+    PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
+    int rc = 0;
+    KLDRMODLX_ASSERT(!pModLX->pvMapping);
+
+    if (pMod->pRdr)
+    {
+        rc = kRdrClose(pMod->pRdr);
+        pMod->pRdr = NULL;
+    }
+    if (pModLX->pbNonResNameTab)
+    {
+        kHlpFree(pModLX->pbNonResNameTab);
+        pModLX->pbNonResNameTab = NULL;
+    }
+    if (pModLX->pbFixupSection)
+    {
+        kHlpFree(pModLX->pbFixupSection);
+        pModLX->pbFixupSection = NULL;
+    }
+    pMod->u32Magic = 0;
+    pMod->pOps = NULL;
+    kHlpFree(pModLX);
+    return rc;
+}
+
+
+/**
+ * Resolved base address aliases.
+ *
+ * @param   pModLX          The interpreter module instance
+ * @param   pBaseAddress    The base address, IN & OUT.
+ */
+static void kldrModLXResolveBaseAddress(PKLDRMODLX pModLX, PKLDRADDR pBaseAddress)
+{
+    if (*pBaseAddress == KLDRMOD_BASEADDRESS_MAP)
+        *pBaseAddress = pModLX->pMod->aSegments[0].MapAddress;
+    else if (*pBaseAddress == KLDRMOD_BASEADDRESS_LINK)
+        *pBaseAddress = pModLX->pMod->aSegments[0].LinkAddress;
+}
+
+
+/** @copydoc kLdrModQuerySymbol */
+static int kldrModLXQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 iSymbol,
+                                const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion,
+                                PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind)
+{
+    PKLDRMODLX                  pModLX = (PKLDRMODLX)pMod->pvData;
+    KU32                        iOrdinal;
+    int                         rc;
+    const struct b32_bundle     *pBundle;
+    K_NOREF(pvBits);
+    K_NOREF(pszVersion);
+
+    /*
+     * Give up at once if there is no entry table.
+     */
+    if (!pModLX->Hdr.e32_enttab)
+        return KLDR_ERR_SYMBOL_NOT_FOUND;
+
+    /*
+     * Translate the symbol name into an ordinal.
+     */
+    if (pchSymbol)
+    {
+        rc = kldrModLXDoNameLookup(pModLX, pchSymbol, cchSymbol, &iSymbol);
+        if (rc)
+            return rc;
+    }
+
+    /*
+     * Iterate the entry table.
+     * (The entry table is made up of bundles of similar exports.)
+     */
+    iOrdinal = 1;
+    pBundle = (const struct b32_bundle *)pModLX->pbEntryTab;
+    while (pBundle->b32_cnt && iOrdinal <= iSymbol)
+    {
+        static const KSIZE s_cbEntry[] = { 0, 3, 5, 5, 7 };
+
+        /*
+         * Check for a hit first.
+         */
+        iOrdinal += pBundle->b32_cnt;
+        if (iSymbol < iOrdinal)
+        {
+            KU32 offObject;
+            const struct e32_entry *pEntry = (const struct e32_entry *)((KUPTR)(pBundle + 1)
+                                                                        +   (iSymbol - (iOrdinal - pBundle->b32_cnt))
+                                                                          * s_cbEntry[pBundle->b32_type]);
+
+            /*
+             * Calculate the return address.
+             */
+            kldrModLXResolveBaseAddress(pModLX, &BaseAddress);
+            switch (pBundle->b32_type)
+            {
+                /* empty bundles are place holders unused ordinal ranges. */
+                case EMPTY:
+                    return KLDR_ERR_SYMBOL_NOT_FOUND;
+
+                /* e32_flags + a 16-bit offset. */
+                case ENTRY16:
+                    offObject = pEntry->e32_variant.e32_offset.offset16;
+                    if (pfKind)
+                        *pfKind = KLDRSYMKIND_16BIT | KLDRSYMKIND_NO_TYPE;
+                    break;
+
+                /* e32_flags + a 16-bit offset + a 16-bit callgate selector. */
+                case GATE16:
+                    offObject = pEntry->e32_variant.e32_callgate.offset;
+                    if (pfKind)
+                        *pfKind = KLDRSYMKIND_16BIT | KLDRSYMKIND_CODE;
+                    break;
+
+                /* e32_flags + a 32-bit offset. */
+                case ENTRY32:
+                    offObject = pEntry->e32_variant.e32_offset.offset32;
+                    if (pfKind)
+                        *pfKind = KLDRSYMKIND_32BIT;
+                    break;
+
+                /* e32_flags + 16-bit import module ordinal + a 32-bit procname or ordinal. */
+                case ENTRYFWD:
+                    return kldrModLXDoForwarderQuery(pModLX, pEntry, pfnGetForwarder, pvUser, puValue, pfKind);
+
+                default:
+                    /* anyone actually using TYPEINFO will end up here. */
+                    KLDRMODLX_ASSERT(!"Bad bundle type");
+                    return KLDR_ERR_LX_BAD_BUNDLE;
+            }
+
+            /*
+             * Validate the object number and calc the return address.
+             */
+            if (    pBundle->b32_obj <= 0
+                ||  pBundle->b32_obj > pMod->cSegments)
+                return KLDR_ERR_LX_BAD_BUNDLE;
+            if (puValue)
+                *puValue = BaseAddress
+                         + offObject
+                         + pMod->aSegments[pBundle->b32_obj - 1].RVA;
+            return 0;
+        }
+
+        /*
+         * Skip the bundle.
+         */
+        if (pBundle->b32_type > ENTRYFWD)
+        {
+            KLDRMODLX_ASSERT(!"Bad type"); /** @todo figure out TYPEINFO. */
+            return KLDR_ERR_LX_BAD_BUNDLE;
+        }
+        if (pBundle->b32_type == 0)
+            pBundle = (const struct b32_bundle *)((const KU8 *)pBundle + 2);
+        else
+            pBundle = (const struct b32_bundle *)((const KU8 *)(pBundle + 1) + s_cbEntry[pBundle->b32_type] * pBundle->b32_cnt);
+    }
+
+    return KLDR_ERR_SYMBOL_NOT_FOUND;
+}
+
+
+/**
+ * Do name lookup.
+ *
+ * @returns See kLdrModQuerySymbol.
+ * @param   pModLX      The module to lookup the symbol in.
+ * @param   pchSymbol   The symbol to lookup.
+ * @param   cchSymbol   The symbol name length.
+ * @param   piSymbol    Where to store the symbol ordinal.
+ */
+static int kldrModLXDoNameLookup(PKLDRMODLX pModLX, const char *pchSymbol, KU32 cchSymbol, KU32 *piSymbol)
+{
+
+    /*
+     * First do a hash table lookup.
+     */
+    /** @todo hash name table for speed. */
+
+    /*
+     * Search the name tables.
+     */
+    const KU8 *pbName = kldrModLXDoNameTableLookupByName(pModLX->pbResNameTab,
+                                                         pModLX->pbLoaderSectionLast - pModLX->pbResNameTab + 1,
+                                                         pchSymbol, cchSymbol);
+    if (!pbName)
+    {
+        if (!pModLX->pbNonResNameTab)
+        {
+            /* lazy load it */
+            /** @todo non-resident name table. */
+        }
+        if (pModLX->pbNonResNameTab)
+            pbName = kldrModLXDoNameTableLookupByName(pModLX->pbResNameTab,
+                                                      pModLX->pbNonResNameTabLast - pModLX->pbResNameTab + 1,
+                                                      pchSymbol, cchSymbol);
+    }
+    if (!pbName)
+        return KLDR_ERR_SYMBOL_NOT_FOUND;
+
+    *piSymbol = *(const KU16 *)(pbName + 1 + *pbName);
+    return 0;
+}
+
+
+#if 0
+/**
+ * Hash a symbol using the algorithm from sdbm.
+ *
+ * The following was is the documenation of the orignal sdbm functions:
+ *
+ * This algorithm was created for sdbm (a public-domain reimplementation of
+ * ndbm) database library. it was found to do well in scrambling bits,
+ * causing better distribution of the keys and fewer splits. it also happens
+ * to be a good general hashing function with good distribution. the actual
+ * function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below
+ * is the faster version used in gawk. [there is even a faster, duff-device
+ * version] the magic constant 65599 was picked out of thin air while
+ * experimenting with different constants, and turns out to be a prime.
+ * this is one of the algorithms used in berkeley db (see sleepycat) and
+ * elsewhere.
+ */
+static KU32 kldrModLXDoHash(const char *pchSymbol, KU8 cchSymbol)
+{
+    KU32 hash = 0;
+    int ch;
+
+    while (     cchSymbol-- > 0
+           &&   (ch = *(unsigned const char *)pchSymbol++))
+        hash = ch + (hash << 6) + (hash << 16) - hash;
+
+    return hash;
+}
+#endif
+
+
+/**
+ * Lookup a name table entry by name.
+ *
+ * @returns Pointer to the name table entry if found.
+ * @returns NULL if not found.
+ * @param   pbNameTable     Pointer to the name table that should be searched.
+ * @param   cbNameTable     The size of the name table.
+ * @param   pchSymbol       The name of the symbol we're looking for.
+ * @param   cchSymbol       The length of the symbol name.
+ */
+static const KU8 *kldrModLXDoNameTableLookupByName(const KU8 *pbNameTable, KI32 cbNameTable,
+                                                   const char *pchSymbol, KSIZE cchSymbol)
+{
+    /*
+     * Determin the namelength up front so we can skip anything which doesn't matches the length.
+     */
+    KU8 cbSymbol8Bit = (KU8)cchSymbol;
+    if (cbSymbol8Bit != cchSymbol)
+        return NULL; /* too long. */
+
+    /*
+     * Walk the name table.
+     */
+    while (*pbNameTable != 0 && cbNameTable > 0)
+    {
+        const KU8 cbName = *pbNameTable;
+
+        cbNameTable -= cbName + 1 + 2;
+        if (cbNameTable < 0)
+            break;
+
+        if (    cbName == cbSymbol8Bit
+            &&  !kHlpMemComp(pbNameTable + 1, pchSymbol, cbName))
+            return pbNameTable;
+
+        /* next entry */
+        pbNameTable += cbName + 1 + 2;
+    }
+
+    return NULL;
+}
+
+
+/**
+ * Deal with a forwarder entry.
+ *
+ * @returns See kLdrModQuerySymbol.
+ * @param   pModLX          The PE module interpreter instance.
+ * @param   pEntry          The forwarder entry.
+ * @param   pfnGetForwarder The callback for resolving forwarder symbols. (optional)
+ * @param   pvUser          The user argument for the callback.
+ * @param   puValue         Where to put the value. (optional)
+ * @param   pfKind          Where to put the symbol kind. (optional)
+ */
+static int kldrModLXDoForwarderQuery(PKLDRMODLX pModLX, const struct e32_entry *pEntry,
+                                     PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind)
+{
+    int rc;
+    KU32 iSymbol;
+    const char *pchSymbol;
+    KU8 cchSymbol;
+
+    if (!pfnGetForwarder)
+        return KLDR_ERR_FORWARDER_SYMBOL;
+
+    /*
+     * Validate the entry import module ordinal.
+     */
+    if (    !pEntry->e32_variant.e32_fwd.modord
+        ||  pEntry->e32_variant.e32_fwd.modord > pModLX->Hdr.e32_impmodcnt)
+        return KLDR_ERR_LX_BAD_FORWARDER;
+
+    /*
+     * Figure out the parameters.
+     */
+    if (pEntry->e32_flags & FWD_ORDINAL)
+    {
+        iSymbol = pEntry->e32_variant.e32_fwd.value;
+        pchSymbol = NULL;                   /* no symbol name. */
+        cchSymbol = 0;
+    }
+    else
+    {
+        const KU8 *pbName;
+
+        /* load the fixup section if necessary. */
+        if (!pModLX->pbImportProcs)
+        {
+            rc = kldrModLXDoLoadFixupSection(pModLX);
+            if (rc)
+                return rc;
+        }
+
+        /* Make name pointer. */
+        pbName = pModLX->pbImportProcs + pEntry->e32_variant.e32_fwd.value;
+        if (    pbName >= pModLX->pbFixupSectionLast
+            ||  pbName < pModLX->pbFixupSection
+            || !*pbName)
+            return KLDR_ERR_LX_BAD_FORWARDER;
+
+
+        /* check for '#' name. */
+        if (pbName[1] == '#')
+        {
+            KU8         cbLeft = *pbName;
+            const KU8  *pb = pbName + 1;
+            unsigned    uBase;
+
+            /* base detection */
+            uBase = 10;
+            if (    cbLeft > 1
+                &&  pb[1] == '0'
+                &&  (pb[2] == 'x' || pb[2] == 'X'))
+            {
+                uBase = 16;
+                pb += 2;
+                cbLeft -= 2;
+            }
+
+            /* ascii to integer */
+            iSymbol = 0;
+            while (cbLeft-- > 0)
+            {
+                /* convert char to digit. */
+                unsigned uDigit = *pb++;
+                if (uDigit >= '0' && uDigit <= '9')
+                    uDigit -= '0';
+                else if (uDigit >= 'a' && uDigit <= 'z')
+                    uDigit -= 'a' + 10;
+                else if (uDigit >= 'A' && uDigit <= 'Z')
+                    uDigit -= 'A' + 10;
+                else if (!uDigit)
+                    break;
+                else
+                    return KLDR_ERR_LX_BAD_FORWARDER;
+                if (uDigit >= uBase)
+                    return KLDR_ERR_LX_BAD_FORWARDER;
+
+                /* insert the digit */
+                iSymbol *= uBase;
+                iSymbol += uDigit;
+            }
+            if (!iSymbol)
+                return KLDR_ERR_LX_BAD_FORWARDER;
+
+            pchSymbol = NULL;               /* no symbol name. */
+            cchSymbol = 0;
+        }
+        else
+        {
+            pchSymbol = (char *)pbName + 1;
+            cchSymbol = *pbName;
+            iSymbol = NIL_KLDRMOD_SYM_ORDINAL;
+        }
+    }
+
+    /*
+     * Resolve the forwarder.
+     */
+    rc = pfnGetForwarder(pModLX->pMod, pEntry->e32_variant.e32_fwd.modord - 1, iSymbol, pchSymbol, cchSymbol, NULL, puValue, pfKind, pvUser);
+    if (!rc && pfKind)
+        *pfKind |= KLDRSYMKIND_FORWARDER;
+    return rc;
+}
+
+
+/**
+ * Loads the fixup section from the executable image.
+ *
+ * The fixup section isn't loaded until it's accessed. It's also freed by kLdrModDone().
+ *
+ * @returns 0 on success, non-zero kLdr or native status code on failure.
+ * @param   pModLX          The PE module interpreter instance.
+ */
+static int kldrModLXDoLoadFixupSection(PKLDRMODLX pModLX)
+{
+    int rc;
+    KU32 off;
+    void *pv;
+
+    pv = kHlpAlloc(pModLX->Hdr.e32_fixupsize);
+    if (!pv)
+        return KERR_NO_MEMORY;
+
+    off = pModLX->Hdr.e32_objtab + pModLX->Hdr.e32_ldrsize;
+    rc = kRdrRead(pModLX->pMod->pRdr, pv, pModLX->Hdr.e32_fixupsize,
+                     off + pModLX->offHdr);
+    if (!rc)
+    {
+        pModLX->pbFixupSection = pv;
+        pModLX->pbFixupSectionLast = pModLX->pbFixupSection + pModLX->Hdr.e32_fixupsize;
+        KLDRMODLX_ASSERT(!pModLX->paoffPageFixups);
+        if (pModLX->Hdr.e32_fpagetab)
+            pModLX->paoffPageFixups = (const KU32 *)(pModLX->pbFixupSection + pModLX->Hdr.e32_fpagetab - off);
+        KLDRMODLX_ASSERT(!pModLX->pbFixupRecs);
+        if (pModLX->Hdr.e32_frectab)
+            pModLX->pbFixupRecs = pModLX->pbFixupSection + pModLX->Hdr.e32_frectab - off;
+        KLDRMODLX_ASSERT(!pModLX->pbImportMods);
+        if (pModLX->Hdr.e32_impmod)
+            pModLX->pbImportMods = pModLX->pbFixupSection + pModLX->Hdr.e32_impmod - off;
+        KLDRMODLX_ASSERT(!pModLX->pbImportProcs);
+        if (pModLX->Hdr.e32_impproc)
+            pModLX->pbImportProcs = pModLX->pbFixupSection + pModLX->Hdr.e32_impproc - off;
+    }
+    else
+        kHlpFree(pv);
+    return rc;
+}
+
+
+/** @copydoc kLdrModEnumSymbols */
+static int kldrModLXEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress,
+                                KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
+{
+    PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
+    const struct b32_bundle *pBundle;
+    KU32 iOrdinal;
+    int rc = 0;
+    K_NOREF(pvBits);
+    K_NOREF(fFlags);
+
+    kldrModLXResolveBaseAddress(pModLX, &BaseAddress);
+
+    /*
+     * Enumerate the entry table.
+     * (The entry table is made up of bundles of similar exports.)
+     */
+    iOrdinal = 1;
+    pBundle = (const struct b32_bundle *)pModLX->pbEntryTab;
+    while (pBundle->b32_cnt && iOrdinal)
+    {
+        static const KSIZE s_cbEntry[] = { 0, 3, 5, 5, 7 };
+
+        /*
+         * Enum the entries in the bundle.
+         */
+        if (pBundle->b32_type != EMPTY)
+        {
+            const struct e32_entry *pEntry;
+            KSIZE cbEntry;
+            KLDRADDR BundleRVA;
+            unsigned cLeft;
+
+
+            /* Validate the bundle. */
+            switch (pBundle->b32_type)
+            {
+                case ENTRY16:
+                case GATE16:
+                case ENTRY32:
+                    if (    pBundle->b32_obj <= 0
+                        ||  pBundle->b32_obj > pMod->cSegments)
+                        return KLDR_ERR_LX_BAD_BUNDLE;
+                    BundleRVA = pMod->aSegments[pBundle->b32_obj - 1].RVA;
+                    break;
+
+                case ENTRYFWD:
+                    BundleRVA = 0;
+                    break;
+
+                default:
+                    /* anyone actually using TYPEINFO will end up here. */
+                    KLDRMODLX_ASSERT(!"Bad bundle type");
+                    return KLDR_ERR_LX_BAD_BUNDLE;
+            }
+
+            /* iterate the bundle entries. */
+            cbEntry = s_cbEntry[pBundle->b32_type];
+            pEntry = (const struct e32_entry *)(pBundle + 1);
+            cLeft = pBundle->b32_cnt;
+            while (cLeft-- > 0)
+            {
+                KLDRADDR uValue;
+                KU32 fKind;
+                int fFoundName;
+                const KU8 *pbName;
+
+                /*
+                 * Calc the symbol value and kind.
+                 */
+                switch (pBundle->b32_type)
+                {
+                    /* e32_flags + a 16-bit offset. */
+                    case ENTRY16:
+                        uValue = BaseAddress + BundleRVA + pEntry->e32_variant.e32_offset.offset16;
+                        fKind = KLDRSYMKIND_16BIT | KLDRSYMKIND_NO_TYPE;
+                        break;
+
+                    /* e32_flags + a 16-bit offset + a 16-bit callgate selector. */
+                    case GATE16:
+                        uValue = BaseAddress + BundleRVA + pEntry->e32_variant.e32_callgate.offset;
+                        fKind = KLDRSYMKIND_16BIT | KLDRSYMKIND_CODE;
+                        break;
+
+                    /* e32_flags + a 32-bit offset. */
+                    case ENTRY32:
+                        uValue = BaseAddress + BundleRVA + pEntry->e32_variant.e32_offset.offset32;
+                        fKind = KLDRSYMKIND_32BIT;
+                        break;
+
+                    /* e32_flags + 16-bit import module ordinal + a 32-bit procname or ordinal. */
+                    case ENTRYFWD:
+                        uValue = 0; /** @todo implement enumeration of forwarders properly. */
+                        fKind = KLDRSYMKIND_FORWARDER;
+                        break;
+
+                    default: /* shut up gcc. */
+                        uValue = 0;
+                        fKind = KLDRSYMKIND_NO_BIT | KLDRSYMKIND_NO_TYPE;
+                        break;
+                }
+
+                /*
+                 * Any symbol names?
+                 */
+                fFoundName = 0;
+
+                /* resident name table. */
+                pbName = pModLX->pbResNameTab;
+                if (pbName)
+                {
+                    do
+                    {
+                        pbName = kldrModLXDoNameTableLookupByOrdinal(pbName, pModLX->pbLoaderSectionLast - pbName + 1, iOrdinal);
+                        if (!pbName)
+                            break;
+                        fFoundName = 1;
+                        rc = pfnCallback(pMod, iOrdinal, (const char *)pbName + 1, *pbName, NULL, uValue, fKind, pvUser);
+                        if (rc)
+                            return rc;
+
+                        /* skip to the next entry */
+                        pbName += 1 + *pbName + 2;
+                    } while (pbName < pModLX->pbLoaderSectionLast);
+                }
+
+                /* resident name table. */
+                pbName = pModLX->pbNonResNameTab;
+                /** @todo lazy load the non-resident name table. */
+                if (pbName)
+                {
+                    do
+                    {
+                        pbName = kldrModLXDoNameTableLookupByOrdinal(pbName, pModLX->pbNonResNameTabLast - pbName + 1, iOrdinal);
+                        if (!pbName)
+                            break;
+                        fFoundName = 1;
+                        rc = pfnCallback(pMod, iOrdinal, (const char *)pbName + 1, *pbName, NULL, uValue, fKind, pvUser);
+                        if (rc)
+                            return rc;
+
+                        /* skip to the next entry */
+                        pbName += 1 + *pbName + 2;
+                    } while (pbName < pModLX->pbLoaderSectionLast);
+                }
+
+                /*
+                 * If no names, call once with the ordinal only.
+                 */
+                if (!fFoundName)
+                {
+                    rc = pfnCallback(pMod, iOrdinal, NULL, 0, NULL, uValue, fKind, pvUser);
+                    if (rc)
+                        return rc;
+                }
+
+                /* next */
+                iOrdinal++;
+                pEntry = (const struct e32_entry *)((KUPTR)pEntry + cbEntry);
+            }
+        }
+
+        /*
+         * The next bundle.
+         */
+        if (pBundle->b32_type > ENTRYFWD)
+        {
+            KLDRMODLX_ASSERT(!"Bad type"); /** @todo figure out TYPEINFO. */
+            return KLDR_ERR_LX_BAD_BUNDLE;
+        }
+        if (pBundle->b32_type == 0)
+            pBundle = (const struct b32_bundle *)((const KU8 *)pBundle + 2);
+        else
+            pBundle = (const struct b32_bundle *)((const KU8 *)(pBundle + 1) + s_cbEntry[pBundle->b32_type] * pBundle->b32_cnt);
+    }
+
+    return 0;
+}
+
+
+/**
+ * Lookup a name table entry by ordinal.
+ *
+ * @returns Pointer to the name table entry if found.
+ * @returns NULL if not found.
+ * @param   pbNameTable Pointer to the name table that should be searched.
+ * @param   cbNameTable The size of the name table.
+ * @param   iOrdinal    The ordinal to search for.
+ */
+static const KU8 *kldrModLXDoNameTableLookupByOrdinal(const KU8 *pbNameTable, KI32 cbNameTable, KU32 iOrdinal)
+{
+    while (*pbNameTable != 0 && cbNameTable > 0)
+    {
+        const KU8   cbName = *pbNameTable;
+        KU32        iName;
+
+        cbNameTable -= cbName + 1 + 2;
+        if (cbNameTable < 0)
+            break;
+
+        iName = *(pbNameTable + cbName + 1)
+              | ((unsigned)*(pbNameTable + cbName + 2) << 8);
+        if (iName == iOrdinal)
+            return pbNameTable;
+
+        /* next entry */
+        pbNameTable += cbName + 1 + 2;
+    }
+
+    return NULL;
+}
+
+
+/** @copydoc kLdrModGetImport */
+static int kldrModLXGetImport(PKLDRMOD pMod, const void *pvBits, KU32 iImport, char *pszName, KSIZE cchName)
+{
+    PKLDRMODLX  pModLX = (PKLDRMODLX)pMod->pvData;
+    const KU8  *pb;
+    int         rc;
+    K_NOREF(pvBits);
+
+    /*
+     * Validate
+     */
+    if (iImport >= pModLX->Hdr.e32_impmodcnt)
+        return KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS;
+
+    /*
+     * Lazy loading the fixup section.
+     */
+    if (!pModLX->pbImportMods)
+    {
+        rc = kldrModLXDoLoadFixupSection(pModLX);
+        if (rc)
+            return rc;
+    }
+
+    /*
+     * Iterate the module import table until we reach the requested import ordinal.
+     */
+    pb = pModLX->pbImportMods;
+    while (iImport-- > 0)
+        pb += *pb + 1;
+
+    /*
+     * Copy out the result.
+     */
+    if (*pb < cchName)
+    {
+        kHlpMemCopy(pszName, pb + 1, *pb);
+        pszName[*pb] = '\0';
+        rc = 0;
+    }
+    else
+    {
+        kHlpMemCopy(pszName, pb + 1, cchName);
+        if (cchName)
+            pszName[cchName - 1] = '\0';
+        rc = KERR_BUFFER_OVERFLOW;
+    }
+
+    return rc;
+}
+
+
+/** @copydoc kLdrModNumberOfImports */
+static KI32 kldrModLXNumberOfImports(PKLDRMOD pMod, const void *pvBits)
+{
+    PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
+    K_NOREF(pvBits);
+    return pModLX->Hdr.e32_impmodcnt;
+}
+
+
+/** @copydoc kLdrModGetStackInfo */
+static int kldrModLXGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo)
+{
+    PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
+    const KU32 i = pModLX->Hdr.e32_stackobj;
+    K_NOREF(pvBits);
+
+    if (    i
+        &&  i <= pMod->cSegments
+        &&  pModLX->Hdr.e32_esp <= pMod->aSegments[i - 1].LinkAddress + pMod->aSegments[i - 1].cb
+        &&  pModLX->Hdr.e32_stacksize
+        &&  pModLX->Hdr.e32_esp - pModLX->Hdr.e32_stacksize >= pMod->aSegments[i - 1].LinkAddress)
+    {
+
+        kldrModLXResolveBaseAddress(pModLX, &BaseAddress);
+        pStackInfo->LinkAddress = pModLX->Hdr.e32_esp - pModLX->Hdr.e32_stacksize;
+        pStackInfo->Address = BaseAddress
+                            + pMod->aSegments[i - 1].RVA
+                            + pModLX->Hdr.e32_esp - pModLX->Hdr.e32_stacksize - pMod->aSegments[i - 1].LinkAddress;
+    }
+    else
+    {
+        pStackInfo->Address = NIL_KLDRADDR;
+        pStackInfo->LinkAddress = NIL_KLDRADDR;
+    }
+    pStackInfo->cbStack = pModLX->Hdr.e32_stacksize;
+    pStackInfo->cbStackThread = 0;
+
+    return 0;
+}
+
+
+/** @copydoc kLdrModQueryMainEntrypoint */
+static int kldrModLXQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress)
+{
+    PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
+    K_NOREF(pvBits);
+
+    /*
+     * Convert the address from the header.
+     */
+    kldrModLXResolveBaseAddress(pModLX, &BaseAddress);
+    *pMainEPAddress = pModLX->Hdr.e32_startobj
+                   && pModLX->Hdr.e32_startobj <= pMod->cSegments
+                   && pModLX->Hdr.e32_eip < pMod->aSegments[pModLX->Hdr.e32_startobj - 1].cb
+        ? BaseAddress + pMod->aSegments[pModLX->Hdr.e32_startobj - 1].RVA + pModLX->Hdr.e32_eip
+        : NIL_KLDRADDR;
+    return 0;
+}
+
+
+/** @copydoc kLdrModEnumDbgInfo */
+static int kldrModLXEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser)
+{
+    /*PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;*/
+    K_NOREF(pfnCallback);
+    K_NOREF(pvUser);
+
+    /*
+     * Quit immediately if no debug info.
+     */
+    if (kldrModLXHasDbgInfo(pMod, pvBits))
+        return 0;
+#if 0
+    /*
+     * Read the debug info and look for familiar magics and structures.
+     */
+    /** @todo */
+#endif
+
+    return 0;
+}
+
+
+/** @copydoc kLdrModHasDbgInfo */
+static int kldrModLXHasDbgInfo(PKLDRMOD pMod, const void *pvBits)
+{
+    PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
+    K_NOREF(pvBits);
+
+    /*
+     * Don't curretnly bother with linkers which doesn't advertise it in the header.
+     */
+    if (    !pModLX->Hdr.e32_debuginfo
+        ||  !pModLX->Hdr.e32_debuglen)
+        return KLDR_ERR_NO_DEBUG_INFO;
+    return 0;
+}
+
+
+/** @copydoc kLdrModMap */
+static int kldrModLXMap(PKLDRMOD pMod)
+{
+    PKLDRMODLX  pModLX = (PKLDRMODLX)pMod->pvData;
+    unsigned    fFixed;
+    void       *pvBase;
+    int         rc;
+
+    /*
+     * Already mapped?
+     */
+    if (pModLX->pvMapping)
+        return KLDR_ERR_ALREADY_MAPPED;
+
+    /*
+     * Allocate memory for it.
+     */
+    /* fixed image? */
+    fFixed = pMod->enmType == KLDRTYPE_EXECUTABLE_FIXED
+          || pMod->enmType == KLDRTYPE_SHARED_LIBRARY_FIXED;
+    if (!fFixed)
+        pvBase = NULL;
+    else
+    {
+        pvBase = (void *)(KUPTR)pMod->aSegments[0].LinkAddress;
+        if ((KUPTR)pvBase != pMod->aSegments[0].LinkAddress)
+            return KLDR_ERR_ADDRESS_OVERFLOW;
+    }
+    rc = kHlpPageAlloc(&pvBase, pModLX->cbMapped, KPROT_EXECUTE_READWRITE, fFixed);
+    if (rc)
+        return rc;
+
+    /*
+     * Load the bits, apply page protection, and update the segment table.
+     */
+    rc = kldrModLXDoLoadBits(pModLX, pvBase);
+    if (!rc)
+        rc = kldrModLXDoProtect(pModLX, pvBase, 0 /* protect */);
+    if (!rc)
+    {
+        KU32 i;
+        for (i = 0; i < pMod->cSegments; i++)
+        {
+            if (pMod->aSegments[i].RVA != NIL_KLDRADDR)
+                pMod->aSegments[i].MapAddress = (KUPTR)pvBase + (KUPTR)pMod->aSegments[i].RVA;
+        }
+        pModLX->pvMapping = pvBase;
+    }
+    else
+        kHlpPageFree(pvBase, pModLX->cbMapped);
+    return rc;
+}
+
+
+/**
+ * Loads the LX pages into the specified memory mapping.
+ *
+ * @returns 0 on success.
+ * @returns non-zero kLdr or OS status code on failure.
+ *
+ * @param   pModLX  The LX module interpreter instance.
+ * @param   pvBits  Where to load the bits.
+ */
+static int kldrModLXDoLoadBits(PKLDRMODLX pModLX, void *pvBits)
+{
+    const PKRDR pRdr = pModLX->pMod->pRdr;
+    KU8 *pbTmpPage = NULL;
+    int rc = 0;
+    KU32 i;
+
+    /*
+     * Iterate the segments.
+     */
+    for (i = 0; i < pModLX->Hdr.e32_objcnt; i++)
+    {
+        const struct o32_obj * const pObj = &pModLX->paObjs[i];
+        const KU32      cPages = pModLX->pMod->aSegments[i].cbMapped / OBJPAGELEN;
+        KU32            iPage;
+        KU8            *pbPage = (KU8 *)pvBits + (KUPTR)pModLX->pMod->aSegments[i].RVA;
+
+        /*
+         * Iterate the page map pages.
+         */
+        for (iPage = 0; !rc && iPage < pObj->o32_mapsize; iPage++, pbPage += OBJPAGELEN)
+        {
+            const struct o32_map *pMap = &pModLX->paPageMappings[iPage + pObj->o32_pagemap - 1];
+            switch (pMap->o32_pageflags)
+            {
+                case VALID:
+                    if (pMap->o32_pagesize == OBJPAGELEN)
+                        rc = kRdrRead(pRdr, pbPage, OBJPAGELEN,
+                                         pModLX->Hdr.e32_datapage + (pMap->o32_pagedataoffset << pModLX->Hdr.e32_pageshift));
+                    else if (pMap->o32_pagesize < OBJPAGELEN)
+                    {
+                        rc = kRdrRead(pRdr, pbPage, pMap->o32_pagesize,
+                                         pModLX->Hdr.e32_datapage + (pMap->o32_pagedataoffset << pModLX->Hdr.e32_pageshift));
+                        kHlpMemSet(pbPage + pMap->o32_pagesize, 0, OBJPAGELEN - pMap->o32_pagesize);
+                    }
+                    else
+                        rc = KLDR_ERR_LX_BAD_PAGE_MAP;
+                    break;
+
+                case ITERDATA:
+                case ITERDATA2:
+                    /* make sure we've got a temp page .*/
+                    if (!pbTmpPage)
+                    {
+                        pbTmpPage = kHlpAlloc(OBJPAGELEN + 256);
+                        if (!pbTmpPage)
+                            break;
+                    }
+                    /* validate the size. */
+                    if (pMap->o32_pagesize > OBJPAGELEN + 252)
+                    {
+                        rc = KLDR_ERR_LX_BAD_PAGE_MAP;
+                        break;
+                    }
+
+                    /* read it and ensure 4 extra zero bytes. */
+                    rc = kRdrRead(pRdr, pbTmpPage, pMap->o32_pagesize,
+                                     pModLX->Hdr.e32_datapage + (pMap->o32_pagedataoffset << pModLX->Hdr.e32_pageshift));
+                    if (rc)
+                        break;
+                    kHlpMemSet(pbTmpPage + pMap->o32_pagesize, 0, 4);
+
+                    /* unpack it into the image page. */
+                    if (pMap->o32_pageflags == ITERDATA2)
+                        rc = kldrModLXDoIterData2Unpacking(pbPage, pbTmpPage, pMap->o32_pagesize);
+                    else
+                        rc = kldrModLXDoIterDataUnpacking(pbPage, pbTmpPage, pMap->o32_pagesize);
+                    break;
+
+                case INVALID: /* we're probably not dealing correctly with INVALID pages... */
+                case ZEROED:
+                    kHlpMemSet(pbPage, 0, OBJPAGELEN);
+                    break;
+
+                case RANGE:
+                    KLDRMODLX_ASSERT(!"RANGE");
+                default:
+                    rc = KLDR_ERR_LX_BAD_PAGE_MAP;
+                    break;
+            }
+        }
+        if (rc)
+            break;
+
+        /*
+         * Zero the remaining pages.
+         */
+        if (iPage < cPages)
+            kHlpMemSet(pbPage, 0, (cPages - iPage) * OBJPAGELEN);
+    }
+
+    if (pbTmpPage)
+        kHlpFree(pbTmpPage);
+    return rc;
+}
+
+
+/**
+ * Unpacks iterdata (aka EXEPACK).
+ *
+ * @returns 0 on success, non-zero kLdr status code on failure.
+ * @param   pbDst       Where to put the uncompressed data. (Assumes OBJPAGELEN size.)
+ * @param   pbSrc       The compressed source data.
+ * @param   cbSrc       The file size of the compressed data. The source buffer
+ *                      contains 4 additional zero bytes.
+ */
+static int kldrModLXDoIterDataUnpacking(KU8 *pbDst, const KU8 *pbSrc, int cbSrc)
+{
+    const struct LX_Iter   *pIter = (const struct LX_Iter *)pbSrc;
+    int                     cbDst = OBJPAGELEN;
+
+    /* Validate size of data. */
+    if (cbSrc >= OBJPAGELEN - 2)
+        return KLDR_ERR_LX_BAD_ITERDATA;
+
+    /*
+     * Expand the page.
+     */
+    while (cbSrc > 0 && pIter->LX_nIter)
+    {
+        if (pIter->LX_nBytes == 1)
+        {
+            /*
+             * Special case - one databyte.
+             */
+            cbDst -= pIter->LX_nIter;
+            if (cbDst < 0)
+                return KLDR_ERR_LX_BAD_ITERDATA;
+
+            cbSrc -= 4 + 1;
+            if (cbSrc < -4)
+                return KLDR_ERR_LX_BAD_ITERDATA;
+
+            kHlpMemSet(pbDst, pIter->LX_Iterdata, pIter->LX_nIter);
+            pbDst += pIter->LX_nIter;
+            pIter++;
+        }
+        else
+        {
+            /*
+             * General.
+             */
+            int i;
+
+            cbDst -= pIter->LX_nIter * pIter->LX_nBytes;
+            if (cbDst < 0)
+                return KLDR_ERR_LX_BAD_ITERDATA;
+
+            cbSrc -= 4 + pIter->LX_nBytes;
+            if (cbSrc < -4)
+                return KLDR_ERR_LX_BAD_ITERDATA;
+
+            for (i = pIter->LX_nIter; i > 0; i--, pbDst += pIter->LX_nBytes)
+                kHlpMemCopy(pbDst, &pIter->LX_Iterdata, pIter->LX_nBytes);
+            pIter   = (struct LX_Iter *)((char*)pIter + 4 + pIter->LX_nBytes);
+        }
+    }
+
+    /*
+     * Zero remainder of the page.
+     */
+    if (cbDst > 0)
+        kHlpMemSet(pbDst, 0, cbDst);
+
+    return 0;
+}
+
+
+/**
+ * Unpacks iterdata (aka EXEPACK).
+ *
+ * @returns 0 on success, non-zero kLdr status code on failure.
+ * @param   pbDst       Where to put the uncompressed data. (Assumes OBJPAGELEN size.)
+ * @param   pbSrc       The compressed source data.
+ * @param   cbSrc       The file size of the compressed data. The source buffer
+ *                      contains 4 additional zero bytes.
+ */
+static int kldrModLXDoIterData2Unpacking(KU8 *pbDst, const KU8 *pbSrc, int cbSrc)
+{
+    int cbDst = OBJPAGELEN;
+
+    while (cbSrc > 0)
+    {
+        /*
+         * Bit 0 and 1 is the encoding type.
+         */
+        switch (*pbSrc & 0x03)
+        {
+            /*
+             *
+             *  0  1  2  3  4  5  6  7
+             *  type  |              |
+             *        ----------------
+             *             cb         <cb bytes of data>
+             *
+             * Bits 2-7 is, if not zero, the length of an uncompressed run
+             * starting at the following byte.
+             *
+             *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
+             *  type  |              |  |                    | |                     |
+             *        ----------------  ---------------------- -----------------------
+             *             zero                 cb                 char to multiply
+             *
+             * If the bits are zero, the following two bytes describes a 1 byte interation
+             * run. First byte is count, second is the byte to copy. A count of zero is
+             * means end of data, and we simply stops. In that case the rest of the data
+             * should be zero.
+             */
+            case 0:
+            {
+                if (*pbSrc)
+                {
+                    const int cb = *pbSrc >> 2;
+                    cbDst -= cb;
+                    if (cbDst < 0)
+                        return KLDR_ERR_LX_BAD_ITERDATA2;
+                    cbSrc -= cb + 1;
+                    if (cbSrc < 0)
+                        return KLDR_ERR_LX_BAD_ITERDATA2;
+                    kHlpMemCopy(pbDst, ++pbSrc, cb);
+                    pbDst += cb;
+                    pbSrc += cb;
+                }
+                else if (cbSrc < 2)
+                    return KLDR_ERR_LX_BAD_ITERDATA2;
+                else
+                {
+                    const int cb = pbSrc[1];
+                    if (!cb)
+                        goto l_endloop;
+                    cbDst -= cb;
+                    if (cbDst < 0)
+                        return KLDR_ERR_LX_BAD_ITERDATA2;
+                    cbSrc -= 3;
+                    if (cbSrc < 0)
+                        return KLDR_ERR_LX_BAD_ITERDATA2;
+                    kHlpMemSet(pbDst, pbSrc[2], cb);
+                    pbDst += cb;
+                    pbSrc += 3;
+                }
+                break;
+            }
+
+
+            /*
+             *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
+             *  type  |  |  |     |  |                       |
+             *        ----  -------  -------------------------
+             *        cb1   cb2 - 3          offset            <cb1 bytes of data>
+             *
+             * Two bytes layed out as described above, followed by cb1 bytes of data to be copied.
+             * The cb2(+3) and offset describes an amount of data to be copied from the expanded
+             * data relative to the current position. The data copied as you would expect it to be.
+             */
+            case 1:
+            {
+                cbSrc -= 2;
+                if (cbSrc < 0)
+                    return KLDR_ERR_LX_BAD_ITERDATA2;
+                else
+                {
+                    const unsigned  off = ((unsigned)pbSrc[1] << 1) | (*pbSrc >> 7);
+                    const int       cb1 = (*pbSrc >> 2) & 3;
+                    const int       cb2 = ((*pbSrc >> 4) & 7) + 3;
+
+                    pbSrc += 2;
+                    cbSrc -= cb1;
+                    if (cbSrc < 0)
+                        return KLDR_ERR_LX_BAD_ITERDATA2;
+                    cbDst -= cb1;
+                    if (cbDst < 0)
+                        return KLDR_ERR_LX_BAD_ITERDATA2;
+                    kHlpMemCopy(pbDst, pbSrc, cb1);
+                    pbDst += cb1;
+                    pbSrc += cb1;
+
+                    if (off > OBJPAGELEN - (unsigned)cbDst)
+                        return KLDR_ERR_LX_BAD_ITERDATA2;
+                    cbDst -= cb2;
+                    if (cbDst < 0)
+                        return KLDR_ERR_LX_BAD_ITERDATA2;
+                    kHlpMemMove(pbDst, pbDst - off, cb2);
+                    pbDst += cb2;
+                }
+                break;
+            }
+
+
+            /*
+             *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
+             *  type  |  |  |                                |
+             *        ----  ----------------------------------
+             *       cb-3               offset
+             *
+             * Two bytes layed out as described above.
+             * The cb(+3) and offset describes an amount of data to be copied from the expanded
+             * data relative to the current position.
+             *
+             * If offset == 1 the data is not copied as expected, but in the memcpyw manner.
+             */
+            case 2:
+            {
+                cbSrc -= 2;
+                if (cbSrc < 0)
+                    return KLDR_ERR_LX_BAD_ITERDATA2;
+                else
+                {
+                    const unsigned  off = ((unsigned)pbSrc[1] << 4) | (*pbSrc >> 4);
+                    const int       cb = ((*pbSrc >> 2) & 3) + 3;
+
+                    pbSrc += 2;
+                    if (off > OBJPAGELEN - (unsigned)cbDst)
+                        return KLDR_ERR_LX_BAD_ITERDATA2;
+                    cbDst -= cb;
+                    if (cbDst < 0)
+                        return KLDR_ERR_LX_BAD_ITERDATA2;
+                    kLdrModLXMemCopyW(pbDst, pbDst - off, cb);
+                    pbDst += cb;
+                }
+                break;
+            }
+
+
+            /*
+             *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
+             *  type  |        |  |              |  |                                |
+             *        ----------  ----------------  ----------------------------------
+             *           cb1            cb2                      offset                <cb1 bytes of data>
+             *
+             * Three bytes layed out as described above, followed by cb1 bytes of data to be copied.
+             * The cb2 and offset describes an amount of data to be copied from the expanded
+             * data relative to the current position.
+             *
+             * If offset == 1 the data is not copied as expected, but in the memcpyw manner.
+             */
+            case 3:
+            {
+                cbSrc -= 3;
+                if (cbSrc < 0)
+                    return KLDR_ERR_LX_BAD_ITERDATA2;
+                else
+                {
+                    const int       cb1 = (*pbSrc >> 2) & 0xf;
+                    const int       cb2 = ((pbSrc[1] & 0xf) << 2) | (*pbSrc >> 6);
+                    const unsigned  off = ((unsigned)pbSrc[2] << 4) | (pbSrc[1] >> 4);
+
+                    pbSrc += 3;
+                    cbSrc -= cb1;
+                    if (cbSrc < 0)
+                        return KLDR_ERR_LX_BAD_ITERDATA2;
+                    cbDst -= cb1;
+                    if (cbDst < 0)
+                        return KLDR_ERR_LX_BAD_ITERDATA2;
+                    kHlpMemCopy(pbDst, pbSrc, cb1);
+                    pbDst += cb1;
+                    pbSrc += cb1;
+
+                    if (off > OBJPAGELEN - (unsigned)cbDst)
+                        return KLDR_ERR_LX_BAD_ITERDATA2;
+                    cbDst -= cb2;
+                    if (cbDst < 0)
+                        return KLDR_ERR_LX_BAD_ITERDATA2;
+                    kLdrModLXMemCopyW(pbDst, pbDst - off, cb2);
+                    pbDst += cb2;
+                }
+                break;
+            }
+        } /* type switch. */
+    } /* unpack loop */
+
+l_endloop:
+
+
+    /*
+     * Zero remainder of the page.
+     */
+    if (cbDst > 0)
+        kHlpMemSet(pbDst, 0, cbDst);
+
+    return 0;
+}
+
+
+/**
+ * Special memcpy employed by the iterdata2 algorithm.
+ *
+ * Emulate a 16-bit memcpy (copying 16-bit at a time) and the effects this
+ * has if src is very close to the destination.
+ *
+ * @param   pbDst   Destination pointer.
+ * @param   pbSrc   Source pointer. Will always be <= pbDst.
+ * @param   cb      Amount of data to be copied.
+ * @remark  This assumes that unaligned word and dword access is fine.
+ */
+static void kLdrModLXMemCopyW(KU8 *pbDst, const KU8 *pbSrc, int cb)
+{
+    switch (pbDst - pbSrc)
+    {
+        case 0:
+        case 1:
+        case 2:
+        case 3:
+            /* 16-bit copy (unaligned) */
+            if (cb & 1)
+                *pbDst++ = *pbSrc++;
+            for (cb >>= 1; cb > 0; cb--, pbDst += 2, pbSrc += 2)
+                *(KU16 *)pbDst = *(const KU16 *)pbSrc;
+            break;
+
+        default:
+            /* 32-bit copy (unaligned) */
+            if (cb & 1)
+                *pbDst++ = *pbSrc++;
+            if (cb & 2)
+            {
+                *(KU16 *)pbDst = *(const KU16 *)pbSrc;
+                pbDst += 2;
+                pbSrc += 2;
+            }
+            for (cb >>= 2; cb > 0; cb--, pbDst += 4, pbSrc += 4)
+                *(KU32 *)pbDst = *(const KU32 *)pbSrc;
+            break;
+    }
+}
+
+
+/**
+ * Unprotects or protects the specified image mapping.
+ *
+ * @returns 0 on success.
+ * @returns non-zero kLdr or OS status code on failure.
+ *
+ * @param   pModLX  The LX module interpreter instance.
+ * @param   pvBits  The mapping to protect.
+ * @param   UnprotectOrProtect  If 1 unprotect (i.e. make all writable), otherwise
+ *          protect according to the object table.
+ */
+static int kldrModLXDoProtect(PKLDRMODLX pModLX, void *pvBits, unsigned fUnprotectOrProtect)
+{
+    KU32 i;
+    PKLDRMOD pMod = pModLX->pMod;
+
+    /*
+     * Change object protection.
+     */
+    for (i = 0; i < pMod->cSegments; i++)
+    {
+        int rc;
+        void *pv;
+        KPROT enmProt;
+
+        /* calc new protection. */
+        enmProt = pMod->aSegments[i].enmProt;
+        if (fUnprotectOrProtect)
+        {
+            switch (enmProt)
+            {
+                case KPROT_NOACCESS:
+                case KPROT_READONLY:
+                case KPROT_READWRITE:
+                case KPROT_WRITECOPY:
+                    enmProt = KPROT_READWRITE;
+                    break;
+                case KPROT_EXECUTE:
+                case KPROT_EXECUTE_READ:
+                case KPROT_EXECUTE_READWRITE:
+                case KPROT_EXECUTE_WRITECOPY:
+                    enmProt = KPROT_EXECUTE_READWRITE;
+                    break;
+                default:
+                    KLDRMODLX_ASSERT(!"bad enmProt");
+                    return -1;
+            }
+        }
+        else
+        {
+            /* copy on write -> normal write. */
+            if (enmProt == KPROT_EXECUTE_WRITECOPY)
+                enmProt = KPROT_EXECUTE_READWRITE;
+            else if (enmProt == KPROT_WRITECOPY)
+                enmProt = KPROT_READWRITE;
+        }
+
+
+        /* calc the address and set page protection. */
+        pv = (KU8 *)pvBits + pMod->aSegments[i].RVA;
+
+        rc = kHlpPageProtect(pv, pMod->aSegments[i].cbMapped, enmProt);
+        if (rc)
+            break;
+
+        /** @todo the gap page should be marked NOACCESS! */
+    }
+
+    return 0;
+}
+
+
+/** @copydoc kLdrModUnmap */
+static int kldrModLXUnmap(PKLDRMOD pMod)
+{
+    PKLDRMODLX  pModLX = (PKLDRMODLX)pMod->pvData;
+    KU32        i;
+    int         rc;
+
+    /*
+     * Mapped?
+     */
+    if (!pModLX->pvMapping)
+        return KLDR_ERR_NOT_MAPPED;
+
+    /*
+     * Free the mapping and update the segments.
+     */
+    rc = kHlpPageFree((void *)pModLX->pvMapping, pModLX->cbMapped);
+    KLDRMODLX_ASSERT(!rc);
+    pModLX->pvMapping = NULL;
+
+    for (i = 0; i < pMod->cSegments; i++)
+        pMod->aSegments[i].MapAddress = 0;
+
+    return rc;
+}
+
+
+/** @copydoc kLdrModAllocTLS */
+static int kldrModLXAllocTLS(PKLDRMOD pMod, void *pvMapping)
+{
+    PKLDRMODLX  pModLX = (PKLDRMODLX)pMod->pvData;
+
+    /* no tls, just do the error checking. */
+    if (   pvMapping == KLDRMOD_INT_MAP
+        && pModLX->pvMapping)
+        return KLDR_ERR_NOT_MAPPED;
+    return 0;
+}
+
+
+/** @copydoc kLdrModFreeTLS */
+static void kldrModLXFreeTLS(PKLDRMOD pMod, void *pvMapping)
+{
+    /* no tls. */
+    K_NOREF(pMod);
+    K_NOREF(pvMapping);
+
+}
+
+
+/** @copydoc kLdrModReload */
+static int kldrModLXReload(PKLDRMOD pMod)
+{
+    PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
+    int rc, rc2;
+
+    /*
+     * Mapped?
+     */
+    if (!pModLX->pvMapping)
+        return KLDR_ERR_NOT_MAPPED;
+
+    /*
+     * Before doing anything we'll have to make all pages writable.
+     */
+    rc = kldrModLXDoProtect(pModLX, (void *)pModLX->pvMapping, 1 /* unprotect */);
+    if (rc)
+        return rc;
+
+    /*
+     * Load the bits again.
+     */
+    rc = kldrModLXDoLoadBits(pModLX, (void *)pModLX->pvMapping);
+
+    /*
+     * Restore protection.
+     */
+    rc2 = kldrModLXDoProtect(pModLX, (void *)pModLX->pvMapping, 0 /* protect */);
+    if (!rc && rc2)
+        rc = rc2;
+    return rc;
+}
+
+
+/** @copydoc kLdrModFixupMapping */
+static int kldrModLXFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
+    int rc, rc2;
+
+    /*
+     * Mapped?
+     */
+    if (!pModLX->pvMapping)
+        return KLDR_ERR_NOT_MAPPED;
+
+    /*
+     * Before doing anything we'll have to make all pages writable.
+     */
+    rc = kldrModLXDoProtect(pModLX, (void *)pModLX->pvMapping, 1 /* unprotect */);
+    if (rc)
+        return rc;
+
+    /*
+     * Apply fixups and resolve imports.
+     */
+    rc = kldrModLXRelocateBits(pMod, (void *)pModLX->pvMapping, (KUPTR)pModLX->pvMapping,
+                               pMod->aSegments[0].LinkAddress, pfnGetImport, pvUser);
+
+    /*
+     * Restore protection.
+     */
+    rc2 = kldrModLXDoProtect(pModLX, (void *)pModLX->pvMapping, 0 /* protect */);
+    if (!rc && rc2)
+        rc = rc2;
+    return rc;
+}
+
+
+/** @copydoc kLdrModCallInit */
+static int kldrModLXCallInit(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle)
+{
+    PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
+    int rc;
+
+    /*
+     * Mapped?
+     */
+    if (pvMapping == KLDRMOD_INT_MAP)
+    {
+        pvMapping = pModLX->pvMapping;
+        if (!pvMapping)
+            return KLDR_ERR_NOT_MAPPED;
+    }
+
+    /*
+     * Do TLS callbacks first and then call the init/term function if it's a DLL.
+     */
+    if ((pModLX->Hdr.e32_mflags & E32MODMASK) == E32MODDLL)
+        rc = kldrModLXDoCallDLL(pModLX, pvMapping, 0 /* attach */, uHandle);
+    else
+        rc = 0;
+    return rc;
+}
+
+
+/**
+ * Call the DLL entrypoint.
+ *
+ * @returns 0 on success.
+ * @returns KLDR_ERR_MODULE_INIT_FAILED  or KLDR_ERR_THREAD_ATTACH_FAILED on failure.
+ * @param   pModLX          The LX module interpreter instance.
+ * @param   pvMapping       The module mapping to use (resolved).
+ * @param   uOp             The operation (DLL_*).
+ * @param   uHandle         The module handle to present.
+ */
+static int kldrModLXDoCallDLL(PKLDRMODLX pModLX, void *pvMapping, unsigned uOp, KUPTR uHandle)
+{
+    int rc;
+
+    /*
+     * If no entrypoint there isn't anything to be done.
+     */
+    if (    !pModLX->Hdr.e32_startobj
+        ||  pModLX->Hdr.e32_startobj > pModLX->Hdr.e32_objcnt)
+        return 0;
+
+    /*
+     * Invoke the entrypoint and convert the boolean result to a kLdr status code.
+     */
+    rc = kldrModLXDoCall((KUPTR)pvMapping
+                         + (KUPTR)pModLX->pMod->aSegments[pModLX->Hdr.e32_startobj - 1].RVA
+                         + pModLX->Hdr.e32_eip,
+                         uHandle, uOp, NULL);
+    if (rc)
+        rc = 0;
+    else if (uOp == 0 /* attach */)
+        rc = KLDR_ERR_MODULE_INIT_FAILED;
+    else /* detach: ignore failures */
+        rc = 0;
+    return rc;
+}
+
+
+/**
+ * Do a 3 parameter callback.
+ *
+ * @returns 32-bit callback return.
+ * @param   uEntrypoint     The address of the function to be called.
+ * @param   uHandle         The first argument, the module handle.
+ * @param   uOp             The second argumnet, the reason we're calling.
+ * @param   pvReserved      The third argument, reserved argument. (figure this one out)
+ */
+static KI32 kldrModLXDoCall(KUPTR uEntrypoint, KUPTR uHandle, KU32 uOp, void *pvReserved)
+{
+#if defined(__X86__) || defined(__i386__) || defined(_M_IX86)
+    KI32 rc;
+/** @todo try/except */
+
+    /*
+     * Paranoia.
+     */
+# ifdef __GNUC__
+    __asm__ __volatile__(
+        "pushl  %2\n\t"
+        "pushl  %1\n\t"
+        "pushl  %0\n\t"
+        "lea   12(%%esp), %2\n\t"
+        "call  *%3\n\t"
+        "movl   %2, %%esp\n\t"
+        : "=a" (rc)
+        : "d" (uOp),
+          "S" (0),
+          "c" (uEntrypoint),
+          "0" (uHandle));
+# elif defined(_MSC_VER)
+    __asm {
+        mov     eax, [uHandle]
+        mov     edx, [uOp]
+        mov     ecx, 0
+        mov     ebx, [uEntrypoint]
+        push    edi
+        mov     edi, esp
+        push    ecx
+        push    edx
+        push    eax
+        call    ebx
+        mov     esp, edi
+        pop     edi
+        mov     [rc], eax
+    }
+# else
+#  error "port me!"
+# endif
+    K_NOREF(pvReserved);
+    return rc;
+
+#else
+    K_NOREF(uEntrypoint);
+    K_NOREF(uHandle);
+    K_NOREF(uOp);
+    K_NOREF(pvReserved);
+    return KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE;
+#endif
+}
+
+
+/** @copydoc kLdrModCallTerm */
+static int kldrModLXCallTerm(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle)
+{
+    PKLDRMODLX  pModLX = (PKLDRMODLX)pMod->pvData;
+
+    /*
+     * Mapped?
+     */
+    if (pvMapping == KLDRMOD_INT_MAP)
+    {
+        pvMapping = pModLX->pvMapping;
+        if (!pvMapping)
+            return KLDR_ERR_NOT_MAPPED;
+    }
+
+    /*
+     * Do the call.
+     */
+    if ((pModLX->Hdr.e32_mflags & E32MODMASK) == E32MODDLL)
+        kldrModLXDoCallDLL(pModLX, pvMapping, 1 /* detach */, uHandle);
+
+    return 0;
+}
+
+
+/** @copydoc kLdrModCallThread */
+static int kldrModLXCallThread(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle, unsigned fAttachingOrDetaching)
+{
+    /* no thread attach/detach callout. */
+    K_NOREF(pMod);
+    K_NOREF(pvMapping);
+    K_NOREF(uHandle);
+    K_NOREF(fAttachingOrDetaching);
+    return 0;
+}
+
+
+/** @copydoc kLdrModSize */
+static KLDRADDR kldrModLXSize(PKLDRMOD pMod)
+{
+    PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
+    return pModLX->cbMapped;
+}
+
+
+/** @copydoc kLdrModGetBits */
+static int kldrModLXGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    PKLDRMODLX  pModLX = (PKLDRMODLX)pMod->pvData;
+    int         rc;
+
+    /*
+     * Load the image bits.
+     */
+    rc = kldrModLXDoLoadBits(pModLX, pvBits);
+    if (rc)
+        return rc;
+
+    /*
+     * Perform relocations.
+     */
+    return kldrModLXRelocateBits(pMod, pvBits, BaseAddress, pMod->aSegments[0].LinkAddress, pfnGetImport, pvUser);
+
+}
+
+
+/** @copydoc kLdrModRelocateBits */
+static int kldrModLXRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
+                                 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
+    KU32 iSeg;
+    int rc;
+
+    /*
+     * Do we need to to *anything*?
+     */
+    if (    NewBaseAddress == OldBaseAddress
+        &&  NewBaseAddress == pModLX->paObjs[0].o32_base
+        &&  !pModLX->Hdr.e32_impmodcnt)
+        return 0;
+
+    /*
+     * Load the fixup section.
+     */
+    if (!pModLX->pbFixupSection)
+    {
+        rc = kldrModLXDoLoadFixupSection(pModLX);
+        if (rc)
+            return rc;
+    }
+
+    /*
+     * Iterate the segments.
+     */
+    for (iSeg = 0; iSeg < pModLX->Hdr.e32_objcnt; iSeg++)
+    {
+        const struct o32_obj * const pObj = &pModLX->paObjs[iSeg];
+        KLDRADDR        PageAddress = NewBaseAddress + pModLX->pMod->aSegments[iSeg].RVA;
+        KU32            iPage;
+        KU8            *pbPage = (KU8 *)pvBits + (KUPTR)pModLX->pMod->aSegments[iSeg].RVA;
+
+        /*
+         * Iterate the page map pages.
+         */
+        for (iPage = 0, rc = 0; !rc && iPage < pObj->o32_mapsize; iPage++, pbPage += OBJPAGELEN, PageAddress += OBJPAGELEN)
+        {
+            const KU8 * const   pbFixupRecEnd = pModLX->pbFixupRecs + pModLX->paoffPageFixups[iPage + pObj->o32_pagemap];
+            const KU8          *pb            = pModLX->pbFixupRecs + pModLX->paoffPageFixups[iPage + pObj->o32_pagemap - 1];
+            KLDRADDR            uValue        = NIL_KLDRADDR;
+            KU32                fKind         = 0;
+            int                 iSelector;
+
+            /* sanity */
+            if (pbFixupRecEnd < pb)
+                return KLDR_ERR_BAD_FIXUP;
+            if (pbFixupRecEnd - 1 > pModLX->pbFixupSectionLast)
+                return KLDR_ERR_BAD_FIXUP;
+            if (pb < pModLX->pbFixupSection)
+                return KLDR_ERR_BAD_FIXUP;
+
+            /*
+             * Iterate the fixup record.
+             */
+            while (pb < pbFixupRecEnd)
+            {
+                union _rel
+                {
+                    const KU8 *             pb;
+                    const struct r32_rlc   *prlc;
+                } u;
+
+                u.pb = pb;
+                pb += 3 + (u.prlc->nr_stype & NRCHAIN ? 0 : 1); /* place pch at the 4th member. */
+
+                /*
+                 * Figure out the target.
+                 */
+                switch (u.prlc->nr_flags & NRRTYP)
+                {
+                    /*
+                     * Internal fixup.
+                     */
+                    case NRRINT:
+                    {
+                        KU16 iTrgObject;
+                        KU32 offTrgObject;
+
+                        /* the object */
+                        if (u.prlc->nr_flags & NR16OBJMOD)
+                        {
+                            iTrgObject = *(const KU16 *)pb;
+                            pb += 2;
+                        }
+                        else
+                            iTrgObject = *pb++;
+                        iTrgObject--;
+                        if (iTrgObject >= pModLX->Hdr.e32_objcnt)
+                            return KLDR_ERR_BAD_FIXUP;
+
+                        /* the target */
+                        if ((u.prlc->nr_stype & NRSRCMASK) != NRSSEG)
+                        {
+                            if (u.prlc->nr_flags & NR32BITOFF)
+                            {
+                                offTrgObject = *(const KU32 *)pb;
+                                pb += 4;
+                            }
+                            else
+                            {
+                                offTrgObject = *(const KU16 *)pb;
+                                pb += 2;
+                            }
+
+                            /* calculate the symbol info. */
+                            uValue = offTrgObject + NewBaseAddress + pMod->aSegments[iTrgObject].RVA;
+                        }
+                        else
+                            uValue = NewBaseAddress + pMod->aSegments[iTrgObject].RVA;
+                        if (    (u.prlc->nr_stype & NRALIAS)
+                            ||  (pMod->aSegments[iTrgObject].fFlags & KLDRSEG_FLAG_16BIT))
+                            iSelector = pMod->aSegments[iTrgObject].Sel16bit;
+                        else
+                            iSelector = pMod->aSegments[iTrgObject].SelFlat;
+                        fKind = 0;
+                        break;
+                    }
+
+                    /*
+                     * Import by symbol ordinal.
+                     */
+                    case NRRORD:
+                    {
+                        KU16 iModule;
+                        KU32 iSymbol;
+
+                        /* the module ordinal */
+                        if (u.prlc->nr_flags & NR16OBJMOD)
+                        {
+                            iModule = *(const KU16 *)pb;
+                            pb += 2;
+                        }
+                        else
+                            iModule = *pb++;
+                        iModule--;
+                        if (iModule >= pModLX->Hdr.e32_impmodcnt)
+                            return KLDR_ERR_BAD_FIXUP;
+#if 1
+                        if (u.prlc->nr_flags & NRICHAIN)
+                            return KLDR_ERR_BAD_FIXUP;
+#endif
+
+                        /* . */
+                        if (u.prlc->nr_flags & NR32BITOFF)
+                        {
+                            iSymbol = *(const KU32 *)pb;
+                            pb += 4;
+                        }
+                        else if (!(u.prlc->nr_flags & NR8BITORD))
+                        {
+                            iSymbol = *(const KU16 *)pb;
+                            pb += 2;
+                        }
+                        else
+                            iSymbol = *pb++;
+
+                        /* resolve it. */
+                        rc = pfnGetImport(pMod, iModule, iSymbol, NULL, 0, NULL, &uValue, &fKind, pvUser);
+                        if (rc)
+                            return rc;
+                        iSelector = -1;
+                        break;
+                    }
+
+                    /*
+                     * Import by symbol name.
+                     */
+                    case NRRNAM:
+                    {
+                        KU32 iModule;
+                        KU16 offSymbol;
+                        const KU8 *pbSymbol;
+
+                        /* the module ordinal */
+                        if (u.prlc->nr_flags & NR16OBJMOD)
+                        {
+                            iModule = *(const KU16 *)pb;
+                            pb += 2;
+                        }
+                        else
+                            iModule = *pb++;
+                        iModule--;
+                        if (iModule >= pModLX->Hdr.e32_impmodcnt)
+                            return KLDR_ERR_BAD_FIXUP;
+#if 1
+                        if (u.prlc->nr_flags & NRICHAIN)
+                            return KLDR_ERR_BAD_FIXUP;
+#endif
+
+                        /* . */
+                        if (u.prlc->nr_flags & NR32BITOFF)
+                        {
+                            offSymbol = *(const KU32 *)pb;
+                            pb += 4;
+                        }
+                        else if (!(u.prlc->nr_flags & NR8BITORD))
+                        {
+                            offSymbol = *(const KU16 *)pb;
+                            pb += 2;
+                        }
+                        else
+                            offSymbol = *pb++;
+                        pbSymbol = pModLX->pbImportProcs + offSymbol;
+                        if (    pbSymbol < pModLX->pbImportProcs
+                            ||  pbSymbol > pModLX->pbFixupSectionLast)
+                            return KLDR_ERR_BAD_FIXUP;
+
+                        /* resolve it. */
+                        rc = pfnGetImport(pMod, iModule, NIL_KLDRMOD_SYM_ORDINAL, (const char *)pbSymbol + 1, *pbSymbol, NULL,
+                                          &uValue, &fKind, pvUser);
+                        if (rc)
+                            return rc;
+                        iSelector = -1;
+                        break;
+                    }
+
+                    case NRRENT:
+                        KLDRMODLX_ASSERT(!"NRRENT");
+                    default:
+                        iSelector = -1;
+                        break;
+                }
+
+                /* addend */
+                if (u.prlc->nr_flags & NRADD)
+                {
+                    if (u.prlc->nr_flags & NR32BITADD)
+                    {
+                        uValue += *(const KU32 *)pb;
+                        pb += 4;
+                    }
+                    else
+                    {
+                        uValue += *(const KU16 *)pb;
+                        pb += 2;
+                    }
+                }
+
+
+                /*
+                 * Deal with the 'source' (i.e. the place that should be modified - very logical).
+                 */
+                if (!(u.prlc->nr_stype & NRCHAIN))
+                {
+                    int off = u.prlc->r32_soff;
+
+                    /* common / simple */
+                    if (    (u.prlc->nr_stype & NRSRCMASK) == NROFF32
+                        &&  off >= 0
+                        &&  off <= OBJPAGELEN - 4)
+                        *(KU32 *)&pbPage[off] = uValue;
+                    else if (    (u.prlc->nr_stype & NRSRCMASK) == NRSOFF32
+                            &&  off >= 0
+                            &&  off <= OBJPAGELEN - 4)
+                        *(KU32 *)&pbPage[off] = uValue - (PageAddress + off + 4);
+                    else
+                    {
+                        /* generic */
+                        rc = kldrModLXDoReloc(pbPage, off, PageAddress, u.prlc, iSelector, uValue, fKind);
+                        if (rc)
+                            return rc;
+                    }
+                }
+                else if (!(u.prlc->nr_flags & NRICHAIN))
+                {
+                    const KI16 *poffSrc = (const KI16 *)pb;
+                    KU8 c = u.pb[2];
+
+                    /* common / simple */
+                    if ((u.prlc->nr_stype & NRSRCMASK) == NROFF32)
+                    {
+                        while (c-- > 0)
+                        {
+                            int off = *poffSrc++;
+                            if (off >= 0 && off <= OBJPAGELEN - 4)
+                                *(KU32 *)&pbPage[off] = uValue;
+                            else
+                            {
+                                rc = kldrModLXDoReloc(pbPage, off, PageAddress, u.prlc, iSelector, uValue, fKind);
+                                if (rc)
+                                    return rc;
+                            }
+                        }
+                    }
+                    else if ((u.prlc->nr_stype & NRSRCMASK) == NRSOFF32)
+                    {
+                        while (c-- > 0)
+                        {
+                            int off = *poffSrc++;
+                            if (off >= 0 && off <= OBJPAGELEN - 4)
+                                *(KU32 *)&pbPage[off] = uValue - (PageAddress + off + 4);
+                            else
+                            {
+                                rc = kldrModLXDoReloc(pbPage, off, PageAddress, u.prlc, iSelector, uValue, fKind);
+                                if (rc)
+                                    return rc;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        while (c-- > 0)
+                        {
+                            rc = kldrModLXDoReloc(pbPage, *poffSrc++, PageAddress, u.prlc, iSelector, uValue, fKind);
+                            if (rc)
+                                return rc;
+                        }
+                    }
+                    pb = (const KU8 *)poffSrc;
+                }
+                else
+                {
+                    /* This is a pain because it will require virgin pages on a relocation. */
+                    KLDRMODLX_ASSERT(!"NRICHAIN");
+                    return KLDR_ERR_LX_NRICHAIN_NOT_SUPPORTED;
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+
+/**
+ * Applies the relocation to one 'source' in a page.
+ *
+ * This takes care of the more esotic case while the common cases
+ * are dealt with seperately.
+ *
+ * @returns 0 on success, non-zero kLdr status code on failure.
+ * @param   pbPage      The page in which to apply the fixup.
+ * @param   off         Page relative offset of where to apply the offset.
+ * @param   uValue      The target value.
+ * @param   fKind       The target kind.
+ */
+static int kldrModLXDoReloc(KU8 *pbPage, int off, KLDRADDR PageAddress, const struct r32_rlc *prlc,
+                            int iSelector, KLDRADDR uValue, KU32 fKind)
+{
+#pragma pack(1) /* just to be sure */
+    union
+    {
+        KU8         ab[6];
+        KU32        off32;
+        KU16        off16;
+        KU8         off8;
+        struct
+        {
+            KU16    off;
+            KU16    Sel;
+        }           Far16;
+        struct
+        {
+            KU32    off;
+            KU16    Sel;
+        }           Far32;
+    }               uData;
+#pragma pack()
+    const KU8      *pbSrc;
+    KU8            *pbDst;
+    KU8             cb;
+
+    K_NOREF(fKind);
+
+    /*
+     * Compose the fixup data.
+     */
+    switch (prlc->nr_stype & NRSRCMASK)
+    {
+        case NRSBYT:
+            uData.off8 = (KU8)uValue;
+            cb = 1;
+            break;
+        case NRSSEG:
+            if (iSelector == -1)
+            {
+                /* fixme */
+            }
+            uData.off16 = iSelector;
+            cb = 2;
+            break;
+        case NRSPTR:
+            if (iSelector == -1)
+            {
+                /* fixme */
+            }
+            uData.Far16.off = (KU16)uValue;
+            uData.Far16.Sel = iSelector;
+            cb = 4;
+            break;
+        case NRSOFF:
+            uData.off16 = (KU16)uValue;
+            cb = 2;
+            break;
+        case NRPTR48:
+            if (iSelector == -1)
+            {
+                /* fixme */
+            }
+            uData.Far32.off = (KU32)uValue;
+            uData.Far32.Sel = iSelector;
+            cb = 6;
+            break;
+        case NROFF32:
+            uData.off32 = (KU32)uValue;
+            cb = 4;
+            break;
+        case NRSOFF32:
+            uData.off32 = (KU32)uValue - (PageAddress + off + 4);
+            cb = 4;
+            break;
+        default:
+            return KLDR_ERR_LX_BAD_FIXUP_SECTION; /** @todo fix error, add more checks! */
+    }
+
+    /*
+     * Apply it. This is sloooow...
+     */
+    pbSrc = &uData.ab[0];
+    pbDst = pbPage + off;
+    while (cb-- > 0)
+    {
+        if (off > OBJPAGELEN)
+            break;
+        if (off >= 0)
+            *pbDst = *pbSrc;
+        pbSrc++;
+        pbDst++;
+    }
+
+    return 0;
+}
+
+
+/**
+ * The LX module interpreter method table.
+ */
+KLDRMODOPS g_kLdrModLXOps =
+{
+    "LX",
+    NULL,
+    kldrModLXCreate,
+    kldrModLXDestroy,
+    kldrModLXQuerySymbol,
+    kldrModLXEnumSymbols,
+    kldrModLXGetImport,
+    kldrModLXNumberOfImports,
+    NULL /* can execute one is optional */,
+    kldrModLXGetStackInfo,
+    kldrModLXQueryMainEntrypoint,
+    NULL /* pfnQueryImageUuid */,
+    NULL /* fixme */,
+    NULL /* fixme */,
+    kldrModLXEnumDbgInfo,
+    kldrModLXHasDbgInfo,
+    kldrModLXMap,
+    kldrModLXUnmap,
+    kldrModLXAllocTLS,
+    kldrModLXFreeTLS,
+    kldrModLXReload,
+    kldrModLXFixupMapping,
+    kldrModLXCallInit,
+    kldrModLXCallTerm,
+    kldrModLXCallThread,
+    kldrModLXSize,
+    kldrModLXGetBits,
+    kldrModLXRelocateBits,
+    NULL /* fixme: pfnMostlyDone */,
+    42 /* the end */
+};
+
diff --git a/src/lib/kStuff/kLdr/kLdrModMachO.c b/src/lib/kStuff/kLdr/kLdrModMachO.c
new file mode 100644
index 0000000..7b4b2d2
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrModMachO.c
@@ -0,0 +1,3718 @@
+/* $Id: kLdrModMachO.c 81 2016-08-18 22:10:38Z bird $ */
+/** @file
+ * kLdr - The Module Interpreter for the MACH-O format.
+ */
+
+/*
+ * Copyright (c) 2006-2013 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kLdr.h>
+#include "kLdrInternal.h"
+#include <k/kLdrFmts/mach-o.h>
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** @def KLDRMODMACHO_STRICT
+ * Define KLDRMODMACHO_STRICT to enabled strict checks in KLDRMODMACHO. */
+#define KLDRMODMACHO_STRICT 1
+
+/** @def KLDRMODMACHO_ASSERT
+ * Assert that an expression is true when KLDR_STRICT is defined.
+ */
+#ifdef KLDRMODMACHO_STRICT
+# define KLDRMODMACHO_ASSERT(expr)  kHlpAssert(expr)
+#else
+# define KLDRMODMACHO_ASSERT(expr)  do {} while (0)
+#endif
+
+/** @def KLDRMODMACHO_CHECK_RETURN
+ * Checks that an expression is true and return if it isn't.
+ * This is a debug aid.
+ */
+#ifdef KLDRMODMACHO_STRICT2
+# define KLDRMODMACHO_CHECK_RETURN(expr, rc)  kHlpAssertReturn(expr, rc)
+#else
+# define KLDRMODMACHO_CHECK_RETURN(expr, rc)  do { if (!(expr)) { return (rc); } } while (0)
+#endif
+
+/** @def KLDRMODMACHO_CHECK_RETURN
+ * Checks that an expression is true and return if it isn't.
+ * This is a debug aid.
+ */
+#ifdef KLDRMODMACHO_STRICT2
+# define KLDRMODMACHO_FAILED_RETURN(rc)  kHlpAssertFailedReturn(rc)
+#else
+# define KLDRMODMACHO_FAILED_RETURN(rc)  return (rc)
+#endif
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Mach-O section details.
+ */
+typedef struct KLDRMODMACHOSECT
+{
+    /** The size of the section (in bytes). */
+    KLDRSIZE                cb;
+    /** The link address of this section. */
+    KLDRADDR                LinkAddress;
+    /** The RVA of this section. */
+    KLDRADDR                RVA;
+    /** The file offset of this section.
+     * This is -1 if the section doesn't have a file backing. */
+    KLDRFOFF                offFile;
+    /** The number of fixups. */
+    KU32                    cFixups;
+    /** The array of fixups. (lazy loaded) */
+    macho_relocation_info_t *paFixups;
+    /** The file offset of the fixups for this section.
+     * This is -1 if the section doesn't have any fixups. */
+    KLDRFOFF                offFixups;
+    /** Mach-O section flags. */
+    KU32                    fFlags;
+    /** kLdr segment index. */
+    KU32                    iSegment;
+    /** Pointer to the Mach-O section structure. */
+    void                   *pvMachoSection;
+} KLDRMODMACHOSECT, *PKLDRMODMACHOSECT;
+
+/**
+ * Extra per-segment info.
+ *
+ * This is corresponds to a kLdr segment, not a Mach-O segment!
+ */
+typedef struct KLDRMODMACHOSEG
+{
+    /** The orignal segment number (in case we had to resort it). */
+    KU32                    iOrgSegNo;
+    /** The number of sections in the segment. */
+    KU32                    cSections;
+    /** Pointer to the sections belonging to this segment.
+     * The array resides in the big memory chunk allocated for
+     * the module handle, so it doesn't need freeing. */
+    PKLDRMODMACHOSECT       paSections;
+
+} KLDRMODMACHOSEG, *PKLDRMODMACHOSEG;
+
+/**
+ * Instance data for the Mach-O MH_OBJECT module interpreter.
+ * @todo interpret the other MH_* formats.
+ */
+typedef struct KLDRMODMACHO
+{
+    /** Pointer to the module. (Follows the section table.) */
+    PKLDRMOD                pMod;
+    /** Pointer to the RDR file mapping of the raw file bits. NULL if not mapped. */
+    const void             *pvBits;
+    /** Pointer to the user mapping. */
+    void                   *pvMapping;
+    /** The module open flags. */
+    KU32                    fOpenFlags;
+
+    /** The offset of the image. (FAT fun.) */
+    KLDRFOFF                offImage;
+    /** The link address. */
+    KLDRADDR                LinkAddress;
+    /** The size of the mapped image. */
+    KLDRADDR                cbImage;
+    /** Whether we're capable of loading the image. */
+    KBOOL                   fCanLoad;
+    /** Whether we're creating a global offset table segment.
+     * This dependes on the cputype and image type. */
+    KBOOL                   fMakeGot;
+    /** The size of a indirect GOT jump stub entry.
+     * This is 0 if not needed. */
+    KU8                     cbJmpStub;
+    /** Effective file type.  If the original was a MH_OBJECT file, the
+     * corresponding MH_DSYM needs the segment translation of a MH_OBJECT too.
+     * The MH_DSYM normally has a separate __DWARF segment, but this is
+     * automatically skipped during the transation. */
+    KU8                     uEffFileType;
+    /** Pointer to the load commands. (endian converted) */
+    KU8                    *pbLoadCommands;
+    /** The Mach-O header. (endian converted)
+     * @remark The reserved field is only valid for real 64-bit headers. */
+    mach_header_64_t        Hdr;
+
+    /** The offset of the symbol table. */
+    KLDRFOFF                offSymbols;
+    /** The number of symbols. */
+    KU32                    cSymbols;
+    /** The pointer to the loaded symbol table. */
+    void                   *pvaSymbols;
+    /** The offset of the string table. */
+    KLDRFOFF                offStrings;
+    /** The size of the of the string table. */
+    KU32                    cchStrings;
+    /** Pointer to the loaded string table. */
+    char                   *pchStrings;
+
+    /** The image UUID, all zeros if not found. */
+    KU8                     abImageUuid[16];
+
+    /** The RVA of the Global Offset Table. */
+    KLDRADDR                GotRVA;
+    /** The RVA of the indirect GOT jump stubs.  */
+    KLDRADDR                JmpStubsRVA;
+
+    /** The number of sections. */
+    KU32                    cSections;
+    /** Pointer to the section array running in parallel to the Mach-O one. */
+    PKLDRMODMACHOSECT       paSections;
+
+    /** Array of segments parallel to the one in KLDRMOD. */
+    KLDRMODMACHOSEG         aSegments[1];
+} KLDRMODMACHO, *PKLDRMODMACHO;
+
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+#if 0
+static KI32 kldrModMachONumberOfImports(PKLDRMOD pMod, const void *pvBits);
+#endif
+static int kldrModMachORelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
+                                    PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
+
+static int  kldrModMachODoCreate(PKRDR pRdr, KLDRFOFF offImage, KU32 fOpenFlags, PKLDRMODMACHO *ppMod);
+static int  kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_header_32_t *pHdr, PKRDR pRdr, KLDRFOFF offImage,
+                                             KU32 fOpenFlags, KU32 *pcSegments, KU32 *pcSections, KU32 *pcbStringPool,
+                                             PKBOOL pfCanLoad, PKLDRADDR pLinkAddress, KU8 *puEffFileType);
+static int  kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStringPool, KU32 cbStringPool);
+static int  kldrModMachOAdjustBaseAddress(PKLDRMODMACHO pModMachO, PKLDRADDR pBaseAddress);
+
+/*static int  kldrModMachOLoadLoadCommands(PKLDRMODMACHO pModMachO);*/
+static int  kldrModMachOLoadObjSymTab(PKLDRMODMACHO pModMachO);
+static int  kldrModMachOLoadFixups(PKLDRMODMACHO pModMachO, KLDRFOFF offFixups, KU32 cFixups, macho_relocation_info_t **ppaFixups);
+static int  kldrModMachOMapVirginBits(PKLDRMODMACHO pModMachO);
+
+static int  kldrModMachODoQuerySymbol32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, KU32 cSyms, const char *pchStrings,
+                                           KU32 cchStrings, KLDRADDR BaseAddress, KU32 iSymbol, const char *pchSymbol,
+                                           KSIZE cchSymbol, PKLDRADDR puValue, KU32 *pfKind);
+static int  kldrModMachODoQuerySymbol64Bit(PKLDRMODMACHO pModMachO, const macho_nlist_64_t *paSyms, KU32 cSyms, const char *pchStrings,
+                                           KU32 cchStrings, KLDRADDR BaseAddress, KU32 iSymbol, const char *pchSymbol,
+                                           KSIZE cchSymbol, PKLDRADDR puValue, KU32 *pfKind);
+static int  kldrModMachODoEnumSymbols32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, KU32 cSyms,
+                                           const char *pchStrings, KU32 cchStrings, KLDRADDR BaseAddress,
+                                           KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser);
+static int  kldrModMachODoEnumSymbols64Bit(PKLDRMODMACHO pModMachO, const macho_nlist_64_t *paSyms, KU32 cSyms,
+                                           const char *pchStrings, KU32 cchStrings, KLDRADDR BaseAddress,
+                                           KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser);
+static int  kldrModMachOObjDoImports(PKLDRMODMACHO pModMachO, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
+static int  kldrModMachOObjDoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress);
+static int  kldrModMachOFixupSectionGeneric32Bit(PKLDRMODMACHO pModMachO, KU8 *pbSectBits, PKLDRMODMACHOSECT pFixupSect,
+                                                 macho_nlist_32_t *paSyms, KU32 cSyms, KLDRADDR NewBaseAddress);
+static int  kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBits, PKLDRMODMACHOSECT pFixupSect,
+                                          macho_nlist_64_t *paSyms, KU32 cSyms, KLDRADDR NewBaseAddress);
+
+static int  kldrModMachOMakeGOT(PKLDRMODMACHO pModMachO, void *pvBits, KLDRADDR NewBaseAddress);
+
+/*static int  kldrModMachODoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress);
+static int  kldrModMachODoImports(PKLDRMODMACHO pModMachO, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);*/
+
+
+/**
+ * Create a loader module instance interpreting the executable image found
+ * in the specified file provider instance.
+ *
+ * @returns 0 on success and *ppMod pointing to a module instance.
+ *          On failure, a non-zero OS specific error code is returned.
+ * @param   pOps            Pointer to the registered method table.
+ * @param   pRdr            The file provider instance to use.
+ * @param   fFlags          Flags, MBZ.
+ * @param   enmCpuArch      The desired CPU architecture. KCPUARCH_UNKNOWN means
+ *                          anything goes, but with a preference for the current
+ *                          host architecture.
+ * @param   offNewHdr       The offset of the new header in MZ files. -1 if not found.
+ * @param   ppMod           Where to store the module instance pointer.
+ */
+static int kldrModMachOCreate(PCKLDRMODOPS pOps, PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch, KLDRFOFF offNewHdr, PPKLDRMOD ppMod)
+{
+    PKLDRMODMACHO pModMachO;
+    int rc;
+
+    /*
+     * Create the instance data and do a minimal header validation.
+     */
+    rc = kldrModMachODoCreate(pRdr, offNewHdr == -1 ? 0 : offNewHdr, fFlags, &pModMachO);
+    if (!rc)
+    {
+
+        /*
+         * Match up against the requested CPU architecture.
+         */
+        if (    enmCpuArch == KCPUARCH_UNKNOWN
+            ||  pModMachO->pMod->enmArch == enmCpuArch)
+        {
+            pModMachO->pMod->pOps = pOps;
+            pModMachO->pMod->u32Magic = KLDRMOD_MAGIC;
+            *ppMod = pModMachO->pMod;
+            return 0;
+        }
+        rc = KLDR_ERR_CPU_ARCH_MISMATCH;
+    }
+    if (pModMachO)
+    {
+        kHlpFree(pModMachO->pbLoadCommands);
+        kHlpFree(pModMachO);
+    }
+    return rc;
+}
+
+
+/**
+ * Separate function for reading creating the Mach-O module instance to
+ * simplify cleanup on failure.
+ */
+static int kldrModMachODoCreate(PKRDR pRdr, KLDRFOFF offImage, KU32 fOpenFlags, PKLDRMODMACHO *ppModMachO)
+{
+    union
+    {
+        mach_header_32_t    Hdr32;
+        mach_header_64_t    Hdr64;
+    } s;
+    PKLDRMODMACHO pModMachO;
+    PKLDRMOD pMod;
+    KU8 *pbLoadCommands;
+    KU32 cSegments = 0; /* (MSC maybe used uninitialized) */
+    KU32 cSections = 0; /* (MSC maybe used uninitialized) */
+    KU32 cbStringPool = 0; /* (MSC maybe used uninitialized) */
+    KSIZE cchFilename;
+    KSIZE cb;
+    KBOOL fMakeGot;
+    KBOOL fCanLoad = K_TRUE;
+    KLDRADDR LinkAddress = NIL_KLDRADDR; /* (MSC maybe used uninitialized) */
+    KU8 cbJmpStub;
+    KU8 uEffFileType = 0; /* (MSC maybe used uninitialized) */
+    int rc;
+    *ppModMachO = NULL;
+
+    kHlpAssert(&s.Hdr32.magic == &s.Hdr64.magic);
+    kHlpAssert(&s.Hdr32.flags == &s.Hdr64.flags);
+
+    /*
+     * Read the Mach-O header.
+     */
+    rc = kRdrRead(pRdr, &s, sizeof(s), offImage);
+    if (rc)
+        return rc;
+    if (    s.Hdr32.magic != IMAGE_MACHO32_SIGNATURE
+        &&  s.Hdr32.magic != IMAGE_MACHO64_SIGNATURE
+        )
+    {
+        if (    s.Hdr32.magic == IMAGE_MACHO32_SIGNATURE_OE
+            ||  s.Hdr32.magic == IMAGE_MACHO64_SIGNATURE_OE)
+            return KLDR_ERR_MACHO_OTHER_ENDIAN_NOT_SUPPORTED;
+        return KLDR_ERR_UNKNOWN_FORMAT;
+    }
+
+    /* sanity checks. */
+    if (    s.Hdr32.sizeofcmds > kRdrSize(pRdr) - sizeof(mach_header_32_t)
+        ||  s.Hdr32.sizeofcmds < sizeof(load_command_t) * s.Hdr32.ncmds
+        ||  (s.Hdr32.flags & ~MH_VALID_FLAGS))
+        return KLDR_ERR_MACHO_BAD_HEADER;
+    switch (s.Hdr32.cputype)
+    {
+        case CPU_TYPE_X86:
+            fMakeGot = K_FALSE;
+            cbJmpStub = 0;
+            break;
+        case CPU_TYPE_X86_64:
+            fMakeGot = s.Hdr32.filetype == MH_OBJECT;
+            cbJmpStub = fMakeGot ? 8 : 0;
+            break;
+        default:
+            return KLDR_ERR_MACHO_UNSUPPORTED_MACHINE;
+    }
+    if (   s.Hdr32.filetype != MH_OBJECT
+        && s.Hdr32.filetype != MH_EXECUTE
+        && s.Hdr32.filetype != MH_DYLIB
+        && s.Hdr32.filetype != MH_BUNDLE
+        && s.Hdr32.filetype != MH_DSYM
+        && s.Hdr32.filetype != MH_KEXT_BUNDLE)
+        return KLDR_ERR_MACHO_UNSUPPORTED_FILE_TYPE;
+
+    /*
+     * Read and pre-parse the load commands to figure out how many segments we'll be needing.
+     */
+    pbLoadCommands = kHlpAlloc(s.Hdr32.sizeofcmds);
+    if (!pbLoadCommands)
+        return KERR_NO_MEMORY;
+    rc = kRdrRead(pRdr, pbLoadCommands, s.Hdr32.sizeofcmds,
+                     s.Hdr32.magic == IMAGE_MACHO32_SIGNATURE
+                  || s.Hdr32.magic == IMAGE_MACHO32_SIGNATURE_OE
+                  ? sizeof(mach_header_32_t) + offImage
+                  : sizeof(mach_header_64_t) + offImage);
+    if (!rc)
+        rc = kldrModMachOPreParseLoadCommands(pbLoadCommands, &s.Hdr32, pRdr, offImage, fOpenFlags,
+                                              &cSegments, &cSections, &cbStringPool, &fCanLoad, &LinkAddress, &uEffFileType);
+    if (rc)
+    {
+        kHlpFree(pbLoadCommands);
+        return rc;
+    }
+    cSegments += fMakeGot;
+
+
+    /*
+     * Calc the instance size, allocate and initialize it.
+     */
+    cchFilename = kHlpStrLen(kRdrName(pRdr));
+    cb = K_ALIGN_Z(  K_OFFSETOF(KLDRMODMACHO, aSegments[cSegments])
+                      + sizeof(KLDRMODMACHOSECT) * cSections, 16)
+       + K_OFFSETOF(KLDRMOD, aSegments[cSegments])
+       + cchFilename + 1
+       + cbStringPool;
+    pModMachO = (PKLDRMODMACHO)kHlpAlloc(cb);
+    if (!pModMachO)
+        return KERR_NO_MEMORY;
+    *ppModMachO = pModMachO;
+    pModMachO->pbLoadCommands = pbLoadCommands;
+    pModMachO->offImage = offImage;
+
+    /* KLDRMOD */
+    pMod = (PKLDRMOD)((KU8 *)pModMachO + K_ALIGN_Z(  K_OFFSETOF(KLDRMODMACHO, aSegments[cSegments])
+                                                      + sizeof(KLDRMODMACHOSECT) * cSections, 16));
+    pMod->pvData = pModMachO;
+    pMod->pRdr = pRdr;
+    pMod->pOps = NULL;      /* set upon success. */
+    pMod->cSegments = cSegments;
+    pMod->cchFilename = cchFilename;
+    pMod->pszFilename = (char *)&pMod->aSegments[pMod->cSegments];
+    kHlpMemCopy((char *)pMod->pszFilename, kRdrName(pRdr), cchFilename + 1);
+    pMod->pszName = kHlpGetFilename(pMod->pszFilename);
+    pMod->cchName = cchFilename - (pMod->pszName - pMod->pszFilename);
+    pMod->fFlags = 0;
+    switch (s.Hdr32.cputype)
+    {
+        case CPU_TYPE_X86:
+            pMod->enmArch = KCPUARCH_X86_32;
+            pMod->enmEndian = KLDRENDIAN_LITTLE;
+            switch (s.Hdr32.cpusubtype)
+            {
+                case CPU_SUBTYPE_I386_ALL:          pMod->enmCpu = KCPU_X86_32_BLEND; break;
+                /*case CPU_SUBTYPE_386: ^^           pMod->enmCpu = KCPU_I386; break;*/
+                case CPU_SUBTYPE_486:               pMod->enmCpu = KCPU_I486; break;
+                case CPU_SUBTYPE_486SX:             pMod->enmCpu = KCPU_I486SX; break;
+                /*case CPU_SUBTYPE_586: vv */
+                case CPU_SUBTYPE_PENT:              pMod->enmCpu = KCPU_I586; break;
+                case CPU_SUBTYPE_PENTPRO:
+                case CPU_SUBTYPE_PENTII_M3:
+                case CPU_SUBTYPE_PENTII_M5:
+                case CPU_SUBTYPE_CELERON:
+                case CPU_SUBTYPE_CELERON_MOBILE:
+                case CPU_SUBTYPE_PENTIUM_3:
+                case CPU_SUBTYPE_PENTIUM_3_M:
+                case CPU_SUBTYPE_PENTIUM_3_XEON:    pMod->enmCpu = KCPU_I686; break;
+                case CPU_SUBTYPE_PENTIUM_M:
+                case CPU_SUBTYPE_PENTIUM_4:
+                case CPU_SUBTYPE_PENTIUM_4_M:
+                case CPU_SUBTYPE_XEON:
+                case CPU_SUBTYPE_XEON_MP:           pMod->enmCpu = KCPU_P4; break;
+                    break;
+
+                default:
+                    /* Hack for kextutil output. */
+                    if (   s.Hdr32.cpusubtype == 0
+                        && s.Hdr32.filetype   == MH_OBJECT)
+                        break;
+                    return KLDR_ERR_MACHO_UNSUPPORTED_MACHINE;
+            }
+            break;
+
+        case CPU_TYPE_X86_64:
+            pMod->enmArch = KCPUARCH_AMD64;
+            pMod->enmEndian = KLDRENDIAN_LITTLE;
+            switch (s.Hdr32.cpusubtype & ~CPU_SUBTYPE_MASK)
+            {
+                case CPU_SUBTYPE_X86_64_ALL:        pMod->enmCpu = KCPU_AMD64_BLEND; break;
+                default:
+                    return KLDR_ERR_MACHO_UNSUPPORTED_MACHINE;
+            }
+            break;
+
+        default:
+            return KLDR_ERR_MACHO_UNSUPPORTED_MACHINE;
+    }
+
+    pMod->enmFmt = KLDRFMT_MACHO;
+    switch (s.Hdr32.filetype)
+    {
+        case MH_OBJECT:     pMod->enmType = KLDRTYPE_OBJECT; break;
+        case MH_EXECUTE:    pMod->enmType = KLDRTYPE_EXECUTABLE_FIXED; break;
+        case MH_DYLIB:      pMod->enmType = KLDRTYPE_SHARED_LIBRARY_RELOCATABLE; break;
+        case MH_BUNDLE:     pMod->enmType = KLDRTYPE_SHARED_LIBRARY_RELOCATABLE; break;
+        case MH_KEXT_BUNDLE:pMod->enmType = KLDRTYPE_SHARED_LIBRARY_RELOCATABLE; break;
+        case MH_DSYM:       pMod->enmType = KLDRTYPE_DEBUG_INFO; break;
+        default:
+            return KLDR_ERR_MACHO_UNSUPPORTED_FILE_TYPE;
+    }
+    pMod->u32Magic = 0;     /* set upon success. */
+
+    /* KLDRMODMACHO */
+    pModMachO->pMod = pMod;
+    pModMachO->pvBits = NULL;
+    pModMachO->pvMapping = NULL;
+    pModMachO->fOpenFlags = fOpenFlags;
+    pModMachO->Hdr = s.Hdr64;
+    if (    s.Hdr32.magic == IMAGE_MACHO32_SIGNATURE
+        ||  s.Hdr32.magic == IMAGE_MACHO32_SIGNATURE_OE)
+        pModMachO->Hdr.reserved = 0;
+    pModMachO->LinkAddress = LinkAddress;
+    pModMachO->cbImage = 0;
+    pModMachO->fCanLoad = fCanLoad;
+    pModMachO->fMakeGot = fMakeGot;
+    pModMachO->cbJmpStub = cbJmpStub;
+    pModMachO->uEffFileType = uEffFileType;
+    pModMachO->offSymbols = 0;
+    pModMachO->cSymbols = 0;
+    pModMachO->pvaSymbols = NULL;
+    pModMachO->offStrings = 0;
+    pModMachO->cchStrings = 0;
+    pModMachO->pchStrings = NULL;
+    kHlpMemSet(pModMachO->abImageUuid, 0, sizeof(pModMachO->abImageUuid));
+    pModMachO->GotRVA = NIL_KLDRADDR;
+    pModMachO->JmpStubsRVA = NIL_KLDRADDR;
+    pModMachO->cSections = cSections;
+    pModMachO->paSections = (PKLDRMODMACHOSECT)&pModMachO->aSegments[pModMachO->pMod->cSegments];
+
+    /*
+     * Setup the KLDRMOD segment array.
+     */
+    rc = kldrModMachOParseLoadCommands(pModMachO, (char *)pMod->pszFilename + pMod->cchFilename + 1, cbStringPool);
+    if (rc)
+        return rc;
+
+    /*
+     * We're done.
+     */
+    return 0;
+}
+
+
+/**
+ * Converts, validates and preparses the load commands before we carve
+ * out the module instance.
+ *
+ * The conversion that's preformed is format endian to host endian.  The
+ * preparsing has to do with segment counting, section counting and string pool
+ * sizing.
+ *
+ * Segment are created in two different ways, depending on the file type.
+ *
+ * For object files there is only one segment command without a given segment
+ * name. The sections inside that segment have different segment names and are
+ * not sorted by their segname attribute.  We create one segment for each
+ * section, with the segment name being 'segname.sectname' in order to hopefully
+ * keep the names unique.  Debug sections does not get segments.
+ *
+ * For non-object files, one kLdr segment is created for each Mach-O segment.
+ * Debug segments is not exposed by kLdr via the kLdr segment table, but via the
+ * debug enumeration callback API.
+ *
+ * @returns 0 on success.
+ * @returns KLDR_ERR_MACHO_* on failure.
+ * @param   pbLoadCommands  The load commands to parse.
+ * @param   pHdr            The header.
+ * @param   pRdr            The file reader.
+ * @param   offImage        The image header (FAT fun).
+ * @param   pcSegments      Where to store the segment count.
+ * @param   pcSegments      Where to store the section count.
+ * @param   pcbStringPool   Where to store the string pool size.
+ * @param   pfCanLoad       Where to store the can-load-image indicator.
+ * @param   pLinkAddress    Where to store the image link address (i.e. the
+ *                          lowest segment address).
+ */
+static int  kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_header_32_t *pHdr, PKRDR pRdr, KLDRFOFF offImage,
+                                             KU32 fOpenFlags, KU32 *pcSegments, KU32 *pcSections, KU32 *pcbStringPool,
+                                             PKBOOL pfCanLoad, PKLDRADDR pLinkAddress, KU8 *puEffFileType)
+{
+    union
+    {
+        KU8                  *pb;
+        load_command_t       *pLoadCmd;
+        segment_command_32_t *pSeg32;
+        segment_command_64_t *pSeg64;
+        thread_command_t     *pThread;
+        symtab_command_t     *pSymTab;
+        uuid_command_t       *pUuid;
+    } u;
+    const KU64 cbFile = kRdrSize(pRdr) - offImage;
+    KU32 cSegments = 0;
+    KU32 cSections = 0;
+    KU32 cbStringPool = 0;
+    KU32 cLeft = pHdr->ncmds;
+    KU32 cbLeft = pHdr->sizeofcmds;
+    KU8 *pb = pbLoadCommands;
+    int cSegmentCommands = 0;
+    int cSymbolTabs = 0;
+    int fConvertEndian = pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE
+                      || pHdr->magic == IMAGE_MACHO64_SIGNATURE_OE;
+    KU8 uEffFileType = *puEffFileType = pHdr->filetype;
+
+    *pcSegments = 0;
+    *pcSections = 0;
+    *pcbStringPool = 0;
+    *pfCanLoad = K_TRUE;
+    *pLinkAddress = ~(KLDRADDR)0;
+
+    while (cLeft-- > 0)
+    {
+        u.pb = pb;
+
+        /*
+         * Convert and validate command header.
+         */
+        KLDRMODMACHO_CHECK_RETURN(cbLeft >= sizeof(load_command_t), KLDR_ERR_MACHO_BAD_LOAD_COMMAND);
+        if (fConvertEndian)
+        {
+            u.pLoadCmd->cmd = K_E2E_U32(u.pLoadCmd->cmd);
+            u.pLoadCmd->cmdsize = K_E2E_U32(u.pLoadCmd->cmdsize);
+        }
+        KLDRMODMACHO_CHECK_RETURN(u.pLoadCmd->cmdsize <= cbLeft, KLDR_ERR_MACHO_BAD_LOAD_COMMAND);
+        cbLeft -= u.pLoadCmd->cmdsize;
+        pb += u.pLoadCmd->cmdsize;
+
+        /*
+         * Convert endian if needed, parse and validate the command.
+         */
+        switch (u.pLoadCmd->cmd)
+        {
+            case LC_SEGMENT_32:
+            {
+                segment_command_32_t *pSrcSeg = (segment_command_32_t *)u.pLoadCmd;
+                section_32_t   *pFirstSect    = (section_32_t *)(pSrcSeg + 1);
+                section_32_t   *pSect         = pFirstSect;
+                KU32            cSectionsLeft = pSrcSeg->nsects;
+                KU64            offSect       = 0;
+
+                /* Convert and verify the segment. */
+                KLDRMODMACHO_CHECK_RETURN(u.pLoadCmd->cmdsize >= sizeof(segment_command_32_t), KLDR_ERR_MACHO_BAD_LOAD_COMMAND);
+                KLDRMODMACHO_CHECK_RETURN(   pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE
+                                          || pHdr->magic == IMAGE_MACHO32_SIGNATURE, KLDR_ERR_MACHO_BIT_MIX);
+                if (fConvertEndian)
+                {
+                    pSrcSeg->vmaddr   = K_E2E_U32(pSrcSeg->vmaddr);
+                    pSrcSeg->vmsize   = K_E2E_U32(pSrcSeg->vmsize);
+                    pSrcSeg->fileoff  = K_E2E_U32(pSrcSeg->fileoff);
+                    pSrcSeg->filesize = K_E2E_U32(pSrcSeg->filesize);
+                    pSrcSeg->maxprot  = K_E2E_U32(pSrcSeg->maxprot);
+                    pSrcSeg->initprot = K_E2E_U32(pSrcSeg->initprot);
+                    pSrcSeg->nsects   = K_E2E_U32(pSrcSeg->nsects);
+                    pSrcSeg->flags    = K_E2E_U32(pSrcSeg->flags);
+                }
+
+                /* Validation code shared with the 64-bit variant. */
+                #define VALIDATE_AND_ADD_SEGMENT(a_cBits) \
+                do { \
+                    KBOOL fSkipSeg = !kHlpStrComp(pSrcSeg->segname, "__DWARF")   /* Note: Not for non-object files. */ \
+                                  || (   !kHlpStrComp(pSrcSeg->segname, "__CTF") /* Their CTF tool did/does weird things, */ \
+                                      && pSrcSeg->vmsize == 0)                   /* overlapping vmaddr and zero vmsize. */ \
+                                  || (cSectionsLeft > 0 && (pFirstSect->flags & S_ATTR_DEBUG)); \
+                    \
+                    /* MH_DSYM files for MH_OBJECT files must have MH_OBJECT segment translation. */ \
+                    if (   uEffFileType == MH_DSYM \
+                        && cSegmentCommands == 0 \
+                        && pSrcSeg->segname[0] == '\0') \
+                        *puEffFileType = uEffFileType = MH_OBJECT; \
+                    \
+                    KLDRMODMACHO_CHECK_RETURN(   pSrcSeg->filesize == 0 \
+                                              || (   pSrcSeg->fileoff <= cbFile \
+                                                  && (KU64)pSrcSeg->fileoff + pSrcSeg->filesize <= cbFile), \
+                                              KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \
+                    KLDRMODMACHO_CHECK_RETURN(   pSrcSeg->filesize <= pSrcSeg->vmsize \
+                                              || (fSkipSeg && !kHlpStrComp(pSrcSeg->segname, "__CTF") /* see above */), \
+                                              KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \
+                    KLDRMODMACHO_CHECK_RETURN((pSrcSeg->maxprot & pSrcSeg->initprot) == pSrcSeg->initprot, \
+                                              KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \
+                    KLDRMODMACHO_CHECK_RETURN(!(pSrcSeg->flags & ~(SG_HIGHVM | SG_FVMLIB | SG_NORELOC | SG_PROTECTED_VERSION_1)), \
+                                              KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \
+                    KLDRMODMACHO_CHECK_RETURN(   pSrcSeg->nsects * sizeof(section_##a_cBits##_t) \
+                                              <= u.pLoadCmd->cmdsize - sizeof(segment_command_##a_cBits##_t), \
+                                              KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \
+                    KLDRMODMACHO_CHECK_RETURN(   uEffFileType != MH_OBJECT \
+                                              || cSegmentCommands == 0 \
+                                              || (   cSegmentCommands == 1 \
+                                                  && uEffFileType == MH_OBJECT \
+                                                  && pHdr->filetype == MH_DSYM \
+                                                  && fSkipSeg), \
+                                              KLDR_ERR_MACHO_BAD_OBJECT_FILE); \
+                    cSegmentCommands++; \
+                    \
+                    /* Add the segment, if not object file. */ \
+                    if (!fSkipSeg && uEffFileType != MH_OBJECT) \
+                    { \
+                        cbStringPool += kHlpStrNLen(&pSrcSeg->segname[0], sizeof(pSrcSeg->segname)) + 1; \
+                        cSegments++; \
+                        if (cSegments == 1) /* The link address is set by the first segment. */  \
+                            *pLinkAddress = pSrcSeg->vmaddr; \
+                    } \
+                } while (0)
+
+                VALIDATE_AND_ADD_SEGMENT(32);
+
+                /*
+                 * Convert, validate and parse the sections.
+                 */
+                cSectionsLeft = pSrcSeg->nsects;
+                pFirstSect = pSect = (section_32_t *)(pSrcSeg + 1);
+                while (cSectionsLeft-- > 0)
+                {
+                    if (fConvertEndian)
+                    {
+                        pSect->addr      = K_E2E_U32(pSect->addr);
+                        pSect->size      = K_E2E_U32(pSect->size);
+                        pSect->offset    = K_E2E_U32(pSect->offset);
+                        pSect->align     = K_E2E_U32(pSect->align);
+                        pSect->reloff    = K_E2E_U32(pSect->reloff);
+                        pSect->nreloc    = K_E2E_U32(pSect->nreloc);
+                        pSect->flags     = K_E2E_U32(pSect->flags);
+                        pSect->reserved1 = K_E2E_U32(pSect->reserved1);
+                        pSect->reserved2 = K_E2E_U32(pSect->reserved2);
+                    }
+
+                    /* Validation code shared with the 64-bit variant. */
+                    #define VALIDATE_AND_ADD_SECTION(a_cBits) \
+                    do { \
+                        int fFileBits; \
+                        \
+                        /* validate */ \
+                        if (uEffFileType != MH_OBJECT) \
+                            KLDRMODMACHO_CHECK_RETURN(!kHlpStrComp(pSect->segname, pSrcSeg->segname),\
+                                                      KLDR_ERR_MACHO_BAD_SECTION); \
+                        \
+                        switch (pSect->flags & SECTION_TYPE) \
+                        { \
+                            case S_ZEROFILL: \
+                                KLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, KLDR_ERR_MACHO_BAD_SECTION); \
+                                KLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, KLDR_ERR_MACHO_BAD_SECTION); \
+                                fFileBits = 0; \
+                                break; \
+                            case S_REGULAR: \
+                            case S_CSTRING_LITERALS: \
+                            case S_COALESCED: \
+                            case S_4BYTE_LITERALS: \
+                            case S_8BYTE_LITERALS: \
+                            case S_16BYTE_LITERALS: \
+                                KLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, KLDR_ERR_MACHO_BAD_SECTION); \
+                                KLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, KLDR_ERR_MACHO_BAD_SECTION); \
+                                fFileBits = 1; \
+                                break; \
+                            \
+                            case S_SYMBOL_STUBS: \
+                                KLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, KLDR_ERR_MACHO_BAD_SECTION); \
+                                /* reserved2 == stub size. 0 has been seen (corecrypto.kext) */ \
+                                KLDRMODMACHO_CHECK_RETURN(pSect->reserved2 < 64, KLDR_ERR_MACHO_BAD_SECTION); \
+                                fFileBits = 1; \
+                                break; \
+                            \
+                            case S_NON_LAZY_SYMBOL_POINTERS: \
+                            case S_LAZY_SYMBOL_POINTERS: \
+                            case S_LAZY_DYLIB_SYMBOL_POINTERS: \
+                                /* (reserved 1 = is indirect symbol table index) */ \
+                                KLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, KLDR_ERR_MACHO_BAD_SECTION); \
+                                *pfCanLoad = K_FALSE; \
+                                fFileBits = -1; /* __DATA.__got in the 64-bit mach_kernel has bits, any things without bits? */ \
+                                break; \
+                            \
+                            case S_MOD_INIT_FUNC_POINTERS: \
+                                /** @todo this requires a query API or flag... (e.g. C++ constructors) */ \
+                                KLDRMODMACHO_CHECK_RETURN(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO, \
+                                                          KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION); \
+                            case S_MOD_TERM_FUNC_POINTERS: \
+                                /** @todo this requires a query API or flag... (e.g. C++ destructors) */ \
+                                KLDRMODMACHO_CHECK_RETURN(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO, \
+                                                          KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION); \
+                                KLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, KLDR_ERR_MACHO_BAD_SECTION); \
+                                KLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, KLDR_ERR_MACHO_BAD_SECTION); \
+                                fFileBits = 1; \
+                                break; /* ignored */ \
+                            \
+                            case S_LITERAL_POINTERS: \
+                            case S_DTRACE_DOF: \
+                                KLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, KLDR_ERR_MACHO_BAD_SECTION); \
+                                KLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, KLDR_ERR_MACHO_BAD_SECTION); \
+                                fFileBits = 1; \
+                                break; \
+                            \
+                            case S_INTERPOSING: \
+                            case S_GB_ZEROFILL: \
+                                KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_UNSUPPORTED_SECTION); \
+                            \
+                            default: \
+                                KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_UNKNOWN_SECTION); \
+                        } \
+                        KLDRMODMACHO_CHECK_RETURN(!(pSect->flags & ~(  S_ATTR_PURE_INSTRUCTIONS | S_ATTR_NO_TOC | S_ATTR_STRIP_STATIC_SYMS \
+                                                                     | S_ATTR_NO_DEAD_STRIP | S_ATTR_LIVE_SUPPORT | S_ATTR_SELF_MODIFYING_CODE \
+                                                                     | S_ATTR_DEBUG | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_EXT_RELOC \
+                                                                     | S_ATTR_LOC_RELOC | SECTION_TYPE)), \
+                                                  KLDR_ERR_MACHO_BAD_SECTION); \
+                        KLDRMODMACHO_CHECK_RETURN((pSect->flags & S_ATTR_DEBUG) == (pSect->flags & S_ATTR_DEBUG), \
+                                                  KLDR_ERR_MACHO_MIXED_DEBUG_SECTION_FLAGS); \
+                        \
+                        KLDRMODMACHO_CHECK_RETURN(pSect->addr - pSrcSeg->vmaddr <= pSrcSeg->vmsize, \
+                                                  KLDR_ERR_MACHO_BAD_SECTION); \
+                        KLDRMODMACHO_CHECK_RETURN(   pSect->addr - pSrcSeg->vmaddr + pSect->size <= pSrcSeg->vmsize \
+                                                  || !kHlpStrComp(pSrcSeg->segname, "__CTF") /* see above */, \
+                                                  KLDR_ERR_MACHO_BAD_SECTION); \
+                        KLDRMODMACHO_CHECK_RETURN(pSect->align < 31, \
+                                                  KLDR_ERR_MACHO_BAD_SECTION); \
+                        /* Workaround for buggy ld64 (or as, llvm, ++) that produces a misaligned __TEXT.__unwind_info. */ \
+                        /* Seen: pSect->align = 4, pSect->addr = 0x5ebe14.  Just adjust the alignment down. */ \
+                        if (   ((K_BIT32(pSect->align) - KU32_C(1)) & pSect->addr) \
+                            && pSect->align == 4 \
+                            && kHlpStrComp(pSect->sectname, "__unwind_info") == 0) \
+                            pSect->align = 2; \
+                        KLDRMODMACHO_CHECK_RETURN(!((K_BIT32(pSect->align) - KU32_C(1)) & pSect->addr), \
+                                                  KLDR_ERR_MACHO_BAD_SECTION); \
+                        KLDRMODMACHO_CHECK_RETURN(!((K_BIT32(pSect->align) - KU32_C(1)) & pSrcSeg->vmaddr), \
+                                                  KLDR_ERR_MACHO_BAD_SECTION); \
+                        \
+                        /* Adjust the section offset before we check file offset. */ \
+                        offSect = (offSect + K_BIT64(pSect->align) - KU64_C(1)) & ~(K_BIT64(pSect->align) - KU64_C(1)); \
+                        if (pSect->addr) \
+                        { \
+                            KLDRMODMACHO_CHECK_RETURN(offSect <= pSect->addr - pSrcSeg->vmaddr, KLDR_ERR_MACHO_BAD_SECTION); \
+                            if (offSect < pSect->addr - pSrcSeg->vmaddr) \
+                                offSect = pSect->addr - pSrcSeg->vmaddr; \
+                        } \
+                        \
+                        if (fFileBits && pSect->offset == 0 && pSrcSeg->fileoff == 0 && pHdr->filetype == MH_DSYM) \
+                            fFileBits = 0; \
+                        if (fFileBits) \
+                        { \
+                            if (uEffFileType != MH_OBJECT) \
+                            { \
+                                KLDRMODMACHO_CHECK_RETURN(pSect->offset == pSrcSeg->fileoff + offSect, \
+                                                          KLDR_ERR_MACHO_NON_CONT_SEG_BITS); \
+                                KLDRMODMACHO_CHECK_RETURN(pSect->offset - pSrcSeg->fileoff <= pSrcSeg->filesize, \
+                                                          KLDR_ERR_MACHO_BAD_SECTION); \
+                            } \
+                            KLDRMODMACHO_CHECK_RETURN(pSect->offset <= cbFile, \
+                                                      KLDR_ERR_MACHO_BAD_SECTION); \
+                            KLDRMODMACHO_CHECK_RETURN((KU64)pSect->offset + pSect->size <= cbFile, \
+                                                      KLDR_ERR_MACHO_BAD_SECTION); \
+                        } \
+                        else \
+                            KLDRMODMACHO_CHECK_RETURN(pSect->offset == 0, KLDR_ERR_MACHO_BAD_SECTION); \
+                        \
+                        if (!pSect->nreloc) \
+                            KLDRMODMACHO_CHECK_RETURN(!pSect->reloff, \
+                                                      KLDR_ERR_MACHO_BAD_SECTION); \
+                        else \
+                        { \
+                            KLDRMODMACHO_CHECK_RETURN(pSect->reloff <= cbFile, \
+                                                      KLDR_ERR_MACHO_BAD_SECTION); \
+                            KLDRMODMACHO_CHECK_RETURN(     (KU64)pSect->reloff \
+                                                         + (KLDRFOFF)pSect->nreloc * sizeof(macho_relocation_info_t) \
+                                                      <= cbFile, \
+                                                      KLDR_ERR_MACHO_BAD_SECTION); \
+                        } \
+                        \
+                        /* Validate against file type (pointless?) and count the section, for object files add segment. */ \
+                        switch (uEffFileType) \
+                        { \
+                            case MH_OBJECT: \
+                                if (   !(pSect->flags & S_ATTR_DEBUG) \
+                                    && kHlpStrComp(pSect->segname, "__DWARF")) \
+                                { \
+                                    cbStringPool += kHlpStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1; \
+                                    cbStringPool += kHlpStrNLen(&pSect->sectname[0], sizeof(pSect->sectname)) + 1; \
+                                    cSegments++; \
+                                    if (cSegments == 1) /* The link address is set by the first segment. */  \
+                                        *pLinkAddress = pSect->addr; \
+                                } \
+                                /* fall thru */ \
+                            case MH_EXECUTE: \
+                            case MH_DYLIB: \
+                            case MH_BUNDLE: \
+                            case MH_DSYM: \
+                            case MH_KEXT_BUNDLE: \
+                                cSections++; \
+                                break; \
+                            default: \
+                                KLDRMODMACHO_FAILED_RETURN(KERR_INVALID_PARAMETER); \
+                        } \
+                        \
+                        /* Advance the section offset, since we're also aligning it. */ \
+                        offSect += pSect->size; \
+                    } while (0) /* VALIDATE_AND_ADD_SECTION */
+
+                    VALIDATE_AND_ADD_SECTION(32);
+
+                    /* next */
+                    pSect++;
+                }
+                break;
+            }
+
+            case LC_SEGMENT_64:
+            {
+                segment_command_64_t *pSrcSeg = (segment_command_64_t *)u.pLoadCmd;
+                section_64_t   *pFirstSect    = (section_64_t *)(pSrcSeg + 1);
+                section_64_t   *pSect         = pFirstSect;
+                KU32            cSectionsLeft = pSrcSeg->nsects;
+                KU64            offSect       = 0;
+
+                /* Convert and verify the segment. */
+                KLDRMODMACHO_CHECK_RETURN(u.pLoadCmd->cmdsize >= sizeof(segment_command_64_t), KLDR_ERR_MACHO_BAD_LOAD_COMMAND);
+                KLDRMODMACHO_CHECK_RETURN(   pHdr->magic == IMAGE_MACHO64_SIGNATURE_OE
+                                          || pHdr->magic == IMAGE_MACHO64_SIGNATURE, KLDR_ERR_MACHO_BIT_MIX);
+                if (fConvertEndian)
+                {
+                    pSrcSeg->vmaddr   = K_E2E_U64(pSrcSeg->vmaddr);
+                    pSrcSeg->vmsize   = K_E2E_U64(pSrcSeg->vmsize);
+                    pSrcSeg->fileoff  = K_E2E_U64(pSrcSeg->fileoff);
+                    pSrcSeg->filesize = K_E2E_U64(pSrcSeg->filesize);
+                    pSrcSeg->maxprot  = K_E2E_U32(pSrcSeg->maxprot);
+                    pSrcSeg->initprot = K_E2E_U32(pSrcSeg->initprot);
+                    pSrcSeg->nsects   = K_E2E_U32(pSrcSeg->nsects);
+                    pSrcSeg->flags    = K_E2E_U32(pSrcSeg->flags);
+                }
+
+                VALIDATE_AND_ADD_SEGMENT(64);
+
+                /*
+                 * Convert, validate and parse the sections.
+                 */
+                while (cSectionsLeft-- > 0)
+                {
+                    if (fConvertEndian)
+                    {
+                        pSect->addr      = K_E2E_U64(pSect->addr);
+                        pSect->size      = K_E2E_U64(pSect->size);
+                        pSect->offset    = K_E2E_U32(pSect->offset);
+                        pSect->align     = K_E2E_U32(pSect->align);
+                        pSect->reloff    = K_E2E_U32(pSect->reloff);
+                        pSect->nreloc    = K_E2E_U32(pSect->nreloc);
+                        pSect->flags     = K_E2E_U32(pSect->flags);
+                        pSect->reserved1 = K_E2E_U32(pSect->reserved1);
+                        pSect->reserved2 = K_E2E_U32(pSect->reserved2);
+                    }
+
+                    VALIDATE_AND_ADD_SECTION(64);
+
+                    /* next */
+                    pSect++;
+                }
+                break;
+            } /* LC_SEGMENT_64 */
+
+
+            case LC_SYMTAB:
+            {
+                KSIZE cbSym;
+                if (fConvertEndian)
+                {
+                    u.pSymTab->symoff  = K_E2E_U32(u.pSymTab->symoff);
+                    u.pSymTab->nsyms   = K_E2E_U32(u.pSymTab->nsyms);
+                    u.pSymTab->stroff  = K_E2E_U32(u.pSymTab->stroff);
+                    u.pSymTab->strsize = K_E2E_U32(u.pSymTab->strsize);
+                }
+
+                /* verify */
+                cbSym = pHdr->magic == IMAGE_MACHO32_SIGNATURE
+                     || pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE
+                      ? sizeof(macho_nlist_32_t)
+                      : sizeof(macho_nlist_64_t);
+                if (    u.pSymTab->symoff >= cbFile
+                    ||  (KU64)u.pSymTab->symoff + u.pSymTab->nsyms * cbSym > cbFile)
+                    KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND);
+                if (    u.pSymTab->stroff >= cbFile
+                    ||  (KU64)u.pSymTab->stroff + u.pSymTab->strsize > cbFile)
+                    KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND);
+
+                /* only one string in objects, please. */
+                cSymbolTabs++;
+                if (    uEffFileType == MH_OBJECT
+                    &&  cSymbolTabs != 1)
+                    KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_OBJECT_FILE);
+                break;
+            }
+
+            case LC_DYSYMTAB:
+                /** @todo deal with this! */
+                break;
+
+            case LC_THREAD:
+            case LC_UNIXTHREAD:
+            {
+                KU32 *pu32 = (KU32 *)(u.pb + sizeof(load_command_t));
+                KU32 cItemsLeft = (u.pThread->cmdsize - sizeof(load_command_t)) / sizeof(KU32);
+                while (cItemsLeft)
+                {
+                    /* convert & verify header items ([0] == flavor, [1] == KU32 count). */
+                    if (cItemsLeft < 2)
+                        KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND);
+                    if (fConvertEndian)
+                    {
+                        pu32[0] = K_E2E_U32(pu32[0]);
+                        pu32[1] = K_E2E_U32(pu32[1]);
+                    }
+                    if (pu32[1] + 2 > cItemsLeft)
+                        KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND);
+
+                    /* convert & verify according to flavor. */
+                    switch (pu32[0])
+                    {
+                        /** @todo */
+                        default:
+                            break;
+                    }
+
+                    /* next */
+                    cItemsLeft -= pu32[1] + 2;
+                    pu32 += pu32[1] + 2;
+                }
+                break;
+            }
+
+            case LC_UUID:
+                if (u.pUuid->cmdsize != sizeof(uuid_command_t))
+                    KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND);
+                /** @todo Check anything here need converting? */
+                break;
+
+            case LC_CODE_SIGNATURE:
+                if (u.pUuid->cmdsize != sizeof(linkedit_data_command_t))
+                    KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND);
+                break;
+
+            case LC_VERSION_MIN_MACOSX:
+            case LC_VERSION_MIN_IPHONEOS:
+                if (u.pUuid->cmdsize != sizeof(version_min_command_t))
+                    KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND);
+                break;
+
+            case LC_SOURCE_VERSION:     /* Harmless. It just gives a clue regarding the source code revision/version. */
+            case LC_DATA_IN_CODE:       /* Ignore */
+            case LC_DYLIB_CODE_SIGN_DRS:/* Ignore */
+                /** @todo valid command size. */
+                break;
+
+            case LC_FUNCTION_STARTS:    /** @todo dylib++ */
+                /* Ignore for now. */
+                break;
+            case LC_ID_DYLIB:           /** @todo dylib */
+            case LC_LOAD_DYLIB:         /** @todo dylib */
+            case LC_LOAD_DYLINKER:      /** @todo dylib */
+            case LC_TWOLEVEL_HINTS:     /** @todo dylib */
+            case LC_LOAD_WEAK_DYLIB:    /** @todo dylib */
+            case LC_ID_DYLINKER:        /** @todo dylib */
+            case LC_RPATH:              /** @todo dylib */
+            case LC_SEGMENT_SPLIT_INFO: /** @todo dylib++ */
+            case LC_REEXPORT_DYLIB:     /** @todo dylib */
+            case LC_DYLD_INFO:          /** @todo dylib */
+            case LC_DYLD_INFO_ONLY:     /** @todo dylib */
+            case LC_LOAD_UPWARD_DYLIB:  /** @todo dylib */
+            case LC_DYLD_ENVIRONMENT:   /** @todo dylib */
+            case LC_MAIN: /** @todo parse this and find and entry point or smth. */
+                /** @todo valid command size. */
+                if (!(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO))
+                    KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_UNSUPPORTED_LOAD_COMMAND);
+                *pfCanLoad = K_FALSE;
+                break;
+
+            case LC_LOADFVMLIB:
+            case LC_IDFVMLIB:
+            case LC_IDENT:
+            case LC_FVMFILE:
+            case LC_PREPAGE:
+            case LC_PREBOUND_DYLIB:
+            case LC_ROUTINES:
+            case LC_ROUTINES_64:
+            case LC_SUB_FRAMEWORK:
+            case LC_SUB_UMBRELLA:
+            case LC_SUB_CLIENT:
+            case LC_SUB_LIBRARY:
+            case LC_PREBIND_CKSUM:
+            case LC_SYMSEG:
+                KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_UNSUPPORTED_LOAD_COMMAND);
+
+            default:
+                KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_UNKNOWN_LOAD_COMMAND);
+        }
+    }
+
+    /* be strict. */
+    if (cbLeft)
+        KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND);
+
+    switch (uEffFileType)
+    {
+        case MH_OBJECT:
+        case MH_EXECUTE:
+        case MH_DYLIB:
+        case MH_BUNDLE:
+        case MH_DSYM:
+        case MH_KEXT_BUNDLE:
+            if (!cSegments)
+                KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_OBJECT_FILE);
+            break;
+    }
+
+    *pcSegments = cSegments;
+    *pcSections = cSections;
+    *pcbStringPool = cbStringPool;
+
+    return 0;
+}
+
+
+/**
+ * Parses the load commands after we've carved out the module instance.
+ *
+ * This fills in the segment table and perhaps some other properties.
+ *
+ * @returns 0 on success.
+ * @returns KLDR_ERR_MACHO_* on failure.
+ * @param   pModMachO       The module.
+ * @param   pbStringPool    The string pool
+ * @param   cbStringPool    The size of the string pool.
+ */
+static int  kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStringPool, KU32 cbStringPool)
+{
+    union
+    {
+        const KU8                  *pb;
+        const load_command_t       *pLoadCmd;
+        const segment_command_32_t *pSeg32;
+        const segment_command_64_t *pSeg64;
+        const symtab_command_t     *pSymTab;
+        const uuid_command_t       *pUuid;
+    } u;
+    KU32 cLeft = pModMachO->Hdr.ncmds;
+    KU32 cbLeft = pModMachO->Hdr.sizeofcmds;
+    const KU8 *pb = pModMachO->pbLoadCommands;
+    PKLDRSEG pDstSeg = &pModMachO->pMod->aSegments[0];
+    PKLDRMODMACHOSEG pSegExtra = &pModMachO->aSegments[0];
+    PKLDRMODMACHOSECT pSectExtra = pModMachO->paSections;
+    const KU32 cSegments = pModMachO->pMod->cSegments;
+    PKLDRSEG pSegItr;
+    K_NOREF(cbStringPool);
+
+    while (cLeft-- > 0)
+    {
+        u.pb = pb;
+        cbLeft -= u.pLoadCmd->cmdsize;
+        pb += u.pLoadCmd->cmdsize;
+
+        /*
+         * Convert endian if needed, parse and validate the command.
+         */
+        switch (u.pLoadCmd->cmd)
+        {
+            case LC_SEGMENT_32:
+            {
+                const segment_command_32_t *pSrcSeg = (const segment_command_32_t *)u.pLoadCmd;
+                section_32_t   *pFirstSect    = (section_32_t *)(pSrcSeg + 1);
+                section_32_t   *pSect         = pFirstSect;
+                KU32            cSectionsLeft = pSrcSeg->nsects;
+
+                /* Adds a segment, used by the macro below and thus shared with the 64-bit segment variant. */
+                #define NEW_SEGMENT(a_cBits, a_achName1, a_fObjFile, a_achName2, a_SegAddr, a_cbSeg, a_fFileBits, a_offFile, a_cbFile) \
+                do { \
+                    pDstSeg->pvUser = NULL; \
+                    pDstSeg->pchName = pbStringPool; \
+                    pDstSeg->cchName = (KU32)kHlpStrNLen(a_achName1, sizeof(a_achName1)); \
+                    kHlpMemCopy(pbStringPool, a_achName1, pDstSeg->cchName); \
+                    pbStringPool += pDstSeg->cchName; \
+                    if (a_fObjFile) \
+                    {   /* MH_OBJECT: Add '.sectname' - sections aren't sorted by segments. */ \
+                        KSIZE cchName2 = kHlpStrNLen(a_achName2, sizeof(a_achName2)); \
+                        *pbStringPool++ = '.'; \
+                        kHlpMemCopy(pbStringPool, a_achName2, cchName2); \
+                        pbStringPool += cchName2; \
+                        pDstSeg->cchName += cchName2; \
+                    } \
+                    *pbStringPool++ = '\0'; \
+                    pDstSeg->SelFlat = 0; \
+                    pDstSeg->Sel16bit = 0; \
+                    pDstSeg->fFlags = 0; \
+                    pDstSeg->enmProt = KPROT_EXECUTE_WRITECOPY; /** @todo fixme! */ \
+                    pDstSeg->cb = (a_cbSeg); \
+                    pDstSeg->Alignment = 1; /* updated while parsing sections. */ \
+                    pDstSeg->LinkAddress = (a_SegAddr); \
+                    if (a_fFileBits) \
+                    { \
+                        pDstSeg->offFile = (a_offFile) + pModMachO->offImage; \
+                        pDstSeg->cbFile  = (a_cbFile); \
+                    } \
+                    else \
+                    { \
+                        pDstSeg->offFile = -1; \
+                        pDstSeg->cbFile  = -1; \
+                    } \
+                    pDstSeg->RVA = (a_SegAddr) - pModMachO->LinkAddress; \
+                    pDstSeg->cbMapped = 0; \
+                    pDstSeg->MapAddress = 0; \
+                    \
+                    pSegExtra->iOrgSegNo = pSegExtra - &pModMachO->aSegments[0]; \
+                    pSegExtra->cSections = 0; \
+                    pSegExtra->paSections = pSectExtra; \
+                } while (0)
+
+                /* Closes the new segment - parter of NEW_SEGMENT. */
+                #define CLOSE_SEGMENT() \
+                do { \
+                    pSegExtra->cSections = pSectExtra - pSegExtra->paSections; \
+                    pSegExtra++; \
+                    pDstSeg++; \
+                } while (0)
+
+
+                /* Shared with the 64-bit variant. */
+                #define ADD_SEGMENT_AND_ITS_SECTIONS(a_cBits) \
+                do { \
+                    KBOOL fAddSegOuter = K_FALSE; \
+                    \
+                    /* \
+                     * Check that the segment name is unique.  We couldn't do that \
+                     * in the preparsing stage. \
+                     */ \
+                    if (pModMachO->uEffFileType != MH_OBJECT) \
+                        for (pSegItr = &pModMachO->pMod->aSegments[0]; pSegItr != pDstSeg; pSegItr++) \
+                            if (!kHlpStrNComp(pSegItr->pchName, pSrcSeg->segname, sizeof(pSrcSeg->segname))) \
+                                KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_DUPLICATE_SEGMENT_NAME); \
+                    \
+                    /* \
+                     * Create a new segment, unless we're supposed to skip this one. \
+                     */ \
+                    if (   pModMachO->uEffFileType != MH_OBJECT \
+                        && (cSectionsLeft == 0 || !(pFirstSect->flags & S_ATTR_DEBUG)) \
+                        && kHlpStrComp(pSrcSeg->segname, "__DWARF") \
+                        && kHlpStrComp(pSrcSeg->segname, "__CTF") ) \
+                    { \
+                        NEW_SEGMENT(a_cBits, pSrcSeg->segname, K_FALSE /*a_fObjFile*/, 0 /*a_achName2*/, \
+                                    pSrcSeg->vmaddr, pSrcSeg->vmsize, \
+                                    pSrcSeg->filesize != 0, pSrcSeg->fileoff, pSrcSeg->filesize); \
+                        fAddSegOuter = K_TRUE; \
+                    } \
+                    \
+                    /* \
+                     * Convert and parse the sections. \
+                     */ \
+                    while (cSectionsLeft-- > 0) \
+                    { \
+                        /* New segment if object file. */ \
+                        KBOOL fAddSegInner = K_FALSE; \
+                        if (   pModMachO->uEffFileType == MH_OBJECT \
+                            && !(pSect->flags & S_ATTR_DEBUG) \
+                            && kHlpStrComp(pSrcSeg->segname, "__DWARF") \
+                            && kHlpStrComp(pSrcSeg->segname, "__CTF") ) \
+                        { \
+                            kHlpAssert(!fAddSegOuter); \
+                            NEW_SEGMENT(a_cBits, pSect->segname, K_TRUE /*a_fObjFile*/, pSect->sectname, \
+                                        pSect->addr, pSect->size, \
+                                        pSect->offset != 0, pSect->offset, pSect->size); \
+                            fAddSegInner = K_TRUE; \
+                        } \
+                        \
+                        /* Section data extract. */ \
+                        pSectExtra->cb = pSect->size; \
+                        pSectExtra->RVA = pSect->addr - pDstSeg->LinkAddress; \
+                        pSectExtra->LinkAddress = pSect->addr; \
+                        if (pSect->offset) \
+                            pSectExtra->offFile = pSect->offset + pModMachO->offImage; \
+                        else \
+                            pSectExtra->offFile = -1; \
+                        pSectExtra->cFixups = pSect->nreloc; \
+                        pSectExtra->paFixups = NULL; \
+                        if (pSect->nreloc) \
+                            pSectExtra->offFixups = pSect->reloff + pModMachO->offImage; \
+                        else \
+                            pSectExtra->offFixups = -1; \
+                        pSectExtra->fFlags = pSect->flags; \
+                        pSectExtra->iSegment = pSegExtra - &pModMachO->aSegments[0]; \
+                        pSectExtra->pvMachoSection = pSect; \
+                        \
+                        /* Update the segment alignment, if we're not skipping it. */ \
+                        if (   (fAddSegOuter || fAddSegInner) \
+                            && pDstSeg->Alignment < ((KLDRADDR)1 << pSect->align)) \
+                            pDstSeg->Alignment = (KLDRADDR)1 << pSect->align; \
+                        \
+                        /* Next section, and if object file next segment. */ \
+                        pSectExtra++; \
+                        pSect++; \
+                        if (fAddSegInner) \
+                            CLOSE_SEGMENT(); \
+                    } \
+                    \
+                    /* Close the segment and advance. */ \
+                    if (fAddSegOuter) \
+                        CLOSE_SEGMENT(); \
+                } while (0) /* ADD_SEGMENT_AND_ITS_SECTIONS */
+
+                ADD_SEGMENT_AND_ITS_SECTIONS(32);
+                break;
+            }
+
+            case LC_SEGMENT_64:
+            {
+                const segment_command_64_t *pSrcSeg = (const segment_command_64_t *)u.pLoadCmd;
+                section_64_t   *pFirstSect    = (section_64_t *)(pSrcSeg + 1);
+                section_64_t   *pSect         = pFirstSect;
+                KU32            cSectionsLeft = pSrcSeg->nsects;
+
+                ADD_SEGMENT_AND_ITS_SECTIONS(64);
+                break;
+            }
+
+            case LC_SYMTAB:
+                switch (pModMachO->uEffFileType)
+                {
+                    case MH_OBJECT:
+                    case MH_EXECUTE:
+                    case MH_DYLIB: /** @todo ??? */
+                    case MH_BUNDLE:  /** @todo ??? */
+                    case MH_DSYM:
+                    case MH_KEXT_BUNDLE:
+                        pModMachO->offSymbols = u.pSymTab->symoff + pModMachO->offImage;
+                        pModMachO->cSymbols = u.pSymTab->nsyms;
+                        pModMachO->offStrings = u.pSymTab->stroff + pModMachO->offImage;
+                        pModMachO->cchStrings = u.pSymTab->strsize;
+                        break;
+                }
+                break;
+
+            case LC_UUID:
+                kHlpMemCopy(pModMachO->abImageUuid, u.pUuid->uuid, sizeof(pModMachO->abImageUuid));
+                break;
+
+            default:
+                break;
+        } /* command switch */
+    } /* while more commands */
+
+    kHlpAssert(pDstSeg == &pModMachO->pMod->aSegments[cSegments - pModMachO->fMakeGot]);
+
+    /*
+     * Adjust mapping addresses calculating the image size.
+     */
+    {
+        KBOOL               fLoadLinkEdit = K_FALSE;
+        PKLDRMODMACHOSECT   pSectExtraItr;
+        KLDRADDR            uNextRVA = 0;
+        KLDRADDR            cb;
+        KU32                cSegmentsToAdjust = cSegments - pModMachO->fMakeGot;
+        KU32                c;
+
+        for (;;)
+        {
+            /* Check if there is __DWARF segment at the end and make sure it's left
+               out of the RVA negotiations and image loading. */
+            if (   cSegmentsToAdjust > 0
+                && !kHlpStrComp(pModMachO->pMod->aSegments[cSegmentsToAdjust - 1].pchName, "__DWARF"))
+            {
+                cSegmentsToAdjust--;
+                pModMachO->pMod->aSegments[cSegmentsToAdjust].RVA = NIL_KLDRADDR;
+                pModMachO->pMod->aSegments[cSegmentsToAdjust].cbMapped = 0;
+                continue;
+            }
+
+            /* If we're skipping the __LINKEDIT segment, check for it and adjust
+               the number of segments we'll be messing with here.  ASSUMES it's
+               last (by now anyway). */
+            if (   !fLoadLinkEdit
+                && cSegmentsToAdjust > 0
+                && !kHlpStrComp(pModMachO->pMod->aSegments[cSegmentsToAdjust - 1].pchName, "__LINKEDIT"))
+            {
+                cSegmentsToAdjust--;
+                pModMachO->pMod->aSegments[cSegmentsToAdjust].RVA = NIL_KLDRADDR;
+                pModMachO->pMod->aSegments[cSegmentsToAdjust].cbMapped = 0;
+                continue;
+            }
+            break;
+        }
+
+        /* Adjust RVAs. */
+        c = cSegmentsToAdjust;
+        for (pDstSeg = &pModMachO->pMod->aSegments[0]; c-- > 0; pDstSeg++)
+        {
+            cb = pDstSeg->RVA - uNextRVA;
+            if (cb >= 0x00100000) /* 1MB */
+            {
+                pDstSeg->RVA = uNextRVA;
+                pModMachO->pMod->fFlags |= KLDRMOD_FLAGS_NON_CONTIGUOUS_LINK_ADDRS;
+            }
+            uNextRVA = pDstSeg->RVA + KLDR_ALIGN_ADDR(pDstSeg->cb, pDstSeg->Alignment);
+        }
+
+        /* Calculate the cbMapping members. */
+        c = cSegmentsToAdjust;
+        for (pDstSeg = &pModMachO->pMod->aSegments[0]; c-- > 1; pDstSeg++)
+        {
+
+            cb = pDstSeg[1].RVA - pDstSeg->RVA;
+            pDstSeg->cbMapped = (KSIZE)cb == cb ? cb : KSIZE_MAX;
+        }
+
+        cb = KLDR_ALIGN_ADDR(pDstSeg->cb, pDstSeg->Alignment);
+        pDstSeg->cbMapped = (KSIZE)cb == cb ? (KSIZE)cb : KSIZE_MAX;
+
+        /* Set the image size. */
+        pModMachO->cbImage = pDstSeg->RVA + cb;
+
+        /* Fixup the section RVAs (internal). */
+        c        = cSegmentsToAdjust;
+        uNextRVA = pModMachO->cbImage;
+        pDstSeg  = &pModMachO->pMod->aSegments[0];
+        for (pSectExtraItr = pModMachO->paSections; pSectExtraItr != pSectExtra; pSectExtraItr++)
+        {
+            if (pSectExtraItr->iSegment < c)
+                pSectExtraItr->RVA += pDstSeg[pSectExtraItr->iSegment].RVA;
+            else
+            {
+                pSectExtraItr->RVA = uNextRVA;
+                uNextRVA += KLDR_ALIGN_ADDR(pSectExtraItr->cb, 64);
+            }
+        }
+    }
+
+    /*
+     * Make the GOT segment if necessary.
+     */
+    if (pModMachO->fMakeGot)
+    {
+        KSIZE cbPtr = (   pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
+                       || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
+                    ? sizeof(KU32)
+                    : sizeof(KU64);
+        KU32 cbGot = pModMachO->cSymbols * cbPtr;
+        KU32 cbJmpStubs;
+
+        pModMachO->GotRVA = pModMachO->cbImage;
+
+        if (pModMachO->cbJmpStub)
+        {
+            cbGot = K_ALIGN_Z(cbGot, 64);
+            pModMachO->JmpStubsRVA = pModMachO->GotRVA + cbGot;
+            cbJmpStubs = pModMachO->cbJmpStub * pModMachO->cSymbols;
+        }
+        else
+        {
+            pModMachO->JmpStubsRVA = NIL_KLDRADDR;
+            cbJmpStubs = 0;
+        }
+
+        pDstSeg = &pModMachO->pMod->aSegments[cSegments - 1];
+        pDstSeg->pvUser = NULL;
+        pDstSeg->pchName = "GOT";
+        pDstSeg->cchName = 3;
+        pDstSeg->SelFlat = 0;
+        pDstSeg->Sel16bit = 0;
+        pDstSeg->fFlags = 0;
+        pDstSeg->enmProt = KPROT_READONLY;
+        pDstSeg->cb = cbGot + cbJmpStubs;
+        pDstSeg->Alignment = 64;
+        pDstSeg->LinkAddress = pModMachO->LinkAddress + pModMachO->GotRVA;
+        pDstSeg->offFile = -1;
+        pDstSeg->cbFile  = -1;
+        pDstSeg->RVA = pModMachO->GotRVA;
+        pDstSeg->cbMapped = KLDR_ALIGN_ADDR(cbGot + cbJmpStubs, pDstSeg->Alignment);
+        pDstSeg->MapAddress = 0;
+
+        pSegExtra->iOrgSegNo = KU32_MAX;
+        pSegExtra->cSections = 0;
+        pSegExtra->paSections = NULL;
+
+        pModMachO->cbImage += pDstSeg->cbMapped;
+    }
+
+    return 0;
+}
+
+
+/** @copydoc KLDRMODOPS::pfnDestroy */
+static int kldrModMachODestroy(PKLDRMOD pMod)
+{
+    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
+    int rc = 0;
+    KU32 i, j;
+    KLDRMODMACHO_ASSERT(!pModMachO->pvMapping);
+
+    i = pMod->cSegments;
+    while (i-- > 0)
+    {
+        j = pModMachO->aSegments[i].cSections;
+        while (j-- > 0)
+        {
+            kHlpFree(pModMachO->aSegments[i].paSections[j].paFixups);
+            pModMachO->aSegments[i].paSections[j].paFixups = NULL;
+        }
+    }
+
+    if (pMod->pRdr)
+    {
+        rc = kRdrClose(pMod->pRdr);
+        pMod->pRdr = NULL;
+    }
+    pMod->u32Magic = 0;
+    pMod->pOps = NULL;
+    kHlpFree(pModMachO->pbLoadCommands);
+    pModMachO->pbLoadCommands = NULL;
+    kHlpFree(pModMachO->pchStrings);
+    pModMachO->pchStrings = NULL;
+    kHlpFree(pModMachO->pvaSymbols);
+    pModMachO->pvaSymbols = NULL;
+    kHlpFree(pModMachO);
+    return rc;
+}
+
+
+/**
+ * Gets the right base address.
+ *
+ * @returns 0 on success.
+ * @returns A non-zero status code if the BaseAddress isn't right.
+ * @param   pModMachO       The interpreter module instance
+ * @param   pBaseAddress    The base address, IN & OUT. Optional.
+ */
+static int kldrModMachOAdjustBaseAddress(PKLDRMODMACHO pModMachO, PKLDRADDR pBaseAddress)
+{
+    /*
+     * Adjust the base address.
+     */
+    if (*pBaseAddress == KLDRMOD_BASEADDRESS_MAP)
+        *pBaseAddress = pModMachO->pMod->aSegments[0].MapAddress;
+    else if (*pBaseAddress == KLDRMOD_BASEADDRESS_LINK)
+        *pBaseAddress = pModMachO->LinkAddress;
+
+    return 0;
+}
+
+
+/**
+ * Resolves a linker generated symbol.
+ *
+ * The Apple linker generates symbols indicating the start and end of sections
+ * and segments.  This function checks for these and returns the right value.
+ *
+ * @returns 0 or KLDR_ERR_SYMBOL_NOT_FOUND.
+ * @param   pModMachO           The interpreter module instance.
+ * @param   pMod                The generic module instance.
+ * @param   pchSymbol           The symbol.
+ * @param   cchSymbol           The length of the symbol.
+ * @param   BaseAddress         The base address to apply when calculating the
+ *                              value.
+ * @param   puValue             Where to return the symbol value.
+ */
+static int kldrModMachOQueryLinkerSymbol(PKLDRMODMACHO pModMachO, PKLDRMOD pMod, const char *pchSymbol, KSIZE cchSymbol,
+                                         KLDRADDR BaseAddress, PKLDRADDR puValue)
+{
+    /*
+     * Match possible name prefixes.
+     */
+    static const struct
+    {
+        const char *pszPrefix;
+        KU8         cchPrefix;
+        KBOOL       fSection;
+        KBOOL       fStart;
+    }   s_aPrefixes[] =
+    {
+        { "section$start$",  (KU8)sizeof("section$start$") - 1,   K_TRUE,  K_TRUE },
+        { "section$end$",    (KU8)sizeof("section$end$") - 1,     K_TRUE,  K_FALSE},
+        { "segment$start$",  (KU8)sizeof("segment$start$") - 1,   K_FALSE, K_TRUE },
+        { "segment$end$",    (KU8)sizeof("segment$end$") - 1,     K_FALSE, K_FALSE},
+    };
+    KSIZE       cchSectName = 0;
+    const char *pchSectName = "";
+    KSIZE       cchSegName  = 0;
+    const char *pchSegName  = NULL;
+    KU32        iPrefix     = K_ELEMENTS(s_aPrefixes) - 1;
+    KU32        iSeg;
+    KLDRADDR    uValue;
+
+    for (;;)
+    {
+        KU8 const cchPrefix = s_aPrefixes[iPrefix].cchPrefix;
+        if (   cchSymbol > cchPrefix
+            && kHlpStrNComp(pchSymbol, s_aPrefixes[iPrefix].pszPrefix, cchPrefix) == 0)
+        {
+            pchSegName = pchSymbol + cchPrefix;
+            cchSegName = cchSymbol - cchPrefix;
+            break;
+        }
+
+        /* next */
+        if (!iPrefix)
+            return KLDR_ERR_SYMBOL_NOT_FOUND;
+        iPrefix--;
+    }
+
+    /*
+     * Split the remainder into segment and section name, if necessary.
+     */
+    if (s_aPrefixes[iPrefix].fSection)
+    {
+        pchSectName = kHlpMemChr(pchSegName, '$', cchSegName);
+        if (!pchSectName)
+            return KLDR_ERR_SYMBOL_NOT_FOUND;
+        cchSegName  = pchSectName - pchSegName;
+        pchSectName++;
+        cchSectName = cchSymbol - (pchSectName - pchSymbol);
+    }
+
+    /*
+     * Locate the segment.
+     */
+    if (!pMod->cSegments)
+        return KLDR_ERR_SYMBOL_NOT_FOUND;
+    for (iSeg = 0; iSeg < pMod->cSegments; iSeg++)
+    {
+        if (   pMod->aSegments[iSeg].cchName >= cchSegName
+            && kHlpMemComp(pMod->aSegments[iSeg].pchName, pchSegName, cchSegName) == 0)
+        {
+            section_32_t const *pSect;
+            if (   pMod->aSegments[iSeg].cchName == cchSegName
+                && pModMachO->Hdr.filetype != MH_OBJECT /* Good enough for __DWARF segs in MH_DHSYM, I hope. */)
+                break;
+
+            pSect = (section_32_t *)pModMachO->aSegments[iSeg].paSections[0].pvMachoSection;
+            if (   pModMachO->uEffFileType == MH_OBJECT
+                && pMod->aSegments[iSeg].cchName > cchSegName + 1
+                && pMod->aSegments[iSeg].pchName[cchSegName] == '.'
+                && kHlpStrNComp(&pMod->aSegments[iSeg].pchName[cchSegName + 1], pSect->sectname, sizeof(pSect->sectname)) == 0
+                && pMod->aSegments[iSeg].cchName - cchSegName - 1 <= sizeof(pSect->sectname) )
+                break;
+        }
+    }
+    if (iSeg >= pMod->cSegments)
+        return KLDR_ERR_SYMBOL_NOT_FOUND;
+
+    if (!s_aPrefixes[iPrefix].fSection)
+    {
+        /*
+         * Calculate the segment start/end address.
+         */
+        uValue = pMod->aSegments[iSeg].RVA;
+        if (!s_aPrefixes[iPrefix].fStart)
+            uValue += pMod->aSegments[iSeg].cb;
+    }
+    else
+    {
+        /*
+         * Locate the section.
+         */
+        KU32 iSect = pModMachO->aSegments[iSeg].cSections;
+        if (!iSect)
+            return KLDR_ERR_SYMBOL_NOT_FOUND;
+        for (;;)
+        {
+            section_32_t *pSect = (section_32_t *)pModMachO->aSegments[iSeg].paSections[iSect].pvMachoSection;
+            if (   cchSectName <= sizeof(pSect->sectname)
+                && kHlpMemComp(pSect->sectname, pchSectName, cchSectName) == 0
+                && (   cchSectName == sizeof(pSect->sectname)
+                    || pSect->sectname[cchSectName] == '\0') )
+                break;
+            /* next */
+            if (!iSect)
+                return KLDR_ERR_SYMBOL_NOT_FOUND;
+            iSect--;
+        }
+
+        uValue = pModMachO->aSegments[iSeg].paSections[iSect].RVA;
+        if (!s_aPrefixes[iPrefix].fStart)
+            uValue += pModMachO->aSegments[iSeg].paSections[iSect].cb;
+    }
+
+    /*
+     * Convert from RVA to load address.
+     */
+    uValue += BaseAddress;
+    if (puValue)
+        *puValue = uValue;
+
+    return 0;
+}
+
+
+/** @copydoc kLdrModQuerySymbol */
+static int kldrModMachOQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 iSymbol,
+                                   const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion,
+                                   PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind)
+{
+    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
+    int rc;
+    K_NOREF(pvBits);
+    K_NOREF(pszVersion);
+    K_NOREF(pfnGetForwarder);
+    K_NOREF(pvUser);
+
+    /*
+     * Resolve defaults.
+     */
+    rc  = kldrModMachOAdjustBaseAddress(pModMachO, &BaseAddress);
+    if (rc)
+        return rc;
+
+    /*
+     * Refuse segmented requests for now.
+     */
+    KLDRMODMACHO_CHECK_RETURN(   !pfKind
+                              || (*pfKind & KLDRSYMKIND_REQ_TYPE_MASK) == KLDRSYMKIND_REQ_FLAT,
+                              KLDR_ERR_TODO);
+
+    /*
+     * Take action according to file type.
+     */
+    if (   pModMachO->Hdr.filetype == MH_OBJECT
+        || pModMachO->Hdr.filetype == MH_EXECUTE /** @todo dylib, execute, dsym: symbols */
+        || pModMachO->Hdr.filetype == MH_DYLIB
+        || pModMachO->Hdr.filetype == MH_BUNDLE
+        || pModMachO->Hdr.filetype == MH_DSYM
+        || pModMachO->Hdr.filetype == MH_KEXT_BUNDLE)
+    {
+        rc = kldrModMachOLoadObjSymTab(pModMachO);
+        if (!rc)
+        {
+            if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
+                ||  pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
+                rc = kldrModMachODoQuerySymbol32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols,
+                                                    pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, iSymbol, pchSymbol,
+                                                    cchSymbol, puValue, pfKind);
+            else
+                rc = kldrModMachODoQuerySymbol64Bit(pModMachO, (macho_nlist_64_t *)pModMachO->pvaSymbols, pModMachO->cSymbols,
+                                                    pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, iSymbol, pchSymbol,
+                                                    cchSymbol, puValue, pfKind);
+        }
+
+        /*
+         * Check for link-editor generated symbols and supply what we can.
+         *
+         * As small service to clients that insists on adding a '_' prefix
+         * before querying symbols, we will ignore the prefix.
+         */
+        if (  rc == KLDR_ERR_SYMBOL_NOT_FOUND
+            && cchSymbol > sizeof("section$end$") - 1
+            && (    pchSymbol[0] == 's'
+                || (pchSymbol[1] == 's' && pchSymbol[0] == '_') )
+            && kHlpMemChr(pchSymbol, '$', cchSymbol) )
+        {
+            if (pchSymbol[0] == '_')
+                rc = kldrModMachOQueryLinkerSymbol(pModMachO, pMod, pchSymbol + 1, cchSymbol - 1, BaseAddress, puValue);
+            else
+                rc = kldrModMachOQueryLinkerSymbol(pModMachO, pMod, pchSymbol, cchSymbol, BaseAddress, puValue);
+        }
+    }
+    else
+        rc = KLDR_ERR_TODO;
+
+    return rc;
+}
+
+
+/**
+ * Lookup a symbol in a 32-bit symbol table.
+ *
+ * @returns See kLdrModQuerySymbol.
+ * @param   pModMachO
+ * @param   paSyms      Pointer to the symbol table.
+ * @param   cSyms       Number of symbols in the table.
+ * @param   pchStrings  Pointer to the string table.
+ * @param   cchStrings  Size of the string table.
+ * @param   BaseAddress Adjusted base address, see kLdrModQuerySymbol.
+ * @param   iSymbol     See kLdrModQuerySymbol.
+ * @param   pchSymbol   See kLdrModQuerySymbol.
+ * @param   cchSymbol   See kLdrModQuerySymbol.
+ * @param   puValue     See kLdrModQuerySymbol.
+ * @param   pfKind      See kLdrModQuerySymbol.
+ */
+static int kldrModMachODoQuerySymbol32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, KU32 cSyms, const char *pchStrings,
+                                          KU32 cchStrings, KLDRADDR BaseAddress, KU32 iSymbol, const char *pchSymbol, KSIZE cchSymbol,
+                                          PKLDRADDR puValue, KU32 *pfKind)
+{
+    /*
+     * Find a valid symbol matching the search criteria.
+     */
+    if (iSymbol == NIL_KLDRMOD_SYM_ORDINAL)
+    {
+        /* simplify validation. */
+        if (cchStrings <= cchSymbol)
+            return KLDR_ERR_SYMBOL_NOT_FOUND;
+        cchStrings -= cchSymbol;
+
+        /* external symbols are usually at the end, so search the other way. */
+        for (iSymbol = cSyms - 1; iSymbol != KU32_MAX; iSymbol--)
+        {
+            const char *psz;
+
+            /* Skip irrellevant and non-public symbols. */
+            if (paSyms[iSymbol].n_type & MACHO_N_STAB)
+                continue;
+            if ((paSyms[iSymbol].n_type & MACHO_N_TYPE) == MACHO_N_UNDF)
+                continue;
+            if (!(paSyms[iSymbol].n_type & MACHO_N_EXT)) /*??*/
+                continue;
+            if (paSyms[iSymbol].n_type & MACHO_N_PEXT) /*??*/
+                continue;
+
+            /* get name */
+            if (!paSyms[iSymbol].n_un.n_strx)
+                continue;
+            if ((KU32)paSyms[iSymbol].n_un.n_strx >= cchStrings)
+                continue;
+            psz = &pchStrings[paSyms[iSymbol].n_un.n_strx];
+            if (psz[cchSymbol])
+                continue;
+            if (kHlpMemComp(psz, pchSymbol, cchSymbol))
+                continue;
+
+            /* match! */
+            break;
+        }
+        if (iSymbol == KU32_MAX)
+            return KLDR_ERR_SYMBOL_NOT_FOUND;
+    }
+    else
+    {
+        if (iSymbol >= cSyms)
+            return KLDR_ERR_SYMBOL_NOT_FOUND;
+        if (paSyms[iSymbol].n_type & MACHO_N_STAB)
+            return KLDR_ERR_SYMBOL_NOT_FOUND;
+        if ((paSyms[iSymbol].n_type & MACHO_N_TYPE) == MACHO_N_UNDF)
+            return KLDR_ERR_SYMBOL_NOT_FOUND;
+    }
+
+    /*
+     * Calc the return values.
+     */
+    if (pfKind)
+    {
+        if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
+            ||  pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
+            *pfKind = KLDRSYMKIND_32BIT | KLDRSYMKIND_NO_TYPE;
+        else
+            *pfKind = KLDRSYMKIND_64BIT | KLDRSYMKIND_NO_TYPE;
+        if (paSyms[iSymbol].n_desc & N_WEAK_DEF)
+            *pfKind |= KLDRSYMKIND_WEAK;
+    }
+
+    switch (paSyms[iSymbol].n_type & MACHO_N_TYPE)
+    {
+        case MACHO_N_SECT:
+        {
+            PKLDRMODMACHOSECT pSect;
+            KLDRADDR offSect;
+            KLDRMODMACHO_CHECK_RETURN((KU32)(paSyms[iSymbol].n_sect - 1) < pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL);
+            pSect = &pModMachO->paSections[paSyms[iSymbol].n_sect - 1];
+
+            offSect = paSyms[iSymbol].n_value - pSect->LinkAddress;
+            KLDRMODMACHO_CHECK_RETURN(   offSect <= pSect->cb
+                                      || (   paSyms[iSymbol].n_sect == 1 /* special hack for __mh_execute_header */
+                                          && offSect == 0U - pSect->RVA
+                                          && pModMachO->uEffFileType != MH_OBJECT),
+                                      KLDR_ERR_MACHO_BAD_SYMBOL);
+            if (puValue)
+                *puValue = BaseAddress + pSect->RVA + offSect;
+
+            if (    pfKind
+                &&  (pSect->fFlags & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SELF_MODIFYING_CODE)))
+                *pfKind = (*pfKind & ~KLDRSYMKIND_TYPE_MASK) | KLDRSYMKIND_CODE;
+            break;
+        }
+
+        case MACHO_N_ABS:
+            if (puValue)
+                *puValue = paSyms[iSymbol].n_value;
+            /*if (pfKind)
+                pfKind |= KLDRSYMKIND_ABS;*/
+            break;
+
+        case MACHO_N_PBUD:
+        case MACHO_N_INDR:
+            /** @todo implement indirect and prebound symbols. */
+        default:
+            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+    }
+
+    return 0;
+}
+
+
+/**
+ * Lookup a symbol in a 64-bit symbol table.
+ *
+ * @returns See kLdrModQuerySymbol.
+ * @param   pModMachO
+ * @param   paSyms      Pointer to the symbol table.
+ * @param   cSyms       Number of symbols in the table.
+ * @param   pchStrings  Pointer to the string table.
+ * @param   cchStrings  Size of the string table.
+ * @param   BaseAddress Adjusted base address, see kLdrModQuerySymbol.
+ * @param   iSymbol     See kLdrModQuerySymbol.
+ * @param   pchSymbol   See kLdrModQuerySymbol.
+ * @param   cchSymbol   See kLdrModQuerySymbol.
+ * @param   puValue     See kLdrModQuerySymbol.
+ * @param   pfKind      See kLdrModQuerySymbol.
+ */
+static int kldrModMachODoQuerySymbol64Bit(PKLDRMODMACHO pModMachO, const macho_nlist_64_t *paSyms, KU32 cSyms, const char *pchStrings,
+                                          KU32 cchStrings, KLDRADDR BaseAddress, KU32 iSymbol, const char *pchSymbol, KSIZE cchSymbol,
+                                          PKLDRADDR puValue, KU32 *pfKind)
+{
+    /*
+     * Find a valid symbol matching the search criteria.
+     */
+    if (iSymbol == NIL_KLDRMOD_SYM_ORDINAL)
+    {
+        /* simplify validation. */
+        if (cchStrings <= cchSymbol)
+            return KLDR_ERR_SYMBOL_NOT_FOUND;
+        cchStrings -= cchSymbol;
+
+        /* external symbols are usually at the end, so search the other way. */
+        for (iSymbol = cSyms - 1; iSymbol != KU32_MAX; iSymbol--)
+        {
+            const char *psz;
+
+            /* Skip irrellevant and non-public symbols. */
+            if (paSyms[iSymbol].n_type & MACHO_N_STAB)
+                continue;
+            if ((paSyms[iSymbol].n_type & MACHO_N_TYPE) == MACHO_N_UNDF)
+                continue;
+            if (!(paSyms[iSymbol].n_type & MACHO_N_EXT)) /*??*/
+                continue;
+            if (paSyms[iSymbol].n_type & MACHO_N_PEXT) /*??*/
+                continue;
+
+            /* get name */
+            if (!paSyms[iSymbol].n_un.n_strx)
+                continue;
+            if ((KU32)paSyms[iSymbol].n_un.n_strx >= cchStrings)
+                continue;
+            psz = &pchStrings[paSyms[iSymbol].n_un.n_strx];
+            if (psz[cchSymbol])
+                continue;
+            if (kHlpMemComp(psz, pchSymbol, cchSymbol))
+                continue;
+
+            /* match! */
+            break;
+        }
+        if (iSymbol == KU32_MAX)
+            return KLDR_ERR_SYMBOL_NOT_FOUND;
+    }
+    else
+    {
+        if (iSymbol >= cSyms)
+            return KLDR_ERR_SYMBOL_NOT_FOUND;
+        if (paSyms[iSymbol].n_type & MACHO_N_STAB)
+            return KLDR_ERR_SYMBOL_NOT_FOUND;
+        if ((paSyms[iSymbol].n_type & MACHO_N_TYPE) == MACHO_N_UNDF)
+            return KLDR_ERR_SYMBOL_NOT_FOUND;
+    }
+
+    /*
+     * Calc the return values.
+     */
+    if (pfKind)
+    {
+        if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
+            ||  pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
+            *pfKind = KLDRSYMKIND_32BIT | KLDRSYMKIND_NO_TYPE;
+        else
+            *pfKind = KLDRSYMKIND_64BIT | KLDRSYMKIND_NO_TYPE;
+        if (paSyms[iSymbol].n_desc & N_WEAK_DEF)
+            *pfKind |= KLDRSYMKIND_WEAK;
+    }
+
+    switch (paSyms[iSymbol].n_type & MACHO_N_TYPE)
+    {
+        case MACHO_N_SECT:
+        {
+            PKLDRMODMACHOSECT pSect;
+            KLDRADDR offSect;
+            KLDRMODMACHO_CHECK_RETURN((KU32)(paSyms[iSymbol].n_sect - 1) < pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL);
+            pSect = &pModMachO->paSections[paSyms[iSymbol].n_sect - 1];
+
+            offSect = paSyms[iSymbol].n_value - pSect->LinkAddress;
+            KLDRMODMACHO_CHECK_RETURN(   offSect <= pSect->cb
+                                      || (   paSyms[iSymbol].n_sect == 1 /* special hack for __mh_execute_header */
+                                          && offSect == 0U - pSect->RVA
+                                          && pModMachO->uEffFileType != MH_OBJECT),
+                                      KLDR_ERR_MACHO_BAD_SYMBOL);
+            if (puValue)
+                *puValue = BaseAddress + pSect->RVA + offSect;
+
+            if (    pfKind
+                &&  (pSect->fFlags & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SELF_MODIFYING_CODE)))
+                *pfKind = (*pfKind & ~KLDRSYMKIND_TYPE_MASK) | KLDRSYMKIND_CODE;
+            break;
+        }
+
+        case MACHO_N_ABS:
+            if (puValue)
+                *puValue = paSyms[iSymbol].n_value;
+            /*if (pfKind)
+                pfKind |= KLDRSYMKIND_ABS;*/
+            break;
+
+        case MACHO_N_PBUD:
+        case MACHO_N_INDR:
+            /** @todo implement indirect and prebound symbols. */
+        default:
+            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+    }
+
+    return 0;
+}
+
+
+/** @copydoc kLdrModEnumSymbols */
+static int kldrModMachOEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress,
+                                   KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
+{
+    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
+    int rc;
+    K_NOREF(pvBits);
+
+    /*
+     * Resolve defaults.
+     */
+    rc  = kldrModMachOAdjustBaseAddress(pModMachO, &BaseAddress);
+    if (rc)
+        return rc;
+
+    /*
+     * Take action according to file type.
+     */
+    if (   pModMachO->Hdr.filetype == MH_OBJECT
+        || pModMachO->Hdr.filetype == MH_EXECUTE /** @todo dylib, execute, dsym: symbols */
+        || pModMachO->Hdr.filetype == MH_DYLIB
+        || pModMachO->Hdr.filetype == MH_BUNDLE
+        || pModMachO->Hdr.filetype == MH_DSYM
+        || pModMachO->Hdr.filetype == MH_KEXT_BUNDLE)
+    {
+        rc = kldrModMachOLoadObjSymTab(pModMachO);
+        if (!rc)
+        {
+            if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
+                ||  pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
+                rc = kldrModMachODoEnumSymbols32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols,
+                                                    pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress,
+                                                    fFlags, pfnCallback, pvUser);
+            else
+                rc = kldrModMachODoEnumSymbols64Bit(pModMachO, (macho_nlist_64_t *)pModMachO->pvaSymbols, pModMachO->cSymbols,
+                                                    pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress,
+                                                    fFlags, pfnCallback, pvUser);
+        }
+    }
+    else
+        KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+
+    return rc;
+}
+
+
+/**
+ * Enum a 32-bit symbol table.
+ *
+ * @returns See kLdrModQuerySymbol.
+ * @param   pModMachO
+ * @param   paSyms      Pointer to the symbol table.
+ * @param   cSyms       Number of symbols in the table.
+ * @param   pchStrings  Pointer to the string table.
+ * @param   cchStrings  Size of the string table.
+ * @param   BaseAddress Adjusted base address, see kLdrModEnumSymbols.
+ * @param   fFlags      See kLdrModEnumSymbols.
+ * @param   pfnCallback See kLdrModEnumSymbols.
+ * @param   pvUser      See kLdrModEnumSymbols.
+ */
+static int kldrModMachODoEnumSymbols32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, KU32 cSyms,
+                                          const char *pchStrings, KU32 cchStrings, KLDRADDR BaseAddress,
+                                          KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
+{
+    const KU32 fKindBase =    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
+                           || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE
+                         ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT;
+    KU32 iSym;
+    int rc;
+
+    /*
+     * Iterate the symbol table.
+     */
+    for (iSym = 0; iSym < cSyms; iSym++)
+    {
+        KU32 fKind;
+        KLDRADDR uValue;
+        const char *psz;
+        KSIZE cch;
+
+        /* Skip debug symbols and undefined symbols. */
+        if (paSyms[iSym].n_type & MACHO_N_STAB)
+            continue;
+        if ((paSyms[iSym].n_type & MACHO_N_TYPE) == MACHO_N_UNDF)
+            continue;
+
+        /* Skip non-public symbols unless they are requested explicitly. */
+        if (!(fFlags & KLDRMOD_ENUM_SYMS_FLAGS_ALL))
+        {
+            if (!(paSyms[iSym].n_type & MACHO_N_EXT)) /*??*/
+                continue;
+            if (paSyms[iSym].n_type & MACHO_N_PEXT) /*??*/
+                continue;
+            if (!paSyms[iSym].n_un.n_strx)
+                continue;
+        }
+
+        /*
+         * Gather symbol info
+         */
+
+        /* name */
+        KLDRMODMACHO_CHECK_RETURN((KU32)paSyms[iSym].n_un.n_strx < cchStrings, KLDR_ERR_MACHO_BAD_SYMBOL);
+        psz = &pchStrings[paSyms[iSym].n_un.n_strx];
+        cch = kHlpStrLen(psz);
+        if (!cch)
+            psz = NULL;
+
+        /* kind & value */
+        fKind = fKindBase;
+        if (paSyms[iSym].n_desc & N_WEAK_DEF)
+            fKind |= KLDRSYMKIND_WEAK;
+        switch (paSyms[iSym].n_type & MACHO_N_TYPE)
+        {
+            case MACHO_N_SECT:
+            {
+                PKLDRMODMACHOSECT pSect;
+                KLDRMODMACHO_CHECK_RETURN((KU32)(paSyms[iSym].n_sect - 1) < pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL);
+                pSect = &pModMachO->paSections[paSyms[iSym].n_sect - 1];
+
+                uValue = paSyms[iSym].n_value - pSect->LinkAddress;
+                KLDRMODMACHO_CHECK_RETURN(   uValue <= pSect->cb
+                                          || (   paSyms[iSym].n_sect == 1 /* special hack for __mh_execute_header */
+                                              && uValue == 0U - pSect->RVA
+                                              && pModMachO->uEffFileType != MH_OBJECT),
+                                          KLDR_ERR_MACHO_BAD_SYMBOL);
+                uValue += BaseAddress + pSect->RVA;
+
+                if (pSect->fFlags & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SELF_MODIFYING_CODE))
+                    fKind |= KLDRSYMKIND_CODE;
+                else
+                    fKind |= KLDRSYMKIND_NO_TYPE;
+                break;
+            }
+
+            case MACHO_N_ABS:
+                uValue = paSyms[iSym].n_value;
+                fKind |= KLDRSYMKIND_NO_TYPE /*KLDRSYMKIND_ABS*/;
+                break;
+
+            case MACHO_N_PBUD:
+            case MACHO_N_INDR:
+                /** @todo implement indirect and prebound symbols. */
+            default:
+                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+        }
+
+        /*
+         * Do callback.
+         */
+        rc = pfnCallback(pModMachO->pMod, iSym, psz, cch, NULL, uValue, fKind, pvUser);
+        if (rc)
+            return rc;
+    }
+    return 0;
+}
+
+
+/**
+ * Enum a 64-bit symbol table.
+ *
+ * @returns See kLdrModQuerySymbol.
+ * @param   pModMachO
+ * @param   paSyms      Pointer to the symbol table.
+ * @param   cSyms       Number of symbols in the table.
+ * @param   pchStrings  Pointer to the string table.
+ * @param   cchStrings  Size of the string table.
+ * @param   BaseAddress Adjusted base address, see kLdrModEnumSymbols.
+ * @param   fFlags      See kLdrModEnumSymbols.
+ * @param   pfnCallback See kLdrModEnumSymbols.
+ * @param   pvUser      See kLdrModEnumSymbols.
+ */
+static int kldrModMachODoEnumSymbols64Bit(PKLDRMODMACHO pModMachO, const macho_nlist_64_t *paSyms, KU32 cSyms,
+                                          const char *pchStrings, KU32 cchStrings, KLDRADDR BaseAddress,
+                                          KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
+{
+    const KU32 fKindBase =    pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE
+                           || pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE
+                         ? KLDRSYMKIND_64BIT : KLDRSYMKIND_32BIT;
+    KU32 iSym;
+    int rc;
+
+    /*
+     * Iterate the symbol table.
+     */
+    for (iSym = 0; iSym < cSyms; iSym++)
+    {
+        KU32 fKind;
+        KLDRADDR uValue;
+        const char *psz;
+        KSIZE cch;
+
+        /* Skip debug symbols and undefined symbols. */
+        if (paSyms[iSym].n_type & MACHO_N_STAB)
+            continue;
+        if ((paSyms[iSym].n_type & MACHO_N_TYPE) == MACHO_N_UNDF)
+            continue;
+
+        /* Skip non-public symbols unless they are requested explicitly. */
+        if (!(fFlags & KLDRMOD_ENUM_SYMS_FLAGS_ALL))
+        {
+            if (!(paSyms[iSym].n_type & MACHO_N_EXT)) /*??*/
+                continue;
+            if (paSyms[iSym].n_type & MACHO_N_PEXT) /*??*/
+                continue;
+            if (!paSyms[iSym].n_un.n_strx)
+                continue;
+        }
+
+        /*
+         * Gather symbol info
+         */
+
+        /* name */
+        KLDRMODMACHO_CHECK_RETURN((KU32)paSyms[iSym].n_un.n_strx < cchStrings, KLDR_ERR_MACHO_BAD_SYMBOL);
+        psz = &pchStrings[paSyms[iSym].n_un.n_strx];
+        cch = kHlpStrLen(psz);
+        if (!cch)
+            psz = NULL;
+
+        /* kind & value */
+        fKind = fKindBase;
+        if (paSyms[iSym].n_desc & N_WEAK_DEF)
+            fKind |= KLDRSYMKIND_WEAK;
+        switch (paSyms[iSym].n_type & MACHO_N_TYPE)
+        {
+            case MACHO_N_SECT:
+            {
+                PKLDRMODMACHOSECT pSect;
+                KLDRMODMACHO_CHECK_RETURN((KU32)(paSyms[iSym].n_sect - 1) < pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL);
+                pSect = &pModMachO->paSections[paSyms[iSym].n_sect - 1];
+
+                uValue = paSyms[iSym].n_value - pSect->LinkAddress;
+                KLDRMODMACHO_CHECK_RETURN(   uValue <= pSect->cb
+                                          || (   paSyms[iSym].n_sect == 1 /* special hack for __mh_execute_header */
+                                              && uValue == 0U - pSect->RVA
+                                              && pModMachO->uEffFileType != MH_OBJECT),
+                                          KLDR_ERR_MACHO_BAD_SYMBOL);
+                uValue += BaseAddress + pSect->RVA;
+
+                if (pSect->fFlags & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SELF_MODIFYING_CODE))
+                    fKind |= KLDRSYMKIND_CODE;
+                else
+                    fKind |= KLDRSYMKIND_NO_TYPE;
+                break;
+            }
+
+            case MACHO_N_ABS:
+                uValue = paSyms[iSym].n_value;
+                fKind |= KLDRSYMKIND_NO_TYPE /*KLDRSYMKIND_ABS*/;
+                break;
+
+            case MACHO_N_PBUD:
+            case MACHO_N_INDR:
+                /** @todo implement indirect and prebound symbols. */
+            default:
+                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+        }
+
+        /*
+         * Do callback.
+         */
+        rc = pfnCallback(pModMachO->pMod, iSym, psz, cch, NULL, uValue, fKind, pvUser);
+        if (rc)
+            return rc;
+    }
+    return 0;
+}
+
+
+/** @copydoc kLdrModGetImport */
+static int kldrModMachOGetImport(PKLDRMOD pMod, const void *pvBits, KU32 iImport, char *pszName, KSIZE cchName)
+{
+    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
+    K_NOREF(pvBits);
+    K_NOREF(iImport);
+    K_NOREF(pszName);
+    K_NOREF(cchName);
+
+    if (pModMachO->Hdr.filetype == MH_OBJECT)
+        return KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS;
+
+    /* later */
+    return KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS;
+}
+
+
+/** @copydoc kLdrModNumberOfImports */
+static KI32 kldrModMachONumberOfImports(PKLDRMOD pMod, const void *pvBits)
+{
+    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
+    K_NOREF(pvBits);
+
+    if (pModMachO->Hdr.filetype == MH_OBJECT)
+        return 0;
+
+    /* later */
+    return 0;
+}
+
+
+/** @copydoc kLdrModGetStackInfo */
+static int kldrModMachOGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo)
+{
+    /*PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;*/
+    K_NOREF(pMod);
+    K_NOREF(pvBits);
+    K_NOREF(BaseAddress);
+
+    pStackInfo->Address = NIL_KLDRADDR;
+    pStackInfo->LinkAddress = NIL_KLDRADDR;
+    pStackInfo->cbStack = pStackInfo->cbStackThread = 0;
+    /* later */
+
+    return 0;
+}
+
+
+/** @copydoc kLdrModQueryMainEntrypoint */
+static int kldrModMachOQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress)
+{
+#if 0
+    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
+    int rc;
+
+    /*
+     * Resolve base address alias if any.
+     */
+    rc = kldrModMachOBitsAndBaseAddress(pModMachO, NULL, &BaseAddress);
+    if (rc)
+        return rc;
+
+    /*
+     * Convert the address from the header.
+     */
+    *pMainEPAddress = pModMachO->Hdrs.OptionalHeader.AddressOfEntryPoint
+        ? BaseAddress + pModMachO->Hdrs.OptionalHeader.AddressOfEntryPoint
+        : NIL_KLDRADDR;
+#else
+    *pMainEPAddress = NIL_KLDRADDR;
+    K_NOREF(pvBits);
+    K_NOREF(BaseAddress);
+    K_NOREF(pMod);
+#endif
+    return 0;
+}
+
+
+/** @copydoc kLdrModQueryImageUuid */
+static int kldrModMachOQueryImageUuid(PKLDRMOD pMod, const void *pvBits, void *pvUuid, KSIZE cbUuid)
+{
+    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
+    K_NOREF(pvBits);
+
+    kHlpMemSet(pvUuid, 0, cbUuid);
+    if (kHlpMemComp(pvUuid, pModMachO->abImageUuid, sizeof(pModMachO->abImageUuid)) == 0)
+        return KLDR_ERR_NO_IMAGE_UUID;
+
+    kHlpMemCopy(pvUuid, pModMachO->abImageUuid, sizeof(pModMachO->abImageUuid));
+    return 0;
+}
+
+
+/** @copydoc kLdrModEnumDbgInfo */
+static int kldrModMachOEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser)
+{
+    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
+    int rc = 0;
+    KU32 iSect;
+    K_NOREF(pvBits);
+
+    for (iSect = 0; iSect < pModMachO->cSections; iSect++)
+    {
+        section_32_t *pMachOSect = pModMachO->paSections[iSect].pvMachoSection; /* (32-bit & 64-bit starts the same way) */
+        char          szTmp[sizeof(pMachOSect->sectname) + 1];
+
+        if (kHlpStrComp(pMachOSect->segname, "__DWARF"))
+            continue;
+
+        kHlpMemCopy(szTmp, pMachOSect->sectname, sizeof(pMachOSect->sectname));
+        szTmp[sizeof(pMachOSect->sectname)] = '\0';
+
+        rc = pfnCallback(pMod, iSect, KLDRDBGINFOTYPE_DWARF, 0, 0, szTmp,
+                         pModMachO->paSections[iSect].offFile,
+                         pModMachO->paSections[iSect].LinkAddress,
+                         pModMachO->paSections[iSect].cb,
+                         NULL, pvUser);
+        if (rc != 0)
+            break;
+    }
+
+    return rc;
+}
+
+
+/** @copydoc kLdrModHasDbgInfo */
+static int kldrModMachOHasDbgInfo(PKLDRMOD pMod, const void *pvBits)
+{
+    /*PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;*/
+
+#if 0
+    /*
+     * Base this entirely on the presence of a debug directory.
+     */
+    if (    pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size
+            < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */
+        ||  !pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)
+        return KLDR_ERR_NO_DEBUG_INFO;
+    return 0;
+#else
+    K_NOREF(pMod);
+    K_NOREF(pvBits);
+    return KLDR_ERR_NO_DEBUG_INFO;
+#endif
+}
+
+
+/** @copydoc kLdrModMap */
+static int kldrModMachOMap(PKLDRMOD pMod)
+{
+    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
+    unsigned fFixed;
+    KU32 i;
+    void *pvBase;
+    int rc;
+
+    if (!pModMachO->fCanLoad)
+        return KLDR_ERR_TODO;
+
+    /*
+     * Already mapped?
+     */
+    if (pModMachO->pvMapping)
+        return KLDR_ERR_ALREADY_MAPPED;
+
+    /*
+     * Map it.
+     */
+    /* fixed image? */
+    fFixed = pMod->enmType == KLDRTYPE_EXECUTABLE_FIXED
+          || pMod->enmType == KLDRTYPE_SHARED_LIBRARY_FIXED;
+    if (!fFixed)
+        pvBase = NULL;
+    else
+    {
+        pvBase = (void *)(KUPTR)pMod->aSegments[0].LinkAddress;
+        if ((KUPTR)pvBase != pMod->aSegments[0].LinkAddress)
+            return KLDR_ERR_ADDRESS_OVERFLOW;
+    }
+
+    /* try do the prepare */
+    rc = kRdrMap(pMod->pRdr, &pvBase, pMod->cSegments, pMod->aSegments, fFixed);
+    if (rc)
+        return rc;
+
+    /*
+     * Update the segments with their map addresses.
+     */
+    for (i = 0; i < pMod->cSegments; i++)
+    {
+        if (pMod->aSegments[i].RVA != NIL_KLDRADDR)
+            pMod->aSegments[i].MapAddress = (KUPTR)pvBase + (KUPTR)pMod->aSegments[i].RVA;
+    }
+    pModMachO->pvMapping = pvBase;
+
+    return 0;
+}
+
+
+/** @copydoc kLdrModUnmap */
+static int kldrModMachOUnmap(PKLDRMOD pMod)
+{
+    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
+    KU32 i;
+    int rc;
+
+    /*
+     * Mapped?
+     */
+    if (!pModMachO->pvMapping)
+        return KLDR_ERR_NOT_MAPPED;
+
+    /*
+     * Try unmap the image.
+     */
+    rc = kRdrUnmap(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments);
+    if (rc)
+        return rc;
+
+    /*
+     * Update the segments to reflect that they aren't mapped any longer.
+     */
+    pModMachO->pvMapping = NULL;
+    for (i = 0; i < pMod->cSegments; i++)
+        pMod->aSegments[i].MapAddress = 0;
+
+    return 0;
+}
+
+
+/** @copydoc kLdrModAllocTLS */
+static int kldrModMachOAllocTLS(PKLDRMOD pMod, void *pvMapping)
+{
+    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
+
+    /*
+     * Mapped?
+     */
+    if (   pvMapping == KLDRMOD_INT_MAP
+        && !pModMachO->pvMapping )
+        return KLDR_ERR_NOT_MAPPED;
+    return 0;
+}
+
+
+/** @copydoc kLdrModFreeTLS */
+static void kldrModMachOFreeTLS(PKLDRMOD pMod, void *pvMapping)
+{
+    K_NOREF(pMod);
+    K_NOREF(pvMapping);
+}
+
+
+/** @copydoc kLdrModReload */
+static int kldrModMachOReload(PKLDRMOD pMod)
+{
+    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
+
+    /*
+     * Mapped?
+     */
+    if (!pModMachO->pvMapping)
+        return KLDR_ERR_NOT_MAPPED;
+
+    /* the file provider does it all */
+    return kRdrRefresh(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments);
+}
+
+
+/** @copydoc kLdrModFixupMapping */
+static int kldrModMachOFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
+    int rc, rc2;
+
+    /*
+     * Mapped?
+     */
+    if (!pModMachO->pvMapping)
+        return KLDR_ERR_NOT_MAPPED;
+
+    /*
+     * Before doing anything we'll have to make all pages writable.
+     */
+    rc = kRdrProtect(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 1 /* unprotect */);
+    if (rc)
+        return rc;
+
+    /*
+     * Resolve imports and apply base relocations.
+     */
+    rc = kldrModMachORelocateBits(pMod, pModMachO->pvMapping, (KUPTR)pModMachO->pvMapping, pModMachO->LinkAddress,
+                                  pfnGetImport, pvUser);
+
+    /*
+     * Restore protection.
+     */
+    rc2 = kRdrProtect(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 0 /* protect */);
+    if (!rc && rc2)
+        rc = rc2;
+    return rc;
+}
+
+
+/**
+ * MH_OBJECT: Resolves undefined symbols (imports).
+ *
+ * @returns 0 on success, non-zero kLdr status code on failure.
+ * @param   pModMachO       The Mach-O module interpreter instance.
+ * @param   pfnGetImport    The callback for resolving an imported symbol.
+ * @param   pvUser          User argument to the callback.
+ */
+static int  kldrModMachOObjDoImports(PKLDRMODMACHO pModMachO, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    const KU32 cSyms = pModMachO->cSymbols;
+    KU32 iSym;
+    int rc;
+
+    /*
+     * Ensure that we've got the symbol table and section fixups handy.
+     */
+    rc = kldrModMachOLoadObjSymTab(pModMachO);
+    if (rc)
+        return rc;
+
+    /*
+     * Iterate the symbol table and resolve undefined symbols.
+     * We currently ignore REFERENCE_TYPE.
+     */
+    if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
+        ||  pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
+    {
+        macho_nlist_32_t *paSyms = (macho_nlist_32_t *)pModMachO->pvaSymbols;
+        for (iSym = 0; iSym < cSyms; iSym++)
+        {
+            /* skip stabs */
+            if (paSyms[iSym].n_type & MACHO_N_STAB)
+                continue;
+
+            if ((paSyms[iSym].n_type & MACHO_N_TYPE) == MACHO_N_UNDF)
+            {
+                const char *pszSymbol;
+                KSIZE cchSymbol;
+                KU32 fKind = KLDRSYMKIND_REQ_FLAT;
+                KLDRADDR Value = NIL_KLDRADDR;
+
+                /** @todo Implement N_REF_TO_WEAK. */
+                KLDRMODMACHO_CHECK_RETURN(!(paSyms[iSym].n_desc & N_REF_TO_WEAK), KLDR_ERR_TODO);
+
+                /* Get the symbol name. */
+                KLDRMODMACHO_CHECK_RETURN((KU32)paSyms[iSym].n_un.n_strx < pModMachO->cchStrings, KLDR_ERR_MACHO_BAD_SYMBOL);
+                pszSymbol = &pModMachO->pchStrings[paSyms[iSym].n_un.n_strx];
+                cchSymbol = kHlpStrLen(pszSymbol);
+
+                /* Check for linker defined symbols relating to sections and segments. */
+                if (   cchSymbol > sizeof("section$end$") - 1
+                    && *pszSymbol == 's'
+                    && kHlpMemChr(pszSymbol, '$', cchSymbol))
+                    rc = kldrModMachOQueryLinkerSymbol(pModMachO, pModMachO->pMod, pszSymbol, cchSymbol, BaseAddress, &Value);
+                else
+                    rc = KLDR_ERR_SYMBOL_NOT_FOUND;
+
+                /* Ask the user for an address to the symbol. */
+                if (rc)
+                    rc = pfnGetImport(pModMachO->pMod, NIL_KLDRMOD_IMPORT, iSym, pszSymbol, cchSymbol, NULL,
+                                      &Value, &fKind, pvUser);
+                if (rc)
+                {
+                    /* weak reference? */
+                    if (!(paSyms[iSym].n_desc & N_WEAK_REF))
+                        break;
+                    Value = 0;
+                }
+
+                /* Update the symbol. */
+                paSyms[iSym].n_value = (KU32)Value;
+                if (paSyms[iSym].n_value != Value)
+                {
+                    rc = KLDR_ERR_ADDRESS_OVERFLOW;
+                    break;
+                }
+            }
+            else if (paSyms[iSym].n_desc & N_WEAK_DEF)
+            {
+                /** @todo implement weak symbols. */
+                /*return KLDR_ERR_TODO; - ignored for now. */
+            }
+        }
+    }
+    else
+    {
+        /* (Identical to the 32-bit code, just different paSym type. (and n_strx is unsigned)) */
+        macho_nlist_64_t *paSyms = (macho_nlist_64_t *)pModMachO->pvaSymbols;
+        for (iSym = 0; iSym < cSyms; iSym++)
+        {
+            /* skip stabs */
+            if (paSyms[iSym].n_type & MACHO_N_STAB)
+                continue;
+
+            if ((paSyms[iSym].n_type & MACHO_N_TYPE) == MACHO_N_UNDF)
+            {
+                const char *pszSymbol;
+                KSIZE cchSymbol;
+                KU32 fKind = KLDRSYMKIND_REQ_FLAT;
+                KLDRADDR Value = NIL_KLDRADDR;
+
+                /** @todo Implement N_REF_TO_WEAK. */
+                KLDRMODMACHO_CHECK_RETURN(!(paSyms[iSym].n_desc & N_REF_TO_WEAK), KLDR_ERR_TODO);
+
+                 /* Get the symbol name. */
+                KLDRMODMACHO_CHECK_RETURN(paSyms[iSym].n_un.n_strx < pModMachO->cchStrings, KLDR_ERR_MACHO_BAD_SYMBOL);
+                pszSymbol = &pModMachO->pchStrings[paSyms[iSym].n_un.n_strx];
+                cchSymbol = kHlpStrLen(pszSymbol);
+
+                /* Check for linker defined symbols relating to sections and segments. */
+                if (   cchSymbol > sizeof("section$end$") - 1
+                    && *pszSymbol == 's'
+                    && kHlpMemChr(pszSymbol, '$', cchSymbol))
+                    rc = kldrModMachOQueryLinkerSymbol(pModMachO, pModMachO->pMod, pszSymbol, cchSymbol, BaseAddress, &Value);
+                else
+                    rc = KLDR_ERR_SYMBOL_NOT_FOUND;
+
+                /* Ask the user for an address to the symbol. */
+                if (rc)
+                    rc = pfnGetImport(pModMachO->pMod, NIL_KLDRMOD_IMPORT, iSym, pszSymbol, cchSymbol, NULL,
+                                      &Value, &fKind, pvUser);
+                if (rc)
+                {
+                    /* weak reference? */
+                    if (!(paSyms[iSym].n_desc & N_WEAK_REF))
+                        break;
+                    Value = 0;
+                }
+
+                /* Update the symbol. */
+                paSyms[iSym].n_value = Value;
+                if (paSyms[iSym].n_value != Value)
+                {
+                    rc = KLDR_ERR_ADDRESS_OVERFLOW;
+                    break;
+                }
+            }
+            else if (paSyms[iSym].n_desc & N_WEAK_DEF)
+            {
+                /** @todo implement weak symbols. */
+                /*return KLDR_ERR_TODO; - ignored for now. */
+            }
+        }
+    }
+
+    return rc;
+}
+
+
+/**
+ * MH_OBJECT: Applies base relocations to a (unprotected) image mapping.
+ *
+ * @returns 0 on success, non-zero kLdr status code on failure.
+ * @param   pModMachO       The Mach-O module interpreter instance.
+ * @param   pvMapping       The mapping to fixup.
+ * @param   NewBaseAddress  The address to fixup the mapping to.
+ * @param   OldBaseAddress  The address the mapping is currently fixed up to.
+ */
+static int  kldrModMachOObjDoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress)
+{
+    KU32 iSeg;
+    int rc;
+
+
+    /*
+     * Ensure that we've got the symbol table and section fixups handy.
+     */
+    rc = kldrModMachOLoadObjSymTab(pModMachO);
+    if (rc)
+        return rc;
+
+    /*
+     * Iterate over the segments and their sections and apply fixups.
+     */
+    for (iSeg = rc = 0; !rc && iSeg < pModMachO->pMod->cSegments; iSeg++)
+    {
+        PKLDRMODMACHOSEG pSeg = &pModMachO->aSegments[iSeg];
+        KU32 iSect;
+
+        for (iSect = 0; iSect < pSeg->cSections; iSect++)
+        {
+            PKLDRMODMACHOSECT pSect = &pSeg->paSections[iSect];
+            KU8 *pbSectBits;
+
+            /* skip sections without fixups. */
+            if (!pSect->cFixups)
+                continue;
+
+            /* lazy load (and endian convert) the fixups. */
+            if (!pSect->paFixups)
+            {
+                rc = kldrModMachOLoadFixups(pModMachO, pSect->offFixups, pSect->cFixups, &pSect->paFixups);
+                if (rc)
+                    break;
+            }
+
+            /*
+             * Apply the fixups.
+             */
+            pbSectBits = (KU8 *)pvMapping + (KUPTR)pSect->RVA;
+            if (pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE) /** @todo this aint right. */
+                rc = kldrModMachOFixupSectionGeneric32Bit(pModMachO, pbSectBits, pSect,
+                                                          (macho_nlist_32_t *)pModMachO->pvaSymbols,
+                                                          pModMachO->cSymbols, NewBaseAddress);
+            else if (   pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE
+                     && pModMachO->Hdr.cputype == CPU_TYPE_X86_64)
+                rc = kldrModMachOFixupSectionAMD64(pModMachO, pbSectBits, pSect,
+                                                   (macho_nlist_64_t *)pModMachO->pvaSymbols,
+                                                   pModMachO->cSymbols, NewBaseAddress);
+            else
+                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+            if (rc)
+                break;
+        }
+    }
+
+    return rc;
+}
+
+
+/**
+ * Applies generic fixups to a section in an image of the same endian-ness
+ * as the host CPU.
+ *
+ * @returns 0 on success, non-zero kLdr status code on failure.
+ * @param   pModMachO       The Mach-O module interpreter instance.
+ * @param   pbSectBits      Pointer to the section bits.
+ * @param   pFixupSect      The section being fixed up.
+ * @param   NewBaseAddress  The new base image address.
+ */
+static int  kldrModMachOFixupSectionGeneric32Bit(PKLDRMODMACHO pModMachO, KU8 *pbSectBits, PKLDRMODMACHOSECT pFixupSect,
+                                                 macho_nlist_32_t *paSyms, KU32 cSyms, KLDRADDR NewBaseAddress)
+{
+    const macho_relocation_info_t *paFixups = pFixupSect->paFixups;
+    const KU32 cFixups = pFixupSect->cFixups;
+    KSIZE cbSectBits = (KSIZE)pFixupSect->cb;
+    const KU8 *pbSectVirginBits;
+    KU32 iFixup;
+    KLDRPU uFixVirgin;
+    KLDRPU uFix;
+    KLDRADDR SymAddr = ~(KLDRADDR)0;
+    int rc;
+
+    /*
+     * Find the virgin bits.
+     */
+    if (pFixupSect->offFile != -1)
+    {
+        rc = kldrModMachOMapVirginBits(pModMachO);
+        if (rc)
+            return rc;
+        pbSectVirginBits = (const KU8 *)pModMachO->pvBits + pFixupSect->offFile;
+    }
+    else
+        pbSectVirginBits = NULL;
+
+    /*
+     * Iterate the fixups and apply them.
+     */
+    for (iFixup = 0; iFixup < cFixups; iFixup++)
+    {
+        union
+        {
+            macho_relocation_info_t     r;
+            scattered_relocation_info_t s;
+        } Fixup;
+        Fixup.r = paFixups[iFixup];
+
+        if (!(Fixup.r.r_address & R_SCATTERED))
+        {
+            /* sanity */
+            if ((KU32)Fixup.r.r_address >= cbSectBits)
+                return KLDR_ERR_BAD_FIXUP;
+
+            /* calc fixup addresses. */
+            uFix.pv = pbSectBits + Fixup.r.r_address;
+            uFixVirgin.pv = pbSectVirginBits ? (KU8 *)pbSectVirginBits + Fixup.r.r_address : 0;
+
+            /*
+             * Calc the symbol value.
+             */
+            /* Calc the linked symbol address / addend. */
+            switch (Fixup.r.r_length)
+            {
+                /** @todo Deal with unaligned accesses on non x86 platforms. */
+                case 0: SymAddr = *uFixVirgin.pi8; break;
+                case 1: SymAddr = *uFixVirgin.pi16; break;
+                case 2: SymAddr = *uFixVirgin.pi32; break;
+                case 3: SymAddr = *uFixVirgin.pi64; break;
+            }
+            if (Fixup.r.r_pcrel)
+                SymAddr += Fixup.r.r_address + pFixupSect->LinkAddress;
+
+            /* Add symbol / section address. */
+            if (Fixup.r.r_extern)
+            {
+                const macho_nlist_32_t *pSym;
+                if (Fixup.r.r_symbolnum >= cSyms)
+                    return KLDR_ERR_BAD_FIXUP;
+                pSym = &paSyms[Fixup.r.r_symbolnum];
+
+                if (pSym->n_type & MACHO_N_STAB)
+                    return KLDR_ERR_BAD_FIXUP;
+
+                switch (pSym->n_type & MACHO_N_TYPE)
+                {
+                    case MACHO_N_SECT:
+                    {
+                        PKLDRMODMACHOSECT pSymSect;
+                        KLDRMODMACHO_CHECK_RETURN((KU32)pSym->n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL);
+                        pSymSect = &pModMachO->paSections[pSym->n_sect - 1];
+
+                        SymAddr += pSym->n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress;
+                        break;
+                    }
+
+                    case MACHO_N_UNDF:
+                    case MACHO_N_ABS:
+                        SymAddr += pSym->n_value;
+                        break;
+
+                    case MACHO_N_INDR:
+                    case MACHO_N_PBUD:
+                        KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+                    default:
+                        KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL);
+                }
+            }
+            else if (Fixup.r.r_symbolnum != R_ABS)
+            {
+                PKLDRMODMACHOSECT pSymSect;
+                if (Fixup.r.r_symbolnum > pModMachO->cSections)
+                    return KLDR_ERR_BAD_FIXUP;
+                pSymSect = &pModMachO->paSections[Fixup.r.r_symbolnum - 1];
+
+                SymAddr -= pSymSect->LinkAddress;
+                SymAddr += pSymSect->RVA + NewBaseAddress;
+            }
+
+            /* adjust for PC relative */
+            if (Fixup.r.r_pcrel)
+                SymAddr -= Fixup.r.r_address + pFixupSect->RVA + NewBaseAddress;
+        }
+        else
+        {
+            PKLDRMODMACHOSECT pSymSect;
+            KU32 iSymSect;
+            KLDRADDR Value;
+
+            /* sanity */
+            KLDRMODMACHO_ASSERT(Fixup.s.r_scattered);
+            if ((KU32)Fixup.s.r_address >= cbSectBits)
+                return KLDR_ERR_BAD_FIXUP;
+
+            /* calc fixup addresses. */
+            uFix.pv = pbSectBits + Fixup.s.r_address;
+            uFixVirgin.pv = pbSectVirginBits ? (KU8 *)pbSectVirginBits + Fixup.s.r_address : 0;
+
+            /*
+             * Calc the symbol value.
+             */
+            /* The addend is stored in the code. */
+            switch (Fixup.s.r_length)
+            {
+                case 0: SymAddr = *uFixVirgin.pi8; break;
+                case 1: SymAddr = *uFixVirgin.pi16; break;
+                case 2: SymAddr = *uFixVirgin.pi32; break;
+                case 3: SymAddr = *uFixVirgin.pi64; break;
+            }
+            if (Fixup.s.r_pcrel)
+                SymAddr += Fixup.s.r_address;
+            Value = Fixup.s.r_value;
+            SymAddr -= Value;                   /* (-> addend only) */
+
+            /* Find the section number from the r_value. */
+            pSymSect = NULL;
+            for (iSymSect = 0; iSymSect < pModMachO->cSections; iSymSect++)
+            {
+                KLDRADDR off = Value - pModMachO->paSections[iSymSect].LinkAddress;
+                if (off < pModMachO->paSections[iSymSect].cb)
+                {
+                    pSymSect = &pModMachO->paSections[iSymSect];
+                    break;
+                }
+                else if (off == pModMachO->paSections[iSymSect].cb) /* edge case */
+                    pSymSect = &pModMachO->paSections[iSymSect];
+            }
+            if (!pSymSect)
+                return KLDR_ERR_BAD_FIXUP;
+
+            /* Calc the symbol address. */
+            SymAddr += Value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress;
+            if (Fixup.s.r_pcrel)
+                SymAddr -= Fixup.s.r_address + pFixupSect->RVA + NewBaseAddress;
+
+            Fixup.r.r_length = ((scattered_relocation_info_t *)&paFixups[iFixup])->r_length;
+            Fixup.r.r_type   = ((scattered_relocation_info_t *)&paFixups[iFixup])->r_type;
+        }
+
+        /*
+         * Write back the fixed up value.
+         */
+        if (Fixup.r.r_type == GENERIC_RELOC_VANILLA)
+        {
+            switch (Fixup.r.r_length)
+            {
+                case 0: *uFix.pu8  = (KU8)SymAddr; break;
+                case 1: *uFix.pu16 = (KU16)SymAddr; break;
+                case 2: *uFix.pu32 = (KU32)SymAddr; break;
+                case 3: *uFix.pu64 = (KU64)SymAddr; break;
+            }
+        }
+        else if (Fixup.r.r_type <= GENERIC_RELOC_LOCAL_SECTDIFF)
+            return KLDR_ERR_MACHO_UNSUPPORTED_FIXUP_TYPE;
+        else
+            return KLDR_ERR_BAD_FIXUP;
+    }
+
+    return 0;
+}
+
+
+/**
+ * Applies AMD64 fixups to a section.
+ *
+ * @returns 0 on success, non-zero kLdr status code on failure.
+ * @param   pModMachO       The Mach-O module interpreter instance.
+ * @param   pbSectBits      Pointer to the section bits.
+ * @param   pFixupSect      The section being fixed up.
+ * @param   NewBaseAddress  The new base image address.
+ */
+static int  kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBits, PKLDRMODMACHOSECT pFixupSect,
+                                          macho_nlist_64_t *paSyms, KU32 cSyms, KLDRADDR NewBaseAddress)
+{
+    const macho_relocation_info_t *paFixups = pFixupSect->paFixups;
+    const KU32 cFixups = pFixupSect->cFixups;
+    KSIZE cbSectBits = (KSIZE)pFixupSect->cb;
+    const KU8 *pbSectVirginBits;
+    KU32 iFixup;
+    KLDRPU uFixVirgin;
+    KLDRPU uFix;
+    KLDRADDR SymAddr;
+    int rc;
+
+    /*
+     * Find the virgin bits.
+     */
+    if (pFixupSect->offFile != -1)
+    {
+        rc = kldrModMachOMapVirginBits(pModMachO);
+        if (rc)
+            return rc;
+        pbSectVirginBits = (const KU8 *)pModMachO->pvBits + pFixupSect->offFile;
+    }
+    else
+        pbSectVirginBits = NULL;
+
+    /*
+     * Iterate the fixups and apply them.
+     */
+    for (iFixup = 0; iFixup < cFixups; iFixup++)
+    {
+        union
+        {
+            macho_relocation_info_t     r;
+            scattered_relocation_info_t s;
+        } Fixup;
+        Fixup.r = paFixups[iFixup];
+
+        /* AMD64 doesn't use scattered fixups. */
+        KLDRMODMACHO_CHECK_RETURN(!(Fixup.r.r_address & R_SCATTERED), KLDR_ERR_BAD_FIXUP);
+
+        /* sanity */
+        KLDRMODMACHO_CHECK_RETURN((KU32)Fixup.r.r_address < cbSectBits, KLDR_ERR_BAD_FIXUP);
+
+        /* calc fixup addresses. */
+        uFix.pv = pbSectBits + Fixup.r.r_address;
+        uFixVirgin.pv = pbSectVirginBits ? (KU8 *)pbSectVirginBits + Fixup.r.r_address : 0;
+
+        /*
+         * Calc the symbol value.
+         */
+        /* Calc the linked symbol address / addend. */
+        switch (Fixup.r.r_length)
+        {
+            /** @todo Deal with unaligned accesses on non x86 platforms. */
+            case 2: SymAddr = *uFixVirgin.pi32; break;
+            case 3: SymAddr = *uFixVirgin.pi64; break;
+            default:
+                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP);
+        }
+
+        /* Add symbol / section address. */
+        if (Fixup.r.r_extern)
+        {
+            const macho_nlist_64_t *pSym;
+
+            KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_symbolnum < cSyms, KLDR_ERR_BAD_FIXUP);
+            pSym = &paSyms[Fixup.r.r_symbolnum];
+            KLDRMODMACHO_CHECK_RETURN(!(pSym->n_type & MACHO_N_STAB), KLDR_ERR_BAD_FIXUP);
+
+            switch (Fixup.r.r_type)
+            {
+                /* GOT references just needs to have their symbol verified.
+                   Later, we'll optimize GOT building here using a parallel sym->got array. */
+                case X86_64_RELOC_GOT_LOAD:
+                case X86_64_RELOC_GOT:
+                    switch (pSym->n_type & MACHO_N_TYPE)
+                    {
+                        case MACHO_N_SECT:
+                        case MACHO_N_UNDF:
+                        case MACHO_N_ABS:
+                            break;
+                        case MACHO_N_INDR:
+                        case MACHO_N_PBUD:
+                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+                        default:
+                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL);
+                    }
+                    SymAddr = sizeof(KU64) * Fixup.r.r_symbolnum + pModMachO->GotRVA + NewBaseAddress;
+                    KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_length == 2, KLDR_ERR_BAD_FIXUP);
+                    SymAddr -= 4;
+                    break;
+
+                /* Verify the r_pcrel field for signed fixups on the way into the default case. */
+                case X86_64_RELOC_BRANCH:
+                case X86_64_RELOC_SIGNED:
+                case X86_64_RELOC_SIGNED_1:
+                case X86_64_RELOC_SIGNED_2:
+                case X86_64_RELOC_SIGNED_4:
+                    KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_pcrel, KLDR_ERR_BAD_FIXUP);
+                default:
+                {
+                    /* Adjust with fixup specific addend and vierfy unsigned/r_pcrel. */
+                    switch (Fixup.r.r_type)
+                    {
+                        case X86_64_RELOC_UNSIGNED:
+                            KLDRMODMACHO_CHECK_RETURN(!Fixup.r.r_pcrel, KLDR_ERR_BAD_FIXUP);
+                            break;
+                        case X86_64_RELOC_BRANCH:
+                            KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_length == 2, KLDR_ERR_BAD_FIXUP);
+                            SymAddr -= 4;
+                            break;
+                        case X86_64_RELOC_SIGNED:
+                        case X86_64_RELOC_SIGNED_1:
+                        case X86_64_RELOC_SIGNED_2:
+                        case X86_64_RELOC_SIGNED_4:
+                            SymAddr -= 4;
+                            break;
+                        default:
+                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP);
+                    }
+
+                    switch (pSym->n_type & MACHO_N_TYPE)
+                    {
+                        case MACHO_N_SECT:
+                        {
+                            PKLDRMODMACHOSECT pSymSect;
+                            KLDRMODMACHO_CHECK_RETURN((KU32)pSym->n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL);
+                            pSymSect = &pModMachO->paSections[pSym->n_sect - 1];
+                            SymAddr += pSym->n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress;
+                            break;
+                        }
+
+                        case MACHO_N_UNDF:
+                            /* branch to an external symbol may have to take a short detour. */
+                            if (   Fixup.r.r_type == X86_64_RELOC_BRANCH
+                                &&       SymAddr + Fixup.r.r_address + pFixupSect->RVA + NewBaseAddress
+                                       - pSym->n_value
+                                       + KU64_C(0x80000000)
+                                    >= KU64_C(0xffffff20))
+                                SymAddr += pModMachO->cbJmpStub * Fixup.r.r_symbolnum + pModMachO->JmpStubsRVA + NewBaseAddress;
+                            else
+                                SymAddr += pSym->n_value;
+                            break;
+
+                        case MACHO_N_ABS:
+                            SymAddr += pSym->n_value;
+                            break;
+
+                        case MACHO_N_INDR:
+                        case MACHO_N_PBUD:
+                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+                        default:
+                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL);
+                    }
+                    break;
+                }
+
+                /*
+                 * This is a weird customer, it will always be follows by an UNSIGNED fixup.
+                 */
+                case X86_64_RELOC_SUBTRACTOR:
+                {
+                    macho_relocation_info_t Fixup2;
+
+                    /* Deal with the SUBTRACT symbol first, by subtracting it from SymAddr. */
+                    switch (pSym->n_type & MACHO_N_TYPE)
+                    {
+                        case MACHO_N_SECT:
+                        {
+                            PKLDRMODMACHOSECT pSymSect;
+                            KLDRMODMACHO_CHECK_RETURN((KU32)pSym->n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL);
+                            pSymSect = &pModMachO->paSections[pSym->n_sect - 1];
+                            SymAddr -= pSym->n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress;
+                            break;
+                        }
+
+                        case MACHO_N_UNDF:
+                        case MACHO_N_ABS:
+                            SymAddr -= pSym->n_value;
+                            break;
+
+                        case MACHO_N_INDR:
+                        case MACHO_N_PBUD:
+                            KLDRMODMACHO_CHECK_RETURN(0,KLDR_ERR_TODO);
+                        default:
+                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL);
+                    }
+
+                    /* Load the 2nd fixup, check sanity. */
+                    iFixup++;
+                    KLDRMODMACHO_CHECK_RETURN(!Fixup.r.r_pcrel && iFixup < cFixups, KLDR_ERR_BAD_FIXUP);
+                    Fixup2 = paFixups[iFixup];
+                    KLDRMODMACHO_CHECK_RETURN(   Fixup2.r_address == Fixup.r.r_address
+                                              && Fixup2.r_length == Fixup.r.r_length
+                                              && Fixup2.r_type == X86_64_RELOC_UNSIGNED
+                                              && !Fixup2.r_pcrel
+                                              && Fixup2.r_symbolnum < cSyms,
+                                              KLDR_ERR_BAD_FIXUP);
+
+                    if (Fixup2.r_extern)
+                    {
+                        KLDRMODMACHO_CHECK_RETURN(Fixup2.r_symbolnum < cSyms, KLDR_ERR_BAD_FIXUP);
+                        pSym = &paSyms[Fixup2.r_symbolnum];
+                        KLDRMODMACHO_CHECK_RETURN(!(pSym->n_type & MACHO_N_STAB), KLDR_ERR_BAD_FIXUP);
+
+                        /* Add it's value to SymAddr. */
+                        switch (pSym->n_type & MACHO_N_TYPE)
+                        {
+                            case MACHO_N_SECT:
+                            {
+                                PKLDRMODMACHOSECT pSymSect;
+                                KLDRMODMACHO_CHECK_RETURN((KU32)pSym->n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL);
+                                pSymSect = &pModMachO->paSections[pSym->n_sect - 1];
+                                SymAddr += pSym->n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress;
+                                break;
+                            }
+
+                            case MACHO_N_UNDF:
+                            case MACHO_N_ABS:
+                                SymAddr += pSym->n_value;
+                                break;
+
+                            case MACHO_N_INDR:
+                            case MACHO_N_PBUD:
+                                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+                            default:
+                                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL);
+                        }
+                    }
+                    else if (Fixup2.r_symbolnum != R_ABS)
+                    {
+                        PKLDRMODMACHOSECT pSymSect;
+                        KLDRMODMACHO_CHECK_RETURN(Fixup2.r_symbolnum <= pModMachO->cSections, KLDR_ERR_BAD_FIXUP);
+                        pSymSect = &pModMachO->paSections[Fixup2.r_symbolnum - 1];
+                        SymAddr += pSymSect->RVA + NewBaseAddress;
+                    }
+                    else
+                        KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP);
+                }
+                break;
+            }
+        }
+        else
+        {
+            /* verify against fixup type and make adjustments */
+            switch (Fixup.r.r_type)
+            {
+                case X86_64_RELOC_UNSIGNED:
+                    KLDRMODMACHO_CHECK_RETURN(!Fixup.r.r_pcrel, KLDR_ERR_BAD_FIXUP);
+                    break;
+                case X86_64_RELOC_BRANCH:
+                    KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_pcrel, KLDR_ERR_BAD_FIXUP);
+                    SymAddr += 4; /* dunno what the assmbler/linker really is doing here... */
+                    break;
+                case X86_64_RELOC_SIGNED:
+                case X86_64_RELOC_SIGNED_1:
+                case X86_64_RELOC_SIGNED_2:
+                case X86_64_RELOC_SIGNED_4:
+                    KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_pcrel, KLDR_ERR_BAD_FIXUP);
+                    break;
+                /*case X86_64_RELOC_GOT_LOAD:*/
+                /*case X86_64_RELOC_GOT: */
+                /*case X86_64_RELOC_SUBTRACTOR: - must be r_extern=1 says as. */
+                default:
+                    KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP);
+            }
+            if (Fixup.r.r_symbolnum != R_ABS)
+            {
+                PKLDRMODMACHOSECT pSymSect;
+                KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_symbolnum <= pModMachO->cSections, KLDR_ERR_BAD_FIXUP);
+                pSymSect = &pModMachO->paSections[Fixup.r.r_symbolnum - 1];
+
+                SymAddr -= pSymSect->LinkAddress;
+                SymAddr += pSymSect->RVA + NewBaseAddress;
+                if (Fixup.r.r_pcrel)
+                    SymAddr += Fixup.r.r_address;
+            }
+        }
+
+        /* adjust for PC relative */
+        if (Fixup.r.r_pcrel)
+            SymAddr -= Fixup.r.r_address + pFixupSect->RVA + NewBaseAddress;
+
+        /*
+         * Write back the fixed up value.
+         */
+        switch (Fixup.r.r_length)
+        {
+            case 3:
+                *uFix.pu64 = (KU64)SymAddr;
+                break;
+            case 2:
+                KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_pcrel || Fixup.r.r_type == X86_64_RELOC_SUBTRACTOR, KLDR_ERR_BAD_FIXUP);
+                KLDRMODMACHO_CHECK_RETURN((KI32)SymAddr == (KI64)SymAddr, KLDR_ERR_ADDRESS_OVERFLOW);
+                *uFix.pu32 = (KU32)SymAddr;
+                break;
+            default:
+                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP);
+        }
+    }
+
+    return 0;
+}
+
+
+/**
+ * Loads the symbol table for a MH_OBJECT file.
+ *
+ * The symbol table is pointed to by KLDRMODMACHO::pvaSymbols.
+ *
+ * @returns 0 on success, non-zero kLdr status code on failure.
+ * @param   pModMachO       The Mach-O module interpreter instance.
+ */
+static int  kldrModMachOLoadObjSymTab(PKLDRMODMACHO pModMachO)
+{
+    int rc = 0;
+
+    if (    !pModMachO->pvaSymbols
+        &&  pModMachO->cSymbols)
+    {
+        KSIZE cbSyms;
+        KSIZE cbSym;
+        void *pvSyms;
+        void *pvStrings;
+
+        /* sanity */
+        KLDRMODMACHO_CHECK_RETURN(   pModMachO->offSymbols
+                                  && (!pModMachO->cchStrings || pModMachO->offStrings),
+                                  KLDR_ERR_MACHO_BAD_OBJECT_FILE);
+
+        /* allocate */
+        cbSym = pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
+             || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE
+             ? sizeof(macho_nlist_32_t)
+             : sizeof(macho_nlist_64_t);
+        cbSyms = pModMachO->cSymbols * cbSym;
+        KLDRMODMACHO_CHECK_RETURN(cbSyms / cbSym == pModMachO->cSymbols, KLDR_ERR_SIZE_OVERFLOW);
+        rc = KERR_NO_MEMORY;
+        pvSyms = kHlpAlloc(cbSyms);
+        if (pvSyms)
+        {
+            if (pModMachO->cchStrings)
+                pvStrings = kHlpAlloc(pModMachO->cchStrings);
+            else
+                pvStrings = kHlpAllocZ(4);
+            if (pvStrings)
+            {
+                /* read */
+                rc = kRdrRead(pModMachO->pMod->pRdr, pvSyms, cbSyms, pModMachO->offSymbols);
+                if (!rc && pModMachO->cchStrings)
+                    rc = kRdrRead(pModMachO->pMod->pRdr, pvStrings, pModMachO->cchStrings, pModMachO->offStrings);
+                if (!rc)
+                {
+                    pModMachO->pvaSymbols = pvSyms;
+                    pModMachO->pchStrings = (char *)pvStrings;
+
+                    /* perform endian conversion? */
+                    if (pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
+                    {
+                        KU32 cLeft = pModMachO->cSymbols;
+                        macho_nlist_32_t *pSym = (macho_nlist_32_t *)pvSyms;
+                        while (cLeft-- > 0)
+                        {
+                            pSym->n_un.n_strx = K_E2E_U32(pSym->n_un.n_strx);
+                            pSym->n_desc = (KI16)K_E2E_U16(pSym->n_desc);
+                            pSym->n_value = K_E2E_U32(pSym->n_value);
+                            pSym++;
+                        }
+                    }
+                    else if (pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE)
+                    {
+                        KU32 cLeft = pModMachO->cSymbols;
+                        macho_nlist_64_t *pSym = (macho_nlist_64_t *)pvSyms;
+                        while (cLeft-- > 0)
+                        {
+                            pSym->n_un.n_strx = K_E2E_U32(pSym->n_un.n_strx);
+                            pSym->n_desc = (KI16)K_E2E_U16(pSym->n_desc);
+                            pSym->n_value = K_E2E_U64(pSym->n_value);
+                            pSym++;
+                        }
+                    }
+
+                    return 0;
+                }
+                kHlpFree(pvStrings);
+            }
+            kHlpFree(pvSyms);
+        }
+    }
+    else
+        KLDRMODMACHO_ASSERT(pModMachO->pchStrings || pModMachO->Hdr.filetype == MH_DSYM);
+
+    return rc;
+}
+
+
+/**
+ * Loads the fixups at the given address and performs endian
+ * conversion if necessary.
+ *
+ * @returns 0 on success, non-zero kLdr status code on failure.
+ * @param   pModMachO       The Mach-O module interpreter instance.
+ * @param   offFixups       The file offset of the fixups.
+ * @param   cFixups         The number of fixups to load.
+ * @param   ppaFixups       Where to put the pointer to the allocated fixup array.
+ */
+static int  kldrModMachOLoadFixups(PKLDRMODMACHO pModMachO, KLDRFOFF offFixups, KU32 cFixups, macho_relocation_info_t **ppaFixups)
+{
+    macho_relocation_info_t *paFixups;
+    KSIZE cbFixups;
+    int rc;
+
+    /* allocate the memory. */
+    cbFixups = cFixups * sizeof(*paFixups);
+    KLDRMODMACHO_CHECK_RETURN(cbFixups / sizeof(*paFixups) == cFixups, KLDR_ERR_SIZE_OVERFLOW);
+    paFixups = (macho_relocation_info_t *)kHlpAlloc(cbFixups);
+    if (!paFixups)
+        return KERR_NO_MEMORY;
+
+    /* read the fixups. */
+    rc = kRdrRead(pModMachO->pMod->pRdr, paFixups, cbFixups, offFixups);
+    if (!rc)
+    {
+        *ppaFixups = paFixups;
+
+        /* do endian conversion if necessary. */
+        if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE
+            ||  pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE)
+        {
+            KU32 iFixup;
+            for (iFixup = 0; iFixup < cFixups; iFixup++)
+            {
+                KU32 *pu32 = (KU32 *)&paFixups[iFixup];
+                pu32[0] = K_E2E_U32(pu32[0]);
+                pu32[1] = K_E2E_U32(pu32[1]);
+            }
+        }
+    }
+    else
+        kHlpFree(paFixups);
+    return rc;
+}
+
+
+/**
+ * Maps the virgin file bits into memory if not already done.
+ *
+ * @returns 0 on success, non-zero kLdr status code on failure.
+ * @param   pModMachO       The Mach-O module interpreter instance.
+ */
+static int kldrModMachOMapVirginBits(PKLDRMODMACHO pModMachO)
+{
+    int rc = 0;
+    if (!pModMachO->pvBits)
+        rc = kRdrAllMap(pModMachO->pMod->pRdr, &pModMachO->pvBits);
+    return rc;
+}
+
+
+/** @copydoc kLdrModCallInit */
+static int kldrModMachOCallInit(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle)
+{
+    /* later */
+    K_NOREF(pMod);
+    K_NOREF(pvMapping);
+    K_NOREF(uHandle);
+    return 0;
+}
+
+
+/** @copydoc kLdrModCallTerm */
+static int kldrModMachOCallTerm(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle)
+{
+    /* later */
+    K_NOREF(pMod);
+    K_NOREF(pvMapping);
+    K_NOREF(uHandle);
+    return 0;
+}
+
+
+/** @copydoc kLdrModCallThread */
+static int kldrModMachOCallThread(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle, unsigned fAttachingOrDetaching)
+{
+    /* Relevant for Mach-O? */
+    K_NOREF(pMod);
+    K_NOREF(pvMapping);
+    K_NOREF(uHandle);
+    K_NOREF(fAttachingOrDetaching);
+    return 0;
+}
+
+
+/** @copydoc kLdrModSize */
+static KLDRADDR kldrModMachOSize(PKLDRMOD pMod)
+{
+    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
+    return pModMachO->cbImage;
+}
+
+
+/** @copydoc kLdrModGetBits */
+static int kldrModMachOGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    PKLDRMODMACHO  pModMachO = (PKLDRMODMACHO)pMod->pvData;
+    KU32        i;
+    int         rc;
+
+    if (!pModMachO->fCanLoad)
+        return KLDR_ERR_TODO;
+
+    /*
+     * Zero the entire buffer first to simplify things.
+     */
+    kHlpMemSet(pvBits, 0, (KSIZE)pModMachO->cbImage);
+
+    /*
+     * When possible use the segment table to load the data.
+     */
+    for (i = 0; i < pMod->cSegments; i++)
+    {
+        /* skip it? */
+        if (    pMod->aSegments[i].cbFile == -1
+            ||  pMod->aSegments[i].offFile == -1
+            ||  pMod->aSegments[i].LinkAddress == NIL_KLDRADDR
+            ||  !pMod->aSegments[i].Alignment)
+            continue;
+        rc = kRdrRead(pMod->pRdr,
+                      (KU8 *)pvBits + pMod->aSegments[i].RVA,
+                      pMod->aSegments[i].cbFile,
+                      pMod->aSegments[i].offFile);
+        if (rc)
+            return rc;
+    }
+
+    /*
+     * Perform relocations.
+     */
+    return kldrModMachORelocateBits(pMod, pvBits, BaseAddress, pModMachO->LinkAddress, pfnGetImport, pvUser);
+}
+
+
+/** @copydoc kLdrModRelocateBits */
+static int kldrModMachORelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
+                                    PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
+    int rc;
+    K_NOREF(OldBaseAddress);
+
+    /*
+     * Call workers to do the jobs.
+     */
+    if (pModMachO->Hdr.filetype == MH_OBJECT)
+    {
+        rc = kldrModMachOObjDoImports(pModMachO, NewBaseAddress, pfnGetImport, pvUser);
+        if (!rc)
+            rc = kldrModMachOObjDoFixups(pModMachO, pvBits, NewBaseAddress);
+
+    }
+    else
+        rc = KLDR_ERR_TODO;
+    /*{
+        rc = kldrModMachODoFixups(pModMachO, pvBits, NewBaseAddress, OldBaseAddress, pfnGetImport, pvUser);
+        if (!rc)
+            rc = kldrModMachODoImports(pModMachO, pvBits, pfnGetImport, pvUser);
+    }*/
+
+    /*
+     * Construct the global offset table if necessary, it's always the last
+     * segment when present.
+     */
+    if (!rc && pModMachO->fMakeGot)
+        rc = kldrModMachOMakeGOT(pModMachO, pvBits, NewBaseAddress);
+
+    return rc;
+}
+
+
+/**
+ * Builds the GOT.
+ *
+ * Assumes the symbol table has all external symbols resolved correctly and that
+ * the bits has been cleared up front.
+ */
+static int kldrModMachOMakeGOT(PKLDRMODMACHO pModMachO, void *pvBits, KLDRADDR NewBaseAddress)
+{
+    KU32  iSym = pModMachO->cSymbols;
+    if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
+        ||  pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
+    {
+        macho_nlist_32_t const *paSyms = (macho_nlist_32_t const *)pModMachO->pvaSymbols;
+        KU32 *paGOT = (KU32 *)((KU8 *)pvBits + pModMachO->GotRVA);
+        while (iSym-- > 0)
+            switch (paSyms[iSym].n_type & MACHO_N_TYPE)
+            {
+                case MACHO_N_SECT:
+                {
+                    PKLDRMODMACHOSECT pSymSect;
+                    KLDRMODMACHO_CHECK_RETURN((KU32)paSyms[iSym].n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL);
+                    pSymSect = &pModMachO->paSections[paSyms[iSym].n_sect - 1];
+                    paGOT[iSym] = paSyms[iSym].n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress;
+                    break;
+                }
+
+                case MACHO_N_UNDF:
+                case MACHO_N_ABS:
+                    paGOT[iSym] = paSyms[iSym].n_value;
+                    break;
+            }
+    }
+    else
+    {
+        macho_nlist_64_t const *paSyms = (macho_nlist_64_t const *)pModMachO->pvaSymbols;
+        KU64 *paGOT = (KU64 *)((KU8 *)pvBits + pModMachO->GotRVA);
+        while (iSym-- > 0)
+        {
+            switch (paSyms[iSym].n_type & MACHO_N_TYPE)
+            {
+                case MACHO_N_SECT:
+                {
+                    PKLDRMODMACHOSECT pSymSect;
+                    KLDRMODMACHO_CHECK_RETURN((KU32)paSyms[iSym].n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL);
+                    pSymSect = &pModMachO->paSections[paSyms[iSym].n_sect - 1];
+                    paGOT[iSym] = paSyms[iSym].n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress;
+                    break;
+                }
+
+                case MACHO_N_UNDF:
+                case MACHO_N_ABS:
+                    paGOT[iSym] = paSyms[iSym].n_value;
+                    break;
+            }
+        }
+
+        if (pModMachO->JmpStubsRVA != NIL_KLDRADDR)
+        {
+            iSym = pModMachO->cSymbols;
+            switch (pModMachO->Hdr.cputype)
+            {
+                /*
+                 * AMD64 is simple since the GOT and the indirect jmps are parallel
+                 * arrays with entries of the same size. The relative offset will
+                 * be the the same for each entry, kind of nice. :-)
+                 */
+                case CPU_TYPE_X86_64:
+                {
+                    KU64   *paJmps = (KU64 *)((KU8 *)pvBits + pModMachO->JmpStubsRVA);
+                    KI32    off;
+                    KU64    u64Tmpl;
+                    union
+                    {
+                        KU8     ab[8];
+                        KU64    u64;
+                    }       Tmpl;
+
+                    /* create the template. */
+                    off = pModMachO->GotRVA - (pModMachO->JmpStubsRVA + 6);
+                    Tmpl.ab[0] = 0xff; /* jmp [GOT-entry wrt RIP] */
+                    Tmpl.ab[1] = 0x25;
+                    Tmpl.ab[2] =  off        & 0xff;
+                    Tmpl.ab[3] = (off >>  8) & 0xff;
+                    Tmpl.ab[4] = (off >> 16) & 0xff;
+                    Tmpl.ab[5] = (off >> 24) & 0xff;
+                    Tmpl.ab[6] = 0xcc;
+                    Tmpl.ab[7] = 0xcc;
+                    u64Tmpl = Tmpl.u64;
+
+                    /* copy the template to every jmp table entry. */
+                    while (iSym-- > 0)
+                        paJmps[iSym] = u64Tmpl;
+                    break;
+                }
+
+                default:
+                    KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+            }
+        }
+    }
+    return 0;
+}
+
+
+/**
+ * The Mach-O module interpreter method table.
+ */
+KLDRMODOPS g_kLdrModMachOOps =
+{
+    "Mach-O",
+    NULL,
+    kldrModMachOCreate,
+    kldrModMachODestroy,
+    kldrModMachOQuerySymbol,
+    kldrModMachOEnumSymbols,
+    kldrModMachOGetImport,
+    kldrModMachONumberOfImports,
+    NULL /* can execute one is optional */,
+    kldrModMachOGetStackInfo,
+    kldrModMachOQueryMainEntrypoint,
+    kldrModMachOQueryImageUuid,
+    NULL,
+    NULL,
+    kldrModMachOEnumDbgInfo,
+    kldrModMachOHasDbgInfo,
+    kldrModMachOMap,
+    kldrModMachOUnmap,
+    kldrModMachOAllocTLS,
+    kldrModMachOFreeTLS,
+    kldrModMachOReload,
+    kldrModMachOFixupMapping,
+    kldrModMachOCallInit,
+    kldrModMachOCallTerm,
+    kldrModMachOCallThread,
+    kldrModMachOSize,
+    kldrModMachOGetBits,
+    kldrModMachORelocateBits,
+    NULL, /** @todo mostly done */
+    42 /* the end */
+};
+
diff --git a/src/lib/kStuff/kLdr/kLdrModNative.c b/src/lib/kStuff/kLdr/kLdrModNative.c
new file mode 100644
index 0000000..29f65a4
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrModNative.c
@@ -0,0 +1,1167 @@
+/* $Id: kLdrModNative.c 82 2016-08-22 21:01:51Z bird $ */
+/** @file
+ * kLdr - The Module Interpreter for the Native Loaders.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kLdr.h>
+#include "kLdrInternal.h"
+
+#if K_OS == K_OS_OS2
+# define INCL_BASE
+# include <os2.h>
+
+# ifndef LIBPATHSTRICT
+#  define LIBPATHSTRICT 3
+# endif
+  extern APIRET DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction);
+# define QHINF_EXEINFO       1 /* NE exeinfo. */
+# define QHINF_READRSRCTBL   2 /* Reads from the resource table. */
+# define QHINF_READFILE      3 /* Reads from the executable file. */
+# define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */
+# define QHINF_LIBPATH       5 /* Gets the entire libpath. */
+# define QHINF_FIXENTRY      6 /* NE only */
+# define QHINF_STE           7 /* NE only */
+# define QHINF_MAPSEL        8 /* NE only */
+
+#elif K_OS == K_OS_WINDOWS
+# undef IMAGE_NT_SIGNATURE
+# undef IMAGE_DOS_SIGNATURE
+# include <windows.h>
+# ifndef IMAGE_SCN_TYPE_NOLOAD
+#  define IMAGE_SCN_TYPE_NOLOAD 0x00000002
+# endif
+
+/*#elif defined(__NT__)
+#include <winnt.h> */
+
+#elif K_OS == K_OS_DARWIN
+# include <dlfcn.h>
+# include <errno.h>
+
+#else
+# error "port me"
+#endif
+
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** @def KLDRMODNATIVE_STRICT
+ * Define KLDRMODNATIVE_STRICT to enabled strict checks in KLDRMODNATIVE. */
+#define KLDRMODNATIVE_STRICT 1
+
+/** @def KLDRMODNATIVE_ASSERT
+ * Assert that an expression is true when KLDR_STRICT is defined.
+ */
+#ifdef KLDRMODNATIVE_STRICT
+# define KLDRMODNATIVE_ASSERT(expr)  kHlpAssert(expr)
+#else
+# define KLDRMODNATIVE_ASSERT(expr)  do {} while (0)
+#endif
+
+#if K_OS == K_OS_WINDOWS
+/** @def KLDRMODNATIVE_RVA2TYPE
+ * Converts a RVA to a pointer of the specified type.
+ * @param   pvBits      The bits (image base).
+ * @param   uRVA        The image relative virtual address.
+ * @param   type        The type to cast to.
+ */
+# define KLDRMODNATIVE_RVA2TYPE(pvBits, uRVA, type) \
+        ( (type) ((KUPTR)(pvBits) + (uRVA)) )
+
+#endif /* PE OSes */
+
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Instance data for the module interpreter for the Native Loaders.
+ */
+typedef struct KLDRMODNATIVE
+{
+    /** Pointer to the module. (Follows the section table.) */
+    PKLDRMOD                    pMod;
+    /** Reserved flags. */
+    KU32                        f32Reserved;
+    /** The number of imported modules.
+     * If ~(KU32)0 this hasn't been determined yet. */
+    KU32                        cImportModules;
+#if K_OS == K_OS_OS2
+    /** The module handle. */
+    HMODULE                     hmod;
+
+#elif K_OS == K_OS_WINDOWS
+    /** The module handle. */
+    HANDLE                      hmod;
+    /** Pointer to the NT headers. */
+    const IMAGE_NT_HEADERS     *pNtHdrs;
+    /** Pointer to the section header array. */
+    const IMAGE_SECTION_HEADER *paShdrs;
+
+#elif K_OS == K_OS_DARWIN
+    /** The dlopen() handle.*/
+    void                       *pvMod;
+
+#else
+# error "Port me"
+#endif
+} KLDRMODNATIVE, *PKLDRMODNATIVE;
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static KI32 kldrModNativeNumberOfImports(PKLDRMOD pMod, const void *pvBits);
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+extern KLDRMODOPS g_kLdrModNativeOps;
+
+
+
+/**
+ * Use native loader to load the file opened by pRdr.
+ *
+ * @returns 0 on success and *ppMod pointing to a module instance.
+ *          On failure, a non-zero OS specific error code is returned.
+ * @param   pOps            Pointer to the registered method table.
+ * @param   pRdr            The file provider instance to use.
+ * @param   offNewHdr       The offset of the new header in MZ files. -1 if not found.
+ * @param   ppMod           Where to store the module instance pointer.
+ */
+static int kldrModNativeCreate(PCKLDRMODOPS pOps, PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch,
+                               KLDRFOFF offNewHdr, PPKLDRMOD ppMod)
+{
+    int rc = kLdrModOpenNative(kRdrName(pRdr), ppMod);
+    if (rc)
+        return rc;
+    rc = kRdrClose(pRdr);
+    KLDRMODNATIVE_ASSERT(!rc);
+    return 0;
+}
+
+
+/**
+ * Loads a module using the native module loader.
+ *
+ * @returns 0 on success.
+ * @returns non-zero native or kLdr status code on failure.
+ * @param   pszFilename         The filename or module name to be loaded.
+ * @param   ppMod               Where to store the module interpreter instance pointer.
+ */
+int kLdrModOpenNative(const char *pszFilename, PPKLDRMOD ppMod)
+{
+    int rc;
+
+    /*
+     * Load the image.
+     */
+#if K_OS == K_OS_OS2
+    HMODULE hmod;
+
+    rc = DosLoadModule(NULL, 0, (PCSZ)pszFilename, &hmod);
+    if (rc)
+        return rc;
+    rc = kLdrModOpenNativeByHandle((KUPTR)hmod, ppMod);
+    if (rc)
+        DosFreeModule(hmod);
+
+#elif K_OS == K_OS_WINDOWS
+    HMODULE hmod;
+
+    hmod = LoadLibrary(pszFilename);
+    if (!hmod)
+        return GetLastError();
+    rc = kLdrModOpenNativeByHandle((KUPTR)hmod, ppMod);
+    if (rc)
+        FreeLibrary(hmod);
+
+#elif K_OS == K_OS_DARWIN
+    void *pvMod;
+
+    pvMod = dlopen(pszFilename, 0);
+    if (!pvMod)
+        return ENOENT;
+    rc = kLdrModOpenNativeByHandle((KUPTR)pvMod, ppMod);
+    if (rc)
+        dlclose(pvMod);
+
+#else
+# error "Port me"
+#endif
+    return rc;
+}
+
+
+/**
+ * Creates a native module interpret for an already module already
+ * loaded by the native loader.
+ *
+ * @returns 0 on success.
+ * @returns non-zero native or kLdr status code on failure.
+ * @param   pszFilename         The filename or module name to be loaded.
+ * @param   ppMod               Where to store the module interpreter instance pointer.
+ * @remark  This will not make the native loader increment the load count.
+ */
+int kLdrModOpenNativeByHandle(KUPTR uHandle, PPKLDRMOD ppMod)
+{
+    KSIZE cb;
+    KU32 cchFilename;
+    KU32 cSegments;
+    PKLDRMOD pMod;
+    PKLDRMODNATIVE pModNative;
+
+    /*
+     * Delcare variables, parse the module header or whatever and determin the
+     * size of the module instance.
+     */
+#if K_OS == K_OS_OS2
+    char szFilename[CCHMAXPATH];
+    int rc;
+
+    /* get the filename. */
+    rc = DosQueryModuleName((HMODULE)uHandle, sizeof(szFilename), szFilename);
+    if (rc)
+    {
+        KLDRMODNATIVE_ASSERT(rc);
+        szFilename[0] = '\0';
+    }
+
+    /* get the segment count. */
+    /** @todo DosQueryHeaderInfo should be able to get us what we want on OS/2. */
+    cSegments = 1;
+
+#elif K_OS == K_OS_WINDOWS
+    DWORD                       dw;
+    char                        szFilename[MAX_PATH];
+    const IMAGE_NT_HEADERS     *pNtHdrs;
+    const IMAGE_SECTION_HEADER *paShdrs;
+    const IMAGE_DOS_HEADER     *pDosHdr = (const IMAGE_DOS_HEADER *)uHandle;
+    unsigned                    i;
+
+    /* get the filename. */
+    dw = GetModuleFileName((HANDLE)uHandle, szFilename, sizeof(szFilename));
+    if (dw <= 0)
+    {
+        KLDRMODNATIVE_ASSERT(dw <= 0);
+        szFilename[0] = '\0';
+    }
+
+    /* get the segment count. */
+    if (pDosHdr->e_magic == IMAGE_DOS_SIGNATURE)
+        pNtHdrs = (const IMAGE_NT_HEADERS *)((KUPTR)pDosHdr + pDosHdr->e_lfanew);
+    else
+        pNtHdrs = (const IMAGE_NT_HEADERS *)pDosHdr;
+    if (pNtHdrs->Signature != IMAGE_NT_SIGNATURE)
+    {
+        KLDRMODNATIVE_ASSERT(!"bad signature");
+        return KLDR_ERR_UNKNOWN_FORMAT;
+    }
+    if (pNtHdrs->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER))
+    {
+        KLDRMODNATIVE_ASSERT(!"bad optional header size");
+        return KLDR_ERR_UNKNOWN_FORMAT;
+    }
+    cSegments = pNtHdrs->FileHeader.NumberOfSections + 1;
+    paShdrs = (const IMAGE_SECTION_HEADER *)(pNtHdrs + 1);
+
+#elif K_OS == K_OS_DARWIN
+    char    szFilename[1] = "";
+    cSegments = 0; /** @todo Figure out the Mac OS X dynamic loader. */
+
+#else
+# error "Port me"
+#endif
+
+    /*
+     * Calc the instance size, allocate and initialize it.
+     */
+    cchFilename = (KU32)kHlpStrLen(szFilename);
+    cb = K_ALIGN_Z(sizeof(KLDRMODNATIVE), 16)
+       + K_OFFSETOF(KLDRMOD, aSegments[cSegments])
+       + cchFilename + 1;
+    pModNative = (PKLDRMODNATIVE)kHlpAlloc(cb);
+    if (!pModNative)
+        return KERR_NO_MEMORY;
+
+    /* KLDRMOD */
+    pMod = (PKLDRMOD)((KU8 *)pModNative + K_ALIGN_Z(sizeof(KLDRMODNATIVE), 16));
+    pMod->pvData = pModNative;
+    pMod->pRdr = NULL;
+    pMod->pOps = NULL;      /* set upon success. */
+    pMod->cSegments = cSegments;
+    pMod->cchFilename = cchFilename;
+    pMod->pszFilename = (char *)&pMod->aSegments[pMod->cSegments];
+    kHlpMemCopy((char *)pMod->pszFilename, szFilename, cchFilename + 1);
+    pMod->pszName = kHlpGetFilename(pMod->pszFilename); /** @todo get soname */
+    pMod->cchName = cchFilename - (KU32)(pMod->pszName - pMod->pszFilename);
+    pMod->fFlags = 0;
+#if defined(__i386__) || defined(__X86__) || defined(_M_IX86)
+    pMod->enmCpu = KCPU_I386;
+    pMod->enmArch = KCPUARCH_X86_32;
+    pMod->enmEndian = KLDRENDIAN_LITTLE;
+#elif defined(__X86_64__) || defined(__x86_64__) || defined(__AMD64__) || defined(_M_IX64)
+    pMod->enmCpu = KCPU_K8;
+    pMod->enmArch = KCPUARCH_AMD64;
+    pMod->enmEndian = KLDRENDIAN_LITTLE;
+#else
+# error "Port me"
+#endif
+    pMod->enmFmt = KLDRFMT_NATIVE;
+    pMod->enmType = KLDRTYPE_SHARED_LIBRARY_RELOCATABLE;
+    pMod->u32Magic = 0;     /* set upon success. */
+
+    /* KLDRMODNATIVE */
+    pModNative->pMod = pMod;
+    pModNative->f32Reserved = 0;
+    pModNative->cImportModules = ~(KU32)0;
+
+    /*
+     * Set native instance data.
+     */
+#if K_OS == K_OS_OS2
+    pModNative->hmod = (HMODULE)uHandle;
+
+    /* just fake a segment for now. */
+    pMod->aSegments[0].pvUser = NULL;
+    pMod->aSegments[0].pchName = "fake";
+    pMod->aSegments[0].cchName = sizeof("fake") - 1;
+    pMod->aSegments[0].enmProt = KPROT_NOACCESS;
+    pMod->aSegments[0].cb = 0;
+    pMod->aSegments[0].Alignment = 0;
+    pMod->aSegments[0].LinkAddress = NIL_KLDRADDR;
+    pMod->aSegments[0].offFile = -1;
+    pMod->aSegments[0].cbFile = 0;
+    pMod->aSegments[0].RVA = NIL_KLDRADDR;
+    pMod->aSegments[0].cbMapped = 0;
+    pMod->aSegments[0].MapAddress = 0;
+
+#elif K_OS == K_OS_WINDOWS
+    pModNative->hmod = (HMODULE)uHandle;
+    pModNative->pNtHdrs = pNtHdrs;
+    pModNative->paShdrs = paShdrs;
+
+    if (pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL)
+        pMod->enmType = !(pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
+            ? KLDRTYPE_SHARED_LIBRARY_RELOCATABLE
+            : KLDRTYPE_SHARED_LIBRARY_FIXED;
+    else
+        pMod->enmType = !(pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
+            ? KLDRTYPE_EXECUTABLE_RELOCATABLE
+            : KLDRTYPE_EXECUTABLE_FIXED;
+
+    /* The implied headers section. */
+    pMod->aSegments[0].pvUser = NULL;
+    pMod->aSegments[0].pchName = "TheHeaders";
+    pMod->aSegments[0].cchName = sizeof("TheHeaders") - 1;
+    pMod->aSegments[0].enmProt = KPROT_READONLY;
+    pMod->aSegments[0].cb = pNtHdrs->OptionalHeader.SizeOfHeaders;
+    pMod->aSegments[0].Alignment = pNtHdrs->OptionalHeader.SectionAlignment;
+    pMod->aSegments[0].LinkAddress = pNtHdrs->OptionalHeader.ImageBase;
+    pMod->aSegments[0].offFile = 0;
+    pMod->aSegments[0].cbFile = pNtHdrs->OptionalHeader.SizeOfHeaders;
+    pMod->aSegments[0].RVA = 0;
+    if (pMod->cSegments > 1)
+        pMod->aSegments[0].cbMapped = paShdrs[0].VirtualAddress;
+    else
+        pMod->aSegments[0].cbMapped = pNtHdrs->OptionalHeader.SizeOfHeaders;
+    pMod->aSegments[0].MapAddress = uHandle;
+
+    /* The section headers. */
+    for (i = 0; i < pNtHdrs->FileHeader.NumberOfSections; i++)
+    {
+        const char *pch;
+        KU32        cchSegName;
+
+        /* unused */
+        pMod->aSegments[i + 1].pvUser = NULL;
+
+        /* name */
+        pMod->aSegments[i + 1].pchName = pch = &paShdrs[i].Name[0];
+        cchSegName = IMAGE_SIZEOF_SHORT_NAME;
+        while (    cchSegName > 0
+               && (pch[cchSegName - 1] == ' ' || pch[cchSegName - 1] == '\0'))
+            cchSegName--;
+        pMod->aSegments[i + 1].cchName = cchSegName;
+
+        /* size and addresses */
+        if (!(paShdrs[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+        {
+            pMod->aSegments[i + 1].cb          = paShdrs[i].Misc.VirtualSize;
+            pMod->aSegments[i + 1].RVA         = paShdrs[i].VirtualAddress;
+            pMod->aSegments[i + 1].LinkAddress = paShdrs[i].VirtualAddress + pNtHdrs->OptionalHeader.ImageBase;
+            pMod->aSegments[i + 1].MapAddress  = paShdrs[i].VirtualAddress + uHandle;
+            pMod->aSegments[i + 1].cbMapped    = paShdrs[i].Misc.VirtualSize;
+            if (i + 2 < pMod->cSegments)
+                pMod->aSegments[i + 1].cbMapped = paShdrs[i + 1].VirtualAddress
+                                                - paShdrs[i].VirtualAddress;
+        }
+        else
+        {
+            pMod->aSegments[i + 1].cb          = 0;
+            pMod->aSegments[i + 1].cbMapped    = 0;
+            pMod->aSegments[i + 1].LinkAddress = NIL_KLDRADDR;
+            pMod->aSegments[i + 1].RVA         = 0;
+            pMod->aSegments[i + 1].MapAddress  = 0;
+        }
+
+        /* file location */
+        pMod->aSegments[i + 1].offFile = paShdrs[i].PointerToRawData;
+        pMod->aSegments[i + 1].cbFile  = paShdrs[i].SizeOfRawData;
+        if (    pMod->aSegments[i + 1].cbMapped > 0 /* if mapped */
+            &&  (KLDRSIZE)pMod->aSegments[i + 1].cbFile > pMod->aSegments[i + 1].cbMapped)
+            pMod->aSegments[i + 1].cbFile = (KLDRFOFF)pMod->aSegments[i + 1].cbMapped;
+
+        /* protection */
+        switch (  paShdrs[i].Characteristics
+                & (IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE))
+        {
+            case 0:
+            case IMAGE_SCN_MEM_SHARED:
+                pMod->aSegments[i + 1].enmProt = KPROT_NOACCESS;
+                break;
+            case IMAGE_SCN_MEM_READ:
+            case IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_SHARED:
+                pMod->aSegments[i + 1].enmProt = KPROT_READONLY;
+                break;
+            case IMAGE_SCN_MEM_WRITE:
+            case IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ:
+                pMod->aSegments[i + 1].enmProt = KPROT_WRITECOPY;
+                break;
+            case IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED:
+            case IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ:
+                pMod->aSegments[i + 1].enmProt = KPROT_READWRITE;
+                break;
+            case IMAGE_SCN_MEM_EXECUTE:
+            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_SHARED:
+                pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE;
+                break;
+            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ:
+            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_SHARED:
+                pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE_READ;
+                break;
+            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE:
+            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ:
+                pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE_WRITECOPY;
+                break;
+            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED:
+            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ:
+                pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE_READWRITE;
+                break;
+        }
+
+        /* alignment. */
+        switch (paShdrs[i].Characteristics & IMAGE_SCN_ALIGN_MASK)
+        {
+            case 0: /* hope this is right... */
+                pMod->aSegments[i + 1].Alignment = pNtHdrs->OptionalHeader.SectionAlignment;
+                break;
+            case IMAGE_SCN_ALIGN_1BYTES:        pMod->aSegments[i + 1].Alignment = 1; break;
+            case IMAGE_SCN_ALIGN_2BYTES:        pMod->aSegments[i + 1].Alignment = 2; break;
+            case IMAGE_SCN_ALIGN_4BYTES:        pMod->aSegments[i + 1].Alignment = 4; break;
+            case IMAGE_SCN_ALIGN_8BYTES:        pMod->aSegments[i + 1].Alignment = 8; break;
+            case IMAGE_SCN_ALIGN_16BYTES:       pMod->aSegments[i + 1].Alignment = 16; break;
+            case IMAGE_SCN_ALIGN_32BYTES:       pMod->aSegments[i + 1].Alignment = 32; break;
+            case IMAGE_SCN_ALIGN_64BYTES:       pMod->aSegments[i + 1].Alignment = 64; break;
+            case IMAGE_SCN_ALIGN_128BYTES:      pMod->aSegments[i + 1].Alignment = 128; break;
+            case IMAGE_SCN_ALIGN_256BYTES:      pMod->aSegments[i + 1].Alignment = 256; break;
+            case IMAGE_SCN_ALIGN_512BYTES:      pMod->aSegments[i + 1].Alignment = 512; break;
+            case IMAGE_SCN_ALIGN_1024BYTES:     pMod->aSegments[i + 1].Alignment = 1024; break;
+            case IMAGE_SCN_ALIGN_2048BYTES:     pMod->aSegments[i + 1].Alignment = 2048; break;
+            case IMAGE_SCN_ALIGN_4096BYTES:     pMod->aSegments[i + 1].Alignment = 4096; break;
+            case IMAGE_SCN_ALIGN_8192BYTES:     pMod->aSegments[i + 1].Alignment = 8192; break;
+            default: kHlpAssert(0);          pMod->aSegments[i + 1].Alignment = 0; break;
+        }
+    }
+
+#elif K_OS == K_OS_DARWIN
+    /** @todo Figure out the Mac OS X dynamic loader. */
+
+#else
+# error "Port me"
+#endif
+
+    /*
+     * We're done.
+     */
+    pMod->u32Magic = KLDRMOD_MAGIC;
+    pMod->pOps = &g_kLdrModNativeOps;
+    *ppMod = pMod;
+    return 0;
+}
+
+
+/** @copydoc KLDRMODOPS::pfnDestroy */
+static int kldrModNativeDestroy(PKLDRMOD pMod)
+{
+    PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
+    int rc;
+
+#if K_OS == K_OS_OS2
+    rc = DosFreeModule(pModNative->hmod);
+
+#elif K_OS == K_OS_WINDOWS
+    if (FreeLibrary(pModNative->hmod))
+        rc = 0;
+    else
+        rc = GetLastError();
+
+#elif K_OS == K_OS_DARWIN
+    dlclose(pModNative->pvMod);
+
+#else
+# error "Port me"
+#endif
+
+    pMod->u32Magic = 0;
+    pMod->pOps = NULL;
+    kHlpFree(pModNative);
+    return rc;
+}
+
+
+/** @copydoc kLdrModQuerySymbol */
+static int kldrModNativeQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 iSymbol,
+                                    const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion,
+                                    PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind)
+{
+    PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
+    const char *pszSymbol = pchSymbol;
+#if K_OS == K_OS_OS2
+    APIRET rc;
+    PFN pfn;
+#elif K_OS == K_OS_WINDOWS
+    FARPROC pfn;
+#elif K_OS == K_OS_DARWIN
+    void *pfn;
+#else
+# error "Port me"
+#endif
+
+    /* make stack copy of the symbol if it isn't zero terminated. */
+    if (pszSymbol && pszSymbol[cchSymbol])
+    {
+        char *pszCopy = kHlpAllocA(cchSymbol + 1);
+        kHlpMemCopy(pszCopy, pchSymbol, cchSymbol);
+        pszCopy[cchSymbol] = '\0';
+        pszSymbol = pszCopy;
+    }
+
+#if K_OS == K_OS_OS2
+    if (!pchSymbol && iSymbol >= 0x10000)
+        return KLDR_ERR_SYMBOL_NOT_FOUND;
+
+    if (puValue)
+    {
+        rc = DosQueryProcAddr(pModNative->hmod,
+                              pszSymbol ? 0 : iSymbol,
+                              (PCSZ)pszSymbol,
+                              &pfn);
+        if (rc)
+            return rc == ERROR_PROC_NOT_FOUND ? KLDR_ERR_SYMBOL_NOT_FOUND : rc;
+        *puValue = (KUPTR)pfn;
+    }
+    if (pfKind)
+    {
+        ULONG ulProcType;
+        rc = DosQueryProcType(pModNative->hmod,
+                              pszSymbol ? 0 : iSymbol,
+                              (PCSZ)pszSymbol,
+                              &ulProcType);
+        if (rc)
+        {
+            if (puValue)
+                *puValue = 0;
+            return rc == ERROR_PROC_NOT_FOUND ? KLDR_ERR_SYMBOL_NOT_FOUND : rc;
+        }
+        *pfKind = (ulProcType & PT_32BIT ? KLDRSYMKIND_32BIT : KLDRSYMKIND_16BIT)
+                | KLDRSYMKIND_NO_TYPE;
+    }
+
+#elif K_OS == K_OS_WINDOWS
+    if (!pszSymbol && iSymbol >= 0x10000)
+        return KLDR_ERR_SYMBOL_NOT_FOUND;
+
+    pfn = GetProcAddress(pModNative->hmod, pszSymbol ? pszSymbol : (const char *)(KUPTR)iSymbol);
+    if (puValue)
+        *puValue = (KUPTR)pfn;
+    if (pfKind)
+        *pfKind = (pModNative->pNtHdrs->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)
+                   ? KLDRSYMKIND_32BIT : KLDRSYMKIND_16BIT)
+                | KLDRSYMKIND_NO_TYPE;
+
+#elif K_OS == K_OS_DARWIN
+    if (!pszSymbol && iSymbol != NIL_KLDRMOD_SYM_ORDINAL)
+        return KLDR_ERR_SYMBOL_NOT_FOUND;
+
+    pfn = dlsym(pModNative->pvMod, pszSymbol);
+    if (!pfn)
+        return KLDR_ERR_SYMBOL_NOT_FOUND;
+    if (puValue)
+        *puValue = (KUPTR)pfn;
+    if (pfKind)
+        *pfKind = (sizeof(KUPTR) == 4 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT)
+                | KLDRSYMKIND_NO_TYPE;
+
+#else
+# error "Port me"
+#endif
+
+    return 0;
+}
+
+
+/** @copydoc kLdrModEnumSymbols */
+static int kldrModNativeEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress,
+                                    KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
+{
+    PKLDRMODNATIVE                  pModNative = (PKLDRMODNATIVE)pMod->pvData;
+#if K_OS == K_OS_OS2
+
+    /** @todo implement export enumeration on OS/2. */
+    (void)pModNative;
+    return ERROR_NOT_SUPPORTED;
+
+#elif K_OS == K_OS_WINDOWS || defined(__NT__)
+    const KU32                     *paFunctions;
+    const IMAGE_EXPORT_DIRECTORY   *pExpDir;
+    const KU32                     *paRVANames;
+    const KU16                     *paOrdinals;
+    KU32                            iFunction;
+    KU32                            cFunctions;
+    KU32                            cNames;
+    int                             rc;
+
+    /*
+     * Make sure we've got mapped bits and resolve any base address aliases.
+     */
+    if (    pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size
+        <   sizeof(IMAGE_EXPORT_DIRECTORY))
+        return 0; /* no exports to enumerate, return success. */
+
+    pExpDir = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
+                                     pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,
+                                     PIMAGE_EXPORT_DIRECTORY);
+
+    /*
+     * Enumerate the ordinal exports.
+     */
+    paRVANames = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pExpDir->AddressOfNames, const KU32 *);
+    paOrdinals = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pExpDir->AddressOfNameOrdinals, const KU16 *);
+    paFunctions = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pExpDir->AddressOfFunctions, const KU32 *);
+    cFunctions = pExpDir->NumberOfFunctions;
+    cNames = pExpDir->NumberOfNames;
+    for (iFunction = 0; iFunction < cFunctions; iFunction++)
+    {
+        unsigned        fFoundName;
+        KU32            iName;
+        const KU32      uRVA = paFunctions[iFunction];
+        const KLDRADDR  uValue = BaseAddress + uRVA;
+        KU32            fKind = (pModNative->pNtHdrs->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)
+                              ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT)
+                              | KLDRSYMKIND_NO_TYPE;
+        if (    uRVA - pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
+            <   pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)
+            fKind |= KLDRSYMKIND_FORWARDER;
+
+        /*
+         * Any symbol names?
+         */
+        fFoundName = 0;
+        for (iName = 0; iName < cNames; iName++)
+        {
+            const char *pszName;
+            if (paOrdinals[iName] != iFunction)
+                continue;
+            fFoundName = 1;
+
+            pszName = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, paRVANames[iName], const char *);
+            rc = pfnCallback(pMod, iFunction + pExpDir->Base, pszName, strlen(pszName), NULL,
+                             uValue, fKind, pvUser);
+            if (rc)
+                return rc;
+        }
+
+        /*
+         * If no names, call once with the ordinal only.
+         */
+        if (!fFoundName)
+        {
+            rc = pfnCallback(pMod, iFunction + pExpDir->Base, NULL, 0, NULL, uValue, fKind, pvUser);
+            if (rc)
+                return rc;
+        }
+    }
+    return 0;
+
+#elif K_OS == K_OS_DARWIN
+    /** @todo implement enumeration on darwin. */
+    (void)pModNative;
+    return KLDR_ERR_TODO;
+
+#else
+# error "Port me"
+#endif
+
+}
+
+
+/** @copydoc kLdrModGetImport */
+static int kldrModNativeGetImport(PKLDRMOD pMod, const void *pvBits, KU32 iImport, char *pszName, KSIZE cchName)
+{
+    PKLDRMODNATIVE                  pModNative = (PKLDRMODNATIVE)pMod->pvData;
+#if K_OS == K_OS_OS2
+
+    /** @todo implement import enumeration on OS/2. */
+    (void)pModNative;
+    return ERROR_NOT_SUPPORTED;
+
+#elif K_OS == K_OS_WINDOWS || defined(__NT__)
+    const IMAGE_IMPORT_DESCRIPTOR  *pImpDesc;
+    const char                     *pszImportName;
+    KSIZE                           cchImportName;
+    int                             rc;
+
+    /*
+     * Simple bounds check.
+     */
+    if (iImport >= (KU32)kldrModNativeNumberOfImports(pMod, pvBits))
+        return KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS;
+
+    /*
+     * Get the name.
+     */
+    pImpDesc = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
+                                      pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
+                                      + sizeof(IMAGE_IMPORT_DESCRIPTOR) * iImport,
+                                      const IMAGE_IMPORT_DESCRIPTOR *);
+    pszImportName = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pImpDesc->Name, const char *);
+    cchImportName = kHlpStrLen(pszImportName);
+    if (cchImportName < cchName)
+    {
+        kHlpMemCopy(pszName, pszImportName, cchImportName + 1);
+        rc = 0;
+    }
+    else
+    {
+        kHlpMemCopy(pszName, pszImportName, cchName);
+        if (cchName)
+            pszName[cchName - 1] = '\0';
+        rc = KERR_BUFFER_OVERFLOW;
+    }
+
+    return rc;
+
+#elif K_OS == K_OS_DARWIN
+    /** @todo Implement import enumeration on darwin. */
+    (void)pModNative;
+    return KLDR_ERR_TODO;
+
+#else
+# error "Port me"
+#endif
+}
+
+
+/** @copydoc kLdrModNumberOfImports */
+static KI32 kldrModNativeNumberOfImports(PKLDRMOD pMod, const void *pvBits)
+{
+    PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
+#if K_OS == K_OS_OS2
+
+    /** @todo implement import counting on OS/2. */
+    (void)pModNative;
+    return -1;
+
+#elif K_OS == K_OS_WINDOWS || defined(__NT__)
+    if (pModNative->cImportModules == ~(KU32)0)
+    {
+        /*
+         * We'll have to walk the import descriptors to figure out their number.
+         */
+        pModNative->cImportModules = 0;
+        if (    pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
+            &&  pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
+        {
+            const IMAGE_IMPORT_DESCRIPTOR  *pImpDesc;
+
+            pImpDesc = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
+                                              pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
+                                              const IMAGE_IMPORT_DESCRIPTOR *);
+            while (pImpDesc->Name && pImpDesc->FirstThunk)
+            {
+                pModNative->cImportModules++;
+                pImpDesc++;
+            }
+        }
+    }
+    return pModNative->cImportModules;
+
+#elif K_OS == K_OS_DARWIN
+    /** @todo Implement import counting on Darwin. */
+    (void)pModNative;
+    return -1;
+
+#else
+# error "Port me"
+#endif
+}
+
+
+/** @copydoc kLdrModGetStackInfo */
+static int kldrModNativeGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo)
+{
+    PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
+#if K_OS == K_OS_OS2
+
+    /** @todo implement stack info on OS/2. */
+    (void)pModNative;
+    return ERROR_NOT_SUPPORTED;
+
+#elif K_OS == K_OS_WINDOWS || defined(__NT__)
+    pStackInfo->Address = NIL_KLDRADDR;
+    pStackInfo->LinkAddress = NIL_KLDRADDR;
+    pStackInfo->cbStack = pStackInfo->cbStackThread = pModNative->pNtHdrs->OptionalHeader.SizeOfStackReserve;
+
+    return 0;
+
+#elif K_OS == K_OS_DARWIN
+    /** @todo Implement stack info on Darwin. */
+    (void)pModNative;
+    return KLDR_ERR_TODO;
+
+#else
+# error "Port me"
+#endif
+}
+
+
+/** @copydoc kLdrModQueryMainEntrypoint */
+static int kldrModNativeQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress)
+{
+    PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
+#if K_OS == K_OS_OS2
+
+    /** @todo implement me on OS/2. */
+    (void)pModNative;
+    return ERROR_NOT_SUPPORTED;
+
+#elif K_OS == K_OS_WINDOWS || defined(__NT__)
+    /*
+     * Convert the address from the header.
+     */
+    *pMainEPAddress = pModNative->pNtHdrs->OptionalHeader.AddressOfEntryPoint
+        ? BaseAddress + pModNative->pNtHdrs->OptionalHeader.AddressOfEntryPoint
+        : NIL_KLDRADDR;
+    return 0;
+
+#elif K_OS == K_OS_DARWIN
+    /** @todo Implement me on Darwin. */
+    (void)pModNative;
+    return KLDR_ERR_TODO;
+
+#else
+# error "Port me"
+#endif
+}
+
+
+/** @copydoc kLdrModEnumDbgInfo */
+static int kldrModNativeEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser)
+{
+    PKLDRMODNATIVE                  pModNative = (PKLDRMODNATIVE)pMod->pvData;
+#if K_OS == K_OS_OS2
+
+    /** @todo implement me on OS/2. */
+    (void)pModNative;
+    return ERROR_NOT_SUPPORTED;
+
+#elif K_OS == K_OS_WINDOWS || defined(__NT__)
+    const IMAGE_DEBUG_DIRECTORY    *pDbgDir;
+    KU32                            iDbgInfo;
+    KU32                            cb;
+    int                             rc;
+
+    /*
+     * Check that there is a debug directory first.
+     */
+    cb = pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+    if (    cb < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */
+        ||  !pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)
+        return 0;
+
+    /*
+     * Enumerate the debug directory.
+     */
+    pDbgDir = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
+                                     pModNative->pNtHdrs->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, NULL /*pszPartNm*/,
+                         pDbgDir->PointerToRawData ? pDbgDir->PointerToRawData : -1,
+                         pDbgDir->AddressOfRawData ? pDbgDir->AddressOfRawData : NIL_KLDRADDR,
+                         pDbgDir->SizeOfData,
+                         NULL /*pszExtFile*/, pvUser);
+        if (rc)
+            break;
+
+        /* next */
+        if (cb <= sizeof(IMAGE_DEBUG_DIRECTORY))
+            break;
+    }
+
+    return rc;
+
+#elif K_OS == K_OS_DARWIN
+    /** @todo Implement me on Darwin. */
+    (void)pModNative;
+    return KLDR_ERR_TODO;
+
+#else
+# error "Port me"
+#endif
+}
+
+
+/** @copydoc kLdrModHasDbgInfo */
+static int kldrModNativeHasDbgInfo(PKLDRMOD pMod, const void *pvBits)
+{
+    PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
+#if K_OS == K_OS_OS2
+
+    /** @todo implement me on OS/2. */
+    (void)pModNative;
+    return KLDR_ERR_NO_DEBUG_INFO;
+
+#elif K_OS == K_OS_WINDOWS || defined(__NT__)
+    /*
+     * Base this entirely on the presence of a debug directory.
+     */
+    if (    pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size
+            < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */
+        ||  !pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)
+        return KLDR_ERR_NO_DEBUG_INFO;
+    return 0;
+
+#elif K_OS == K_OS_DARWIN
+    /** @todo Implement me on Darwin. */
+    (void)pModNative;
+    return KLDR_ERR_NO_DEBUG_INFO;
+
+#else
+# error "Port me"
+#endif
+}
+
+
+/** @copydoc kLdrModMap */
+static int kldrModNativeMap(PKLDRMOD pMod)
+{
+    return 0;
+}
+
+
+/** @copydoc kLdrModUnmap */
+static int kldrModNativeUnmap(PKLDRMOD pMod)
+{
+    return 0;
+}
+
+
+/** @copydoc kLdrModAllocTLS */
+static int kldrModNativeAllocTLS(PKLDRMOD pMod, void *pvMapping)
+{
+    return 0;
+}
+
+
+/** @copydoc kLdrModFreeTLS */
+static void kldrModNativeFreeTLS(PKLDRMOD pMod, void *pvMapping)
+{
+}
+
+
+/** @copydoc kLdrModReload */
+static int kldrModNativeReload(PKLDRMOD pMod)
+{
+    return 0;
+}
+
+
+/** @copydoc kLdrModFixupMapping */
+static int kldrModNativeFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    return 0;
+}
+
+
+/** @copydoc kLdrModCallInit */
+static int kldrModNativeCallInit(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle)
+{
+    return 0;
+}
+
+
+/** @copydoc kLdrModCallTerm */
+static int kldrModNativeCallTerm(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle)
+{
+    return 0;
+}
+
+
+/** @copydoc kLdrModCallThread */
+static int kldrModNativeCallThread(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle, unsigned fAttachingOrDetaching)
+{
+    return 0;
+}
+
+
+/** @copydoc kLdrModSize */
+static KLDRADDR kldrModNativeSize(PKLDRMOD pMod)
+{
+#if K_OS == K_OS_OS2
+    return 0; /* don't bother */
+
+#elif K_OS == K_OS_WINDOWS || defined(__NT__)
+    /* just because we can. */
+    PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
+    return pModNative->pNtHdrs->OptionalHeader.SizeOfImage;
+
+#elif K_OS == K_OS_DARWIN
+    /** @todo Implement me on Darwin. */
+    return 0;
+
+#else
+# error "Port me"
+#endif
+}
+
+
+/** @copydoc kLdrModGetBits */
+static int kldrModNativeGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+#if K_OS == K_OS_OS2
+    return ERROR_NOT_SUPPORTED; /* don't bother */
+
+#elif K_OS == K_OS_WINDOWS || defined(__NT__)
+    return ERROR_NOT_SUPPORTED; /* don't bother even if we could implement this. */
+
+#elif K_OS == K_OS_DARWIN
+    return KLDR_ERR_TODO; /* don't bother. */
+
+#else
+# error "Port me"
+#endif
+}
+
+
+/** @copydoc kLdrModRelocateBits */
+static int kldrModNativeRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
+                                     PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+#if K_OS == K_OS_OS2
+    return ERROR_NOT_SUPPORTED; /* don't bother */
+
+#elif K_OS == K_OS_WINDOWS || defined(__NT__)
+    return ERROR_NOT_SUPPORTED; /* don't bother even if we could implement this. */
+
+#elif K_OS == K_OS_DARWIN
+    return KLDR_ERR_TODO; /* don't bother. */
+
+#else
+# error "Port me"
+#endif
+}
+
+
+/**
+ * The native module interpreter method table.
+ */
+KLDRMODOPS g_kLdrModNativeOps =
+{
+    "Native",
+    NULL,
+    kldrModNativeCreate,
+    kldrModNativeDestroy,
+    kldrModNativeQuerySymbol,
+    kldrModNativeEnumSymbols,
+    kldrModNativeGetImport,
+    kldrModNativeNumberOfImports,
+    NULL /* can execute one is optional */,
+    kldrModNativeGetStackInfo,
+    kldrModNativeQueryMainEntrypoint,
+    NULL /* pfnQueryImageUuid */,
+    NULL /* fixme */,
+    NULL /* fixme */,
+    kldrModNativeEnumDbgInfo,
+    kldrModNativeHasDbgInfo,
+    kldrModNativeMap,
+    kldrModNativeUnmap,
+    kldrModNativeAllocTLS,
+    kldrModNativeFreeTLS,
+    kldrModNativeReload,
+    kldrModNativeFixupMapping,
+    kldrModNativeCallInit,
+    kldrModNativeCallTerm,
+    kldrModNativeCallThread,
+    kldrModNativeSize,
+    kldrModNativeGetBits,
+    kldrModNativeRelocateBits,
+    NULL /* fixme */,
+    42 /* the end */
+};
+
diff --git a/src/lib/kStuff/kLdr/kLdrModPE.c b/src/lib/kStuff/kLdr/kLdrModPE.c
new file mode 100644
index 0000000..1379572
--- /dev/null
+++ b/src/lib/kStuff/kLdr/kLdrModPE.c
@@ -0,0 +1,2044 @@
+/* $Id: kLdrModPE.c 85 2016-09-06 03:21:04Z bird $ */
+/** @file
+ * kLdr - The Module Interpreter for the Portable Executable (PE) Format.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kLdr.h>
+#include "kLdrInternal.h"
+#include <k/kLdrFmts/pe.h>
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** @def KLDRMODPE_STRICT
+ * Define KLDRMODPE_STRICT to enabled strict checks in KLDRMODPE. */
+#define KLDRMODPE_STRICT 1
+
+/** @def KLDRMODPE_ASSERT
+ * Assert that an expression is true when KLDR_STRICT is defined.
+ */
+#ifdef KLDRMODPE_STRICT
+# define KLDRMODPE_ASSERT(expr)  kHlpAssert(expr)
+#else
+# define KLDRMODPE_ASSERT(expr)  do {} while (0)
+#endif
+
+/** @def KLDRMODPE_RVA2TYPE
+ * Converts a RVA to a pointer of the specified type.
+ * @param   pvBits      The bits (image base).
+ * @param   uRVA        The image relative virtual address.
+ * @param   type        The type to cast to.
+ */
+#define KLDRMODPE_RVA2TYPE(pvBits, uRVA, type) \
+        ( (type) ((KUPTR)(pvBits) + (KUPTR)(uRVA)) )
+
+/** @def KLDRMODPE_VALID_RVA
+ * Checks that the specified RVA value is non-zero and within the bounds of the image.
+ * @returns true/false.
+ * @param   pModPE      The PE module interpreter instance.
+ * @param   uRVA        The RVA to validate.
+ */
+#define KLDRMODPE_VALID_RVA(pModPE, uRVA) \
+        ( (uRVA) && (uRVA) < (pModPE)->Hdrs.OptionalHeader.SizeOfImage )
+
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Instance data for the PE module interpreter.
+ */
+typedef struct KLDRMODPE
+{
+    /** Pointer to the module. (Follows the section table.) */
+    PKLDRMOD                pMod;
+    /** Pointer to the RDR mapping of the raw file bits. NULL if not mapped. */
+    const void             *pvBits;
+    /** Pointer to the user mapping. */
+    const void             *pvMapping;
+    /** Reserved flags. */
+    KU32                    f32Reserved;
+    /** The number of imported modules.
+     * If ~(KU32)0 this hasn't been determined yet. */
+    KU32                    cImportModules;
+    /** The offset of the NT headers. */
+    KLDRFOFF                offHdrs;
+    /** Copy of the NT headers. */
+    IMAGE_NT_HEADERS64      Hdrs;
+    /** The section header table . */
+    IMAGE_SECTION_HEADER    aShdrs[1];
+} KLDRMODPE, *PKLDRMODPE;
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static KI32 kldrModPENumberOfImports(PKLDRMOD pMod, const void *pvBits);
+static int  kldrModPERelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
+                                  PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
+
+static int  kldrModPEDoCreate(PKRDR pRdr, KLDRFOFF offNewHdr, PKLDRMODPE *ppMod);
+/*static void kldrModPEDoLoadConfigConversion(PIMAGE_LOAD_CONFIG_DIRECTORY64 pLoadCfg); */
+static int  kLdrModPEDoOptionalHeaderValidation(PKLDRMODPE pModPE);
+static int  kLdrModPEDoSectionHeadersValidation(PKLDRMODPE pModPE);
+static void kldrModPEDoOptionalHeaderConversion(PIMAGE_OPTIONAL_HEADER64 pOptionalHeader);
+static int  kldrModPEDoForwarderQuery(PKLDRMODPE pModPE, const void *pvBits, const char *pszForwarder,
+                                     PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser, PKLDRADDR puValue, KU32 *pfKind);
+static int  kldrModPEDoFixups(PKLDRMODPE pModPE, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress);
+static int  kldrModPEDoImports32Bit(PKLDRMODPE pModPE, void *pvMapping, const IMAGE_IMPORT_DESCRIPTOR *pImpDesc,
+                                    PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
+static int  kldrModPEDoImports64Bit(PKLDRMODPE pModPE, void *pvMapping, const IMAGE_IMPORT_DESCRIPTOR *pImpDesc,
+                                    PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
+static int  kldrModPEDoImports(PKLDRMODPE pModPE, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
+static int  kldrModPEDoCallDLL(PKLDRMODPE pModPE, void *pvMapping, unsigned uOp, KUPTR uHandle);
+static int  kldrModPEDoCallTLS(PKLDRMODPE pModPE, void *pvMapping, unsigned uOp, KUPTR uHandle);
+static KI32 kldrModPEDoCall(KUPTR uEntrypoint, KUPTR uHandle, KU32 uOp, void *pvReserved);
+
+
+/**
+ * Create a loader module instance interpreting the executable image found
+ * in the specified file provider instance.
+ *
+ * @returns 0 on success and *ppMod pointing to a module instance.
+ *          On failure, a non-zero OS specific error code is returned.
+ * @param   pOps            Pointer to the registered method table.
+ * @param   pRdr            The file provider instance to use.
+ * @param   fFlags          Flags, MBZ.
+ * @param   enmCpuArch      The desired CPU architecture. KCPUARCH_UNKNOWN means
+ *                          anything goes, but with a preference for the current
+ *                          host architecture.
+ * @param   offNewHdr       The offset of the new header in MZ files. -1 if not found.
+ * @param   ppMod           Where to store the module instance pointer.
+ */
+static int kldrModPECreate(PCKLDRMODOPS pOps, PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch, KLDRFOFF offNewHdr, PPKLDRMOD ppMod)
+{
+    PKLDRMODPE pModPE;
+    int rc;
+    K_NOREF(fFlags);
+
+    /*
+     * Create the instance data and do a minimal header validation.
+     */
+    rc = kldrModPEDoCreate(pRdr, offNewHdr, &pModPE);
+    if (!rc)
+    {
+        /*
+         * Match up against the requested CPU architecture.
+         */
+        if (    enmCpuArch == KCPUARCH_UNKNOWN
+            ||  pModPE->pMod->enmArch == enmCpuArch)
+        {
+            pModPE->pMod->pOps = pOps;
+            pModPE->pMod->u32Magic = KLDRMOD_MAGIC;
+            *ppMod = pModPE->pMod;
+            return 0;
+        }
+        rc = KLDR_ERR_CPU_ARCH_MISMATCH;
+    }
+    kHlpFree(pModPE);
+    return rc;
+}
+
+
+/**
+ * Separate function for reading creating the PE module instance to
+ * simplify cleanup on failure.
+ */
+static int kldrModPEDoCreate(PKRDR pRdr, KLDRFOFF offNewHdr, PKLDRMODPE *ppModPE)
+{
+    struct
+    {
+        KU32                Signature;
+        IMAGE_FILE_HEADER   FileHdr;
+    } s;
+    PKLDRMODPE pModPE;
+    PKLDRMOD pMod;
+    KSIZE cb;
+    KSIZE cchFilename;
+    KLDRFOFF off;
+    KU32 i;
+    int rc;
+    *ppModPE = NULL;
+
+    /*
+     * Read the signature and file header.
+     */
+    rc = kRdrRead(pRdr, &s, sizeof(s), offNewHdr > 0 ? offNewHdr : 0);
+    if (rc)
+        return rc;
+    if (s.Signature != IMAGE_NT_SIGNATURE)
+        return KLDR_ERR_UNKNOWN_FORMAT;
+
+    /* sanity checks. */
+    if (    s.FileHdr.NumberOfSections > 4096
+        ||  (   s.FileHdr.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER32)
+             && s.FileHdr.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER64))
+        ||  !(s.FileHdr.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)
+       )
+        return KLDR_ERR_PE_BAD_FILE_HEADER;
+    if (    s.FileHdr.Machine != IMAGE_FILE_MACHINE_I386
+        &&  s.FileHdr.Machine != IMAGE_FILE_MACHINE_AMD64
+       )
+        return KLDR_ERR_PE_UNSUPPORTED_MACHINE;
+
+    /*
+     * Calc the instance size, allocate and initialize it.
+     */
+    cchFilename = kHlpStrLen(kRdrName(pRdr));
+    cb = K_ALIGN_Z(K_OFFSETOF(KLDRMODPE, aShdrs[s.FileHdr.NumberOfSections]), 16)
+       + K_OFFSETOF(KLDRMOD, aSegments[s.FileHdr.NumberOfSections + 1])
+       + cchFilename + 1;
+    pModPE = (PKLDRMODPE)kHlpAlloc(cb);
+    if (!pModPE)
+        return KERR_NO_MEMORY;
+    *ppModPE = pModPE;
+
+    /* KLDRMOD */
+    pMod = (PKLDRMOD)((KU8 *)pModPE + K_ALIGN_Z(K_OFFSETOF(KLDRMODPE, aShdrs[s.FileHdr.NumberOfSections]), 16));
+    pMod->pvData = pModPE;
+    pMod->pRdr = pRdr;
+    pMod->pOps = NULL;      /* set upon success. */
+    pMod->cSegments = s.FileHdr.NumberOfSections + 1;
+    pMod->cchFilename = cchFilename;
+    pMod->pszFilename = (char *)&pMod->aSegments[pMod->cSegments];
+    kHlpMemCopy((char *)pMod->pszFilename, kRdrName(pRdr), cchFilename + 1);
+    pMod->pszName = kHlpGetFilename(pMod->pszFilename);
+    pMod->cchName = cchFilename - (pMod->pszName - pMod->pszFilename);
+    pMod->fFlags = 0;
+    switch (s.FileHdr.Machine)
+    {
+        case IMAGE_FILE_MACHINE_I386:
+            pMod->enmCpu = KCPU_I386;
+            pMod->enmArch = KCPUARCH_X86_32;
+            pMod->enmEndian = KLDRENDIAN_LITTLE;
+            break;
+
+        case IMAGE_FILE_MACHINE_AMD64:
+            pMod->enmCpu = KCPU_K8;
+            pMod->enmArch = KCPUARCH_AMD64;
+            pMod->enmEndian = KLDRENDIAN_LITTLE;
+            break;
+        default:
+            kHlpAssert(0);
+            break;
+    }
+    pMod->enmFmt = KLDRFMT_PE;
+    if (s.FileHdr.Characteristics & IMAGE_FILE_DLL)
+        pMod->enmType = !(s.FileHdr.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
+            ? KLDRTYPE_SHARED_LIBRARY_RELOCATABLE
+            : KLDRTYPE_SHARED_LIBRARY_FIXED;
+    else
+        pMod->enmType = !(s.FileHdr.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
+            ? KLDRTYPE_EXECUTABLE_RELOCATABLE
+            : KLDRTYPE_EXECUTABLE_FIXED;
+    pMod->u32Magic = 0;     /* set upon success. */
+
+    /* KLDRMODPE */
+    pModPE->pMod = pMod;
+    pModPE->pvBits = NULL;
+    pModPE->pvMapping = NULL;
+    pModPE->f32Reserved = 0;
+    pModPE->cImportModules = ~(KU32)0;
+    pModPE->offHdrs = offNewHdr >= 0 ? offNewHdr : 0;
+    pModPE->Hdrs.Signature = s.Signature;
+    pModPE->Hdrs.FileHeader = s.FileHdr;
+
+    /*
+     * Read the optional header and the section table.
+     */
+    off = pModPE->offHdrs + sizeof(pModPE->Hdrs.Signature) + sizeof(pModPE->Hdrs.FileHeader);
+    rc = kRdrRead(pRdr, &pModPE->Hdrs.OptionalHeader, pModPE->Hdrs.FileHeader.SizeOfOptionalHeader, off);
+    if (rc)
+        return rc;
+    if (pModPE->Hdrs.FileHeader.SizeOfOptionalHeader != sizeof(pModPE->Hdrs.OptionalHeader))
+        kldrModPEDoOptionalHeaderConversion(&pModPE->Hdrs.OptionalHeader);
+    off += pModPE->Hdrs.FileHeader.SizeOfOptionalHeader;
+    rc = kRdrRead(pRdr, &pModPE->aShdrs[0], sizeof(IMAGE_SECTION_HEADER) * pModPE->Hdrs.FileHeader.NumberOfSections, off);
+    if (rc)
+        return rc;
+
+    /*
+     * Validate the two.
+     */
+    rc = kLdrModPEDoOptionalHeaderValidation(pModPE);
+    if (rc)
+        return rc;
+    for (i = 0; i < pModPE->Hdrs.FileHeader.NumberOfSections; i++)
+    {
+        rc = kLdrModPEDoSectionHeadersValidation(pModPE);
+        if (rc)
+            return rc;
+    }
+
+    /*
+     * Setup the KLDRMOD segment array.
+     */
+    /* The implied headers section. */
+    pMod->aSegments[0].pvUser = NULL;
+    pMod->aSegments[0].pchName = "TheHeaders";
+    pMod->aSegments[0].cchName = sizeof("TheHeaders") - 1;
+    pMod->aSegments[0].enmProt = KPROT_READONLY;
+    pMod->aSegments[0].cb = pModPE->Hdrs.OptionalHeader.SizeOfHeaders;
+    pMod->aSegments[0].Alignment = pModPE->Hdrs.OptionalHeader.SectionAlignment;
+    pMod->aSegments[0].LinkAddress = pModPE->Hdrs.OptionalHeader.ImageBase;
+    pMod->aSegments[0].offFile = 0;
+    pMod->aSegments[0].cbFile = pModPE->Hdrs.OptionalHeader.SizeOfHeaders;
+    pMod->aSegments[0].RVA = 0;
+    if (pMod->cSegments > 1)
+        pMod->aSegments[0].cbMapped = pModPE->aShdrs[0].VirtualAddress;
+    else
+        pMod->aSegments[0].cbMapped = pModPE->Hdrs.OptionalHeader.SizeOfHeaders;
+    pMod->aSegments[0].MapAddress = 0;
+
+    /* The section headers. */
+    for (i = 0; i < pModPE->Hdrs.FileHeader.NumberOfSections; i++)
+    {
+        const char *pch;
+
+        /* unused */
+        pMod->aSegments[i + 1].pvUser = NULL;
+        pMod->aSegments[i + 1].MapAddress = 0;
+        pMod->aSegments[i + 1].SelFlat = 0;
+        pMod->aSegments[i + 1].Sel16bit = 0;
+        pMod->aSegments[i + 1].fFlags = 0;
+
+        /* name */
+        pMod->aSegments[i + 1].pchName = pch = (const char *)&pModPE->aShdrs[i].Name[0];
+        cb = IMAGE_SIZEOF_SHORT_NAME;
+        while (   cb > 0
+               && (pch[cb - 1] == ' ' || pch[cb - 1] == '\0'))
+            cb--;
+        pMod->aSegments[i + 1].cchName = cb;
+
+        /* size and addresses */
+        if (!(pModPE->aShdrs[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+        {
+            /* Kluge to deal with wlink ".reloc" sections that has a VirtualSize of 0 bytes. */
+            KU32 cb = pModPE->aShdrs[i].Misc.VirtualSize;
+            if (!cb)
+                cb = K_ALIGN_Z(pModPE->aShdrs[i].SizeOfRawData, pModPE->Hdrs.OptionalHeader.SectionAlignment);
+            pMod->aSegments[i + 1].cb          = pModPE->aShdrs[i].Misc.VirtualSize;
+            pMod->aSegments[i + 1].LinkAddress = pModPE->aShdrs[i].VirtualAddress
+                                               + pModPE->Hdrs.OptionalHeader.ImageBase;
+            pMod->aSegments[i + 1].RVA         = pModPE->aShdrs[i].VirtualAddress;
+            pMod->aSegments[i + 1].cbMapped    = cb;
+            if (i + 2 < pMod->cSegments)
+                pMod->aSegments[i + 1].cbMapped= pModPE->aShdrs[i + 1].VirtualAddress
+                                               - pModPE->aShdrs[i].VirtualAddress;
+        }
+        else
+        {
+            pMod->aSegments[i + 1].cb          = 0;
+            pMod->aSegments[i + 1].cbMapped    = 0;
+            pMod->aSegments[i + 1].LinkAddress = NIL_KLDRADDR;
+            pMod->aSegments[i + 1].RVA         = 0;
+        }
+
+        /* file location */
+        pMod->aSegments[i + 1].offFile = pModPE->aShdrs[i].PointerToRawData;
+        pMod->aSegments[i + 1].cbFile  = pModPE->aShdrs[i].SizeOfRawData;
+        if (    pMod->aSegments[i + 1].cbMapped > 0 /* if mapped */
+            &&  (KLDRSIZE)pMod->aSegments[i + 1].cbFile > pMod->aSegments[i + 1].cbMapped)
+            pMod->aSegments[i + 1].cbFile = pMod->aSegments[i + 1].cbMapped;
+
+        /* protection */
+        switch (  pModPE->aShdrs[i].Characteristics
+                & (IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE))
+        {
+            case 0:
+            case IMAGE_SCN_MEM_SHARED:
+                pMod->aSegments[i + 1].enmProt = KPROT_NOACCESS;
+                break;
+            case IMAGE_SCN_MEM_READ:
+            case IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_SHARED:
+                pMod->aSegments[i + 1].enmProt = KPROT_READONLY;
+                break;
+            case IMAGE_SCN_MEM_WRITE:
+            case IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ:
+                pMod->aSegments[i + 1].enmProt = KPROT_WRITECOPY;
+                break;
+            case IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED:
+            case IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ:
+                pMod->aSegments[i + 1].enmProt = KPROT_READWRITE;
+                break;
+            case IMAGE_SCN_MEM_EXECUTE:
+            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_SHARED:
+                pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE;
+                break;
+            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ:
+            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_SHARED:
+                pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE_READ;
+                break;
+            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE:
+            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ:
+                pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE_WRITECOPY;
+                break;
+            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED:
+            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ:
+                pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE_READWRITE;
+                break;
+        }
+
+        /* alignment. */
+        switch (pModPE->aShdrs[i].Characteristics & IMAGE_SCN_ALIGN_MASK)
+        {
+            case 0: /* hope this is right... */
+                pMod->aSegments[i + 1].Alignment = pModPE->Hdrs.OptionalHeader.SectionAlignment;
+                break;
+            case IMAGE_SCN_ALIGN_1BYTES:        pMod->aSegments[i + 1].Alignment = 1; break;
+            case IMAGE_SCN_ALIGN_2BYTES:        pMod->aSegments[i + 1].Alignment = 2; break;
+            case IMAGE_SCN_ALIGN_4BYTES:        pMod->aSegments[i + 1].Alignment = 4; break;
+            case IMAGE_SCN_ALIGN_8BYTES:        pMod->aSegments[i + 1].Alignment = 8; break;
+            case IMAGE_SCN_ALIGN_16BYTES:       pMod->aSegments[i + 1].Alignment = 16; break;
+            case IMAGE_SCN_ALIGN_32BYTES:       pMod->aSegments[i + 1].Alignment = 32; break;
+            case IMAGE_SCN_ALIGN_64BYTES:       pMod->aSegments[i + 1].Alignment = 64; break;
+            case IMAGE_SCN_ALIGN_128BYTES:      pMod->aSegments[i + 1].Alignment = 128; break;
+            case IMAGE_SCN_ALIGN_256BYTES:      pMod->aSegments[i + 1].Alignment = 256; break;
+            case IMAGE_SCN_ALIGN_512BYTES:      pMod->aSegments[i + 1].Alignment = 512; break;
+            case IMAGE_SCN_ALIGN_1024BYTES:     pMod->aSegments[i + 1].Alignment = 1024; break;
+            case IMAGE_SCN_ALIGN_2048BYTES:     pMod->aSegments[i + 1].Alignment = 2048; break;
+            case IMAGE_SCN_ALIGN_4096BYTES:     pMod->aSegments[i + 1].Alignment = 4096; break;
+            case IMAGE_SCN_ALIGN_8192BYTES:     pMod->aSegments[i + 1].Alignment = 8192; break;
+            default: kHlpAssert(0);          pMod->aSegments[i + 1].Alignment = 0; break;
+        }
+    }
+
+    /*
+     * We're done.
+     */
+    *ppModPE = pModPE;
+    return 0;
+}
+
+
+/**
+ * Converts a 32-bit optional header to a 64-bit one
+ *
+ * @param   pOptHdr     The optional header to convert.
+ */
+static void kldrModPEDoOptionalHeaderConversion(PIMAGE_OPTIONAL_HEADER64 pOptHdr)
+{
+    /* volatile everywhere! */
+    IMAGE_OPTIONAL_HEADER32 volatile *pOptHdr32 = (IMAGE_OPTIONAL_HEADER32 volatile *)pOptHdr;
+    IMAGE_OPTIONAL_HEADER64 volatile *pOptHdr64 = pOptHdr;
+    KU32 volatile                    *pu32Dst;
+    KU32 volatile                    *pu32Src;
+    KU32 volatile                    *pu32SrcLast;
+    KU32                              u32;
+
+    /* From LoaderFlags and out the difference is 4 * 32-bits. */
+    pu32Dst     = (KU32 *)&pOptHdr64->DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] - 1;
+    pu32Src     = (KU32 *)&pOptHdr32->DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] - 1;
+    pu32SrcLast = (KU32 *)&pOptHdr32->LoaderFlags;
+    while (pu32Src >= pu32SrcLast)
+        *pu32Dst-- = *pu32Src--;
+
+    /* The previous 4 fields are 32/64 and needs special attention. */
+    pOptHdr64->SizeOfHeapCommit   = pOptHdr32->SizeOfHeapCommit;
+    pOptHdr64->SizeOfHeapReserve  = pOptHdr32->SizeOfHeapReserve;
+    pOptHdr64->SizeOfStackCommit  = pOptHdr32->SizeOfStackCommit;
+    u32 = pOptHdr32->SizeOfStackReserve;
+    pOptHdr64->SizeOfStackReserve = u32;
+
+    /*
+     * The rest matches except for BaseOfData which has been merged into ImageBase in the 64-bit version.
+     * Thus, ImageBase needs some special treatement. It will probably work fine assigning one to the
+     * other since this is all declared volatile, but taking now chances, we'll use a temp variable.
+     */
+    u32 = pOptHdr32->ImageBase;
+    pOptHdr64->ImageBase = u32;
+}
+
+
+#if 0
+/**
+ * Converts a 32-bit load config directory to a 64 bit one.
+ *
+ * @param   pOptHdr     The load config to convert.
+ */
+static void kldrModPEDoLoadConfigConversion(PIMAGE_LOAD_CONFIG_DIRECTORY64 pLoadCfg)
+{
+    /* volatile everywhere! */
+    IMAGE_LOAD_CONFIG_DIRECTORY32 volatile *pLoadCfg32 = (IMAGE_LOAD_CONFIG_DIRECTORY32 volatile *)pLoadCfg;
+    IMAGE_LOAD_CONFIG_DIRECTORY64 volatile *pLoadCfg64 = pLoadCfg;
+    KU32                                    u32;
+
+    pLoadCfg64->SEHandlerCount             = pLoadCfg32->SEHandlerCount;
+    pLoadCfg64->SEHandlerTable             = pLoadCfg32->SEHandlerTable;
+    pLoadCfg64->SecurityCookie             = pLoadCfg32->SecurityCookie;
+    pLoadCfg64->EditList                   = pLoadCfg32->EditList;
+    pLoadCfg64->Reserved1                  = pLoadCfg32->Reserved1;
+    pLoadCfg64->CSDVersion                 = pLoadCfg32->CSDVersion;
+    /* (ProcessHeapFlags switched place with ProcessAffinityMask, but we're
+     * more than 16 byte off by now so it doesn't matter.) */
+    pLoadCfg64->ProcessHeapFlags           = pLoadCfg32->ProcessHeapFlags;
+    pLoadCfg64->ProcessAffinityMask        = pLoadCfg32->ProcessAffinityMask;
+    pLoadCfg64->VirtualMemoryThreshold     = pLoadCfg32->VirtualMemoryThreshold;
+    pLoadCfg64->MaximumAllocationSize      = pLoadCfg32->MaximumAllocationSize;
+    pLoadCfg64->LockPrefixTable            = pLoadCfg32->LockPrefixTable;
+    pLoadCfg64->DeCommitTotalFreeThreshold = pLoadCfg32->DeCommitTotalFreeThreshold;
+    u32 = pLoadCfg32->DeCommitFreeBlockThreshold;
+    pLoadCfg64->DeCommitFreeBlockThreshold = u32;
+    /* the remainder matches. */
+}
+#endif
+
+
+/**
+ * Internal worker which validates the section headers.
+ */
+static int kLdrModPEDoOptionalHeaderValidation(PKLDRMODPE pModPE)
+{
+    const unsigned fIs32Bit = pModPE->Hdrs.FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32);
+
+    /* the magic */
+    if (    pModPE->Hdrs.OptionalHeader.Magic
+        !=  (fIs32Bit ? IMAGE_NT_OPTIONAL_HDR32_MAGIC : IMAGE_NT_OPTIONAL_HDR64_MAGIC))
+        return KLDR_ERR_PE_BAD_OPTIONAL_HEADER;
+
+    /** @todo validate more */
+    return 0;
+}
+
+
+/**
+ * Internal worker which validates the section headers.
+ */
+static int kLdrModPEDoSectionHeadersValidation(PKLDRMODPE pModPE)
+{
+    /** @todo validate shdrs */
+    K_NOREF(pModPE);
+    return 0;
+}
+
+
+/** @copydoc KLDRMODOPS::pfnDestroy */
+static int kldrModPEDestroy(PKLDRMOD pMod)
+{
+    PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData;
+    int rc = 0;
+    KLDRMODPE_ASSERT(!pModPE->pvMapping);
+
+    if (pMod->pRdr)
+    {
+        rc = kRdrClose(pMod->pRdr);
+        pMod->pRdr = NULL;
+    }
+    pMod->u32Magic = 0;
+    pMod->pOps = NULL;
+    kHlpFree(pModPE);
+    return rc;
+}
+
+
+/**
+ * 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)
+{
+    PKLDRMOD    pMod = pModPE->pMod;
+    KBOOL       fFixed;
+    void       *pvBase;
+    int         rc;
+    KU32        i;
+
+    /*
+     * Map it.
+     */
+    /* fixed image? */
+    fFixed = fForReal
+          && (   pMod->enmType == KLDRTYPE_EXECUTABLE_FIXED
+              || pMod->enmType == KLDRTYPE_SHARED_LIBRARY_FIXED);
+    if (!fFixed)
+        pvBase = NULL;
+    else
+    {
+        pvBase = (void *)(KUPTR)pMod->aSegments[0].LinkAddress;
+        if ((KUPTR)pvBase != pMod->aSegments[0].LinkAddress)
+            return KLDR_ERR_ADDRESS_OVERFLOW;
+    }
+
+    /* try do the prepare */
+    rc = kRdrMap(pMod->pRdr, &pvBase, pMod->cSegments, pMod->aSegments, fFixed);
+    if (rc)
+        return rc;
+
+    /*
+     * Update the segments with their map addresses.
+     */
+    if (fForReal)
+    {
+        for (i = 0; i < pMod->cSegments; i++)
+        {
+            if (pMod->aSegments[i].RVA != NIL_KLDRADDR)
+                pMod->aSegments[i].MapAddress = (KUPTR)pvBase + (KUPTR)pMod->aSegments[i].RVA;
+        }
+        pModPE->pvMapping = pvBase;
+    }
+    else
+        pModPE->pvBits = pvBase;
+    return 0;
+}
+
+
+/**
+ * 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   pvMapping       The mapping to unmap.
+ */
+static int kldrModPEDoUnmap(PKLDRMODPE pModPE, const void *pvMapping)
+{
+    PKLDRMOD    pMod = pModPE->pMod;
+    int         rc;
+    KU32        i;
+
+    /*
+     * Try unmap the image.
+     */
+    rc = kRdrUnmap(pMod->pRdr, (void *)pvMapping, pMod->cSegments, pMod->aSegments);
+    if (rc)
+        return rc;
+
+    /*
+     * Update the segments to reflect that they aren't mapped any longer.
+     */
+    if (pModPE->pvMapping == pvMapping)
+    {
+        pModPE->pvMapping = NULL;
+        for (i = 0; i < pMod->cSegments; i++)
+            pMod->aSegments[i].MapAddress = 0;
+    }
+    if (pModPE->pvBits == pvMapping)
+        pModPE->pvBits = NULL;
+
+    return 0;
+}
+
+
+/**
+ * Gets usable bits and the right base address.
+ *
+ * @returns 0 on success.
+ * @returns A non-zero status code if the BaseAddress isn't right or some problem is encountered
+ *          featch in a temp mapping the bits.
+ * @param   pModPE          The interpreter module instance
+ * @param   ppvBits         The bits address, IN & OUT.
+ * @param   pBaseAddress    The base address, IN & OUT. Optional.
+ */
+static int kldrModPEBitsAndBaseAddress(PKLDRMODPE pModPE, const void **ppvBits, PKLDRADDR pBaseAddress)
+{
+    int rc = 0;
+
+    /*
+     * Correct the base address.
+     *
+     * We don't use the base address for interpreting the bits in this
+     * interpreter, which makes things relativly simple.
+     */
+    if (pBaseAddress)
+    {
+        if (*pBaseAddress == KLDRMOD_BASEADDRESS_MAP)
+            *pBaseAddress = pModPE->pMod->aSegments[0].MapAddress;
+        else if (*pBaseAddress == KLDRMOD_BASEADDRESS_LINK)
+            *pBaseAddress = pModPE->Hdrs.OptionalHeader.ImageBase;
+    }
+
+    /*
+     * Get bits.
+     */
+    if (ppvBits && !*ppvBits)
+    {
+        if (pModPE->pvMapping)
+            *ppvBits = pModPE->pvMapping;
+        else if (pModPE->pvBits)
+            *ppvBits = pModPE->pvBits;
+        else
+        {
+            /* create an internal mapping. */
+            rc = kldrModPEDoMap(pModPE, 0 /* not for real */);
+            if (rc)
+                return rc;
+            KLDRMODPE_ASSERT(pModPE->pvBits);
+            *ppvBits = pModPE->pvBits;
+        }
+    }
+
+    return 0;
+}
+
+
+/** @copydoc kLdrModQuerySymbol */
+static int kldrModPEQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 iSymbol,
+                                const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion,
+                                PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind)
+
+{
+    PKLDRMODPE                      pModPE = (PKLDRMODPE)pMod->pvData;
+    const KU32                     *paExportRVAs;
+    const IMAGE_EXPORT_DIRECTORY   *pExpDir;
+    KU32                            iExpOrd;
+    KU32                            uRVA;
+    int                             rc;
+
+    /*
+     * Make sure we've got mapped bits and resolve any base address aliases.
+     */
+    rc = kldrModPEBitsAndBaseAddress(pModPE, &pvBits, &BaseAddress);
+    if (rc)
+        return rc;
+    if (    pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size
+        <   sizeof(IMAGE_EXPORT_DIRECTORY))
+        return KLDR_ERR_SYMBOL_NOT_FOUND;
+    if (pszVersion && *pszVersion)
+        return KLDR_ERR_SYMBOL_NOT_FOUND;
+
+    pExpDir = KLDRMODPE_RVA2TYPE(pvBits,
+                                 pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,
+                                 PIMAGE_EXPORT_DIRECTORY);
+    if (!pchSymbol)
+    {
+        /*
+         * Simple, calculate the unbased ordinal and bounds check it.
+         */
+        iExpOrd = iSymbol - pExpDir->Base;
+        if (iExpOrd >= K_MAX(pExpDir->NumberOfNames, pExpDir->NumberOfFunctions))
+            return KLDR_ERR_SYMBOL_NOT_FOUND;
+    }
+    else
+    {
+        /*
+         * Do a binary search for the name.
+         * (The name table is sorted in ascending ordered by the linker.)
+         */
+        const KU32 *paRVANames = KLDRMODPE_RVA2TYPE(pvBits, pExpDir->AddressOfNames, const KU32 *);
+        const KU16 *paOrdinals = KLDRMODPE_RVA2TYPE(pvBits, pExpDir->AddressOfNameOrdinals, const KU16 *);
+        KI32        iStart = 1; /* one based binary searching is simpler. */
+        KI32        iEnd = pExpDir->NumberOfNames;
+
+        for (;;)
+        {
+            KI32        i;
+            int         diff;
+            const char *pszName;
+
+            /* done? */
+            if (iStart > iEnd)
+            {
+#ifdef KLDRMODPE_STRICT /* Make sure the linker and we both did our job right. */
+                for (i = 0; i < (KI32)pExpDir->NumberOfNames; i++)
+
+                {
+                    pszName = KLDRMODPE_RVA2TYPE(pvBits, paRVANames[i], const char *);
+                    KLDRMODPE_ASSERT(kHlpStrNComp(pszName, pchSymbol, cchSymbol) || pszName[cchSymbol]);
+                    KLDRMODPE_ASSERT(i == 0 || kHlpStrComp(pszName, KLDRMODPE_RVA2TYPE(pvBits, paRVANames[i - 1], const char *)));
+                }
+#endif
+                return KLDR_ERR_SYMBOL_NOT_FOUND;
+            }
+
+            i = (iEnd - iStart) / 2 + iStart;
+            pszName = KLDRMODPE_RVA2TYPE(pvBits, paRVANames[i - 1], const char *);
+            diff = kHlpStrNComp(pszName, pchSymbol, cchSymbol);
+            if (!diff)
+                diff = pszName[cchSymbol] - 0;
+            if (diff < 0)
+                iStart = i + 1;     /* The symbol must be after the current name. */
+            else if (diff)
+                iEnd = i - 1;       /* The symbol must be before the current name. */
+            else
+            {
+                iExpOrd = paOrdinals[i - 1];    /* match! */
+                break;
+            }
+        }
+    }
+
+    /*
+     * Lookup the address in the 'symbol' table.
+     */
+    paExportRVAs = KLDRMODPE_RVA2TYPE(pvBits, pExpDir->AddressOfFunctions, const KU32 *);
+    uRVA = paExportRVAs[iExpOrd];
+    if (    uRVA - pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
+        <   pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)
+        return kldrModPEDoForwarderQuery(pModPE, pvBits, KLDRMODPE_RVA2TYPE(pvBits, uRVA, const char *),
+                                         pfnGetForwarder, pvUser, puValue, pfKind);
+
+    /*
+     * Set the return value.
+     */
+    if (puValue)
+        *puValue = BaseAddress + uRVA;
+    if (pfKind)
+        *pfKind = (pModPE->Hdrs.FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)
+                   ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT)
+                | KLDRSYMKIND_NO_TYPE;
+    return 0;
+}
+
+
+/**
+ * Deal with a forwarder entry.
+ *
+ * We do this seprately from kldrModPEQuerySymbol because the code is clumsy (as is all PE code
+ * thanks to the descriptive field names), and because it uses quite a bit more stack and we're
+ * trying to avoid allocating stack unless we have to.
+ *
+ * @returns See kLdrModQuerySymbol.
+ * @param   pModPE          The PE module interpreter instance.
+ * @param   pvBits          Where to read the image from.
+ * @param   pszForwarder    The forwarder entry name.
+ * @param   pfnGetForwarder The callback for resolving forwarder symbols. (optional)
+ * @param   pvUser          The user argument for the callback.
+ * @param   puValue         Where to put the value. (optional)
+ * @param   pfKind          Where to put the symbol kind. (optional)
+ */
+static int kldrModPEDoForwarderQuery(PKLDRMODPE pModPE, const void *pvBits, const char *pszForwarder,
+                                     PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind)
+{
+    const IMAGE_IMPORT_DESCRIPTOR *paImpDir;
+    KU32            iImpModule;
+    KU32            cchImpModule;
+    const char     *pszSymbol;
+    KU32            iSymbol;
+    int             rc;
+
+    if (!pfnGetForwarder)
+        return KLDR_ERR_FORWARDER_SYMBOL;
+
+    /*
+     * Separate the name into a module name and a symbol name or ordinal.
+     *
+     * The module name ends at the first dot ('.').
+     * After the dot follows either a symbol name or a hash ('#') + ordinal.
+     */
+    pszSymbol = pszForwarder;
+    while (*pszSymbol != '.')
+        pszSymbol++;
+    if (!*pszSymbol)
+        return KLDR_ERR_PE_BAD_FORWARDER;
+    cchImpModule = pszSymbol - pszForwarder;
+
+    pszSymbol++;                        /* skip the dot */
+    if (!*pszSymbol)
+        return KLDR_ERR_PE_BAD_FORWARDER;
+    if (*pszSymbol == '#')
+    {
+        unsigned uBase;
+        pszSymbol++;                    /* skip the hash */
+
+        /* base detection */
+        uBase = 10;
+        if (pszSymbol[0] == '0' &&  (pszSymbol[1] == 'x' || pszSymbol[1] == 'X'))
+        {
+            uBase = 16;
+            pszSymbol += 2;
+        }
+
+        /* ascii to integer */
+        iSymbol = 0;
+        for (;;)
+        {
+            /* convert char to digit. */
+            unsigned uDigit = *pszSymbol++;
+            if (uDigit >= '0' && uDigit <= '9')
+                uDigit -= '0';
+            else if (uDigit >= 'a' && uDigit <= 'z')
+                uDigit -= 'a' + 10;
+            else if (uDigit >= 'A' && uDigit <= 'Z')
+                uDigit -= 'A' + 10;
+            else if (!uDigit)
+                break;
+            else
+                return KLDR_ERR_PE_BAD_FORWARDER;
+            if (uDigit >= uBase)
+                return KLDR_ERR_PE_BAD_FORWARDER;
+
+            /* insert the digit */
+            iSymbol *= uBase;
+            iSymbol += uDigit;
+        }
+
+        pszSymbol = NULL;               /* no symbol name. */
+    }
+    else
+        iSymbol = NIL_KLDRMOD_SYM_ORDINAL; /* no ordinal number. */
+
+
+    /*
+     * Find the import module name.
+     *
+     * We ASSUME the linker will make sure there is an import
+     * entry for the module... not sure if this is right though.
+     */
+    if (    !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
+        ||  !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
+        return KLDR_ERR_PE_FORWARDER_IMPORT_NOT_FOUND;
+    paImpDir = KLDRMODPE_RVA2TYPE(pvBits,
+                                  pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
+                                  const IMAGE_IMPORT_DESCRIPTOR *);
+
+    kldrModPENumberOfImports(pModPE->pMod, pvBits);
+    for (iImpModule = 0; iImpModule < pModPE->cImportModules; iImpModule++)
+    {
+        const char *pszName = KLDRMODPE_RVA2TYPE(pvBits, paImpDir[iImpModule].Name, const char *);
+        KSIZE       cchName = kHlpStrLen(pszName);
+        if (    (   cchName == cchImpModule
+                 || (   cchName > cchImpModule
+                     && pszName[cchImpModule] == '.'
+                     && (pszName[cchImpModule + 1] == 'd' || pszName[cchImpModule + 1] == 'D')
+                     && (pszName[cchImpModule + 2] == 'l' || pszName[cchImpModule + 2] == 'L')
+                     && (pszName[cchImpModule + 3] == 'l' || pszName[cchImpModule + 3] == 'L'))
+                )
+            &&  kHlpMemICompAscii(pszName, pszForwarder, cchImpModule)
+           )
+        {
+            /*
+             * Now the rest is up to the callback (almost).
+             */
+            rc = pfnGetForwarder(pModPE->pMod, iImpModule, iSymbol, pszSymbol,
+                                 pszSymbol ? kHlpStrLen(pszSymbol) : 0, NULL, puValue, pfKind, pvUser);
+            if (!rc && pfKind)
+                *pfKind |= KLDRSYMKIND_FORWARDER;
+            return rc;
+        }
+    }
+    return KLDR_ERR_PE_FORWARDER_IMPORT_NOT_FOUND;
+}
+
+
+/** @copydoc kLdrModEnumSymbols */
+static int kldrModPEEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress,
+                                KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
+{
+    PKLDRMODPE                      pModPE = (PKLDRMODPE)pMod->pvData;
+    const KU32                     *paFunctions;
+    const IMAGE_EXPORT_DIRECTORY   *pExpDir;
+    const KU32                     *paRVANames;
+    const KU16                     *paOrdinals;
+    KU32                            iFunction;
+    KU32                            cFunctions;
+    KU32                            cNames;
+    int                             rc;
+    K_NOREF(fFlags);
+
+    /*
+     * Make sure we've got mapped bits and resolve any base address aliases.
+     */
+    rc = kldrModPEBitsAndBaseAddress(pModPE, &pvBits, &BaseAddress);
+    if (rc)
+        return rc;
+
+    if (    pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size
+        <   sizeof(IMAGE_EXPORT_DIRECTORY))
+        return 0; /* no exports to enumerate, return success. */
+
+    pExpDir = KLDRMODPE_RVA2TYPE(pvBits,
+                                 pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,
+                                 PIMAGE_EXPORT_DIRECTORY);
+
+    /*
+     * Enumerate the ordinal exports.
+     */
+    paRVANames = KLDRMODPE_RVA2TYPE(pvBits, pExpDir->AddressOfNames, const KU32 *);
+    paOrdinals = KLDRMODPE_RVA2TYPE(pvBits, pExpDir->AddressOfNameOrdinals, const KU16 *);
+    paFunctions = KLDRMODPE_RVA2TYPE(pvBits, pExpDir->AddressOfFunctions, const KU32 *);
+    cFunctions = pExpDir->NumberOfFunctions;
+    cNames = pExpDir->NumberOfNames;
+    for (iFunction = 0; iFunction < cFunctions; iFunction++)
+    {
+        unsigned        fFoundName;
+        KU32            iName;
+        const KU32      uRVA = paFunctions[iFunction];
+        const KLDRADDR  uValue = BaseAddress + uRVA;
+        KU32            fKind = (pModPE->Hdrs.FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)
+                              ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT)
+                              | KLDRSYMKIND_NO_TYPE;
+        if (    uRVA - pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
+            <   pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)
+            fKind |= KLDRSYMKIND_FORWARDER;
+
+        /*
+         * Any symbol names?
+         */
+        fFoundName = 0;
+        for (iName = 0; iName < cNames; iName++)
+        {
+            const char *pszName;
+            if (paOrdinals[iName] != iFunction)
+                continue;
+            fFoundName = 1;
+            pszName = KLDRMODPE_RVA2TYPE(pvBits, paRVANames[iName], const char *);
+            rc = pfnCallback(pMod, iFunction + pExpDir->Base, pszName, kHlpStrLen(pszName), NULL,
+                             uValue, fKind, pvUser);
+            if (rc)
+                return rc;
+        }
+
+        /*
+         * If no names, call once with the ordinal only.
+         */
+        if (!fFoundName)
+        {
+            rc = pfnCallback(pMod, iFunction + pExpDir->Base, NULL, 0, NULL, uValue, fKind, pvUser);
+            if (rc)
+                return rc;
+        }
+    }
+
+    return 0;
+}
+
+
+/** @copydoc kLdrModGetImport */
+static int kldrModPEGetImport(PKLDRMOD pMod, const void *pvBits, KU32 iImport, char *pszName, KSIZE cchName)
+{
+    PKLDRMODPE                      pModPE = (PKLDRMODPE)pMod->pvData;
+    const IMAGE_IMPORT_DESCRIPTOR  *pImpDesc;
+    const char                     *pszImportName;
+    KSIZE                           cchImportName;
+    int                             rc;
+
+    /*
+     * Make sure we've got mapped bits and resolve any base address aliases.
+     */
+    rc = kldrModPEBitsAndBaseAddress(pModPE, &pvBits, NULL);
+    if (rc)
+        return rc;
+
+    /*
+     * Simple bounds check.
+     */
+    if (iImport >= (KU32)kldrModPENumberOfImports(pMod, pvBits))
+        return KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS;
+
+    /*
+     * Get the name.
+     */
+    pImpDesc = KLDRMODPE_RVA2TYPE(pvBits,
+                                  pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
+                                  + sizeof(IMAGE_IMPORT_DESCRIPTOR) * iImport,
+                                  const IMAGE_IMPORT_DESCRIPTOR *);
+    pszImportName = KLDRMODPE_RVA2TYPE(pvBits, pImpDesc->Name, const char *);
+    cchImportName = kHlpStrLen(pszImportName);
+    if (cchImportName < cchName)
+    {
+        kHlpMemCopy(pszName, pszImportName, cchImportName + 1);
+        rc = 0;
+    }
+    else
+    {
+        kHlpMemCopy(pszName, pszImportName, cchName);
+        if (cchName)
+            pszName[cchName - 1] = '\0';
+        rc = KERR_BUFFER_OVERFLOW;
+    }
+
+    return rc;
+}
+
+
+/** @copydoc kLdrModNumberOfImports */
+static KI32 kldrModPENumberOfImports(PKLDRMOD pMod, const void *pvBits)
+{
+    PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData;
+    if (pModPE->cImportModules == ~(KU32)0)
+    {
+        /*
+         * We'll have to walk the import descriptors to figure out their number.
+         * First, make sure we've got mapped bits.
+         */
+        if (kldrModPEBitsAndBaseAddress(pModPE, &pvBits, NULL))
+            return -1;
+        pModPE->cImportModules = 0;
+        if (    pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
+            &&  pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
+        {
+            const IMAGE_IMPORT_DESCRIPTOR  *pImpDesc;
+
+            pImpDesc = KLDRMODPE_RVA2TYPE(pvBits,
+                                          pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
+                                          const IMAGE_IMPORT_DESCRIPTOR *);
+            while (pImpDesc->Name && pImpDesc->FirstThunk)
+            {
+                pModPE->cImportModules++;
+                pImpDesc++;
+            }
+        }
+    }
+    return pModPE->cImportModules;
+}
+
+
+/** @copydoc kLdrModGetStackInfo */
+static int kldrModPEGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo)
+{
+    PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData;
+    K_NOREF(pvBits);
+    K_NOREF(BaseAddress);
+
+    pStackInfo->Address = NIL_KLDRADDR;
+    pStackInfo->LinkAddress = NIL_KLDRADDR;
+    pStackInfo->cbStack = pStackInfo->cbStackThread = pModPE->Hdrs.OptionalHeader.SizeOfStackReserve;
+
+    return 0;
+}
+
+
+/** @copydoc kLdrModQueryMainEntrypoint */
+static int kldrModPEQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress)
+{
+    PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData;
+    int rc;
+    K_NOREF(pvBits);
+
+    /*
+     * 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
+        : NIL_KLDRADDR;
+    return 0;
+}
+
+
+/** @copydoc kLdrModEnumDbgInfo */
+static int kldrModPEEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser)
+{
+    PKLDRMODPE                      pModPE = (PKLDRMODPE)pMod->pvData;
+    const IMAGE_DEBUG_DIRECTORY    *pDbgDir;
+    KU32                            iDbgInfo;
+    KU32                            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, NULL,
+                         pDbgDir->PointerToRawData ? (KLDRFOFF)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 */
+static int kldrModPEHasDbgInfo(PKLDRMOD pMod, const void *pvBits)
+{
+    PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData;
+    K_NOREF(pvBits);
+
+    /*
+     * 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 */
+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 */
+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 = kldrModPEDoUnmap(pModPE, pModPE->pvMapping);
+    if (rc)
+        return rc;
+    KLDRMODPE_ASSERT(!pModPE->pvMapping);
+    return 0;
+
+}
+
+
+/** @copydoc kLdrModAllocTLS */
+static int kldrModPEAllocTLS(PKLDRMOD pMod, void *pvMapping)
+{
+    PKLDRMODPE  pModPE = (PKLDRMODPE)pMod->pvData;
+
+    /*
+     * Mapped?
+     */
+    if (pvMapping == KLDRMOD_INT_MAP)
+    {
+        pvMapping = pModPE->pvMapping;
+        if (!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 */
+static void kldrModPEFreeTLS(PKLDRMOD pMod, void *pvMapping)
+{
+    PKLDRMODPE  pModPE = (PKLDRMODPE)pMod->pvData;
+
+    /*
+     * Mapped?
+     */
+    if (pvMapping == KLDRMOD_INT_MAP)
+    {
+        pvMapping = pModPE->pvMapping;
+        if (!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 */
+static int kldrModPEReload(PKLDRMOD pMod)
+{
+    PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData;
+
+    /*
+     * Mapped?
+     */
+    if (!pModPE->pvMapping)
+        return KLDR_ERR_NOT_MAPPED;
+
+    /* the file provider does it all */
+    return kRdrRefresh(pMod->pRdr, (void *)pModPE->pvMapping, pMod->cSegments, pMod->aSegments);
+}
+
+
+/** @copydoc kLdrModFixupMapping */
+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 = kRdrProtect(pMod->pRdr, (void *)pModPE->pvMapping, pMod->cSegments, pMod->aSegments, 1 /* unprotect */);
+    if (rc)
+        return rc;
+
+    /*
+     * Apply base relocations.
+     */
+    rc = kldrModPEDoFixups(pModPE, (void *)pModPE->pvMapping, (KUPTR)pModPE->pvMapping,
+                           pModPE->Hdrs.OptionalHeader.ImageBase);
+
+    /*
+     * Resolve imports.
+     */
+    if (!rc)
+        rc = kldrModPEDoImports(pModPE, (void *)pModPE->pvMapping, pfnGetImport, pvUser);
+
+    /*
+     * Restore protection.
+     */
+    rc2 = kRdrProtect(pMod->pRdr, (void *)pModPE->pvMapping, pMod->cSegments, pMod->aSegments, 0 /* protect */);
+    if (!rc && rc2)
+        rc = rc2;
+    return rc;
+}
+
+
+/**
+ * Applies base relocations to a (unprotected) image mapping.
+ *
+ * @returns 0 on success, non-zero kLdr status code on failure.
+ * @param   pModPE          The PE module interpreter instance.
+ * @param   pvMapping       The mapping to fixup.
+ * @param   NewBaseAddress  The address to fixup the mapping to.
+ * @param   OldBaseAddress  The address the mapping is currently fixed up to.
+ */
+static int  kldrModPEDoFixups(PKLDRMODPE pModPE, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress)
+{
+    const KLDRADDR                  Delta = NewBaseAddress - OldBaseAddress;
+    KU32                            cbLeft = pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
+    const IMAGE_BASE_RELOCATION    *pBR, *pFirstBR;
+
+    /*
+     * Don't don anything if the delta is 0 or there aren't any relocations.
+     */
+    if (    !Delta
+        ||  !cbLeft
+        ||  !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
+        return 0;
+
+    /*
+     * Process the fixups block by block.
+     * (These blocks appears to be 4KB on all archs despite the native page size.)
+     */
+    pBR = pFirstBR = KLDRMODPE_RVA2TYPE(pvMapping,
+                                        pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
+                                        const IMAGE_BASE_RELOCATION *);
+    while (     cbLeft > sizeof(IMAGE_BASE_RELOCATION)
+           &&   pBR->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION) /* paranoia */)
+    {
+        union
+        {
+            KU8        *pu8;
+            KU16       *pu16;
+            KU32       *pu32;
+            KU64       *pu64;
+        }               uChunk,
+                        u;
+        const KU16 *poffFixup = (const KU16 *)(pBR + 1);
+        const KU32  cbBlock = K_MIN(cbLeft, pBR->SizeOfBlock) - sizeof(IMAGE_BASE_RELOCATION); /* more caution... */
+        KU32        cFixups = cbBlock / sizeof(poffFixup[0]);
+        uChunk.pu8 = KLDRMODPE_RVA2TYPE(pvMapping, pBR->VirtualAddress, KU8 *);
+
+        /*
+         * Loop thru the fixups in this chunk.
+         */
+        while (cFixups > 0)
+        {
+            u.pu8 = uChunk.pu8 + (*poffFixup & 0xfff);
+            switch (*poffFixup >> 12) /* ordered by value. */
+            {
+                /* 0 - Alignment placeholder. */
+                case IMAGE_REL_BASED_ABSOLUTE:
+                    break;
+
+                /* 1 - 16-bit, add 2nd 16-bit part of the delta. (rare) */
+                case IMAGE_REL_BASED_HIGH:
+                    *u.pu16 += (KU16)(Delta >> 16);
+                    break;
+
+                /* 2 - 16-bit, add 1st 16-bit part of the delta. (rare) */
+                case IMAGE_REL_BASED_LOW:
+                    *u.pu16 += (KU16)Delta;
+                    break;
+
+                /* 3 - 32-bit, add delta. (frequent in 32-bit images) */
+                case IMAGE_REL_BASED_HIGHLOW:
+                    *u.pu32 += (KU32)Delta;
+                    break;
+
+                /* 4 - 16-bit, add 2nd 16-bit of the delta, sign adjust for the lower 16-bit. one arg. (rare)  */
+                case IMAGE_REL_BASED_HIGHADJ:
+                {
+                    KI32 i32;
+                    if (cFixups <= 1)
+                        return KLDR_ERR_PE_BAD_FIXUP;
+
+                    i32 = (KU32)*u.pu16 << 16;
+                    i32 |= *++poffFixup; cFixups--; /* the addend argument */
+                    i32 += (KU32)Delta;
+                    i32 += 0x8000;
+                    *u.pu16 = (KU16)(i32 >> 16);
+                    break;
+                }
+
+                /* 5 - 32-bit MIPS JMPADDR, no implemented. */
+                case IMAGE_REL_BASED_MIPS_JMPADDR:
+                    *u.pu32 = (*u.pu32 & 0xc0000000)
+                            | ((KU32)((*u.pu32 << 2) + (KU32)Delta) >> 2);
+                    break;
+
+                /* 6 - Intra section? Reserved value in later specs. Not implemented. */
+                case IMAGE_REL_BASED_SECTION:
+                    KLDRMODPE_ASSERT(!"SECTION");
+                    return KLDR_ERR_PE_BAD_FIXUP;
+
+                /* 7 - Relative intra section? Reserved value in later specs. Not implemented. */
+                case IMAGE_REL_BASED_REL32:
+                    KLDRMODPE_ASSERT(!"SECTION");
+                    return KLDR_ERR_PE_BAD_FIXUP;
+
+                /* 8 - reserved according to binutils... */
+                case 8:
+                    KLDRMODPE_ASSERT(!"RESERVERED8");
+                    return KLDR_ERR_PE_BAD_FIXUP;
+
+                /* 9 - IA64_IMM64 (/ MIPS_JMPADDR16), no specs nor need to support the platform yet.
+                 * Bet this requires more code than all the other fixups put together in good IA64 spirit :-) */
+                case IMAGE_REL_BASED_IA64_IMM64:
+                    KLDRMODPE_ASSERT(!"IA64_IMM64 / MIPS_JMPADDR16");
+                    return KLDR_ERR_PE_BAD_FIXUP;
+
+                /* 10 - 64-bit, add delta. (frequently in 64-bit images) */
+                case IMAGE_REL_BASED_DIR64:
+                    *u.pu64 += (KU64)Delta;
+                    break;
+
+                /* 11 - 16-bit, add 3rd 16-bit of the delta, sign adjust for the lower 32-bit. two args. (rare) */
+                case IMAGE_REL_BASED_HIGH3ADJ:
+                {
+                    KI64 i64;
+                    if (cFixups <= 2)
+                        return KLDR_ERR_PE_BAD_FIXUP;
+
+                    i64 = (KU64)*u.pu16 << 32
+                        | ((KU32)poffFixup[2] << 16)
+                        | poffFixup[1];
+                    i64 += Delta;
+                    i64 += 0x80008000UL;
+                    *u.pu16 = (KU16)(i64 >> 32);
+                    /* skip the addends arguments */
+                    poffFixup += 2;
+                    cFixups -= 2;
+                    break;
+                }
+
+                /* the rest are yet to be defined.*/
+                default:
+                    return KLDR_ERR_PE_BAD_FIXUP;
+            }
+
+            /*
+             * Next relocation.
+             */
+            poffFixup++;
+            cFixups--;
+        }
+
+
+        /*
+         * Next block.
+         */
+        cbLeft -= pBR->SizeOfBlock;
+        pBR = (PIMAGE_BASE_RELOCATION)((KUPTR)pBR + pBR->SizeOfBlock);
+    }
+
+    return 0;
+}
+
+
+
+/**
+ * Resolves imports.
+ *
+ * @returns 0 on success, non-zero kLdr status code on failure.
+ * @param   pModPE          The PE module interpreter instance.
+ * @param   pvMapping       The mapping which imports should be resolved.
+ * @param   pfnGetImport    The callback for resolving an imported symbol.
+ * @param   pvUser          User argument to the callback.
+ */
+static int  kldrModPEDoImports(PKLDRMODPE pModPE, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    const IMAGE_IMPORT_DESCRIPTOR *pImpDesc;
+
+    /*
+     * If no imports, there is nothing to do.
+     */
+    kldrModPENumberOfImports(pModPE->pMod, pvMapping);
+    if (!pModPE->cImportModules)
+        return 0;
+
+    pImpDesc = KLDRMODPE_RVA2TYPE(pvMapping,
+                                  pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
+                                  const IMAGE_IMPORT_DESCRIPTOR *);
+    if (pModPE->Hdrs.FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32))
+        return kldrModPEDoImports32Bit(pModPE, pvMapping, pImpDesc, pfnGetImport, pvUser);
+    return kldrModPEDoImports64Bit(pModPE, pvMapping, pImpDesc, pfnGetImport, pvUser);
+}
+
+
+/**
+ * Resolves imports, 32-bit image.
+ *
+ * @returns 0 on success, non-zero kLdr status code on failure.
+ * @param   pModPE          The PE module interpreter instance.
+ * @param   pvMapping       The mapping which imports should be resolved.
+ * @param   pImpDesc        Pointer to the first import descriptor.
+ * @param   pfnGetImport    The callback for resolving an imported symbol.
+ * @param   pvUser          User argument to the callback.
+ */
+static int  kldrModPEDoImports32Bit(PKLDRMODPE pModPE, void *pvMapping, const IMAGE_IMPORT_DESCRIPTOR *pImpDesc,
+                                    PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    PKLDRMOD pMod = pModPE->pMod;
+    KU32 iImp;
+
+    /*
+     * Iterate the import descriptors.
+     */
+    for (iImp = 0; iImp < pModPE->cImportModules; iImp++, pImpDesc++)
+    {
+        PIMAGE_THUNK_DATA32         pFirstThunk = KLDRMODPE_RVA2TYPE(pvMapping, pImpDesc->FirstThunk, PIMAGE_THUNK_DATA32);
+        const IMAGE_THUNK_DATA32   *pThunk = pImpDesc->u.OriginalFirstThunk
+            ? KLDRMODPE_RVA2TYPE(pvMapping, pImpDesc->u.OriginalFirstThunk, const IMAGE_THUNK_DATA32 *)
+            : KLDRMODPE_RVA2TYPE(pvMapping, pImpDesc->FirstThunk, const IMAGE_THUNK_DATA32 *);
+
+        /* Iterate the thunks. */
+        while (pThunk->u1.Ordinal != 0)
+        {
+            KLDRADDR    Value;
+            KU32        fKind = KLDRSYMKIND_REQ_FLAT;
+            int         rc;
+
+            /* Ordinal or name import? */
+            if (IMAGE_SNAP_BY_ORDINAL32(pThunk->u1.Ordinal))
+                rc = pfnGetImport(pMod, iImp, IMAGE_ORDINAL32(pThunk->u1.Ordinal), NULL, 0, NULL, &Value, &fKind, pvUser);
+            else if (KLDRMODPE_VALID_RVA(pModPE, pThunk->u1.Ordinal))
+            {
+                const IMAGE_IMPORT_BY_NAME *pName = KLDRMODPE_RVA2TYPE(pvMapping, pThunk->u1.Ordinal, const IMAGE_IMPORT_BY_NAME *);
+                rc = pfnGetImport(pMod, iImp, NIL_KLDRMOD_SYM_ORDINAL, (const char *)pName->Name,
+                                  kHlpStrLen((const char *)pName->Name), NULL, &Value, &fKind, pvUser);
+            }
+            else
+            {
+                KLDRMODPE_ASSERT(!"bad 32-bit import");
+                return KLDR_ERR_PE_BAD_IMPORT;
+            }
+            if (rc)
+                return rc;
+
+            /* Apply it. */
+            pFirstThunk->u1.Function = (KU32)Value;
+            if (pFirstThunk->u1.Function != Value)
+            {
+                KLDRMODPE_ASSERT(!"overflow");
+                return KLDR_ERR_ADDRESS_OVERFLOW;
+            }
+
+            /* next */
+            pThunk++;
+            pFirstThunk++;
+        }
+    }
+
+    return 0;
+}
+
+
+/**
+ * Resolves imports, 64-bit image.
+ *
+ * @returns 0 on success, non-zero kLdr status code on failure.
+ * @param   pModPE          The PE module interpreter instance.
+ * @param   pvMapping       The mapping which imports should be resolved.
+ * @param   pImpDesc        Pointer to the first import descriptor.
+ * @param   pfnGetImport    The callback for resolving an imported symbol.
+ * @param   pvUser          User argument to the callback.
+ */
+static int  kldrModPEDoImports64Bit(PKLDRMODPE pModPE, void *pvMapping, const IMAGE_IMPORT_DESCRIPTOR *pImpDesc,
+                                    PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    PKLDRMOD pMod = pModPE->pMod;
+    KU32 iImp;
+
+    /*
+     * Iterate the import descriptors.
+     */
+    for (iImp = 0; iImp < pModPE->cImportModules; iImp++, pImpDesc++)
+    {
+        PIMAGE_THUNK_DATA64         pFirstThunk = KLDRMODPE_RVA2TYPE(pvMapping, pImpDesc->FirstThunk, PIMAGE_THUNK_DATA64);
+        const IMAGE_THUNK_DATA64   *pThunk = pImpDesc->u.OriginalFirstThunk
+            ? KLDRMODPE_RVA2TYPE(pvMapping, pImpDesc->u.OriginalFirstThunk, const IMAGE_THUNK_DATA64 *)
+            : KLDRMODPE_RVA2TYPE(pvMapping, pImpDesc->FirstThunk, const IMAGE_THUNK_DATA64 *);
+
+        /* Iterate the thunks. */
+        while (pThunk->u1.Ordinal != 0)
+        {
+            KLDRADDR    Value;
+            KU32        fKind = KLDRSYMKIND_REQ_FLAT;
+            int         rc;
+
+            /* Ordinal or name import? */
+            if (IMAGE_SNAP_BY_ORDINAL64(pThunk->u1.Ordinal))
+                rc = pfnGetImport(pMod, iImp, (KU32)IMAGE_ORDINAL64(pThunk->u1.Ordinal), NULL, 0, NULL, &Value, &fKind, pvUser);
+            else if (KLDRMODPE_VALID_RVA(pModPE, pThunk->u1.Ordinal))
+            {
+                const IMAGE_IMPORT_BY_NAME *pName = KLDRMODPE_RVA2TYPE(pvMapping, pThunk->u1.Ordinal, const IMAGE_IMPORT_BY_NAME *);
+                rc = pfnGetImport(pMod, iImp, NIL_KLDRMOD_SYM_ORDINAL, (const char *)pName->Name,
+                                  kHlpStrLen((const char *)pName->Name), NULL, &Value, &fKind, pvUser);
+            }
+            else
+            {
+                KLDRMODPE_ASSERT(!"bad 64-bit import");
+                return KLDR_ERR_PE_BAD_IMPORT;
+            }
+            if (rc)
+                return rc;
+
+            /* Apply it. */
+            pFirstThunk->u1.Function = Value;
+
+            /* next */
+            pThunk++;
+            pFirstThunk++;
+        }
+    }
+
+    return 0;
+}
+
+
+
+/** @copydoc kLdrModCallInit */
+static int kldrModPECallInit(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle)
+{
+    PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData;
+    int rc;
+
+    /*
+     * Mapped?
+     */
+    if (pvMapping == KLDRMOD_INT_MAP)
+    {
+        pvMapping = pModPE->pvMapping;
+        if (!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, pvMapping, DLL_PROCESS_ATTACH, uHandle);
+    if (    !rc
+        &&  (pModPE->Hdrs.FileHeader.Characteristics & IMAGE_FILE_DLL))
+    {
+        rc = kldrModPEDoCallDLL(pModPE, pvMapping, DLL_PROCESS_ATTACH, uHandle);
+        if (rc)
+            kldrModPEDoCallTLS(pModPE, pvMapping, DLL_PROCESS_DETACH, uHandle);
+    }
+
+    return rc;
+}
+
+
+/**
+ * Call the DLL entrypoint.
+ *
+ * @returns 0 on success.
+ * @returns KLDR_ERR_MODULE_INIT_FAILED  or KLDR_ERR_THREAD_ATTACH_FAILED on failure.
+ * @param   pModPE          The PE module interpreter instance.
+ * @param   pvMapping       The module mapping to use (resolved).
+ * @param   uOp             The operation (DLL_*).
+ * @param   uHandle         The module handle to present.
+ */
+static int  kldrModPEDoCallDLL(PKLDRMODPE pModPE, void *pvMapping, unsigned uOp, KUPTR uHandle)
+{
+    int rc;
+
+    /*
+     * If no entrypoint there isn't anything to be done.
+     */
+    if (!pModPE->Hdrs.OptionalHeader.AddressOfEntryPoint)
+        return 0;
+
+    /*
+     * Invoke the entrypoint and convert the boolean result to a kLdr status code.
+     */
+    rc = kldrModPEDoCall((KUPTR)pvMapping + pModPE->Hdrs.OptionalHeader.AddressOfEntryPoint, uHandle, uOp, NULL);
+    if (rc)
+        rc = 0;
+    else if (uOp == DLL_PROCESS_ATTACH)
+        rc = KLDR_ERR_MODULE_INIT_FAILED;
+    else if (uOp == DLL_THREAD_ATTACH)
+        rc = KLDR_ERR_THREAD_ATTACH_FAILED;
+    else /* detach: ignore failures */
+        rc = 0;
+    return rc;
+}
+
+
+/**
+ * Call the TLS entrypoints.
+ *
+ * @returns 0 on success.
+ * @returns KLDR_ERR_THREAD_ATTACH_FAILED on failure.
+ * @param   pModPE          The PE module interpreter instance.
+ * @param   pvMapping       The module mapping to use (resolved).
+ * @param   uOp             The operation (DLL_*).
+ * @param   uHandle         The module handle to present.
+ */
+static int  kldrModPEDoCallTLS(PKLDRMODPE pModPE, void *pvMapping, unsigned uOp, KUPTR uHandle)
+{
+    /** @todo implement TLS support. */
+    K_NOREF(pModPE);
+    K_NOREF(pvMapping);
+    K_NOREF(uOp);
+    K_NOREF(uHandle);
+    return 0;
+}
+
+
+/**
+ * Do a 3 parameter callback.
+ *
+ * @returns 32-bit callback return.
+ * @param   uEntrypoint     The address of the function to be called.
+ * @param   uHandle         The first argument, the module handle.
+ * @param   uOp             The second argumnet, the reason we're calling.
+ * @param   pvReserved      The third argument, reserved argument. (figure this one out)
+ */
+static KI32 kldrModPEDoCall(KUPTR uEntrypoint, KUPTR uHandle, KU32 uOp, void *pvReserved)
+{
+    KI32 rc;
+
+/** @todo try/except */
+#if defined(__X86__) || defined(__i386__) || defined(_M_IX86)
+    /*
+     * Be very careful.
+     * Not everyone will have got the calling convention right.
+     */
+# ifdef __GNUC__
+    __asm__ __volatile__(
+        "pushl  %2\n\t"
+        "pushl  %1\n\t"
+        "pushl  %0\n\t"
+        "lea   12(%%esp), %2\n\t"
+        "call  *%3\n\t"
+        "movl   %2, %%esp\n\t"
+        : "=a" (rc)
+        : "d" (uOp),
+          "S" (0),
+          "c" (uEntrypoint),
+          "0" (uHandle));
+# elif defined(_MSC_VER)
+    __asm {
+        mov     eax, [uHandle]
+        mov     edx, [uOp]
+        mov     ecx, 0
+        mov     ebx, [uEntrypoint]
+        push    edi
+        mov     edi, esp
+        push    ecx
+        push    edx
+        push    eax
+        call    ebx
+        mov     esp, edi
+        pop     edi
+        mov     [rc], eax
+    }
+# else
+#  error "port me!"
+# endif
+
+#elif defined(__AMD64__) || defined(__x86_64__) || defined(_M_IX86)
+    /*
+     * For now, let's just get the work done...
+     */
+    /** @todo Deal with GCC / MSC differences in some sensible way. */
+    int (*pfn)(KUPTR uHandle, KU32 uOp, void *pvReserved);
+    pfn = (int (*)(KUPTR uHandle, KU32 uOp, void *pvReserved))uEntrypoint;
+    rc = pfn(uHandle, uOp, NULL);
+
+#else
+# error "port me"
+#endif
+    K_NOREF(pvReserved);
+
+    return rc;
+}
+
+
+/** @copydoc kLdrModCallTerm */
+static int kldrModPECallTerm(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle)
+{
+    PKLDRMODPE  pModPE = (PKLDRMODPE)pMod->pvData;
+
+    /*
+     * Mapped?
+     */
+    if (pvMapping == KLDRMOD_INT_MAP)
+    {
+        pvMapping = pModPE->pvMapping;
+        if (!pvMapping)
+            return KLDR_ERR_NOT_MAPPED;
+    }
+
+    /*
+     * Do TLS callbacks first.
+     */
+    kldrModPEDoCallTLS(pModPE, pvMapping, DLL_PROCESS_DETACH, uHandle);
+    if (pModPE->Hdrs.FileHeader.Characteristics & IMAGE_FILE_DLL)
+        kldrModPEDoCallDLL(pModPE, pvMapping, DLL_PROCESS_DETACH, uHandle);
+
+    return 0;
+}
+
+
+/** @copydoc kLdrModCallThread */
+static int kldrModPECallThread(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle, unsigned fAttachingOrDetaching)
+{
+    PKLDRMODPE  pModPE = (PKLDRMODPE)pMod->pvData;
+    unsigned    uOp = fAttachingOrDetaching ? DLL_THREAD_ATTACH : DLL_THREAD_DETACH;
+    int         rc;
+
+    /*
+     * Mapped?
+     */
+    if (pvMapping == KLDRMOD_INT_MAP)
+    {
+        pvMapping = pModPE->pvMapping;
+        if (!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, pvMapping, uOp, uHandle);
+    if (!fAttachingOrDetaching)
+        rc = 0;
+    if (    !rc
+        &&  (pModPE->Hdrs.FileHeader.Characteristics & IMAGE_FILE_DLL))
+    {
+        rc = kldrModPEDoCallDLL(pModPE, pvMapping, uOp, uHandle);
+        if (!fAttachingOrDetaching)
+            rc = 0;
+        if (rc)
+            kldrModPEDoCallTLS(pModPE, pvMapping, uOp, uHandle);
+    }
+
+    return rc;
+}
+
+
+/** @copydoc kLdrModSize */
+static KLDRADDR kldrModPESize(PKLDRMOD pMod)
+{
+    PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData;
+    return pModPE->Hdrs.OptionalHeader.SizeOfImage;
+}
+
+
+/** @copydoc kLdrModGetBits */
+static int kldrModPEGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
+{
+    PKLDRMODPE  pModPE = (PKLDRMODPE)pMod->pvData;
+    KU32        i;
+    int         rc;
+
+    /*
+     * Zero the entire buffer first to simplify things.
+     */
+    kHlpMemSet(pvBits, 0, pModPE->Hdrs.OptionalHeader.SizeOfImage);
+
+    /*
+     * Iterate the segments and read the data within them.
+     */
+    for (i = 0; i < pMod->cSegments; i++)
+    {
+        /* skip it? */
+        if (    pMod->aSegments[i].cbFile == -1
+            ||  pMod->aSegments[i].offFile == -1
+            ||  pMod->aSegments[i].LinkAddress == NIL_KLDRADDR
+            ||  !pMod->aSegments[i].Alignment)
+            continue;
+        rc = kRdrRead(pMod->pRdr,
+                         (KU8 *)pvBits + (pMod->aSegments[i].LinkAddress - pModPE->Hdrs.OptionalHeader.ImageBase),
+                         pMod->aSegments[i].cbFile,
+                         pMod->aSegments[i].offFile);
+        if (rc)
+            return rc;
+    }
+
+    /*
+     * Perform relocations.
+     */
+    return kldrModPERelocateBits(pMod, pvBits, BaseAddress, pModPE->Hdrs.OptionalHeader.ImageBase, pfnGetImport, pvUser);
+
+}
+
+
+/** @copydoc kLdrModRelocateBits */
+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;
+}
+
+
+/**
+ * The PE module interpreter method table.
+ */
+KLDRMODOPS g_kLdrModPEOps =
+{
+    "PE",
+    NULL,
+    kldrModPECreate,
+    kldrModPEDestroy,
+    kldrModPEQuerySymbol,
+    kldrModPEEnumSymbols,
+    kldrModPEGetImport,
+    kldrModPENumberOfImports,
+    NULL /* can execute one is optional */,
+    kldrModPEGetStackInfo,
+    kldrModPEQueryMainEntrypoint,
+    NULL /* pfnQueryImageUuid */,
+    NULL, /** @todo resources */
+    NULL, /** @todo resources */
+    kldrModPEEnumDbgInfo,
+    kldrModPEHasDbgInfo,
+    kldrModPEMap,
+    kldrModPEUnmap,
+    kldrModPEAllocTLS,
+    kldrModPEFreeTLS,
+    kldrModPEReload,
+    kldrModPEFixupMapping,
+    kldrModPECallInit,
+    kldrModPECallTerm,
+    kldrModPECallThread,
+    kldrModPESize,
+    kldrModPEGetBits,
+    kldrModPERelocateBits,
+    NULL, /** @todo mostly done */
+    42 /* the end */
+};
diff --git a/src/lib/kStuff/kLdr/testcase/Makefile.kmk b/src/lib/kStuff/kLdr/testcase/Makefile.kmk
new file mode 100644
index 0000000..7b3efb6
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/Makefile.kmk
@@ -0,0 +1,305 @@
+# $Id: Makefile.kmk 29 2009-07-01 20:30:29Z bird $
+## @file
+# kBuild Makefile for the kLdr testcases.
+#
+
+#
+# Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+# generate rules.
+DEPTH ?= ../..
+SUB_DEPTH = ../..
+include $(PATH_KBUILD)/subheader.kmk
+
+
+#
+# Templates for the testcases.
+#
+TEMPLATE_TST = Testcase template
+ifeq ($(BUILD_TARGET),win)
+ ifeq ($(BUILD_TARGET_ARCH),x86)
+  TEMPLATE_TST_TOOL = VCC70
+  TEMPLATE_TST_CFLAGS = -W3 -Zi -Zl -MD
+  TEMPLATE_TST_CXXFLAGS = -W3 -Zi -Zl -MD
+  TEMPLATE_TST_LIBS = \
+   	$(PATH_TOOL_VCC70_LIB)/oldnames.lib \
+   	$(PATH_TOOL_VCC70_LIB)/msvcrt.lib
+ else
+  TEMPLATE_TST_TOOL = VCC80AMD64
+  TEMPLATE_TST_CFLAGS = -W3 -Zi -Zl -MD
+  TEMPLATE_TST_CXXFLAGS = -W3 -Zi -Zl -MD
+  TEMPLATE_TST_LIBS = \
+   	$(PATH_TOOL_VCC80AMD64_LIB)/oldnames.lib \
+   	$(PATH_TOOL_VCC80AMD64_LIB)/msvcrt.lib
+ endif
+ TEMPLATE_TST_CFLAGS.release = -O2
+ TEMPLATE_TST_CXXFLAGS.release = -O2
+ TEMPLATE_TST_ASFLAGS = -f win
+ TEMPLATE_TST_DEFS = __WIN__
+ TEMPLATE_TST_SDKS.x86 = WIN32SDK
+ TEMPLATE_TST_SDKS.amd64 = WIN64SDK
+
+else
+ TEMPLATE_TST_CFLAGS = -Wall -pedantic -g
+ TEMPLATE_TST_CFLAGS.release = -O2
+ TEMPLATE_TST_LDFLAGS =
+ ifneq ($(filter os2,$(BUILD_TARGET)),)
+  TEMPLATE_TST_TOOL = GCC3OMF
+  TEMPLATE_TST_ASFLAGS = -f obj
+  TEMPLATE_TST_LIBS = os2 gcc end
+ else ifneq ($(filter darwin,$(BUILD_TARGET)),)
+  TEMPLATE_TST_TOOL = GCC4MACHO
+  TEMPLATE_TST_ASFLAGS = -f macho
+  TEMPLATE_TST_DEFS = __DARWIN__
+  TEMPLATE_TST_LIBS =
+ else
+  TEMPLATE_TST_TOOL = GCC3
+  TEMPLATE_TST_ASFLAGS = -f elf
+  TEMPLATE_TST_LIBS = gcc
+ endif
+endif
+TEMPLATE_TST_INCS := $(PATH_SUB_CURRENT) $(PATH_SUB_ROOT)/include
+
+
+TEMPLATE_TSTPROG = Testcase program template
+TEMPLATE_TSTPROG_EXTENDS = TST
+
+
+TEMPLATE_TSTDLL = Testcase dll template
+TEMPLATE_TSTDLL_EXTENDS = TST
+
+
+TEMPLATE_TSTBARE = Bare bone testcase template
+ifeq ($(BUILD_TARGET),win)
+ ifeq ($(BUILD_TARGET_ARCH),x86)
+  TEMPLATE_TSTBARE_TOOL = VCC70
+ else
+  TEMPLATE_TSTBARE_TOOL = VCC80AMD64
+ endif
+ TEMPLATE_TSTBARE_CFLAGS = -W3 -Zi -Zl
+ TEMPLATE_TSTBARE_CFLAGS.release = -O2
+ TEMPLATE_TSTBARE_CXXFLAGS = -W3 -Zi -Zl
+ TEMPLATE_TSTBARE_CXXFLAGS.release = -O2
+ TEMPLATE_TSTBARE_ASFLAGS = -f win
+ TEMPLATE_TSTBARE_DEFS = __WIN__
+ TEMPLATE_TSTBARE_SDKS.x86 = WIN32SDK
+ TEMPLATE_TSTBARE_SDKS.amd64 = WIN64SDK
+
+else
+ TEMPLATE_TSTBARE_CFLAGS = -Wall -pedantic -g
+ TEMPLATE_TSTBARE_CFLAGS.release = -O2
+ TEMPLATE_TSTBARE_LDFLAGS = -nostdlib -lgcc
+ ifeq ($(filter-out os2,$(BUILD_TARGET)),)
+  TEMPLATE_TSTBARE_TOOL = GCC3OMF
+  TEMPLATE_TSTBARE_ASFLAGS = -f obj
+  TEMPLATE_TSTBARE_ASTOOL = NASM
+  TEMPLATE_TSTBARE_DEFS = main=main_wrapped
+  TEMPLATE_TSTBARE_LIBS = os2
+ else ifeq ($(filter-out darwin,$(BUILD_TARGET)),)
+  TEMPLATE_TSTBARE_TOOL = GCC4MACHO
+  TEMPLATE_TSTBARE_ASFLAGS = -f macho
+  TEMPLATE_TSTBARE_ASTOOL = NASM
+  TEMPLATE_TSTBARE_DEFS = __DARWIN__
+  TEMPLATE_TSTBARE_LIBS =
+  TEMPLATE_TSTBARE_CFLAGS += -static -fno-common
+  TEMPLATE_TSTBARE_LDFLAGS += -nostdlib -r
+ else
+  TEMPLATE_TSTBARE_TOOL = GCC3
+  TEMPLATE_TSTBARE_ASFLAGS = -f elf
+  TEMPLATE_TSTBARE_LIBS = gcc
+ endif
+endif
+TEMPLATE_TSTBARE_INCS := $(PATH_SUB_CURRENT) $(PATH_SUB_ROOT)/include
+
+TEMPLATE_TSTBAREPROG = Bare bone testcase program template
+TEMPLATE_TSTBAREPROG_EXTENDS = TSTBARE
+ifneq ($(filter win win32 win64,$(BUILD_TARGET)),)
+TEMPLATE_TSTBAREPROG_LDFLAGS += -Entry:WindowsMain -FIXED:NO
+else
+TEMPLATE_TSTBAREPROG_LDFLAGS.nt += -FIXED:NO
+endif
+
+
+TEMPLATE_TSTBAREDLL = Bare bone testcase dll template
+TEMPLATE_TSTBAREDLL_EXTENDS = TSTBARE
+ifeq ($(BUILD_TARGET),win)
+ TEMPLATE_TSTBAREDLL_LDFLAGS += -Entry:DllMain
+else ifeq ($(BUILD_TARGET),darwin)
+# TEMPLATE_TSTBAREDLL_CFLAGS += -dynamiclib
+# TEMPLATE_TSTBAREDLL_LDFLAGS += -dynamiclib
+endif
+
+
+
+
+#
+# tst-0: four dlls, three of which depends on the 4th and no external dependencies.
+#        The purpose of this testcase is to debug the dynamic loader without
+#        messing with the native loader at all.
+#
+PROGRAMS += tst-0 tst-0-driver
+DLLS += tst-0-a tst-0-b tst-0-c tst-0-d
+
+tst-0-driver_TEMPLATE = TSTPROG
+tst-0-driver_SOURCES  = tst-0-driver.c
+
+tst-0-a_TEMPLATE = TSTBAREDLL
+tst-0-a_SOURCES  = tst-0-a.c tstDllMainStub.c
+tst-0-a_SOURCES.os2= tstDllMainStub-os2.asm
+
+tst-0-b_TEMPLATE = TSTBAREDLL
+tst-0-b_SOURCES  = tst-0-b.c tstDllMainStub.c
+tst-0-b_SOURCES.os2= tstDllMainStub-os2.asm
+
+tst-0-c_TEMPLATE = TSTBAREDLL
+tst-0-c_SOURCES  = tst-0-c.c tstDllMainStub.c
+tst-0-c_SOURCES.os2= tstDllMainStub-os2.asm
+
+tst-0-d_TEMPLATE = TSTBAREDLL
+tst-0-d_SOURCES  = tst-0-d.c tstDllMainStub.c
+tst-0-d_SOURCES.os2= tstDllMainStub-os2.asm
+
+tst-0_TEMPLATE   = TSTBAREPROG
+tst-0_SOURCES    = tst-0.c tstExeMainStub.c
+tst-0_SOURCES.os2= tstExeMainStub-os2.asm
+
+ifeq ($(BUILD_TARGET),win)
+tst-0-driver_LIBS= $(PATH_LIB)/kLdr.lib
+tst-0-a_LIBS     = $(PATH_TARGET)/tst-0-d/tst-0-d.lib
+tst-0-b_LIBS     = $(PATH_TARGET)/tst-0-d/tst-0-d.lib
+tst-0-c_LIBS     = $(PATH_TARGET)/tst-0-d/tst-0-d.lib
+tst-0_LIBS       = $(TARGET_tst-0-a:.dll=.lib) $(TARGET_tst-0-b:.dll=.lib) $(TARGET_tst-0-c:.dll=.lib)
+else
+tst-0-driver_LIBS= $(PATH_DLL)/kLdr$(SUFF_DLL)
+tst-0-a_LIBS     = $(subst -a,-d,$(TARGET_tst-0-a))
+tst-0-b_LIBS     = $(subst -b,-d,$(TARGET_tst-0-b))
+tst-0-c_LIBS     = $(subst -c,-d,$(TARGET_tst-0-c))
+tst-0_LIBS       = $(TARGET_tst-0-a) $(TARGET_tst-0-b) $(TARGET_tst-0-c)
+endif
+
+
+#
+# tst-1: four dlls, three of which depends on the 4th and the testcase depends on those three again.
+#
+PROGRAMS += tst-1
+DLLS += tst-1-a tst-1-b tst-1-c tst-1-d
+
+tst-1-a_TEMPLATE = TSTDLL
+tst-1-a_SOURCES  = tst-1-a.c tstDllMain.c
+
+tst-1-b_TEMPLATE = TSTDLL
+tst-1-b_SOURCES  = tst-1-b.c tstDllMain.c
+
+tst-1-c_TEMPLATE = TSTDLL
+tst-1-c_SOURCES  = tst-1-c.c tstDllMain.c
+
+tst-1-d_TEMPLATE = TSTDLL
+tst-1-d_SOURCES  = tst-1-d.c tstDllMain.c
+
+tst-1_TEMPLATE   = TSTPROG
+tst-1_SOURCES    = tst-1.c
+
+ifeq ($(BUILD_TARGET),win)
+tst-1-a_LIBS     = $(PATH_TARGET)/tst-1-d/tst-1-d.lib
+tst-1-b_LIBS     = $(PATH_TARGET)/tst-1-d/tst-1-d.lib
+tst-1-c_LIBS     = $(PATH_TARGET)/tst-1-d/tst-1-d.lib
+tst-1_LIBS       = $(TARGET_tst-1-a:.dll=.lib) $(TARGET_tst-1-b:.dll=.lib) $(TARGET_tst-1-c:.dll=.lib)
+else
+tst-1-a_LIBS     = $(subst -a,-d,$(TARGET_tst-1-a))
+tst-1-b_LIBS     = $(subst -b,-d,$(TARGET_tst-1-b))
+tst-1-c_LIBS     = $(subst -c,-d,$(TARGET_tst-1-c))
+tst-1_LIBS       = $(TARGET_tst-1-a) $(TARGET_tst-1-b) $(TARGET_tst-1-c)
+endif
+
+
+#
+# tst-2: four dlls, three of which depends on the 1st, and the testcase depends on those all of them.
+#
+PROGRAMS += tst-2
+DLLS += tst-2-a tst-2-b tst-2-c tst-2-d
+
+tst-2-a_TEMPLATE = TSTDLL
+tst-2-a_SOURCES  = tst-2-a.c tstDllMain.c
+
+tst-2-b_TEMPLATE = TSTDLL
+tst-2-b_SOURCES  = tst-2-b.c tstDllMain.c
+
+tst-2-c_TEMPLATE = TSTDLL
+tst-2-c_SOURCES  = tst-2-c.c tstDllMain.c
+
+tst-2-d_TEMPLATE = TSTDLL
+tst-2-d_SOURCES  = tst-2-d.c tstDllMain.c
+
+tst-2_TEMPLATE   = TSTPROG
+tst-2_SOURCES    = tst-2.c
+
+ifeq ($(BUILD_TARGET),win)
+tst-2-b_LIBS     = $(PATH_TARGET)/tst-2-a/tst-2-a.lib
+tst-2-c_LIBS     = $(PATH_TARGET)/tst-2-a/tst-2-a.lib
+tst-2-d_LIBS     = $(PATH_TARGET)/tst-2-a/tst-2-a.lib
+tst-2_LIBS       = $(TARGET_tst-2-b:.dll=.lib) $(TARGET_tst-2-c:.dll=.lib) $(TARGET_tst-2-d:.dll=.lib) $(TARGET_tst-2-a:.dll=.lib)
+else
+tst-2-b_LIBS     = $(subst -b,-a,$(TARGET_tst-2-b))
+tst-2-c_LIBS     = $(subst -c,-a,$(TARGET_tst-2-c))
+tst-2-d_LIBS     = $(subst -d,-a,$(TARGET_tst-2-d))
+tst-2_LIBS       = $(TARGET_tst-2-a) $(TARGET_tst-2-b) $(TARGET_tst-2-c) $(TARGET_tst-2-d)
+endif
+
+
+#
+# tst-3: Single module.
+#
+PROGRAMS += tst-3-driver
+ifeq ($(BUILD_TARGET),darwin)
+SYSMODS += tst-3
+else
+DLLS += tst-3
+LIBRARIES.win += tst-3-imp
+LIBRARIES.os2 += tst-3-imp
+endif
+
+tst-3_TEMPLATE = TSTBAREDLL
+tst-3_SOURCES  = tst-3.c tst-3-ext.c tstDllMainStub.c
+tst-3_SOURCES.os2= tstDllMainStub-os2.asm
+tst-3_LIBS.os2 = $(TARGET_tst-3-imp)
+tst-3_LIBS.win = $(TARGET_tst-3-imp)
+
+tst-3-imp_TEMPLATE = TSTBAREDLL
+tst-3-imp_SOURCES.win = tst-3-imp-win.def
+tst-3-imp_SOURCES.os2 = tst-3-imp-os2.def
+
+tst-3-driver_TEMPLATE = TSTPROG
+tst-3-driver_SOURCES  = tst-3-driver.c
+
+ifeq ($(BUILD_TARGET),win)
+tst-3-driver_LIBS = $(PATH_LIB)/kLdr.lib
+else
+tst-3-driver_LIBS = $(PATH_DLL)/kLdr$(SUFF_DLL)
+endif
+
+
+# generate rules.
+include $(PATH_KBUILD)/subfooter.kmk
+
diff --git a/src/lib/kStuff/kLdr/testcase/bin/tst-3.dll.win.x86 b/src/lib/kStuff/kLdr/testcase/bin/tst-3.dll.win.x86
new file mode 100644
index 0000000..2a48ccb
Binary files /dev/null and b/src/lib/kStuff/kLdr/testcase/bin/tst-3.dll.win.x86 differ
diff --git a/src/lib/kStuff/kLdr/testcase/bin/tst-3.rel.darwin.x86 b/src/lib/kStuff/kLdr/testcase/bin/tst-3.rel.darwin.x86
new file mode 100644
index 0000000..a18a919
Binary files /dev/null and b/src/lib/kStuff/kLdr/testcase/bin/tst-3.rel.darwin.x86 differ
diff --git a/src/lib/kStuff/kLdr/testcase/tst-0-a.c b/src/lib/kStuff/kLdr/testcase/tst-0-a.c
new file mode 100644
index 0000000..a5533f2
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-0-a.c
@@ -0,0 +1,10 @@
+#include "tst.h"
+const char *g_pszName = "a";
+
+MY_IMPORT(int) FuncD(void);
+
+MY_EXPORT(int) FuncA(void)
+{
+    return FuncD() | (g_pszName[0] == 'a' ? 0x42 : 0x0001);
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-0-b.c b/src/lib/kStuff/kLdr/testcase/tst-0-b.c
new file mode 100644
index 0000000..286b179
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-0-b.c
@@ -0,0 +1,10 @@
+#include "tst.h"
+const char *g_pszName = "b";
+
+MY_IMPORT(int) FuncD(void);
+
+MY_EXPORT(int) FuncB(void)
+{
+    return FuncD() | (g_pszName[0] == 'b' ? 0x4200 : 0x0010);
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-0-c.c b/src/lib/kStuff/kLdr/testcase/tst-0-c.c
new file mode 100644
index 0000000..3c9d449
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-0-c.c
@@ -0,0 +1,10 @@
+#include "tst.h"
+const char *g_pszName = "c";
+
+MY_IMPORT(int) FuncD(void);
+
+MY_EXPORT(int) FuncC(void)
+{
+    return FuncD() | (g_pszName[0] == 'c' ? 0x420000 : 0x0100);
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-0-d.c b/src/lib/kStuff/kLdr/testcase/tst-0-d.c
new file mode 100644
index 0000000..a5501b0
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-0-d.c
@@ -0,0 +1,8 @@
+#include "tst.h"
+const char *g_pszName = "d";
+
+MY_EXPORT(int) FuncD(void)
+{
+    return g_pszName[0] == 'd' ? 0x42000000 : 0x1000;
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-0-driver.c b/src/lib/kStuff/kLdr/testcase/tst-0-driver.c
new file mode 100644
index 0000000..be304d5
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-0-driver.c
@@ -0,0 +1,502 @@
+/* $Id: tst-0-driver.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - Dynamic Loader testcase no. 0, Driver.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "tst.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** Select the appropriate KLDRSYMKIND bit define. */
+#define MY_KLDRSYMKIND_BITS     ( sizeof(void *) == 4 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT )
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** The numbers of errors. */
+static int g_cErrors = 0;
+
+
+
+/**
+ * Report failure.
+ */
+static int Failure(const char *pszFormat, ...)
+{
+    va_list va;
+
+    g_cErrors++;
+
+    printf("tst-0-driver: ");
+    va_start(va, pszFormat);
+    vprintf(pszFormat, va);
+    va_end(va);
+    printf("\n");
+    return 1;
+}
+
+
+int main(int argc, char **argv)
+{
+    const char *pszErrInit = "Error, szErr wasn't zapped";
+    char szErr[512];
+    char szBuf[512];
+    char *psz;
+    KSIZE cch;
+    HKLDRMOD hMod;
+    int rc;
+
+    /*
+     * The first thing to do is a simple load / unload test
+     * using the tst-0-a library (it'll drag in tst-0-d).
+     */
+    printf("tst-0-driver: Basic API test using 'tst-0-a'...\n");
+    hMod = (HKLDRMOD)0xffffeeee;
+    strcpy(szErr, pszErrInit);
+    rc = kLdrDyldLoad("tst-0-a", NULL, NULL, KLDRDYLD_SEARCH_HOST,
+                      KLDRDYLD_LOAD_FLAGS_RECURSIVE_INIT, &hMod, szErr, sizeof(szErr));
+    if (rc)
+        Failure("kLdrDyldLoad(\"tst-0\",...) failed, rc=%d (%#x). szErr='%s'.\n", rc, rc, szErr);
+    if (!strcmp(szErr, pszErrInit))
+        Failure("szErr wasn't set.\n");
+    if (hMod == (HKLDRMOD)0xffffeeee)
+        Failure("hMod wasn't set.\n");
+    if (hMod == NIL_HKLDRMOD && !rc)
+        Failure("rc=0 but hMod=NIL_HKLDRMOD\n");
+    if (!rc)
+    {
+        HKLDRMOD hMod2;
+        HKLDRMOD hMod3;
+        printf("tst-0-driver: hMod=%p ('tst-0-a')\n", (void *)hMod);
+
+        /*
+         * Simple test of kLdrDyldFindByName.
+         */
+        hMod2 = (HKLDRMOD)0xffffeeee;
+        rc = kLdrDyldFindByName("tst-0", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod2);
+        if (!rc)
+            Failure("kLdrDyldFindByName(\"tst-0\",,,) didn't fail!\n");
+        if (rc && hMod2 != NIL_HKLDRMOD)
+            Failure("hMod2 wasn't set correctly on kLdrDyldFindByName failure!\n");
+
+        hMod2 = (HKLDRMOD)0xffffeeee;
+        rc = kLdrDyldFindByName("tst-0-a", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod2);
+        if (rc)
+            Failure("kLdrDyldFindByName(\"tst-0-a\",,,) failed, rc=%d (%#x)\n", rc, rc);
+        if (!rc && hMod2 != hMod)
+            Failure("kLdrDyldFindByName(\"tst-0-a\",,,) returned the wrong module handle: %p instead of %p\n",
+                    (void *)hMod2, (void *)hMod);
+
+        hMod2 = (HKLDRMOD)0xffffeeee;
+        rc = kLdrDyldFindByName("tst-0-d", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod2);
+        if (!rc)
+            printf("tst-0-driver: hMod2=%p ('tst-0-d')\n", (void *)hMod2);
+        else
+            Failure("kLdrDyldFindByName(\"tst-0-d\",,,) failed, rc=%d (%#x)\n", rc, rc);
+
+        /*
+         * Get the name and filename for each of the two modules.
+         */
+        rc = kLdrDyldGetName(hMod2, szBuf, sizeof(szBuf));
+        if (!rc)
+        {
+            printf("tst-0-driver: name: '%s' ('tst-0-d')\n", szBuf);
+            psz = strstr(szBuf, "-0-");
+            if (    !psz
+                ||  strnicmp(psz, "-0-d", sizeof("-0-d") - 1))
+                Failure("kLdrDyldGetName(\"tst-0-d\",,,) -> '%s': pattern '-0-d' not found\n", szBuf);
+
+            /* overflow test. */
+            cch = strlen(szBuf);
+            szBuf[cch + 1] = szBuf[cch] = szBuf[cch - 1] = 'x';
+            szBuf[cch + 2] = '\0';
+            rc = kLdrDyldGetName(hMod2, szBuf, cch);
+            if (rc == KERR_BUFFER_OVERFLOW)
+            {
+                if (!szBuf[0])
+                    Failure("kLdrDyldGetName didn't return partial result on overflow\n");
+                else if (szBuf[cch - 1])
+                    Failure("kLdrDyldGetName didn't terminate partial result correctly overflow: '%s'\n", szBuf);
+                else if (szBuf[cch] != 'x')
+                    Failure("kLdrDyldGetName exceeded the buffer limit on partial overflow: '%s'\n", szBuf);
+            }
+            else
+                Failure("kLdrDyldGetName(\"tst-0-d\",,,) -> rc=%d (%#x) instead of KERR_BUFFER_OVERFLOW\n", rc, rc);
+
+            /* check that we can query the module by the returned name. */
+            rc = kLdrDyldGetName(hMod2, szBuf, sizeof(szBuf));
+            if (!rc)
+            {
+                hMod3 = (HKLDRMOD)0xffffeeee;
+                rc = kLdrDyldFindByName(szBuf, NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod3);
+                if (rc || hMod3 != hMod2)
+                    Failure("kLdrDyldFindByName(\"%s\",,,) failed, rc=%d (%#x) hMod3=%p hMod2=%p\n",
+                            szBuf, rc, rc, (void *)hMod3, (void *)hMod2);
+            }
+            else
+                Failure("kLdrDyldGetName(\"tst-0-d\",,,) failed (b), rc=%d (%#x)\n", rc, rc);
+        }
+        else
+            Failure("kLdrDyldGetName(\"tst-0-d\",,,) failed, rc=%d (%#x)\n", rc, rc);
+
+        rc = kLdrDyldGetFilename(hMod2, szBuf, sizeof(szBuf));
+        if (!rc)
+        {
+            printf("tst-0-driver: filename: '%s' ('tst-0-d')\n", szBuf);
+
+            /* overflow test. */
+            cch = strlen(szBuf);
+            szBuf[cch + 1] = szBuf[cch] = szBuf[cch - 1] = 'x';
+            szBuf[cch + 2] = '\0';
+            rc = kLdrDyldGetFilename(hMod2, szBuf, cch);
+            if (rc == KERR_BUFFER_OVERFLOW)
+            {
+                if (!szBuf[0])
+                    Failure("kLdrDyldGetFilename didn't return partial result on overflow\n");
+                else if (szBuf[cch - 1])
+                    Failure("kLdrDyldGetFilename didn't terminate partial result correctly overflow: '%s'\n", szBuf);
+                else if (szBuf[cch] != 'x')
+                    Failure("kLdrDyldGetFilename exceeded the buffer limit on partial overflow: '%s'\n", szBuf);
+            }
+            else
+                Failure("kLdrDyldGetFilename(\"tst-0-d\",,,) -> rc=%d (%#x) instead of KERR_BUFFER_OVERFLOW\n", rc, rc);
+
+            /* check that we can query the module by the returned filename. */
+            rc = kLdrDyldGetFilename(hMod2, szBuf, sizeof(szBuf));
+            if (!rc)
+            {
+                hMod3 = (HKLDRMOD)0xffffeeee;
+                rc = kLdrDyldFindByName(szBuf, NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod3);
+                if (rc || hMod3 != hMod2)
+                    Failure("kLdrDyldFindByName(\"%s\",,,) failed, rc=%d (%#x) hMod3=%p hMod2=%p\n",
+                            szBuf, rc, rc, (void *)hMod3, (void *)hMod2);
+            }
+            else
+                Failure("kLdrDyldGetName(\"tst-0-d\",,,) failed (b), rc=%d (%#x)\n", rc, rc);
+        }
+        else
+            Failure("kLdrDyldGetFilename(\"tst-0-d\",,,) failed, rc=%d (%#x)\n", rc, rc);
+
+        /* the other module */
+        rc = kLdrDyldGetName(hMod, szBuf, sizeof(szBuf));
+        if (!rc)
+        {
+            printf("tst-0-driver: name: '%s' ('tst-0-a')\n", szBuf);
+            psz = strstr(szBuf, "-0-");
+            if (    !psz
+                ||  strnicmp(psz, "-0-a", sizeof("-0-a") - 1))
+                Failure("kLdrDyldGetName(\"tst-0-a\",,,) -> '%s': pattern '-0-a' not found\n", szBuf);
+
+            /* check that we can query the module by the returned name. */
+            hMod3 = (HKLDRMOD)0xffffeeee;
+            rc = kLdrDyldFindByName(szBuf, NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod3);
+            if (rc || hMod3 != hMod)
+                Failure("kLdrDyldFindByName(\"%s\",,,) failed, rc=%d (%#x) hMod3=%p hMod=%p\n",
+                        szBuf, rc, rc, (void *)hMod3, (void *)hMod);
+        }
+        else
+            Failure("kLdrDyldGetName(\"tst-0-a\",,,) failed, rc=%d (%#x)\n", rc, rc);
+
+        rc = kLdrDyldGetFilename(hMod, szBuf, sizeof(szBuf));
+        if (!rc)
+        {
+            printf("tst-0-driver: filename: '%s' ('tst-0-a')\n", szBuf);
+
+            /* check that we can query the module by the returned filename. */
+            hMod3 = (HKLDRMOD)0xffffeeee;
+            rc = kLdrDyldFindByName(szBuf, NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod3);
+            if (rc || hMod3 != hMod)
+                Failure("kLdrDyldFindByName(\"%s\",,,) failed, rc=%d (%#x) hMod3=%p hMod=%p\n",
+                        szBuf, rc, rc, (void *)hMod3, (void *)hMod);
+        }
+        else
+            Failure("kLdrDyldGetFilename(\"tst-0-a\",,,) failed, rc=%d (%#x)\n", rc, rc);
+
+
+        /*
+         * Resolve the symbol exported by each of the two modules and call them.
+         */
+        if (!g_cErrors)
+        {
+            KUPTR uValue;
+            KU32  fKind;
+
+            fKind = 0xffeeffee;
+            uValue = ~(KUPTR)42;
+            rc = kLdrDyldQuerySymbol(hMod, NIL_KLDRMOD_SYM_ORDINAL, MY_NAME("FuncA"), NULL, &uValue, &fKind);
+            if (!rc)
+            {
+                if (uValue == ~(KUPTR)42)
+                    Failure("kLdrDyldQuerySymbol(\"tst-0-a\",,\"FuncA\",): uValue wasn't set.\n");
+                if (fKind == 0xffeeffee)
+                    Failure("kLdrDyldQuerySymbol(\"tst-0-a\",,\"FuncA\",): fKind wasn't set.\n");
+                if (    (fKind & KLDRSYMKIND_BIT_MASK) != KLDRSYMKIND_NO_BIT
+                    &&  (fKind & KLDRSYMKIND_BIT_MASK) != MY_KLDRSYMKIND_BITS)
+                    Failure("fKind=%#x indicates a different code 'bit' mode than we running at.\n", fKind);
+                if (    (fKind & KLDRSYMKIND_TYPE_MASK) != KLDRSYMKIND_NO_TYPE
+                    &&  (fKind & KLDRSYMKIND_TYPE_MASK) != KLDRSYMKIND_CODE)
+                    Failure("fKind=%#x indicates that \"FuncA\" isn't code.\n", fKind);
+                if (fKind & KLDRSYMKIND_FORWARDER)
+                    Failure("fKind=%#x indicates that \"FuncA\" is a forwarder. it isn't.\n", fKind);
+
+                /* call it. */
+                if (!g_cErrors)
+                {
+                    int (*pfnFuncA)(void) = (int (*)(void))uValue;
+                    rc = pfnFuncA();
+                    if (rc != 0x42000042)
+                        Failure("FuncA returned %#x expected 0x42000042\n", rc);
+                }
+
+                /*
+                 * Test kLdrDyldFindByAddress now that we've got an address.
+                 */
+                hMod3 = (HKLDRMOD)0xeeeeffff;
+                rc = kLdrDyldFindByAddress(uValue, &hMod3, NULL, NULL);
+                if (!rc)
+                {
+                    KUPTR offSegment;
+                    KU32 iSegment;
+
+                    if (hMod3 != hMod)
+                        Failure("kLdrDyldFindByAddress(%#p/*FuncA*/, \"tst-0-a\",,,) return incorrect hMod3=%p instead of %p.\n",
+                                uValue, hMod3, hMod);
+
+                    hMod3 = (HKLDRMOD)0xeeeeffff;
+                    iSegment = 0x42424242;
+                    rc = kLdrDyldFindByAddress(uValue, &hMod3, &iSegment, &offSegment);
+                    if (!rc)
+                    {
+                        if (hMod3 != hMod)
+                            Failure("Bad hMod3 on 2nd kLdrDyldFindByAddress call.\n");
+                        if (iSegment > 0x1000) /* safe guess */
+                            Failure("Bad iSegment=%#x\n", iSegment);
+                        if (offSegment > 0x100000) /* guesswork */
+                            Failure("Bad offSegment=%p\n", (void *)offSegment);
+                    }
+                    else
+                        Failure("kLdrDyldFindByAddress(%#p/*FuncA*/, \"tst-0-a\",,,) failed (b), rc=%d (%#x)\n",
+                                uValue, rc, rc);
+
+                    /* negative test */
+                    hMod3 = (HKLDRMOD)0xeeeeffff;
+                    iSegment = 0x42424242;
+                    offSegment = 0x87654321;
+                    rc = kLdrDyldFindByAddress(~(KUPTR)16, &hMod3, &iSegment, &offSegment);
+                    if (!rc)
+                        Failure("negative kLdrDyldFindByAddress test returned successfully!\n");
+                    if (iSegment != ~(KU32)0)
+                        Failure("negative kLdrDyldFindByAddress: bad iSegment=%#x\n", iSegment);
+                    if (offSegment != ~(KUPTR)0)
+                        Failure("negative kLdrDyldFindByAddress: bad offSegment=%p\n", (void *)offSegment);
+                    if (hMod3 != NIL_HKLDRMOD)
+                        Failure("negative kLdrDyldFindByAddress: bad hMod3=%p\n", (void *)hMod3);
+                }
+                else
+                    Failure("kLdrDyldFindByAddress(%#p/*FuncA*/, \"tst-0-a\",,,) failed, rc=%d (%#x)\n",
+                            uValue, rc, rc);
+            }
+            else
+                Failure("kLdrDyldQuerySymbol(\"tst-0-a\",,\"FuncA\",) failed, rc=%d (%#x)\n", rc, rc);
+
+            fKind = 0xffeeffee;
+            uValue = ~(KUPTR)42;
+            rc = kLdrDyldQuerySymbol(hMod2, NIL_KLDRMOD_SYM_ORDINAL, MY_NAME("FuncD"), NULL, &uValue, &fKind);
+            if (!rc)
+            {
+                if (uValue == ~(KUPTR)42)
+                    Failure("kLdrDyldQuerySymbol(\"tst-0-d\",,\"FuncD\",): uValue wasn't set.\n");
+                if (fKind == 0xffeeffee)
+                    Failure("kLdrDyldQuerySymbol(\"tst-0-d\",,\"FuncD\",): fKind wasn't set.\n");
+                if (    (fKind & KLDRSYMKIND_BIT_MASK) != KLDRSYMKIND_NO_BIT
+                    &&  (fKind & KLDRSYMKIND_BIT_MASK) != MY_KLDRSYMKIND_BITS)
+                    Failure("fKind=%#x indicates a different code 'bit' mode than we running at.\n", fKind);
+                if (    (fKind & KLDRSYMKIND_TYPE_MASK) != KLDRSYMKIND_NO_TYPE
+                    &&  (fKind & KLDRSYMKIND_TYPE_MASK) != KLDRSYMKIND_CODE)
+                    Failure("fKind=%#x indicates that \"FuncD\" isn't code.\n", fKind);
+                if (fKind & KLDRSYMKIND_FORWARDER)
+                    Failure("fKind=%#x indicates that \"FuncD\" is a forwarder. it isn't.\n", fKind);
+
+                /* call it. */
+                if (!g_cErrors)
+                {
+                    int (*pfnFuncD)(void) = (int (*)(void))uValue;
+                    rc = pfnFuncD();
+                    if (rc != 0x42000000)
+                        Failure("FuncD returned %#x expected 0x42000000\n", rc);
+                }
+
+                /* use the address to get the module handle. */
+                hMod3 = (HKLDRMOD)0xeeeeffff;
+                rc = kLdrDyldFindByAddress(uValue, &hMod3, NULL, NULL);
+                if (!rc)
+                {
+                    if (hMod3 != hMod2)
+                        Failure("kLdrDyldFindByAddress(%#p/*FuncD*/,,,) return incorrect hMod3=%p instead of %p.\n",
+                                uValue, hMod3, hMod2);
+                }
+                else
+                    Failure("kLdrDyldFindByAddress(%#p/*FuncD*/,,,) failed, rc=%d (%#x)\n",
+                            uValue, rc, rc);
+            }
+            else
+                Failure("kLdrDyldQuerySymbol(\"tst-0-a\",,\"FuncA\",) failed, rc=%d (%#x)\n", rc, rc);
+
+        }
+
+        /*
+         * Finally unload it.
+         */
+        rc = kLdrDyldUnload(hMod);
+        if (rc)
+            Failure("kLdrDyldUnload() failed. rc=%d (%#x)\n", rc, rc);
+        if (!rc)
+        {
+            rc = kLdrDyldFindByName("tst-0-d", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod2);
+            if (rc != KLDR_ERR_MODULE_NOT_FOUND)
+                Failure("kLdrDyldFindByName(\"tst-0-d\",,,) return rc=%d (%#x), expected KLDR_ERR_MODULE_NOT_FOUND\n", rc, rc);
+
+            rc = kLdrDyldFindByName("tst-0-a", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod2);
+            if (rc != KLDR_ERR_MODULE_NOT_FOUND)
+                Failure("kLdrDyldFindByName(\"tst-0-a\",,,) return rc=%d (%#x), expected KLDR_ERR_MODULE_NOT_FOUND\n", rc, rc);
+        }
+    }
+
+    /*
+     * Now do what tst-0 would do; load the three dlls, resolve and call their functions.
+     */
+    if (!g_cErrors)
+    {
+        HKLDRMOD hModA;
+        int (*pfnFuncA)(void);
+        HKLDRMOD hModB;
+        int (*pfnFuncB)(void);
+        HKLDRMOD hModC;
+        int (*pfnFuncC)(void);
+        KUPTR uValue;
+
+        rc = kLdrDyldLoad("tst-0-a", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hModA, NULL, 0);
+        if (rc)
+            Failure("kLdrDyldLoad(\"tst-0-a\",,,,) -> %d (%#x)\n", rc, rc);
+        if (!rc)
+        {
+            rc = kLdrDyldLoad("tst-0-b", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hModB, szErr, sizeof(szErr));
+            if (rc)
+                Failure("kLdrDyldLoad(\"tst-0-b\",,,,) -> %d (%#x) szErr='%s'\n", rc, rc, szErr);
+        }
+        if (!rc)
+        {
+            rc = kLdrDyldLoad("tst-0-c", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hModC, szErr, sizeof(szErr));
+            if (rc)
+                Failure("kLdrDyldLoad(\"tst-0-c\",,,,) -> %d (%#x) szErr='%s'\n", rc, rc, szErr);
+        }
+        if (!rc)
+        {
+            rc = kLdrDyldQuerySymbol(hModA, NIL_KLDRMOD_SYM_ORDINAL, MY_NAME("FuncA"), NULL, &uValue, NULL);
+            if (!rc)
+                pfnFuncA = (int (*)(void))uValue;
+            else
+                Failure("kLdrDyldQuerySymbol(,,\"FuncA\",,) -> %d (%#x)\n", rc, rc);
+        }
+        if (!rc)
+        {
+            rc = kLdrDyldQuerySymbol(hModB, NIL_KLDRMOD_SYM_ORDINAL, MY_NAME("FuncB"), NULL, &uValue, NULL);
+            if (!rc)
+                pfnFuncB = (int (*)(void))uValue;
+            else
+                Failure("kLdrDyldQuerySymbol(,,\"FuncB\",,) -> %d (%#x)\n", rc, rc);
+        }
+        if (!rc)
+        {
+            rc = kLdrDyldQuerySymbol(hModC, NIL_KLDRMOD_SYM_ORDINAL, MY_NAME("FuncC"), NULL, &uValue, NULL);
+            if (!rc)
+                pfnFuncC = (int (*)(void))uValue;
+            else
+                Failure("kLdrDyldQuerySymbol(,,\"FuncA\",,) -> %d (%#x)\n", rc, rc);
+        }
+        if (!rc)
+        {
+            int u = pfnFuncA() | pfnFuncB() | pfnFuncC();
+            if (u == 0x42424242)
+                printf("tst-0-driver: FuncA/B/C => %#x (correct)\n", u);
+            else
+                Failure("FuncA/B/C => %#x\n", u);
+
+            rc = kLdrDyldUnload(hModA);
+            if (rc)
+                Failure("Unload A failed, rc=%d (%#x)\n", rc, rc);
+            u = pfnFuncB() | pfnFuncC();
+            if (u != 0x42424200)
+                Failure("FuncB/C returns %#x instead of 0x42424200 after unloading A\n", u);
+
+            rc = kLdrDyldUnload(hModB);
+            if (rc)
+                Failure("Unload B failed, rc=%d (%#x)\n", rc, rc);
+            u = pfnFuncC();
+            if (u != 0x42420000)
+                Failure("FuncC returns %#x instead of 0x42420000 after unloading A\n", u);
+
+            rc = kLdrDyldUnload(hModC);
+            if (rc)
+                Failure("Unload C failed, rc=%d (%#x)\n", rc, rc);
+
+            rc = kLdrDyldFindByName("tst-0-d", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod);
+            if (rc != KLDR_ERR_MODULE_NOT_FOUND)
+                Failure("Query for \"tst-0-d\" after unloading A,B and C returns rc=%d (%#x) instead of KLDR_ERR_MODULE_NOT_FOUND\n",
+                        rc, rc);
+        }
+    }
+
+    /*
+     * Now invoke the executable stub which launches the tst-0 program.
+     */
+    if (!g_cErrors)
+    {
+        /// @todo
+    }
+
+    /*
+     * Summary
+     */
+    if (!g_cErrors)
+        printf("tst-0-driver: SUCCESS\n");
+    else
+        printf("tst-0-driver: FAILURE - %d errors\n", g_cErrors);
+    return !!g_cErrors;
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-0.c b/src/lib/kStuff/kLdr/testcase/tst-0.c
new file mode 100644
index 0000000..d19c35c
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-0.c
@@ -0,0 +1,13 @@
+#include "tst.h"
+
+MY_IMPORT(int) FuncA(void);
+MY_IMPORT(int) FuncB(void);
+MY_IMPORT(int) FuncC(void);
+
+int main()
+{
+    unsigned u;
+    u = FuncA() | FuncB() | FuncC();
+    return u == 0x42424242 ? 0 : 1;
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-1-a.c b/src/lib/kStuff/kLdr/testcase/tst-1-a.c
new file mode 100644
index 0000000..d554112
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-1-a.c
@@ -0,0 +1,10 @@
+#include "tst.h"
+const char *g_pszName = "a";
+
+MY_IMPORT(int) FuncD(void);
+
+MY_EXPORT(int) FuncA(void)
+{
+    return FuncD();
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-1-b.c b/src/lib/kStuff/kLdr/testcase/tst-1-b.c
new file mode 100644
index 0000000..5156e58
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-1-b.c
@@ -0,0 +1,10 @@
+#include "tst.h"
+const char *g_pszName = "b";
+
+MY_IMPORT(int) FuncD(void);
+
+MY_EXPORT(int) FuncB(void)
+{
+    return FuncD();
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-1-c.c b/src/lib/kStuff/kLdr/testcase/tst-1-c.c
new file mode 100644
index 0000000..c40f55d
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-1-c.c
@@ -0,0 +1,10 @@
+#include "tst.h"
+const char *g_pszName = "c";
+
+MY_IMPORT(int) FuncD(void);
+
+MY_EXPORT(int) FuncC(void)
+{
+    return FuncD();
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-1-d.c b/src/lib/kStuff/kLdr/testcase/tst-1-d.c
new file mode 100644
index 0000000..ab8bf93
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-1-d.c
@@ -0,0 +1,8 @@
+#include "tst.h"
+const char *g_pszName = "d";
+
+MY_EXPORT(int) FuncD(void)
+{
+    return 0;
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-1.c b/src/lib/kStuff/kLdr/testcase/tst-1.c
new file mode 100644
index 0000000..58b9770
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-1.c
@@ -0,0 +1,15 @@
+#include "tst.h"
+#include <stdio.h>
+
+MY_IMPORT(int) FuncA(void);
+MY_IMPORT(int) FuncB(void);
+MY_IMPORT(int) FuncC(void);
+
+int main()
+{
+    printf("graph:\n"
+           "  tst-1 -> a -> d\n"
+           "           b -> d\n"
+           "           c -> d\n");
+    return FuncA() + FuncB() + FuncC();
+}
diff --git a/src/lib/kStuff/kLdr/testcase/tst-2-a.c b/src/lib/kStuff/kLdr/testcase/tst-2-a.c
new file mode 100644
index 0000000..274f92e
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-2-a.c
@@ -0,0 +1,8 @@
+#include "tst.h"
+const char *g_pszName = "a";
+
+MY_EXPORT(int) FuncA(void)
+{
+    return 0;
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-2-b.c b/src/lib/kStuff/kLdr/testcase/tst-2-b.c
new file mode 100644
index 0000000..63c2c58
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-2-b.c
@@ -0,0 +1,10 @@
+#include "tst.h"
+const char *g_pszName = "b";
+
+MY_IMPORT(int) FuncA(void);
+
+MY_EXPORT(int) FuncB(void)
+{
+    return FuncA();
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-2-c.c b/src/lib/kStuff/kLdr/testcase/tst-2-c.c
new file mode 100644
index 0000000..29ab68f
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-2-c.c
@@ -0,0 +1,10 @@
+#include "tst.h"
+const char *g_pszName = "c";
+
+MY_IMPORT(int) FuncA(void);
+
+MY_EXPORT(int) FuncC(void)
+{
+    return FuncA();
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-2-d.c b/src/lib/kStuff/kLdr/testcase/tst-2-d.c
new file mode 100644
index 0000000..34efd0a
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-2-d.c
@@ -0,0 +1,10 @@
+#include "tst.h"
+const char *g_pszName = "d";
+
+MY_IMPORT(int) FuncA(void);
+
+MY_EXPORT(int) FuncD(void)
+{
+    return FuncA();
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-2.c b/src/lib/kStuff/kLdr/testcase/tst-2.c
new file mode 100644
index 0000000..6110a4b
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-2.c
@@ -0,0 +1,16 @@
+#include "tst.h"
+
+MY_IMPORT(int) FuncA(void);
+MY_IMPORT(int) FuncB(void);
+MY_IMPORT(int) FuncC(void);
+MY_IMPORT(int) FuncD(void);
+
+int main()
+{
+    printf("graph:\n"
+           "  tst-2 -> b -> a\n"
+           "           c -> a\n"
+           "           d -> a\n"
+           "           a\n");
+    return FuncA() + FuncB() + FuncC() + FuncD();
+}
diff --git a/src/lib/kStuff/kLdr/testcase/tst-3-driver.c b/src/lib/kStuff/kLdr/testcase/tst-3-driver.c
new file mode 100644
index 0000000..483a585
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-3-driver.c
@@ -0,0 +1,216 @@
+/* $Id: tst-3-driver.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - Dynamic Loader testcase no. 3, Driver.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "tst.h"
+#include <k/kErr.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _MSC_VER
+# include <malloc.h>
+#endif
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** Select the appropriate KLDRSYMKIND bit define. */
+#define MY_KLDRSYMKIND_BITS     ( sizeof(void *) == 4 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT )
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** The numbers of errors. */
+static int g_cErrors = 0;
+
+
+/**
+ * Report failure.
+ */
+static int Failure(const char *pszFormat, ...)
+{
+    va_list va;
+
+    g_cErrors++;
+
+    printf("tst-3-driver: ");
+    va_start(va, pszFormat);
+    vprintf(pszFormat, va);
+    va_end(va);
+    printf("\n");
+    return 1;
+}
+
+
+/**
+ * External symbol used by the testcase module.
+ */
+static int Tst3Ext(int iFortyTwo)
+{
+    if (iFortyTwo != 42)
+        return 256;
+    return 42;
+}
+
+
+/**
+ * Callback for resolving the Tst3Ext import.
+ */
+static int GetImport(PKLDRMOD pMod, KU32 iImport, KU32 iSymbol, const char *pchSymbol, KSIZE cchSymbol,
+                     const char *pszVersion, PKLDRADDR puValue, KU32 *pfKind, void *pvUser)
+{
+    if (*pfKind != KLDRSYMKIND_REQ_FLAT)
+        return -1;
+
+    if (    !strncmp(pchSymbol, "Tst3Ext", strlen("Tst3Ext"))
+        ||  !strncmp(pchSymbol, "_Tst3Ext", strlen("_Tst3Ext")))
+    {
+        *puValue = (KUPTR)&Tst3Ext;
+        *pfKind = KLDRSYMKIND_CODE | (sizeof(pfKind) == 4 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT);
+        return 0;
+    }
+
+    return -2;
+}
+
+
+/**
+ * Performs the tests on one module.
+ * @returns non sense.
+ */
+int TestModule(const char *pszFile)
+{
+    PKLDRMOD pMod;
+    KLDRSIZE cbImage;
+    void *pvBits;
+    int rc;
+
+    printf("tst-3-driver: testing '%s'...\n", pszFile);
+
+    /* open it. */
+    rc = kLdrModOpen(pszFile, &pMod);
+    if (rc)
+        return Failure("kLdrModOpen(%s,) -> %#d (%s)\n", pszFile, rc, kErrName(rc));
+
+    /* get bits. */
+    cbImage = kLdrModSize(pMod);
+    pvBits = malloc((KSIZE)cbImage + 0xfff);
+    if (pvBits)
+    {
+        void *pvBits2 = (void *)( ((KUPTR)pvBits + 0xfff) & ~(KUPTR)0xfff );
+
+        KLDRADDR BaseAddress = (KUPTR)pvBits2;
+        rc = kLdrModGetBits(pMod, pvBits2, BaseAddress, GetImport, NULL);
+        if (!rc)
+        {
+            KLDRADDR EntryPoint;
+
+            /* call into it */
+            rc = kLdrModQuerySymbol(pMod, pvBits2, BaseAddress, NIL_KLDRMOD_SYM_ORDINAL, "_Tst3", strlen("_Tst3"), NULL, NULL, NULL,
+                                    &EntryPoint, NULL);
+            if (rc == KLDR_ERR_SYMBOL_NOT_FOUND)
+                rc = kLdrModQuerySymbol(pMod, pvBits2, BaseAddress, NIL_KLDRMOD_SYM_ORDINAL, "Tst3", strlen("Tst3"), NULL, NULL, NULL,
+                                        &EntryPoint, NULL);
+            if (!rc)
+            {
+                int (*pfnEntryPoint)(int) = (int (*)(int)) ((KUPTR)EntryPoint);
+                rc = pfnEntryPoint(42);
+                if (rc == 42)
+                {
+                    /* relocate twice and try again. */
+                    rc = kLdrModRelocateBits(pMod, pvBits2, BaseAddress + 0x22000, BaseAddress, GetImport, NULL);
+                    if (!rc)
+                    {
+                        rc = kLdrModRelocateBits(pMod, pvBits2, BaseAddress, BaseAddress + 0x22000, GetImport, NULL);
+                        if (!rc)
+                        {
+                            rc = pfnEntryPoint(42);
+                            if (rc == 42)
+                            {
+                                printf("tst-3-driver: success.\n");
+                            }
+                            else
+                                Failure("pfnEntryPoint(42) -> %d (2nd)\n", rc);
+                        }
+                        else
+                            Failure("kLdrModRelocateBits(,,, + 0x22000,,,) -> %#x (%s)\n", rc, kErrName(rc));
+                    }
+                    else
+                        Failure("kLdrModRelocateBits(,, + 0x22000,,,,) -> %#x (%s)\n", rc, kErrName(rc));
+                }
+                else
+                    Failure("pfnEntryPoint(42) -> %d (1st)\n", rc);
+            }
+            else
+                Failure("kLdrModQuerySymbol -> %#x (%s)\n", rc, kErrName(rc));
+        }
+        else
+            Failure("kLdrModGetBits -> %#x (%s)\n", rc, kErrName(rc));
+        free(pvBits);
+    }
+    else
+        Failure("malloc(%lx) -> NULL\n", (long)cbImage);
+
+    /* clean up */
+    rc = kLdrModClose(pMod);
+    if (rc)
+        Failure("kLdrModOpen(%s,) -> %#x (%s)\n", pszFile, rc, kErrName(rc));
+    return 0;
+}
+
+
+int main(int argc, char **argv)
+{
+    int i;
+
+    /*
+     * Test all the given modules (requires arguments).
+     */
+    for (i = 1; i < argc; i++)
+    {
+        TestModule(argv[i]);
+    }
+
+
+    /*
+     * Summary
+     */
+    if (!g_cErrors)
+        printf("tst-3-driver: SUCCESS\n");
+    else
+        printf("tst-3-driver: FAILURE - %d errors\n", g_cErrors);
+    return !!g_cErrors;
+}
diff --git a/src/lib/kStuff/kLdr/testcase/tst-3-ext.c b/src/lib/kStuff/kLdr/testcase/tst-3-ext.c
new file mode 100644
index 0000000..2b4c839
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-3-ext.c
@@ -0,0 +1,39 @@
+/* $Id: tst-3-ext.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - Dynamic Loader testcase no. 3, 2nd object module.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "tst.h"
+
+extern int g_i1;
+
+int Tst3Sub(int iFortyTwo)
+{
+    return iFortyTwo * 11 * g_i1;
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-3-imp-os2.def b/src/lib/kStuff/kLdr/testcase/tst-3-imp-os2.def
new file mode 100644
index 0000000..9ec3b13
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-3-imp-os2.def
@@ -0,0 +1,34 @@
+; $Id: tst-3-imp-os2.def 29 2009-07-01 20:30:29Z bird $
+;; @file
+; kLdr - Dynamic Loader testcase no. 3, Fake module import library - OS/2.
+;
+
+;
+; Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+;
+; Permission is hereby granted, free of charge, to any person
+; obtaining a copy of this software and associated documentation
+; files (the "Software"), to deal in the Software without
+; restriction, including without limitation the rights to use,
+; copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of the Software, and to permit persons to whom the
+; Software is furnished to do so, subject to the following
+; conditions:
+;
+; The above copyright notice and this permission notice shall be
+; included in all copies or substantial portions of the Software.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+; OTHER DEALINGS IN THE SOFTWARE.
+;
+
+LIBRARY tst-3-imp
+EXPORTS
+    _Tst3Ext
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-3-imp-win.def b/src/lib/kStuff/kLdr/testcase/tst-3-imp-win.def
new file mode 100644
index 0000000..7381804
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-3-imp-win.def
@@ -0,0 +1,34 @@
+; $Id: tst-3-imp-win.def 29 2009-07-01 20:30:29Z bird $
+;; @file
+; kLdr - Dynamic Loader testcase no. 3, Fake module import library - Windows.
+;
+
+;
+; Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+;
+; Permission is hereby granted, free of charge, to any person
+; obtaining a copy of this software and associated documentation
+; files (the "Software"), to deal in the Software without
+; restriction, including without limitation the rights to use,
+; copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of the Software, and to permit persons to whom the
+; Software is furnished to do so, subject to the following
+; conditions:
+;
+; The above copyright notice and this permission notice shall be
+; included in all copies or substantial portions of the Software.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+; OTHER DEALINGS IN THE SOFTWARE.
+;
+
+LIBRARY tst-3-imp
+EXPORTS
+    Tst3Ext
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst-3.c b/src/lib/kStuff/kLdr/testcase/tst-3.c
new file mode 100644
index 0000000..ed89d9e
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst-3.c
@@ -0,0 +1,78 @@
+/* $Id: tst-3.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - Dynamic Loader testcase no. 3, Driver.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "tst.h"
+
+
+int g_i1 = 1;
+int g_i2 = 2;
+int *g_pi1 = &g_i1;
+
+extern int Tst3Sub(int);
+int (*g_pfnTst3Sub)(int) = &Tst3Sub;
+
+MY_IMPORT(int) Tst3Ext(int);
+int (*g_pfnTst3Ext)(int) = &Tst3Ext;
+
+char g_achBss[256];
+
+
+MY_EXPORT(int) Tst3(int iFortyTwo)
+{
+    int rc;
+
+    if (iFortyTwo != 42)
+        return 0;
+    if (g_i1 != 1)
+        return 1;
+    if (g_i2 != 2)
+        return 2;
+    if (g_pi1 != &g_i1)
+        return 3;
+    if (g_pfnTst3Sub != &Tst3Sub)
+        return 4;
+    rc = Tst3Sub(iFortyTwo);
+    if (rc != g_pfnTst3Sub(iFortyTwo))
+        return 5;
+    rc = Tst3Ext(iFortyTwo);
+    if (rc != 42)
+        return 6;
+    rc = g_pfnTst3Ext(iFortyTwo);
+    if (rc != 42)
+        return 7;
+    for (rc = 0; rc < sizeof(g_achBss); rc++)
+        if (g_achBss[rc])
+            return 8;
+    if (g_achBss[0] || g_achBss[1] || g_achBss[255])
+        return 9;
+
+    return 42;
+}
+
diff --git a/src/lib/kStuff/kLdr/testcase/tst.h b/src/lib/kStuff/kLdr/testcase/tst.h
new file mode 100644
index 0000000..f06dba7
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tst.h
@@ -0,0 +1,57 @@
+/* $Id: tst.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr testcase header.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___tst_h___
+#define ___tst_h___
+
+#include <k/kLdr.h>
+#include <k/kHlp.h>
+
+#if K_OS == K_OS_OS2 \
+ || K_OS == K_OS_WINDOWS
+# define MY_EXPORT(type) __declspec(dllexport) type
+/*# define MY_IMPORT(type) extern __declspec(dllimport) type*/
+# define MY_IMPORT(type) extern type
+#else
+# define MY_EXPORT(type) type
+# define MY_IMPORT(type) extern type
+#endif
+
+#if K_OS == K_OS_OS2 \
+ || K_OS == K_OS_DARWIN
+# define MY_NAME(a) "_" a
+#else
+# define MY_NAME(a) a
+#endif
+
+extern const char *g_pszName;
+
+#endif
+
diff --git a/src/lib/kStuff/kLdr/testcase/tstDllMain.c b/src/lib/kStuff/kLdr/testcase/tstDllMain.c
new file mode 100644
index 0000000..b86819c
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tstDllMain.c
@@ -0,0 +1,192 @@
+/* $Id: tstDllMain.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr testcase.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "tst.h"
+
+#if K_OS == K_OS_OS2
+# define INCL_BASE
+# include <os2.h>
+# include <string.h>
+
+#elif K_OS == K_OS_WINDOWS
+# include <windows.h>
+# include <string.h>
+
+#elif K_OS == K_OS_DARWIN
+# include <unistd.h>
+# include <string.h>
+
+#else
+# error "port me"
+#endif
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+void tstWrite(const char *psz);
+
+
+
+#if K_OS == K_OS_OS2
+/**
+ * OS/2 DLL 'main'
+ */
+ULONG _System _DLL_InitTerm(HMODULE hmod, ULONG fFlags)
+{
+    switch (fFlags)
+    {
+        case 0:
+            tstWrite("init: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return TRUE;
+
+        case 1:
+            tstWrite("term: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return TRUE;
+
+        default:
+            tstWrite("!invalid!: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return FALSE;
+    }
+}
+
+#elif K_OS == K_OS_WINDOWS
+
+/**
+ * OS/2 DLL 'main'
+ */
+BOOL __stdcall DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved)
+{
+    switch (dwReason)
+    {
+        case DLL_PROCESS_ATTACH:
+            tstWrite("init: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return TRUE;
+
+        case DLL_PROCESS_DETACH:
+            tstWrite("term: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return TRUE;
+
+        case DLL_THREAD_ATTACH:
+            tstWrite("thread init: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return TRUE;
+
+        case DLL_THREAD_DETACH:
+            tstWrite("thread term: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return TRUE;
+
+        default:
+            tstWrite("!invalid!: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return FALSE;
+    }
+}
+
+#elif K_OS == K_OS_DARWIN
+/* later */
+
+#else
+# error "port me"
+#endif
+
+
+/**
+ * Writes a string with unix lineendings.
+ *
+ * @param   pszMsg  The string.
+ */
+void tstWrite(const char *pszMsg)
+{
+#if K_OS == K_OS_OS2 || K_OS == K_OS_WINDOWS
+    /*
+     * Line by line.
+     */
+    ULONG       cbWritten;
+    const char *pszNl = strchr(pszMsg, '\n');
+
+    while (pszNl)
+    {
+        cbWritten = pszNl - pszMsg;
+
+#if K_OS == K_OS_OS2
+        if (cbWritten)
+            DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
+        DosWrite((HFILE)2, "\r\n", 2, &cbWritten);
+#else
+        if (cbWritten)
+            WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
+        WriteFile((HANDLE)STD_ERROR_HANDLE, "\r\n", 2, &cbWritten, NULL);
+#endif
+
+        /* next */
+        pszMsg = pszNl + 1;
+        pszNl = strchr(pszMsg, '\n');
+    }
+
+    /*
+     * Remaining incomplete line.
+     */
+    if (*pszMsg)
+    {
+        cbWritten = strlen(pszMsg);
+#if K_OS == K_OS_OS2
+        DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
+#else
+        WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
+#endif
+    }
+
+#elif K_OS == K_OS_DARWIN
+    write(STDERR_FILENO, pszMsg, strlen(pszMsg));
+
+#else
+# error "port me"
+#endif
+}
+
+
diff --git a/src/lib/kStuff/kLdr/testcase/tstDllMainStub-os2.asm b/src/lib/kStuff/kLdr/testcase/tstDllMainStub-os2.asm
new file mode 100644
index 0000000..76dad01
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tstDllMainStub-os2.asm
@@ -0,0 +1,40 @@
+; $Id: tstDllMainStub-os2.asm 29 2009-07-01 20:30:29Z bird $
+;; @file
+; kLdr - OS/2 entry point thingy...
+;
+
+;
+; Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+;
+; Permission is hereby granted, free of charge, to any person
+; obtaining a copy of this software and associated documentation
+; files (the "Software"), to deal in the Software without
+; restriction, including without limitation the rights to use,
+; copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of the Software, and to permit persons to whom the
+; Software is furnished to do so, subject to the following
+; conditions:
+;
+; The above copyright notice and this permission notice shall be
+; included in all copies or substantial portions of the Software.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+; OTHER DEALINGS IN THE SOFTWARE.
+;
+
+segment TEXT32 public CLASS=CODE align=16 use32
+extern _DLL_InitTerm
+..start:
+    jmp _DLL_InitTerm
+
+segment DATA32 stack CLASS=DATA align=16 use32
+
+global WEAK$ZERO
+WEAK$ZERO EQU 0
+
diff --git a/src/lib/kStuff/kLdr/testcase/tstDllMainStub.c b/src/lib/kStuff/kLdr/testcase/tstDllMainStub.c
new file mode 100644
index 0000000..67681c8
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tstDllMainStub.c
@@ -0,0 +1,76 @@
+/* $Id: tstDllMainStub.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr testcase - DLL Stub.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "tst.h"
+
+#if K_OS == K_OS_OS2
+# define INCL_BASE
+# include <os2.h>
+
+#elif K_OS == K_OS_WINDOWS
+# include <windows.h>
+
+#elif K_OS == K_OS_DARWIN
+/* later */
+
+#else
+# error "port me"
+#endif
+
+
+#if K_OS == K_OS_OS2
+/**
+ * OS/2 DLL 'main'
+ */
+ULONG _System _DLL_InitTerm(HMODULE hmod, ULONG fFlag)
+{
+    return TRUE;
+}
+
+#elif K_OS == K_OS_WINDOWS
+
+/**
+ * Window DLL 'main'
+ */
+BOOL __stdcall DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved)
+{
+    return TRUE;
+}
+
+#elif K_OS == K_OS_DARWIN
+/* later */
+
+#else
+# error "port me"
+#endif
+
diff --git a/src/lib/kStuff/kLdr/testcase/tstExeMainStub-os2.asm b/src/lib/kStuff/kLdr/testcase/tstExeMainStub-os2.asm
new file mode 100644
index 0000000..d4a8ee9
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tstExeMainStub-os2.asm
@@ -0,0 +1,40 @@
+; $Id: tstExeMainStub-os2.asm 29 2009-07-01 20:30:29Z bird $
+;; @file
+; kLdr - OS/2 entry point thingy...
+;
+
+;
+; Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+;
+; Permission is hereby granted, free of charge, to any person
+; obtaining a copy of this software and associated documentation
+; files (the "Software"), to deal in the Software without
+; restriction, including without limitation the rights to use,
+; copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of the Software, and to permit persons to whom the
+; Software is furnished to do so, subject to the following
+; conditions:
+;
+; The above copyright notice and this permission notice shall be
+; included in all copies or substantial portions of the Software.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+; OTHER DEALINGS IN THE SOFTWARE.
+;
+
+segment TEXT32 public CLASS=CODE align=16 use32
+extern OS2Main
+..start:
+    jmp OS2Main
+
+segment DATA32 stack CLASS=DATA align=16 use32
+
+global WEAK$ZERO
+WEAK$ZERO EQU 0
+
diff --git a/src/lib/kStuff/kLdr/testcase/tstExeMainStub.c b/src/lib/kStuff/kLdr/testcase/tstExeMainStub.c
new file mode 100644
index 0000000..9ec9f47
--- /dev/null
+++ b/src/lib/kStuff/kLdr/testcase/tstExeMainStub.c
@@ -0,0 +1,93 @@
+/* $Id: tstExeMainStub.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr testcase - DLL Stub.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "tst.h"
+
+#if K_OS == K_OS_OS2
+# define INCL_BASE
+# include <os2.h>
+
+#elif K_OS == K_OS_WINDOWS
+/* nothing */
+
+#elif K_OS == K_OS_NT
+# include <ddk/ntapi.h> /** @todo fix the nt port. */
+
+#else
+# error "port me"
+#endif
+
+
+extern int main();
+
+
+#if K_OS == K_OS_OS2
+/**
+ * OS/2 'main'.
+ */
+ULONG _System OS2Main(HMODULE hmod, ULONG fFlag, ULONG ulReserved, PSZ pszzEnv, PSZ pszzCmdLine)
+{
+    int rc;
+    rc = main();
+    return rc;
+}
+
+#elif K_OS == K_OS_WINDOWS
+/**
+ * Windows'main'
+ */
+int WindowsMain(void)
+{
+    int rc;
+    rc = main();
+    return rc;
+}
+
+#elif K_OS == K_OS_NT
+/**
+ * Windows NT 'main'
+ */
+VOID NtProcess(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved)
+{
+    int rc;
+    rc = main();
+    /* (no way around this) */
+    for (;;)
+        ZwTerminateProcess(NtCurrentProcess(), rc);
+}
+
+#else
+# error "port me"
+#endif
+
+
diff --git a/src/lib/kStuff/kLdr/tg/KLDRSTATE.gif b/src/lib/kStuff/kLdr/tg/KLDRSTATE.gif
new file mode 100644
index 0000000..2c9004d
Binary files /dev/null and b/src/lib/kStuff/kLdr/tg/KLDRSTATE.gif differ
diff --git a/src/lib/kStuff/kLdr/tg/KLDRSTATE.txvstc b/src/lib/kStuff/kLdr/tg/KLDRSTATE.txvstc
new file mode 100644
index 0000000..fc4f3c8
--- /dev/null
+++ b/src/lib/kStuff/kLdr/tg/KLDRSTATE.txvstc
@@ -0,0 +1,529 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodeSet version="1.0">
+    <view uin="id83t9setug73fpetug74ah">
+        <property name="$metaclass" value="State Diagram"/>
+        <property name="@__options" value=""/>
+        <reference df-class-name="reference" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid4wa62etug73fpetug7hpd">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="90,40,80,40"/>
+            <property name="bounds_setted_by_user" value="true"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid4wa62etug73fpetug7hpd.linkid7iy6aetug73fpetugal1c:id83t9setug73fpetug74ah.nodeid4wa62etug73fpetug7hpd">
+                <property name="sourceAnchor" value="130,80"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="130,110"/>
+            </reference>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid4wa62etug73fpetug7hpd.linkid14j0oetug73fpetugbmyx:id83t9setug73fpetug74ah.nodeid4wa62etug73fpetug7hpd">
+                <property name="sourceAnchor" value="90,70"/>
+                <property name="bendpoints" value="30,70,30,1000"/>
+                <property name="targetAnchor" value="150,1000"/>
+                <property name="bounds_setted_by_user" value="true"/>
+                <reference referencedUin="linklabel:$transitionInplaceEditing:design:link:::id83t9setug73fpetug74ah.nodeid4wa62etug73fpetug7hpd.linkid14j0oetug73fpetugbmyx:id83t9setug73fpetug74ah.nodeid4wa62etug73fpetug7hpd">
+                    <property name="bounds" value="10,50,77,16"/>
+                </reference>
+            </reference>
+        </reference>
+        <reference df-class-name="reference1" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid67r7zetug73fpetug87g4">
+            <property name="$shortcutReference" value="true"/>
+            <property name="background_color" value="0,0,0"/>
+            <property name="bounds" value="120,0,12,12"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid67r7zetug73fpetug87g4.linkid2j70ketug73fpetug8gs8:id83t9setug73fpetug74ah.nodeid67r7zetug73fpetug87g4">
+                <property name="sourceAnchor" value="126,12"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="126,40"/>
+            </reference>
+        </reference>
+        <reference df-class-name="reference2" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeidd21uetug73fpetug8kak">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="90,110,80,40"/>
+            <property name="bounds_setted_by_user" value="true"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeidd21uetug73fpetug8kak.linkid7cno0etug73fpetuganpl:id83t9setug73fpetug74ah.nodeidd21uetug73fpetug8kak">
+                <property name="sourceAnchor" value="130,150"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="130,190"/>
+            </reference>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeidd21uetug73fpetug8kak.linkid4elkbetug73fpetugbpa9:id83t9setug73fpetug74ah.nodeidd21uetug73fpetug8kak">
+                <property name="sourceAnchor" value="90,140"/>
+                <property name="bendpoints" value="30,140,30,990"/>
+                <property name="targetAnchor" value="150,990"/>
+                <property name="bounds_setted_by_user" value="true"/>
+            </reference>
+        </reference>
+        <reference df-class-name="reference3" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeidq28metug73fpetug8uf9">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="320,110,110,40"/>
+            <property name="bounds_setted_by_user" value="true"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeidq28metug73fpetug8uf9.linkidd5q0etug73fpetugl30f:id83t9setug73fpetug74ah.nodeidq28metug73fpetug8uf9">
+                <property name="sourceAnchor" value="380,150"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="380,190"/>
+            </reference>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeidq28metug73fpetug8uf9.linkid2yl8cetug73fpetugl74g:id83t9setug73fpetug74ah.nodeidq28metug73fpetug8uf9">
+                <property name="sourceAnchor" value="430,140"/>
+                <property name="bendpoints" value="550,140,550,840"/>
+                <property name="targetAnchor" value="284,840"/>
+                <property name="bounds_setted_by_user" value="true"/>
+                <reference referencedUin="linklabel:$transitionInplaceEditing:design:link:::id83t9setug73fpetug74ah.nodeidq28metug73fpetug8uf9.linkid2yl8cetug73fpetugl74g:id83t9setug73fpetug74ah.nodeidq28metug73fpetug8uf9">
+                    <property name="bounds" value="470,120,77,16"/>
+                </reference>
+            </reference>
+        </reference>
+        <reference df-class-name="reference4" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid7et8etug73fpetug938l">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="80,190,135,40"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid7et8etug73fpetug938l.linkidr4phetug73fpetugcezv:id83t9setug73fpetug74ah.nodeid7et8etug73fpetug938l">
+                <property name="sourceAnchor" value="130,230"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="130,270"/>
+            </reference>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid7et8etug73fpetug938l.linkid82puetug73fpetugbwui:id83t9setug73fpetug74ah.nodeid7et8etug73fpetug938l">
+                <property name="sourceAnchor" value="80,220"/>
+                <property name="bendpoints" value="30,220,30,980"/>
+                <property name="targetAnchor" value="150,980"/>
+                <property name="bounds_setted_by_user" value="true"/>
+            </reference>
+        </reference>
+        <reference df-class-name="reference5" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid71qrcetug73fpetuga3zj">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="90,270,80,40"/>
+            <property name="bounds_setted_by_user" value="true"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid71qrcetug73fpetuga3zj.linkid4fiuhetug73fpetugbs4x:id83t9setug73fpetug74ah.nodeid71qrcetug73fpetuga3zj">
+                <property name="sourceAnchor" value="90,300"/>
+                <property name="bendpoints" value="30,300,30,970"/>
+                <property name="targetAnchor" value="150,970"/>
+                <property name="bounds_setted_by_user" value="true"/>
+            </reference>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid71qrcetug73fpetuga3zj.linkid8ewc7etug73fpetughpzu:id83t9setug73fpetug74ah.nodeid71qrcetug73fpetuga3zj">
+                <property name="sourceAnchor" value="130,310"/>
+                <property name="bendpoints" value="130,330,190,330"/>
+                <property name="targetAnchor" value="190,350"/>
+                <property name="bounds_setted_by_user" value="true"/>
+            </reference>
+        </reference>
+        <reference df-class-name="reference6" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid3wom6etug73fpetugb9cg">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="150,950,134,60"/>
+            <property name="bounds_setted_by_user" value="true"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid3wom6etug73fpetugb9cg.linkid80127etug73fpetugd66b:id83t9setug73fpetug74ah.nodeid3wom6etug73fpetugb9cg">
+                <property name="sourceAnchor" value="210,1010"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="210,1040"/>
+            </reference>
+        </reference>
+        <reference df-class-name="reference7" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid7vd8retug73fpetugcr3e">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="150,1040,134,40"/>
+            <property name="bounds_setted_by_user" value="true"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid7vd8retug73fpetugcr3e.linkid8h4qnetug73fpetugf6j3:id83t9setug73fpetug74ah.nodeid7vd8retug73fpetugcr3e">
+                <property name="sourceAnchor" value="208,1080"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="208,1110"/>
+            </reference>
+        </reference>
+        <reference df-class-name="reference8" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid417yeetug73fpetugeb3p">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="150,880,134,40"/>
+            <property name="bounds_setted_by_user" value="true"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid417yeetug73fpetugeb3p.linkid6ngyletug73fpetugehbp:id83t9setug73fpetug74ah.nodeid417yeetug73fpetugeb3p">
+                <property name="sourceAnchor" value="210,920"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="210,950"/>
+            </reference>
+        </reference>
+        <reference df-class-name="reference9" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="150,790,134,60"/>
+            <property name="bounds_setted_by_user" value="true"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5.linkid6vibeetug73fpetugephi:id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5">
+                <property name="sourceAnchor" value="210,850"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="210,880"/>
+            </reference>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5.linkid1izxmetug73fpetugesem:id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5">
+                <property name="sourceAnchor" value="260,790"/>
+                <property name="bendpoints" value="260,770,590,770,590,90,380,90"/>
+                <property name="targetAnchor" value="380,110"/>
+                <property name="bounds_setted_by_user" value="true"/>
+                <reference referencedUin="linklabel:$transitionInplaceEditing:design:link:::id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5.linkid1izxmetug73fpetugesem:id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5">
+                    <property name="bounds" value="290,750,84,16"/>
+                </reference>
+            </reference>
+        </reference>
+        <reference df-class-name="reference10" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid17bz7etug73fpetugf23i">
+            <property name="$shortcutReference" value="true"/>
+            <property name="background_color" value="0,0,0"/>
+            <property name="bounds" value="200,1110,15,15"/>
+        </reference>
+        <reference df-class-name="reference11" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid6b4f8etug73fpetugfa3i">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="150,380,129,40"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid6b4f8etug73fpetugfa3i.linkidy5coetug73fpetughmwy:id83t9setug73fpetug74ah.nodeid6b4f8etug73fpetugfa3i">
+                <property name="sourceAnchor" value="210,420"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="210,460"/>
+            </reference>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid6b4f8etug73fpetugfa3i.linkid989qmetug73fpetugi623:id83t9setug73fpetug74ah.nodeid6b4f8etug73fpetugfa3i">
+                <property name="sourceAnchor" value="150,410"/>
+                <property name="bendpoints" value="60,410,60,810"/>
+                <property name="targetAnchor" value="150,810"/>
+                <property name="bounds_setted_by_user" value="true"/>
+                <reference referencedUin="linklabel:$transitionInplaceEditing:design:link:::id83t9setug73fpetug74ah.nodeid6b4f8etug73fpetugfa3i.linkid989qmetug73fpetugi623:id83t9setug73fpetug74ah.nodeid6b4f8etug73fpetugfa3i">
+                    <property name="bounds" value="50,390,94,16"/>
+                </reference>
+            </reference>
+        </reference>
+        <reference df-class-name="reference12" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid2vt9ietug73fpetugfjhj">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="150,460,134,40"/>
+            <property name="bounds_setted_by_user" value="true"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid2vt9ietug73fpetugfjhj.linkid7b0d0etug73fpetughibe:id83t9setug73fpetug74ah.nodeid2vt9ietug73fpetugfjhj">
+                <property name="sourceAnchor" value="284,490"/>
+                <property name="bendpoints" value="460,490"/>
+                <property name="targetAnchor" value="460,540"/>
+                <property name="bounds_setted_by_user" value="true"/>
+                <reference referencedUin="linklabel:$transitionInplaceEditing:design:link:::id83t9setug73fpetug74ah.nodeid2vt9ietug73fpetugfjhj.linkid7b0d0etug73fpetughibe:id83t9setug73fpetug74ah.nodeid2vt9ietug73fpetugfjhj">
+                    <property name="bounds" value="290,490,42,16"/>
+                </reference>
+            </reference>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid2vt9ietug73fpetugfjhj.linkid2yeeuetug73fpetughfff:id83t9setug73fpetug74ah.nodeid2vt9ietug73fpetugfjhj">
+                <property name="sourceAnchor" value="210,500"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="210,540"/>
+            </reference>
+        </reference>
+        <reference df-class-name="reference13" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid8048etug73fpetugfpwv">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="150,540,134,50"/>
+            <property name="bounds_setted_by_user" value="true"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid8048etug73fpetugfpwv.linkid5imvsetug73fpetughcca:id83t9setug73fpetug74ah.nodeid8048etug73fpetugfpwv">
+                <property name="sourceAnchor" value="210,590"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="210,630"/>
+            </reference>
+        </reference>
+        <reference df-class-name="reference14" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeidswftetug73fpetugfwd3">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="150,630,131,40"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeidswftetug73fpetugfwd3.linkid7ockpetuqdc66etuqdq4c:id83t9setug73fpetug74ah.nodeidswftetug73fpetugfwd3">
+                <property name="sourceAnchor" value="281,650"/>
+                <property name="bendpoints" value="310,650,310,570"/>
+                <property name="targetAnchor" value="284,570"/>
+                <property name="bounds_setted_by_user" value="true"/>
+                <reference referencedUin="linklabel:$transitionInplaceEditing:design:link:::id83t9setug73fpetug74ah.nodeidswftetug73fpetugfwd3.linkid7ockpetuqdc66etuqdq4c:id83t9setug73fpetug74ah.nodeidswftetug73fpetugfwd3">
+                    <property name="bounds" value="290,650,84,16"/>
+                </reference>
+            </reference>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeidswftetug73fpetugfwd3.linkid3jvhdetug73fpetugiz5h:id83t9setug73fpetug74ah.nodeidswftetug73fpetugfwd3">
+                <property name="sourceAnchor" value="210,670"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="210,710"/>
+            </reference>
+        </reference>
+        <reference df-class-name="reference15" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid3z4oketug73fpetuggjl4">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="410,540,121,50"/>
+            <property name="bounds_setted_by_user" value="true"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid3z4oketug73fpetuggjl4.linkidotudetug73fpetugilak:id83t9setug73fpetug74ah.nodeid3z4oketug73fpetuggjl4">
+                <property name="sourceAnchor" value="460,590"/>
+                <property name="bendpoints" value="460,910"/>
+                <property name="targetAnchor" value="284,910"/>
+                <property name="bounds_setted_by_user" value="true"/>
+                <reference referencedUin="linklabel:$transitionInplaceEditing:design:link:::id83t9setug73fpetug74ah.nodeid3z4oketug73fpetuggjl4.linkidotudetug73fpetugilak:id83t9setug73fpetug74ah.nodeid3z4oketug73fpetuggjl4">
+                    <property name="bounds" value="470,600,45,16"/>
+                </reference>
+            </reference>
+        </reference>
+        <reference df-class-name="reference16" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid9bbfsetug73fpetugirr0">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="150,710,134,40"/>
+            <property name="bounds_setted_by_user" value="true"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid9bbfsetug73fpetugirr0.linkids5u8etug73fpetugj2bq:id83t9setug73fpetug74ah.nodeid9bbfsetug73fpetugirr0">
+                <property name="sourceAnchor" value="210,750"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="210,790"/>
+            </reference>
+        </reference>
+        <reference df-class-name="reference17" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid6t6upetug73fpetugj6k4">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="290,190,189,40"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid6t6upetug73fpetugj6k4.linkid529snetug73fpetuglmq0:id83t9setug73fpetug74ah.nodeid6t6upetug73fpetugj6k4">
+                <property name="sourceAnchor" value="479,220"/>
+                <property name="bendpoints" value="550,220,550,830"/>
+                <property name="targetAnchor" value="284,830"/>
+                <property name="bounds_setted_by_user" value="true"/>
+            </reference>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid6t6upetug73fpetugj6k4.linkid733w4etug73fpetuglagw:id83t9setug73fpetug74ah.nodeid6t6upetug73fpetugj6k4">
+                <property name="sourceAnchor" value="380,230"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="380,270"/>
+            </reference>
+        </reference>
+        <reference df-class-name="reference18" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid5e0mxetug73fpetugjk65">
+            <property name="$shortcutReference" value="true"/>
+            <property name="bounds" value="320,270,118,40"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid5e0mxetug73fpetugjk65.linkidcf8yetug73fpetuglj2g:id83t9setug73fpetug74ah.nodeid5e0mxetug73fpetugjk65">
+                <property name="sourceAnchor" value="438,300"/>
+                <property name="bendpoints" value="550,300,550,820"/>
+                <property name="targetAnchor" value="284,820"/>
+                <property name="bounds_setted_by_user" value="true"/>
+            </reference>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid5e0mxetug73fpetugjk65.linkid5watyetug73fpetugle5c:id83t9setug73fpetug74ah.nodeid5e0mxetug73fpetugjk65">
+                <property name="sourceAnchor" value="380,310"/>
+                <property name="bendpoints" value="380,330,230,330"/>
+                <property name="targetAnchor" value="230,350"/>
+                <property name="bounds_setted_by_user" value="true"/>
+            </reference>
+        </reference>
+        <reference df-class-name="reference19" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid6yrvpetui3nn8etui62p3">
+            <property name="$shortcutReference" value="true"/>
+            <property name="background_color" value="0,0,0"/>
+            <property name="bounds" value="180,350,60,6"/>
+            <reference referencedUin="design:link:::id83t9setug73fpetug74ah.nodeid6yrvpetui3nn8etui62p3.linkid4uffpetui3nn8etui6xmx:id83t9setug73fpetug74ah.nodeid6yrvpetui3nn8etui62p3">
+                <property name="sourceAnchor" value="210,356"/>
+                <property name="bendpoints" value=""/>
+                <property name="targetAnchor" value="210,380"/>
+                <reference referencedUin="linklabel:$transitionInplaceEditing:design:link:::id83t9setug73fpetug74ah.nodeid6yrvpetui3nn8etui62p3.linkid4uffpetui3nn8etui6xmx:id83t9setug73fpetug74ah.nodeid6yrvpetui3nn8etui62p3">
+                    <property name="bounds" value="220,360,122,16"/>
+                </reference>
+            </reference>
+        </reference>
+    </view>
+    <node uin="id83t9setug73fpetug74ah.nodeid4wa62etug73fpetug7hpd">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="Open"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid4wa62etug73fpetug7hpd.linkid7iy6aetug73fpetugal1c">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeidd21uetug73fpetug8kak"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid4wa62etug73fpetug7hpd"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+        <link uin="id83t9setug73fpetug74ah.nodeid4wa62etug73fpetug7hpd.linkid14j0oetug73fpetugbmyx">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid3wom6etug73fpetugb9cg"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid4wa62etug73fpetug7hpd"/>
+            <property name="$metaclass" value="Transition"/>
+            <property name="$event_name" value="done (failed)"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid67r7zetug73fpetug87g4">
+        <property name="$metaclass" value="Start State"/>
+        <property name="$name" value="StartState1"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid67r7zetug73fpetug87g4.linkid2j70ketug73fpetug8gs8">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid4wa62etug73fpetug7hpd"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid67r7zetug73fpetug87g4"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeidd21uetug73fpetug8kak">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="Mapped"/>
+        <link uin="id83t9setug73fpetug74ah.nodeidd21uetug73fpetug8kak.linkid7cno0etug73fpetuganpl">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid7et8etug73fpetug938l"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeidd21uetug73fpetug8kak"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+        <link uin="id83t9setug73fpetug74ah.nodeidd21uetug73fpetug8kak.linkid4elkbetug73fpetugbpa9">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid3wom6etug73fpetugb9cg"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeidd21uetug73fpetug8kak"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeidq28metug73fpetug8uf9">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="Reloaded"/>
+        <link uin="id83t9setug73fpetug74ah.nodeidq28metug73fpetug8uf9.linkidd5q0etug73fpetugl30f">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid6t6upetug73fpetugj6k4"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeidq28metug73fpetug8uf9"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+        <link uin="id83t9setug73fpetug74ah.nodeidq28metug73fpetug8uf9.linkid2yl8cetug73fpetugl74g">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeidq28metug73fpetug8uf9"/>
+            <property name="$metaclass" value="Transition"/>
+            <property name="$event_name" value="done (failed)"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid7et8etug73fpetug938l">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="LoadedPrerequisites"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid7et8etug73fpetug938l.linkid82puetug73fpetugbwui">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid3wom6etug73fpetugb9cg"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid7et8etug73fpetug938l"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+        <link uin="id83t9setug73fpetug74ah.nodeid7et8etug73fpetug938l.linkidr4phetug73fpetugcezv">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid71qrcetug73fpetuga3zj"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid7et8etug73fpetug938l"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid71qrcetug73fpetuga3zj">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="FixedUp"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid71qrcetug73fpetuga3zj.linkid4fiuhetug73fpetugbs4x">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid3wom6etug73fpetugb9cg"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid71qrcetug73fpetuga3zj"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+        <link uin="id83t9setug73fpetug74ah.nodeid71qrcetug73fpetuga3zj.linkid8ewc7etug73fpetughpzu">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid6yrvpetui3nn8etui62p3"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid71qrcetug73fpetuga3zj"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid3wom6etug73fpetugb9cg">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="PendingDestroy"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid3wom6etug73fpetugb9cg.linkid80127etug73fpetugd66b">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid7vd8retug73fpetugcr3e"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid3wom6etug73fpetugb9cg"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid7vd8retug73fpetugcr3e">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="Destroyed"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid7vd8retug73fpetugcr3e.linkid8h4qnetug73fpetugf6j3">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid17bz7etug73fpetugf23i"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid7vd8retug73fpetugcr3e"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid417yeetug73fpetugeb3p">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="GC"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid417yeetug73fpetugeb3p.linkid6ngyletug73fpetugehbp">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid3wom6etug73fpetugb9cg"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid417yeetug73fpetugeb3p"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="PendingGC"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5.linkid6vibeetug73fpetugephi">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid417yeetug73fpetugeb3p"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+        <link uin="id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5.linkid1izxmetug73fpetugesem">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeidq28metug73fpetug8uf9"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5"/>
+            <property name="$metaclass" value="Transition"/>
+            <property name="$event_name" value="Loaded again"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid17bz7etug73fpetugf23i">
+        <property name="$metaclass" value="End State"/>
+        <property name="$name" value="EndState1"/>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid6b4f8etug73fpetugfa3i">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="PendingInitialization"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid6b4f8etug73fpetugfa3i.linkidy5coetug73fpetughmwy">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid2vt9ietug73fpetugfjhj"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid6b4f8etug73fpetugfa3i"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+        <link uin="id83t9setug73fpetug74ah.nodeid6b4f8etug73fpetugfa3i.linkid989qmetug73fpetugi623">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid6b4f8etug73fpetugfa3i"/>
+            <property name="$metaclass" value="Transition"/>
+            <property name="$event_name" value="Other init failure"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid2vt9ietug73fpetugfjhj">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="Initializing"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid2vt9ietug73fpetugfjhj.linkid2yeeuetug73fpetughfff">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid8048etug73fpetugfpwv"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid2vt9ietug73fpetugfjhj"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+        <link uin="id83t9setug73fpetug74ah.nodeid2vt9ietug73fpetugfjhj.linkid7b0d0etug73fpetughibe">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid3z4oketug73fpetuggjl4"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid2vt9ietug73fpetugfjhj"/>
+            <property name="$metaclass" value="Transition"/>
+            <property name="$event_name" value="Failed"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid8048etug73fpetugfpwv">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="Good"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid8048etug73fpetugfpwv.linkid5imvsetug73fpetughcca">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeidswftetug73fpetugfwd3"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid8048etug73fpetugfpwv"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeidswftetug73fpetugfwd3">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="PendingTermination"/>
+        <link uin="id83t9setug73fpetug74ah.nodeidswftetug73fpetugfwd3.linkid3jvhdetug73fpetugiz5h">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid9bbfsetug73fpetugirr0"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeidswftetug73fpetugfwd3"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+        <link uin="id83t9setug73fpetug74ah.nodeidswftetug73fpetugfwd3.linkid7ockpetuqdc66etuqdq4c">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid8048etug73fpetugfpwv"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeidswftetug73fpetugfwd3"/>
+            <property name="$metaclass" value="Transition"/>
+            <property name="$event_name" value="Loaded again"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid3z4oketug73fpetuggjl4">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="InitializationFailed"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid3z4oketug73fpetuggjl4.linkidotudetug73fpetugilak">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid417yeetug73fpetugeb3p"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid3z4oketug73fpetuggjl4"/>
+            <property name="$metaclass" value="Transition"/>
+            <property name="$event_name" value="Do GC"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid9bbfsetug73fpetugirr0">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="Terminating"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid9bbfsetug73fpetugirr0.linkids5u8etug73fpetugj2bq">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid9bbfsetug73fpetugirr0"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid6t6upetug73fpetugj6k4">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="ReloadedLoadedPrerequisites"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid6t6upetug73fpetugj6k4.linkid733w4etug73fpetuglagw">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid5e0mxetug73fpetugjk65"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid6t6upetug73fpetugj6k4"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+        <link uin="id83t9setug73fpetug74ah.nodeid6t6upetug73fpetugj6k4.linkid529snetug73fpetuglmq0">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid6t6upetug73fpetugj6k4"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid5e0mxetug73fpetugjk65">
+        <property name="$metaclass" value="State"/>
+        <property name="$name" value="ReloadedFixedUp"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid5e0mxetug73fpetugjk65.linkid5watyetug73fpetugle5c">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid6yrvpetui3nn8etui62p3"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid5e0mxetug73fpetugjk65"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+        <link uin="id83t9setug73fpetug74ah.nodeid5e0mxetug73fpetugjk65.linkidcf8yetug73fpetuglj2g">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid7q41getug73fpetugejq5"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid5e0mxetug73fpetugjk65"/>
+            <property name="$metaclass" value="Transition"/>
+        </link>
+    </node>
+    <node uin="id83t9setug73fpetug74ah.nodeid6yrvpetui3nn8etui62p3">
+        <property name="$orientation" value="horizontal"/>
+        <property name="$metaclass" value="Synchronization Bar"/>
+        <property name="$name" value="SyncBar1"/>
+        <link uin="id83t9setug73fpetug74ah.nodeid6yrvpetui3nn8etui62p3.linkid4uffpetui3nn8etui6xmx">
+            <participant role="Supplier" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid6b4f8etug73fpetugfa3i"/>
+            <participant role="Client" referencedUin="design:node:::id83t9setug73fpetug74ah.nodeid6yrvpetui3nn8etui62p3"/>
+            <property name="$metaclass" value="Transition"/>
+            <property name="$event_name" value="Fixed up all modules"/>
+        </link>
+    </node>
+</nodeSet>
diff --git a/src/lib/kStuff/kLdr/tg/default.txvpck b/src/lib/kStuff/kLdr/tg/default.txvpck
new file mode 100644
index 0000000..b253f0f
--- /dev/null
+++ b/src/lib/kStuff/kLdr/tg/default.txvpck
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodeSet version="1.0">
+    <view uin="id309n7etug73fpetug73wh">
+        <property name="$metaclass" value="Package Diagram"/>
+        <property name="@__options" value=""/>
+        <property name="$defaultDiagram" value=""/>
+    </view>
+</nodeSet>
diff --git a/src/lib/kStuff/kLdr/tg/kLdr.tpr b/src/lib/kStuff/kLdr/tg/kLdr.tpr
new file mode 100644
index 0000000..fb3d016
--- /dev/null
+++ b/src/lib/kStuff/kLdr/tg/kLdr.tpr
@@ -0,0 +1,23 @@
+[Project]
+Language=cpp
+Root.0=$PROJECT_DIR$
+Root.0.access=writable
+Root.0.file_types=cpp_source;cpp_header;diagram
+Root.0.package_prefix=
+Version=3.0
+projectfile.encoding=MS932
+Root.1=$TGH$/jdk/jre/lib/rt.jar
+Root.1.access=import
+Root.1.non_removable=
+[workspace]
+Developer.CodingWorkspace={{0,2,-1,0,0,0,0,0,0,1,0,50,75,25,-1,-1,-1,-1}${0,1,-1,0,0,0,0,1,0,1,0,50,75,25,-1,-1,-1,-1}${0,3,-1,0,0,0,0,1,0,1,0,66,50,25,-1,-1,-1,-1}${0,3,-1,0,0,0,0,1,0,1,0,66,50,25,-1,-1,-1,-1}${0,-1,-1,0,0,0,0,0,0,1,0,5,5,5,-1,-1,-1,-1}${0,5,-1,0,0,0,0,0,0,1,0,50,50,25,-1,-1,-1,-1}${0,4,-1,0,0,0,0,1,0,1,1,66,50,25,-1,-1,-1,-1}${0,7,-1,0,0,0,0,0,0,1,0,50,50,75,-1,-1,-1,-1}}
+Developer.DebugWorkspace={{0,2,-1,0,0,0,0,0,0,1,0,50,75,25,-1,-1,-1,-1}${0,1,-1,0,0,0,0,1,0,1,1,50,75,25,-1,-1,-1,-1}${0,3,-1,0,0,0,0,0,0,1,0,50,50,25,-1,-1,-1,-1}${0,3,-1,0,0,0,0,0,0,1,0,50,50,25,-1,-1,-1,-1}${0,-1,-1,0,0,0,0,0,0,1,0,5,5,5,-1,-1,-1,-1}${0,4,-1,0,0,0,0,0,0,1,0,50,50,25,-1,-1,-1,-1}${0,0,-1,0,0,0,0,1,0,1,0,75,5,5,-1,-1,-1,-1}${0,7,-1,0,0,0,0,0,0,1,0,50,50,75,-1,-1,-1,-1}}
+Developer.DesignWorkspace={{0,2,-1,0,0,0,0,1,0,1,0,50,75,22,-1,-1,-1,-1}${0,1,-1,0,0,0,0,0,0,1,0,50,75,22,-1,-1,-1,-1}${0,3,-1,0,0,0,0,1,0,1,0,50,50,22,-1,-1,-1,-1}${0,3,-1,0,0,0,0,1,0,1,0,50,50,22,-1,-1,-1,-1}${0,-1,-1,0,0,0,0,0,0,1,0,5,5,5,-1,-1,-1,-1}${0,4,-1,0,0,0,0,1,0,1,1,50,50,22,-1,-1,-1,-1}${0,0,-1,0,0,0,0,0,0,1,0,75,5,5,-1,-1,-1,-1}${0,7,-1,0,0,0,0,0,0,1,0,50,50,75,-1,-1,-1,-1}}
+Developer.kLdr={{0,2,-1,0,0,0,0,1,0,1,1,50,75,22,-1,-1,-1,-1}${0,1,-1,0,0,0,0,0,0,1,0,50,75,22,-1,-1,-1,-1}${0,3,-1,0,0,0,0,1,0,1,0,50,50,22,-1,-1,-1,-1}${0,3,-1,0,0,0,0,1,0,1,0,50,50,22,-1,-1,-1,-1}${0,-1,-1,0,0,0,0,0,0,1,0,5,5,5,-1,-1,-1,-1}${0,4,-1,0,0,0,0,1,0,1,0,50,50,22,-1,-1,-1,-1}${0,0,-1,0,0,0,0,0,0,1,0,75,5,5,-1,-1,-1,-1}${0,7,-1,0,0,0,0,0,0,1,0,50,50,75,-1,-1,-1,-1}}
+names.Developer={kLdr,DesignWorkspace,CodingWorkspace,DebugWorkspace}
+[vcs]
+provider.class=CVS LAN
+[lastOpenProjectName]
+Developer=kLdr
+[model]
+showDiagramContents=true
diff --git a/src/lib/kStuff/kLdr/tg/kLdr.tws b/src/lib/kStuff/kLdr/tg/kLdr.tws
new file mode 100644
index 0000000..4730025
--- /dev/null
+++ b/src/lib/kStuff/kLdr/tg/kLdr.tws
@@ -0,0 +1,2 @@
+workspace.diagram.active = <oiref:design#Class#id83t9setug73fpetug74ah.diagram:oiref>
+workspace.diagram.open.0 = <oiref:design#Class#id83t9setug73fpetug74ah.diagram:oiref>
diff --git a/src/lib/kStuff/kLdr/tstkLdrHeap.c b/src/lib/kStuff/kLdr/tstkLdrHeap.c
new file mode 100644
index 0000000..a5891dd
--- /dev/null
+++ b/src/lib/kStuff/kLdr/tstkLdrHeap.c
@@ -0,0 +1,223 @@
+/* $Id: tstkLdrHeap.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - Heap testcase.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kLdr.h>
+#include <k/kHlp.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+#define CHECK_FATAL(expr) \
+    do { if (!(expr)) { printf("tstkLdrHeap(%d): FATAL FAILURE - %s\n", __LINE__, #expr); return 1; } \
+    } while (0)
+
+#define CHECK(expr) \
+    do { if (!(expr)) { printf("tstkLdrHeap(%d): ERROR - %s\n", __LINE__, #expr); cErrors++; kHlpAssertBreakpoint();} \
+    } while (0)
+
+
+/**
+ * Get a random size.
+ * @returns random size.
+ */
+static unsigned RandSize(void)
+{
+    unsigned i = (unsigned)rand() % (256*1024 - 1);
+    return i ? i : 1;
+}
+
+/**
+ * Get a random index.
+ * @returns random index.
+ * @param   cEntries    The number of entries in the table.
+ */
+static unsigned RandIdx(unsigned cEntries)
+{
+    unsigned i = (unsigned)rand();
+    while (i >= cEntries)
+        i >>= 1;
+    return i;
+}
+
+#if 0
+# define kHlpAlloc(a) malloc(a)
+# define kHlpFree(a) free(a)
+#endif
+
+int main()
+{
+    int cErrors = 0;
+    int rc;
+#define MAX_ALLOCS 256
+    static struct
+    {
+        void *pv;
+        unsigned cb;
+    } s_aAllocs[MAX_ALLOCS];
+    unsigned cAllocs;
+    unsigned i;
+    unsigned j;
+
+    /*
+     * Some simple init / term.
+     */
+    rc = kHlpHeapInit();
+    CHECK_FATAL(!rc);
+    kHlpHeapTerm();
+
+    rc = kHlpHeapInit();
+    CHECK_FATAL(!rc);
+    kHlpHeapTerm();
+
+
+    /*
+     * Simple alloc all, free all in FIFO order.
+     */
+    rc = kHlpHeapInit();
+    CHECK_FATAL(!rc);
+
+    /* 1. allocate all slots. */
+    for (i = 0; i < MAX_ALLOCS; i++)
+    {
+        s_aAllocs[i].cb = RandSize();
+        s_aAllocs[i].pv = kHlpAlloc(s_aAllocs[i].cb);
+        CHECK(s_aAllocs[i].pv);
+    }
+
+    /* 2. free all slots. */
+    for (i = 0; i < MAX_ALLOCS; i++)
+        kHlpFree(s_aAllocs[i].pv);
+
+    /* terminate */
+    kHlpHeapTerm();
+
+
+    /*
+     * Simple alloc all, free all in LIFO order.
+     */
+    rc = kHlpHeapInit();
+    CHECK_FATAL(!rc);
+
+    /* 1. allocate all slots. */
+    for (i = 0; i < MAX_ALLOCS; i++)
+    {
+        s_aAllocs[i].cb = RandSize();
+        s_aAllocs[i].pv = kHlpAlloc(s_aAllocs[i].cb);
+        CHECK(s_aAllocs[i].pv);
+    }
+
+    /* 2. free all slots. */
+    i = MAX_ALLOCS;
+    while (i-- > 0)
+        kHlpFree(s_aAllocs[i].pv);
+
+    /* terminate */
+    kHlpHeapTerm();
+
+
+    /*
+     * Bunch of allocations, free half, allocate and free in pairs, free all.
+     */
+    rc = kHlpHeapInit();
+    CHECK_FATAL(!rc);
+
+    /* 1. allocate all slots. */
+    for (i = 0; i < MAX_ALLOCS; i++)
+    {
+        s_aAllocs[i].cb = RandSize();
+        s_aAllocs[i].pv = kHlpAlloc(s_aAllocs[i].cb);
+        CHECK(s_aAllocs[i].pv);
+    }
+    cAllocs = MAX_ALLOCS;
+
+    /* 2. free half (random order). */
+    while (cAllocs > MAX_ALLOCS / 2)
+    {
+        i = RandIdx(cAllocs);
+        kHlpFree(s_aAllocs[i].pv);
+        cAllocs--;
+        if (i != cAllocs)
+            s_aAllocs[i] = s_aAllocs[cAllocs];
+    }
+
+    /* 3. lots of alloc and free activity. */
+    for (j = 0; j < MAX_ALLOCS * 32; j++)
+    {
+        /* allocate */
+        unsigned cMax = RandIdx(MAX_ALLOCS / 4) + 1;
+        while (cAllocs < MAX_ALLOCS && cMax-- > 0)
+        {
+            i = cAllocs;
+            s_aAllocs[i].cb = RandSize();
+            s_aAllocs[i].pv = kHlpAlloc(s_aAllocs[i].cb);
+            CHECK(s_aAllocs[i].pv);
+            cAllocs++;
+        }
+
+        /* free */
+        cMax = RandIdx(MAX_ALLOCS / 4) + 1;
+        while (cAllocs > MAX_ALLOCS / 2 && cMax-- > 0)
+        {
+            i = RandIdx(cAllocs);
+            kHlpFree(s_aAllocs[i].pv);
+            cAllocs--;
+            if (i != cAllocs)
+                s_aAllocs[i] = s_aAllocs[cAllocs];
+        }
+    }
+
+    /* 4. free all */
+    while (cAllocs > 0)
+    {
+        i = RandIdx(cAllocs);
+        kHlpFree(s_aAllocs[i].pv);
+        cAllocs--;
+        if (i != cAllocs)
+            s_aAllocs[i] = s_aAllocs[cAllocs];
+    }
+
+    /* terminate */
+    kHlpHeapTerm();
+
+
+    /* summary */
+    if (!cErrors)
+        printf("tstkLdrHeap: SUCCESS\n");
+    else
+        printf("tstkLdrHeap: FAILURE - %d errors\n", cErrors);
+    return !!cErrors;
+}
diff --git a/src/lib/kStuff/kLdr/tstkLdrMod.c b/src/lib/kStuff/kLdr/tstkLdrMod.c
new file mode 100644
index 0000000..c49907b
--- /dev/null
+++ b/src/lib/kStuff/kLdr/tstkLdrMod.c
@@ -0,0 +1,629 @@
+/* $Id: tstkLdrMod.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kLdr - Module interpreter testcase.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kLdr.h>
+#include <k/kErr.h>
+#include <k/kErrors.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** The default base address used in the tests. */
+#define MY_BASEADDRESS      0x2400000
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** The numbers of errors. */
+static int g_cErrors = 0;
+
+
+
+/**
+ * Report failure.
+ */
+static int Failure(const char *pszFormat, ...)
+{
+    va_list va;
+
+    g_cErrors++;
+
+    printf("tstLdrMod: ");
+    va_start(va, pszFormat);
+    vprintf(pszFormat, va);
+    va_end(va);
+    printf("\n");
+    return 1;
+}
+
+
+/** Dummy import resolver callback. */
+static int BasicTestsGetImport(PKLDRMOD pMod, KU32 iImport, KU32 iSymbol, const char *pchSymbol, KSIZE cchSymbol,
+                               const char *pszVersion, PKLDRADDR puValue, KU32 *pfKind, void *pvUser)
+{
+    *puValue = 0xdeadface;
+    *pfKind = KLDRSYMKIND_NO_BIT | KLDRSYMKIND_NO_TYPE;
+    return 0;
+}
+
+
+/**
+ * Verbose memcmp().
+ */
+static int TestMemComp(const void *pv1, const void *pv2, KSIZE cb)
+{
+    KSIZE           off;
+    const KU8      *pb1 = (const KU8 *)pv1;
+    const KU8      *pb2 = (const KU8 *)pv2;
+    if (!memcmp(pb1, pb2, cb))
+        return 0;
+    printf("Mismatching blocks pv1=%p pv2=%p cb=%#x:\n", pv1, pv2, cb);
+    for (off = 0; off < cb; off++)
+    {
+        if (pb1[off] == pb2[off])
+            continue;
+        printf("%08x %02x != %02x\n", off, pb1[off], pb2[off]);
+    }
+    return memcmp(pb1, pb2, cb); /* lazy */
+}
+
+
+/**
+ * Performs basic relocation tests.
+ */
+static int BasicTestsRelocate(PKLDRMOD pMod, void *pvBits, void *pvBits2)
+{
+    const KSIZE cbImage = (KSIZE)kLdrModSize(pMod);
+    int rc;
+
+    printf("* Relocation test...\n");
+
+    /*
+     * Get the same bits again to check that we get the same result.
+     */
+    memset(pvBits2, 0xfe, cbImage);
+    rc = kLdrModGetBits(pMod, pvBits2, (KUPTR)pvBits, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("failed to get image bits, rc=%d (%s) (a)", rc, kErrName(rc));
+    if (TestMemComp(pvBits2, pvBits, cbImage))
+        return Failure("relocation test failed, mismatching bits (a)");
+
+    /*
+     * Short relocation round trip.
+     */
+    rc = kLdrModRelocateBits(pMod, pvBits2, 0x1000, (KUPTR)pvBits, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("failed to relocate, rc=%d (%s) (b1)", rc, kErrName(rc));
+    rc = kLdrModRelocateBits(pMod, pvBits2, (KUPTR)pvBits, 0x1000, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("failed to relocate, rc=%d (%s) (b2)", rc, kErrName(rc));
+    if (TestMemComp(pvBits2, pvBits, cbImage))
+        return Failure("relocation test failed, mismatching bits (b)");
+
+    /*
+     * Longer trip where we also check the intermediate results.
+     */
+    /* stage one */
+    rc = kLdrModRelocateBits(pMod, pvBits, 0x1000000, (KUPTR)pvBits, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("failed to relocate, rc=%d (%s) (c1)", rc, kErrName(rc));
+    memset(pvBits2, 0xfe, cbImage);
+    rc = kLdrModGetBits(pMod, pvBits2, 0x1000000, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("failed to get image bits, rc=%d (%s) (c1)", rc, kErrName(rc));
+    if (TestMemComp(pvBits2, pvBits, cbImage))
+        return Failure("relocation test failed, mismatching bits (c1)");
+
+    /* stage two */
+    rc = kLdrModRelocateBits(pMod, pvBits, ~(KUPTR)0x1010000, 0x1000000, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("failed to relocate, rc=%d (%s) (c2)", rc, kErrName(rc));
+    memset(pvBits2, 0xef, cbImage);
+    rc = kLdrModGetBits(pMod, pvBits2, ~(KUPTR)0x1010000, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("failed to get image bits, rc=%d (%s) (c2)", rc, kErrName(rc));
+    if (TestMemComp(pvBits2, pvBits, cbImage))
+        return Failure("relocation test failed, mismatching bits (c2)");
+
+    /* stage three */
+    rc = kLdrModRelocateBits(pMod, pvBits, MY_BASEADDRESS, ~(KUPTR)0x1010000, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("failed to relocate, rc=%d (%s) (c3)", rc, kErrName(rc));
+    memset(pvBits2, 0xef, cbImage);
+    rc = kLdrModGetBits(pMod, pvBits2, MY_BASEADDRESS, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("failed to get image bits, rc=%d (%s) (c3)", rc, kErrName(rc));
+    if (TestMemComp(pvBits2, pvBits, cbImage))
+        return Failure("relocation test failed, mismatching bits (c3)");
+
+    /* stage four */
+    rc = kLdrModRelocateBits(pMod, pvBits, ~(KUPTR)0 / 2 - 0x10000, MY_BASEADDRESS, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("failed to relocate, rc=%d %(s) (c4)", rc, kErrName(rc));
+    memset(pvBits2, 0xdc, cbImage);
+    rc = kLdrModGetBits(pMod, pvBits2, ~(KUPTR)0 / 2 - 0x10000, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("failed to get image bits, rc=%d (%s) (c4)", rc, kErrName(rc));
+    if (TestMemComp(pvBits2, pvBits, cbImage))
+        return Failure("relocation test failed, mismatching bits (c4)");
+
+    /* return */
+    rc = kLdrModRelocateBits(pMod, pvBits, (KUPTR)pvBits, ~(KUPTR)0 / 2 - 0x10000, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("failed to relocate, rc=%d (%s) (c5)", rc, kErrName(rc));
+    memset(pvBits2, 0xcd, cbImage);
+    rc = kLdrModGetBits(pMod, pvBits2, (KUPTR)pvBits, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("failed to get image bits, rc=%d (%s) (c5)", rc, kErrName(rc));
+    if (TestMemComp(pvBits2, pvBits, cbImage))
+        return Failure("relocation test failed, mismatching bits (c5)");
+
+    return 0;
+}
+
+
+/**
+ * Dump symbols and check that we can query each of them recursivly.
+ */
+static int BasicTestsEnumSymCallback(PKLDRMOD pMod, KU32 iSymbol, const char *pchSymbol, KSIZE cchSymbol,
+                                     const char *pszVersion, KLDRADDR uValue, KU32 fKind, void *pvUser)
+{
+    KLDRADDR    uValue2;
+    KU32        fKind2;
+    int         rc;
+
+    /* dump */
+    printf("#0x%08x: %016" PRI_KLDRADDR " %#08x", iSymbol, uValue, fKind);
+    if (pchSymbol)
+        printf(" %.*s", cchSymbol, pchSymbol);
+    printf("\n");
+
+    /* query by ordinal */
+    if (iSymbol != NIL_KLDRMOD_SYM_ORDINAL)
+    {
+        fKind2 = 0;
+        rc = kLdrModQuerySymbol(pMod, pvUser, MY_BASEADDRESS, iSymbol, NULL, 0, NULL, NULL, NULL,
+                                &uValue2, &fKind2);
+        if (rc)
+            return Failure("Couldn't find symbol %#x (%.*s) by ordinal. rc=%d (%s)", iSymbol, cchSymbol, pchSymbol, rc, kErrName(rc));
+        if (uValue != uValue2)
+            return Failure("Symbol %#x (%.*s): Value mismatch %016" PRI_KLDRADDR " != %016" PRI_KLDRADDR " (enum!=query/ord)  pvBits=%p",
+                           iSymbol, cchSymbol, pchSymbol, uValue, uValue2, pvUser);
+        if (fKind != fKind2)
+            return Failure("Symbol %#x (%.*s): Kind mismatch %#x != %#x (enum!=query/ord) pvBits=%p",
+                           iSymbol, cchSymbol, pchSymbol, fKind, fKind2, pvUser);
+    }
+
+    /* query by name. */
+    if (pchSymbol)
+    {
+        fKind2 = 0;
+        rc = kLdrModQuerySymbol(pMod, pvUser, MY_BASEADDRESS, NIL_KLDRMOD_SYM_ORDINAL, pchSymbol, cchSymbol, pszVersion,
+                                NULL, NULL, &uValue2, &fKind2);
+        if (rc)
+            return Failure("Couldn't find symbol %#x (%.*s) by name. rc=%d (%s)", iSymbol, cchSymbol, pchSymbol, rc, kErrName(rc));
+        if (uValue != uValue2)
+            return Failure("Symbol %#x (%.*s): Value mismatch %016" PRI_KLDRADDR " != %016" PRI_KLDRADDR " (enum!=query/name) pvBits=%p",
+                           iSymbol, cchSymbol, pchSymbol, uValue, uValue2, pvUser);
+        if (fKind != fKind2)
+            return Failure("Symbol %#x (%.*s): Kind mismatch %#x != %#x (enum!=query/name) pvBits=%p",
+                           iSymbol, cchSymbol, pchSymbol, fKind, fKind2, pvUser);
+    }
+
+    return 0;
+}
+
+
+/**
+ * Dump debugger information and check it for correctness.
+ */
+static int BasicTestEnumDbgInfoCallback(PKLDRMOD pMod, KU32 iDbgInfo, KLDRDBGINFOTYPE enmType,
+                                        KI16 iMajorVer, KI16 iMinorVer, KLDRFOFF offFile, KLDRADDR LinkAddress,
+                                        KLDRSIZE cb, const char *pszExtFile, void *pvUser)
+{
+    printf("#0x%08x: enmType=%d %d.%d offFile=0x%" PRI_KLDRADDR " LinkAddress=%" PRI_KLDRADDR " cb=%" PRI_KLDRSIZE " pvUser=%p\n",
+           iDbgInfo, enmType, iMajorVer, iMinorVer, (KLDRADDR)offFile, LinkAddress, cb, pvUser);
+    if (pszExtFile)
+        printf("            pszExtFile=%p '%s'\n", pszExtFile, pszExtFile);
+
+    if (enmType >= KLDRDBGINFOTYPE_END || enmType <= KLDRDBGINFOTYPE_INVALID)
+        return Failure("Bad enmType");
+    if (pvUser != NULL)
+        return Failure("pvUser");
+
+    return 0;
+}
+
+
+/**
+ * Performs the basic module loader test on the specified module and image bits.
+ */
+static int BasicTestsSub2(PKLDRMOD pMod, void *pvBits)
+{
+    KI32 cImports;
+    KI32 i;
+    int rc;
+    KU32 fKind;
+    KLDRADDR Value;
+    KLDRADDR MainEPAddress;
+    KLDRSTACKINFO StackInfo;
+
+    printf("* Testing queries with pvBits=%p...\n", pvBits);
+
+    /*
+     * Get the import modules.
+     */
+    cImports = kLdrModNumberOfImports(pMod, pvBits);
+    printf("cImports=%d\n", cImports);
+    if (cImports < 0)
+        return Failure("failed to query the number of import, cImports=%d", cImports);
+    for (i = 0; i < cImports; i++)
+    {
+        char szImportModule[260];
+        rc = kLdrModGetImport(pMod, pvBits, i, szImportModule, sizeof(szImportModule));
+        if (rc)
+            return Failure("failed to get import module name, rc=%d (%s). (%.260s)", rc, kErrName(rc), szImportModule);
+        printf("import #%d: '%s'\n", i, szImportModule);
+    }
+
+    /*
+     * Query stack info.
+     */
+    StackInfo.Address = ~(KLDRADDR)42;
+    StackInfo.LinkAddress = ~(KLDRADDR)42;
+    StackInfo.cbStack = ~(KLDRSIZE)42;
+    StackInfo.cbStackThread = ~(KLDRSIZE)42;
+    rc = kLdrModGetStackInfo(pMod, pvBits, MY_BASEADDRESS, &StackInfo);
+    if (rc)
+        return Failure("kLdrModGetStackInfo failed with rc=%d (%s)", rc, kErrName(rc));
+    printf("Stack: Address=%016" PRI_KLDRADDR "   LinkAddress=%016" PRI_KLDRADDR "\n"
+           "       cbStack=%016" PRI_KLDRSIZE " cbStackThread=%016" PRI_KLDRSIZE "\n",
+           StackInfo.Address, StackInfo.LinkAddress, StackInfo.cbStack, StackInfo.cbStackThread);
+    if (StackInfo.Address == ~(KLDRADDR)42)
+        return Failure("Bad StackInfo.Address");
+    if (StackInfo.LinkAddress == ~(KLDRADDR)42)
+        return Failure("Bad StackInfo.LinkAddress");
+    if (StackInfo.cbStack == ~(KLDRSIZE)42)
+        return Failure("Bad StackInfo.cbStack");
+    if (StackInfo.cbStackThread == ~(KLDRSIZE)42)
+        return Failure("Bad StackInfo.cbStackThread");
+
+    /*
+     * Query entrypoint.
+     */
+    MainEPAddress = ~(KLDRADDR)42;
+    rc = kLdrModQueryMainEntrypoint(pMod, pvBits, MY_BASEADDRESS, &MainEPAddress);
+    if (rc)
+        return Failure("kLdrModQueryMainEntrypoint failed with rc=%d (%s)", rc, kErrName(rc));
+    printf("Entrypoint: %016" PRI_KLDRADDR "\n", MainEPAddress);
+    if (MainEPAddress == ~(KLDRADDR)42)
+        return Failure("MainEPAddress wasn't set.");
+    if (MainEPAddress != NIL_KLDRADDR && MainEPAddress < MY_BASEADDRESS)
+        return Failure("Bad MainEPAddress (a).");
+    if (MainEPAddress != NIL_KLDRADDR && MainEPAddress >= MY_BASEADDRESS + kLdrModSize(pMod))
+        return Failure("Bad MainEPAddress (b).");
+
+    /*
+     * Debugger information.
+     */
+    rc = kLdrModHasDbgInfo(pMod, pvBits);
+    if (!rc)
+        printf("Has Debugger Information\n");
+    else if (rc == KLDR_ERR_NO_DEBUG_INFO)
+        printf("NO Debugger Information\n");
+    else
+        return Failure("kLdrModHasDbgInfo failed with rc=%d (%s)", rc, kErrName(rc));
+    rc = kLdrModEnumDbgInfo(pMod, pvBits, BasicTestEnumDbgInfoCallback, NULL);
+    if (rc)
+        return Failure("kLdrModEnumDbgInfo failed with rc=%d (%s)", rc, kErrName(rc));
+
+
+    /*
+     * Negative symbol query tests.
+     */
+    fKind = 0;
+    Value = 0x0badc0de;
+    rc = kLdrModQuerySymbol(pMod, pvBits, MY_BASEADDRESS, NIL_KLDRMOD_SYM_ORDINAL - 20, NULL, 0, NULL, NULL, NULL,
+                            &Value, &fKind);
+    if (rc)
+    {
+        if (Value != 0)
+            return Failure("Value wasn't cleared on failure.");
+    }
+
+    fKind = 0;
+    Value = 0x0badc0de;
+    rc = kLdrModQuerySymbol(pMod, pvBits, MY_BASEADDRESS, NIL_KLDRMOD_SYM_ORDINAL, NULL, 0, NULL, NULL, NULL,
+                            &Value, &fKind);
+    if (!rc)
+        return Failure("NIL ordinal succeeded!");
+    if (Value != 0)
+        return Failure("Value wasn't cleared on failure.");
+
+    /*
+     * Enumerate and query all symbols.
+     */
+    printf("\n"
+           "Symbols:\n");
+    rc = kLdrModEnumSymbols(pMod, pvBits, MY_BASEADDRESS, 0, BasicTestsEnumSymCallback, pvBits);
+    if (rc)
+        return Failure("kLdrModEnumSymbols failed with rc=%d (%s)", rc, kErrName(rc));
+
+
+/*int     kLdrModCanExecuteOn(PKLDRMOD pMod, const void *pvBits, KCPUARCH enmArch, KCPU enmCpu);
+*/
+
+    return 0;
+}
+
+
+/**
+ * Performs the basic module loader test on the specified module
+ */
+static int BasicTestsSub(PKLDRMOD pMod)
+{
+    int         rc;
+    KU32        i;
+    void       *pvBits;
+    KSIZE       cbImage;
+
+    /*
+     * Check/dump the module structure.
+     */
+    printf("pMod=%p u32Magic=%#x cSegments=%d\n", (void *)pMod, pMod->u32Magic, pMod->cSegments);
+    printf("enmType=%d enmFmt=%d enmArch=%d enmCpu=%d enmEndian=%d\n",
+           pMod->enmType, pMod->enmFmt, pMod->enmArch, pMod->enmCpu, pMod->enmEndian);
+    printf("Filename: %s (%d bytes)\n", pMod->pszFilename, pMod->cchFilename);
+    printf("    Name: %s (%d bytes)\n", pMod->pszName, pMod->cchName);
+    printf("\n");
+
+    if (pMod->u32Magic != KLDRMOD_MAGIC)
+        return Failure("Bad u32Magic");
+    if (strlen(pMod->pszFilename) != pMod->cchFilename)
+        return Failure("Bad cchFilename");
+    if (strlen(pMod->pszName) != pMod->cchName)
+        return Failure("Bad cchName");
+    if (pMod->enmFmt >= KLDRFMT_END || pMod->enmFmt <= KLDRFMT_INVALID)
+        return Failure("Bad enmFmt");
+    if (pMod->enmType >= KLDRTYPE_END || pMod->enmType <= KLDRTYPE_INVALID)
+        return Failure("Bad enmType: %d", pMod->enmType);
+    if (!K_ARCH_IS_VALID(pMod->enmArch))
+        return Failure("Bad enmArch");
+    if (pMod->enmCpu >= KCPU_END || pMod->enmCpu <= KCPU_INVALID)
+        return Failure("Bad enmCpu");
+    if (pMod->enmEndian >= KLDRENDIAN_END || pMod->enmEndian <= KLDRENDIAN_INVALID)
+        return Failure("Bad enmEndian");
+
+    for (i = 0; i < pMod->cSegments; i++)
+    {
+        printf("seg #%d: pvUser=%p enmProt=%d Name: '%.*s' (%d bytes)\n",
+               i, pMod->aSegments[i].pvUser, pMod->aSegments[i].enmProt,
+               pMod->aSegments[i].cchName, pMod->aSegments[i].pchName, pMod->aSegments[i].cchName);
+        printf("LinkAddress: %016" PRI_KLDRADDR "       cb: %016" PRI_KLDRSIZE "  Alignment=%08" PRI_KLDRADDR " \n",
+               pMod->aSegments[i].LinkAddress, pMod->aSegments[i].cb, pMod->aSegments[i].Alignment);
+        printf("        RVA: %016" PRI_KLDRADDR " cbMapped: %016" PRI_KLDRSIZE " MapAddress=%p\n",
+               pMod->aSegments[i].RVA, (KLDRSIZE)pMod->aSegments[i].cbMapped, (void *)pMod->aSegments[i].MapAddress);
+        printf("    offFile: %016" PRI_KLDRADDR "   cbFile: %016" PRI_KLDRSIZE "\n",
+               (KLDRADDR)pMod->aSegments[i].offFile, (KLDRSIZE)pMod->aSegments[i].cbFile);
+        printf("\n");
+
+        if (pMod->aSegments[i].pvUser != NULL)
+            return Failure("Bad pvUser");
+        if (pMod->aSegments[i].enmProt >= KPROT_END || pMod->aSegments[i].enmProt <= KPROT_INVALID)
+            return Failure("Bad enmProt");
+        if (pMod->aSegments[i].MapAddress != 0)
+            return Failure("Bad MapAddress");
+        if (pMod->aSegments[i].cbMapped < pMod->aSegments[i].cb)
+            return Failure("Bad cbMapped (1)");
+        if (pMod->aSegments[i].cbMapped && !pMod->aSegments[i].Alignment)
+            return Failure("Bad cbMapped (2)");
+        if (pMod->aSegments[i].cbMapped > kLdrModSize(pMod))
+            return Failure("Bad cbMapped (3)");
+        if (    pMod->aSegments[i].Alignment
+            &&  (pMod->aSegments[i].RVA & (pMod->aSegments[i].Alignment - 1)))
+            return Failure("Bad RVA (1)");
+        if (pMod->aSegments[i].RVA != NIL_KLDRADDR && !pMod->aSegments[i].Alignment)
+            return Failure("Bad RVA (2)");
+        if (    pMod->aSegments[i].RVA != NIL_KLDRADDR
+            &&  pMod->aSegments[i].RVA >= kLdrModSize(pMod))
+            return Failure("Bad RVA (3)");
+        if (    pMod->aSegments[i].RVA != NIL_KLDRADDR
+            &&  pMod->aSegments[i].RVA + pMod->aSegments[i].cbMapped > kLdrModSize(pMod))
+            return Failure("Bad RVA/cbMapped (4)");
+        if (pMod->aSegments[i].LinkAddress != NIL_KLDRADDR && !pMod->aSegments[i].Alignment)
+            return Failure("Bad LinkAddress");
+        if (    pMod->aSegments[i].LinkAddress != NIL_KLDRADDR
+            &&  (pMod->aSegments[i].LinkAddress) & (pMod->aSegments[i].Alignment - 1))
+            return Failure("Bad LinkAddress alignment");
+        if (pMod->aSegments[i].offFile != -1 && pMod->aSegments[i].cbFile == -1)
+            return Failure("Bad offFile");
+        if (pMod->aSegments[i].offFile == -1 && pMod->aSegments[i].cbFile != -1)
+            return Failure("Bad cbFile");
+    }
+
+
+    /*
+     * Get image the size and query the image bits.
+     */
+    printf("* Testing user mapping...\n");
+
+    cbImage = (KSIZE)kLdrModSize(pMod);
+    if (cbImage != kLdrModSize(pMod))
+        return Failure("aborting test because the image is too huge!");
+    pvBits = malloc((KSIZE)cbImage);
+    if (!pvBits)
+        return Failure("failed to allocate %d bytes for the image", cbImage);
+
+    rc = kLdrModGetBits(pMod, pvBits, (KUPTR)pvBits, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("failed to get image bits, rc=%d (%s)", rc, kErrName(rc));
+
+    /*
+     * Another cleanup nesting.
+     */
+    rc = BasicTestsSub2(pMod, pvBits);
+    if (!rc)
+    {
+        /*
+         * Test relocating the bits in a few different ways before we're done with them.
+         */
+        void *pvBits2 = malloc((KSIZE)cbImage);
+        if (pvBits2)
+        {
+            rc = BasicTestsRelocate(pMod, pvBits, pvBits2);
+            free(pvBits2);
+        }
+        else
+            rc = Failure("failed to allocate %d bytes for the 2nd image", cbImage);
+    }
+
+    free(pvBits);
+    return rc;
+}
+
+
+/**
+ * Tests the mapping related api, after mapping.
+ */
+static int BasicTestsSubMap2(PKLDRMOD pMod)
+{
+    int rc;
+
+    rc = kLdrModFixupMapping(pMod, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("kLdrModFixupMapping (a) failed, rc=%d (%s)", rc, kErrName(rc));
+
+    rc = kLdrModReload(pMod);
+    if (rc)
+        return Failure("kLdrModReload (a) failed, rc=%d (%s)", rc, kErrName(rc));
+
+    rc = kLdrModReload(pMod);
+    if (rc)
+        return Failure("kLdrModReload (b) failed, rc=%d (%s)", rc, kErrName(rc));
+
+    rc = kLdrModFixupMapping(pMod, BasicTestsGetImport, NULL);
+    if (rc)
+        return Failure("kLdrModFixupMapping (b) failed, rc=%d (%s)", rc, kErrName(rc));
+
+    rc = kLdrModAllocTLS(pMod);
+    if (rc)
+        return Failure("kLdrModAllocTLS (a) failed, rc=%d (%s)", rc, kErrName(rc));
+    kLdrModFreeTLS(pMod);
+
+    rc = kLdrModAllocTLS(pMod);
+    if (rc)
+        return Failure("kLdrModAllocTLS (b) failed, rc=%d (%s)", rc, kErrName(rc));
+    kLdrModFreeTLS(pMod);
+
+    /*
+     * Repeat the BasicTestsSub2 with pvBits as NULL to test module
+     * interpreters that can utilize the mapping.
+     */
+    rc = BasicTestsSub2(pMod, NULL);
+    if (rc)
+        return Failure("BasicTestsSub2 in Map2 failed, rc=%d (%s)", rc, kErrName(rc));
+    return 0;
+}
+
+
+/**
+ * Tests the mapping related api.
+ */
+static int BasicTestsSubMap(PKLDRMOD pMod)
+{
+    int rc, rc2;
+    printf("* Mapping tests...\n");
+
+    rc = kLdrModMap(pMod);
+    if (rc)
+        return Failure("kLdrModMap failed, rc=%d (%s)", rc, kErrName(rc));
+    rc = BasicTestsSubMap2(pMod);
+    rc2 = kLdrModUnmap(pMod);
+    if (rc2)
+    {
+        Failure("kLdrModUnmap failed, rc=%d (%s)", rc2, kErrName(rc2));
+        rc = rc ? rc : rc2;
+    }
+
+    printf("* Mapping tests done.\n");
+    return rc;
+}
+
+
+/**
+ * Performs basic module loader tests on the specified file.
+ */
+static int BasicTests(const char *pszFilename)
+{
+    PKLDRMOD pMod;
+    int rc, rc2;
+
+    printf("tstLdrMod: Testing '%s'", pszFilename);
+    rc = kLdrModOpen(pszFilename, &pMod);
+    if (!rc)
+    {
+        rc = BasicTestsSub(pMod);
+        if (!rc)
+            rc = BasicTestsSubMap(pMod);
+        if (!rc)
+            rc = BasicTestsSub2(pMod, NULL);
+        rc2 = kLdrModClose(pMod);
+        if (rc2)
+            Failure("failed to close '%s', rc=%d (%s)", pszFilename, rc, kErrName(rc));
+        if (rc2 && !rc)
+            rc = rc2;
+    }
+    else
+        Failure("Failed to open '%s', rc=%d (%s)", pszFilename, rc, kErrName(rc));
+    return rc ? 1 : 0;
+}
+
+
+int main(int argc, char **argv)
+{
+    BasicTests(argv[argc-1]);
+
+    if (!g_cErrors)
+        printf("tstLdrMod: SUCCESS\n");
+    else
+        printf("tstLdrMod: FAILURE - %d errors\n", g_cErrors);
+    return !!g_cErrors;
+}
+
diff --git a/src/lib/kStuff/kProfiler2/Makefile.kmk b/src/lib/kStuff/kProfiler2/Makefile.kmk
new file mode 100644
index 0000000..b3650c9
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/Makefile.kmk
@@ -0,0 +1,237 @@
+# $Id: Makefile.kmk 29 2009-07-01 20:30:29Z bird $
+## @file
+# kProfiler Mark 2, sub-makefile.
+#
+
+#
+# Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+DEPTH ?= ..
+SUB_DEPTH = ..
+include $(PATH_KBUILD)/subheader.kmk
+
+#LIBRARIES  += kPrf2GC kPrf2R0
+DLLS       += kPrf2
+PROGRAMS   += kPrf2Read
+
+
+#
+# Our template.
+#
+TEMPLATE_kPrf2 = kProfiler Template
+if1of ($(BUILD_TARGET), win)
+TEMPLATE_kPrf2_EXTENDS = kStuff
+
+else # Eliminate these
+TEMPLATE_kPrf2_TOOL             = GCC3
+TEMPLATE_kPrf2_TOOL.os2         = GCC3OMF
+TEMPLATE_kPrf2_TOOL.win.x86     = VCC70
+TEMPLATE_kPrf2_TOOL.win.amd64   = VCC80AMD64
+TEMPLATE_kPrf2_ASTOOL           = YASM
+TEMPLATE_kPrf2_ASTOOL.os2       = NASM
+
+TEMPLATE_kPrf2_SDKS.win         = WINPSDK
+
+TEMPLATE_kPrf2_CXXFLAGS.freebsd = -g
+TEMPLATE_kPrf2_CXXFLAGS.linux   = -g
+TEMPLATE_kPrf2_CXXFLAGS.os2     = -g
+TEMPLATE_kPrf2_CXXFLAGS.win     = -Zi -Zl -W3 -GF -GR-
+TEMPLATE_kPrf2_CXXFLAGS.win.amd64 = -GS- #-FAcs
+ifneq ($(BUILD_TYPE),debug)
+TEMPLATE_kPrf2_CXXFLAGS.freebsd+= -O3
+TEMPLATE_kPrf2_CXXFLAGS.linux  += -O3
+TEMPLATE_kPrf2_CXXFLAGS.os2    += -O3
+TEMPLATE_kPrf2_CXXFLAGS.win    += -O2b2
+endif
+
+TEMPLATE_kPrf2_ASFLAGS.freebsd  = -f elf
+TEMPLATE_kPrf2_ASFLAGS.linux    = -f elf
+TEMPLATE_kPrf2_ASFLAGS.os2      = -f omf
+TEMPLATE_kPrf2_ASFLAGS.win.x86  = -f win32 -g cv8
+TEMPLATE_kPrf2_ASFLAGS.win.amd64 = -f win64 -g cv8
+
+TEMPLATE_kPrf2_INCS             = \
+	../include
+
+TEMPLATE_kPrf2_LDFLAGS.freebsd  = -g
+TEMPLATE_kPrf2_LDFLAGS.linux    = -g
+TEMPLATE_kPrf2_LDFLAGS.os2      = -g
+TEMPLATE_kPrf2_LDFLAGS.win      = /DEBUG
+
+TEMPLATE_kPrf2_LIBS.freebsd     =
+TEMPLATE_kPrf2_LIBS.linux       =
+TEMPLATE_kPrf2_LIBS.os2         =
+TEMPLATE_kPrf2_LIBS.win         = \
+	$(PATH_SDK_WINPSDK_LIB)/psapi.Lib
+TEMPLATE_kPrf2_LIBS.win.x86     = \
+	$(PATH_TOOL_VCC70_LIB)/libcmt.lib \
+	$(PATH_TOOL_VCC70_LIB)/oldnames.lib
+TEMPLATE_kPrf2_LIBS.win.amd64   = \
+	$(PATH_TOOL_VCC80AMD64_LIB)/oldnames.lib \
+	$(PATH_TOOL_VCC80AMD64_LIB)/libcmt.lib
+endif
+
+
+#
+# kPrf2 - The profiler module.
+#
+kPrf2_TEMPLATE      = kPrf2
+kPrf2_DEFS.x86      = KPRF_BITS=32
+kPrf2_DEFS.amd64    = KPRF_BITS=64
+kPrf2_LDFLAGS.win.amd64 = -Entry:DllMain
+
+kPrf2_SOURCES       = \
+	kProfileR3.cpp
+#	kProfileGC.cpp
+#	kProfileR0.cpp
+
+kPrf2_SOURCES.win = \
+	dllmain-win.cpp \
+	kPrf2WinApiWrapperHlp.c \
+	prf$(BUILD_TARGET_ARCH)msc.asm \
+	kPrf2-win-$(BUILD_TARGET_ARCH).def
+prfx86msc.asm_DEFS.win.x86 = \
+	KPRF_ENTER=_KPrfEnter \
+	KPRF_LEAVE=_KPrfLeave
+prfamd64msc.asm_DEFS.win.amd64 = \
+	KPRF_ENTER=KPrfEnter \
+	KPRF_LEAVE=KPrfLeave
+
+#
+# kPrf2Read - The read & producer of statistics.
+#
+kPrf2Read_TEMPLATE = kStuffEXE
+kPrf2Read_SOURCES  = \
+	kPrf2Read.cpp
+kPrf2Read_LIBS  = \
+	$(PATH_LIB)/kDbgStatic$(SUFF_LIB) \
+	$(PATH_LIB)/kRdrStatic$(SUFF_LIB) \
+	$(PATH_LIB)/kHlpCRTStatic$(SUFF_LIB)
+
+#
+# kPrf2WinApiWrappers
+#
+IMPORT_LIBS.win += kPrf2WinApiWrappersImp
+kPrf2WinApiWrappersImp_TEMPLATE = kStuffEXE
+kPrf2WinApiWrappersImp_SOURCES.x86   = kPrf2WinApiWrappersImp-x86.def
+kPrf2WinApiWrappersImp_SOURCES.amd64 = kPrf2WinApiWrappersImp-amd64.def
+
+DLLS.win += kPrf2WinApiWrappers
+kPrf2WinApiWrappers_TEMPLATE = kPrf2
+kPrf2WinApiWrappers_CFLAGS = -GH -Gh
+kPrf2WinApiWrappers_LDFLAGS.win.x86 = -Entry:DllMain at 12
+kPrf2WinApiWrappers_LDFLAGS.win.amd64 = -Entry:DllMain
+kPrf2WinApiWrappers_SOURCES = \
+	kPrf2WinApiWrappers.c \
+	kPrf2WinApiWrappersImp-$(BUILD_TARGET_ARCH).def
+kPrf2WinApiWrappers_LIBS = \
+	$(PATH_kPrf2)/kPrf2.lib
+
+ifeq (0,1)
+kPrf2WinApiWrappers-kernel32.h:
+	$(SED) -f kPrf2WinApi-pre.sed --output $@.tmp \
+		$(PATH_SDK_WINPSDK_INC)/WinBase.h \
+		$(PATH_SDK_WINPSDK_INC)/WinCon.h \
+		$(PATH_SDK_WINPSDK_INC)/WinNLS.h \
+		$(PATH_SDK_WINPSDK_INC)/WinVer.h \
+		$(PATH_SDK_WINPSDK_INC)/WinNT.h \
+		$(PATH_SDK_WINPSDK_INC)/TlHelp32.h
+	$(APPEND) $@.tmp 'BOOL WINAPI ReplaceFile( LPCSTR lpReplacedFileName, LPCSTR lpReplacementFileName, LPCSTR lpBackupFileName, DWORD dwReplaceFlags, LPVOID lpExclude, LPVOID lpReserved );'
+	$(APPEND) $@.tmp 'BOOL WINAPI SetConsoleCursor( PVOID pvUnknown1, PVOID pvUnknown2 );'
+	$(APPEND) $@.tmp 'LPCH WINAPI GetEnvironmentStringsA( VOID );'
+	$(APPEND) $@.tmp 'BOOL WINAPI GetBinaryType( LPCSTR lpApplicationName, LPDWORD lpBinaryType );'
+	$(APPEND) $@.tmp 'WORD NTAPI RtlCaptureStackBackTrace( DWORD FramesToSkip, DWORD FramesToCapture, PVOID * BackTrace, PDWORD BackTraceHash );'
+	$(APPEND) $@.tmp 'PVOID RtlFillMemory( PVOID pv, int ch, SIZE_T cb );'
+	$(APPEND) $@.tmp 'PVOID RtlZeroMemory( PVOID pv, SIZE_T cb );'
+	$(APPEND) $@.tmp 'PVOID RtlMoveMemory( PVOID pvDst, PVOID pvSrc, SIZE_T cb );'
+	$(APPEND) $@.tmp 'VOID NTAPI RtlUnwind( PVOID TargetFrame, PVOID TargetIp, PEXCEPTION_RECORD ExceptionRecord, PVOID ReturnValue );'
+	$(APPEND) $@.tmp 'VOID NTAPI RtlUnwindEx( FRAME_POINTERS TargetFrame, PVOID TargetIp, PEXCEPTION_RECORD ExceptionRecord, PVOID ReturnValue, PCONTEXT ContextRecord, PUNWIND_HISTORY_TABLE HistoryTable );'
+	$(APPEND) $@.tmp 'ULONGLONG WINAPI RtlVirtualUnwind( ULONG HandlerType, ULONGLONG ImageBase, ULONGLONG ControlPC, PRUNTIME_FUNCTION FunctionEntry, PCONTEXT ContextRecord, PBOOLEAN InFunction, PFRAME_POINTERS EstablisherFrame, PKNONVOLATILE_CONTEXT_POINTERS ContextPointers );'
+	$(APPEND) $@.tmp 'PVOID WINAPI RtlPcToFileHeader( PVOID PcValue, PVOID * BaseOfImage );'
+	$(APPEND) $@.tmp 'PVOID WINAPI RtlLookupFunctionEntry( ULONGLONG ControlPC, PULONGLONG ImageBase, PULONGLONG TargetGp );'
+	$(APPEND) $@.tmp 'void WINAPI RtlRaiseException(PEXCEPTION_RECORD pXcpRec);'
+	$(APPEND) $@.tmp 'int WINAPI uaw_lstrcmpW( LPCUWSTR lpString1, LPCUWSTR lpString2 );'
+	$(APPEND) $@.tmp 'int WINAPI uaw_lstrcmpiW( LPCUWSTR lpString1, LPCUWSTR lpString2 );'
+	$(APPEND) $@.tmp 'int WINAPI uaw_lstrlenW( LPCUWSTR lpString );'
+	$(APPEND) $@.tmp 'LPUWSTR WINAPI uaw_wcschr( LPCUWSTR lpString, WCHAR wc );'
+	$(APPEND) $@.tmp 'LPUWSTR WINAPI uaw_wcscpy( LPUWSTR lpDst, LPCUWSTR lpSrc );'
+	$(APPEND) $@.tmp 'int WINAPI uaw_wcsicmp( LPCUWSTR lp1, LPCUWSTR lp2 );'
+	$(APPEND) $@.tmp 'SIZE_T WINAPI uaw_wcslen( LPCUWSTR lp1 );'
+	$(APPEND) $@.tmp 'LPUWSTR WINAPI uaw_wcsrchr( LPCUWSTR lpString, WCHAR wc );'
+	$(APPEND) $@.tmp 'LPSTR WINAPI lstrcat( LPSTR lpString1, LPCSTR lpString2 );'
+	$(APPEND) $@.tmp 'int WINAPI lstrcmp( LPCSTR lpString1, LPCSTR lpString2 );'
+	$(APPEND) $@.tmp 'int WINAPI lstrcmpi( LPCSTR lpString1, LPCSTR lpString2 );'
+	$(APPEND) $@.tmp 'LPSTR WINAPI lstrcpy( LPSTR lpString1, LPCSTR lpString2 );'
+	$(APPEND) $@.tmp 'LPSTR WINAPI lstrcpyn( LPSTR lpString1, LPCSTR lpString2, int iMaxLength );'
+	$(APPEND) $@.tmp 'int WINAPI lstrlen( LPCSTR lpString );'
+	$(SED) -f kPrf2WinApi-gencode.sed --output $@ $@.tmp
+	$(RM) -f $@.tmp
+
+kPrf2WinApiWrappersImp-$(KBUILD_TARGET_ARCH).def:
+	$(RM) -f $@
+	$(PATH_TOOL_$(TEMPLATE_kStuff_TOOL.win.$(BUILD_TARGET_ARCH))_BIN)/dumpbin.exe /EXPORTS /OUT:$@.tmp $(PATH_SDK_WINPSDK_LIB)/Kernel32.lib
+	$(SED) -f kPrf2WinApi-dumpbin.sed --output $@.tmp2 $@.tmp
+	$(APPEND) $@ 'LIBRARY kPrf2WinApiWrappers'
+	$(APPEND) $@ 'EXPORTS'
+	$(SED) -f kPrf2WinApi-genimp.sed --append $@ $@.tmp2
+	$(RM) -f $@.tmp $@.tmp2
+endif
+
+#
+# A simple testcase.
+#
+PROGRAMS.win.x86 += tst
+tst_TOOL = VCC70
+tst_SDKS = WINPSDK
+tst_CFLAGS = -GH -Gh -Zi -Zl -GR- -GX- -GF- -W3 -wd4244
+tst_SOURCES = tst.c
+tst.c_CFLAGS = -Od
+tst_LDFLAGS = /DEBUG
+tst_LIBS = \
+	$(PATH_TOOL_VCC70_LIB)/msvcrt.lib \
+	$(PATH_TOOL_VCC70_LIB)/msvcprt.lib \
+	$(PATH_TOOL_VCC70_LIB)/oldnames.lib \
+	$(PATH_kPrf2)/kPrf2.lib
+
+PROGRAMS += tstlongjmp
+tstlongjmp_TEMPLATE = kStuffEXE
+tstlongjmp_CFLAGS.win = -GH -Gh -Zi
+tstlongjmp_SOURCES = tstlongjmp.c
+tstlongjmp_LIBS = \
+	$(PATH_kPrf2)/kPrf2.lib
+
+# Generate the rules
+include $(PATH_KBUILD)/subfooter.kmk
+
+
+#
+# Aliases for .cpp.h files so we can more easily do syntax checking from the editor.
+#
+CORE := $(wildcard *core*.cpp.h *core*.h.h)
+$(CORE:.h=.o) $(CORE:.h=.obj) : kProfileR3.o
+
+READ := $(wildcard *read*.cpp.h *read*.h.h)
+$(READ:.h=.o) $(READ:.h=.obj) : kPrf2Read.o
+
diff --git a/src/lib/kStuff/kProfiler2/dllmain-win.cpp b/src/lib/kStuff/kProfiler2/dllmain-win.cpp
new file mode 100644
index 0000000..56928d9
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/dllmain-win.cpp
@@ -0,0 +1,75 @@
+/* $Id: dllmain-win.cpp 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kProfiler Mark 2 - The Windows DllMain for the profiler DLL.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <Windows.h>
+#include "kProfileR3.h"
+
+
+/**
+ * The DLL Main for the kPrf DLL.
+ *
+ * This is required because we need to initialize the profiler at some point
+ * and because we need to know when threads terminate. (We don't care about
+ * when threads get created, we simply pick them up when we see them the
+ * first time.)
+ *
+ * @returns Success indicator.
+ * @param   hInstDll        The instance handle of the DLL. (i.e. the module handle)
+ * @param   fdwReason       The reason why we're here. This is a 'flag' for reasons of
+ *                          tradition, it's really a kind of enum.
+ * @param   pReserved       Reserved / undocumented something.
+ */
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, PVOID pReserved)
+{
+    switch (fdwReason)
+    {
+        case DLL_PROCESS_ATTACH:
+            if (kPrfInitialize())
+                return FALSE;
+            break;
+
+        case DLL_PROCESS_DETACH:
+            kPrfTerminate();
+            break;
+
+        case DLL_THREAD_ATTACH:
+            break;
+
+        case DLL_THREAD_DETACH:
+            kPrfTerminateThread();
+            break;
+    }
+
+    return TRUE;
+}
+
diff --git a/src/lib/kStuff/kProfiler2/kPrf2-win-amd64.def b/src/lib/kStuff/kProfiler2/kPrf2-win-amd64.def
new file mode 100644
index 0000000..33bb8e2
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kPrf2-win-amd64.def
@@ -0,0 +1,37 @@
+; $Id: kPrf2-win-amd64.def 29 2009-07-01 20:30:29Z bird $LIBRARY kPrf2
+;; @file
+; kProfiler Mark 2 - Windows Linker Definition File, AMD64.
+;
+
+;
+; Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+;
+; Permission is hereby granted, free of charge, to any person
+; obtaining a copy of this software and associated documentation
+; files (the "Software"), to deal in the Software without
+; restriction, including without limitation the rights to use,
+; copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of the Software, and to permit persons to whom the
+; Software is furnished to do so, subject to the following
+; conditions:
+;
+; The above copyright notice and this permission notice shall be
+; included in all copies or substantial portions of the Software.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+; OTHER DEALINGS IN THE SOFTWARE.
+;
+
+LIBRARY kPrf2
+EXPORTS
+    _penter
+    _pexit
+    KPrfInit
+    kPrf2WrapResolve
+
diff --git a/src/lib/kStuff/kProfiler2/kPrf2-win-x86.def b/src/lib/kStuff/kProfiler2/kPrf2-win-x86.def
new file mode 100644
index 0000000..d486a09
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kPrf2-win-x86.def
@@ -0,0 +1,36 @@
+; $Id: kPrf2-win-x86.def 29 2009-07-01 20:30:29Z bird $
+;; @file
+; kProfiler Mark 2 - Windows Linker Definition File, x86.
+;
+
+;
+; Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+;
+; Permission is hereby granted, free of charge, to any person
+; obtaining a copy of this software and associated documentation
+; files (the "Software"), to deal in the Software without
+; restriction, including without limitation the rights to use,
+; copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of the Software, and to permit persons to whom the
+; Software is furnished to do so, subject to the following
+; conditions:
+;
+; The above copyright notice and this permission notice shall be
+; included in all copies or substantial portions of the Software.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+; OTHER DEALINGS IN THE SOFTWARE.
+;
+
+LIBRARY kPrf2
+EXPORTS
+    _penter
+    _pexit
+    KPrfInit
+    kPrf2WrapResolve
diff --git a/src/lib/kStuff/kProfiler2/kPrf2Read.cpp b/src/lib/kStuff/kProfiler2/kPrf2Read.cpp
new file mode 100644
index 0000000..5f24e4a
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kPrf2Read.cpp
@@ -0,0 +1,503 @@
+/* $Id: kPrf2Read.cpp 77 2016-06-22 17:03:55Z bird $ */
+/** @file
+ * kProfiler Mark 2 - The reader and producer of statistics.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <k/kDbg.h>
+
+
+/** @def KPRF_OFF2PTR
+ * Internal helper for converting a offset to a pointer.
+ * @internal
+ */
+#define KPRF_OFF2PTR(TypePrefix, TypeName, off, pHdr) \
+    ( (KPRF_TYPE(TypePrefix, TypeName)) ((off) + (KUPTR)pHdr) )
+
+/** @def KPRF_ALIGN
+ * The usual align macro.
+ * @internal
+ */
+#define KPRF_ALIGN(n, align) ( ((n) + ( (align) - 1)) & ~((align) - 1) )
+
+/** @def KPRF_OFFSETOF
+ * My usual extended offsetof macro, except this returns KU32 and mangles the type name.
+ * @internal
+ */
+#define KPRF_OFFSETOF(kPrfType, Member) ( (KU32)(KUPTR)&((KPRF_TYPE(P,kPrfType))0)->Member )
+
+/** @def PRF_SIZEOF
+ * Size of a kPrf type.
+ * @internal
+ */
+#define KPRF_SIZEOF(kPrfType)           sizeof(KPRF_TYPE(,kPrfType))
+
+#ifdef _MSC_VER
+# define KPRF_FMT_U64   "I64u"
+# define KPRF_FMT_X64   "I64x"
+# define KPRF_FMT_I64   "I64d"
+#else
+# define KPRF_FMT_X64   "llx"
+# define KPRF_FMT_U64   "llu"
+# define KPRF_FMT_I64   "lld"
+#endif
+
+
+/*
+ * Instantiate the readers.
+ */
+/* 32-bit */
+#define KPRF_NAME(Suffix)               KPrf32##Suffix
+#define KPRF_TYPE(Prefix,Suffix)        Prefix##KPRF32##Suffix
+#define KPRF_BITS                       32
+#define KPRF_FMT_UPTR                   "#010x"
+
+#include "prfcore.h.h"
+#include "prfreader.cpp.h"
+
+#undef KPRF_FMT_UPTR
+#undef KPRF_NAME
+#undef KPRF_TYPE
+#undef KPRF_BITS
+
+/* 64-bit */
+#define KPRF_NAME(Suffix)               KPrf64##Suffix
+#define KPRF_TYPE(Prefix,Suffix)        Prefix##KPRF64##Suffix
+#define KPRF_BITS                       64
+#ifdef _MSC_VER
+# define KPRF_FMT_UPTR                  "#018I64x"
+#else
+# define KPRF_FMT_UPTR                  "#018llx"
+#endif
+
+#include "prfcore.h.h"
+#include "prfreader.cpp.h"
+
+#undef KPRF_FMT_UPTR
+#undef KPRF_NAME
+#undef KPRF_TYPE
+#undef KPRF_BITS
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Header union type.
+ */
+typedef union KPRFHDR
+{
+    KPRF32HDR   Hdr32;
+    KPRF64HDR   Hdr64;
+} KPRFHDR;
+typedef KPRFHDR *PKPRFHDR;
+typedef const KPRFHDR *PCKPRFHDR;
+
+
+
+/**
+ * Read the data set into memory.
+ *
+ * @returns Pointer to the loaded data set. (release using free()).
+ *
+ * @param   pszFilename         The path to the profiler data set.
+ * @param   pcb                 Where to store the size of the data set.
+ * @param   pOut                Where to write errors.
+ */
+PKPRFHDR kPrfLoad(const char *pszFilename, KU32 *pcb, FILE *pOut)
+{
+    FILE *pFile = fopen(pszFilename, "rb");
+    if (!pFile)
+    {
+        fprintf(pOut, "Cannot open '%s' for reading!\n", pszFilename);
+        return NULL;
+    }
+
+    /*
+     * Read the file into memory.
+     */
+    long cbFile;
+    if (    !fseek(pFile, 0, SEEK_END)
+        &&  (cbFile = ftell(pFile)) >= 0
+        &&  !fseek(pFile, 0, SEEK_SET)
+        )
+    {
+        if (pcb)
+            *pcb = cbFile;
+
+        void *pvData = malloc(cbFile);
+        if (pvData)
+        {
+            if (fread(pvData, cbFile, 1, pFile))
+            {
+
+                fclose(pFile);
+                return (PKPRFHDR)pvData;
+            }
+            fprintf(pOut, "Failed reading '%s' into memory!\n", pszFilename);
+            free(pvData);
+        }
+        else
+            fprintf(pOut, "Failed to allocate %ld bytes of memory for reading the file '%s' into!\n", cbFile, pszFilename);
+    }
+    else
+        fprintf(pOut, "Failed to determin the size of '%s'!\n", pszFilename);
+
+    fclose(pFile);
+    return NULL;
+}
+
+
+/**
+ * Validates the data set
+ *
+ * @returns true if valid.
+ * @returns false if invalid.
+ *
+ * @param   pHdr        Pointer to the data set.
+ * @param   cb          The size of the data set.
+ * @param   pOut        Where to write error messages.
+ */
+static bool kPrfIsValidate(PCKPRFHDR pHdr, KU32 cb, FILE *pOut)
+{
+    /*
+     * We ASSUMES that the header is identicial with the exception
+     * of the uBasePtr size. (this is padded out and the upper bits are all zero)
+     */
+
+    if (    pHdr->Hdr32.u32Magic != KPRF32HDR_MAGIC
+        &&  pHdr->Hdr32.u32Magic != KPRF64HDR_MAGIC)
+    {
+        fprintf(pOut, "Invalid magic %#x\n", pHdr->Hdr32.u32Magic);
+        return false;
+    }
+
+    if (    pHdr->Hdr32.cFormatBits != 32
+        &&  pHdr->Hdr32.cFormatBits != 64)
+    {
+        fprintf(pOut, "Invalid/Unsupported bit count %u\n", pHdr->Hdr32.cFormatBits);
+        return false;
+    }
+
+    if (pHdr->Hdr32.cb > cb)
+    {
+        fprintf(pOut, "Data set size mismatch. Header say %#x, input is %#x\n", pHdr->Hdr32.cb, cb);
+        return false;
+    }
+
+#define KPRF_VALIDATE_SIZE(MemBaseName, cb32, cb64) do {\
+        if (pHdr->Hdr32.cb##MemBaseName > (pHdr->Hdr32.cFormatBits == 32 ? cb32 : cb64)) \
+        { \
+            fprintf(pOut, "cb" #MemBaseName " was expected to be %#x but is %#x. Probably a format change, rebuild.\n", \
+                    (unsigned)(pHdr->Hdr32.cFormatBits == 32 ? cb32 : cb64), pHdr->Hdr32.cb##MemBaseName); \
+            return false; \
+        }\
+    } while (0)
+
+    KPRF_VALIDATE_SIZE(Function, sizeof(KPRF32FUNC), sizeof(KPRF64FUNC));
+    KPRF_VALIDATE_SIZE(Thread, sizeof(KPRF32THREAD), sizeof(KPRF64THREAD));
+    KPRF_VALIDATE_SIZE(Stack,
+                       (KU32)&((PKPRF32STACK)0)->aFrames[pHdr->Hdr32.cMaxStackFrames],
+                       (KU32)&((PKPRF64STACK)0)->aFrames[pHdr->Hdr32.cMaxStackFrames]);
+
+    KUPTR cbHeader = (KUPTR)&pHdr->Hdr32.aiFunctions[pHdr->Hdr32.cFunctions] - (KUPTR)pHdr;
+    if (    cbHeader != (KU32)cbHeader
+        ||  cbHeader >= cb)
+    {
+        fprintf(pOut, "cFunctions (%#x) is too large to fit the lookup table inside the data set.\n",
+                pHdr->Hdr32.cFunctions);
+        return false;
+    }
+
+    /* The space assignment is hereby required to be equal to the member order in the header. */
+    KU32 offMin = cbHeader;
+#define KPRF_VALIDATE_OFF(off, name) do {\
+        if (    off > 0 \
+            &&  off < offMin) \
+        { \
+            fprintf(pOut, #name " (%#x) is overlapping with other element or invalid space assignment order.\n", off); \
+            return false; \
+        }\
+        if (off >= cb) \
+        { \
+            fprintf(pOut, #name " (%#x) is outside the data set (%#x)\n", off, cb); \
+            return false; \
+        }\
+    } while (0)
+#define KPRF_VALIDATE_MEM(MemBaseName) do {\
+        KPRF_VALIDATE_OFF(pHdr->Hdr32.off##MemBaseName##s, off##MemBaseName##s); \
+        if (    pHdr->Hdr32.off##MemBaseName##s \
+            &&  (   pHdr->Hdr32.off##MemBaseName##s + pHdr->Hdr32.cb##MemBaseName * pHdr->Hdr32.cMax##MemBaseName##s > cb \
+                 || pHdr->Hdr32.off##MemBaseName##s + pHdr->Hdr32.cb##MemBaseName * pHdr->Hdr32.cMax##MemBaseName##s < pHdr->Hdr32.off##MemBaseName##s)\
+           ) \
+        { \
+            fprintf(pOut, #MemBaseName " (%#x) is outside the data set (%#x)\n", \
+                    pHdr->Hdr32.off##MemBaseName##s + pHdr->Hdr32.cb##MemBaseName * pHdr->Hdr32.cMax##MemBaseName##s, cb); \
+            return false; \
+        }\
+        if (pHdr->Hdr32.c##MemBaseName##s > pHdr->Hdr32.cMax##MemBaseName##s) \
+        { \
+            fprintf(pOut, "c" #MemBaseName " (%#x) higher than the max (%#x)\n", \
+                    pHdr->Hdr32.c##MemBaseName##s, pHdr->Hdr32.cMax##MemBaseName##s); \
+            return false; \
+        } \
+        if (pHdr->Hdr32.off##MemBaseName##s) \
+            offMin += pHdr->Hdr32.cb##MemBaseName * pHdr->Hdr32.cMax##MemBaseName##s; \
+    } while (0)
+
+    KPRF_VALIDATE_MEM(Function);
+    KPRF_VALIDATE_OFF(pHdr->Hdr32.offModSegs, offModSegs);
+    if (pHdr->Hdr32.offModSegs)
+        KPRF_VALIDATE_OFF(pHdr->Hdr32.offModSegs + pHdr->Hdr32.cbMaxModSegs, cbMaxModSegs);
+    if (pHdr->Hdr32.cbModSegs > pHdr->Hdr32.cbMaxModSegs)
+    {
+        fprintf(pOut, "ccbModSegs (%#x) higher than the max (%#x)\n",
+                pHdr->Hdr32.cbModSegs, pHdr->Hdr32.cbMaxModSegs);
+        return false;
+    }
+    if (pHdr->Hdr32.offModSegs) \
+        offMin += pHdr->Hdr32.cbMaxModSegs; \
+    KPRF_VALIDATE_MEM(Thread);
+    KPRF_VALIDATE_MEM(Stack);
+    KPRF_VALIDATE_OFF(pHdr->Hdr32.offCommandLine, offCommandLine);
+    KPRF_VALIDATE_OFF(pHdr->Hdr32.offCommandLine + pHdr->Hdr32.cchCommandLine, cchCommandLine);
+
+    /*
+     * Validate the function lookup table
+     */
+    for (KU32 i = 0; i < pHdr->Hdr32.cFunctions; i++)
+        if (pHdr->Hdr32.aiFunctions[i] >= pHdr->Hdr32.cFunctions)
+        {
+            fprintf(pOut, "Function lookup entry %#x is invalid: index %#x, max is %#x\n",
+                    i, pHdr->Hdr32.aiFunctions[i], pHdr->Hdr32.cFunctions);
+            return false;
+        }
+
+    /*
+     * Validate the functions.
+     */
+    switch (pHdr->Hdr32.cFormatBits)
+    {
+        case 32:
+            return KPrf32IsValid(&pHdr->Hdr32, cb, pOut);
+
+        case 64:
+            return KPrf64IsValid(&pHdr->Hdr64, cb, pOut);
+    }
+    return false;
+#undef KPRF_VALIDATE_SIZE
+#undef KPRF_VALIDATE_MEM
+#undef KPRF_VALIDATE_OFF
+}
+
+
+/**
+ * Dumps a kProfiler 2 format file.
+ *
+ * @returns 0 on success.
+ * @returns -1 on failure.
+ *
+ * @param   pszFilename         The path to the profiler data set.
+ * @param   pOut                Where to write the output.
+ */
+int KPrfDumpFile(const char *pszFilename, FILE *pOut)
+{
+    /*
+     * Load and validate the data set.
+     */
+    KU32 cb;
+    PKPRFHDR pHdr = kPrfLoad(pszFilename, &cb, pOut);
+    if (!pHdr)
+        return -1;
+    if (!kPrfIsValidate(pHdr, cb, pOut))
+        return -1;
+
+    /*
+     * Switch to the appropirate dumper routine.
+     */
+    int rc;
+    switch (pHdr->Hdr32.cFormatBits)
+    {
+        case 32:
+            rc = KPrf32Dump(&pHdr->Hdr32, pOut);
+            break;
+
+        case 64:
+            rc = KPrf64Dump(&pHdr->Hdr64, pOut);
+            break;
+
+        default:
+            fprintf(stderr, "Unsupported bit count %d\n", pHdr->Hdr32.cFormatBits);
+            rc = -1;
+            break;
+    }
+
+    return rc;
+}
+
+
+/**
+ * Creates a HTML report from a kProfiler 2 format file.
+ *
+ * @returns 0 on success.
+ * @returns -1 on failure.
+ *
+ * @param   pszFilename         The path to the profiler data set.
+ * @param   pOut                Where to write the output.
+ */
+int KPrfHtmlReport(const char *pszFilename, FILE *pOut)
+{
+    /*
+     * Load and validate the data set.
+     */
+    KU32 cb;
+    PKPRFHDR pHdr = kPrfLoad(pszFilename, &cb, pOut);
+    if (!pHdr)
+        return -1;
+    if (!kPrfIsValidate(pHdr, cb, pOut))
+        return -1;
+
+    /*
+     * Switch to the appropirate dumper routine.
+     */
+    int rc;
+    switch (pHdr->Hdr32.cFormatBits)
+    {
+        case 32:
+        {
+            PKPRF32REPORT pReport;
+            rc = KPrf32Analyse(&pHdr->Hdr32, &pReport);
+            if (!rc)
+            {
+                rc = KPrf32WriteHtmlReport(pReport, pOut);
+                if (rc)
+                    fprintf(stderr, "Error while writing HTML report for '%s'\n", pszFilename);
+                KPrf32DeleteReport(pReport);
+            }
+            else
+                fprintf(stderr, "Analysis of '%s' failed!\n", pszFilename);
+            break;
+        }
+
+        case 64:
+        {
+            PKPRF64REPORT pReport;
+            rc = KPrf64Analyse(&pHdr->Hdr64, &pReport);
+            if (!rc)
+            {
+                rc = KPrf64WriteHtmlReport(pReport, pOut);
+                if (rc)
+                    fprintf(stderr, "Error while writing HTML report for '%s'\n", pszFilename);
+                KPrf64DeleteReport(pReport);
+            }
+            else
+                fprintf(stderr, "Analysis of '%s' failed!\n", pszFilename);
+            break;
+        }
+
+        default:
+            fprintf(stderr, "Unsupported bit count %d\n", pHdr->Hdr32.cFormatBits);
+            rc = -1;
+            break;
+    }
+
+    return rc;
+}
+
+
+
+/**
+ * Prints the usage.
+ */
+static int Usage(void)
+{
+    printf("kProfiler MK2 - Reader & Producer of Statistics\n"
+           "usage: kPrf2Read [-r|-d] <file1> [[-r|-d] file2 []]\n"
+           );
+    return 1;
+}
+
+
+int main(int argc, char **argv)
+{
+    /*
+     * Parse arguments.
+     */
+    if (argc <= 1)
+        return Usage();
+    enum { OP_DUMP, OP_HTML } enmOp = OP_DUMP;
+    for (int i = 1; i < argc; i++)
+    {
+        if (argv[i][0] == '-')
+        {
+            switch (argv[i][1])
+            {
+                case 'h':
+                case 'H':
+                case '?':
+                case '-':
+                    return Usage();
+
+                case 'd':
+                    enmOp = OP_DUMP;
+                    break;
+
+                case 'r':
+                    enmOp = OP_HTML;
+                    break;
+
+                default:
+                    printf("Syntax error: Unknown argument '%s'\n", argv[i]);
+                    return 1;
+            }
+        }
+        else
+        {
+            int rc;
+            switch (enmOp)
+            {
+                case OP_DUMP:
+                    rc = KPrfDumpFile(argv[i], stdout);
+                    break;
+                case OP_HTML:
+                    rc = KPrfHtmlReport(argv[i], stdout);
+                    break;
+            }
+            if (rc)
+                return rc;
+        }
+    }
+
+    return 0;
+}
diff --git a/src/lib/kStuff/kProfiler2/kPrf2WinApi-dumpbin.sed b/src/lib/kStuff/kProfiler2/kPrf2WinApi-dumpbin.sed
new file mode 100644
index 0000000..a9a44f2
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kPrf2WinApi-dumpbin.sed
@@ -0,0 +1,96 @@
+# $Id: kPrf2WinApi-dumpbin.sed 29 2009-07-01 20:30:29Z bird $
+## @file
+# Strip down dumpbin /export output.
+#
+
+#
+# Copyright (c) 2008 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+#
+# State switch
+#
+x
+/^exports$/b exports
+/^summary$/b summary
+b header
+
+#
+# Header
+#
+:header
+x
+/^[[:space:]][[:space:]]*ordinal[[:space:]]*name[[:space:]]*$/b switch_to_exports
+b drop_line
+
+#
+# Exports
+#
+:switch_to_exports
+s/^.*$/exports/
+h
+b drop_line
+
+:exports
+x
+/^[[:space:]][[:space:]]*Summary[[:space:]]*$/b switch_to_summary
+s/^[[:space:]]*//
+s/[[:space:]]*$//
+s/[[:space:]][[:space:]]*/ /g
+/^$/b drop_line
+
+# Filter out APIs that hasn't been implemented.
+/AddLocalAlternateComputerNameA/b drop_line
+/AddLocalAlternateComputerNameW/b drop_line
+/EnumerateLocalComputerNamesA/b drop_line
+/EnumerateLocalComputerNamesW/b drop_line
+/RemoveLocalAlternateComputerNameA/b drop_line
+/RemoveLocalAlternateComputerNameW/b drop_line
+/SetLocalPrimaryComputerNameA/b drop_line
+/SetLocalPrimaryComputerNameW/b drop_line
+/__C_specific_handler/b drop_line
+/__misaligned_access/b drop_line
+/_local_unwind/b drop_line
+
+b end
+
+#
+# Summary
+#
+:switch_to_summary
+s/^.*$/summary/
+h
+b drop_line
+
+:summary
+x
+b drop_line
+
+#
+# Tail
+#
+:drop_line
+d
+:end
+
diff --git a/src/lib/kStuff/kProfiler2/kPrf2WinApi-gencode.sed b/src/lib/kStuff/kProfiler2/kPrf2WinApi-gencode.sed
new file mode 100644
index 0000000..7d39edf
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kPrf2WinApi-gencode.sed
@@ -0,0 +1,120 @@
+# $Id: kPrf2WinApi-gencode.sed 29 2009-07-01 20:30:29Z bird $
+## @file
+# Generate code (for kernel32).
+#
+
+#
+# Copyright (c) 2008 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+# Example:
+#       BOOL WINAPI FindActCtxSectionGuid( DWORD dwFlags, const GUID * lpExtensionGuid, ULONG ulSectionId, const GUID * lpGuidToFind, PACTCTX_SECTION_KEYED_DATA ReturnedData );
+#
+# Should be turned into:
+#       typedef BOOL WINAPI FN_FindActCtxSectionGuid( DWORD dwFlags, const GUID * lpExtensionGuid, ULONG ulSectionId, const GUID * lpGuidToFind, PACTCTX_SECTION_KEYED_DATA ReturnedData );
+#       __declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindActCtxSectionGuid( DWORD dwFlags, const GUID * lpExtensionGuid, ULONG ulSectionId, const GUID * lpGuidToFind, PACTCTX_SECTION_KEYED_DATA ReturnedData )
+#       {
+#           static FN_FindActCtxSectionGuid *pfn = 0;
+#           if (!pfn)
+#               kPrfWrapResolve((void **)&pfn, "FindActCtxSectionGuid", &g_Kernel32);
+#           return pfn( dwFlags, lpExtensionGuid, ulSectionId, lpGuidToFind, ReturnedData );
+#       }
+#
+
+# Ignore empty lines.
+/^[[:space:]]*$/b delete
+
+# Some hacks.
+/([[:space:]]*VOID[[:space:]]*)/b no_hacking_void
+s/([[:space:]]*\([A-Z][A-Z0-9_]*\)[[:space:]]*)/( \1 a)/
+:no_hacking_void
+
+
+# Save the pattern space.
+h
+
+# Make the typedef.
+s/[[:space:]]\([A-Za-z_][A-Za-z0-9_]*\)(/ FN_\1(/
+s/^/typedef /
+p
+
+# Function definition
+g
+s/\n//g
+s/\r//g
+s/[[:space:]]\([A-Za-z_][A-Za-z0-9_]*\)(/ kPrf2Wrap_\1(/
+s/^/__declspec(dllexport) /
+s/;//
+p
+i\
+{
+
+#     static FN_FindActCtxSectionGuid *pfn = 0;
+#     if (!pfn)
+g
+s/^.*[[:space:]]\([A-Za-z_][A-Za-z0-9_]*\)(.*$/    static FN_\1 *pfn = 0;/
+p
+i\
+    if (!pfn)
+
+#       kPrfWrapResolve((void **)&pfn, "FindActCtxSectionGuid", &g_Kernel32);
+g
+s/^.*[[:space:]]\([A-Za-z_][A-Za-z0-9_]*\)(.*$/        kPrf2WrapResolve((void **)\&pfn, "\1\", \&g_Kernel32);/
+p
+
+#     The invocation and return statement.
+#     Some trouble here....
+g
+/^VOID WINAPI/b void_return
+/^void WINAPI/b void_return
+/^VOID __cdecl/b void_return
+/^void __cdecl/b void_return
+/^VOID NTAPI/b void_return
+/^void NTAPI/b void_return
+s/^.*(/    return pfn(/
+b morph_params
+
+:void_return
+s/^.*(/    pfn(/
+
+:morph_params
+s/ *\[\] *//
+s/ \*/ /g
+s/, *[a-zA-Z_][^,)]* \([a-zA-Z_][a-zA-Z_0-9]* *)\)/, \1/g
+s/( *[a-zA-Z_][^,)]* \([a-zA-Z_][a-zA-Z_0-9]* *[,)]\)/( \1/g
+s/, *[a-zA-Z_][^,)]* \([a-zA-Z_][a-zA-Z_0-9]* *,\)/, \1/g
+s/, *[a-zA-Z_][^,)]* \([a-zA-Z_][a-zA-Z_0-9]* *,\)/, \1/g
+s/, *[a-zA-Z_][^,)]* \([a-zA-Z_][a-zA-Z_0-9]* *,\)/, \1/g
+s/, *[a-zA-Z_][^,)]* \([a-zA-Z_][a-zA-Z_0-9]* *,\)/, \1/g
+s/( VOID )/ ()/
+s/( void )/ ()/
+p
+i\
+}
+i\
+
+# Done
+:delete
+d
+
diff --git a/src/lib/kStuff/kProfiler2/kPrf2WinApi-genimp.sed b/src/lib/kStuff/kProfiler2/kPrf2WinApi-genimp.sed
new file mode 100644
index 0000000..1473ed0
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kPrf2WinApi-genimp.sed
@@ -0,0 +1,55 @@
+# $Id: kPrf2WinApi-genimp.sed 29 2009-07-01 20:30:29Z bird $
+##
+# Generate imports from normalized dumpbin output.
+#
+
+#
+# Copyright (c) 2008 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+# Normalize the input a bit.
+s/[[:space:]][[:space:]]*/ /g
+s/^[[:space:]]//
+s/[[:space:]]$//
+/^$/b drop_line
+
+# Expects a single name - no ordinals yet.
+/\@/b have_at
+
+s/^\(.*\)$/  \1=kPrf2Wrap_\1/
+b end
+
+:have_at
+h
+s/^\([^ ]\)\(@[0-9]*\)$/  \1\2=kPrf2Wrap_\1/
+p
+g
+s/^\([^ ]\)\(@[0-9]*\)$/  \1=kPrf2Wrap_\1/
+b end
+
+:drop_line
+d
+b end
+
+:end
diff --git a/src/lib/kStuff/kProfiler2/kPrf2WinApi-pre.sed b/src/lib/kStuff/kProfiler2/kPrf2WinApi-pre.sed
new file mode 100644
index 0000000..de90156
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kPrf2WinApi-pre.sed
@@ -0,0 +1,117 @@
+# $Id: kPrf2WinApi-pre.sed 29 2009-07-01 20:30:29Z bird $
+## @file
+# This SED script will try normalize a windows header
+# in order to make it easy to pick out function prototypes.
+#
+
+#
+# Copyright (c) 2008 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+
+# Drop all preprocessor lines (#if/#else/#endif/#define/#undef/#pragma/comments)
+# (we don't bother with multi line comments ATM.)
+/^[[:space:]]*#/b drop_line
+/^[[:space:]]*\/\//b drop_line
+
+# Drop empty lines.
+/^[[:space:]]*$/b drop_line
+
+# Drop trailing comments and trailing whitespace
+s/[[:space:]][[:space:]]*\/\.*$//g
+s,[[:space:]][[:space:]]*/\*[^*/]*\*/[[:space:]]*$,,g
+s/[[:space:]][[:space:]]*$//g
+
+# Pick out the WINBASEAPI stuff (WinBase.h)
+/^WINBASEAPI/b winapi
+/^NTSYSAPI/b winapi
+/^WINAPI$/b winapi_perhaps
+/^APIENTRY$/b winapi_perhaps
+h
+d
+b end
+
+# No WINBASEAPI, so we'll have to carefully check the hold buffer.
+:winapi_perhaps
+x
+/^[A-Z][A-Z0-9_][A-Z0-9_]*[A-Z0-9]$/!b drop_line
+G
+s/\r/ /g
+s/\n/ /g
+b winapi
+
+# Make it one line and a bit standardized
+:winapi
+/;/b winapi_got_it
+N
+b winapi
+:winapi_got_it
+s/\n/ /g
+s/[[:space:]][[:space:]]*\/\*[^*/]*\*\/[[:space:]]*//g
+s/[[:space:]][[:space:]]*(/(/g
+s/)[[:space:]][[:space:]]*/)/g
+s/(\([^[:space:]]\)/( \1/g
+s/\([^[:space:]]\))/\1 )/g
+s/[*]\([^[:space:]]\)/* \1/g
+s/\([^[:space:]]\)[*]/\1 */g
+s/[[:space:]][[:space:]]*/ /g
+s/[[:space:]][[:space:]]*,/,/g
+s/,/, /g
+s/,[[:space:]][[:space:]]*/, /g
+
+# Drop the nasty bit of the sal.h / SpecString.h stuff.
+s/[[:space:]]__[a-z][a-z_]*([^()]*)[[:space:]]*/ /g
+s/[[:space:]]__out[a-z_]*[[:space:]]*/ /g
+s/[[:space:]]__in[a-z_]*[[:space:]]*/ /g
+s/[[:space:]]__deref[a-z_]*[[:space:]]*/ /g
+s/[[:space:]]__reserved[[:space:]]*/ /g
+s/[[:space:]]__nullnullterminated[[:space:]]*/ /g
+s/[[:space:]]__checkReturn[[:space:]]*/ /g
+
+# Drop some similar stuff.
+s/[[:space:]]OPTIONAL[[:space:]]/ /g
+s/[[:space:]]OPTIONAL,/ ,/g
+
+# The __declspec() bit isn't necessary
+s/WINBASEAPI *//
+s/NTSYSAPI *//
+s/DECLSPEC_NORETURN *//
+s/__declspec([^()]*) *//
+
+# Normalize spaces.
+s/[[:space:]]/ /g
+
+# Clear the hold space
+x
+s/^.*$//
+x
+b end
+
+:drop_line
+s/^.*$//
+h
+d
+
+:end
+
diff --git a/src/lib/kStuff/kProfiler2/kPrf2WinApiWrapperHlp.c b/src/lib/kStuff/kProfiler2/kPrf2WinApiWrapperHlp.c
new file mode 100644
index 0000000..0788cdf
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kPrf2WinApiWrapperHlp.c
@@ -0,0 +1,53 @@
+/* $Id: kPrf2WinApiWrapperHlp.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * Helpers for the Windows API wrapper DLL.
+ */
+
+/*
+ * Copyright (c) 2008 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <Windows.h>
+#include "kPRf2WinApiWRapperHlp.h"
+
+
+FARPROC kPrf2WrapResolve(void **ppfn, const char *pszName, PKPRF2WRAPDLL pDll)
+{
+    FARPROC pfn;
+    HMODULE hmod = pDll->hmod;
+    if (hmod == INVALID_HANDLE_VALUE)
+    {
+        hmod = LoadLibraryA(pDll->szName);
+        pDll->hmod = hmod;
+    }
+
+    pfn = GetProcAddress(hmod, pszName);
+    *ppfn = (void *)pfn;
+    return pfn;
+}
+
+
diff --git a/src/lib/kStuff/kProfiler2/kPrf2WinApiWrapperHlp.h b/src/lib/kStuff/kProfiler2/kPrf2WinApiWrapperHlp.h
new file mode 100644
index 0000000..b75d303
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kPrf2WinApiWrapperHlp.h
@@ -0,0 +1,41 @@
+/* $Id: kPrf2WinApiWrapperHlp.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * Helpers for the Windows API wrapper DLL.
+ */
+
+/*
+ * Copyright (c) 2008 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+typedef struct KPRF2WRAPDLL
+{
+    HMODULE hmod;
+    char szName[32];
+} KPRF2WRAPDLL;
+typedef KPRF2WRAPDLL *PKPRF2WRAPDLL;
+typedef KPRF2WRAPDLL const *PCKPRF2WRAPDLL;
+
+FARPROC kPrf2WrapResolve(void **ppfn, const char *pszName, PKPRF2WRAPDLL pDll);
+
+
diff --git a/src/lib/kStuff/kProfiler2/kPrf2WinApiWrappers-kernel32.h b/src/lib/kStuff/kProfiler2/kPrf2WinApiWrappers-kernel32.h
new file mode 100644
index 0000000..dde33cf
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kPrf2WinApiWrappers-kernel32.h
@@ -0,0 +1,9360 @@
+typedef PVOID WINAPI FN_EncodePointer( PVOID Ptr );
+__declspec(dllexport) PVOID WINAPI kPrf2Wrap_EncodePointer( PVOID Ptr )
+{
+    static FN_EncodePointer *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EncodePointer", &g_Kernel32);
+    return pfn( Ptr );
+}
+
+typedef PVOID WINAPI FN_DecodePointer( PVOID Ptr );
+__declspec(dllexport) PVOID WINAPI kPrf2Wrap_DecodePointer( PVOID Ptr )
+{
+    static FN_DecodePointer *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DecodePointer", &g_Kernel32);
+    return pfn( Ptr );
+}
+
+typedef PVOID WINAPI FN_EncodeSystemPointer( PVOID Ptr );
+__declspec(dllexport) PVOID WINAPI kPrf2Wrap_EncodeSystemPointer( PVOID Ptr )
+{
+    static FN_EncodeSystemPointer *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EncodeSystemPointer", &g_Kernel32);
+    return pfn( Ptr );
+}
+
+typedef PVOID WINAPI FN_DecodeSystemPointer( PVOID Ptr );
+__declspec(dllexport) PVOID WINAPI kPrf2Wrap_DecodeSystemPointer( PVOID Ptr )
+{
+    static FN_DecodeSystemPointer *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DecodeSystemPointer", &g_Kernel32);
+    return pfn( Ptr );
+}
+
+typedef DWORD WINAPI FN_GetFreeSpace( UINT a);
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetFreeSpace( UINT a)
+{
+    static FN_GetFreeSpace *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFreeSpace", &g_Kernel32);
+    return pfn( a);
+}
+
+typedef LONG WINAPI FN_InterlockedIncrement( LONG volatile * lpAddend );
+__declspec(dllexport) LONG WINAPI kPrf2Wrap_InterlockedIncrement( LONG volatile * lpAddend )
+{
+    static FN_InterlockedIncrement *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InterlockedIncrement", &g_Kernel32);
+    return pfn( lpAddend );
+}
+
+typedef LONG WINAPI FN_InterlockedDecrement( LONG volatile * lpAddend );
+__declspec(dllexport) LONG WINAPI kPrf2Wrap_InterlockedDecrement( LONG volatile * lpAddend )
+{
+    static FN_InterlockedDecrement *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InterlockedDecrement", &g_Kernel32);
+    return pfn( lpAddend );
+}
+
+typedef LONG WINAPI FN_InterlockedExchange( LONG volatile * Target, LONG Value );
+__declspec(dllexport) LONG WINAPI kPrf2Wrap_InterlockedExchange( LONG volatile * Target, LONG Value )
+{
+    static FN_InterlockedExchange *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InterlockedExchange", &g_Kernel32);
+    return pfn( Target, Value );
+}
+
+typedef LONG WINAPI FN_InterlockedExchangeAdd( LONG volatile * Addend, LONG Value );
+__declspec(dllexport) LONG WINAPI kPrf2Wrap_InterlockedExchangeAdd( LONG volatile * Addend, LONG Value )
+{
+    static FN_InterlockedExchangeAdd *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InterlockedExchangeAdd", &g_Kernel32);
+    return pfn( Addend, Value );
+}
+
+typedef LONG WINAPI FN_InterlockedCompareExchange( LONG volatile * Destination, LONG Exchange, LONG Comperand );
+__declspec(dllexport) LONG WINAPI kPrf2Wrap_InterlockedCompareExchange( LONG volatile * Destination, LONG Exchange, LONG Comperand )
+{
+    static FN_InterlockedCompareExchange *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InterlockedCompareExchange", &g_Kernel32);
+    return pfn( Destination, Exchange, Comperand );
+}
+
+typedef LONGLONG WINAPI FN_InterlockedCompareExchange64( LONGLONG volatile * Destination, LONGLONG Exchange, LONGLONG Comperand );
+__declspec(dllexport) LONGLONG WINAPI kPrf2Wrap_InterlockedCompareExchange64( LONGLONG volatile * Destination, LONGLONG Exchange, LONGLONG Comperand )
+{
+    static FN_InterlockedCompareExchange64 *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InterlockedCompareExchange64", &g_Kernel32);
+    return pfn( Destination, Exchange, Comperand );
+}
+
+typedef VOID WINAPI FN_InitializeSListHead( PSLIST_HEADER ListHead );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_InitializeSListHead( PSLIST_HEADER ListHead )
+{
+    static FN_InitializeSListHead *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InitializeSListHead", &g_Kernel32);
+    pfn( ListHead );
+}
+
+typedef PSLIST_ENTRY WINAPI FN_InterlockedPopEntrySList( PSLIST_HEADER ListHead );
+__declspec(dllexport) PSLIST_ENTRY WINAPI kPrf2Wrap_InterlockedPopEntrySList( PSLIST_HEADER ListHead )
+{
+    static FN_InterlockedPopEntrySList *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InterlockedPopEntrySList", &g_Kernel32);
+    return pfn( ListHead );
+}
+
+typedef PSLIST_ENTRY WINAPI FN_InterlockedPushEntrySList( PSLIST_HEADER ListHead, PSLIST_ENTRY ListEntry );
+__declspec(dllexport) PSLIST_ENTRY WINAPI kPrf2Wrap_InterlockedPushEntrySList( PSLIST_HEADER ListHead, PSLIST_ENTRY ListEntry )
+{
+    static FN_InterlockedPushEntrySList *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InterlockedPushEntrySList", &g_Kernel32);
+    return pfn( ListHead, ListEntry );
+}
+
+typedef PSLIST_ENTRY WINAPI FN_InterlockedFlushSList( PSLIST_HEADER ListHead );
+__declspec(dllexport) PSLIST_ENTRY WINAPI kPrf2Wrap_InterlockedFlushSList( PSLIST_HEADER ListHead )
+{
+    static FN_InterlockedFlushSList *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InterlockedFlushSList", &g_Kernel32);
+    return pfn( ListHead );
+}
+
+typedef USHORT WINAPI FN_QueryDepthSList( PSLIST_HEADER ListHead );
+__declspec(dllexport) USHORT WINAPI kPrf2Wrap_QueryDepthSList( PSLIST_HEADER ListHead )
+{
+    static FN_QueryDepthSList *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "QueryDepthSList", &g_Kernel32);
+    return pfn( ListHead );
+}
+
+typedef BOOL WINAPI FN_FreeResource( HGLOBAL hResData );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FreeResource( HGLOBAL hResData )
+{
+    static FN_FreeResource *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FreeResource", &g_Kernel32);
+    return pfn( hResData );
+}
+
+typedef LPVOID WINAPI FN_LockResource( HGLOBAL hResData );
+__declspec(dllexport) LPVOID WINAPI kPrf2Wrap_LockResource( HGLOBAL hResData )
+{
+    static FN_LockResource *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LockResource", &g_Kernel32);
+    return pfn( hResData );
+}
+
+typedef BOOL WINAPI FN_FreeLibrary( HMODULE hLibModule );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FreeLibrary( HMODULE hLibModule )
+{
+    static FN_FreeLibrary *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FreeLibrary", &g_Kernel32);
+    return pfn( hLibModule );
+}
+
+typedef VOID WINAPI FN_FreeLibraryAndExitThread( HMODULE hLibModule, DWORD dwExitCode );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_FreeLibraryAndExitThread( HMODULE hLibModule, DWORD dwExitCode )
+{
+    static FN_FreeLibraryAndExitThread *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FreeLibraryAndExitThread", &g_Kernel32);
+    pfn( hLibModule, dwExitCode );
+}
+
+typedef BOOL WINAPI FN_DisableThreadLibraryCalls( HMODULE hLibModule );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DisableThreadLibraryCalls( HMODULE hLibModule )
+{
+    static FN_DisableThreadLibraryCalls *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DisableThreadLibraryCalls", &g_Kernel32);
+    return pfn( hLibModule );
+}
+
+typedef FARPROC WINAPI FN_GetProcAddress( HMODULE hModule, LPCSTR lpProcName );
+__declspec(dllexport) FARPROC WINAPI kPrf2Wrap_GetProcAddress( HMODULE hModule, LPCSTR lpProcName )
+{
+    static FN_GetProcAddress *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProcAddress", &g_Kernel32);
+    return pfn( hModule, lpProcName );
+}
+
+typedef DWORD WINAPI FN_GetVersion( VOID );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetVersion( VOID )
+{
+    static FN_GetVersion *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetVersion", &g_Kernel32);
+    return pfn ();
+}
+
+typedef HGLOBAL WINAPI FN_GlobalAlloc( UINT uFlags, SIZE_T dwBytes );
+__declspec(dllexport) HGLOBAL WINAPI kPrf2Wrap_GlobalAlloc( UINT uFlags, SIZE_T dwBytes )
+{
+    static FN_GlobalAlloc *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalAlloc", &g_Kernel32);
+    return pfn( uFlags, dwBytes );
+}
+
+typedef HGLOBAL WINAPI FN_GlobalReAlloc( HGLOBAL hMem, SIZE_T dwBytes, UINT uFlags );
+__declspec(dllexport) HGLOBAL WINAPI kPrf2Wrap_GlobalReAlloc( HGLOBAL hMem, SIZE_T dwBytes, UINT uFlags )
+{
+    static FN_GlobalReAlloc *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalReAlloc", &g_Kernel32);
+    return pfn( hMem, dwBytes, uFlags );
+}
+
+typedef SIZE_T WINAPI FN_GlobalSize( HGLOBAL hMem );
+__declspec(dllexport) SIZE_T WINAPI kPrf2Wrap_GlobalSize( HGLOBAL hMem )
+{
+    static FN_GlobalSize *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalSize", &g_Kernel32);
+    return pfn( hMem );
+}
+
+typedef UINT WINAPI FN_GlobalFlags( HGLOBAL hMem );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GlobalFlags( HGLOBAL hMem )
+{
+    static FN_GlobalFlags *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalFlags", &g_Kernel32);
+    return pfn( hMem );
+}
+
+typedef LPVOID WINAPI FN_GlobalLock( HGLOBAL hMem );
+__declspec(dllexport) LPVOID WINAPI kPrf2Wrap_GlobalLock( HGLOBAL hMem )
+{
+    static FN_GlobalLock *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalLock", &g_Kernel32);
+    return pfn( hMem );
+}
+
+typedef HGLOBAL WINAPI FN_GlobalHandle( LPCVOID pMem );
+__declspec(dllexport) HGLOBAL WINAPI kPrf2Wrap_GlobalHandle( LPCVOID pMem )
+{
+    static FN_GlobalHandle *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalHandle", &g_Kernel32);
+    return pfn( pMem );
+}
+
+typedef BOOL WINAPI FN_GlobalUnlock( HGLOBAL hMem );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GlobalUnlock( HGLOBAL hMem )
+{
+    static FN_GlobalUnlock *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalUnlock", &g_Kernel32);
+    return pfn( hMem );
+}
+
+typedef HGLOBAL WINAPI FN_GlobalFree( HGLOBAL hMem );
+__declspec(dllexport) HGLOBAL WINAPI kPrf2Wrap_GlobalFree( HGLOBAL hMem )
+{
+    static FN_GlobalFree *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalFree", &g_Kernel32);
+    return pfn( hMem );
+}
+
+typedef SIZE_T WINAPI FN_GlobalCompact( DWORD dwMinFree );
+__declspec(dllexport) SIZE_T WINAPI kPrf2Wrap_GlobalCompact( DWORD dwMinFree )
+{
+    static FN_GlobalCompact *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalCompact", &g_Kernel32);
+    return pfn( dwMinFree );
+}
+
+typedef VOID WINAPI FN_GlobalFix( HGLOBAL hMem );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_GlobalFix( HGLOBAL hMem )
+{
+    static FN_GlobalFix *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalFix", &g_Kernel32);
+    pfn( hMem );
+}
+
+typedef VOID WINAPI FN_GlobalUnfix( HGLOBAL hMem );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_GlobalUnfix( HGLOBAL hMem )
+{
+    static FN_GlobalUnfix *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalUnfix", &g_Kernel32);
+    pfn( hMem );
+}
+
+typedef LPVOID WINAPI FN_GlobalWire( HGLOBAL hMem );
+__declspec(dllexport) LPVOID WINAPI kPrf2Wrap_GlobalWire( HGLOBAL hMem )
+{
+    static FN_GlobalWire *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalWire", &g_Kernel32);
+    return pfn( hMem );
+}
+
+typedef BOOL WINAPI FN_GlobalUnWire( HGLOBAL hMem );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GlobalUnWire( HGLOBAL hMem )
+{
+    static FN_GlobalUnWire *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalUnWire", &g_Kernel32);
+    return pfn( hMem );
+}
+
+typedef VOID WINAPI FN_GlobalMemoryStatus( LPMEMORYSTATUS lpBuffer );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_GlobalMemoryStatus( LPMEMORYSTATUS lpBuffer )
+{
+    static FN_GlobalMemoryStatus *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalMemoryStatus", &g_Kernel32);
+    pfn( lpBuffer );
+}
+
+typedef BOOL WINAPI FN_GlobalMemoryStatusEx( LPMEMORYSTATUSEX lpBuffer );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GlobalMemoryStatusEx( LPMEMORYSTATUSEX lpBuffer )
+{
+    static FN_GlobalMemoryStatusEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalMemoryStatusEx", &g_Kernel32);
+    return pfn( lpBuffer );
+}
+
+typedef HLOCAL WINAPI FN_LocalAlloc( UINT uFlags, SIZE_T uBytes );
+__declspec(dllexport) HLOCAL WINAPI kPrf2Wrap_LocalAlloc( UINT uFlags, SIZE_T uBytes )
+{
+    static FN_LocalAlloc *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LocalAlloc", &g_Kernel32);
+    return pfn( uFlags, uBytes );
+}
+
+typedef HLOCAL WINAPI FN_LocalReAlloc( HLOCAL hMem, SIZE_T uBytes, UINT uFlags );
+__declspec(dllexport) HLOCAL WINAPI kPrf2Wrap_LocalReAlloc( HLOCAL hMem, SIZE_T uBytes, UINT uFlags )
+{
+    static FN_LocalReAlloc *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LocalReAlloc", &g_Kernel32);
+    return pfn( hMem, uBytes, uFlags );
+}
+
+typedef LPVOID WINAPI FN_LocalLock( HLOCAL hMem );
+__declspec(dllexport) LPVOID WINAPI kPrf2Wrap_LocalLock( HLOCAL hMem )
+{
+    static FN_LocalLock *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LocalLock", &g_Kernel32);
+    return pfn( hMem );
+}
+
+typedef HLOCAL WINAPI FN_LocalHandle( LPCVOID pMem );
+__declspec(dllexport) HLOCAL WINAPI kPrf2Wrap_LocalHandle( LPCVOID pMem )
+{
+    static FN_LocalHandle *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LocalHandle", &g_Kernel32);
+    return pfn( pMem );
+}
+
+typedef BOOL WINAPI FN_LocalUnlock( HLOCAL hMem );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LocalUnlock( HLOCAL hMem )
+{
+    static FN_LocalUnlock *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LocalUnlock", &g_Kernel32);
+    return pfn( hMem );
+}
+
+typedef SIZE_T WINAPI FN_LocalSize( HLOCAL hMem );
+__declspec(dllexport) SIZE_T WINAPI kPrf2Wrap_LocalSize( HLOCAL hMem )
+{
+    static FN_LocalSize *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LocalSize", &g_Kernel32);
+    return pfn( hMem );
+}
+
+typedef UINT WINAPI FN_LocalFlags( HLOCAL hMem );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_LocalFlags( HLOCAL hMem )
+{
+    static FN_LocalFlags *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LocalFlags", &g_Kernel32);
+    return pfn( hMem );
+}
+
+typedef HLOCAL WINAPI FN_LocalFree( HLOCAL hMem );
+__declspec(dllexport) HLOCAL WINAPI kPrf2Wrap_LocalFree( HLOCAL hMem )
+{
+    static FN_LocalFree *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LocalFree", &g_Kernel32);
+    return pfn( hMem );
+}
+
+typedef SIZE_T WINAPI FN_LocalShrink( HLOCAL hMem, UINT cbNewSize );
+__declspec(dllexport) SIZE_T WINAPI kPrf2Wrap_LocalShrink( HLOCAL hMem, UINT cbNewSize )
+{
+    static FN_LocalShrink *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LocalShrink", &g_Kernel32);
+    return pfn( hMem, cbNewSize );
+}
+
+typedef SIZE_T WINAPI FN_LocalCompact( UINT uMinFree );
+__declspec(dllexport) SIZE_T WINAPI kPrf2Wrap_LocalCompact( UINT uMinFree )
+{
+    static FN_LocalCompact *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LocalCompact", &g_Kernel32);
+    return pfn( uMinFree );
+}
+
+typedef BOOL WINAPI FN_FlushInstructionCache( HANDLE hProcess, LPCVOID lpBaseAddress, SIZE_T dwSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FlushInstructionCache( HANDLE hProcess, LPCVOID lpBaseAddress, SIZE_T dwSize )
+{
+    static FN_FlushInstructionCache *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FlushInstructionCache", &g_Kernel32);
+    return pfn( hProcess, lpBaseAddress, dwSize );
+}
+
+typedef LPVOID WINAPI FN_VirtualAlloc( LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect );
+__declspec(dllexport) LPVOID WINAPI kPrf2Wrap_VirtualAlloc( LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect )
+{
+    static FN_VirtualAlloc *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VirtualAlloc", &g_Kernel32);
+    return pfn( lpAddress, dwSize, flAllocationType, flProtect );
+}
+
+typedef BOOL WINAPI FN_VirtualFree( LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_VirtualFree( LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType )
+{
+    static FN_VirtualFree *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VirtualFree", &g_Kernel32);
+    return pfn( lpAddress, dwSize, dwFreeType );
+}
+
+typedef BOOL WINAPI FN_VirtualProtect( LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_VirtualProtect( LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect )
+{
+    static FN_VirtualProtect *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VirtualProtect", &g_Kernel32);
+    return pfn( lpAddress, dwSize, flNewProtect, lpflOldProtect );
+}
+
+typedef SIZE_T WINAPI FN_VirtualQuery( LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength );
+__declspec(dllexport) SIZE_T WINAPI kPrf2Wrap_VirtualQuery( LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength )
+{
+    static FN_VirtualQuery *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VirtualQuery", &g_Kernel32);
+    return pfn( lpAddress, lpBuffer, dwLength );
+}
+
+typedef LPVOID WINAPI FN_VirtualAllocEx( HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect );
+__declspec(dllexport) LPVOID WINAPI kPrf2Wrap_VirtualAllocEx( HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect )
+{
+    static FN_VirtualAllocEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VirtualAllocEx", &g_Kernel32);
+    return pfn( hProcess, lpAddress, dwSize, flAllocationType, flProtect );
+}
+
+typedef UINT WINAPI FN_GetWriteWatch( DWORD dwFlags, PVOID lpBaseAddress, SIZE_T dwRegionSize, PVOID * lpAddresses, ULONG_PTR * lpdwCount, PULONG lpdwGranularity );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetWriteWatch( DWORD dwFlags, PVOID lpBaseAddress, SIZE_T dwRegionSize, PVOID * lpAddresses, ULONG_PTR * lpdwCount, PULONG lpdwGranularity )
+{
+    static FN_GetWriteWatch *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetWriteWatch", &g_Kernel32);
+    return pfn( dwFlags, lpBaseAddress, dwRegionSize, lpAddresses, lpdwCount, lpdwGranularity );
+}
+
+typedef UINT WINAPI FN_ResetWriteWatch( LPVOID lpBaseAddress, SIZE_T dwRegionSize );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_ResetWriteWatch( LPVOID lpBaseAddress, SIZE_T dwRegionSize )
+{
+    static FN_ResetWriteWatch *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ResetWriteWatch", &g_Kernel32);
+    return pfn( lpBaseAddress, dwRegionSize );
+}
+
+typedef SIZE_T WINAPI FN_GetLargePageMinimum( VOID );
+__declspec(dllexport) SIZE_T WINAPI kPrf2Wrap_GetLargePageMinimum( VOID )
+{
+    static FN_GetLargePageMinimum *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetLargePageMinimum", &g_Kernel32);
+    return pfn ();
+}
+
+typedef UINT WINAPI FN_EnumSystemFirmwareTables( DWORD FirmwareTableProviderSignature, PVOID pFirmwareTableEnumBuffer, DWORD BufferSize );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_EnumSystemFirmwareTables( DWORD FirmwareTableProviderSignature, PVOID pFirmwareTableEnumBuffer, DWORD BufferSize )
+{
+    static FN_EnumSystemFirmwareTables *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumSystemFirmwareTables", &g_Kernel32);
+    return pfn( FirmwareTableProviderSignature, pFirmwareTableEnumBuffer, BufferSize );
+}
+
+typedef UINT WINAPI FN_GetSystemFirmwareTable( DWORD FirmwareTableProviderSignature, DWORD FirmwareTableID, PVOID pFirmwareTableBuffer, DWORD BufferSize );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetSystemFirmwareTable( DWORD FirmwareTableProviderSignature, DWORD FirmwareTableID, PVOID pFirmwareTableBuffer, DWORD BufferSize )
+{
+    static FN_GetSystemFirmwareTable *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemFirmwareTable", &g_Kernel32);
+    return pfn( FirmwareTableProviderSignature, FirmwareTableID, pFirmwareTableBuffer, BufferSize );
+}
+
+typedef BOOL WINAPI FN_VirtualFreeEx( HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_VirtualFreeEx( HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType )
+{
+    static FN_VirtualFreeEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VirtualFreeEx", &g_Kernel32);
+    return pfn( hProcess, lpAddress, dwSize, dwFreeType );
+}
+
+typedef BOOL WINAPI FN_VirtualProtectEx( HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_VirtualProtectEx( HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect )
+{
+    static FN_VirtualProtectEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VirtualProtectEx", &g_Kernel32);
+    return pfn( hProcess, lpAddress, dwSize, flNewProtect, lpflOldProtect );
+}
+
+typedef SIZE_T WINAPI FN_VirtualQueryEx( HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength );
+__declspec(dllexport) SIZE_T WINAPI kPrf2Wrap_VirtualQueryEx( HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength )
+{
+    static FN_VirtualQueryEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VirtualQueryEx", &g_Kernel32);
+    return pfn( hProcess, lpAddress, lpBuffer, dwLength );
+}
+
+typedef HANDLE WINAPI FN_HeapCreate( DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_HeapCreate( DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize )
+{
+    static FN_HeapCreate *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "HeapCreate", &g_Kernel32);
+    return pfn( flOptions, dwInitialSize, dwMaximumSize );
+}
+
+typedef BOOL WINAPI FN_HeapDestroy( HANDLE hHeap );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_HeapDestroy( HANDLE hHeap )
+{
+    static FN_HeapDestroy *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "HeapDestroy", &g_Kernel32);
+    return pfn( hHeap );
+}
+
+typedef LPVOID WINAPI FN_HeapAlloc( HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes );
+__declspec(dllexport) LPVOID WINAPI kPrf2Wrap_HeapAlloc( HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes )
+{
+    static FN_HeapAlloc *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "HeapAlloc", &g_Kernel32);
+    return pfn( hHeap, dwFlags, dwBytes );
+}
+
+typedef LPVOID WINAPI FN_HeapReAlloc( HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes );
+__declspec(dllexport) LPVOID WINAPI kPrf2Wrap_HeapReAlloc( HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes )
+{
+    static FN_HeapReAlloc *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "HeapReAlloc", &g_Kernel32);
+    return pfn( hHeap, dwFlags, lpMem, dwBytes );
+}
+
+typedef BOOL WINAPI FN_HeapFree( HANDLE hHeap, DWORD dwFlags, LPVOID lpMem );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_HeapFree( HANDLE hHeap, DWORD dwFlags, LPVOID lpMem )
+{
+    static FN_HeapFree *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "HeapFree", &g_Kernel32);
+    return pfn( hHeap, dwFlags, lpMem );
+}
+
+typedef SIZE_T WINAPI FN_HeapSize( HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem );
+__declspec(dllexport) SIZE_T WINAPI kPrf2Wrap_HeapSize( HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem )
+{
+    static FN_HeapSize *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "HeapSize", &g_Kernel32);
+    return pfn( hHeap, dwFlags, lpMem );
+}
+
+typedef BOOL WINAPI FN_HeapValidate( HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_HeapValidate( HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem )
+{
+    static FN_HeapValidate *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "HeapValidate", &g_Kernel32);
+    return pfn( hHeap, dwFlags, lpMem );
+}
+
+typedef SIZE_T WINAPI FN_HeapCompact( HANDLE hHeap, DWORD dwFlags );
+__declspec(dllexport) SIZE_T WINAPI kPrf2Wrap_HeapCompact( HANDLE hHeap, DWORD dwFlags )
+{
+    static FN_HeapCompact *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "HeapCompact", &g_Kernel32);
+    return pfn( hHeap, dwFlags );
+}
+
+typedef HANDLE WINAPI FN_GetProcessHeap( VOID );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_GetProcessHeap( VOID )
+{
+    static FN_GetProcessHeap *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProcessHeap", &g_Kernel32);
+    return pfn ();
+}
+
+typedef DWORD WINAPI FN_GetProcessHeaps( DWORD NumberOfHeaps, PHANDLE ProcessHeaps );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetProcessHeaps( DWORD NumberOfHeaps, PHANDLE ProcessHeaps )
+{
+    static FN_GetProcessHeaps *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProcessHeaps", &g_Kernel32);
+    return pfn( NumberOfHeaps, ProcessHeaps );
+}
+
+typedef BOOL WINAPI FN_HeapLock( HANDLE hHeap );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_HeapLock( HANDLE hHeap )
+{
+    static FN_HeapLock *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "HeapLock", &g_Kernel32);
+    return pfn( hHeap );
+}
+
+typedef BOOL WINAPI FN_HeapUnlock( HANDLE hHeap );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_HeapUnlock( HANDLE hHeap )
+{
+    static FN_HeapUnlock *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "HeapUnlock", &g_Kernel32);
+    return pfn( hHeap );
+}
+
+typedef BOOL WINAPI FN_HeapWalk( HANDLE hHeap, LPPROCESS_HEAP_ENTRY lpEntry );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_HeapWalk( HANDLE hHeap, LPPROCESS_HEAP_ENTRY lpEntry )
+{
+    static FN_HeapWalk *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "HeapWalk", &g_Kernel32);
+    return pfn( hHeap, lpEntry );
+}
+
+typedef BOOL WINAPI FN_HeapSetInformation( HANDLE HeapHandle, HEAP_INFORMATION_CLASS HeapInformationClass, PVOID HeapInformation, SIZE_T HeapInformationLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_HeapSetInformation( HANDLE HeapHandle, HEAP_INFORMATION_CLASS HeapInformationClass, PVOID HeapInformation, SIZE_T HeapInformationLength )
+{
+    static FN_HeapSetInformation *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "HeapSetInformation", &g_Kernel32);
+    return pfn( HeapHandle, HeapInformationClass, HeapInformation, HeapInformationLength );
+}
+
+typedef BOOL WINAPI FN_HeapQueryInformation( HANDLE HeapHandle, HEAP_INFORMATION_CLASS HeapInformationClass, PVOID HeapInformation, SIZE_T HeapInformationLength, PSIZE_T ReturnLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_HeapQueryInformation( HANDLE HeapHandle, HEAP_INFORMATION_CLASS HeapInformationClass, PVOID HeapInformation, SIZE_T HeapInformationLength, PSIZE_T ReturnLength )
+{
+    static FN_HeapQueryInformation *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "HeapQueryInformation", &g_Kernel32);
+    return pfn( HeapHandle, HeapInformationClass, HeapInformation, HeapInformationLength, ReturnLength );
+}
+
+typedef BOOL WINAPI FN_GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
+{
+    static FN_GetBinaryTypeA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetBinaryTypeA", &g_Kernel32);
+    return pfn( lpApplicationName, lpBinaryType );
+}
+
+typedef BOOL WINAPI FN_GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
+{
+    static FN_GetBinaryTypeW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetBinaryTypeW", &g_Kernel32);
+    return pfn( lpApplicationName, lpBinaryType );
+}
+
+typedef DWORD WINAPI FN_GetShortPathNameA( LPCSTR lpszLongPath, LPSTR lpszShortPath, DWORD cchBuffer );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetShortPathNameA( LPCSTR lpszLongPath, LPSTR lpszShortPath, DWORD cchBuffer )
+{
+    static FN_GetShortPathNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetShortPathNameA", &g_Kernel32);
+    return pfn( lpszLongPath, lpszShortPath, cchBuffer );
+}
+
+typedef DWORD WINAPI FN_GetShortPathNameW( LPCWSTR lpszLongPath, LPWSTR lpszShortPath, DWORD cchBuffer );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetShortPathNameW( LPCWSTR lpszLongPath, LPWSTR lpszShortPath, DWORD cchBuffer )
+{
+    static FN_GetShortPathNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetShortPathNameW", &g_Kernel32);
+    return pfn( lpszLongPath, lpszShortPath, cchBuffer );
+}
+
+typedef DWORD WINAPI FN_GetLongPathNameA( LPCSTR lpszShortPath, LPSTR lpszLongPath, DWORD cchBuffer );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetLongPathNameA( LPCSTR lpszShortPath, LPSTR lpszLongPath, DWORD cchBuffer )
+{
+    static FN_GetLongPathNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetLongPathNameA", &g_Kernel32);
+    return pfn( lpszShortPath, lpszLongPath, cchBuffer );
+}
+
+typedef DWORD WINAPI FN_GetLongPathNameW( LPCWSTR lpszShortPath, LPWSTR lpszLongPath, DWORD cchBuffer );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetLongPathNameW( LPCWSTR lpszShortPath, LPWSTR lpszLongPath, DWORD cchBuffer )
+{
+    static FN_GetLongPathNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetLongPathNameW", &g_Kernel32);
+    return pfn( lpszShortPath, lpszLongPath, cchBuffer );
+}
+
+typedef BOOL WINAPI FN_GetProcessAffinityMask( HANDLE hProcess, PDWORD_PTR lpProcessAffinityMask, PDWORD_PTR lpSystemAffinityMask );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetProcessAffinityMask( HANDLE hProcess, PDWORD_PTR lpProcessAffinityMask, PDWORD_PTR lpSystemAffinityMask )
+{
+    static FN_GetProcessAffinityMask *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProcessAffinityMask", &g_Kernel32);
+    return pfn( hProcess, lpProcessAffinityMask, lpSystemAffinityMask );
+}
+
+typedef BOOL WINAPI FN_SetProcessAffinityMask( HANDLE hProcess, DWORD_PTR dwProcessAffinityMask );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetProcessAffinityMask( HANDLE hProcess, DWORD_PTR dwProcessAffinityMask )
+{
+    static FN_SetProcessAffinityMask *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetProcessAffinityMask", &g_Kernel32);
+    return pfn( hProcess, dwProcessAffinityMask );
+}
+
+typedef BOOL WINAPI FN_GetProcessHandleCount( HANDLE hProcess, PDWORD pdwHandleCount );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetProcessHandleCount( HANDLE hProcess, PDWORD pdwHandleCount )
+{
+    static FN_GetProcessHandleCount *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProcessHandleCount", &g_Kernel32);
+    return pfn( hProcess, pdwHandleCount );
+}
+
+typedef BOOL WINAPI FN_GetProcessTimes( HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetProcessTimes( HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime )
+{
+    static FN_GetProcessTimes *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProcessTimes", &g_Kernel32);
+    return pfn( hProcess, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime );
+}
+
+typedef BOOL WINAPI FN_GetProcessIoCounters( HANDLE hProcess, PIO_COUNTERS lpIoCounters );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetProcessIoCounters( HANDLE hProcess, PIO_COUNTERS lpIoCounters )
+{
+    static FN_GetProcessIoCounters *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProcessIoCounters", &g_Kernel32);
+    return pfn( hProcess, lpIoCounters );
+}
+
+typedef BOOL WINAPI FN_GetProcessWorkingSetSize( HANDLE hProcess, PSIZE_T lpMinimumWorkingSetSize, PSIZE_T lpMaximumWorkingSetSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetProcessWorkingSetSize( HANDLE hProcess, PSIZE_T lpMinimumWorkingSetSize, PSIZE_T lpMaximumWorkingSetSize )
+{
+    static FN_GetProcessWorkingSetSize *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProcessWorkingSetSize", &g_Kernel32);
+    return pfn( hProcess, lpMinimumWorkingSetSize, lpMaximumWorkingSetSize );
+}
+
+typedef BOOL WINAPI FN_GetProcessWorkingSetSizeEx( HANDLE hProcess, PSIZE_T lpMinimumWorkingSetSize, PSIZE_T lpMaximumWorkingSetSize, PDWORD Flags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetProcessWorkingSetSizeEx( HANDLE hProcess, PSIZE_T lpMinimumWorkingSetSize, PSIZE_T lpMaximumWorkingSetSize, PDWORD Flags )
+{
+    static FN_GetProcessWorkingSetSizeEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProcessWorkingSetSizeEx", &g_Kernel32);
+    return pfn( hProcess, lpMinimumWorkingSetSize, lpMaximumWorkingSetSize, Flags );
+}
+
+typedef BOOL WINAPI FN_SetProcessWorkingSetSize( HANDLE hProcess, SIZE_T dwMinimumWorkingSetSize, SIZE_T dwMaximumWorkingSetSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetProcessWorkingSetSize( HANDLE hProcess, SIZE_T dwMinimumWorkingSetSize, SIZE_T dwMaximumWorkingSetSize )
+{
+    static FN_SetProcessWorkingSetSize *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetProcessWorkingSetSize", &g_Kernel32);
+    return pfn( hProcess, dwMinimumWorkingSetSize, dwMaximumWorkingSetSize );
+}
+
+typedef BOOL WINAPI FN_SetProcessWorkingSetSizeEx( HANDLE hProcess, SIZE_T dwMinimumWorkingSetSize, SIZE_T dwMaximumWorkingSetSize, DWORD Flags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetProcessWorkingSetSizeEx( HANDLE hProcess, SIZE_T dwMinimumWorkingSetSize, SIZE_T dwMaximumWorkingSetSize, DWORD Flags )
+{
+    static FN_SetProcessWorkingSetSizeEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetProcessWorkingSetSizeEx", &g_Kernel32);
+    return pfn( hProcess, dwMinimumWorkingSetSize, dwMaximumWorkingSetSize, Flags );
+}
+
+typedef HANDLE WINAPI FN_OpenProcess( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenProcess( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId )
+{
+    static FN_OpenProcess *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenProcess", &g_Kernel32);
+    return pfn( dwDesiredAccess, bInheritHandle, dwProcessId );
+}
+
+typedef HANDLE WINAPI FN_GetCurrentProcess( VOID );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_GetCurrentProcess( VOID )
+{
+    static FN_GetCurrentProcess *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCurrentProcess", &g_Kernel32);
+    return pfn ();
+}
+
+typedef DWORD WINAPI FN_GetCurrentProcessId( VOID );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetCurrentProcessId( VOID )
+{
+    static FN_GetCurrentProcessId *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCurrentProcessId", &g_Kernel32);
+    return pfn ();
+}
+
+typedef VOID WINAPI FN_ExitProcess( UINT uExitCode );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_ExitProcess( UINT uExitCode )
+{
+    static FN_ExitProcess *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ExitProcess", &g_Kernel32);
+    pfn( uExitCode );
+}
+
+typedef BOOL WINAPI FN_TerminateProcess( HANDLE hProcess, UINT uExitCode );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_TerminateProcess( HANDLE hProcess, UINT uExitCode )
+{
+    static FN_TerminateProcess *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "TerminateProcess", &g_Kernel32);
+    return pfn( hProcess, uExitCode );
+}
+
+typedef BOOL WINAPI FN_GetExitCodeProcess( HANDLE hProcess, LPDWORD lpExitCode );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetExitCodeProcess( HANDLE hProcess, LPDWORD lpExitCode )
+{
+    static FN_GetExitCodeProcess *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetExitCodeProcess", &g_Kernel32);
+    return pfn( hProcess, lpExitCode );
+}
+
+typedef VOID WINAPI FN_FatalExit( int ExitCode );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_FatalExit( int ExitCode )
+{
+    static FN_FatalExit *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FatalExit", &g_Kernel32);
+    pfn( ExitCode );
+}
+
+typedef LPCH WINAPI FN_GetEnvironmentStrings( VOID );
+__declspec(dllexport) LPCH WINAPI kPrf2Wrap_GetEnvironmentStrings( VOID )
+{
+    static FN_GetEnvironmentStrings *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetEnvironmentStrings", &g_Kernel32);
+    return pfn ();
+}
+
+typedef LPWCH WINAPI FN_GetEnvironmentStringsW( VOID );
+__declspec(dllexport) LPWCH WINAPI kPrf2Wrap_GetEnvironmentStringsW( VOID )
+{
+    static FN_GetEnvironmentStringsW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetEnvironmentStringsW", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL WINAPI FN_SetEnvironmentStringsA( LPCH NewEnvironment );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetEnvironmentStringsA( LPCH NewEnvironment )
+{
+    static FN_SetEnvironmentStringsA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetEnvironmentStringsA", &g_Kernel32);
+    return pfn( NewEnvironment );
+}
+
+typedef BOOL WINAPI FN_SetEnvironmentStringsW( LPWCH NewEnvironment );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetEnvironmentStringsW( LPWCH NewEnvironment )
+{
+    static FN_SetEnvironmentStringsW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetEnvironmentStringsW", &g_Kernel32);
+    return pfn( NewEnvironment );
+}
+
+typedef BOOL WINAPI FN_FreeEnvironmentStringsA( LPCH a);
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FreeEnvironmentStringsA( LPCH a)
+{
+    static FN_FreeEnvironmentStringsA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FreeEnvironmentStringsA", &g_Kernel32);
+    return pfn( a);
+}
+
+typedef BOOL WINAPI FN_FreeEnvironmentStringsW( LPWCH a);
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FreeEnvironmentStringsW( LPWCH a)
+{
+    static FN_FreeEnvironmentStringsW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FreeEnvironmentStringsW", &g_Kernel32);
+    return pfn( a);
+}
+
+typedef VOID WINAPI FN_RaiseException( DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, CONST ULONG_PTR * lpArguments );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_RaiseException( DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, CONST ULONG_PTR * lpArguments )
+{
+    static FN_RaiseException *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RaiseException", &g_Kernel32);
+    pfn( dwExceptionCode, dwExceptionFlags, nNumberOfArguments, lpArguments );
+}
+
+typedef LONG WINAPI FN_UnhandledExceptionFilter( struct _EXCEPTION_POINTERS * ExceptionInfo );
+__declspec(dllexport) LONG WINAPI kPrf2Wrap_UnhandledExceptionFilter( struct _EXCEPTION_POINTERS * ExceptionInfo )
+{
+    static FN_UnhandledExceptionFilter *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "UnhandledExceptionFilter", &g_Kernel32);
+    return pfn( ExceptionInfo );
+}
+
+typedef LPTOP_LEVEL_EXCEPTION_FILTER WINAPI FN_SetUnhandledExceptionFilter( LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter );
+__declspec(dllexport) LPTOP_LEVEL_EXCEPTION_FILTER WINAPI kPrf2Wrap_SetUnhandledExceptionFilter( LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter )
+{
+    static FN_SetUnhandledExceptionFilter *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetUnhandledExceptionFilter", &g_Kernel32);
+    return pfn( lpTopLevelExceptionFilter );
+}
+
+typedef LPVOID WINAPI FN_CreateFiber( SIZE_T dwStackSize, LPFIBER_START_ROUTINE lpStartAddress, LPVOID lpParameter );
+__declspec(dllexport) LPVOID WINAPI kPrf2Wrap_CreateFiber( SIZE_T dwStackSize, LPFIBER_START_ROUTINE lpStartAddress, LPVOID lpParameter )
+{
+    static FN_CreateFiber *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateFiber", &g_Kernel32);
+    return pfn( dwStackSize, lpStartAddress, lpParameter );
+}
+
+typedef LPVOID WINAPI FN_CreateFiberEx( SIZE_T dwStackCommitSize, SIZE_T dwStackReserveSize, DWORD dwFlags, LPFIBER_START_ROUTINE lpStartAddress, LPVOID lpParameter );
+__declspec(dllexport) LPVOID WINAPI kPrf2Wrap_CreateFiberEx( SIZE_T dwStackCommitSize, SIZE_T dwStackReserveSize, DWORD dwFlags, LPFIBER_START_ROUTINE lpStartAddress, LPVOID lpParameter )
+{
+    static FN_CreateFiberEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateFiberEx", &g_Kernel32);
+    return pfn( dwStackCommitSize, dwStackReserveSize, dwFlags, lpStartAddress, lpParameter );
+}
+
+typedef VOID WINAPI FN_DeleteFiber( LPVOID lpFiber );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_DeleteFiber( LPVOID lpFiber )
+{
+    static FN_DeleteFiber *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DeleteFiber", &g_Kernel32);
+    pfn( lpFiber );
+}
+
+typedef LPVOID WINAPI FN_ConvertThreadToFiber( LPVOID lpParameter );
+__declspec(dllexport) LPVOID WINAPI kPrf2Wrap_ConvertThreadToFiber( LPVOID lpParameter )
+{
+    static FN_ConvertThreadToFiber *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ConvertThreadToFiber", &g_Kernel32);
+    return pfn( lpParameter );
+}
+
+typedef LPVOID WINAPI FN_ConvertThreadToFiberEx( LPVOID lpParameter, DWORD dwFlags );
+__declspec(dllexport) LPVOID WINAPI kPrf2Wrap_ConvertThreadToFiberEx( LPVOID lpParameter, DWORD dwFlags )
+{
+    static FN_ConvertThreadToFiberEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ConvertThreadToFiberEx", &g_Kernel32);
+    return pfn( lpParameter, dwFlags );
+}
+
+typedef BOOL WINAPI FN_ConvertFiberToThread( VOID );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ConvertFiberToThread( VOID )
+{
+    static FN_ConvertFiberToThread *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ConvertFiberToThread", &g_Kernel32);
+    return pfn ();
+}
+
+typedef VOID WINAPI FN_SwitchToFiber( LPVOID lpFiber );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_SwitchToFiber( LPVOID lpFiber )
+{
+    static FN_SwitchToFiber *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SwitchToFiber", &g_Kernel32);
+    pfn( lpFiber );
+}
+
+typedef BOOL WINAPI FN_SwitchToThread( VOID );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SwitchToThread( VOID )
+{
+    static FN_SwitchToThread *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SwitchToThread", &g_Kernel32);
+    return pfn ();
+}
+
+typedef HANDLE WINAPI FN_CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId )
+{
+    static FN_CreateThread *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateThread", &g_Kernel32);
+    return pfn( lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId );
+}
+
+typedef HANDLE WINAPI FN_CreateRemoteThread( HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateRemoteThread( HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId )
+{
+    static FN_CreateRemoteThread *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateRemoteThread", &g_Kernel32);
+    return pfn( hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId );
+}
+
+typedef HANDLE WINAPI FN_GetCurrentThread( VOID );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_GetCurrentThread( VOID )
+{
+    static FN_GetCurrentThread *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCurrentThread", &g_Kernel32);
+    return pfn ();
+}
+
+typedef DWORD WINAPI FN_GetCurrentThreadId( VOID );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetCurrentThreadId( VOID )
+{
+    static FN_GetCurrentThreadId *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCurrentThreadId", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL WINAPI FN_SetThreadStackGuarantee( PULONG StackSizeInBytes );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetThreadStackGuarantee( PULONG StackSizeInBytes )
+{
+    static FN_SetThreadStackGuarantee *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetThreadStackGuarantee", &g_Kernel32);
+    return pfn( StackSizeInBytes );
+}
+
+typedef DWORD WINAPI FN_GetProcessIdOfThread( HANDLE Thread );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetProcessIdOfThread( HANDLE Thread )
+{
+    static FN_GetProcessIdOfThread *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProcessIdOfThread", &g_Kernel32);
+    return pfn( Thread );
+}
+
+typedef DWORD WINAPI FN_GetThreadId( HANDLE Thread );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetThreadId( HANDLE Thread )
+{
+    static FN_GetThreadId *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetThreadId", &g_Kernel32);
+    return pfn( Thread );
+}
+
+typedef DWORD WINAPI FN_GetProcessId( HANDLE Process );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetProcessId( HANDLE Process )
+{
+    static FN_GetProcessId *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProcessId", &g_Kernel32);
+    return pfn( Process );
+}
+
+typedef DWORD WINAPI FN_GetCurrentProcessorNumber( VOID );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetCurrentProcessorNumber( VOID )
+{
+    static FN_GetCurrentProcessorNumber *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCurrentProcessorNumber", &g_Kernel32);
+    return pfn ();
+}
+
+typedef DWORD_PTR WINAPI FN_SetThreadAffinityMask( HANDLE hThread, DWORD_PTR dwThreadAffinityMask );
+__declspec(dllexport) DWORD_PTR WINAPI kPrf2Wrap_SetThreadAffinityMask( HANDLE hThread, DWORD_PTR dwThreadAffinityMask )
+{
+    static FN_SetThreadAffinityMask *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetThreadAffinityMask", &g_Kernel32);
+    return pfn( hThread, dwThreadAffinityMask );
+}
+
+typedef DWORD WINAPI FN_SetThreadIdealProcessor( HANDLE hThread, DWORD dwIdealProcessor );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_SetThreadIdealProcessor( HANDLE hThread, DWORD dwIdealProcessor )
+{
+    static FN_SetThreadIdealProcessor *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetThreadIdealProcessor", &g_Kernel32);
+    return pfn( hThread, dwIdealProcessor );
+}
+
+typedef BOOL WINAPI FN_SetProcessPriorityBoost( HANDLE hProcess, BOOL bDisablePriorityBoost );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetProcessPriorityBoost( HANDLE hProcess, BOOL bDisablePriorityBoost )
+{
+    static FN_SetProcessPriorityBoost *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetProcessPriorityBoost", &g_Kernel32);
+    return pfn( hProcess, bDisablePriorityBoost );
+}
+
+typedef BOOL WINAPI FN_GetProcessPriorityBoost( HANDLE hProcess, PBOOL pDisablePriorityBoost );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetProcessPriorityBoost( HANDLE hProcess, PBOOL pDisablePriorityBoost )
+{
+    static FN_GetProcessPriorityBoost *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProcessPriorityBoost", &g_Kernel32);
+    return pfn( hProcess, pDisablePriorityBoost );
+}
+
+typedef BOOL WINAPI FN_RequestWakeupLatency( LATENCY_TIME latency );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_RequestWakeupLatency( LATENCY_TIME latency )
+{
+    static FN_RequestWakeupLatency *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RequestWakeupLatency", &g_Kernel32);
+    return pfn( latency );
+}
+
+typedef BOOL WINAPI FN_IsSystemResumeAutomatic( VOID );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsSystemResumeAutomatic( VOID )
+{
+    static FN_IsSystemResumeAutomatic *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsSystemResumeAutomatic", &g_Kernel32);
+    return pfn ();
+}
+
+typedef HANDLE WINAPI FN_OpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId )
+{
+    static FN_OpenThread *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenThread", &g_Kernel32);
+    return pfn( dwDesiredAccess, bInheritHandle, dwThreadId );
+}
+
+typedef BOOL WINAPI FN_SetThreadPriority( HANDLE hThread, int nPriority );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetThreadPriority( HANDLE hThread, int nPriority )
+{
+    static FN_SetThreadPriority *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetThreadPriority", &g_Kernel32);
+    return pfn( hThread, nPriority );
+}
+
+typedef BOOL WINAPI FN_SetThreadPriorityBoost( HANDLE hThread, BOOL bDisablePriorityBoost );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetThreadPriorityBoost( HANDLE hThread, BOOL bDisablePriorityBoost )
+{
+    static FN_SetThreadPriorityBoost *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetThreadPriorityBoost", &g_Kernel32);
+    return pfn( hThread, bDisablePriorityBoost );
+}
+
+typedef BOOL WINAPI FN_GetThreadPriorityBoost( HANDLE hThread, PBOOL pDisablePriorityBoost );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetThreadPriorityBoost( HANDLE hThread, PBOOL pDisablePriorityBoost )
+{
+    static FN_GetThreadPriorityBoost *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetThreadPriorityBoost", &g_Kernel32);
+    return pfn( hThread, pDisablePriorityBoost );
+}
+
+typedef int WINAPI FN_GetThreadPriority( HANDLE hThread );
+__declspec(dllexport) int WINAPI kPrf2Wrap_GetThreadPriority( HANDLE hThread )
+{
+    static FN_GetThreadPriority *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetThreadPriority", &g_Kernel32);
+    return pfn( hThread );
+}
+
+typedef BOOL WINAPI FN_GetThreadTimes( HANDLE hThread, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetThreadTimes( HANDLE hThread, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime )
+{
+    static FN_GetThreadTimes *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetThreadTimes", &g_Kernel32);
+    return pfn( hThread, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime );
+}
+
+typedef BOOL WINAPI FN_GetThreadIOPendingFlag( HANDLE hThread, PBOOL lpIOIsPending );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetThreadIOPendingFlag( HANDLE hThread, PBOOL lpIOIsPending )
+{
+    static FN_GetThreadIOPendingFlag *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetThreadIOPendingFlag", &g_Kernel32);
+    return pfn( hThread, lpIOIsPending );
+}
+
+typedef VOID WINAPI FN_ExitThread( DWORD dwExitCode );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_ExitThread( DWORD dwExitCode )
+{
+    static FN_ExitThread *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ExitThread", &g_Kernel32);
+    pfn( dwExitCode );
+}
+
+typedef BOOL WINAPI FN_TerminateThread( HANDLE hThread, DWORD dwExitCode );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_TerminateThread( HANDLE hThread, DWORD dwExitCode )
+{
+    static FN_TerminateThread *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "TerminateThread", &g_Kernel32);
+    return pfn( hThread, dwExitCode );
+}
+
+typedef BOOL WINAPI FN_GetExitCodeThread( HANDLE hThread, LPDWORD lpExitCode );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetExitCodeThread( HANDLE hThread, LPDWORD lpExitCode )
+{
+    static FN_GetExitCodeThread *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetExitCodeThread", &g_Kernel32);
+    return pfn( hThread, lpExitCode );
+}
+
+typedef BOOL WINAPI FN_GetThreadSelectorEntry( HANDLE hThread, DWORD dwSelector, LPLDT_ENTRY lpSelectorEntry );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetThreadSelectorEntry( HANDLE hThread, DWORD dwSelector, LPLDT_ENTRY lpSelectorEntry )
+{
+    static FN_GetThreadSelectorEntry *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetThreadSelectorEntry", &g_Kernel32);
+    return pfn( hThread, dwSelector, lpSelectorEntry );
+}
+
+typedef EXECUTION_STATE WINAPI FN_SetThreadExecutionState( EXECUTION_STATE esFlags );
+__declspec(dllexport) EXECUTION_STATE WINAPI kPrf2Wrap_SetThreadExecutionState( EXECUTION_STATE esFlags )
+{
+    static FN_SetThreadExecutionState *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetThreadExecutionState", &g_Kernel32);
+    return pfn( esFlags );
+}
+
+typedef DWORD WINAPI FN_GetLastError( VOID );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetLastError( VOID )
+{
+    static FN_GetLastError *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetLastError", &g_Kernel32);
+    return pfn ();
+}
+
+typedef VOID WINAPI FN_SetLastError( DWORD dwErrCode );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_SetLastError( DWORD dwErrCode )
+{
+    static FN_SetLastError *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetLastError", &g_Kernel32);
+    pfn( dwErrCode );
+}
+
+typedef VOID WINAPI FN_RestoreLastError( DWORD dwErrCode );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_RestoreLastError( DWORD dwErrCode )
+{
+    static FN_RestoreLastError *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RestoreLastError", &g_Kernel32);
+    pfn( dwErrCode );
+}
+
+typedef BOOL WINAPI FN_GetOverlappedResult( HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred, BOOL bWait );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetOverlappedResult( HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred, BOOL bWait )
+{
+    static FN_GetOverlappedResult *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetOverlappedResult", &g_Kernel32);
+    return pfn( hFile, lpOverlapped, lpNumberOfBytesTransferred, bWait );
+}
+
+typedef HANDLE WINAPI FN_CreateIoCompletionPort( HANDLE FileHandle, HANDLE ExistingCompletionPort, ULONG_PTR CompletionKey, DWORD NumberOfConcurrentThreads );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateIoCompletionPort( HANDLE FileHandle, HANDLE ExistingCompletionPort, ULONG_PTR CompletionKey, DWORD NumberOfConcurrentThreads )
+{
+    static FN_CreateIoCompletionPort *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateIoCompletionPort", &g_Kernel32);
+    return pfn( FileHandle, ExistingCompletionPort, CompletionKey, NumberOfConcurrentThreads );
+}
+
+typedef BOOL WINAPI FN_GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred, PULONG_PTR lpCompletionKey, LPOVERLAPPED * lpOverlapped, DWORD dwMilliseconds );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred, PULONG_PTR lpCompletionKey, LPOVERLAPPED * lpOverlapped, DWORD dwMilliseconds )
+{
+    static FN_GetQueuedCompletionStatus *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetQueuedCompletionStatus", &g_Kernel32);
+    return pfn( CompletionPort, lpNumberOfBytesTransferred, lpCompletionKey, lpOverlapped, dwMilliseconds );
+}
+
+typedef BOOL WINAPI FN_PostQueuedCompletionStatus( HANDLE CompletionPort, DWORD dwNumberOfBytesTransferred, ULONG_PTR dwCompletionKey, LPOVERLAPPED lpOverlapped );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_PostQueuedCompletionStatus( HANDLE CompletionPort, DWORD dwNumberOfBytesTransferred, ULONG_PTR dwCompletionKey, LPOVERLAPPED lpOverlapped )
+{
+    static FN_PostQueuedCompletionStatus *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "PostQueuedCompletionStatus", &g_Kernel32);
+    return pfn( CompletionPort, dwNumberOfBytesTransferred, dwCompletionKey, lpOverlapped );
+}
+
+typedef UINT WINAPI FN_SetErrorMode( UINT uMode );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_SetErrorMode( UINT uMode )
+{
+    static FN_SetErrorMode *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetErrorMode", &g_Kernel32);
+    return pfn( uMode );
+}
+
+typedef BOOL WINAPI FN_ReadProcessMemory( HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T * lpNumberOfBytesRead );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadProcessMemory( HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T * lpNumberOfBytesRead )
+{
+    static FN_ReadProcessMemory *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadProcessMemory", &g_Kernel32);
+    return pfn( hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead );
+}
+
+typedef BOOL WINAPI FN_WriteProcessMemory( HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T * lpNumberOfBytesWritten );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteProcessMemory( HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T * lpNumberOfBytesWritten )
+{
+    static FN_WriteProcessMemory *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteProcessMemory", &g_Kernel32);
+    return pfn( hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten );
+}
+
+typedef BOOL WINAPI FN_GetThreadContext( HANDLE hThread, LPCONTEXT lpContext );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetThreadContext( HANDLE hThread, LPCONTEXT lpContext )
+{
+    static FN_GetThreadContext *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetThreadContext", &g_Kernel32);
+    return pfn( hThread, lpContext );
+}
+
+typedef BOOL WINAPI FN_SetThreadContext( HANDLE hThread, CONST CONTEXT * lpContext );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetThreadContext( HANDLE hThread, CONST CONTEXT * lpContext )
+{
+    static FN_SetThreadContext *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetThreadContext", &g_Kernel32);
+    return pfn( hThread, lpContext );
+}
+
+typedef DWORD WINAPI FN_SuspendThread( HANDLE hThread );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_SuspendThread( HANDLE hThread )
+{
+    static FN_SuspendThread *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SuspendThread", &g_Kernel32);
+    return pfn( hThread );
+}
+
+typedef DWORD WINAPI FN_ResumeThread( HANDLE hThread );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_ResumeThread( HANDLE hThread )
+{
+    static FN_ResumeThread *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ResumeThread", &g_Kernel32);
+    return pfn( hThread );
+}
+
+typedef DWORD WINAPI FN_QueueUserAPC( PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_QueueUserAPC( PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData )
+{
+    static FN_QueueUserAPC *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "QueueUserAPC", &g_Kernel32);
+    return pfn( pfnAPC, hThread, dwData );
+}
+
+typedef BOOL WINAPI FN_IsDebuggerPresent( VOID );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsDebuggerPresent( VOID )
+{
+    static FN_IsDebuggerPresent *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsDebuggerPresent", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL WINAPI FN_CheckRemoteDebuggerPresent( HANDLE hProcess, PBOOL pbDebuggerPresent );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CheckRemoteDebuggerPresent( HANDLE hProcess, PBOOL pbDebuggerPresent )
+{
+    static FN_CheckRemoteDebuggerPresent *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CheckRemoteDebuggerPresent", &g_Kernel32);
+    return pfn( hProcess, pbDebuggerPresent );
+}
+
+typedef VOID WINAPI FN_DebugBreak( VOID );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_DebugBreak( VOID )
+{
+    static FN_DebugBreak *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DebugBreak", &g_Kernel32);
+    pfn ();
+}
+
+typedef BOOL WINAPI FN_WaitForDebugEvent( LPDEBUG_EVENT lpDebugEvent, DWORD dwMilliseconds );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WaitForDebugEvent( LPDEBUG_EVENT lpDebugEvent, DWORD dwMilliseconds )
+{
+    static FN_WaitForDebugEvent *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WaitForDebugEvent", &g_Kernel32);
+    return pfn( lpDebugEvent, dwMilliseconds );
+}
+
+typedef BOOL WINAPI FN_ContinueDebugEvent( DWORD dwProcessId, DWORD dwThreadId, DWORD dwContinueStatus );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ContinueDebugEvent( DWORD dwProcessId, DWORD dwThreadId, DWORD dwContinueStatus )
+{
+    static FN_ContinueDebugEvent *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ContinueDebugEvent", &g_Kernel32);
+    return pfn( dwProcessId, dwThreadId, dwContinueStatus );
+}
+
+typedef BOOL WINAPI FN_DebugActiveProcess( DWORD dwProcessId );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DebugActiveProcess( DWORD dwProcessId )
+{
+    static FN_DebugActiveProcess *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DebugActiveProcess", &g_Kernel32);
+    return pfn( dwProcessId );
+}
+
+typedef BOOL WINAPI FN_DebugActiveProcessStop( DWORD dwProcessId );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DebugActiveProcessStop( DWORD dwProcessId )
+{
+    static FN_DebugActiveProcessStop *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DebugActiveProcessStop", &g_Kernel32);
+    return pfn( dwProcessId );
+}
+
+typedef BOOL WINAPI FN_DebugSetProcessKillOnExit( BOOL KillOnExit );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DebugSetProcessKillOnExit( BOOL KillOnExit )
+{
+    static FN_DebugSetProcessKillOnExit *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DebugSetProcessKillOnExit", &g_Kernel32);
+    return pfn( KillOnExit );
+}
+
+typedef BOOL WINAPI FN_DebugBreakProcess( HANDLE Process );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DebugBreakProcess( HANDLE Process )
+{
+    static FN_DebugBreakProcess *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DebugBreakProcess", &g_Kernel32);
+    return pfn( Process );
+}
+
+typedef VOID WINAPI FN_InitializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_InitializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
+{
+    static FN_InitializeCriticalSection *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InitializeCriticalSection", &g_Kernel32);
+    pfn( lpCriticalSection );
+}
+
+typedef VOID WINAPI FN_EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
+{
+    static FN_EnterCriticalSection *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnterCriticalSection", &g_Kernel32);
+    pfn( lpCriticalSection );
+}
+
+typedef VOID WINAPI FN_LeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_LeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
+{
+    static FN_LeaveCriticalSection *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LeaveCriticalSection", &g_Kernel32);
+    pfn( lpCriticalSection );
+}
+
+typedef BOOL WINAPI FN_InitializeCriticalSectionAndSpinCount( LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_InitializeCriticalSectionAndSpinCount( LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount )
+{
+    static FN_InitializeCriticalSectionAndSpinCount *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InitializeCriticalSectionAndSpinCount", &g_Kernel32);
+    return pfn( lpCriticalSection, dwSpinCount );
+}
+
+typedef DWORD WINAPI FN_SetCriticalSectionSpinCount( LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_SetCriticalSectionSpinCount( LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount )
+{
+    static FN_SetCriticalSectionSpinCount *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetCriticalSectionSpinCount", &g_Kernel32);
+    return pfn( lpCriticalSection, dwSpinCount );
+}
+
+typedef BOOL WINAPI FN_TryEnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_TryEnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
+{
+    static FN_TryEnterCriticalSection *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "TryEnterCriticalSection", &g_Kernel32);
+    return pfn( lpCriticalSection );
+}
+
+typedef VOID WINAPI FN_DeleteCriticalSection( LPCRITICAL_SECTION lpCriticalSection );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_DeleteCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
+{
+    static FN_DeleteCriticalSection *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DeleteCriticalSection", &g_Kernel32);
+    pfn( lpCriticalSection );
+}
+
+typedef BOOL WINAPI FN_SetEvent( HANDLE hEvent );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetEvent( HANDLE hEvent )
+{
+    static FN_SetEvent *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetEvent", &g_Kernel32);
+    return pfn( hEvent );
+}
+
+typedef BOOL WINAPI FN_ResetEvent( HANDLE hEvent );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ResetEvent( HANDLE hEvent )
+{
+    static FN_ResetEvent *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ResetEvent", &g_Kernel32);
+    return pfn( hEvent );
+}
+
+typedef BOOL WINAPI FN_PulseEvent( HANDLE hEvent );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_PulseEvent( HANDLE hEvent )
+{
+    static FN_PulseEvent *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "PulseEvent", &g_Kernel32);
+    return pfn( hEvent );
+}
+
+typedef BOOL WINAPI FN_ReleaseSemaphore( HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReleaseSemaphore( HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount )
+{
+    static FN_ReleaseSemaphore *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReleaseSemaphore", &g_Kernel32);
+    return pfn( hSemaphore, lReleaseCount, lpPreviousCount );
+}
+
+typedef BOOL WINAPI FN_ReleaseMutex( HANDLE hMutex );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReleaseMutex( HANDLE hMutex )
+{
+    static FN_ReleaseMutex *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReleaseMutex", &g_Kernel32);
+    return pfn( hMutex );
+}
+
+typedef DWORD WINAPI FN_WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds )
+{
+    static FN_WaitForSingleObject *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WaitForSingleObject", &g_Kernel32);
+    return pfn( hHandle, dwMilliseconds );
+}
+
+typedef DWORD WINAPI FN_WaitForMultipleObjects( DWORD nCount, CONST HANDLE * lpHandles, BOOL bWaitAll, DWORD dwMilliseconds );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_WaitForMultipleObjects( DWORD nCount, CONST HANDLE * lpHandles, BOOL bWaitAll, DWORD dwMilliseconds )
+{
+    static FN_WaitForMultipleObjects *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WaitForMultipleObjects", &g_Kernel32);
+    return pfn( nCount, lpHandles, bWaitAll, dwMilliseconds );
+}
+
+typedef VOID WINAPI FN_Sleep( DWORD dwMilliseconds );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_Sleep( DWORD dwMilliseconds )
+{
+    static FN_Sleep *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Sleep", &g_Kernel32);
+    pfn( dwMilliseconds );
+}
+
+typedef HGLOBAL WINAPI FN_LoadResource( HMODULE hModule, HRSRC hResInfo );
+__declspec(dllexport) HGLOBAL WINAPI kPrf2Wrap_LoadResource( HMODULE hModule, HRSRC hResInfo )
+{
+    static FN_LoadResource *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LoadResource", &g_Kernel32);
+    return pfn( hModule, hResInfo );
+}
+
+typedef DWORD WINAPI FN_SizeofResource( HMODULE hModule, HRSRC hResInfo );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_SizeofResource( HMODULE hModule, HRSRC hResInfo )
+{
+    static FN_SizeofResource *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SizeofResource", &g_Kernel32);
+    return pfn( hModule, hResInfo );
+}
+
+typedef ATOM WINAPI FN_GlobalDeleteAtom( ATOM nAtom );
+__declspec(dllexport) ATOM WINAPI kPrf2Wrap_GlobalDeleteAtom( ATOM nAtom )
+{
+    static FN_GlobalDeleteAtom *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalDeleteAtom", &g_Kernel32);
+    return pfn( nAtom );
+}
+
+typedef BOOL WINAPI FN_InitAtomTable( DWORD nSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_InitAtomTable( DWORD nSize )
+{
+    static FN_InitAtomTable *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InitAtomTable", &g_Kernel32);
+    return pfn( nSize );
+}
+
+typedef ATOM WINAPI FN_DeleteAtom( ATOM nAtom );
+__declspec(dllexport) ATOM WINAPI kPrf2Wrap_DeleteAtom( ATOM nAtom )
+{
+    static FN_DeleteAtom *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DeleteAtom", &g_Kernel32);
+    return pfn( nAtom );
+}
+
+typedef UINT WINAPI FN_SetHandleCount( UINT uNumber );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_SetHandleCount( UINT uNumber )
+{
+    static FN_SetHandleCount *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetHandleCount", &g_Kernel32);
+    return pfn( uNumber );
+}
+
+typedef DWORD WINAPI FN_GetLogicalDrives( VOID );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetLogicalDrives( VOID )
+{
+    static FN_GetLogicalDrives *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetLogicalDrives", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL WINAPI FN_LockFile( HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LockFile( HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh )
+{
+    static FN_LockFile *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LockFile", &g_Kernel32);
+    return pfn( hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh );
+}
+
+typedef BOOL WINAPI FN_UnlockFile( HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_UnlockFile( HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh )
+{
+    static FN_UnlockFile *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "UnlockFile", &g_Kernel32);
+    return pfn( hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh );
+}
+
+typedef BOOL WINAPI FN_LockFileEx( HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LockFileEx( HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped )
+{
+    static FN_LockFileEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LockFileEx", &g_Kernel32);
+    return pfn( hFile, dwFlags, dwReserved, nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh, lpOverlapped );
+}
+
+typedef BOOL WINAPI FN_UnlockFileEx( HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_UnlockFileEx( HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped )
+{
+    static FN_UnlockFileEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "UnlockFileEx", &g_Kernel32);
+    return pfn( hFile, dwReserved, nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh, lpOverlapped );
+}
+
+typedef BOOL WINAPI FN_GetFileInformationByHandle( HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetFileInformationByHandle( HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation )
+{
+    static FN_GetFileInformationByHandle *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFileInformationByHandle", &g_Kernel32);
+    return pfn( hFile, lpFileInformation );
+}
+
+typedef DWORD WINAPI FN_GetFileType( HANDLE hFile );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetFileType( HANDLE hFile )
+{
+    static FN_GetFileType *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFileType", &g_Kernel32);
+    return pfn( hFile );
+}
+
+typedef DWORD WINAPI FN_GetFileSize( HANDLE hFile, LPDWORD lpFileSizeHigh );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetFileSize( HANDLE hFile, LPDWORD lpFileSizeHigh )
+{
+    static FN_GetFileSize *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFileSize", &g_Kernel32);
+    return pfn( hFile, lpFileSizeHigh );
+}
+
+typedef BOOL WINAPI FN_GetFileSizeEx( HANDLE hFile, PLARGE_INTEGER lpFileSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetFileSizeEx( HANDLE hFile, PLARGE_INTEGER lpFileSize )
+{
+    static FN_GetFileSizeEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFileSizeEx", &g_Kernel32);
+    return pfn( hFile, lpFileSize );
+}
+
+typedef HANDLE WINAPI FN_GetStdHandle( DWORD nStdHandle );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_GetStdHandle( DWORD nStdHandle )
+{
+    static FN_GetStdHandle *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetStdHandle", &g_Kernel32);
+    return pfn( nStdHandle );
+}
+
+typedef BOOL WINAPI FN_SetStdHandle( DWORD nStdHandle, HANDLE hHandle );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetStdHandle( DWORD nStdHandle, HANDLE hHandle )
+{
+    static FN_SetStdHandle *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetStdHandle", &g_Kernel32);
+    return pfn( nStdHandle, hHandle );
+}
+
+typedef BOOL WINAPI FN_WriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped )
+{
+    static FN_WriteFile *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteFile", &g_Kernel32);
+    return pfn( hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped );
+}
+
+typedef BOOL WINAPI FN_ReadFile( HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadFile( HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped )
+{
+    static FN_ReadFile *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadFile", &g_Kernel32);
+    return pfn( hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped );
+}
+
+typedef BOOL WINAPI FN_FlushFileBuffers( HANDLE hFile );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FlushFileBuffers( HANDLE hFile )
+{
+    static FN_FlushFileBuffers *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FlushFileBuffers", &g_Kernel32);
+    return pfn( hFile );
+}
+
+typedef BOOL WINAPI FN_DeviceIoControl( HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DeviceIoControl( HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped )
+{
+    static FN_DeviceIoControl *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DeviceIoControl", &g_Kernel32);
+    return pfn( hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped );
+}
+
+typedef BOOL WINAPI FN_RequestDeviceWakeup( HANDLE hDevice );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_RequestDeviceWakeup( HANDLE hDevice )
+{
+    static FN_RequestDeviceWakeup *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RequestDeviceWakeup", &g_Kernel32);
+    return pfn( hDevice );
+}
+
+typedef BOOL WINAPI FN_CancelDeviceWakeupRequest( HANDLE hDevice );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CancelDeviceWakeupRequest( HANDLE hDevice )
+{
+    static FN_CancelDeviceWakeupRequest *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CancelDeviceWakeupRequest", &g_Kernel32);
+    return pfn( hDevice );
+}
+
+typedef BOOL WINAPI FN_GetDevicePowerState( HANDLE hDevice, BOOL * pfOn );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetDevicePowerState( HANDLE hDevice, BOOL * pfOn )
+{
+    static FN_GetDevicePowerState *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetDevicePowerState", &g_Kernel32);
+    return pfn( hDevice, pfOn );
+}
+
+typedef BOOL WINAPI FN_SetMessageWaitingIndicator( HANDLE hMsgIndicator, ULONG ulMsgCount );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetMessageWaitingIndicator( HANDLE hMsgIndicator, ULONG ulMsgCount )
+{
+    static FN_SetMessageWaitingIndicator *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetMessageWaitingIndicator", &g_Kernel32);
+    return pfn( hMsgIndicator, ulMsgCount );
+}
+
+typedef BOOL WINAPI FN_SetEndOfFile( HANDLE hFile );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetEndOfFile( HANDLE hFile )
+{
+    static FN_SetEndOfFile *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetEndOfFile", &g_Kernel32);
+    return pfn( hFile );
+}
+
+typedef DWORD WINAPI FN_SetFilePointer( HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_SetFilePointer( HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod )
+{
+    static FN_SetFilePointer *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetFilePointer", &g_Kernel32);
+    return pfn( hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod );
+}
+
+typedef BOOL WINAPI FN_SetFilePointerEx( HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetFilePointerEx( HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod )
+{
+    static FN_SetFilePointerEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetFilePointerEx", &g_Kernel32);
+    return pfn( hFile, liDistanceToMove, lpNewFilePointer, dwMoveMethod );
+}
+
+typedef BOOL WINAPI FN_FindClose( HANDLE hFindFile );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindClose( HANDLE hFindFile )
+{
+    static FN_FindClose *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindClose", &g_Kernel32);
+    return pfn( hFindFile );
+}
+
+typedef BOOL WINAPI FN_GetFileTime( HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime, LPFILETIME lpLastWriteTime );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetFileTime( HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime, LPFILETIME lpLastWriteTime )
+{
+    static FN_GetFileTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFileTime", &g_Kernel32);
+    return pfn( hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime );
+}
+
+typedef BOOL WINAPI FN_SetFileTime( HANDLE hFile, CONST FILETIME * lpCreationTime, CONST FILETIME * lpLastAccessTime, CONST FILETIME * lpLastWriteTime );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetFileTime( HANDLE hFile, CONST FILETIME * lpCreationTime, CONST FILETIME * lpLastAccessTime, CONST FILETIME * lpLastWriteTime )
+{
+    static FN_SetFileTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetFileTime", &g_Kernel32);
+    return pfn( hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime );
+}
+
+typedef BOOL WINAPI FN_SetFileValidData( HANDLE hFile, LONGLONG ValidDataLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetFileValidData( HANDLE hFile, LONGLONG ValidDataLength )
+{
+    static FN_SetFileValidData *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetFileValidData", &g_Kernel32);
+    return pfn( hFile, ValidDataLength );
+}
+
+typedef BOOL WINAPI FN_SetFileShortNameA( HANDLE hFile, LPCSTR lpShortName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetFileShortNameA( HANDLE hFile, LPCSTR lpShortName )
+{
+    static FN_SetFileShortNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetFileShortNameA", &g_Kernel32);
+    return pfn( hFile, lpShortName );
+}
+
+typedef BOOL WINAPI FN_SetFileShortNameW( HANDLE hFile, LPCWSTR lpShortName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetFileShortNameW( HANDLE hFile, LPCWSTR lpShortName )
+{
+    static FN_SetFileShortNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetFileShortNameW", &g_Kernel32);
+    return pfn( hFile, lpShortName );
+}
+
+typedef BOOL WINAPI FN_CloseHandle( HANDLE hObject );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CloseHandle( HANDLE hObject )
+{
+    static FN_CloseHandle *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CloseHandle", &g_Kernel32);
+    return pfn( hObject );
+}
+
+typedef BOOL WINAPI FN_DuplicateHandle( HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DuplicateHandle( HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions )
+{
+    static FN_DuplicateHandle *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DuplicateHandle", &g_Kernel32);
+    return pfn( hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions );
+}
+
+typedef BOOL WINAPI FN_GetHandleInformation( HANDLE hObject, LPDWORD lpdwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetHandleInformation( HANDLE hObject, LPDWORD lpdwFlags )
+{
+    static FN_GetHandleInformation *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetHandleInformation", &g_Kernel32);
+    return pfn( hObject, lpdwFlags );
+}
+
+typedef BOOL WINAPI FN_SetHandleInformation( HANDLE hObject, DWORD dwMask, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetHandleInformation( HANDLE hObject, DWORD dwMask, DWORD dwFlags )
+{
+    static FN_SetHandleInformation *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetHandleInformation", &g_Kernel32);
+    return pfn( hObject, dwMask, dwFlags );
+}
+
+typedef DWORD WINAPI FN_LoadModule( LPCSTR lpModuleName, LPVOID lpParameterBlock );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_LoadModule( LPCSTR lpModuleName, LPVOID lpParameterBlock )
+{
+    static FN_LoadModule *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LoadModule", &g_Kernel32);
+    return pfn( lpModuleName, lpParameterBlock );
+}
+
+typedef UINT WINAPI FN_WinExec( LPCSTR lpCmdLine, UINT uCmdShow );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_WinExec( LPCSTR lpCmdLine, UINT uCmdShow )
+{
+    static FN_WinExec *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WinExec", &g_Kernel32);
+    return pfn( lpCmdLine, uCmdShow );
+}
+
+typedef BOOL WINAPI FN_ClearCommBreak( HANDLE hFile );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ClearCommBreak( HANDLE hFile )
+{
+    static FN_ClearCommBreak *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ClearCommBreak", &g_Kernel32);
+    return pfn( hFile );
+}
+
+typedef BOOL WINAPI FN_ClearCommError( HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ClearCommError( HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat )
+{
+    static FN_ClearCommError *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ClearCommError", &g_Kernel32);
+    return pfn( hFile, lpErrors, lpStat );
+}
+
+typedef BOOL WINAPI FN_SetupComm( HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetupComm( HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue )
+{
+    static FN_SetupComm *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetupComm", &g_Kernel32);
+    return pfn( hFile, dwInQueue, dwOutQueue );
+}
+
+typedef BOOL WINAPI FN_EscapeCommFunction( HANDLE hFile, DWORD dwFunc );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EscapeCommFunction( HANDLE hFile, DWORD dwFunc )
+{
+    static FN_EscapeCommFunction *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EscapeCommFunction", &g_Kernel32);
+    return pfn( hFile, dwFunc );
+}
+
+typedef BOOL WINAPI FN_GetCommConfig( HANDLE hCommDev, LPCOMMCONFIG lpCC, LPDWORD lpdwSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetCommConfig( HANDLE hCommDev, LPCOMMCONFIG lpCC, LPDWORD lpdwSize )
+{
+    static FN_GetCommConfig *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCommConfig", &g_Kernel32);
+    return pfn( hCommDev, lpCC, lpdwSize );
+}
+
+typedef BOOL WINAPI FN_GetCommMask( HANDLE hFile, LPDWORD lpEvtMask );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetCommMask( HANDLE hFile, LPDWORD lpEvtMask )
+{
+    static FN_GetCommMask *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCommMask", &g_Kernel32);
+    return pfn( hFile, lpEvtMask );
+}
+
+typedef BOOL WINAPI FN_GetCommProperties( HANDLE hFile, LPCOMMPROP lpCommProp );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetCommProperties( HANDLE hFile, LPCOMMPROP lpCommProp )
+{
+    static FN_GetCommProperties *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCommProperties", &g_Kernel32);
+    return pfn( hFile, lpCommProp );
+}
+
+typedef BOOL WINAPI FN_GetCommModemStatus( HANDLE hFile, LPDWORD lpModemStat );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetCommModemStatus( HANDLE hFile, LPDWORD lpModemStat )
+{
+    static FN_GetCommModemStatus *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCommModemStatus", &g_Kernel32);
+    return pfn( hFile, lpModemStat );
+}
+
+typedef BOOL WINAPI FN_GetCommState( HANDLE hFile, LPDCB lpDCB );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetCommState( HANDLE hFile, LPDCB lpDCB )
+{
+    static FN_GetCommState *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCommState", &g_Kernel32);
+    return pfn( hFile, lpDCB );
+}
+
+typedef BOOL WINAPI FN_GetCommTimeouts( HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetCommTimeouts( HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts )
+{
+    static FN_GetCommTimeouts *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCommTimeouts", &g_Kernel32);
+    return pfn( hFile, lpCommTimeouts );
+}
+
+typedef BOOL WINAPI FN_PurgeComm( HANDLE hFile, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_PurgeComm( HANDLE hFile, DWORD dwFlags )
+{
+    static FN_PurgeComm *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "PurgeComm", &g_Kernel32);
+    return pfn( hFile, dwFlags );
+}
+
+typedef BOOL WINAPI FN_SetCommBreak( HANDLE hFile );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetCommBreak( HANDLE hFile )
+{
+    static FN_SetCommBreak *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetCommBreak", &g_Kernel32);
+    return pfn( hFile );
+}
+
+typedef BOOL WINAPI FN_SetCommConfig( HANDLE hCommDev, LPCOMMCONFIG lpCC, DWORD dwSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetCommConfig( HANDLE hCommDev, LPCOMMCONFIG lpCC, DWORD dwSize )
+{
+    static FN_SetCommConfig *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetCommConfig", &g_Kernel32);
+    return pfn( hCommDev, lpCC, dwSize );
+}
+
+typedef BOOL WINAPI FN_SetCommMask( HANDLE hFile, DWORD dwEvtMask );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetCommMask( HANDLE hFile, DWORD dwEvtMask )
+{
+    static FN_SetCommMask *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetCommMask", &g_Kernel32);
+    return pfn( hFile, dwEvtMask );
+}
+
+typedef BOOL WINAPI FN_SetCommState( HANDLE hFile, LPDCB lpDCB );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetCommState( HANDLE hFile, LPDCB lpDCB )
+{
+    static FN_SetCommState *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetCommState", &g_Kernel32);
+    return pfn( hFile, lpDCB );
+}
+
+typedef BOOL WINAPI FN_SetCommTimeouts( HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetCommTimeouts( HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts )
+{
+    static FN_SetCommTimeouts *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetCommTimeouts", &g_Kernel32);
+    return pfn( hFile, lpCommTimeouts );
+}
+
+typedef BOOL WINAPI FN_TransmitCommChar( HANDLE hFile, char cChar );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_TransmitCommChar( HANDLE hFile, char cChar )
+{
+    static FN_TransmitCommChar *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "TransmitCommChar", &g_Kernel32);
+    return pfn( hFile, cChar );
+}
+
+typedef BOOL WINAPI FN_WaitCommEvent( HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WaitCommEvent( HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped )
+{
+    static FN_WaitCommEvent *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WaitCommEvent", &g_Kernel32);
+    return pfn( hFile, lpEvtMask, lpOverlapped );
+}
+
+typedef DWORD WINAPI FN_SetTapePosition( HANDLE hDevice, DWORD dwPositionMethod, DWORD dwPartition, DWORD dwOffsetLow, DWORD dwOffsetHigh, BOOL bImmediate );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_SetTapePosition( HANDLE hDevice, DWORD dwPositionMethod, DWORD dwPartition, DWORD dwOffsetLow, DWORD dwOffsetHigh, BOOL bImmediate )
+{
+    static FN_SetTapePosition *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetTapePosition", &g_Kernel32);
+    return pfn( hDevice, dwPositionMethod, dwPartition, dwOffsetLow, dwOffsetHigh, bImmediate );
+}
+
+typedef DWORD WINAPI FN_GetTapePosition( HANDLE hDevice, DWORD dwPositionType, LPDWORD lpdwPartition, LPDWORD lpdwOffsetLow, LPDWORD lpdwOffsetHigh );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetTapePosition( HANDLE hDevice, DWORD dwPositionType, LPDWORD lpdwPartition, LPDWORD lpdwOffsetLow, LPDWORD lpdwOffsetHigh )
+{
+    static FN_GetTapePosition *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetTapePosition", &g_Kernel32);
+    return pfn( hDevice, dwPositionType, lpdwPartition, lpdwOffsetLow, lpdwOffsetHigh );
+}
+
+typedef DWORD WINAPI FN_PrepareTape( HANDLE hDevice, DWORD dwOperation, BOOL bImmediate );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_PrepareTape( HANDLE hDevice, DWORD dwOperation, BOOL bImmediate )
+{
+    static FN_PrepareTape *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "PrepareTape", &g_Kernel32);
+    return pfn( hDevice, dwOperation, bImmediate );
+}
+
+typedef DWORD WINAPI FN_EraseTape( HANDLE hDevice, DWORD dwEraseType, BOOL bImmediate );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_EraseTape( HANDLE hDevice, DWORD dwEraseType, BOOL bImmediate )
+{
+    static FN_EraseTape *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EraseTape", &g_Kernel32);
+    return pfn( hDevice, dwEraseType, bImmediate );
+}
+
+typedef DWORD WINAPI FN_CreateTapePartition( HANDLE hDevice, DWORD dwPartitionMethod, DWORD dwCount, DWORD dwSize );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_CreateTapePartition( HANDLE hDevice, DWORD dwPartitionMethod, DWORD dwCount, DWORD dwSize )
+{
+    static FN_CreateTapePartition *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateTapePartition", &g_Kernel32);
+    return pfn( hDevice, dwPartitionMethod, dwCount, dwSize );
+}
+
+typedef DWORD WINAPI FN_WriteTapemark( HANDLE hDevice, DWORD dwTapemarkType, DWORD dwTapemarkCount, BOOL bImmediate );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_WriteTapemark( HANDLE hDevice, DWORD dwTapemarkType, DWORD dwTapemarkCount, BOOL bImmediate )
+{
+    static FN_WriteTapemark *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteTapemark", &g_Kernel32);
+    return pfn( hDevice, dwTapemarkType, dwTapemarkCount, bImmediate );
+}
+
+typedef DWORD WINAPI FN_GetTapeStatus( HANDLE hDevice );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetTapeStatus( HANDLE hDevice )
+{
+    static FN_GetTapeStatus *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetTapeStatus", &g_Kernel32);
+    return pfn( hDevice );
+}
+
+typedef DWORD WINAPI FN_GetTapeParameters( HANDLE hDevice, DWORD dwOperation, LPDWORD lpdwSize, LPVOID lpTapeInformation );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetTapeParameters( HANDLE hDevice, DWORD dwOperation, LPDWORD lpdwSize, LPVOID lpTapeInformation )
+{
+    static FN_GetTapeParameters *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetTapeParameters", &g_Kernel32);
+    return pfn( hDevice, dwOperation, lpdwSize, lpTapeInformation );
+}
+
+typedef DWORD WINAPI FN_SetTapeParameters( HANDLE hDevice, DWORD dwOperation, LPVOID lpTapeInformation );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_SetTapeParameters( HANDLE hDevice, DWORD dwOperation, LPVOID lpTapeInformation )
+{
+    static FN_SetTapeParameters *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetTapeParameters", &g_Kernel32);
+    return pfn( hDevice, dwOperation, lpTapeInformation );
+}
+
+typedef BOOL WINAPI FN_Beep( DWORD dwFreq, DWORD dwDuration );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Beep( DWORD dwFreq, DWORD dwDuration )
+{
+    static FN_Beep *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Beep", &g_Kernel32);
+    return pfn( dwFreq, dwDuration );
+}
+
+typedef int WINAPI FN_MulDiv( int nNumber, int nNumerator, int nDenominator );
+__declspec(dllexport) int WINAPI kPrf2Wrap_MulDiv( int nNumber, int nNumerator, int nDenominator )
+{
+    static FN_MulDiv *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MulDiv", &g_Kernel32);
+    return pfn( nNumber, nNumerator, nDenominator );
+}
+
+typedef VOID WINAPI FN_GetSystemTime( LPSYSTEMTIME lpSystemTime );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_GetSystemTime( LPSYSTEMTIME lpSystemTime )
+{
+    static FN_GetSystemTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemTime", &g_Kernel32);
+    pfn( lpSystemTime );
+}
+
+typedef VOID WINAPI FN_GetSystemTimeAsFileTime( LPFILETIME lpSystemTimeAsFileTime );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_GetSystemTimeAsFileTime( LPFILETIME lpSystemTimeAsFileTime )
+{
+    static FN_GetSystemTimeAsFileTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemTimeAsFileTime", &g_Kernel32);
+    pfn( lpSystemTimeAsFileTime );
+}
+
+typedef BOOL WINAPI FN_SetSystemTime( CONST SYSTEMTIME * lpSystemTime );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetSystemTime( CONST SYSTEMTIME * lpSystemTime )
+{
+    static FN_SetSystemTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetSystemTime", &g_Kernel32);
+    return pfn( lpSystemTime );
+}
+
+typedef VOID WINAPI FN_GetLocalTime( LPSYSTEMTIME lpSystemTime );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_GetLocalTime( LPSYSTEMTIME lpSystemTime )
+{
+    static FN_GetLocalTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetLocalTime", &g_Kernel32);
+    pfn( lpSystemTime );
+}
+
+typedef BOOL WINAPI FN_SetLocalTime( CONST SYSTEMTIME * lpSystemTime );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetLocalTime( CONST SYSTEMTIME * lpSystemTime )
+{
+    static FN_SetLocalTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetLocalTime", &g_Kernel32);
+    return pfn( lpSystemTime );
+}
+
+typedef VOID WINAPI FN_GetSystemInfo( LPSYSTEM_INFO lpSystemInfo );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_GetSystemInfo( LPSYSTEM_INFO lpSystemInfo )
+{
+    static FN_GetSystemInfo *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemInfo", &g_Kernel32);
+    pfn( lpSystemInfo );
+}
+
+typedef BOOL WINAPI FN_SetSystemFileCacheSize( SIZE_T MinimumFileCacheSize, SIZE_T MaximumFileCacheSize, DWORD Flags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetSystemFileCacheSize( SIZE_T MinimumFileCacheSize, SIZE_T MaximumFileCacheSize, DWORD Flags )
+{
+    static FN_SetSystemFileCacheSize *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetSystemFileCacheSize", &g_Kernel32);
+    return pfn( MinimumFileCacheSize, MaximumFileCacheSize, Flags );
+}
+
+typedef BOOL WINAPI FN_GetSystemFileCacheSize( PSIZE_T lpMinimumFileCacheSize, PSIZE_T lpMaximumFileCacheSize, PDWORD lpFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetSystemFileCacheSize( PSIZE_T lpMinimumFileCacheSize, PSIZE_T lpMaximumFileCacheSize, PDWORD lpFlags )
+{
+    static FN_GetSystemFileCacheSize *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemFileCacheSize", &g_Kernel32);
+    return pfn( lpMinimumFileCacheSize, lpMaximumFileCacheSize, lpFlags );
+}
+
+typedef BOOL WINAPI FN_GetSystemRegistryQuota( PDWORD pdwQuotaAllowed, PDWORD pdwQuotaUsed );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetSystemRegistryQuota( PDWORD pdwQuotaAllowed, PDWORD pdwQuotaUsed )
+{
+    static FN_GetSystemRegistryQuota *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemRegistryQuota", &g_Kernel32);
+    return pfn( pdwQuotaAllowed, pdwQuotaUsed );
+}
+
+typedef BOOL WINAPI FN_GetSystemTimes( LPFILETIME lpIdleTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetSystemTimes( LPFILETIME lpIdleTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime )
+{
+    static FN_GetSystemTimes *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemTimes", &g_Kernel32);
+    return pfn( lpIdleTime, lpKernelTime, lpUserTime );
+}
+
+typedef VOID WINAPI FN_GetNativeSystemInfo( LPSYSTEM_INFO lpSystemInfo );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_GetNativeSystemInfo( LPSYSTEM_INFO lpSystemInfo )
+{
+    static FN_GetNativeSystemInfo *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetNativeSystemInfo", &g_Kernel32);
+    pfn( lpSystemInfo );
+}
+
+typedef BOOL WINAPI FN_IsProcessorFeaturePresent( DWORD ProcessorFeature );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsProcessorFeaturePresent( DWORD ProcessorFeature )
+{
+    static FN_IsProcessorFeaturePresent *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsProcessorFeaturePresent", &g_Kernel32);
+    return pfn( ProcessorFeature );
+}
+
+typedef BOOL WINAPI FN_SystemTimeToTzSpecificLocalTime( LPTIME_ZONE_INFORMATION lpTimeZoneInformation, LPSYSTEMTIME lpUniversalTime, LPSYSTEMTIME lpLocalTime );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SystemTimeToTzSpecificLocalTime( LPTIME_ZONE_INFORMATION lpTimeZoneInformation, LPSYSTEMTIME lpUniversalTime, LPSYSTEMTIME lpLocalTime )
+{
+    static FN_SystemTimeToTzSpecificLocalTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SystemTimeToTzSpecificLocalTime", &g_Kernel32);
+    return pfn( lpTimeZoneInformation, lpUniversalTime, lpLocalTime );
+}
+
+typedef BOOL WINAPI FN_TzSpecificLocalTimeToSystemTime( LPTIME_ZONE_INFORMATION lpTimeZoneInformation, LPSYSTEMTIME lpLocalTime, LPSYSTEMTIME lpUniversalTime );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_TzSpecificLocalTimeToSystemTime( LPTIME_ZONE_INFORMATION lpTimeZoneInformation, LPSYSTEMTIME lpLocalTime, LPSYSTEMTIME lpUniversalTime )
+{
+    static FN_TzSpecificLocalTimeToSystemTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "TzSpecificLocalTimeToSystemTime", &g_Kernel32);
+    return pfn( lpTimeZoneInformation, lpLocalTime, lpUniversalTime );
+}
+
+typedef DWORD WINAPI FN_GetTimeZoneInformation( LPTIME_ZONE_INFORMATION lpTimeZoneInformation );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetTimeZoneInformation( LPTIME_ZONE_INFORMATION lpTimeZoneInformation )
+{
+    static FN_GetTimeZoneInformation *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetTimeZoneInformation", &g_Kernel32);
+    return pfn( lpTimeZoneInformation );
+}
+
+typedef BOOL WINAPI FN_SetTimeZoneInformation( CONST TIME_ZONE_INFORMATION * lpTimeZoneInformation );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetTimeZoneInformation( CONST TIME_ZONE_INFORMATION * lpTimeZoneInformation )
+{
+    static FN_SetTimeZoneInformation *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetTimeZoneInformation", &g_Kernel32);
+    return pfn( lpTimeZoneInformation );
+}
+
+typedef BOOL WINAPI FN_SystemTimeToFileTime( CONST SYSTEMTIME * lpSystemTime, LPFILETIME lpFileTime );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SystemTimeToFileTime( CONST SYSTEMTIME * lpSystemTime, LPFILETIME lpFileTime )
+{
+    static FN_SystemTimeToFileTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SystemTimeToFileTime", &g_Kernel32);
+    return pfn( lpSystemTime, lpFileTime );
+}
+
+typedef BOOL WINAPI FN_FileTimeToLocalFileTime( CONST FILETIME * lpFileTime, LPFILETIME lpLocalFileTime );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FileTimeToLocalFileTime( CONST FILETIME * lpFileTime, LPFILETIME lpLocalFileTime )
+{
+    static FN_FileTimeToLocalFileTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FileTimeToLocalFileTime", &g_Kernel32);
+    return pfn( lpFileTime, lpLocalFileTime );
+}
+
+typedef BOOL WINAPI FN_LocalFileTimeToFileTime( CONST FILETIME * lpLocalFileTime, LPFILETIME lpFileTime );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LocalFileTimeToFileTime( CONST FILETIME * lpLocalFileTime, LPFILETIME lpFileTime )
+{
+    static FN_LocalFileTimeToFileTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LocalFileTimeToFileTime", &g_Kernel32);
+    return pfn( lpLocalFileTime, lpFileTime );
+}
+
+typedef BOOL WINAPI FN_FileTimeToSystemTime( CONST FILETIME * lpFileTime, LPSYSTEMTIME lpSystemTime );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FileTimeToSystemTime( CONST FILETIME * lpFileTime, LPSYSTEMTIME lpSystemTime )
+{
+    static FN_FileTimeToSystemTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FileTimeToSystemTime", &g_Kernel32);
+    return pfn( lpFileTime, lpSystemTime );
+}
+
+typedef LONG WINAPI FN_CompareFileTime( CONST FILETIME * lpFileTime1, CONST FILETIME * lpFileTime2 );
+__declspec(dllexport) LONG WINAPI kPrf2Wrap_CompareFileTime( CONST FILETIME * lpFileTime1, CONST FILETIME * lpFileTime2 )
+{
+    static FN_CompareFileTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CompareFileTime", &g_Kernel32);
+    return pfn( lpFileTime1, lpFileTime2 );
+}
+
+typedef BOOL WINAPI FN_FileTimeToDosDateTime( CONST FILETIME * lpFileTime, LPWORD lpFatDate, LPWORD lpFatTime );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FileTimeToDosDateTime( CONST FILETIME * lpFileTime, LPWORD lpFatDate, LPWORD lpFatTime )
+{
+    static FN_FileTimeToDosDateTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FileTimeToDosDateTime", &g_Kernel32);
+    return pfn( lpFileTime, lpFatDate, lpFatTime );
+}
+
+typedef BOOL WINAPI FN_DosDateTimeToFileTime( WORD wFatDate, WORD wFatTime, LPFILETIME lpFileTime );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DosDateTimeToFileTime( WORD wFatDate, WORD wFatTime, LPFILETIME lpFileTime )
+{
+    static FN_DosDateTimeToFileTime *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DosDateTimeToFileTime", &g_Kernel32);
+    return pfn( wFatDate, wFatTime, lpFileTime );
+}
+
+typedef DWORD WINAPI FN_GetTickCount( VOID );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetTickCount( VOID )
+{
+    static FN_GetTickCount *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetTickCount", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL WINAPI FN_SetSystemTimeAdjustment( DWORD dwTimeAdjustment, BOOL bTimeAdjustmentDisabled );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetSystemTimeAdjustment( DWORD dwTimeAdjustment, BOOL bTimeAdjustmentDisabled )
+{
+    static FN_SetSystemTimeAdjustment *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetSystemTimeAdjustment", &g_Kernel32);
+    return pfn( dwTimeAdjustment, bTimeAdjustmentDisabled );
+}
+
+typedef BOOL WINAPI FN_GetSystemTimeAdjustment( PDWORD lpTimeAdjustment, PDWORD lpTimeIncrement, PBOOL lpTimeAdjustmentDisabled );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetSystemTimeAdjustment( PDWORD lpTimeAdjustment, PDWORD lpTimeIncrement, PBOOL lpTimeAdjustmentDisabled )
+{
+    static FN_GetSystemTimeAdjustment *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemTimeAdjustment", &g_Kernel32);
+    return pfn( lpTimeAdjustment, lpTimeIncrement, lpTimeAdjustmentDisabled );
+}
+
+typedef DWORD WINAPI FN_FormatMessageA( DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize, va_list * Arguments );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_FormatMessageA( DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize, va_list * Arguments )
+{
+    static FN_FormatMessageA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FormatMessageA", &g_Kernel32);
+    return pfn( dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments );
+}
+
+typedef DWORD WINAPI FN_FormatMessageW( DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, va_list * Arguments );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_FormatMessageW( DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, va_list * Arguments )
+{
+    static FN_FormatMessageW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FormatMessageW", &g_Kernel32);
+    return pfn( dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments );
+}
+
+typedef BOOL WINAPI FN_CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize )
+{
+    static FN_CreatePipe *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreatePipe", &g_Kernel32);
+    return pfn( hReadPipe, hWritePipe, lpPipeAttributes, nSize );
+}
+
+typedef BOOL WINAPI FN_ConnectNamedPipe( HANDLE hNamedPipe, LPOVERLAPPED lpOverlapped );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ConnectNamedPipe( HANDLE hNamedPipe, LPOVERLAPPED lpOverlapped )
+{
+    static FN_ConnectNamedPipe *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ConnectNamedPipe", &g_Kernel32);
+    return pfn( hNamedPipe, lpOverlapped );
+}
+
+typedef BOOL WINAPI FN_DisconnectNamedPipe( HANDLE hNamedPipe );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DisconnectNamedPipe( HANDLE hNamedPipe )
+{
+    static FN_DisconnectNamedPipe *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DisconnectNamedPipe", &g_Kernel32);
+    return pfn( hNamedPipe );
+}
+
+typedef BOOL WINAPI FN_SetNamedPipeHandleState( HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetNamedPipeHandleState( HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout )
+{
+    static FN_SetNamedPipeHandleState *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetNamedPipeHandleState", &g_Kernel32);
+    return pfn( hNamedPipe, lpMode, lpMaxCollectionCount, lpCollectDataTimeout );
+}
+
+typedef BOOL WINAPI FN_GetNamedPipeInfo( HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutBufferSize, LPDWORD lpInBufferSize, LPDWORD lpMaxInstances );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetNamedPipeInfo( HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutBufferSize, LPDWORD lpInBufferSize, LPDWORD lpMaxInstances )
+{
+    static FN_GetNamedPipeInfo *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetNamedPipeInfo", &g_Kernel32);
+    return pfn( hNamedPipe, lpFlags, lpOutBufferSize, lpInBufferSize, lpMaxInstances );
+}
+
+typedef BOOL WINAPI FN_PeekNamedPipe( HANDLE hNamedPipe, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD lpBytesRead, LPDWORD lpTotalBytesAvail, LPDWORD lpBytesLeftThisMessage );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_PeekNamedPipe( HANDLE hNamedPipe, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD lpBytesRead, LPDWORD lpTotalBytesAvail, LPDWORD lpBytesLeftThisMessage )
+{
+    static FN_PeekNamedPipe *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "PeekNamedPipe", &g_Kernel32);
+    return pfn( hNamedPipe, lpBuffer, nBufferSize, lpBytesRead, lpTotalBytesAvail, lpBytesLeftThisMessage );
+}
+
+typedef BOOL WINAPI FN_TransactNamedPipe( HANDLE hNamedPipe, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_TransactNamedPipe( HANDLE hNamedPipe, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped )
+{
+    static FN_TransactNamedPipe *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "TransactNamedPipe", &g_Kernel32);
+    return pfn( hNamedPipe, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesRead, lpOverlapped );
+}
+
+typedef HANDLE WINAPI FN_CreateMailslotA( LPCSTR lpName, DWORD nMaxMessageSize, DWORD lReadTimeout, LPSECURITY_ATTRIBUTES lpSecurityAttributes );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateMailslotA( LPCSTR lpName, DWORD nMaxMessageSize, DWORD lReadTimeout, LPSECURITY_ATTRIBUTES lpSecurityAttributes )
+{
+    static FN_CreateMailslotA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateMailslotA", &g_Kernel32);
+    return pfn( lpName, nMaxMessageSize, lReadTimeout, lpSecurityAttributes );
+}
+
+typedef HANDLE WINAPI FN_CreateMailslotW( LPCWSTR lpName, DWORD nMaxMessageSize, DWORD lReadTimeout, LPSECURITY_ATTRIBUTES lpSecurityAttributes );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateMailslotW( LPCWSTR lpName, DWORD nMaxMessageSize, DWORD lReadTimeout, LPSECURITY_ATTRIBUTES lpSecurityAttributes )
+{
+    static FN_CreateMailslotW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateMailslotW", &g_Kernel32);
+    return pfn( lpName, nMaxMessageSize, lReadTimeout, lpSecurityAttributes );
+}
+
+typedef BOOL WINAPI FN_GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize, LPDWORD lpNextSize, LPDWORD lpMessageCount, LPDWORD lpReadTimeout );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize, LPDWORD lpNextSize, LPDWORD lpMessageCount, LPDWORD lpReadTimeout )
+{
+    static FN_GetMailslotInfo *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetMailslotInfo", &g_Kernel32);
+    return pfn( hMailslot, lpMaxMessageSize, lpNextSize, lpMessageCount, lpReadTimeout );
+}
+
+typedef BOOL WINAPI FN_SetMailslotInfo( HANDLE hMailslot, DWORD lReadTimeout );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetMailslotInfo( HANDLE hMailslot, DWORD lReadTimeout )
+{
+    static FN_SetMailslotInfo *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetMailslotInfo", &g_Kernel32);
+    return pfn( hMailslot, lReadTimeout );
+}
+
+typedef LPVOID WINAPI FN_MapViewOfFile( HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap );
+__declspec(dllexport) LPVOID WINAPI kPrf2Wrap_MapViewOfFile( HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap )
+{
+    static FN_MapViewOfFile *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MapViewOfFile", &g_Kernel32);
+    return pfn( hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap );
+}
+
+typedef BOOL WINAPI FN_FlushViewOfFile( LPCVOID lpBaseAddress, SIZE_T dwNumberOfBytesToFlush );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FlushViewOfFile( LPCVOID lpBaseAddress, SIZE_T dwNumberOfBytesToFlush )
+{
+    static FN_FlushViewOfFile *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FlushViewOfFile", &g_Kernel32);
+    return pfn( lpBaseAddress, dwNumberOfBytesToFlush );
+}
+
+typedef BOOL WINAPI FN_UnmapViewOfFile( LPCVOID lpBaseAddress );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_UnmapViewOfFile( LPCVOID lpBaseAddress )
+{
+    static FN_UnmapViewOfFile *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "UnmapViewOfFile", &g_Kernel32);
+    return pfn( lpBaseAddress );
+}
+
+typedef BOOL WINAPI FN_EncryptFileA( LPCSTR lpFileName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EncryptFileA( LPCSTR lpFileName )
+{
+    static FN_EncryptFileA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EncryptFileA", &g_Kernel32);
+    return pfn( lpFileName );
+}
+
+typedef BOOL WINAPI FN_EncryptFileW( LPCWSTR lpFileName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EncryptFileW( LPCWSTR lpFileName )
+{
+    static FN_EncryptFileW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EncryptFileW", &g_Kernel32);
+    return pfn( lpFileName );
+}
+
+typedef BOOL WINAPI FN_DecryptFileA( LPCSTR lpFileName, DWORD dwReserved );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DecryptFileA( LPCSTR lpFileName, DWORD dwReserved )
+{
+    static FN_DecryptFileA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DecryptFileA", &g_Kernel32);
+    return pfn( lpFileName, dwReserved );
+}
+
+typedef BOOL WINAPI FN_DecryptFileW( LPCWSTR lpFileName, DWORD dwReserved );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DecryptFileW( LPCWSTR lpFileName, DWORD dwReserved )
+{
+    static FN_DecryptFileW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DecryptFileW", &g_Kernel32);
+    return pfn( lpFileName, dwReserved );
+}
+
+typedef BOOL WINAPI FN_FileEncryptionStatusA( LPCSTR lpFileName, LPDWORD lpStatus );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FileEncryptionStatusA( LPCSTR lpFileName, LPDWORD lpStatus )
+{
+    static FN_FileEncryptionStatusA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FileEncryptionStatusA", &g_Kernel32);
+    return pfn( lpFileName, lpStatus );
+}
+
+typedef BOOL WINAPI FN_FileEncryptionStatusW( LPCWSTR lpFileName, LPDWORD lpStatus );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FileEncryptionStatusW( LPCWSTR lpFileName, LPDWORD lpStatus )
+{
+    static FN_FileEncryptionStatusW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FileEncryptionStatusW", &g_Kernel32);
+    return pfn( lpFileName, lpStatus );
+}
+
+typedef DWORD WINAPI FN_OpenEncryptedFileRawA( LPCSTR lpFileName, ULONG ulFlags, PVOID * pvContext );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_OpenEncryptedFileRawA( LPCSTR lpFileName, ULONG ulFlags, PVOID * pvContext )
+{
+    static FN_OpenEncryptedFileRawA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenEncryptedFileRawA", &g_Kernel32);
+    return pfn( lpFileName, ulFlags, pvContext );
+}
+
+typedef DWORD WINAPI FN_OpenEncryptedFileRawW( LPCWSTR lpFileName, ULONG ulFlags, PVOID * pvContext );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_OpenEncryptedFileRawW( LPCWSTR lpFileName, ULONG ulFlags, PVOID * pvContext )
+{
+    static FN_OpenEncryptedFileRawW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenEncryptedFileRawW", &g_Kernel32);
+    return pfn( lpFileName, ulFlags, pvContext );
+}
+
+typedef DWORD WINAPI FN_ReadEncryptedFileRaw( PFE_EXPORT_FUNC pfExportCallback, PVOID pvCallbackContext, PVOID pvContext );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_ReadEncryptedFileRaw( PFE_EXPORT_FUNC pfExportCallback, PVOID pvCallbackContext, PVOID pvContext )
+{
+    static FN_ReadEncryptedFileRaw *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadEncryptedFileRaw", &g_Kernel32);
+    return pfn( pfExportCallback, pvCallbackContext, pvContext );
+}
+
+typedef DWORD WINAPI FN_WriteEncryptedFileRaw( PFE_IMPORT_FUNC pfImportCallback, PVOID pvCallbackContext, PVOID pvContext );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_WriteEncryptedFileRaw( PFE_IMPORT_FUNC pfImportCallback, PVOID pvCallbackContext, PVOID pvContext )
+{
+    static FN_WriteEncryptedFileRaw *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteEncryptedFileRaw", &g_Kernel32);
+    return pfn( pfImportCallback, pvCallbackContext, pvContext );
+}
+
+typedef VOID WINAPI FN_CloseEncryptedFileRaw( PVOID pvContext );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_CloseEncryptedFileRaw( PVOID pvContext )
+{
+    static FN_CloseEncryptedFileRaw *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CloseEncryptedFileRaw", &g_Kernel32);
+    pfn( pvContext );
+}
+
+typedef int WINAPI FN_lstrcmpA( LPCSTR lpString1, LPCSTR lpString2 );
+__declspec(dllexport) int WINAPI kPrf2Wrap_lstrcmpA( LPCSTR lpString1, LPCSTR lpString2 )
+{
+    static FN_lstrcmpA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrcmpA", &g_Kernel32);
+    return pfn( lpString1, lpString2 );
+}
+
+typedef int WINAPI FN_lstrcmpW( LPCWSTR lpString1, LPCWSTR lpString2 );
+__declspec(dllexport) int WINAPI kPrf2Wrap_lstrcmpW( LPCWSTR lpString1, LPCWSTR lpString2 )
+{
+    static FN_lstrcmpW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrcmpW", &g_Kernel32);
+    return pfn( lpString1, lpString2 );
+}
+
+typedef int WINAPI FN_lstrcmpiA( LPCSTR lpString1, LPCSTR lpString2 );
+__declspec(dllexport) int WINAPI kPrf2Wrap_lstrcmpiA( LPCSTR lpString1, LPCSTR lpString2 )
+{
+    static FN_lstrcmpiA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrcmpiA", &g_Kernel32);
+    return pfn( lpString1, lpString2 );
+}
+
+typedef int WINAPI FN_lstrcmpiW( LPCWSTR lpString1, LPCWSTR lpString2 );
+__declspec(dllexport) int WINAPI kPrf2Wrap_lstrcmpiW( LPCWSTR lpString1, LPCWSTR lpString2 )
+{
+    static FN_lstrcmpiW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrcmpiW", &g_Kernel32);
+    return pfn( lpString1, lpString2 );
+}
+
+typedef LPSTR WINAPI FN_lstrcpynA( LPSTR lpString1, LPCSTR lpString2, int iMaxLength );
+__declspec(dllexport) LPSTR WINAPI kPrf2Wrap_lstrcpynA( LPSTR lpString1, LPCSTR lpString2, int iMaxLength )
+{
+    static FN_lstrcpynA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrcpynA", &g_Kernel32);
+    return pfn( lpString1, lpString2, iMaxLength );
+}
+
+typedef LPWSTR WINAPI FN_lstrcpynW( LPWSTR lpString1, LPCWSTR lpString2, int iMaxLength );
+__declspec(dllexport) LPWSTR WINAPI kPrf2Wrap_lstrcpynW( LPWSTR lpString1, LPCWSTR lpString2, int iMaxLength )
+{
+    static FN_lstrcpynW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrcpynW", &g_Kernel32);
+    return pfn( lpString1, lpString2, iMaxLength );
+}
+
+typedef LPSTR WINAPI FN_lstrcpyA( LPSTR lpString1, LPCSTR lpString2 );
+__declspec(dllexport) LPSTR WINAPI kPrf2Wrap_lstrcpyA( LPSTR lpString1, LPCSTR lpString2 )
+{
+    static FN_lstrcpyA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrcpyA", &g_Kernel32);
+    return pfn( lpString1, lpString2 );
+}
+
+typedef LPWSTR WINAPI FN_lstrcpyW( LPWSTR lpString1, LPCWSTR lpString2 );
+__declspec(dllexport) LPWSTR WINAPI kPrf2Wrap_lstrcpyW( LPWSTR lpString1, LPCWSTR lpString2 )
+{
+    static FN_lstrcpyW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrcpyW", &g_Kernel32);
+    return pfn( lpString1, lpString2 );
+}
+
+typedef LPSTR WINAPI FN_lstrcatA( LPSTR lpString1, LPCSTR lpString2 );
+__declspec(dllexport) LPSTR WINAPI kPrf2Wrap_lstrcatA( LPSTR lpString1, LPCSTR lpString2 )
+{
+    static FN_lstrcatA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrcatA", &g_Kernel32);
+    return pfn( lpString1, lpString2 );
+}
+
+typedef LPWSTR WINAPI FN_lstrcatW( LPWSTR lpString1, LPCWSTR lpString2 );
+__declspec(dllexport) LPWSTR WINAPI kPrf2Wrap_lstrcatW( LPWSTR lpString1, LPCWSTR lpString2 )
+{
+    static FN_lstrcatW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrcatW", &g_Kernel32);
+    return pfn( lpString1, lpString2 );
+}
+
+typedef int WINAPI FN_lstrlenA( LPCSTR lpString );
+__declspec(dllexport) int WINAPI kPrf2Wrap_lstrlenA( LPCSTR lpString )
+{
+    static FN_lstrlenA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrlenA", &g_Kernel32);
+    return pfn( lpString );
+}
+
+typedef int WINAPI FN_lstrlenW( LPCWSTR lpString );
+__declspec(dllexport) int WINAPI kPrf2Wrap_lstrlenW( LPCWSTR lpString )
+{
+    static FN_lstrlenW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrlenW", &g_Kernel32);
+    return pfn( lpString );
+}
+
+typedef HFILE WINAPI FN_OpenFile( LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle );
+__declspec(dllexport) HFILE WINAPI kPrf2Wrap_OpenFile( LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle )
+{
+    static FN_OpenFile *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenFile", &g_Kernel32);
+    return pfn( lpFileName, lpReOpenBuff, uStyle );
+}
+
+typedef HFILE WINAPI FN__lopen( LPCSTR lpPathName, int iReadWrite );
+__declspec(dllexport) HFILE WINAPI kPrf2Wrap__lopen( LPCSTR lpPathName, int iReadWrite )
+{
+    static FN__lopen *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "_lopen", &g_Kernel32);
+    return pfn( lpPathName, iReadWrite );
+}
+
+typedef HFILE WINAPI FN__lcreat( LPCSTR lpPathName, int iAttribute );
+__declspec(dllexport) HFILE WINAPI kPrf2Wrap__lcreat( LPCSTR lpPathName, int iAttribute )
+{
+    static FN__lcreat *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "_lcreat", &g_Kernel32);
+    return pfn( lpPathName, iAttribute );
+}
+
+typedef UINT WINAPI FN__lread( HFILE hFile, LPVOID lpBuffer, UINT uBytes );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap__lread( HFILE hFile, LPVOID lpBuffer, UINT uBytes )
+{
+    static FN__lread *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "_lread", &g_Kernel32);
+    return pfn( hFile, lpBuffer, uBytes );
+}
+
+typedef UINT WINAPI FN__lwrite( HFILE hFile, LPCCH lpBuffer, UINT uBytes );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap__lwrite( HFILE hFile, LPCCH lpBuffer, UINT uBytes )
+{
+    static FN__lwrite *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "_lwrite", &g_Kernel32);
+    return pfn( hFile, lpBuffer, uBytes );
+}
+
+typedef long WINAPI FN__hread( HFILE hFile, LPVOID lpBuffer, long lBytes );
+__declspec(dllexport) long WINAPI kPrf2Wrap__hread( HFILE hFile, LPVOID lpBuffer, long lBytes )
+{
+    static FN__hread *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "_hread", &g_Kernel32);
+    return pfn( hFile, lpBuffer, lBytes );
+}
+
+typedef long WINAPI FN__hwrite( HFILE hFile, LPCCH lpBuffer, long lBytes );
+__declspec(dllexport) long WINAPI kPrf2Wrap__hwrite( HFILE hFile, LPCCH lpBuffer, long lBytes )
+{
+    static FN__hwrite *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "_hwrite", &g_Kernel32);
+    return pfn( hFile, lpBuffer, lBytes );
+}
+
+typedef HFILE WINAPI FN__lclose( HFILE hFile );
+__declspec(dllexport) HFILE WINAPI kPrf2Wrap__lclose( HFILE hFile )
+{
+    static FN__lclose *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "_lclose", &g_Kernel32);
+    return pfn( hFile );
+}
+
+typedef LONG WINAPI FN__llseek( HFILE hFile, LONG lOffset, int iOrigin );
+__declspec(dllexport) LONG WINAPI kPrf2Wrap__llseek( HFILE hFile, LONG lOffset, int iOrigin )
+{
+    static FN__llseek *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "_llseek", &g_Kernel32);
+    return pfn( hFile, lOffset, iOrigin );
+}
+
+typedef BOOL WINAPI FN_IsTextUnicode( CONST VOID * lpv, int iSize, LPINT lpiResult );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsTextUnicode( CONST VOID * lpv, int iSize, LPINT lpiResult )
+{
+    static FN_IsTextUnicode *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsTextUnicode", &g_Kernel32);
+    return pfn( lpv, iSize, lpiResult );
+}
+
+typedef DWORD WINAPI FN_FlsAlloc( PFLS_CALLBACK_FUNCTION lpCallback );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_FlsAlloc( PFLS_CALLBACK_FUNCTION lpCallback )
+{
+    static FN_FlsAlloc *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FlsAlloc", &g_Kernel32);
+    return pfn( lpCallback );
+}
+
+typedef PVOID WINAPI FN_FlsGetValue( DWORD dwFlsIndex );
+__declspec(dllexport) PVOID WINAPI kPrf2Wrap_FlsGetValue( DWORD dwFlsIndex )
+{
+    static FN_FlsGetValue *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FlsGetValue", &g_Kernel32);
+    return pfn( dwFlsIndex );
+}
+
+typedef BOOL WINAPI FN_FlsSetValue( DWORD dwFlsIndex, PVOID lpFlsData );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FlsSetValue( DWORD dwFlsIndex, PVOID lpFlsData )
+{
+    static FN_FlsSetValue *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FlsSetValue", &g_Kernel32);
+    return pfn( dwFlsIndex, lpFlsData );
+}
+
+typedef BOOL WINAPI FN_FlsFree( DWORD dwFlsIndex );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FlsFree( DWORD dwFlsIndex )
+{
+    static FN_FlsFree *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FlsFree", &g_Kernel32);
+    return pfn( dwFlsIndex );
+}
+
+typedef DWORD WINAPI FN_TlsAlloc( VOID );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_TlsAlloc( VOID )
+{
+    static FN_TlsAlloc *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "TlsAlloc", &g_Kernel32);
+    return pfn ();
+}
+
+typedef LPVOID WINAPI FN_TlsGetValue( DWORD dwTlsIndex );
+__declspec(dllexport) LPVOID WINAPI kPrf2Wrap_TlsGetValue( DWORD dwTlsIndex )
+{
+    static FN_TlsGetValue *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "TlsGetValue", &g_Kernel32);
+    return pfn( dwTlsIndex );
+}
+
+typedef BOOL WINAPI FN_TlsSetValue( DWORD dwTlsIndex, LPVOID lpTlsValue );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_TlsSetValue( DWORD dwTlsIndex, LPVOID lpTlsValue )
+{
+    static FN_TlsSetValue *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "TlsSetValue", &g_Kernel32);
+    return pfn( dwTlsIndex, lpTlsValue );
+}
+
+typedef BOOL WINAPI FN_TlsFree( DWORD dwTlsIndex );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_TlsFree( DWORD dwTlsIndex )
+{
+    static FN_TlsFree *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "TlsFree", &g_Kernel32);
+    return pfn( dwTlsIndex );
+}
+
+typedef DWORD WINAPI FN_SleepEx( DWORD dwMilliseconds, BOOL bAlertable );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_SleepEx( DWORD dwMilliseconds, BOOL bAlertable )
+{
+    static FN_SleepEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SleepEx", &g_Kernel32);
+    return pfn( dwMilliseconds, bAlertable );
+}
+
+typedef DWORD WINAPI FN_WaitForSingleObjectEx( HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertable );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_WaitForSingleObjectEx( HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertable )
+{
+    static FN_WaitForSingleObjectEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WaitForSingleObjectEx", &g_Kernel32);
+    return pfn( hHandle, dwMilliseconds, bAlertable );
+}
+
+typedef DWORD WINAPI FN_WaitForMultipleObjectsEx( DWORD nCount, CONST HANDLE * lpHandles, BOOL bWaitAll, DWORD dwMilliseconds, BOOL bAlertable );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_WaitForMultipleObjectsEx( DWORD nCount, CONST HANDLE * lpHandles, BOOL bWaitAll, DWORD dwMilliseconds, BOOL bAlertable )
+{
+    static FN_WaitForMultipleObjectsEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WaitForMultipleObjectsEx", &g_Kernel32);
+    return pfn( nCount, lpHandles, bWaitAll, dwMilliseconds, bAlertable );
+}
+
+typedef DWORD WINAPI FN_SignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_SignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable )
+{
+    static FN_SignalObjectAndWait *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SignalObjectAndWait", &g_Kernel32);
+    return pfn( hObjectToSignal, hObjectToWaitOn, dwMilliseconds, bAlertable );
+}
+
+typedef BOOL WINAPI FN_ReadFileEx( HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadFileEx( HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
+{
+    static FN_ReadFileEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadFileEx", &g_Kernel32);
+    return pfn( hFile, lpBuffer, nNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine );
+}
+
+typedef BOOL WINAPI FN_WriteFileEx( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteFileEx( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
+{
+    static FN_WriteFileEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteFileEx", &g_Kernel32);
+    return pfn( hFile, lpBuffer, nNumberOfBytesToWrite, lpOverlapped, lpCompletionRoutine );
+}
+
+typedef BOOL WINAPI FN_BackupRead( HANDLE hFile, LPBYTE lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, BOOL bAbort, BOOL bProcessSecurity, LPVOID * lpContext );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_BackupRead( HANDLE hFile, LPBYTE lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, BOOL bAbort, BOOL bProcessSecurity, LPVOID * lpContext )
+{
+    static FN_BackupRead *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "BackupRead", &g_Kernel32);
+    return pfn( hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, bAbort, bProcessSecurity, lpContext );
+}
+
+typedef BOOL WINAPI FN_BackupSeek( HANDLE hFile, DWORD dwLowBytesToSeek, DWORD dwHighBytesToSeek, LPDWORD lpdwLowByteSeeked, LPDWORD lpdwHighByteSeeked, LPVOID * lpContext );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_BackupSeek( HANDLE hFile, DWORD dwLowBytesToSeek, DWORD dwHighBytesToSeek, LPDWORD lpdwLowByteSeeked, LPDWORD lpdwHighByteSeeked, LPVOID * lpContext )
+{
+    static FN_BackupSeek *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "BackupSeek", &g_Kernel32);
+    return pfn( hFile, dwLowBytesToSeek, dwHighBytesToSeek, lpdwLowByteSeeked, lpdwHighByteSeeked, lpContext );
+}
+
+typedef BOOL WINAPI FN_BackupWrite( HANDLE hFile, LPBYTE lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, BOOL bAbort, BOOL bProcessSecurity, LPVOID * lpContext );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_BackupWrite( HANDLE hFile, LPBYTE lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, BOOL bAbort, BOOL bProcessSecurity, LPVOID * lpContext )
+{
+    static FN_BackupWrite *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "BackupWrite", &g_Kernel32);
+    return pfn( hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, bAbort, bProcessSecurity, lpContext );
+}
+
+typedef BOOL WINAPI FN_ReadFileScatter( HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[], DWORD nNumberOfBytesToRead, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadFileScatter( HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[], DWORD nNumberOfBytesToRead, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped )
+{
+    static FN_ReadFileScatter *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadFileScatter", &g_Kernel32);
+    return pfn( hFile, aSegmentArray, nNumberOfBytesToRead, lpReserved, lpOverlapped );
+}
+
+typedef BOOL WINAPI FN_WriteFileGather( HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[], DWORD nNumberOfBytesToWrite, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteFileGather( HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[], DWORD nNumberOfBytesToWrite, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped )
+{
+    static FN_WriteFileGather *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteFileGather", &g_Kernel32);
+    return pfn( hFile, aSegmentArray, nNumberOfBytesToWrite, lpReserved, lpOverlapped );
+}
+
+typedef HANDLE WINAPI FN_CreateMutexA( LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateMutexA( LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCSTR lpName )
+{
+    static FN_CreateMutexA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateMutexA", &g_Kernel32);
+    return pfn( lpMutexAttributes, bInitialOwner, lpName );
+}
+
+typedef HANDLE WINAPI FN_CreateMutexW( LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateMutexW( LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName )
+{
+    static FN_CreateMutexW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateMutexW", &g_Kernel32);
+    return pfn( lpMutexAttributes, bInitialOwner, lpName );
+}
+
+typedef HANDLE WINAPI FN_OpenMutexA( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenMutexA( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName )
+{
+    static FN_OpenMutexA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenMutexA", &g_Kernel32);
+    return pfn( dwDesiredAccess, bInheritHandle, lpName );
+}
+
+typedef HANDLE WINAPI FN_OpenMutexW( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenMutexW( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName )
+{
+    static FN_OpenMutexW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenMutexW", &g_Kernel32);
+    return pfn( dwDesiredAccess, bInheritHandle, lpName );
+}
+
+typedef HANDLE WINAPI FN_CreateEventA( LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateEventA( LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCSTR lpName )
+{
+    static FN_CreateEventA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateEventA", &g_Kernel32);
+    return pfn( lpEventAttributes, bManualReset, bInitialState, lpName );
+}
+
+typedef HANDLE WINAPI FN_CreateEventW( LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateEventW( LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName )
+{
+    static FN_CreateEventW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateEventW", &g_Kernel32);
+    return pfn( lpEventAttributes, bManualReset, bInitialState, lpName );
+}
+
+typedef HANDLE WINAPI FN_OpenEventA( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenEventA( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName )
+{
+    static FN_OpenEventA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenEventA", &g_Kernel32);
+    return pfn( dwDesiredAccess, bInheritHandle, lpName );
+}
+
+typedef HANDLE WINAPI FN_OpenEventW( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenEventW( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName )
+{
+    static FN_OpenEventW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenEventW", &g_Kernel32);
+    return pfn( dwDesiredAccess, bInheritHandle, lpName );
+}
+
+typedef HANDLE WINAPI FN_CreateSemaphoreA( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateSemaphoreA( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCSTR lpName )
+{
+    static FN_CreateSemaphoreA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateSemaphoreA", &g_Kernel32);
+    return pfn( lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName );
+}
+
+typedef HANDLE WINAPI FN_CreateSemaphoreW( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCWSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateSemaphoreW( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCWSTR lpName )
+{
+    static FN_CreateSemaphoreW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateSemaphoreW", &g_Kernel32);
+    return pfn( lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName );
+}
+
+typedef HANDLE WINAPI FN_OpenSemaphoreA( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenSemaphoreA( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName )
+{
+    static FN_OpenSemaphoreA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenSemaphoreA", &g_Kernel32);
+    return pfn( dwDesiredAccess, bInheritHandle, lpName );
+}
+
+typedef HANDLE WINAPI FN_OpenSemaphoreW( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenSemaphoreW( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName )
+{
+    static FN_OpenSemaphoreW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenSemaphoreW", &g_Kernel32);
+    return pfn( dwDesiredAccess, bInheritHandle, lpName );
+}
+
+typedef HANDLE WINAPI FN_CreateWaitableTimerA( LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, LPCSTR lpTimerName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateWaitableTimerA( LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, LPCSTR lpTimerName )
+{
+    static FN_CreateWaitableTimerA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateWaitableTimerA", &g_Kernel32);
+    return pfn( lpTimerAttributes, bManualReset, lpTimerName );
+}
+
+typedef HANDLE WINAPI FN_CreateWaitableTimerW( LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, LPCWSTR lpTimerName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateWaitableTimerW( LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, LPCWSTR lpTimerName )
+{
+    static FN_CreateWaitableTimerW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateWaitableTimerW", &g_Kernel32);
+    return pfn( lpTimerAttributes, bManualReset, lpTimerName );
+}
+
+typedef HANDLE WINAPI FN_OpenWaitableTimerA( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpTimerName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenWaitableTimerA( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpTimerName )
+{
+    static FN_OpenWaitableTimerA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenWaitableTimerA", &g_Kernel32);
+    return pfn( dwDesiredAccess, bInheritHandle, lpTimerName );
+}
+
+typedef HANDLE WINAPI FN_OpenWaitableTimerW( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpTimerName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenWaitableTimerW( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpTimerName )
+{
+    static FN_OpenWaitableTimerW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenWaitableTimerW", &g_Kernel32);
+    return pfn( dwDesiredAccess, bInheritHandle, lpTimerName );
+}
+
+typedef BOOL WINAPI FN_SetWaitableTimer( HANDLE hTimer, const LARGE_INTEGER * lpDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, BOOL fResume );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetWaitableTimer( HANDLE hTimer, const LARGE_INTEGER * lpDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, BOOL fResume )
+{
+    static FN_SetWaitableTimer *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetWaitableTimer", &g_Kernel32);
+    return pfn( hTimer, lpDueTime, lPeriod, pfnCompletionRoutine, lpArgToCompletionRoutine, fResume );
+}
+
+typedef BOOL WINAPI FN_CancelWaitableTimer( HANDLE hTimer );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CancelWaitableTimer( HANDLE hTimer )
+{
+    static FN_CancelWaitableTimer *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CancelWaitableTimer", &g_Kernel32);
+    return pfn( hTimer );
+}
+
+typedef HANDLE WINAPI FN_CreateFileMappingA( HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateFileMappingA( HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName )
+{
+    static FN_CreateFileMappingA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateFileMappingA", &g_Kernel32);
+    return pfn( hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName );
+}
+
+typedef HANDLE WINAPI FN_CreateFileMappingW( HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCWSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateFileMappingW( HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCWSTR lpName )
+{
+    static FN_CreateFileMappingW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateFileMappingW", &g_Kernel32);
+    return pfn( hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName );
+}
+
+typedef HANDLE WINAPI FN_OpenFileMappingA( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenFileMappingA( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName )
+{
+    static FN_OpenFileMappingA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenFileMappingA", &g_Kernel32);
+    return pfn( dwDesiredAccess, bInheritHandle, lpName );
+}
+
+typedef HANDLE WINAPI FN_OpenFileMappingW( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenFileMappingW( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName )
+{
+    static FN_OpenFileMappingW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenFileMappingW", &g_Kernel32);
+    return pfn( dwDesiredAccess, bInheritHandle, lpName );
+}
+
+typedef DWORD WINAPI FN_GetLogicalDriveStringsA( DWORD nBufferLength, LPSTR lpBuffer );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetLogicalDriveStringsA( DWORD nBufferLength, LPSTR lpBuffer )
+{
+    static FN_GetLogicalDriveStringsA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetLogicalDriveStringsA", &g_Kernel32);
+    return pfn( nBufferLength, lpBuffer );
+}
+
+typedef DWORD WINAPI FN_GetLogicalDriveStringsW( DWORD nBufferLength, LPWSTR lpBuffer );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetLogicalDriveStringsW( DWORD nBufferLength, LPWSTR lpBuffer )
+{
+    static FN_GetLogicalDriveStringsW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetLogicalDriveStringsW", &g_Kernel32);
+    return pfn( nBufferLength, lpBuffer );
+}
+
+typedef HANDLE WINAPI FN_CreateMemoryResourceNotification( MEMORY_RESOURCE_NOTIFICATION_TYPE NotificationType );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateMemoryResourceNotification( MEMORY_RESOURCE_NOTIFICATION_TYPE NotificationType )
+{
+    static FN_CreateMemoryResourceNotification *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateMemoryResourceNotification", &g_Kernel32);
+    return pfn( NotificationType );
+}
+
+typedef BOOL WINAPI FN_QueryMemoryResourceNotification( HANDLE ResourceNotificationHandle, PBOOL ResourceState );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_QueryMemoryResourceNotification( HANDLE ResourceNotificationHandle, PBOOL ResourceState )
+{
+    static FN_QueryMemoryResourceNotification *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "QueryMemoryResourceNotification", &g_Kernel32);
+    return pfn( ResourceNotificationHandle, ResourceState );
+}
+
+typedef HMODULE WINAPI FN_LoadLibraryA( LPCSTR lpLibFileName );
+__declspec(dllexport) HMODULE WINAPI kPrf2Wrap_LoadLibraryA( LPCSTR lpLibFileName )
+{
+    static FN_LoadLibraryA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LoadLibraryA", &g_Kernel32);
+    return pfn( lpLibFileName );
+}
+
+typedef HMODULE WINAPI FN_LoadLibraryW( LPCWSTR lpLibFileName );
+__declspec(dllexport) HMODULE WINAPI kPrf2Wrap_LoadLibraryW( LPCWSTR lpLibFileName )
+{
+    static FN_LoadLibraryW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LoadLibraryW", &g_Kernel32);
+    return pfn( lpLibFileName );
+}
+
+typedef HMODULE WINAPI FN_LoadLibraryExA( LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags );
+__declspec(dllexport) HMODULE WINAPI kPrf2Wrap_LoadLibraryExA( LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags )
+{
+    static FN_LoadLibraryExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LoadLibraryExA", &g_Kernel32);
+    return pfn( lpLibFileName, hFile, dwFlags );
+}
+
+typedef HMODULE WINAPI FN_LoadLibraryExW( LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags );
+__declspec(dllexport) HMODULE WINAPI kPrf2Wrap_LoadLibraryExW( LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags )
+{
+    static FN_LoadLibraryExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LoadLibraryExW", &g_Kernel32);
+    return pfn( lpLibFileName, hFile, dwFlags );
+}
+
+typedef DWORD WINAPI FN_GetModuleFileNameA( HMODULE hModule, LPCH lpFilename, DWORD nSize );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetModuleFileNameA( HMODULE hModule, LPCH lpFilename, DWORD nSize )
+{
+    static FN_GetModuleFileNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetModuleFileNameA", &g_Kernel32);
+    return pfn( hModule, lpFilename, nSize );
+}
+
+typedef DWORD WINAPI FN_GetModuleFileNameW( HMODULE hModule, LPWCH lpFilename, DWORD nSize );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetModuleFileNameW( HMODULE hModule, LPWCH lpFilename, DWORD nSize )
+{
+    static FN_GetModuleFileNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetModuleFileNameW", &g_Kernel32);
+    return pfn( hModule, lpFilename, nSize );
+}
+
+typedef HMODULE WINAPI FN_GetModuleHandleA( LPCSTR lpModuleName );
+__declspec(dllexport) HMODULE WINAPI kPrf2Wrap_GetModuleHandleA( LPCSTR lpModuleName )
+{
+    static FN_GetModuleHandleA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetModuleHandleA", &g_Kernel32);
+    return pfn( lpModuleName );
+}
+
+typedef HMODULE WINAPI FN_GetModuleHandleW( LPCWSTR lpModuleName );
+__declspec(dllexport) HMODULE WINAPI kPrf2Wrap_GetModuleHandleW( LPCWSTR lpModuleName )
+{
+    static FN_GetModuleHandleW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetModuleHandleW", &g_Kernel32);
+    return pfn( lpModuleName );
+}
+
+typedef BOOL WINAPI FN_GetModuleHandleExA( DWORD dwFlags, LPCSTR lpModuleName, HMODULE * phModule );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetModuleHandleExA( DWORD dwFlags, LPCSTR lpModuleName, HMODULE * phModule )
+{
+    static FN_GetModuleHandleExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetModuleHandleExA", &g_Kernel32);
+    return pfn( dwFlags, lpModuleName, phModule );
+}
+
+typedef BOOL WINAPI FN_GetModuleHandleExW( DWORD dwFlags, LPCWSTR lpModuleName, HMODULE * phModule );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetModuleHandleExW( DWORD dwFlags, LPCWSTR lpModuleName, HMODULE * phModule )
+{
+    static FN_GetModuleHandleExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetModuleHandleExW", &g_Kernel32);
+    return pfn( dwFlags, lpModuleName, phModule );
+}
+
+typedef BOOL WINAPI FN_NeedCurrentDirectoryForExePathA( LPCSTR ExeName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_NeedCurrentDirectoryForExePathA( LPCSTR ExeName )
+{
+    static FN_NeedCurrentDirectoryForExePathA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "NeedCurrentDirectoryForExePathA", &g_Kernel32);
+    return pfn( ExeName );
+}
+
+typedef BOOL WINAPI FN_NeedCurrentDirectoryForExePathW( LPCWSTR ExeName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_NeedCurrentDirectoryForExePathW( LPCWSTR ExeName )
+{
+    static FN_NeedCurrentDirectoryForExePathW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "NeedCurrentDirectoryForExePathW", &g_Kernel32);
+    return pfn( ExeName );
+}
+
+typedef BOOL WINAPI FN_CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
+{
+    static FN_CreateProcessA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateProcessA", &g_Kernel32);
+    return pfn( lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation );
+}
+
+typedef BOOL WINAPI FN_CreateProcessW( LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreateProcessW( LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
+{
+    static FN_CreateProcessW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateProcessW", &g_Kernel32);
+    return pfn( lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation );
+}
+
+typedef BOOL WINAPI FN_SetProcessShutdownParameters( DWORD dwLevel, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetProcessShutdownParameters( DWORD dwLevel, DWORD dwFlags )
+{
+    static FN_SetProcessShutdownParameters *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetProcessShutdownParameters", &g_Kernel32);
+    return pfn( dwLevel, dwFlags );
+}
+
+typedef BOOL WINAPI FN_GetProcessShutdownParameters( LPDWORD lpdwLevel, LPDWORD lpdwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetProcessShutdownParameters( LPDWORD lpdwLevel, LPDWORD lpdwFlags )
+{
+    static FN_GetProcessShutdownParameters *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProcessShutdownParameters", &g_Kernel32);
+    return pfn( lpdwLevel, lpdwFlags );
+}
+
+typedef DWORD WINAPI FN_GetProcessVersion( DWORD ProcessId );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetProcessVersion( DWORD ProcessId )
+{
+    static FN_GetProcessVersion *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProcessVersion", &g_Kernel32);
+    return pfn( ProcessId );
+}
+
+typedef VOID WINAPI FN_FatalAppExitA( UINT uAction, LPCSTR lpMessageText );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_FatalAppExitA( UINT uAction, LPCSTR lpMessageText )
+{
+    static FN_FatalAppExitA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FatalAppExitA", &g_Kernel32);
+    pfn( uAction, lpMessageText );
+}
+
+typedef VOID WINAPI FN_FatalAppExitW( UINT uAction, LPCWSTR lpMessageText );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_FatalAppExitW( UINT uAction, LPCWSTR lpMessageText )
+{
+    static FN_FatalAppExitW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FatalAppExitW", &g_Kernel32);
+    pfn( uAction, lpMessageText );
+}
+
+typedef VOID WINAPI FN_GetStartupInfoA( LPSTARTUPINFOA lpStartupInfo );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_GetStartupInfoA( LPSTARTUPINFOA lpStartupInfo )
+{
+    static FN_GetStartupInfoA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetStartupInfoA", &g_Kernel32);
+    pfn( lpStartupInfo );
+}
+
+typedef VOID WINAPI FN_GetStartupInfoW( LPSTARTUPINFOW lpStartupInfo );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_GetStartupInfoW( LPSTARTUPINFOW lpStartupInfo )
+{
+    static FN_GetStartupInfoW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetStartupInfoW", &g_Kernel32);
+    pfn( lpStartupInfo );
+}
+
+typedef LPSTR WINAPI FN_GetCommandLineA( VOID );
+__declspec(dllexport) LPSTR WINAPI kPrf2Wrap_GetCommandLineA( VOID )
+{
+    static FN_GetCommandLineA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCommandLineA", &g_Kernel32);
+    return pfn ();
+}
+
+typedef LPWSTR WINAPI FN_GetCommandLineW( VOID );
+__declspec(dllexport) LPWSTR WINAPI kPrf2Wrap_GetCommandLineW( VOID )
+{
+    static FN_GetCommandLineW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCommandLineW", &g_Kernel32);
+    return pfn ();
+}
+
+typedef DWORD WINAPI FN_GetEnvironmentVariableA( LPCSTR lpName, LPSTR lpBuffer, DWORD nSize );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetEnvironmentVariableA( LPCSTR lpName, LPSTR lpBuffer, DWORD nSize )
+{
+    static FN_GetEnvironmentVariableA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetEnvironmentVariableA", &g_Kernel32);
+    return pfn( lpName, lpBuffer, nSize );
+}
+
+typedef DWORD WINAPI FN_GetEnvironmentVariableW( LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetEnvironmentVariableW( LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize )
+{
+    static FN_GetEnvironmentVariableW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetEnvironmentVariableW", &g_Kernel32);
+    return pfn( lpName, lpBuffer, nSize );
+}
+
+typedef BOOL WINAPI FN_SetEnvironmentVariableA( LPCSTR lpName, LPCSTR lpValue );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetEnvironmentVariableA( LPCSTR lpName, LPCSTR lpValue )
+{
+    static FN_SetEnvironmentVariableA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetEnvironmentVariableA", &g_Kernel32);
+    return pfn( lpName, lpValue );
+}
+
+typedef BOOL WINAPI FN_SetEnvironmentVariableW( LPCWSTR lpName, LPCWSTR lpValue );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetEnvironmentVariableW( LPCWSTR lpName, LPCWSTR lpValue )
+{
+    static FN_SetEnvironmentVariableW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetEnvironmentVariableW", &g_Kernel32);
+    return pfn( lpName, lpValue );
+}
+
+typedef DWORD WINAPI FN_ExpandEnvironmentStringsA( LPCSTR lpSrc, LPSTR lpDst, DWORD nSize );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_ExpandEnvironmentStringsA( LPCSTR lpSrc, LPSTR lpDst, DWORD nSize )
+{
+    static FN_ExpandEnvironmentStringsA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ExpandEnvironmentStringsA", &g_Kernel32);
+    return pfn( lpSrc, lpDst, nSize );
+}
+
+typedef DWORD WINAPI FN_ExpandEnvironmentStringsW( LPCWSTR lpSrc, LPWSTR lpDst, DWORD nSize );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_ExpandEnvironmentStringsW( LPCWSTR lpSrc, LPWSTR lpDst, DWORD nSize )
+{
+    static FN_ExpandEnvironmentStringsW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ExpandEnvironmentStringsW", &g_Kernel32);
+    return pfn( lpSrc, lpDst, nSize );
+}
+
+typedef DWORD WINAPI FN_GetFirmwareEnvironmentVariableA( LPCSTR lpName, LPCSTR lpGuid, PVOID pBuffer, DWORD nSize );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetFirmwareEnvironmentVariableA( LPCSTR lpName, LPCSTR lpGuid, PVOID pBuffer, DWORD nSize )
+{
+    static FN_GetFirmwareEnvironmentVariableA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFirmwareEnvironmentVariableA", &g_Kernel32);
+    return pfn( lpName, lpGuid, pBuffer, nSize );
+}
+
+typedef DWORD WINAPI FN_GetFirmwareEnvironmentVariableW( LPCWSTR lpName, LPCWSTR lpGuid, PVOID pBuffer, DWORD nSize );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetFirmwareEnvironmentVariableW( LPCWSTR lpName, LPCWSTR lpGuid, PVOID pBuffer, DWORD nSize )
+{
+    static FN_GetFirmwareEnvironmentVariableW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFirmwareEnvironmentVariableW", &g_Kernel32);
+    return pfn( lpName, lpGuid, pBuffer, nSize );
+}
+
+typedef BOOL WINAPI FN_SetFirmwareEnvironmentVariableA( LPCSTR lpName, LPCSTR lpGuid, PVOID pValue, DWORD nSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetFirmwareEnvironmentVariableA( LPCSTR lpName, LPCSTR lpGuid, PVOID pValue, DWORD nSize )
+{
+    static FN_SetFirmwareEnvironmentVariableA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetFirmwareEnvironmentVariableA", &g_Kernel32);
+    return pfn( lpName, lpGuid, pValue, nSize );
+}
+
+typedef BOOL WINAPI FN_SetFirmwareEnvironmentVariableW( LPCWSTR lpName, LPCWSTR lpGuid, PVOID pValue, DWORD nSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetFirmwareEnvironmentVariableW( LPCWSTR lpName, LPCWSTR lpGuid, PVOID pValue, DWORD nSize )
+{
+    static FN_SetFirmwareEnvironmentVariableW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetFirmwareEnvironmentVariableW", &g_Kernel32);
+    return pfn( lpName, lpGuid, pValue, nSize );
+}
+
+typedef VOID WINAPI FN_OutputDebugStringA( LPCSTR lpOutputString );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_OutputDebugStringA( LPCSTR lpOutputString )
+{
+    static FN_OutputDebugStringA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OutputDebugStringA", &g_Kernel32);
+    pfn( lpOutputString );
+}
+
+typedef VOID WINAPI FN_OutputDebugStringW( LPCWSTR lpOutputString );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_OutputDebugStringW( LPCWSTR lpOutputString )
+{
+    static FN_OutputDebugStringW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OutputDebugStringW", &g_Kernel32);
+    pfn( lpOutputString );
+}
+
+typedef HRSRC WINAPI FN_FindResourceA( HMODULE hModule, LPCSTR lpName, LPCSTR lpType );
+__declspec(dllexport) HRSRC WINAPI kPrf2Wrap_FindResourceA( HMODULE hModule, LPCSTR lpName, LPCSTR lpType )
+{
+    static FN_FindResourceA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindResourceA", &g_Kernel32);
+    return pfn( hModule, lpName, lpType );
+}
+
+typedef HRSRC WINAPI FN_FindResourceW( HMODULE hModule, LPCWSTR lpName, LPCWSTR lpType );
+__declspec(dllexport) HRSRC WINAPI kPrf2Wrap_FindResourceW( HMODULE hModule, LPCWSTR lpName, LPCWSTR lpType )
+{
+    static FN_FindResourceW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindResourceW", &g_Kernel32);
+    return pfn( hModule, lpName, lpType );
+}
+
+typedef HRSRC WINAPI FN_FindResourceExA( HMODULE hModule, LPCSTR lpType, LPCSTR lpName, WORD wLanguage );
+__declspec(dllexport) HRSRC WINAPI kPrf2Wrap_FindResourceExA( HMODULE hModule, LPCSTR lpType, LPCSTR lpName, WORD wLanguage )
+{
+    static FN_FindResourceExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindResourceExA", &g_Kernel32);
+    return pfn( hModule, lpType, lpName, wLanguage );
+}
+
+typedef HRSRC WINAPI FN_FindResourceExW( HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLanguage );
+__declspec(dllexport) HRSRC WINAPI kPrf2Wrap_FindResourceExW( HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLanguage )
+{
+    static FN_FindResourceExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindResourceExW", &g_Kernel32);
+    return pfn( hModule, lpType, lpName, wLanguage );
+}
+
+typedef BOOL WINAPI FN_EnumResourceTypesA( HMODULE hModule, ENUMRESTYPEPROCA lpEnumFunc, LONG_PTR lParam );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumResourceTypesA( HMODULE hModule, ENUMRESTYPEPROCA lpEnumFunc, LONG_PTR lParam )
+{
+    static FN_EnumResourceTypesA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumResourceTypesA", &g_Kernel32);
+    return pfn( hModule, lpEnumFunc, lParam );
+}
+
+typedef BOOL WINAPI FN_EnumResourceTypesW( HMODULE hModule, ENUMRESTYPEPROCW lpEnumFunc, LONG_PTR lParam );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumResourceTypesW( HMODULE hModule, ENUMRESTYPEPROCW lpEnumFunc, LONG_PTR lParam )
+{
+    static FN_EnumResourceTypesW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumResourceTypesW", &g_Kernel32);
+    return pfn( hModule, lpEnumFunc, lParam );
+}
+
+typedef BOOL WINAPI FN_EnumResourceNamesA( HMODULE hModule, LPCSTR lpType, ENUMRESNAMEPROCA lpEnumFunc, LONG_PTR lParam );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumResourceNamesA( HMODULE hModule, LPCSTR lpType, ENUMRESNAMEPROCA lpEnumFunc, LONG_PTR lParam )
+{
+    static FN_EnumResourceNamesA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumResourceNamesA", &g_Kernel32);
+    return pfn( hModule, lpType, lpEnumFunc, lParam );
+}
+
+typedef BOOL WINAPI FN_EnumResourceNamesW( HMODULE hModule, LPCWSTR lpType, ENUMRESNAMEPROCW lpEnumFunc, LONG_PTR lParam );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumResourceNamesW( HMODULE hModule, LPCWSTR lpType, ENUMRESNAMEPROCW lpEnumFunc, LONG_PTR lParam )
+{
+    static FN_EnumResourceNamesW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumResourceNamesW", &g_Kernel32);
+    return pfn( hModule, lpType, lpEnumFunc, lParam );
+}
+
+typedef BOOL WINAPI FN_EnumResourceLanguagesA( HMODULE hModule, LPCSTR lpType, LPCSTR lpName, ENUMRESLANGPROCA lpEnumFunc, LONG_PTR lParam );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumResourceLanguagesA( HMODULE hModule, LPCSTR lpType, LPCSTR lpName, ENUMRESLANGPROCA lpEnumFunc, LONG_PTR lParam )
+{
+    static FN_EnumResourceLanguagesA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumResourceLanguagesA", &g_Kernel32);
+    return pfn( hModule, lpType, lpName, lpEnumFunc, lParam );
+}
+
+typedef BOOL WINAPI FN_EnumResourceLanguagesW( HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, ENUMRESLANGPROCW lpEnumFunc, LONG_PTR lParam );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumResourceLanguagesW( HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, ENUMRESLANGPROCW lpEnumFunc, LONG_PTR lParam )
+{
+    static FN_EnumResourceLanguagesW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumResourceLanguagesW", &g_Kernel32);
+    return pfn( hModule, lpType, lpName, lpEnumFunc, lParam );
+}
+
+typedef HANDLE WINAPI FN_BeginUpdateResourceA( LPCSTR pFileName, BOOL bDeleteExistingResources );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_BeginUpdateResourceA( LPCSTR pFileName, BOOL bDeleteExistingResources )
+{
+    static FN_BeginUpdateResourceA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "BeginUpdateResourceA", &g_Kernel32);
+    return pfn( pFileName, bDeleteExistingResources );
+}
+
+typedef HANDLE WINAPI FN_BeginUpdateResourceW( LPCWSTR pFileName, BOOL bDeleteExistingResources );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_BeginUpdateResourceW( LPCWSTR pFileName, BOOL bDeleteExistingResources )
+{
+    static FN_BeginUpdateResourceW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "BeginUpdateResourceW", &g_Kernel32);
+    return pfn( pFileName, bDeleteExistingResources );
+}
+
+typedef BOOL WINAPI FN_UpdateResourceA( HANDLE hUpdate, LPCSTR lpType, LPCSTR lpName, WORD wLanguage, LPVOID lpData, DWORD cb );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_UpdateResourceA( HANDLE hUpdate, LPCSTR lpType, LPCSTR lpName, WORD wLanguage, LPVOID lpData, DWORD cb )
+{
+    static FN_UpdateResourceA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "UpdateResourceA", &g_Kernel32);
+    return pfn( hUpdate, lpType, lpName, wLanguage, lpData, cb );
+}
+
+typedef BOOL WINAPI FN_UpdateResourceW( HANDLE hUpdate, LPCWSTR lpType, LPCWSTR lpName, WORD wLanguage, LPVOID lpData, DWORD cb );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_UpdateResourceW( HANDLE hUpdate, LPCWSTR lpType, LPCWSTR lpName, WORD wLanguage, LPVOID lpData, DWORD cb )
+{
+    static FN_UpdateResourceW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "UpdateResourceW", &g_Kernel32);
+    return pfn( hUpdate, lpType, lpName, wLanguage, lpData, cb );
+}
+
+typedef BOOL WINAPI FN_EndUpdateResourceA( HANDLE hUpdate, BOOL fDiscard );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EndUpdateResourceA( HANDLE hUpdate, BOOL fDiscard )
+{
+    static FN_EndUpdateResourceA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EndUpdateResourceA", &g_Kernel32);
+    return pfn( hUpdate, fDiscard );
+}
+
+typedef BOOL WINAPI FN_EndUpdateResourceW( HANDLE hUpdate, BOOL fDiscard );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EndUpdateResourceW( HANDLE hUpdate, BOOL fDiscard )
+{
+    static FN_EndUpdateResourceW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EndUpdateResourceW", &g_Kernel32);
+    return pfn( hUpdate, fDiscard );
+}
+
+typedef ATOM WINAPI FN_GlobalAddAtomA( LPCSTR lpString );
+__declspec(dllexport) ATOM WINAPI kPrf2Wrap_GlobalAddAtomA( LPCSTR lpString )
+{
+    static FN_GlobalAddAtomA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalAddAtomA", &g_Kernel32);
+    return pfn( lpString );
+}
+
+typedef ATOM WINAPI FN_GlobalAddAtomW( LPCWSTR lpString );
+__declspec(dllexport) ATOM WINAPI kPrf2Wrap_GlobalAddAtomW( LPCWSTR lpString )
+{
+    static FN_GlobalAddAtomW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalAddAtomW", &g_Kernel32);
+    return pfn( lpString );
+}
+
+typedef ATOM WINAPI FN_GlobalFindAtomA( LPCSTR lpString );
+__declspec(dllexport) ATOM WINAPI kPrf2Wrap_GlobalFindAtomA( LPCSTR lpString )
+{
+    static FN_GlobalFindAtomA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalFindAtomA", &g_Kernel32);
+    return pfn( lpString );
+}
+
+typedef ATOM WINAPI FN_GlobalFindAtomW( LPCWSTR lpString );
+__declspec(dllexport) ATOM WINAPI kPrf2Wrap_GlobalFindAtomW( LPCWSTR lpString )
+{
+    static FN_GlobalFindAtomW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalFindAtomW", &g_Kernel32);
+    return pfn( lpString );
+}
+
+typedef UINT WINAPI FN_GlobalGetAtomNameA( ATOM nAtom, LPSTR lpBuffer, int nSize );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GlobalGetAtomNameA( ATOM nAtom, LPSTR lpBuffer, int nSize )
+{
+    static FN_GlobalGetAtomNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalGetAtomNameA", &g_Kernel32);
+    return pfn( nAtom, lpBuffer, nSize );
+}
+
+typedef UINT WINAPI FN_GlobalGetAtomNameW( ATOM nAtom, LPWSTR lpBuffer, int nSize );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GlobalGetAtomNameW( ATOM nAtom, LPWSTR lpBuffer, int nSize )
+{
+    static FN_GlobalGetAtomNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GlobalGetAtomNameW", &g_Kernel32);
+    return pfn( nAtom, lpBuffer, nSize );
+}
+
+typedef ATOM WINAPI FN_AddAtomA( LPCSTR lpString );
+__declspec(dllexport) ATOM WINAPI kPrf2Wrap_AddAtomA( LPCSTR lpString )
+{
+    static FN_AddAtomA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddAtomA", &g_Kernel32);
+    return pfn( lpString );
+}
+
+typedef ATOM WINAPI FN_AddAtomW( LPCWSTR lpString );
+__declspec(dllexport) ATOM WINAPI kPrf2Wrap_AddAtomW( LPCWSTR lpString )
+{
+    static FN_AddAtomW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddAtomW", &g_Kernel32);
+    return pfn( lpString );
+}
+
+typedef ATOM WINAPI FN_FindAtomA( LPCSTR lpString );
+__declspec(dllexport) ATOM WINAPI kPrf2Wrap_FindAtomA( LPCSTR lpString )
+{
+    static FN_FindAtomA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindAtomA", &g_Kernel32);
+    return pfn( lpString );
+}
+
+typedef ATOM WINAPI FN_FindAtomW( LPCWSTR lpString );
+__declspec(dllexport) ATOM WINAPI kPrf2Wrap_FindAtomW( LPCWSTR lpString )
+{
+    static FN_FindAtomW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindAtomW", &g_Kernel32);
+    return pfn( lpString );
+}
+
+typedef UINT WINAPI FN_GetAtomNameA( ATOM nAtom, LPSTR lpBuffer, int nSize );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetAtomNameA( ATOM nAtom, LPSTR lpBuffer, int nSize )
+{
+    static FN_GetAtomNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetAtomNameA", &g_Kernel32);
+    return pfn( nAtom, lpBuffer, nSize );
+}
+
+typedef UINT WINAPI FN_GetAtomNameW( ATOM nAtom, LPWSTR lpBuffer, int nSize );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetAtomNameW( ATOM nAtom, LPWSTR lpBuffer, int nSize )
+{
+    static FN_GetAtomNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetAtomNameW", &g_Kernel32);
+    return pfn( nAtom, lpBuffer, nSize );
+}
+
+typedef UINT WINAPI FN_GetProfileIntA( LPCSTR lpAppName, LPCSTR lpKeyName, INT nDefault );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetProfileIntA( LPCSTR lpAppName, LPCSTR lpKeyName, INT nDefault )
+{
+    static FN_GetProfileIntA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProfileIntA", &g_Kernel32);
+    return pfn( lpAppName, lpKeyName, nDefault );
+}
+
+typedef UINT WINAPI FN_GetProfileIntW( LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetProfileIntW( LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault )
+{
+    static FN_GetProfileIntW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProfileIntW", &g_Kernel32);
+    return pfn( lpAppName, lpKeyName, nDefault );
+}
+
+typedef DWORD WINAPI FN_GetProfileStringA( LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpDefault, LPSTR lpReturnedString, DWORD nSize );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetProfileStringA( LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpDefault, LPSTR lpReturnedString, DWORD nSize )
+{
+    static FN_GetProfileStringA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProfileStringA", &g_Kernel32);
+    return pfn( lpAppName, lpKeyName, lpDefault, lpReturnedString, nSize );
+}
+
+typedef DWORD WINAPI FN_GetProfileStringW( LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpDefault, LPWSTR lpReturnedString, DWORD nSize );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetProfileStringW( LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpDefault, LPWSTR lpReturnedString, DWORD nSize )
+{
+    static FN_GetProfileStringW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProfileStringW", &g_Kernel32);
+    return pfn( lpAppName, lpKeyName, lpDefault, lpReturnedString, nSize );
+}
+
+typedef BOOL WINAPI FN_WriteProfileStringA( LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpString );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteProfileStringA( LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpString )
+{
+    static FN_WriteProfileStringA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteProfileStringA", &g_Kernel32);
+    return pfn( lpAppName, lpKeyName, lpString );
+}
+
+typedef BOOL WINAPI FN_WriteProfileStringW( LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpString );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteProfileStringW( LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpString )
+{
+    static FN_WriteProfileStringW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteProfileStringW", &g_Kernel32);
+    return pfn( lpAppName, lpKeyName, lpString );
+}
+
+typedef DWORD WINAPI FN_GetProfileSectionA( LPCSTR lpAppName, LPSTR lpReturnedString, DWORD nSize );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetProfileSectionA( LPCSTR lpAppName, LPSTR lpReturnedString, DWORD nSize )
+{
+    static FN_GetProfileSectionA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProfileSectionA", &g_Kernel32);
+    return pfn( lpAppName, lpReturnedString, nSize );
+}
+
+typedef DWORD WINAPI FN_GetProfileSectionW( LPCWSTR lpAppName, LPWSTR lpReturnedString, DWORD nSize );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetProfileSectionW( LPCWSTR lpAppName, LPWSTR lpReturnedString, DWORD nSize )
+{
+    static FN_GetProfileSectionW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetProfileSectionW", &g_Kernel32);
+    return pfn( lpAppName, lpReturnedString, nSize );
+}
+
+typedef BOOL WINAPI FN_WriteProfileSectionA( LPCSTR lpAppName, LPCSTR lpString );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteProfileSectionA( LPCSTR lpAppName, LPCSTR lpString )
+{
+    static FN_WriteProfileSectionA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteProfileSectionA", &g_Kernel32);
+    return pfn( lpAppName, lpString );
+}
+
+typedef BOOL WINAPI FN_WriteProfileSectionW( LPCWSTR lpAppName, LPCWSTR lpString );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteProfileSectionW( LPCWSTR lpAppName, LPCWSTR lpString )
+{
+    static FN_WriteProfileSectionW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteProfileSectionW", &g_Kernel32);
+    return pfn( lpAppName, lpString );
+}
+
+typedef UINT WINAPI FN_GetPrivateProfileIntA( LPCSTR lpAppName, LPCSTR lpKeyName, INT nDefault, LPCSTR lpFileName );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetPrivateProfileIntA( LPCSTR lpAppName, LPCSTR lpKeyName, INT nDefault, LPCSTR lpFileName )
+{
+    static FN_GetPrivateProfileIntA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetPrivateProfileIntA", &g_Kernel32);
+    return pfn( lpAppName, lpKeyName, nDefault, lpFileName );
+}
+
+typedef UINT WINAPI FN_GetPrivateProfileIntW( LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault, LPCWSTR lpFileName );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetPrivateProfileIntW( LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault, LPCWSTR lpFileName )
+{
+    static FN_GetPrivateProfileIntW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetPrivateProfileIntW", &g_Kernel32);
+    return pfn( lpAppName, lpKeyName, nDefault, lpFileName );
+}
+
+typedef DWORD WINAPI FN_GetPrivateProfileStringA( LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpDefault, LPSTR lpReturnedString, DWORD nSize, LPCSTR lpFileName );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetPrivateProfileStringA( LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpDefault, LPSTR lpReturnedString, DWORD nSize, LPCSTR lpFileName )
+{
+    static FN_GetPrivateProfileStringA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetPrivateProfileStringA", &g_Kernel32);
+    return pfn( lpAppName, lpKeyName, lpDefault, lpReturnedString, nSize, lpFileName );
+}
+
+typedef DWORD WINAPI FN_GetPrivateProfileStringW( LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpDefault, LPWSTR lpReturnedString, DWORD nSize, LPCWSTR lpFileName );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetPrivateProfileStringW( LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpDefault, LPWSTR lpReturnedString, DWORD nSize, LPCWSTR lpFileName )
+{
+    static FN_GetPrivateProfileStringW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetPrivateProfileStringW", &g_Kernel32);
+    return pfn( lpAppName, lpKeyName, lpDefault, lpReturnedString, nSize, lpFileName );
+}
+
+typedef BOOL WINAPI FN_WritePrivateProfileStringA( LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpString, LPCSTR lpFileName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WritePrivateProfileStringA( LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpString, LPCSTR lpFileName )
+{
+    static FN_WritePrivateProfileStringA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WritePrivateProfileStringA", &g_Kernel32);
+    return pfn( lpAppName, lpKeyName, lpString, lpFileName );
+}
+
+typedef BOOL WINAPI FN_WritePrivateProfileStringW( LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpString, LPCWSTR lpFileName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WritePrivateProfileStringW( LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpString, LPCWSTR lpFileName )
+{
+    static FN_WritePrivateProfileStringW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WritePrivateProfileStringW", &g_Kernel32);
+    return pfn( lpAppName, lpKeyName, lpString, lpFileName );
+}
+
+typedef DWORD WINAPI FN_GetPrivateProfileSectionA( LPCSTR lpAppName, LPSTR lpReturnedString, DWORD nSize, LPCSTR lpFileName );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetPrivateProfileSectionA( LPCSTR lpAppName, LPSTR lpReturnedString, DWORD nSize, LPCSTR lpFileName )
+{
+    static FN_GetPrivateProfileSectionA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetPrivateProfileSectionA", &g_Kernel32);
+    return pfn( lpAppName, lpReturnedString, nSize, lpFileName );
+}
+
+typedef DWORD WINAPI FN_GetPrivateProfileSectionW( LPCWSTR lpAppName, LPWSTR lpReturnedString, DWORD nSize, LPCWSTR lpFileName );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetPrivateProfileSectionW( LPCWSTR lpAppName, LPWSTR lpReturnedString, DWORD nSize, LPCWSTR lpFileName )
+{
+    static FN_GetPrivateProfileSectionW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetPrivateProfileSectionW", &g_Kernel32);
+    return pfn( lpAppName, lpReturnedString, nSize, lpFileName );
+}
+
+typedef BOOL WINAPI FN_WritePrivateProfileSectionA( LPCSTR lpAppName, LPCSTR lpString, LPCSTR lpFileName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WritePrivateProfileSectionA( LPCSTR lpAppName, LPCSTR lpString, LPCSTR lpFileName )
+{
+    static FN_WritePrivateProfileSectionA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WritePrivateProfileSectionA", &g_Kernel32);
+    return pfn( lpAppName, lpString, lpFileName );
+}
+
+typedef BOOL WINAPI FN_WritePrivateProfileSectionW( LPCWSTR lpAppName, LPCWSTR lpString, LPCWSTR lpFileName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WritePrivateProfileSectionW( LPCWSTR lpAppName, LPCWSTR lpString, LPCWSTR lpFileName )
+{
+    static FN_WritePrivateProfileSectionW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WritePrivateProfileSectionW", &g_Kernel32);
+    return pfn( lpAppName, lpString, lpFileName );
+}
+
+typedef DWORD WINAPI FN_GetPrivateProfileSectionNamesA( LPSTR lpszReturnBuffer, DWORD nSize, LPCSTR lpFileName );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetPrivateProfileSectionNamesA( LPSTR lpszReturnBuffer, DWORD nSize, LPCSTR lpFileName )
+{
+    static FN_GetPrivateProfileSectionNamesA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetPrivateProfileSectionNamesA", &g_Kernel32);
+    return pfn( lpszReturnBuffer, nSize, lpFileName );
+}
+
+typedef DWORD WINAPI FN_GetPrivateProfileSectionNamesW( LPWSTR lpszReturnBuffer, DWORD nSize, LPCWSTR lpFileName );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetPrivateProfileSectionNamesW( LPWSTR lpszReturnBuffer, DWORD nSize, LPCWSTR lpFileName )
+{
+    static FN_GetPrivateProfileSectionNamesW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetPrivateProfileSectionNamesW", &g_Kernel32);
+    return pfn( lpszReturnBuffer, nSize, lpFileName );
+}
+
+typedef BOOL WINAPI FN_GetPrivateProfileStructA( LPCSTR lpszSection, LPCSTR lpszKey, LPVOID lpStruct, UINT uSizeStruct, LPCSTR szFile );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetPrivateProfileStructA( LPCSTR lpszSection, LPCSTR lpszKey, LPVOID lpStruct, UINT uSizeStruct, LPCSTR szFile )
+{
+    static FN_GetPrivateProfileStructA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetPrivateProfileStructA", &g_Kernel32);
+    return pfn( lpszSection, lpszKey, lpStruct, uSizeStruct, szFile );
+}
+
+typedef BOOL WINAPI FN_GetPrivateProfileStructW( LPCWSTR lpszSection, LPCWSTR lpszKey, LPVOID lpStruct, UINT uSizeStruct, LPCWSTR szFile );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetPrivateProfileStructW( LPCWSTR lpszSection, LPCWSTR lpszKey, LPVOID lpStruct, UINT uSizeStruct, LPCWSTR szFile )
+{
+    static FN_GetPrivateProfileStructW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetPrivateProfileStructW", &g_Kernel32);
+    return pfn( lpszSection, lpszKey, lpStruct, uSizeStruct, szFile );
+}
+
+typedef BOOL WINAPI FN_WritePrivateProfileStructA( LPCSTR lpszSection, LPCSTR lpszKey, LPVOID lpStruct, UINT uSizeStruct, LPCSTR szFile );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WritePrivateProfileStructA( LPCSTR lpszSection, LPCSTR lpszKey, LPVOID lpStruct, UINT uSizeStruct, LPCSTR szFile )
+{
+    static FN_WritePrivateProfileStructA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WritePrivateProfileStructA", &g_Kernel32);
+    return pfn( lpszSection, lpszKey, lpStruct, uSizeStruct, szFile );
+}
+
+typedef BOOL WINAPI FN_WritePrivateProfileStructW( LPCWSTR lpszSection, LPCWSTR lpszKey, LPVOID lpStruct, UINT uSizeStruct, LPCWSTR szFile );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WritePrivateProfileStructW( LPCWSTR lpszSection, LPCWSTR lpszKey, LPVOID lpStruct, UINT uSizeStruct, LPCWSTR szFile )
+{
+    static FN_WritePrivateProfileStructW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WritePrivateProfileStructW", &g_Kernel32);
+    return pfn( lpszSection, lpszKey, lpStruct, uSizeStruct, szFile );
+}
+
+typedef UINT WINAPI FN_GetDriveTypeA( LPCSTR lpRootPathName );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetDriveTypeA( LPCSTR lpRootPathName )
+{
+    static FN_GetDriveTypeA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetDriveTypeA", &g_Kernel32);
+    return pfn( lpRootPathName );
+}
+
+typedef UINT WINAPI FN_GetDriveTypeW( LPCWSTR lpRootPathName );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetDriveTypeW( LPCWSTR lpRootPathName )
+{
+    static FN_GetDriveTypeW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetDriveTypeW", &g_Kernel32);
+    return pfn( lpRootPathName );
+}
+
+typedef UINT WINAPI FN_GetSystemDirectoryA( LPSTR lpBuffer, UINT uSize );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetSystemDirectoryA( LPSTR lpBuffer, UINT uSize )
+{
+    static FN_GetSystemDirectoryA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemDirectoryA", &g_Kernel32);
+    return pfn( lpBuffer, uSize );
+}
+
+typedef UINT WINAPI FN_GetSystemDirectoryW( LPWSTR lpBuffer, UINT uSize );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetSystemDirectoryW( LPWSTR lpBuffer, UINT uSize )
+{
+    static FN_GetSystemDirectoryW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemDirectoryW", &g_Kernel32);
+    return pfn( lpBuffer, uSize );
+}
+
+typedef DWORD WINAPI FN_GetTempPathA( DWORD nBufferLength, LPSTR lpBuffer );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetTempPathA( DWORD nBufferLength, LPSTR lpBuffer )
+{
+    static FN_GetTempPathA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetTempPathA", &g_Kernel32);
+    return pfn( nBufferLength, lpBuffer );
+}
+
+typedef DWORD WINAPI FN_GetTempPathW( DWORD nBufferLength, LPWSTR lpBuffer );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetTempPathW( DWORD nBufferLength, LPWSTR lpBuffer )
+{
+    static FN_GetTempPathW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetTempPathW", &g_Kernel32);
+    return pfn( nBufferLength, lpBuffer );
+}
+
+typedef UINT WINAPI FN_GetTempFileNameA( LPCSTR lpPathName, LPCSTR lpPrefixString, UINT uUnique, LPSTR lpTempFileName );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetTempFileNameA( LPCSTR lpPathName, LPCSTR lpPrefixString, UINT uUnique, LPSTR lpTempFileName )
+{
+    static FN_GetTempFileNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetTempFileNameA", &g_Kernel32);
+    return pfn( lpPathName, lpPrefixString, uUnique, lpTempFileName );
+}
+
+typedef UINT WINAPI FN_GetTempFileNameW( LPCWSTR lpPathName, LPCWSTR lpPrefixString, UINT uUnique, LPWSTR lpTempFileName );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetTempFileNameW( LPCWSTR lpPathName, LPCWSTR lpPrefixString, UINT uUnique, LPWSTR lpTempFileName )
+{
+    static FN_GetTempFileNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetTempFileNameW", &g_Kernel32);
+    return pfn( lpPathName, lpPrefixString, uUnique, lpTempFileName );
+}
+
+typedef UINT WINAPI FN_GetWindowsDirectoryA( LPSTR lpBuffer, UINT uSize );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetWindowsDirectoryA( LPSTR lpBuffer, UINT uSize )
+{
+    static FN_GetWindowsDirectoryA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetWindowsDirectoryA", &g_Kernel32);
+    return pfn( lpBuffer, uSize );
+}
+
+typedef UINT WINAPI FN_GetWindowsDirectoryW( LPWSTR lpBuffer, UINT uSize );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetWindowsDirectoryW( LPWSTR lpBuffer, UINT uSize )
+{
+    static FN_GetWindowsDirectoryW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetWindowsDirectoryW", &g_Kernel32);
+    return pfn( lpBuffer, uSize );
+}
+
+typedef UINT WINAPI FN_GetSystemWindowsDirectoryA( LPSTR lpBuffer, UINT uSize );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetSystemWindowsDirectoryA( LPSTR lpBuffer, UINT uSize )
+{
+    static FN_GetSystemWindowsDirectoryA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemWindowsDirectoryA", &g_Kernel32);
+    return pfn( lpBuffer, uSize );
+}
+
+typedef UINT WINAPI FN_GetSystemWindowsDirectoryW( LPWSTR lpBuffer, UINT uSize );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetSystemWindowsDirectoryW( LPWSTR lpBuffer, UINT uSize )
+{
+    static FN_GetSystemWindowsDirectoryW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemWindowsDirectoryW", &g_Kernel32);
+    return pfn( lpBuffer, uSize );
+}
+
+typedef UINT WINAPI FN_GetSystemWow64DirectoryA( LPSTR lpBuffer, UINT uSize );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetSystemWow64DirectoryA( LPSTR lpBuffer, UINT uSize )
+{
+    static FN_GetSystemWow64DirectoryA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemWow64DirectoryA", &g_Kernel32);
+    return pfn( lpBuffer, uSize );
+}
+
+typedef UINT WINAPI FN_GetSystemWow64DirectoryW( LPWSTR lpBuffer, UINT uSize );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetSystemWow64DirectoryW( LPWSTR lpBuffer, UINT uSize )
+{
+    static FN_GetSystemWow64DirectoryW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemWow64DirectoryW", &g_Kernel32);
+    return pfn( lpBuffer, uSize );
+}
+
+typedef BOOLEAN WINAPI FN_Wow64EnableWow64FsRedirection( BOOLEAN Wow64FsEnableRedirection );
+__declspec(dllexport) BOOLEAN WINAPI kPrf2Wrap_Wow64EnableWow64FsRedirection( BOOLEAN Wow64FsEnableRedirection )
+{
+    static FN_Wow64EnableWow64FsRedirection *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Wow64EnableWow64FsRedirection", &g_Kernel32);
+    return pfn( Wow64FsEnableRedirection );
+}
+
+typedef BOOL WINAPI FN_Wow64DisableWow64FsRedirection( PVOID * OldValue );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Wow64DisableWow64FsRedirection( PVOID * OldValue )
+{
+    static FN_Wow64DisableWow64FsRedirection *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Wow64DisableWow64FsRedirection", &g_Kernel32);
+    return pfn( OldValue );
+}
+
+typedef BOOL WINAPI FN_Wow64RevertWow64FsRedirection( PVOID OlValue );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Wow64RevertWow64FsRedirection( PVOID OlValue )
+{
+    static FN_Wow64RevertWow64FsRedirection *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Wow64RevertWow64FsRedirection", &g_Kernel32);
+    return pfn( OlValue );
+}
+
+typedef BOOL WINAPI FN_SetCurrentDirectoryA( LPCSTR lpPathName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetCurrentDirectoryA( LPCSTR lpPathName )
+{
+    static FN_SetCurrentDirectoryA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetCurrentDirectoryA", &g_Kernel32);
+    return pfn( lpPathName );
+}
+
+typedef BOOL WINAPI FN_SetCurrentDirectoryW( LPCWSTR lpPathName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetCurrentDirectoryW( LPCWSTR lpPathName )
+{
+    static FN_SetCurrentDirectoryW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetCurrentDirectoryW", &g_Kernel32);
+    return pfn( lpPathName );
+}
+
+typedef DWORD WINAPI FN_GetCurrentDirectoryA( DWORD nBufferLength, LPSTR lpBuffer );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetCurrentDirectoryA( DWORD nBufferLength, LPSTR lpBuffer )
+{
+    static FN_GetCurrentDirectoryA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCurrentDirectoryA", &g_Kernel32);
+    return pfn( nBufferLength, lpBuffer );
+}
+
+typedef DWORD WINAPI FN_GetCurrentDirectoryW( DWORD nBufferLength, LPWSTR lpBuffer );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetCurrentDirectoryW( DWORD nBufferLength, LPWSTR lpBuffer )
+{
+    static FN_GetCurrentDirectoryW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCurrentDirectoryW", &g_Kernel32);
+    return pfn( nBufferLength, lpBuffer );
+}
+
+typedef BOOL WINAPI FN_SetDllDirectoryA( LPCSTR lpPathName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetDllDirectoryA( LPCSTR lpPathName )
+{
+    static FN_SetDllDirectoryA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetDllDirectoryA", &g_Kernel32);
+    return pfn( lpPathName );
+}
+
+typedef BOOL WINAPI FN_SetDllDirectoryW( LPCWSTR lpPathName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetDllDirectoryW( LPCWSTR lpPathName )
+{
+    static FN_SetDllDirectoryW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetDllDirectoryW", &g_Kernel32);
+    return pfn( lpPathName );
+}
+
+typedef DWORD WINAPI FN_GetDllDirectoryA( DWORD nBufferLength, LPSTR lpBuffer );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetDllDirectoryA( DWORD nBufferLength, LPSTR lpBuffer )
+{
+    static FN_GetDllDirectoryA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetDllDirectoryA", &g_Kernel32);
+    return pfn( nBufferLength, lpBuffer );
+}
+
+typedef DWORD WINAPI FN_GetDllDirectoryW( DWORD nBufferLength, LPWSTR lpBuffer );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetDllDirectoryW( DWORD nBufferLength, LPWSTR lpBuffer )
+{
+    static FN_GetDllDirectoryW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetDllDirectoryW", &g_Kernel32);
+    return pfn( nBufferLength, lpBuffer );
+}
+
+typedef BOOL WINAPI FN_GetDiskFreeSpaceA( LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetDiskFreeSpaceA( LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters )
+{
+    static FN_GetDiskFreeSpaceA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetDiskFreeSpaceA", &g_Kernel32);
+    return pfn( lpRootPathName, lpSectorsPerCluster, lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters );
+}
+
+typedef BOOL WINAPI FN_GetDiskFreeSpaceW( LPCWSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetDiskFreeSpaceW( LPCWSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters )
+{
+    static FN_GetDiskFreeSpaceW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetDiskFreeSpaceW", &g_Kernel32);
+    return pfn( lpRootPathName, lpSectorsPerCluster, lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters );
+}
+
+typedef BOOL WINAPI FN_GetDiskFreeSpaceExA( LPCSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailableToCaller, PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetDiskFreeSpaceExA( LPCSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailableToCaller, PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes )
+{
+    static FN_GetDiskFreeSpaceExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetDiskFreeSpaceExA", &g_Kernel32);
+    return pfn( lpDirectoryName, lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes );
+}
+
+typedef BOOL WINAPI FN_GetDiskFreeSpaceExW( LPCWSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailableToCaller, PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetDiskFreeSpaceExW( LPCWSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailableToCaller, PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes )
+{
+    static FN_GetDiskFreeSpaceExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetDiskFreeSpaceExW", &g_Kernel32);
+    return pfn( lpDirectoryName, lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes );
+}
+
+typedef BOOL WINAPI FN_CreateDirectoryA( LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreateDirectoryA( LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes )
+{
+    static FN_CreateDirectoryA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateDirectoryA", &g_Kernel32);
+    return pfn( lpPathName, lpSecurityAttributes );
+}
+
+typedef BOOL WINAPI FN_CreateDirectoryW( LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreateDirectoryW( LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes )
+{
+    static FN_CreateDirectoryW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateDirectoryW", &g_Kernel32);
+    return pfn( lpPathName, lpSecurityAttributes );
+}
+
+typedef BOOL WINAPI FN_CreateDirectoryExA( LPCSTR lpTemplateDirectory, LPCSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreateDirectoryExA( LPCSTR lpTemplateDirectory, LPCSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes )
+{
+    static FN_CreateDirectoryExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateDirectoryExA", &g_Kernel32);
+    return pfn( lpTemplateDirectory, lpNewDirectory, lpSecurityAttributes );
+}
+
+typedef BOOL WINAPI FN_CreateDirectoryExW( LPCWSTR lpTemplateDirectory, LPCWSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreateDirectoryExW( LPCWSTR lpTemplateDirectory, LPCWSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes )
+{
+    static FN_CreateDirectoryExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateDirectoryExW", &g_Kernel32);
+    return pfn( lpTemplateDirectory, lpNewDirectory, lpSecurityAttributes );
+}
+
+typedef BOOL WINAPI FN_RemoveDirectoryA( LPCSTR lpPathName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_RemoveDirectoryA( LPCSTR lpPathName )
+{
+    static FN_RemoveDirectoryA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RemoveDirectoryA", &g_Kernel32);
+    return pfn( lpPathName );
+}
+
+typedef BOOL WINAPI FN_RemoveDirectoryW( LPCWSTR lpPathName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_RemoveDirectoryW( LPCWSTR lpPathName )
+{
+    static FN_RemoveDirectoryW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RemoveDirectoryW", &g_Kernel32);
+    return pfn( lpPathName );
+}
+
+typedef DWORD WINAPI FN_GetFullPathNameA( LPCSTR lpFileName, DWORD nBufferLength, LPSTR lpBuffer, LPSTR * lpFilePart );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetFullPathNameA( LPCSTR lpFileName, DWORD nBufferLength, LPSTR lpBuffer, LPSTR * lpFilePart )
+{
+    static FN_GetFullPathNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFullPathNameA", &g_Kernel32);
+    return pfn( lpFileName, nBufferLength, lpBuffer, lpFilePart );
+}
+
+typedef DWORD WINAPI FN_GetFullPathNameW( LPCWSTR lpFileName, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR * lpFilePart );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetFullPathNameW( LPCWSTR lpFileName, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR * lpFilePart )
+{
+    static FN_GetFullPathNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFullPathNameW", &g_Kernel32);
+    return pfn( lpFileName, nBufferLength, lpBuffer, lpFilePart );
+}
+
+typedef BOOL WINAPI FN_DefineDosDeviceA( DWORD dwFlags, LPCSTR lpDeviceName, LPCSTR lpTargetPath );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DefineDosDeviceA( DWORD dwFlags, LPCSTR lpDeviceName, LPCSTR lpTargetPath )
+{
+    static FN_DefineDosDeviceA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DefineDosDeviceA", &g_Kernel32);
+    return pfn( dwFlags, lpDeviceName, lpTargetPath );
+}
+
+typedef BOOL WINAPI FN_DefineDosDeviceW( DWORD dwFlags, LPCWSTR lpDeviceName, LPCWSTR lpTargetPath );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DefineDosDeviceW( DWORD dwFlags, LPCWSTR lpDeviceName, LPCWSTR lpTargetPath )
+{
+    static FN_DefineDosDeviceW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DefineDosDeviceW", &g_Kernel32);
+    return pfn( dwFlags, lpDeviceName, lpTargetPath );
+}
+
+typedef DWORD WINAPI FN_QueryDosDeviceA( LPCSTR lpDeviceName, LPSTR lpTargetPath, DWORD ucchMax );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_QueryDosDeviceA( LPCSTR lpDeviceName, LPSTR lpTargetPath, DWORD ucchMax )
+{
+    static FN_QueryDosDeviceA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "QueryDosDeviceA", &g_Kernel32);
+    return pfn( lpDeviceName, lpTargetPath, ucchMax );
+}
+
+typedef DWORD WINAPI FN_QueryDosDeviceW( LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_QueryDosDeviceW( LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax )
+{
+    static FN_QueryDosDeviceW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "QueryDosDeviceW", &g_Kernel32);
+    return pfn( lpDeviceName, lpTargetPath, ucchMax );
+}
+
+typedef HANDLE WINAPI FN_CreateFileA( LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateFileA( LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile )
+{
+    static FN_CreateFileA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateFileA", &g_Kernel32);
+    return pfn( lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile );
+}
+
+typedef HANDLE WINAPI FN_CreateFileW( LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateFileW( LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile )
+{
+    static FN_CreateFileW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateFileW", &g_Kernel32);
+    return pfn( lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile );
+}
+
+typedef HANDLE WINAPI FN_ReOpenFile( HANDLE hOriginalFile, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwFlagsAndAttributes );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_ReOpenFile( HANDLE hOriginalFile, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwFlagsAndAttributes )
+{
+    static FN_ReOpenFile *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReOpenFile", &g_Kernel32);
+    return pfn( hOriginalFile, dwDesiredAccess, dwShareMode, dwFlagsAndAttributes );
+}
+
+typedef BOOL WINAPI FN_SetFileAttributesA( LPCSTR lpFileName, DWORD dwFileAttributes );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetFileAttributesA( LPCSTR lpFileName, DWORD dwFileAttributes )
+{
+    static FN_SetFileAttributesA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetFileAttributesA", &g_Kernel32);
+    return pfn( lpFileName, dwFileAttributes );
+}
+
+typedef BOOL WINAPI FN_SetFileAttributesW( LPCWSTR lpFileName, DWORD dwFileAttributes );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetFileAttributesW( LPCWSTR lpFileName, DWORD dwFileAttributes )
+{
+    static FN_SetFileAttributesW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetFileAttributesW", &g_Kernel32);
+    return pfn( lpFileName, dwFileAttributes );
+}
+
+typedef DWORD WINAPI FN_GetFileAttributesA( LPCSTR lpFileName );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetFileAttributesA( LPCSTR lpFileName )
+{
+    static FN_GetFileAttributesA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFileAttributesA", &g_Kernel32);
+    return pfn( lpFileName );
+}
+
+typedef DWORD WINAPI FN_GetFileAttributesW( LPCWSTR lpFileName );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetFileAttributesW( LPCWSTR lpFileName )
+{
+    static FN_GetFileAttributesW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFileAttributesW", &g_Kernel32);
+    return pfn( lpFileName );
+}
+
+typedef BOOL WINAPI FN_GetFileAttributesExA( LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetFileAttributesExA( LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation )
+{
+    static FN_GetFileAttributesExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFileAttributesExA", &g_Kernel32);
+    return pfn( lpFileName, fInfoLevelId, lpFileInformation );
+}
+
+typedef BOOL WINAPI FN_GetFileAttributesExW( LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetFileAttributesExW( LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation )
+{
+    static FN_GetFileAttributesExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFileAttributesExW", &g_Kernel32);
+    return pfn( lpFileName, fInfoLevelId, lpFileInformation );
+}
+
+typedef DWORD WINAPI FN_GetCompressedFileSizeA( LPCSTR lpFileName, LPDWORD lpFileSizeHigh );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetCompressedFileSizeA( LPCSTR lpFileName, LPDWORD lpFileSizeHigh )
+{
+    static FN_GetCompressedFileSizeA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCompressedFileSizeA", &g_Kernel32);
+    return pfn( lpFileName, lpFileSizeHigh );
+}
+
+typedef DWORD WINAPI FN_GetCompressedFileSizeW( LPCWSTR lpFileName, LPDWORD lpFileSizeHigh );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetCompressedFileSizeW( LPCWSTR lpFileName, LPDWORD lpFileSizeHigh )
+{
+    static FN_GetCompressedFileSizeW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCompressedFileSizeW", &g_Kernel32);
+    return pfn( lpFileName, lpFileSizeHigh );
+}
+
+typedef BOOL WINAPI FN_DeleteFileA( LPCSTR lpFileName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DeleteFileA( LPCSTR lpFileName )
+{
+    static FN_DeleteFileA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DeleteFileA", &g_Kernel32);
+    return pfn( lpFileName );
+}
+
+typedef BOOL WINAPI FN_DeleteFileW( LPCWSTR lpFileName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DeleteFileW( LPCWSTR lpFileName )
+{
+    static FN_DeleteFileW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DeleteFileW", &g_Kernel32);
+    return pfn( lpFileName );
+}
+
+typedef BOOL WINAPI FN_CheckNameLegalDOS8Dot3A( LPCSTR lpName, LPSTR lpOemName, DWORD OemNameSize, PBOOL pbNameContainsSpaces , PBOOL pbNameLegal );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CheckNameLegalDOS8Dot3A( LPCSTR lpName, LPSTR lpOemName, DWORD OemNameSize, PBOOL pbNameContainsSpaces , PBOOL pbNameLegal )
+{
+    static FN_CheckNameLegalDOS8Dot3A *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CheckNameLegalDOS8Dot3A", &g_Kernel32);
+    return pfn( lpName, lpOemName, OemNameSize, pbNameContainsSpaces , pbNameLegal );
+}
+
+typedef BOOL WINAPI FN_CheckNameLegalDOS8Dot3W( LPCWSTR lpName, LPSTR lpOemName, DWORD OemNameSize, PBOOL pbNameContainsSpaces , PBOOL pbNameLegal );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CheckNameLegalDOS8Dot3W( LPCWSTR lpName, LPSTR lpOemName, DWORD OemNameSize, PBOOL pbNameContainsSpaces , PBOOL pbNameLegal )
+{
+    static FN_CheckNameLegalDOS8Dot3W *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CheckNameLegalDOS8Dot3W", &g_Kernel32);
+    return pfn( lpName, lpOemName, OemNameSize, pbNameContainsSpaces , pbNameLegal );
+}
+
+typedef HANDLE WINAPI FN_FindFirstFileExA( LPCSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, LPVOID lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter, DWORD dwAdditionalFlags );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_FindFirstFileExA( LPCSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, LPVOID lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter, DWORD dwAdditionalFlags )
+{
+    static FN_FindFirstFileExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindFirstFileExA", &g_Kernel32);
+    return pfn( lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags );
+}
+
+typedef HANDLE WINAPI FN_FindFirstFileExW( LPCWSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, LPVOID lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter, DWORD dwAdditionalFlags );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_FindFirstFileExW( LPCWSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, LPVOID lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter, DWORD dwAdditionalFlags )
+{
+    static FN_FindFirstFileExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindFirstFileExW", &g_Kernel32);
+    return pfn( lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags );
+}
+
+typedef HANDLE WINAPI FN_FindFirstFileA( LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_FindFirstFileA( LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData )
+{
+    static FN_FindFirstFileA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindFirstFileA", &g_Kernel32);
+    return pfn( lpFileName, lpFindFileData );
+}
+
+typedef HANDLE WINAPI FN_FindFirstFileW( LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_FindFirstFileW( LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData )
+{
+    static FN_FindFirstFileW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindFirstFileW", &g_Kernel32);
+    return pfn( lpFileName, lpFindFileData );
+}
+
+typedef BOOL WINAPI FN_FindNextFileA( HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindNextFileA( HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData )
+{
+    static FN_FindNextFileA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindNextFileA", &g_Kernel32);
+    return pfn( hFindFile, lpFindFileData );
+}
+
+typedef BOOL WINAPI FN_FindNextFileW( HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindNextFileW( HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData )
+{
+    static FN_FindNextFileW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindNextFileW", &g_Kernel32);
+    return pfn( hFindFile, lpFindFileData );
+}
+
+typedef DWORD WINAPI FN_SearchPathA( LPCSTR lpPath, LPCSTR lpFileName, LPCSTR lpExtension, DWORD nBufferLength, LPSTR lpBuffer, LPSTR * lpFilePart );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_SearchPathA( LPCSTR lpPath, LPCSTR lpFileName, LPCSTR lpExtension, DWORD nBufferLength, LPSTR lpBuffer, LPSTR * lpFilePart )
+{
+    static FN_SearchPathA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SearchPathA", &g_Kernel32);
+    return pfn( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart );
+}
+
+typedef DWORD WINAPI FN_SearchPathW( LPCWSTR lpPath, LPCWSTR lpFileName, LPCWSTR lpExtension, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR * lpFilePart );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_SearchPathW( LPCWSTR lpPath, LPCWSTR lpFileName, LPCWSTR lpExtension, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR * lpFilePart )
+{
+    static FN_SearchPathW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SearchPathW", &g_Kernel32);
+    return pfn( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart );
+}
+
+typedef BOOL WINAPI FN_CopyFileA( LPCSTR lpExistingFileName, LPCSTR lpNewFileName, BOOL bFailIfExists );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CopyFileA( LPCSTR lpExistingFileName, LPCSTR lpNewFileName, BOOL bFailIfExists )
+{
+    static FN_CopyFileA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CopyFileA", &g_Kernel32);
+    return pfn( lpExistingFileName, lpNewFileName, bFailIfExists );
+}
+
+typedef BOOL WINAPI FN_CopyFileW( LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CopyFileW( LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists )
+{
+    static FN_CopyFileW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CopyFileW", &g_Kernel32);
+    return pfn( lpExistingFileName, lpNewFileName, bFailIfExists );
+}
+
+typedef BOOL WINAPI FN_CopyFileExA( LPCSTR lpExistingFileName, LPCSTR lpNewFileName, LPPROGRESS_ROUTINE lpProgressRoutine, LPVOID lpData, LPBOOL pbCancel, DWORD dwCopyFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CopyFileExA( LPCSTR lpExistingFileName, LPCSTR lpNewFileName, LPPROGRESS_ROUTINE lpProgressRoutine, LPVOID lpData, LPBOOL pbCancel, DWORD dwCopyFlags )
+{
+    static FN_CopyFileExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CopyFileExA", &g_Kernel32);
+    return pfn( lpExistingFileName, lpNewFileName, lpProgressRoutine, lpData, pbCancel, dwCopyFlags );
+}
+
+typedef BOOL WINAPI FN_CopyFileExW( LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, LPPROGRESS_ROUTINE lpProgressRoutine, LPVOID lpData, LPBOOL pbCancel, DWORD dwCopyFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CopyFileExW( LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, LPPROGRESS_ROUTINE lpProgressRoutine, LPVOID lpData, LPBOOL pbCancel, DWORD dwCopyFlags )
+{
+    static FN_CopyFileExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CopyFileExW", &g_Kernel32);
+    return pfn( lpExistingFileName, lpNewFileName, lpProgressRoutine, lpData, pbCancel, dwCopyFlags );
+}
+
+typedef BOOL WINAPI FN_MoveFileA( LPCSTR lpExistingFileName, LPCSTR lpNewFileName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_MoveFileA( LPCSTR lpExistingFileName, LPCSTR lpNewFileName )
+{
+    static FN_MoveFileA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MoveFileA", &g_Kernel32);
+    return pfn( lpExistingFileName, lpNewFileName );
+}
+
+typedef BOOL WINAPI FN_MoveFileW( LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_MoveFileW( LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName )
+{
+    static FN_MoveFileW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MoveFileW", &g_Kernel32);
+    return pfn( lpExistingFileName, lpNewFileName );
+}
+
+typedef BOOL WINAPI FN_MoveFileExA( LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_MoveFileExA( LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags )
+{
+    static FN_MoveFileExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MoveFileExA", &g_Kernel32);
+    return pfn( lpExistingFileName, lpNewFileName, dwFlags );
+}
+
+typedef BOOL WINAPI FN_MoveFileExW( LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_MoveFileExW( LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags )
+{
+    static FN_MoveFileExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MoveFileExW", &g_Kernel32);
+    return pfn( lpExistingFileName, lpNewFileName, dwFlags );
+}
+
+typedef BOOL WINAPI FN_MoveFileWithProgressA( LPCSTR lpExistingFileName, LPCSTR lpNewFileName, LPPROGRESS_ROUTINE lpProgressRoutine, LPVOID lpData, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_MoveFileWithProgressA( LPCSTR lpExistingFileName, LPCSTR lpNewFileName, LPPROGRESS_ROUTINE lpProgressRoutine, LPVOID lpData, DWORD dwFlags )
+{
+    static FN_MoveFileWithProgressA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MoveFileWithProgressA", &g_Kernel32);
+    return pfn( lpExistingFileName, lpNewFileName, lpProgressRoutine, lpData, dwFlags );
+}
+
+typedef BOOL WINAPI FN_MoveFileWithProgressW( LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, LPPROGRESS_ROUTINE lpProgressRoutine, LPVOID lpData, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_MoveFileWithProgressW( LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, LPPROGRESS_ROUTINE lpProgressRoutine, LPVOID lpData, DWORD dwFlags )
+{
+    static FN_MoveFileWithProgressW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MoveFileWithProgressW", &g_Kernel32);
+    return pfn( lpExistingFileName, lpNewFileName, lpProgressRoutine, lpData, dwFlags );
+}
+
+typedef BOOL WINAPI FN_ReplaceFileA( LPCSTR lpReplacedFileName, LPCSTR lpReplacementFileName, LPCSTR lpBackupFileName, DWORD dwReplaceFlags, LPVOID lpExclude, LPVOID lpReserved );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReplaceFileA( LPCSTR lpReplacedFileName, LPCSTR lpReplacementFileName, LPCSTR lpBackupFileName, DWORD dwReplaceFlags, LPVOID lpExclude, LPVOID lpReserved )
+{
+    static FN_ReplaceFileA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReplaceFileA", &g_Kernel32);
+    return pfn( lpReplacedFileName, lpReplacementFileName, lpBackupFileName, dwReplaceFlags, lpExclude, lpReserved );
+}
+
+typedef BOOL WINAPI FN_ReplaceFileW( LPCWSTR lpReplacedFileName, LPCWSTR lpReplacementFileName, LPCWSTR lpBackupFileName, DWORD dwReplaceFlags, LPVOID lpExclude, LPVOID lpReserved );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReplaceFileW( LPCWSTR lpReplacedFileName, LPCWSTR lpReplacementFileName, LPCWSTR lpBackupFileName, DWORD dwReplaceFlags, LPVOID lpExclude, LPVOID lpReserved )
+{
+    static FN_ReplaceFileW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReplaceFileW", &g_Kernel32);
+    return pfn( lpReplacedFileName, lpReplacementFileName, lpBackupFileName, dwReplaceFlags, lpExclude, lpReserved );
+}
+
+typedef BOOL WINAPI FN_CreateHardLinkA( LPCSTR lpFileName, LPCSTR lpExistingFileName, LPSECURITY_ATTRIBUTES lpSecurityAttributes );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreateHardLinkA( LPCSTR lpFileName, LPCSTR lpExistingFileName, LPSECURITY_ATTRIBUTES lpSecurityAttributes )
+{
+    static FN_CreateHardLinkA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateHardLinkA", &g_Kernel32);
+    return pfn( lpFileName, lpExistingFileName, lpSecurityAttributes );
+}
+
+typedef BOOL WINAPI FN_CreateHardLinkW( LPCWSTR lpFileName, LPCWSTR lpExistingFileName, LPSECURITY_ATTRIBUTES lpSecurityAttributes );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreateHardLinkW( LPCWSTR lpFileName, LPCWSTR lpExistingFileName, LPSECURITY_ATTRIBUTES lpSecurityAttributes )
+{
+    static FN_CreateHardLinkW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateHardLinkW", &g_Kernel32);
+    return pfn( lpFileName, lpExistingFileName, lpSecurityAttributes );
+}
+
+typedef HANDLE WINAPI FN_FindFirstStreamW( LPCWSTR lpFileName, STREAM_INFO_LEVELS InfoLevel, LPVOID lpFindStreamData, DWORD dwFlags );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_FindFirstStreamW( LPCWSTR lpFileName, STREAM_INFO_LEVELS InfoLevel, LPVOID lpFindStreamData, DWORD dwFlags )
+{
+    static FN_FindFirstStreamW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindFirstStreamW", &g_Kernel32);
+    return pfn( lpFileName, InfoLevel, lpFindStreamData, dwFlags );
+}
+
+typedef BOOL APIENTRY FN_FindNextStreamW( HANDLE hFindStream, LPVOID lpFindStreamData );
+__declspec(dllexport) BOOL APIENTRY kPrf2Wrap_FindNextStreamW( HANDLE hFindStream, LPVOID lpFindStreamData )
+{
+    static FN_FindNextStreamW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindNextStreamW", &g_Kernel32);
+    return pfn( hFindStream, lpFindStreamData );
+}
+
+typedef HANDLE WINAPI FN_CreateNamedPipeA( LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateNamedPipeA( LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes )
+{
+    static FN_CreateNamedPipeA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateNamedPipeA", &g_Kernel32);
+    return pfn( lpName, dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize, nInBufferSize, nDefaultTimeOut, lpSecurityAttributes );
+}
+
+typedef HANDLE WINAPI FN_CreateNamedPipeW( LPCWSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateNamedPipeW( LPCWSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes )
+{
+    static FN_CreateNamedPipeW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateNamedPipeW", &g_Kernel32);
+    return pfn( lpName, dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize, nInBufferSize, nDefaultTimeOut, lpSecurityAttributes );
+}
+
+typedef BOOL WINAPI FN_GetNamedPipeHandleStateA( HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances, LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout, LPSTR lpUserName, DWORD nMaxUserNameSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetNamedPipeHandleStateA( HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances, LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout, LPSTR lpUserName, DWORD nMaxUserNameSize )
+{
+    static FN_GetNamedPipeHandleStateA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetNamedPipeHandleStateA", &g_Kernel32);
+    return pfn( hNamedPipe, lpState, lpCurInstances, lpMaxCollectionCount, lpCollectDataTimeout, lpUserName, nMaxUserNameSize );
+}
+
+typedef BOOL WINAPI FN_GetNamedPipeHandleStateW( HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances, LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout, LPWSTR lpUserName, DWORD nMaxUserNameSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetNamedPipeHandleStateW( HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances, LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout, LPWSTR lpUserName, DWORD nMaxUserNameSize )
+{
+    static FN_GetNamedPipeHandleStateW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetNamedPipeHandleStateW", &g_Kernel32);
+    return pfn( hNamedPipe, lpState, lpCurInstances, lpMaxCollectionCount, lpCollectDataTimeout, lpUserName, nMaxUserNameSize );
+}
+
+typedef BOOL WINAPI FN_CallNamedPipeA( LPCSTR lpNamedPipeName, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesRead, DWORD nTimeOut );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CallNamedPipeA( LPCSTR lpNamedPipeName, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesRead, DWORD nTimeOut )
+{
+    static FN_CallNamedPipeA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CallNamedPipeA", &g_Kernel32);
+    return pfn( lpNamedPipeName, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesRead, nTimeOut );
+}
+
+typedef BOOL WINAPI FN_CallNamedPipeW( LPCWSTR lpNamedPipeName, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesRead, DWORD nTimeOut );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CallNamedPipeW( LPCWSTR lpNamedPipeName, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesRead, DWORD nTimeOut )
+{
+    static FN_CallNamedPipeW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CallNamedPipeW", &g_Kernel32);
+    return pfn( lpNamedPipeName, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesRead, nTimeOut );
+}
+
+typedef BOOL WINAPI FN_WaitNamedPipeA( LPCSTR lpNamedPipeName, DWORD nTimeOut );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WaitNamedPipeA( LPCSTR lpNamedPipeName, DWORD nTimeOut )
+{
+    static FN_WaitNamedPipeA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WaitNamedPipeA", &g_Kernel32);
+    return pfn( lpNamedPipeName, nTimeOut );
+}
+
+typedef BOOL WINAPI FN_WaitNamedPipeW( LPCWSTR lpNamedPipeName, DWORD nTimeOut );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WaitNamedPipeW( LPCWSTR lpNamedPipeName, DWORD nTimeOut )
+{
+    static FN_WaitNamedPipeW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WaitNamedPipeW", &g_Kernel32);
+    return pfn( lpNamedPipeName, nTimeOut );
+}
+
+typedef BOOL WINAPI FN_SetVolumeLabelA( LPCSTR lpRootPathName, LPCSTR lpVolumeName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetVolumeLabelA( LPCSTR lpRootPathName, LPCSTR lpVolumeName )
+{
+    static FN_SetVolumeLabelA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetVolumeLabelA", &g_Kernel32);
+    return pfn( lpRootPathName, lpVolumeName );
+}
+
+typedef BOOL WINAPI FN_SetVolumeLabelW( LPCWSTR lpRootPathName, LPCWSTR lpVolumeName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetVolumeLabelW( LPCWSTR lpRootPathName, LPCWSTR lpVolumeName )
+{
+    static FN_SetVolumeLabelW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetVolumeLabelW", &g_Kernel32);
+    return pfn( lpRootPathName, lpVolumeName );
+}
+
+typedef VOID WINAPI FN_SetFileApisToOEM( VOID );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_SetFileApisToOEM( VOID )
+{
+    static FN_SetFileApisToOEM *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetFileApisToOEM", &g_Kernel32);
+    pfn ();
+}
+
+typedef VOID WINAPI FN_SetFileApisToANSI( VOID );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_SetFileApisToANSI( VOID )
+{
+    static FN_SetFileApisToANSI *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetFileApisToANSI", &g_Kernel32);
+    pfn ();
+}
+
+typedef BOOL WINAPI FN_AreFileApisANSI( VOID );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AreFileApisANSI( VOID )
+{
+    static FN_AreFileApisANSI *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AreFileApisANSI", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL WINAPI FN_GetVolumeInformationA( LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetVolumeInformationA( LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize )
+{
+    static FN_GetVolumeInformationA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetVolumeInformationA", &g_Kernel32);
+    return pfn( lpRootPathName, lpVolumeNameBuffer, nVolumeNameSize, lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags, lpFileSystemNameBuffer, nFileSystemNameSize );
+}
+
+typedef BOOL WINAPI FN_GetVolumeInformationW( LPCWSTR lpRootPathName, LPWSTR lpVolumeNameBuffer, DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, LPWSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetVolumeInformationW( LPCWSTR lpRootPathName, LPWSTR lpVolumeNameBuffer, DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, LPWSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize )
+{
+    static FN_GetVolumeInformationW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetVolumeInformationW", &g_Kernel32);
+    return pfn( lpRootPathName, lpVolumeNameBuffer, nVolumeNameSize, lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags, lpFileSystemNameBuffer, nFileSystemNameSize );
+}
+
+typedef BOOL WINAPI FN_CancelIo( HANDLE hFile );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CancelIo( HANDLE hFile )
+{
+    static FN_CancelIo *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CancelIo", &g_Kernel32);
+    return pfn( hFile );
+}
+
+typedef BOOL WINAPI FN_ClearEventLogA( HANDLE hEventLog, LPCSTR lpBackupFileName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ClearEventLogA( HANDLE hEventLog, LPCSTR lpBackupFileName )
+{
+    static FN_ClearEventLogA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ClearEventLogA", &g_Kernel32);
+    return pfn( hEventLog, lpBackupFileName );
+}
+
+typedef BOOL WINAPI FN_ClearEventLogW( HANDLE hEventLog, LPCWSTR lpBackupFileName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ClearEventLogW( HANDLE hEventLog, LPCWSTR lpBackupFileName )
+{
+    static FN_ClearEventLogW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ClearEventLogW", &g_Kernel32);
+    return pfn( hEventLog, lpBackupFileName );
+}
+
+typedef BOOL WINAPI FN_BackupEventLogA( HANDLE hEventLog, LPCSTR lpBackupFileName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_BackupEventLogA( HANDLE hEventLog, LPCSTR lpBackupFileName )
+{
+    static FN_BackupEventLogA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "BackupEventLogA", &g_Kernel32);
+    return pfn( hEventLog, lpBackupFileName );
+}
+
+typedef BOOL WINAPI FN_BackupEventLogW( HANDLE hEventLog, LPCWSTR lpBackupFileName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_BackupEventLogW( HANDLE hEventLog, LPCWSTR lpBackupFileName )
+{
+    static FN_BackupEventLogW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "BackupEventLogW", &g_Kernel32);
+    return pfn( hEventLog, lpBackupFileName );
+}
+
+typedef BOOL WINAPI FN_CloseEventLog( HANDLE hEventLog );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CloseEventLog( HANDLE hEventLog )
+{
+    static FN_CloseEventLog *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CloseEventLog", &g_Kernel32);
+    return pfn( hEventLog );
+}
+
+typedef BOOL WINAPI FN_DeregisterEventSource( HANDLE hEventLog );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DeregisterEventSource( HANDLE hEventLog )
+{
+    static FN_DeregisterEventSource *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DeregisterEventSource", &g_Kernel32);
+    return pfn( hEventLog );
+}
+
+typedef BOOL WINAPI FN_NotifyChangeEventLog( HANDLE hEventLog, HANDLE hEvent );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_NotifyChangeEventLog( HANDLE hEventLog, HANDLE hEvent )
+{
+    static FN_NotifyChangeEventLog *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "NotifyChangeEventLog", &g_Kernel32);
+    return pfn( hEventLog, hEvent );
+}
+
+typedef BOOL WINAPI FN_GetNumberOfEventLogRecords( HANDLE hEventLog, PDWORD NumberOfRecords );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetNumberOfEventLogRecords( HANDLE hEventLog, PDWORD NumberOfRecords )
+{
+    static FN_GetNumberOfEventLogRecords *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetNumberOfEventLogRecords", &g_Kernel32);
+    return pfn( hEventLog, NumberOfRecords );
+}
+
+typedef BOOL WINAPI FN_GetOldestEventLogRecord( HANDLE hEventLog, PDWORD OldestRecord );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetOldestEventLogRecord( HANDLE hEventLog, PDWORD OldestRecord )
+{
+    static FN_GetOldestEventLogRecord *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetOldestEventLogRecord", &g_Kernel32);
+    return pfn( hEventLog, OldestRecord );
+}
+
+typedef HANDLE WINAPI FN_OpenEventLogA( LPCSTR lpUNCServerName, LPCSTR lpSourceName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenEventLogA( LPCSTR lpUNCServerName, LPCSTR lpSourceName )
+{
+    static FN_OpenEventLogA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenEventLogA", &g_Kernel32);
+    return pfn( lpUNCServerName, lpSourceName );
+}
+
+typedef HANDLE WINAPI FN_OpenEventLogW( LPCWSTR lpUNCServerName, LPCWSTR lpSourceName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenEventLogW( LPCWSTR lpUNCServerName, LPCWSTR lpSourceName )
+{
+    static FN_OpenEventLogW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenEventLogW", &g_Kernel32);
+    return pfn( lpUNCServerName, lpSourceName );
+}
+
+typedef HANDLE WINAPI FN_RegisterEventSourceA( LPCSTR lpUNCServerName, LPCSTR lpSourceName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_RegisterEventSourceA( LPCSTR lpUNCServerName, LPCSTR lpSourceName )
+{
+    static FN_RegisterEventSourceA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RegisterEventSourceA", &g_Kernel32);
+    return pfn( lpUNCServerName, lpSourceName );
+}
+
+typedef HANDLE WINAPI FN_RegisterEventSourceW( LPCWSTR lpUNCServerName, LPCWSTR lpSourceName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_RegisterEventSourceW( LPCWSTR lpUNCServerName, LPCWSTR lpSourceName )
+{
+    static FN_RegisterEventSourceW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RegisterEventSourceW", &g_Kernel32);
+    return pfn( lpUNCServerName, lpSourceName );
+}
+
+typedef HANDLE WINAPI FN_OpenBackupEventLogA( LPCSTR lpUNCServerName, LPCSTR lpFileName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenBackupEventLogA( LPCSTR lpUNCServerName, LPCSTR lpFileName )
+{
+    static FN_OpenBackupEventLogA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenBackupEventLogA", &g_Kernel32);
+    return pfn( lpUNCServerName, lpFileName );
+}
+
+typedef HANDLE WINAPI FN_OpenBackupEventLogW( LPCWSTR lpUNCServerName, LPCWSTR lpFileName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenBackupEventLogW( LPCWSTR lpUNCServerName, LPCWSTR lpFileName )
+{
+    static FN_OpenBackupEventLogW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenBackupEventLogW", &g_Kernel32);
+    return pfn( lpUNCServerName, lpFileName );
+}
+
+typedef BOOL WINAPI FN_ReadEventLogA( HANDLE hEventLog, DWORD dwReadFlags, DWORD dwRecordOffset, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, DWORD * pnBytesRead, DWORD * pnMinNumberOfBytesNeeded );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadEventLogA( HANDLE hEventLog, DWORD dwReadFlags, DWORD dwRecordOffset, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, DWORD * pnBytesRead, DWORD * pnMinNumberOfBytesNeeded )
+{
+    static FN_ReadEventLogA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadEventLogA", &g_Kernel32);
+    return pfn( hEventLog, dwReadFlags, dwRecordOffset, lpBuffer, nNumberOfBytesToRead, pnBytesRead, pnMinNumberOfBytesNeeded );
+}
+
+typedef BOOL WINAPI FN_ReadEventLogW( HANDLE hEventLog, DWORD dwReadFlags, DWORD dwRecordOffset, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, DWORD * pnBytesRead, DWORD * pnMinNumberOfBytesNeeded );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadEventLogW( HANDLE hEventLog, DWORD dwReadFlags, DWORD dwRecordOffset, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, DWORD * pnBytesRead, DWORD * pnMinNumberOfBytesNeeded )
+{
+    static FN_ReadEventLogW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadEventLogW", &g_Kernel32);
+    return pfn( hEventLog, dwReadFlags, dwRecordOffset, lpBuffer, nNumberOfBytesToRead, pnBytesRead, pnMinNumberOfBytesNeeded );
+}
+
+typedef BOOL WINAPI FN_ReportEventA( HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid, WORD wNumStrings, DWORD dwDataSize, LPCSTR * lpStrings, LPVOID lpRawData );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReportEventA( HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid, WORD wNumStrings, DWORD dwDataSize, LPCSTR * lpStrings, LPVOID lpRawData )
+{
+    static FN_ReportEventA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReportEventA", &g_Kernel32);
+    return pfn( hEventLog, wType, wCategory, dwEventID, lpUserSid, wNumStrings, dwDataSize, lpStrings, lpRawData );
+}
+
+typedef BOOL WINAPI FN_ReportEventW( HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid, WORD wNumStrings, DWORD dwDataSize, LPCWSTR * lpStrings, LPVOID lpRawData );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReportEventW( HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid, WORD wNumStrings, DWORD dwDataSize, LPCWSTR * lpStrings, LPVOID lpRawData )
+{
+    static FN_ReportEventW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReportEventW", &g_Kernel32);
+    return pfn( hEventLog, wType, wCategory, dwEventID, lpUserSid, wNumStrings, dwDataSize, lpStrings, lpRawData );
+}
+
+typedef BOOL WINAPI FN_GetEventLogInformation( HANDLE hEventLog, DWORD dwInfoLevel, LPVOID lpBuffer, DWORD cbBufSize, LPDWORD pcbBytesNeeded );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetEventLogInformation( HANDLE hEventLog, DWORD dwInfoLevel, LPVOID lpBuffer, DWORD cbBufSize, LPDWORD pcbBytesNeeded )
+{
+    static FN_GetEventLogInformation *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetEventLogInformation", &g_Kernel32);
+    return pfn( hEventLog, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded );
+}
+
+typedef BOOL WINAPI FN_DuplicateToken( HANDLE ExistingTokenHandle, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, PHANDLE DuplicateTokenHandle );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DuplicateToken( HANDLE ExistingTokenHandle, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, PHANDLE DuplicateTokenHandle )
+{
+    static FN_DuplicateToken *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DuplicateToken", &g_Kernel32);
+    return pfn( ExistingTokenHandle, ImpersonationLevel, DuplicateTokenHandle );
+}
+
+typedef BOOL WINAPI FN_GetKernelObjectSecurity( HANDLE Handle, SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetKernelObjectSecurity( HANDLE Handle, SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded )
+{
+    static FN_GetKernelObjectSecurity *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetKernelObjectSecurity", &g_Kernel32);
+    return pfn( Handle, RequestedInformation, pSecurityDescriptor, nLength, lpnLengthNeeded );
+}
+
+typedef BOOL WINAPI FN_ImpersonateNamedPipeClient( HANDLE hNamedPipe );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ImpersonateNamedPipeClient( HANDLE hNamedPipe )
+{
+    static FN_ImpersonateNamedPipeClient *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ImpersonateNamedPipeClient", &g_Kernel32);
+    return pfn( hNamedPipe );
+}
+
+typedef BOOL WINAPI FN_ImpersonateSelf( SECURITY_IMPERSONATION_LEVEL ImpersonationLevel );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ImpersonateSelf( SECURITY_IMPERSONATION_LEVEL ImpersonationLevel )
+{
+    static FN_ImpersonateSelf *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ImpersonateSelf", &g_Kernel32);
+    return pfn( ImpersonationLevel );
+}
+
+typedef BOOL WINAPI FN_RevertToSelf( VOID );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_RevertToSelf( VOID )
+{
+    static FN_RevertToSelf *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RevertToSelf", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL APIENTRY FN_SetThreadToken( PHANDLE Thread, HANDLE Token );
+__declspec(dllexport) BOOL APIENTRY kPrf2Wrap_SetThreadToken( PHANDLE Thread, HANDLE Token )
+{
+    static FN_SetThreadToken *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetThreadToken", &g_Kernel32);
+    return pfn( Thread, Token );
+}
+
+typedef BOOL WINAPI FN_AccessCheck( PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET PrivilegeSet, LPDWORD PrivilegeSetLength, LPDWORD GrantedAccess, LPBOOL AccessStatus );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AccessCheck( PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET PrivilegeSet, LPDWORD PrivilegeSetLength, LPDWORD GrantedAccess, LPBOOL AccessStatus )
+{
+    static FN_AccessCheck *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AccessCheck", &g_Kernel32);
+    return pfn( pSecurityDescriptor, ClientToken, DesiredAccess, GenericMapping, PrivilegeSet, PrivilegeSetLength, GrantedAccess, AccessStatus );
+}
+
+typedef BOOL WINAPI FN_AccessCheckByType( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID PrincipalSelfSid, HANDLE ClientToken, DWORD DesiredAccess, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET PrivilegeSet, LPDWORD PrivilegeSetLength, LPDWORD GrantedAccess, LPBOOL AccessStatus );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AccessCheckByType( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID PrincipalSelfSid, HANDLE ClientToken, DWORD DesiredAccess, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET PrivilegeSet, LPDWORD PrivilegeSetLength, LPDWORD GrantedAccess, LPBOOL AccessStatus )
+{
+    static FN_AccessCheckByType *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AccessCheckByType", &g_Kernel32);
+    return pfn( pSecurityDescriptor, PrincipalSelfSid, ClientToken, DesiredAccess, ObjectTypeList, ObjectTypeListLength, GenericMapping, PrivilegeSet, PrivilegeSetLength, GrantedAccess, AccessStatus );
+}
+
+typedef BOOL WINAPI FN_AccessCheckByTypeResultList( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID PrincipalSelfSid, HANDLE ClientToken, DWORD DesiredAccess, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET PrivilegeSet, LPDWORD PrivilegeSetLength, LPDWORD GrantedAccessList, LPDWORD AccessStatusList );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AccessCheckByTypeResultList( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID PrincipalSelfSid, HANDLE ClientToken, DWORD DesiredAccess, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET PrivilegeSet, LPDWORD PrivilegeSetLength, LPDWORD GrantedAccessList, LPDWORD AccessStatusList )
+{
+    static FN_AccessCheckByTypeResultList *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AccessCheckByTypeResultList", &g_Kernel32);
+    return pfn( pSecurityDescriptor, PrincipalSelfSid, ClientToken, DesiredAccess, ObjectTypeList, ObjectTypeListLength, GenericMapping, PrivilegeSet, PrivilegeSetLength, GrantedAccessList, AccessStatusList );
+}
+
+typedef BOOL WINAPI FN_OpenProcessToken( HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_OpenProcessToken( HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle )
+{
+    static FN_OpenProcessToken *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenProcessToken", &g_Kernel32);
+    return pfn( ProcessHandle, DesiredAccess, TokenHandle );
+}
+
+typedef BOOL WINAPI FN_OpenThreadToken( HANDLE ThreadHandle, DWORD DesiredAccess, BOOL OpenAsSelf, PHANDLE TokenHandle );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_OpenThreadToken( HANDLE ThreadHandle, DWORD DesiredAccess, BOOL OpenAsSelf, PHANDLE TokenHandle )
+{
+    static FN_OpenThreadToken *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenThreadToken", &g_Kernel32);
+    return pfn( ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle );
+}
+
+typedef BOOL WINAPI FN_GetTokenInformation( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetTokenInformation( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength )
+{
+    static FN_GetTokenInformation *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetTokenInformation", &g_Kernel32);
+    return pfn( TokenHandle, TokenInformationClass, TokenInformation, TokenInformationLength, ReturnLength );
+}
+
+typedef BOOL WINAPI FN_SetTokenInformation( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetTokenInformation( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength )
+{
+    static FN_SetTokenInformation *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetTokenInformation", &g_Kernel32);
+    return pfn( TokenHandle, TokenInformationClass, TokenInformation, TokenInformationLength );
+}
+
+typedef BOOL WINAPI FN_AdjustTokenPrivileges( HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AdjustTokenPrivileges( HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength )
+{
+    static FN_AdjustTokenPrivileges *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AdjustTokenPrivileges", &g_Kernel32);
+    return pfn( TokenHandle, DisableAllPrivileges, NewState, BufferLength, PreviousState, ReturnLength );
+}
+
+typedef BOOL WINAPI FN_AdjustTokenGroups( HANDLE TokenHandle, BOOL ResetToDefault, PTOKEN_GROUPS NewState, DWORD BufferLength, PTOKEN_GROUPS PreviousState, PDWORD ReturnLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AdjustTokenGroups( HANDLE TokenHandle, BOOL ResetToDefault, PTOKEN_GROUPS NewState, DWORD BufferLength, PTOKEN_GROUPS PreviousState, PDWORD ReturnLength )
+{
+    static FN_AdjustTokenGroups *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AdjustTokenGroups", &g_Kernel32);
+    return pfn( TokenHandle, ResetToDefault, NewState, BufferLength, PreviousState, ReturnLength );
+}
+
+typedef BOOL WINAPI FN_PrivilegeCheck( HANDLE ClientToken, PPRIVILEGE_SET RequiredPrivileges, LPBOOL pfResult );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_PrivilegeCheck( HANDLE ClientToken, PPRIVILEGE_SET RequiredPrivileges, LPBOOL pfResult )
+{
+    static FN_PrivilegeCheck *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "PrivilegeCheck", &g_Kernel32);
+    return pfn( ClientToken, RequiredPrivileges, pfResult );
+}
+
+typedef BOOL WINAPI FN_AccessCheckAndAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, LPSTR ObjectTypeName, LPSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPBOOL AccessStatus, LPBOOL pfGenerateOnClose );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AccessCheckAndAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, LPSTR ObjectTypeName, LPSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPBOOL AccessStatus, LPBOOL pfGenerateOnClose )
+{
+    static FN_AccessCheckAndAuditAlarmA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AccessCheckAndAuditAlarmA", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, ObjectTypeName, ObjectName, SecurityDescriptor, DesiredAccess, GenericMapping, ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose );
+}
+
+typedef BOOL WINAPI FN_AccessCheckAndAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, LPWSTR ObjectTypeName, LPWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPBOOL AccessStatus, LPBOOL pfGenerateOnClose );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AccessCheckAndAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, LPWSTR ObjectTypeName, LPWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPBOOL AccessStatus, LPBOOL pfGenerateOnClose )
+{
+    static FN_AccessCheckAndAuditAlarmW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AccessCheckAndAuditAlarmW", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, ObjectTypeName, ObjectName, SecurityDescriptor, DesiredAccess, GenericMapping, ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose );
+}
+
+typedef BOOL WINAPI FN_AccessCheckByTypeAndAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, LPCSTR ObjectTypeName, LPCSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, DWORD DesiredAccess, AUDIT_EVENT_TYPE AuditType, DWORD Flags, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPBOOL AccessStatus, LPBOOL pfGenerateOnClose );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AccessCheckByTypeAndAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, LPCSTR ObjectTypeName, LPCSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, DWORD DesiredAccess, AUDIT_EVENT_TYPE AuditType, DWORD Flags, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPBOOL AccessStatus, LPBOOL pfGenerateOnClose )
+{
+    static FN_AccessCheckByTypeAndAuditAlarmA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AccessCheckByTypeAndAuditAlarmA", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, ObjectTypeName, ObjectName, SecurityDescriptor, PrincipalSelfSid, DesiredAccess, AuditType, Flags, ObjectTypeList, ObjectTypeListLength, GenericMapping, ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose );
+}
+
+typedef BOOL WINAPI FN_AccessCheckByTypeAndAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, LPCWSTR ObjectTypeName, LPCWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, DWORD DesiredAccess, AUDIT_EVENT_TYPE AuditType, DWORD Flags, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPBOOL AccessStatus, LPBOOL pfGenerateOnClose );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AccessCheckByTypeAndAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, LPCWSTR ObjectTypeName, LPCWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, DWORD DesiredAccess, AUDIT_EVENT_TYPE AuditType, DWORD Flags, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPBOOL AccessStatus, LPBOOL pfGenerateOnClose )
+{
+    static FN_AccessCheckByTypeAndAuditAlarmW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AccessCheckByTypeAndAuditAlarmW", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, ObjectTypeName, ObjectName, SecurityDescriptor, PrincipalSelfSid, DesiredAccess, AuditType, Flags, ObjectTypeList, ObjectTypeListLength, GenericMapping, ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose );
+}
+
+typedef BOOL WINAPI FN_AccessCheckByTypeResultListAndAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, LPCSTR ObjectTypeName, LPCSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, DWORD DesiredAccess, AUDIT_EVENT_TYPE AuditType, DWORD Flags, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPDWORD AccessStatusList, LPBOOL pfGenerateOnClose );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AccessCheckByTypeResultListAndAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, LPCSTR ObjectTypeName, LPCSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, DWORD DesiredAccess, AUDIT_EVENT_TYPE AuditType, DWORD Flags, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPDWORD AccessStatusList, LPBOOL pfGenerateOnClose )
+{
+    static FN_AccessCheckByTypeResultListAndAuditAlarmA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AccessCheckByTypeResultListAndAuditAlarmA", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, ObjectTypeName, ObjectName, SecurityDescriptor, PrincipalSelfSid, DesiredAccess, AuditType, Flags, ObjectTypeList, ObjectTypeListLength, GenericMapping, ObjectCreation, GrantedAccess, AccessStatusList, pfGenerateOnClose );
+}
+
+typedef BOOL WINAPI FN_AccessCheckByTypeResultListAndAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, LPCWSTR ObjectTypeName, LPCWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, DWORD DesiredAccess, AUDIT_EVENT_TYPE AuditType, DWORD Flags, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPDWORD AccessStatusList, LPBOOL pfGenerateOnClose );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AccessCheckByTypeResultListAndAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, LPCWSTR ObjectTypeName, LPCWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, DWORD DesiredAccess, AUDIT_EVENT_TYPE AuditType, DWORD Flags, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPDWORD AccessStatusList, LPBOOL pfGenerateOnClose )
+{
+    static FN_AccessCheckByTypeResultListAndAuditAlarmW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AccessCheckByTypeResultListAndAuditAlarmW", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, ObjectTypeName, ObjectName, SecurityDescriptor, PrincipalSelfSid, DesiredAccess, AuditType, Flags, ObjectTypeList, ObjectTypeListLength, GenericMapping, ObjectCreation, GrantedAccess, AccessStatusList, pfGenerateOnClose );
+}
+
+typedef BOOL WINAPI FN_AccessCheckByTypeResultListAndAuditAlarmByHandleA( LPCSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken, LPCSTR ObjectTypeName, LPCSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, DWORD DesiredAccess, AUDIT_EVENT_TYPE AuditType, DWORD Flags, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPDWORD AccessStatusList, LPBOOL pfGenerateOnClose );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AccessCheckByTypeResultListAndAuditAlarmByHandleA( LPCSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken, LPCSTR ObjectTypeName, LPCSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, DWORD DesiredAccess, AUDIT_EVENT_TYPE AuditType, DWORD Flags, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPDWORD AccessStatusList, LPBOO [...]
+{
+    static FN_AccessCheckByTypeResultListAndAuditAlarmByHandleA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AccessCheckByTypeResultListAndAuditAlarmByHandleA", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, ClientToken, ObjectTypeName, ObjectName, SecurityDescriptor, PrincipalSelfSid, DesiredAccess, AuditType, Flags, ObjectTypeList, ObjectTypeListLength, GenericMapping, ObjectCreation, GrantedAccess, AccessStatusList, pfGenerateOnClose );
+}
+
+typedef BOOL WINAPI FN_AccessCheckByTypeResultListAndAuditAlarmByHandleW( LPCWSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken, LPCWSTR ObjectTypeName, LPCWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, DWORD DesiredAccess, AUDIT_EVENT_TYPE AuditType, DWORD Flags, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPDWORD AccessStatusList, LPBOOL pfGenerateOnClose );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AccessCheckByTypeResultListAndAuditAlarmByHandleW( LPCWSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken, LPCWSTR ObjectTypeName, LPCWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, DWORD DesiredAccess, AUDIT_EVENT_TYPE AuditType, DWORD Flags, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPDWORD AccessStatusList, LP [...]
+{
+    static FN_AccessCheckByTypeResultListAndAuditAlarmByHandleW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AccessCheckByTypeResultListAndAuditAlarmByHandleW", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, ClientToken, ObjectTypeName, ObjectName, SecurityDescriptor, PrincipalSelfSid, DesiredAccess, AuditType, Flags, ObjectTypeList, ObjectTypeListLength, GenericMapping, ObjectCreation, GrantedAccess, AccessStatusList, pfGenerateOnClose );
+}
+
+typedef BOOL WINAPI FN_ObjectOpenAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, LPSTR ObjectTypeName, LPSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess, DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted, LPBOOL GenerateOnClose );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ObjectOpenAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, LPSTR ObjectTypeName, LPSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess, DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted, LPBOOL GenerateOnClose )
+{
+    static FN_ObjectOpenAuditAlarmA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ObjectOpenAuditAlarmA", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, ObjectTypeName, ObjectName, pSecurityDescriptor, ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted, GenerateOnClose );
+}
+
+typedef BOOL WINAPI FN_ObjectOpenAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, LPWSTR ObjectTypeName, LPWSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess, DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted, LPBOOL GenerateOnClose );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ObjectOpenAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, LPWSTR ObjectTypeName, LPWSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess, DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted, LPBOOL GenerateOnClose )
+{
+    static FN_ObjectOpenAuditAlarmW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ObjectOpenAuditAlarmW", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, ObjectTypeName, ObjectName, pSecurityDescriptor, ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted, GenerateOnClose );
+}
+
+typedef BOOL WINAPI FN_ObjectPrivilegeAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken, DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ObjectPrivilegeAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken, DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted )
+{
+    static FN_ObjectPrivilegeAuditAlarmA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ObjectPrivilegeAuditAlarmA", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, ClientToken, DesiredAccess, Privileges, AccessGranted );
+}
+
+typedef BOOL WINAPI FN_ObjectPrivilegeAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken, DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ObjectPrivilegeAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken, DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted )
+{
+    static FN_ObjectPrivilegeAuditAlarmW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ObjectPrivilegeAuditAlarmW", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, ClientToken, DesiredAccess, Privileges, AccessGranted );
+}
+
+typedef BOOL WINAPI FN_ObjectCloseAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ObjectCloseAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose )
+{
+    static FN_ObjectCloseAuditAlarmA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ObjectCloseAuditAlarmA", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, GenerateOnClose );
+}
+
+typedef BOOL WINAPI FN_ObjectCloseAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ObjectCloseAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose )
+{
+    static FN_ObjectCloseAuditAlarmW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ObjectCloseAuditAlarmW", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, GenerateOnClose );
+}
+
+typedef BOOL WINAPI FN_ObjectDeleteAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ObjectDeleteAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose )
+{
+    static FN_ObjectDeleteAuditAlarmA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ObjectDeleteAuditAlarmA", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, GenerateOnClose );
+}
+
+typedef BOOL WINAPI FN_ObjectDeleteAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ObjectDeleteAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose )
+{
+    static FN_ObjectDeleteAuditAlarmW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ObjectDeleteAuditAlarmW", &g_Kernel32);
+    return pfn( SubsystemName, HandleId, GenerateOnClose );
+}
+
+typedef BOOL WINAPI FN_PrivilegedServiceAuditAlarmA( LPCSTR SubsystemName, LPCSTR ServiceName, HANDLE ClientToken, PPRIVILEGE_SET Privileges, BOOL AccessGranted );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_PrivilegedServiceAuditAlarmA( LPCSTR SubsystemName, LPCSTR ServiceName, HANDLE ClientToken, PPRIVILEGE_SET Privileges, BOOL AccessGranted )
+{
+    static FN_PrivilegedServiceAuditAlarmA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "PrivilegedServiceAuditAlarmA", &g_Kernel32);
+    return pfn( SubsystemName, ServiceName, ClientToken, Privileges, AccessGranted );
+}
+
+typedef BOOL WINAPI FN_PrivilegedServiceAuditAlarmW( LPCWSTR SubsystemName, LPCWSTR ServiceName, HANDLE ClientToken, PPRIVILEGE_SET Privileges, BOOL AccessGranted );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_PrivilegedServiceAuditAlarmW( LPCWSTR SubsystemName, LPCWSTR ServiceName, HANDLE ClientToken, PPRIVILEGE_SET Privileges, BOOL AccessGranted )
+{
+    static FN_PrivilegedServiceAuditAlarmW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "PrivilegedServiceAuditAlarmW", &g_Kernel32);
+    return pfn( SubsystemName, ServiceName, ClientToken, Privileges, AccessGranted );
+}
+
+typedef BOOL WINAPI FN_IsWellKnownSid( PSID pSid, WELL_KNOWN_SID_TYPE WellKnownSidType );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsWellKnownSid( PSID pSid, WELL_KNOWN_SID_TYPE WellKnownSidType )
+{
+    static FN_IsWellKnownSid *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsWellKnownSid", &g_Kernel32);
+    return pfn( pSid, WellKnownSidType );
+}
+
+typedef BOOL WINAPI FN_CreateWellKnownSid( WELL_KNOWN_SID_TYPE WellKnownSidType, PSID DomainSid, PSID pSid, DWORD * cbSid );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreateWellKnownSid( WELL_KNOWN_SID_TYPE WellKnownSidType, PSID DomainSid, PSID pSid, DWORD * cbSid )
+{
+    static FN_CreateWellKnownSid *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateWellKnownSid", &g_Kernel32);
+    return pfn( WellKnownSidType, DomainSid, pSid, cbSid );
+}
+
+typedef BOOL WINAPI FN_EqualDomainSid( PSID pSid1, PSID pSid2, BOOL * pfEqual );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EqualDomainSid( PSID pSid1, PSID pSid2, BOOL * pfEqual )
+{
+    static FN_EqualDomainSid *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EqualDomainSid", &g_Kernel32);
+    return pfn( pSid1, pSid2, pfEqual );
+}
+
+typedef BOOL WINAPI FN_GetWindowsAccountDomainSid( PSID pSid, PSID pDomainSid, DWORD * cbDomainSid );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetWindowsAccountDomainSid( PSID pSid, PSID pDomainSid, DWORD * cbDomainSid )
+{
+    static FN_GetWindowsAccountDomainSid *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetWindowsAccountDomainSid", &g_Kernel32);
+    return pfn( pSid, pDomainSid, cbDomainSid );
+}
+
+typedef BOOL WINAPI FN_IsValidSid( PSID pSid );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsValidSid( PSID pSid )
+{
+    static FN_IsValidSid *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsValidSid", &g_Kernel32);
+    return pfn( pSid );
+}
+
+typedef BOOL WINAPI FN_EqualSid( PSID pSid1, PSID pSid2 );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EqualSid( PSID pSid1, PSID pSid2 )
+{
+    static FN_EqualSid *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EqualSid", &g_Kernel32);
+    return pfn( pSid1, pSid2 );
+}
+
+typedef BOOL WINAPI FN_EqualPrefixSid( PSID pSid1, PSID pSid2 );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EqualPrefixSid( PSID pSid1, PSID pSid2 )
+{
+    static FN_EqualPrefixSid *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EqualPrefixSid", &g_Kernel32);
+    return pfn( pSid1, pSid2 );
+}
+
+typedef DWORD WINAPI FN_GetSidLengthRequired( UCHAR nSubAuthorityCount );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetSidLengthRequired( UCHAR nSubAuthorityCount )
+{
+    static FN_GetSidLengthRequired *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSidLengthRequired", &g_Kernel32);
+    return pfn( nSubAuthorityCount );
+}
+
+typedef BOOL WINAPI FN_AllocateAndInitializeSid( PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, BYTE nSubAuthorityCount, DWORD nSubAuthority0, DWORD nSubAuthority1, DWORD nSubAuthority2, DWORD nSubAuthority3, DWORD nSubAuthority4, DWORD nSubAuthority5, DWORD nSubAuthority6, DWORD nSubAuthority7, PSID * pSid );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AllocateAndInitializeSid( PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, BYTE nSubAuthorityCount, DWORD nSubAuthority0, DWORD nSubAuthority1, DWORD nSubAuthority2, DWORD nSubAuthority3, DWORD nSubAuthority4, DWORD nSubAuthority5, DWORD nSubAuthority6, DWORD nSubAuthority7, PSID * pSid )
+{
+    static FN_AllocateAndInitializeSid *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AllocateAndInitializeSid", &g_Kernel32);
+    return pfn( pIdentifierAuthority, nSubAuthorityCount, nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3, nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid );
+}
+
+typedef PVOID WINAPI FN_FreeSid( PSID pSid );
+__declspec(dllexport) PVOID WINAPI kPrf2Wrap_FreeSid( PSID pSid )
+{
+    static FN_FreeSid *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FreeSid", &g_Kernel32);
+    return pfn( pSid );
+}
+
+typedef BOOL WINAPI FN_InitializeSid( PSID Sid, PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, BYTE nSubAuthorityCount );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_InitializeSid( PSID Sid, PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, BYTE nSubAuthorityCount )
+{
+    static FN_InitializeSid *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InitializeSid", &g_Kernel32);
+    return pfn( Sid, pIdentifierAuthority, nSubAuthorityCount );
+}
+
+typedef PSID_IDENTIFIER_AUTHORITY WINAPI FN_GetSidIdentifierAuthority( PSID pSid );
+__declspec(dllexport) PSID_IDENTIFIER_AUTHORITY WINAPI kPrf2Wrap_GetSidIdentifierAuthority( PSID pSid )
+{
+    static FN_GetSidIdentifierAuthority *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSidIdentifierAuthority", &g_Kernel32);
+    return pfn( pSid );
+}
+
+typedef PDWORD WINAPI FN_GetSidSubAuthority( PSID pSid, DWORD nSubAuthority );
+__declspec(dllexport) PDWORD WINAPI kPrf2Wrap_GetSidSubAuthority( PSID pSid, DWORD nSubAuthority )
+{
+    static FN_GetSidSubAuthority *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSidSubAuthority", &g_Kernel32);
+    return pfn( pSid, nSubAuthority );
+}
+
+typedef PUCHAR WINAPI FN_GetSidSubAuthorityCount( PSID pSid );
+__declspec(dllexport) PUCHAR WINAPI kPrf2Wrap_GetSidSubAuthorityCount( PSID pSid )
+{
+    static FN_GetSidSubAuthorityCount *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSidSubAuthorityCount", &g_Kernel32);
+    return pfn( pSid );
+}
+
+typedef DWORD WINAPI FN_GetLengthSid( PSID pSid );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetLengthSid( PSID pSid )
+{
+    static FN_GetLengthSid *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetLengthSid", &g_Kernel32);
+    return pfn( pSid );
+}
+
+typedef BOOL WINAPI FN_CopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
+{
+    static FN_CopySid *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CopySid", &g_Kernel32);
+    return pfn( nDestinationSidLength, pDestinationSid, pSourceSid );
+}
+
+typedef BOOL WINAPI FN_AreAllAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AreAllAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
+{
+    static FN_AreAllAccessesGranted *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AreAllAccessesGranted", &g_Kernel32);
+    return pfn( GrantedAccess, DesiredAccess );
+}
+
+typedef BOOL WINAPI FN_AreAnyAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AreAnyAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
+{
+    static FN_AreAnyAccessesGranted *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AreAnyAccessesGranted", &g_Kernel32);
+    return pfn( GrantedAccess, DesiredAccess );
+}
+
+typedef VOID WINAPI FN_MapGenericMask( PDWORD AccessMask, PGENERIC_MAPPING GenericMapping );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_MapGenericMask( PDWORD AccessMask, PGENERIC_MAPPING GenericMapping )
+{
+    static FN_MapGenericMask *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MapGenericMask", &g_Kernel32);
+    pfn( AccessMask, GenericMapping );
+}
+
+typedef BOOL WINAPI FN_IsValidAcl( PACL pAcl );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsValidAcl( PACL pAcl )
+{
+    static FN_IsValidAcl *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsValidAcl", &g_Kernel32);
+    return pfn( pAcl );
+}
+
+typedef BOOL WINAPI FN_InitializeAcl( PACL pAcl, DWORD nAclLength, DWORD dwAclRevision );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_InitializeAcl( PACL pAcl, DWORD nAclLength, DWORD dwAclRevision )
+{
+    static FN_InitializeAcl *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InitializeAcl", &g_Kernel32);
+    return pfn( pAcl, nAclLength, dwAclRevision );
+}
+
+typedef BOOL WINAPI FN_GetAclInformation( PACL pAcl, LPVOID pAclInformation, DWORD nAclInformationLength, ACL_INFORMATION_CLASS dwAclInformationClass );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetAclInformation( PACL pAcl, LPVOID pAclInformation, DWORD nAclInformationLength, ACL_INFORMATION_CLASS dwAclInformationClass )
+{
+    static FN_GetAclInformation *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetAclInformation", &g_Kernel32);
+    return pfn( pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass );
+}
+
+typedef BOOL WINAPI FN_SetAclInformation( PACL pAcl, LPVOID pAclInformation, DWORD nAclInformationLength, ACL_INFORMATION_CLASS dwAclInformationClass );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetAclInformation( PACL pAcl, LPVOID pAclInformation, DWORD nAclInformationLength, ACL_INFORMATION_CLASS dwAclInformationClass )
+{
+    static FN_SetAclInformation *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetAclInformation", &g_Kernel32);
+    return pfn( pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass );
+}
+
+typedef BOOL WINAPI FN_AddAce( PACL pAcl, DWORD dwAceRevision, DWORD dwStartingAceIndex, LPVOID pAceList, DWORD nAceListLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AddAce( PACL pAcl, DWORD dwAceRevision, DWORD dwStartingAceIndex, LPVOID pAceList, DWORD nAceListLength )
+{
+    static FN_AddAce *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddAce", &g_Kernel32);
+    return pfn( pAcl, dwAceRevision, dwStartingAceIndex, pAceList, nAceListLength );
+}
+
+typedef BOOL WINAPI FN_DeleteAce( PACL pAcl, DWORD dwAceIndex );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DeleteAce( PACL pAcl, DWORD dwAceIndex )
+{
+    static FN_DeleteAce *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DeleteAce", &g_Kernel32);
+    return pfn( pAcl, dwAceIndex );
+}
+
+typedef BOOL WINAPI FN_GetAce( PACL pAcl, DWORD dwAceIndex, LPVOID * pAce );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetAce( PACL pAcl, DWORD dwAceIndex, LPVOID * pAce )
+{
+    static FN_GetAce *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetAce", &g_Kernel32);
+    return pfn( pAcl, dwAceIndex, pAce );
+}
+
+typedef BOOL WINAPI FN_AddAccessAllowedAce( PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AddAccessAllowedAce( PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid )
+{
+    static FN_AddAccessAllowedAce *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddAccessAllowedAce", &g_Kernel32);
+    return pfn( pAcl, dwAceRevision, AccessMask, pSid );
+}
+
+typedef BOOL WINAPI FN_AddAccessAllowedAceEx( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, PSID pSid );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AddAccessAllowedAceEx( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, PSID pSid )
+{
+    static FN_AddAccessAllowedAceEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddAccessAllowedAceEx", &g_Kernel32);
+    return pfn( pAcl, dwAceRevision, AceFlags, AccessMask, pSid );
+}
+
+typedef BOOL WINAPI FN_AddAccessDeniedAce( PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AddAccessDeniedAce( PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid )
+{
+    static FN_AddAccessDeniedAce *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddAccessDeniedAce", &g_Kernel32);
+    return pfn( pAcl, dwAceRevision, AccessMask, pSid );
+}
+
+typedef BOOL WINAPI FN_AddAccessDeniedAceEx( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, PSID pSid );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AddAccessDeniedAceEx( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, PSID pSid )
+{
+    static FN_AddAccessDeniedAceEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddAccessDeniedAceEx", &g_Kernel32);
+    return pfn( pAcl, dwAceRevision, AceFlags, AccessMask, pSid );
+}
+
+typedef BOOL WINAPI FN_AddAuditAccessAce( PACL pAcl, DWORD dwAceRevision, DWORD dwAccessMask, PSID pSid, BOOL bAuditSuccess, BOOL bAuditFailure );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AddAuditAccessAce( PACL pAcl, DWORD dwAceRevision, DWORD dwAccessMask, PSID pSid, BOOL bAuditSuccess, BOOL bAuditFailure )
+{
+    static FN_AddAuditAccessAce *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddAuditAccessAce", &g_Kernel32);
+    return pfn( pAcl, dwAceRevision, dwAccessMask, pSid, bAuditSuccess, bAuditFailure );
+}
+
+typedef BOOL WINAPI FN_AddAuditAccessAceEx( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD dwAccessMask, PSID pSid, BOOL bAuditSuccess, BOOL bAuditFailure );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AddAuditAccessAceEx( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD dwAccessMask, PSID pSid, BOOL bAuditSuccess, BOOL bAuditFailure )
+{
+    static FN_AddAuditAccessAceEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddAuditAccessAceEx", &g_Kernel32);
+    return pfn( pAcl, dwAceRevision, AceFlags, dwAccessMask, pSid, bAuditSuccess, bAuditFailure );
+}
+
+typedef BOOL WINAPI FN_AddAccessAllowedObjectAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, GUID * ObjectTypeGuid, GUID * InheritedObjectTypeGuid, PSID pSid );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AddAccessAllowedObjectAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, GUID * ObjectTypeGuid, GUID * InheritedObjectTypeGuid, PSID pSid )
+{
+    static FN_AddAccessAllowedObjectAce *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddAccessAllowedObjectAce", &g_Kernel32);
+    return pfn( pAcl, dwAceRevision, AceFlags, AccessMask, ObjectTypeGuid, InheritedObjectTypeGuid, pSid );
+}
+
+typedef BOOL WINAPI FN_AddAccessDeniedObjectAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, GUID * ObjectTypeGuid, GUID * InheritedObjectTypeGuid, PSID pSid );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AddAccessDeniedObjectAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, GUID * ObjectTypeGuid, GUID * InheritedObjectTypeGuid, PSID pSid )
+{
+    static FN_AddAccessDeniedObjectAce *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddAccessDeniedObjectAce", &g_Kernel32);
+    return pfn( pAcl, dwAceRevision, AceFlags, AccessMask, ObjectTypeGuid, InheritedObjectTypeGuid, pSid );
+}
+
+typedef BOOL WINAPI FN_AddAuditAccessObjectAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, GUID * ObjectTypeGuid, GUID * InheritedObjectTypeGuid, PSID pSid, BOOL bAuditSuccess, BOOL bAuditFailure );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AddAuditAccessObjectAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, GUID * ObjectTypeGuid, GUID * InheritedObjectTypeGuid, PSID pSid, BOOL bAuditSuccess, BOOL bAuditFailure )
+{
+    static FN_AddAuditAccessObjectAce *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddAuditAccessObjectAce", &g_Kernel32);
+    return pfn( pAcl, dwAceRevision, AceFlags, AccessMask, ObjectTypeGuid, InheritedObjectTypeGuid, pSid, bAuditSuccess, bAuditFailure );
+}
+
+typedef BOOL WINAPI FN_FindFirstFreeAce( PACL pAcl, LPVOID * pAce );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindFirstFreeAce( PACL pAcl, LPVOID * pAce )
+{
+    static FN_FindFirstFreeAce *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindFirstFreeAce", &g_Kernel32);
+    return pfn( pAcl, pAce );
+}
+
+typedef BOOL WINAPI FN_InitializeSecurityDescriptor( PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_InitializeSecurityDescriptor( PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision )
+{
+    static FN_InitializeSecurityDescriptor *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "InitializeSecurityDescriptor", &g_Kernel32);
+    return pfn( pSecurityDescriptor, dwRevision );
+}
+
+typedef BOOL WINAPI FN_IsValidSecurityDescriptor( PSECURITY_DESCRIPTOR pSecurityDescriptor );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsValidSecurityDescriptor( PSECURITY_DESCRIPTOR pSecurityDescriptor )
+{
+    static FN_IsValidSecurityDescriptor *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsValidSecurityDescriptor", &g_Kernel32);
+    return pfn( pSecurityDescriptor );
+}
+
+typedef DWORD WINAPI FN_GetSecurityDescriptorLength( PSECURITY_DESCRIPTOR pSecurityDescriptor );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetSecurityDescriptorLength( PSECURITY_DESCRIPTOR pSecurityDescriptor )
+{
+    static FN_GetSecurityDescriptorLength *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSecurityDescriptorLength", &g_Kernel32);
+    return pfn( pSecurityDescriptor );
+}
+
+typedef BOOL WINAPI FN_GetSecurityDescriptorControl( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSECURITY_DESCRIPTOR_CONTROL pControl, LPDWORD lpdwRevision );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetSecurityDescriptorControl( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSECURITY_DESCRIPTOR_CONTROL pControl, LPDWORD lpdwRevision )
+{
+    static FN_GetSecurityDescriptorControl *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSecurityDescriptorControl", &g_Kernel32);
+    return pfn( pSecurityDescriptor, pControl, lpdwRevision );
+}
+
+typedef BOOL WINAPI FN_SetSecurityDescriptorControl( PSECURITY_DESCRIPTOR pSecurityDescriptor, SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetSecurityDescriptorControl( PSECURITY_DESCRIPTOR pSecurityDescriptor, SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet )
+{
+    static FN_SetSecurityDescriptorControl *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetSecurityDescriptorControl", &g_Kernel32);
+    return pfn( pSecurityDescriptor, ControlBitsOfInterest, ControlBitsToSet );
+}
+
+typedef BOOL WINAPI FN_SetSecurityDescriptorDacl( PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, BOOL bDaclDefaulted );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetSecurityDescriptorDacl( PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, BOOL bDaclDefaulted )
+{
+    static FN_SetSecurityDescriptorDacl *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetSecurityDescriptorDacl", &g_Kernel32);
+    return pfn( pSecurityDescriptor, bDaclPresent, pDacl, bDaclDefaulted );
+}
+
+typedef BOOL WINAPI FN_GetSecurityDescriptorDacl( PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbDaclPresent, PACL * pDacl, LPBOOL lpbDaclDefaulted );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetSecurityDescriptorDacl( PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbDaclPresent, PACL * pDacl, LPBOOL lpbDaclDefaulted )
+{
+    static FN_GetSecurityDescriptorDacl *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSecurityDescriptorDacl", &g_Kernel32);
+    return pfn( pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted );
+}
+
+typedef BOOL WINAPI FN_SetSecurityDescriptorSacl( PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bSaclPresent, PACL pSacl, BOOL bSaclDefaulted );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetSecurityDescriptorSacl( PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bSaclPresent, PACL pSacl, BOOL bSaclDefaulted )
+{
+    static FN_SetSecurityDescriptorSacl *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetSecurityDescriptorSacl", &g_Kernel32);
+    return pfn( pSecurityDescriptor, bSaclPresent, pSacl, bSaclDefaulted );
+}
+
+typedef BOOL WINAPI FN_GetSecurityDescriptorSacl( PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbSaclPresent, PACL * pSacl, LPBOOL lpbSaclDefaulted );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetSecurityDescriptorSacl( PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbSaclPresent, PACL * pSacl, LPBOOL lpbSaclDefaulted )
+{
+    static FN_GetSecurityDescriptorSacl *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSecurityDescriptorSacl", &g_Kernel32);
+    return pfn( pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted );
+}
+
+typedef BOOL WINAPI FN_SetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pOwner, BOOL bOwnerDefaulted );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pOwner, BOOL bOwnerDefaulted )
+{
+    static FN_SetSecurityDescriptorOwner *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetSecurityDescriptorOwner", &g_Kernel32);
+    return pfn( pSecurityDescriptor, pOwner, bOwnerDefaulted );
+}
+
+typedef BOOL WINAPI FN_GetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID * pOwner, LPBOOL lpbOwnerDefaulted );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID * pOwner, LPBOOL lpbOwnerDefaulted )
+{
+    static FN_GetSecurityDescriptorOwner *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSecurityDescriptorOwner", &g_Kernel32);
+    return pfn( pSecurityDescriptor, pOwner, lpbOwnerDefaulted );
+}
+
+typedef BOOL WINAPI FN_SetSecurityDescriptorGroup( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pGroup, BOOL bGroupDefaulted );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetSecurityDescriptorGroup( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pGroup, BOOL bGroupDefaulted )
+{
+    static FN_SetSecurityDescriptorGroup *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetSecurityDescriptorGroup", &g_Kernel32);
+    return pfn( pSecurityDescriptor, pGroup, bGroupDefaulted );
+}
+
+typedef BOOL WINAPI FN_GetSecurityDescriptorGroup( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID * pGroup, LPBOOL lpbGroupDefaulted );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetSecurityDescriptorGroup( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID * pGroup, LPBOOL lpbGroupDefaulted )
+{
+    static FN_GetSecurityDescriptorGroup *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSecurityDescriptorGroup", &g_Kernel32);
+    return pfn( pSecurityDescriptor, pGroup, lpbGroupDefaulted );
+}
+
+typedef DWORD WINAPI FN_SetSecurityDescriptorRMControl( PSECURITY_DESCRIPTOR SecurityDescriptor, PUCHAR RMControl );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_SetSecurityDescriptorRMControl( PSECURITY_DESCRIPTOR SecurityDescriptor, PUCHAR RMControl )
+{
+    static FN_SetSecurityDescriptorRMControl *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetSecurityDescriptorRMControl", &g_Kernel32);
+    return pfn( SecurityDescriptor, RMControl );
+}
+
+typedef DWORD WINAPI FN_GetSecurityDescriptorRMControl( PSECURITY_DESCRIPTOR SecurityDescriptor, PUCHAR RMControl );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetSecurityDescriptorRMControl( PSECURITY_DESCRIPTOR SecurityDescriptor, PUCHAR RMControl )
+{
+    static FN_GetSecurityDescriptorRMControl *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSecurityDescriptorRMControl", &g_Kernel32);
+    return pfn( SecurityDescriptor, RMControl );
+}
+
+typedef BOOL WINAPI FN_CreatePrivateObjectSecurity( PSECURITY_DESCRIPTOR ParentDescriptor, PSECURITY_DESCRIPTOR CreatorDescriptor, PSECURITY_DESCRIPTOR * NewDescriptor, BOOL IsDirectoryObject, HANDLE Token, PGENERIC_MAPPING GenericMapping );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreatePrivateObjectSecurity( PSECURITY_DESCRIPTOR ParentDescriptor, PSECURITY_DESCRIPTOR CreatorDescriptor, PSECURITY_DESCRIPTOR * NewDescriptor, BOOL IsDirectoryObject, HANDLE Token, PGENERIC_MAPPING GenericMapping )
+{
+    static FN_CreatePrivateObjectSecurity *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreatePrivateObjectSecurity", &g_Kernel32);
+    return pfn( ParentDescriptor, CreatorDescriptor, NewDescriptor, IsDirectoryObject, Token, GenericMapping );
+}
+
+typedef BOOL WINAPI FN_ConvertToAutoInheritPrivateObjectSecurity( PSECURITY_DESCRIPTOR ParentDescriptor, PSECURITY_DESCRIPTOR CurrentSecurityDescriptor, PSECURITY_DESCRIPTOR * NewSecurityDescriptor, GUID * ObjectType, BOOLEAN IsDirectoryObject, PGENERIC_MAPPING GenericMapping );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ConvertToAutoInheritPrivateObjectSecurity( PSECURITY_DESCRIPTOR ParentDescriptor, PSECURITY_DESCRIPTOR CurrentSecurityDescriptor, PSECURITY_DESCRIPTOR * NewSecurityDescriptor, GUID * ObjectType, BOOLEAN IsDirectoryObject, PGENERIC_MAPPING GenericMapping )
+{
+    static FN_ConvertToAutoInheritPrivateObjectSecurity *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ConvertToAutoInheritPrivateObjectSecurity", &g_Kernel32);
+    return pfn( ParentDescriptor, CurrentSecurityDescriptor, NewSecurityDescriptor, ObjectType, IsDirectoryObject, GenericMapping );
+}
+
+typedef BOOL WINAPI FN_CreatePrivateObjectSecurityEx( PSECURITY_DESCRIPTOR ParentDescriptor, PSECURITY_DESCRIPTOR CreatorDescriptor, PSECURITY_DESCRIPTOR * NewDescriptor, GUID * ObjectType, BOOL IsContainerObject, ULONG AutoInheritFlags, HANDLE Token, PGENERIC_MAPPING GenericMapping );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreatePrivateObjectSecurityEx( PSECURITY_DESCRIPTOR ParentDescriptor, PSECURITY_DESCRIPTOR CreatorDescriptor, PSECURITY_DESCRIPTOR * NewDescriptor, GUID * ObjectType, BOOL IsContainerObject, ULONG AutoInheritFlags, HANDLE Token, PGENERIC_MAPPING GenericMapping )
+{
+    static FN_CreatePrivateObjectSecurityEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreatePrivateObjectSecurityEx", &g_Kernel32);
+    return pfn( ParentDescriptor, CreatorDescriptor, NewDescriptor, ObjectType, IsContainerObject, AutoInheritFlags, Token, GenericMapping );
+}
+
+typedef BOOL WINAPI FN_CreatePrivateObjectSecurityWithMultipleInheritance( PSECURITY_DESCRIPTOR ParentDescriptor, PSECURITY_DESCRIPTOR CreatorDescriptor, PSECURITY_DESCRIPTOR * NewDescriptor, GUID * *ObjectTypes, ULONG GuidCount, BOOL IsContainerObject, ULONG AutoInheritFlags, HANDLE Token, PGENERIC_MAPPING GenericMapping );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreatePrivateObjectSecurityWithMultipleInheritance( PSECURITY_DESCRIPTOR ParentDescriptor, PSECURITY_DESCRIPTOR CreatorDescriptor, PSECURITY_DESCRIPTOR * NewDescriptor, GUID * *ObjectTypes, ULONG GuidCount, BOOL IsContainerObject, ULONG AutoInheritFlags, HANDLE Token, PGENERIC_MAPPING GenericMapping )
+{
+    static FN_CreatePrivateObjectSecurityWithMultipleInheritance *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreatePrivateObjectSecurityWithMultipleInheritance", &g_Kernel32);
+    return pfn( ParentDescriptor, CreatorDescriptor, NewDescriptor, ObjectTypes, GuidCount, IsContainerObject, AutoInheritFlags, Token, GenericMapping );
+}
+
+typedef BOOL WINAPI FN_SetPrivateObjectSecurity( SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor, PSECURITY_DESCRIPTOR * ObjectsSecurityDescriptor, PGENERIC_MAPPING GenericMapping, HANDLE Token );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetPrivateObjectSecurity( SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor, PSECURITY_DESCRIPTOR * ObjectsSecurityDescriptor, PGENERIC_MAPPING GenericMapping, HANDLE Token )
+{
+    static FN_SetPrivateObjectSecurity *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetPrivateObjectSecurity", &g_Kernel32);
+    return pfn( SecurityInformation, ModificationDescriptor, ObjectsSecurityDescriptor, GenericMapping, Token );
+}
+
+typedef BOOL WINAPI FN_SetPrivateObjectSecurityEx( SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor, PSECURITY_DESCRIPTOR * ObjectsSecurityDescriptor, ULONG AutoInheritFlags, PGENERIC_MAPPING GenericMapping, HANDLE Token );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetPrivateObjectSecurityEx( SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor, PSECURITY_DESCRIPTOR * ObjectsSecurityDescriptor, ULONG AutoInheritFlags, PGENERIC_MAPPING GenericMapping, HANDLE Token )
+{
+    static FN_SetPrivateObjectSecurityEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetPrivateObjectSecurityEx", &g_Kernel32);
+    return pfn( SecurityInformation, ModificationDescriptor, ObjectsSecurityDescriptor, AutoInheritFlags, GenericMapping, Token );
+}
+
+typedef BOOL WINAPI FN_GetPrivateObjectSecurity( PSECURITY_DESCRIPTOR ObjectDescriptor, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ResultantDescriptor, DWORD DescriptorLength, PDWORD ReturnLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetPrivateObjectSecurity( PSECURITY_DESCRIPTOR ObjectDescriptor, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ResultantDescriptor, DWORD DescriptorLength, PDWORD ReturnLength )
+{
+    static FN_GetPrivateObjectSecurity *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetPrivateObjectSecurity", &g_Kernel32);
+    return pfn( ObjectDescriptor, SecurityInformation, ResultantDescriptor, DescriptorLength, ReturnLength );
+}
+
+typedef BOOL WINAPI FN_DestroyPrivateObjectSecurity( PSECURITY_DESCRIPTOR * ObjectDescriptor );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DestroyPrivateObjectSecurity( PSECURITY_DESCRIPTOR * ObjectDescriptor )
+{
+    static FN_DestroyPrivateObjectSecurity *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DestroyPrivateObjectSecurity", &g_Kernel32);
+    return pfn( ObjectDescriptor );
+}
+
+typedef BOOL WINAPI FN_MakeSelfRelativeSD( PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, LPDWORD lpdwBufferLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_MakeSelfRelativeSD( PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, LPDWORD lpdwBufferLength )
+{
+    static FN_MakeSelfRelativeSD *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MakeSelfRelativeSD", &g_Kernel32);
+    return pfn( pAbsoluteSecurityDescriptor, pSelfRelativeSecurityDescriptor, lpdwBufferLength );
+}
+
+typedef BOOL WINAPI FN_MakeAbsoluteSD( PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, LPDWORD lpdwAbsoluteSecurityDescriptorSize, PACL pDacl, LPDWORD lpdwDaclSize, PACL pSacl, LPDWORD lpdwSaclSize, PSID pOwner, LPDWORD lpdwOwnerSize, PSID pPrimaryGroup, LPDWORD lpdwPrimaryGroupSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_MakeAbsoluteSD( PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, LPDWORD lpdwAbsoluteSecurityDescriptorSize, PACL pDacl, LPDWORD lpdwDaclSize, PACL pSacl, LPDWORD lpdwSaclSize, PSID pOwner, LPDWORD lpdwOwnerSize, PSID pPrimaryGroup, LPDWORD lpdwPrimaryGroupSize )
+{
+    static FN_MakeAbsoluteSD *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MakeAbsoluteSD", &g_Kernel32);
+    return pfn( pSelfRelativeSecurityDescriptor, pAbsoluteSecurityDescriptor, lpdwAbsoluteSecurityDescriptorSize, pDacl, lpdwDaclSize, pSacl, lpdwSaclSize, pOwner, lpdwOwnerSize, pPrimaryGroup, lpdwPrimaryGroupSize );
+}
+
+typedef BOOL WINAPI FN_MakeAbsoluteSD2( PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, LPDWORD lpdwBufferSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_MakeAbsoluteSD2( PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, LPDWORD lpdwBufferSize )
+{
+    static FN_MakeAbsoluteSD2 *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MakeAbsoluteSD2", &g_Kernel32);
+    return pfn( pSelfRelativeSecurityDescriptor, lpdwBufferSize );
+}
+
+typedef BOOL WINAPI FN_SetFileSecurityA( LPCSTR lpFileName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetFileSecurityA( LPCSTR lpFileName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor )
+{
+    static FN_SetFileSecurityA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetFileSecurityA", &g_Kernel32);
+    return pfn( lpFileName, SecurityInformation, pSecurityDescriptor );
+}
+
+typedef BOOL WINAPI FN_SetFileSecurityW( LPCWSTR lpFileName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetFileSecurityW( LPCWSTR lpFileName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor )
+{
+    static FN_SetFileSecurityW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetFileSecurityW", &g_Kernel32);
+    return pfn( lpFileName, SecurityInformation, pSecurityDescriptor );
+}
+
+typedef BOOL WINAPI FN_GetFileSecurityA( LPCSTR lpFileName, SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetFileSecurityA( LPCSTR lpFileName, SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded )
+{
+    static FN_GetFileSecurityA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFileSecurityA", &g_Kernel32);
+    return pfn( lpFileName, RequestedInformation, pSecurityDescriptor, nLength, lpnLengthNeeded );
+}
+
+typedef BOOL WINAPI FN_GetFileSecurityW( LPCWSTR lpFileName, SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetFileSecurityW( LPCWSTR lpFileName, SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded )
+{
+    static FN_GetFileSecurityW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFileSecurityW", &g_Kernel32);
+    return pfn( lpFileName, RequestedInformation, pSecurityDescriptor, nLength, lpnLengthNeeded );
+}
+
+typedef BOOL WINAPI FN_SetKernelObjectSecurity( HANDLE Handle, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetKernelObjectSecurity( HANDLE Handle, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor )
+{
+    static FN_SetKernelObjectSecurity *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetKernelObjectSecurity", &g_Kernel32);
+    return pfn( Handle, SecurityInformation, SecurityDescriptor );
+}
+
+typedef HANDLE WINAPI FN_FindFirstChangeNotificationA( LPCSTR lpPathName, BOOL bWatchSubtree, DWORD dwNotifyFilter );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_FindFirstChangeNotificationA( LPCSTR lpPathName, BOOL bWatchSubtree, DWORD dwNotifyFilter )
+{
+    static FN_FindFirstChangeNotificationA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindFirstChangeNotificationA", &g_Kernel32);
+    return pfn( lpPathName, bWatchSubtree, dwNotifyFilter );
+}
+
+typedef HANDLE WINAPI FN_FindFirstChangeNotificationW( LPCWSTR lpPathName, BOOL bWatchSubtree, DWORD dwNotifyFilter );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_FindFirstChangeNotificationW( LPCWSTR lpPathName, BOOL bWatchSubtree, DWORD dwNotifyFilter )
+{
+    static FN_FindFirstChangeNotificationW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindFirstChangeNotificationW", &g_Kernel32);
+    return pfn( lpPathName, bWatchSubtree, dwNotifyFilter );
+}
+
+typedef BOOL WINAPI FN_FindNextChangeNotification( HANDLE hChangeHandle );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindNextChangeNotification( HANDLE hChangeHandle )
+{
+    static FN_FindNextChangeNotification *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindNextChangeNotification", &g_Kernel32);
+    return pfn( hChangeHandle );
+}
+
+typedef BOOL WINAPI FN_FindCloseChangeNotification( HANDLE hChangeHandle );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindCloseChangeNotification( HANDLE hChangeHandle )
+{
+    static FN_FindCloseChangeNotification *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindCloseChangeNotification", &g_Kernel32);
+    return pfn( hChangeHandle );
+}
+
+typedef BOOL WINAPI FN_ReadDirectoryChangesW( HANDLE hDirectory, LPVOID lpBuffer, DWORD nBufferLength, BOOL bWatchSubtree, DWORD dwNotifyFilter, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadDirectoryChangesW( HANDLE hDirectory, LPVOID lpBuffer, DWORD nBufferLength, BOOL bWatchSubtree, DWORD dwNotifyFilter, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
+{
+    static FN_ReadDirectoryChangesW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadDirectoryChangesW", &g_Kernel32);
+    return pfn( hDirectory, lpBuffer, nBufferLength, bWatchSubtree, dwNotifyFilter, lpBytesReturned, lpOverlapped, lpCompletionRoutine );
+}
+
+typedef BOOL WINAPI FN_VirtualLock( LPVOID lpAddress, SIZE_T dwSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_VirtualLock( LPVOID lpAddress, SIZE_T dwSize )
+{
+    static FN_VirtualLock *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VirtualLock", &g_Kernel32);
+    return pfn( lpAddress, dwSize );
+}
+
+typedef BOOL WINAPI FN_VirtualUnlock( LPVOID lpAddress, SIZE_T dwSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_VirtualUnlock( LPVOID lpAddress, SIZE_T dwSize )
+{
+    static FN_VirtualUnlock *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VirtualUnlock", &g_Kernel32);
+    return pfn( lpAddress, dwSize );
+}
+
+typedef LPVOID WINAPI FN_MapViewOfFileEx( HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress );
+__declspec(dllexport) LPVOID WINAPI kPrf2Wrap_MapViewOfFileEx( HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress )
+{
+    static FN_MapViewOfFileEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MapViewOfFileEx", &g_Kernel32);
+    return pfn( hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap, lpBaseAddress );
+}
+
+typedef BOOL WINAPI FN_SetPriorityClass( HANDLE hProcess, DWORD dwPriorityClass );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetPriorityClass( HANDLE hProcess, DWORD dwPriorityClass )
+{
+    static FN_SetPriorityClass *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetPriorityClass", &g_Kernel32);
+    return pfn( hProcess, dwPriorityClass );
+}
+
+typedef DWORD WINAPI FN_GetPriorityClass( HANDLE hProcess );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetPriorityClass( HANDLE hProcess )
+{
+    static FN_GetPriorityClass *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetPriorityClass", &g_Kernel32);
+    return pfn( hProcess );
+}
+
+typedef BOOL WINAPI FN_IsBadReadPtr( CONST VOID * lp, UINT_PTR ucb );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsBadReadPtr( CONST VOID * lp, UINT_PTR ucb )
+{
+    static FN_IsBadReadPtr *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsBadReadPtr", &g_Kernel32);
+    return pfn( lp, ucb );
+}
+
+typedef BOOL WINAPI FN_IsBadWritePtr( LPVOID lp, UINT_PTR ucb );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsBadWritePtr( LPVOID lp, UINT_PTR ucb )
+{
+    static FN_IsBadWritePtr *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsBadWritePtr", &g_Kernel32);
+    return pfn( lp, ucb );
+}
+
+typedef BOOL WINAPI FN_IsBadHugeReadPtr( CONST VOID * lp, UINT_PTR ucb );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsBadHugeReadPtr( CONST VOID * lp, UINT_PTR ucb )
+{
+    static FN_IsBadHugeReadPtr *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsBadHugeReadPtr", &g_Kernel32);
+    return pfn( lp, ucb );
+}
+
+typedef BOOL WINAPI FN_IsBadHugeWritePtr( LPVOID lp, UINT_PTR ucb );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsBadHugeWritePtr( LPVOID lp, UINT_PTR ucb )
+{
+    static FN_IsBadHugeWritePtr *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsBadHugeWritePtr", &g_Kernel32);
+    return pfn( lp, ucb );
+}
+
+typedef BOOL WINAPI FN_IsBadCodePtr( FARPROC lpfn );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsBadCodePtr( FARPROC lpfn )
+{
+    static FN_IsBadCodePtr *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsBadCodePtr", &g_Kernel32);
+    return pfn( lpfn );
+}
+
+typedef BOOL WINAPI FN_IsBadStringPtrA( LPCSTR lpsz, UINT_PTR ucchMax );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsBadStringPtrA( LPCSTR lpsz, UINT_PTR ucchMax )
+{
+    static FN_IsBadStringPtrA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsBadStringPtrA", &g_Kernel32);
+    return pfn( lpsz, ucchMax );
+}
+
+typedef BOOL WINAPI FN_IsBadStringPtrW( LPCWSTR lpsz, UINT_PTR ucchMax );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsBadStringPtrW( LPCWSTR lpsz, UINT_PTR ucchMax )
+{
+    static FN_IsBadStringPtrW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsBadStringPtrW", &g_Kernel32);
+    return pfn( lpsz, ucchMax );
+}
+
+typedef BOOL WINAPI FN_LookupAccountSidA( LPCSTR lpSystemName, PSID Sid, LPSTR Name, LPDWORD cchName, LPSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LookupAccountSidA( LPCSTR lpSystemName, PSID Sid, LPSTR Name, LPDWORD cchName, LPSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
+{
+    static FN_LookupAccountSidA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LookupAccountSidA", &g_Kernel32);
+    return pfn( lpSystemName, Sid, Name, cchName, ReferencedDomainName, cchReferencedDomainName, peUse );
+}
+
+typedef BOOL WINAPI FN_LookupAccountSidW( LPCWSTR lpSystemName, PSID Sid, LPWSTR Name, LPDWORD cchName, LPWSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LookupAccountSidW( LPCWSTR lpSystemName, PSID Sid, LPWSTR Name, LPDWORD cchName, LPWSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
+{
+    static FN_LookupAccountSidW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LookupAccountSidW", &g_Kernel32);
+    return pfn( lpSystemName, Sid, Name, cchName, ReferencedDomainName, cchReferencedDomainName, peUse );
+}
+
+typedef BOOL WINAPI FN_LookupAccountNameA( LPCSTR lpSystemName, LPCSTR lpAccountName, PSID Sid, LPDWORD cbSid, LPSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LookupAccountNameA( LPCSTR lpSystemName, LPCSTR lpAccountName, PSID Sid, LPDWORD cbSid, LPSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
+{
+    static FN_LookupAccountNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LookupAccountNameA", &g_Kernel32);
+    return pfn( lpSystemName, lpAccountName, Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
+}
+
+typedef BOOL WINAPI FN_LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid, LPDWORD cbSid, LPWSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid, LPDWORD cbSid, LPWSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
+{
+    static FN_LookupAccountNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LookupAccountNameW", &g_Kernel32);
+    return pfn( lpSystemName, lpAccountName, Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
+}
+
+typedef BOOL WINAPI FN_LookupPrivilegeValueA( LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LookupPrivilegeValueA( LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid )
+{
+    static FN_LookupPrivilegeValueA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LookupPrivilegeValueA", &g_Kernel32);
+    return pfn( lpSystemName, lpName, lpLuid );
+}
+
+typedef BOOL WINAPI FN_LookupPrivilegeValueW( LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LookupPrivilegeValueW( LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid )
+{
+    static FN_LookupPrivilegeValueW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LookupPrivilegeValueW", &g_Kernel32);
+    return pfn( lpSystemName, lpName, lpLuid );
+}
+
+typedef BOOL WINAPI FN_LookupPrivilegeNameA( LPCSTR lpSystemName, PLUID lpLuid, LPSTR lpName, LPDWORD cchName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LookupPrivilegeNameA( LPCSTR lpSystemName, PLUID lpLuid, LPSTR lpName, LPDWORD cchName )
+{
+    static FN_LookupPrivilegeNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LookupPrivilegeNameA", &g_Kernel32);
+    return pfn( lpSystemName, lpLuid, lpName, cchName );
+}
+
+typedef BOOL WINAPI FN_LookupPrivilegeNameW( LPCWSTR lpSystemName, PLUID lpLuid, LPWSTR lpName, LPDWORD cchName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LookupPrivilegeNameW( LPCWSTR lpSystemName, PLUID lpLuid, LPWSTR lpName, LPDWORD cchName )
+{
+    static FN_LookupPrivilegeNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LookupPrivilegeNameW", &g_Kernel32);
+    return pfn( lpSystemName, lpLuid, lpName, cchName );
+}
+
+typedef BOOL WINAPI FN_LookupPrivilegeDisplayNameA( LPCSTR lpSystemName, LPCSTR lpName, LPSTR lpDisplayName, LPDWORD cchDisplayName, LPDWORD lpLanguageId );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LookupPrivilegeDisplayNameA( LPCSTR lpSystemName, LPCSTR lpName, LPSTR lpDisplayName, LPDWORD cchDisplayName, LPDWORD lpLanguageId )
+{
+    static FN_LookupPrivilegeDisplayNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LookupPrivilegeDisplayNameA", &g_Kernel32);
+    return pfn( lpSystemName, lpName, lpDisplayName, cchDisplayName, lpLanguageId );
+}
+
+typedef BOOL WINAPI FN_LookupPrivilegeDisplayNameW( LPCWSTR lpSystemName, LPCWSTR lpName, LPWSTR lpDisplayName, LPDWORD cchDisplayName, LPDWORD lpLanguageId );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LookupPrivilegeDisplayNameW( LPCWSTR lpSystemName, LPCWSTR lpName, LPWSTR lpDisplayName, LPDWORD cchDisplayName, LPDWORD lpLanguageId )
+{
+    static FN_LookupPrivilegeDisplayNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LookupPrivilegeDisplayNameW", &g_Kernel32);
+    return pfn( lpSystemName, lpName, lpDisplayName, cchDisplayName, lpLanguageId );
+}
+
+typedef BOOL WINAPI FN_AllocateLocallyUniqueId( PLUID Luid );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AllocateLocallyUniqueId( PLUID Luid )
+{
+    static FN_AllocateLocallyUniqueId *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AllocateLocallyUniqueId", &g_Kernel32);
+    return pfn( Luid );
+}
+
+typedef BOOL WINAPI FN_BuildCommDCBA( LPCSTR lpDef, LPDCB lpDCB );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_BuildCommDCBA( LPCSTR lpDef, LPDCB lpDCB )
+{
+    static FN_BuildCommDCBA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "BuildCommDCBA", &g_Kernel32);
+    return pfn( lpDef, lpDCB );
+}
+
+typedef BOOL WINAPI FN_BuildCommDCBW( LPCWSTR lpDef, LPDCB lpDCB );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_BuildCommDCBW( LPCWSTR lpDef, LPDCB lpDCB )
+{
+    static FN_BuildCommDCBW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "BuildCommDCBW", &g_Kernel32);
+    return pfn( lpDef, lpDCB );
+}
+
+typedef BOOL WINAPI FN_BuildCommDCBAndTimeoutsA( LPCSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_BuildCommDCBAndTimeoutsA( LPCSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts )
+{
+    static FN_BuildCommDCBAndTimeoutsA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "BuildCommDCBAndTimeoutsA", &g_Kernel32);
+    return pfn( lpDef, lpDCB, lpCommTimeouts );
+}
+
+typedef BOOL WINAPI FN_BuildCommDCBAndTimeoutsW( LPCWSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_BuildCommDCBAndTimeoutsW( LPCWSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts )
+{
+    static FN_BuildCommDCBAndTimeoutsW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "BuildCommDCBAndTimeoutsW", &g_Kernel32);
+    return pfn( lpDef, lpDCB, lpCommTimeouts );
+}
+
+typedef BOOL WINAPI FN_CommConfigDialogA( LPCSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CommConfigDialogA( LPCSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC )
+{
+    static FN_CommConfigDialogA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CommConfigDialogA", &g_Kernel32);
+    return pfn( lpszName, hWnd, lpCC );
+}
+
+typedef BOOL WINAPI FN_CommConfigDialogW( LPCWSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CommConfigDialogW( LPCWSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC )
+{
+    static FN_CommConfigDialogW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CommConfigDialogW", &g_Kernel32);
+    return pfn( lpszName, hWnd, lpCC );
+}
+
+typedef BOOL WINAPI FN_GetDefaultCommConfigA( LPCSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetDefaultCommConfigA( LPCSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize )
+{
+    static FN_GetDefaultCommConfigA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetDefaultCommConfigA", &g_Kernel32);
+    return pfn( lpszName, lpCC, lpdwSize );
+}
+
+typedef BOOL WINAPI FN_GetDefaultCommConfigW( LPCWSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetDefaultCommConfigW( LPCWSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize )
+{
+    static FN_GetDefaultCommConfigW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetDefaultCommConfigW", &g_Kernel32);
+    return pfn( lpszName, lpCC, lpdwSize );
+}
+
+typedef BOOL WINAPI FN_SetDefaultCommConfigA( LPCSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetDefaultCommConfigA( LPCSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize )
+{
+    static FN_SetDefaultCommConfigA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetDefaultCommConfigA", &g_Kernel32);
+    return pfn( lpszName, lpCC, dwSize );
+}
+
+typedef BOOL WINAPI FN_SetDefaultCommConfigW( LPCWSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetDefaultCommConfigW( LPCWSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize )
+{
+    static FN_SetDefaultCommConfigW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetDefaultCommConfigW", &g_Kernel32);
+    return pfn( lpszName, lpCC, dwSize );
+}
+
+typedef BOOL WINAPI FN_GetComputerNameA( LPSTR lpBuffer, LPDWORD nSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetComputerNameA( LPSTR lpBuffer, LPDWORD nSize )
+{
+    static FN_GetComputerNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetComputerNameA", &g_Kernel32);
+    return pfn( lpBuffer, nSize );
+}
+
+typedef BOOL WINAPI FN_GetComputerNameW( LPWSTR lpBuffer, LPDWORD nSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetComputerNameW( LPWSTR lpBuffer, LPDWORD nSize )
+{
+    static FN_GetComputerNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetComputerNameW", &g_Kernel32);
+    return pfn( lpBuffer, nSize );
+}
+
+typedef BOOL WINAPI FN_SetComputerNameA( LPCSTR lpComputerName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetComputerNameA( LPCSTR lpComputerName )
+{
+    static FN_SetComputerNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetComputerNameA", &g_Kernel32);
+    return pfn( lpComputerName );
+}
+
+typedef BOOL WINAPI FN_SetComputerNameW( LPCWSTR lpComputerName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetComputerNameW( LPCWSTR lpComputerName )
+{
+    static FN_SetComputerNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetComputerNameW", &g_Kernel32);
+    return pfn( lpComputerName );
+}
+
+typedef BOOL WINAPI FN_GetComputerNameExA( COMPUTER_NAME_FORMAT NameType, LPSTR lpBuffer, LPDWORD nSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetComputerNameExA( COMPUTER_NAME_FORMAT NameType, LPSTR lpBuffer, LPDWORD nSize )
+{
+    static FN_GetComputerNameExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetComputerNameExA", &g_Kernel32);
+    return pfn( NameType, lpBuffer, nSize );
+}
+
+typedef BOOL WINAPI FN_GetComputerNameExW( COMPUTER_NAME_FORMAT NameType, LPWSTR lpBuffer, LPDWORD nSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetComputerNameExW( COMPUTER_NAME_FORMAT NameType, LPWSTR lpBuffer, LPDWORD nSize )
+{
+    static FN_GetComputerNameExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetComputerNameExW", &g_Kernel32);
+    return pfn( NameType, lpBuffer, nSize );
+}
+
+typedef BOOL WINAPI FN_SetComputerNameExA( COMPUTER_NAME_FORMAT NameType, LPCSTR lpBuffer );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetComputerNameExA( COMPUTER_NAME_FORMAT NameType, LPCSTR lpBuffer )
+{
+    static FN_SetComputerNameExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetComputerNameExA", &g_Kernel32);
+    return pfn( NameType, lpBuffer );
+}
+
+typedef BOOL WINAPI FN_SetComputerNameExW( COMPUTER_NAME_FORMAT NameType, LPCWSTR lpBuffer );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetComputerNameExW( COMPUTER_NAME_FORMAT NameType, LPCWSTR lpBuffer )
+{
+    static FN_SetComputerNameExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetComputerNameExW", &g_Kernel32);
+    return pfn( NameType, lpBuffer );
+}
+
+typedef BOOL WINAPI FN_DnsHostnameToComputerNameA( LPCSTR Hostname, LPSTR ComputerName, LPDWORD nSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DnsHostnameToComputerNameA( LPCSTR Hostname, LPSTR ComputerName, LPDWORD nSize )
+{
+    static FN_DnsHostnameToComputerNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DnsHostnameToComputerNameA", &g_Kernel32);
+    return pfn( Hostname, ComputerName, nSize );
+}
+
+typedef BOOL WINAPI FN_DnsHostnameToComputerNameW( LPCWSTR Hostname, LPWSTR ComputerName, LPDWORD nSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DnsHostnameToComputerNameW( LPCWSTR Hostname, LPWSTR ComputerName, LPDWORD nSize )
+{
+    static FN_DnsHostnameToComputerNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DnsHostnameToComputerNameW", &g_Kernel32);
+    return pfn( Hostname, ComputerName, nSize );
+}
+
+typedef BOOL WINAPI FN_GetUserNameA( LPSTR lpBuffer, LPDWORD pcbBuffer );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetUserNameA( LPSTR lpBuffer, LPDWORD pcbBuffer )
+{
+    static FN_GetUserNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetUserNameA", &g_Kernel32);
+    return pfn( lpBuffer, pcbBuffer );
+}
+
+typedef BOOL WINAPI FN_GetUserNameW( LPWSTR lpBuffer, LPDWORD pcbBuffer );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetUserNameW( LPWSTR lpBuffer, LPDWORD pcbBuffer )
+{
+    static FN_GetUserNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetUserNameW", &g_Kernel32);
+    return pfn( lpBuffer, pcbBuffer );
+}
+
+typedef BOOL WINAPI FN_LogonUserA( LPCSTR lpszUsername, LPCSTR lpszDomain, LPCSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LogonUserA( LPCSTR lpszUsername, LPCSTR lpszDomain, LPCSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken )
+{
+    static FN_LogonUserA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LogonUserA", &g_Kernel32);
+    return pfn( lpszUsername, lpszDomain, lpszPassword, dwLogonType, dwLogonProvider, phToken );
+}
+
+typedef BOOL WINAPI FN_LogonUserW( LPCWSTR lpszUsername, LPCWSTR lpszDomain, LPCWSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LogonUserW( LPCWSTR lpszUsername, LPCWSTR lpszDomain, LPCWSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken )
+{
+    static FN_LogonUserW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LogonUserW", &g_Kernel32);
+    return pfn( lpszUsername, lpszDomain, lpszPassword, dwLogonType, dwLogonProvider, phToken );
+}
+
+typedef BOOL WINAPI FN_LogonUserExA( LPCSTR lpszUsername, LPCSTR lpszDomain, LPCSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken, PSID * ppLogonSid, PVOID * ppProfileBuffer, LPDWORD pdwProfileLength, PQUOTA_LIMITS pQuotaLimits );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LogonUserExA( LPCSTR lpszUsername, LPCSTR lpszDomain, LPCSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken, PSID * ppLogonSid, PVOID * ppProfileBuffer, LPDWORD pdwProfileLength, PQUOTA_LIMITS pQuotaLimits )
+{
+    static FN_LogonUserExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LogonUserExA", &g_Kernel32);
+    return pfn( lpszUsername, lpszDomain, lpszPassword, dwLogonType, dwLogonProvider, phToken, ppLogonSid, ppProfileBuffer, pdwProfileLength, pQuotaLimits );
+}
+
+typedef BOOL WINAPI FN_LogonUserExW( LPCWSTR lpszUsername, LPCWSTR lpszDomain, LPCWSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken, PSID * ppLogonSid, PVOID * ppProfileBuffer, LPDWORD pdwProfileLength, PQUOTA_LIMITS pQuotaLimits );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_LogonUserExW( LPCWSTR lpszUsername, LPCWSTR lpszDomain, LPCWSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken, PSID * ppLogonSid, PVOID * ppProfileBuffer, LPDWORD pdwProfileLength, PQUOTA_LIMITS pQuotaLimits )
+{
+    static FN_LogonUserExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LogonUserExW", &g_Kernel32);
+    return pfn( lpszUsername, lpszDomain, lpszPassword, dwLogonType, dwLogonProvider, phToken, ppLogonSid, ppProfileBuffer, pdwProfileLength, pQuotaLimits );
+}
+
+typedef BOOL WINAPI FN_ImpersonateLoggedOnUser( HANDLE hToken );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ImpersonateLoggedOnUser( HANDLE hToken )
+{
+    static FN_ImpersonateLoggedOnUser *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ImpersonateLoggedOnUser", &g_Kernel32);
+    return pfn( hToken );
+}
+
+typedef BOOL WINAPI FN_CreateProcessAsUserA( HANDLE hToken, LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreateProcessAsUserA( HANDLE hToken, LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
+{
+    static FN_CreateProcessAsUserA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateProcessAsUserA", &g_Kernel32);
+    return pfn( hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation );
+}
+
+typedef BOOL WINAPI FN_CreateProcessAsUserW( HANDLE hToken, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreateProcessAsUserW( HANDLE hToken, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
+{
+    static FN_CreateProcessAsUserW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateProcessAsUserW", &g_Kernel32);
+    return pfn( hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation );
+}
+
+typedef BOOL WINAPI FN_CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
+{
+    static FN_CreateProcessWithLogonW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateProcessWithLogonW", &g_Kernel32);
+    return pfn( lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation );
+}
+
+typedef BOOL WINAPI FN_CreateProcessWithTokenW( HANDLE hToken, DWORD dwLogonFlags, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreateProcessWithTokenW( HANDLE hToken, DWORD dwLogonFlags, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
+{
+    static FN_CreateProcessWithTokenW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateProcessWithTokenW", &g_Kernel32);
+    return pfn( hToken, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation );
+}
+
+typedef BOOL APIENTRY FN_ImpersonateAnonymousToken( HANDLE ThreadHandle );
+__declspec(dllexport) BOOL APIENTRY kPrf2Wrap_ImpersonateAnonymousToken( HANDLE ThreadHandle )
+{
+    static FN_ImpersonateAnonymousToken *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ImpersonateAnonymousToken", &g_Kernel32);
+    return pfn( ThreadHandle );
+}
+
+typedef BOOL WINAPI FN_DuplicateTokenEx( HANDLE hExistingToken, DWORD dwDesiredAccess, LPSECURITY_ATTRIBUTES lpTokenAttributes, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, TOKEN_TYPE TokenType, PHANDLE phNewToken );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DuplicateTokenEx( HANDLE hExistingToken, DWORD dwDesiredAccess, LPSECURITY_ATTRIBUTES lpTokenAttributes, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, TOKEN_TYPE TokenType, PHANDLE phNewToken )
+{
+    static FN_DuplicateTokenEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DuplicateTokenEx", &g_Kernel32);
+    return pfn( hExistingToken, dwDesiredAccess, lpTokenAttributes, ImpersonationLevel, TokenType, phNewToken );
+}
+
+typedef BOOL APIENTRY FN_CreateRestrictedToken( HANDLE ExistingTokenHandle, DWORD Flags, DWORD DisableSidCount, PSID_AND_ATTRIBUTES SidsToDisable, DWORD DeletePrivilegeCount, PLUID_AND_ATTRIBUTES PrivilegesToDelete, DWORD RestrictedSidCount, PSID_AND_ATTRIBUTES SidsToRestrict, PHANDLE NewTokenHandle );
+__declspec(dllexport) BOOL APIENTRY kPrf2Wrap_CreateRestrictedToken( HANDLE ExistingTokenHandle, DWORD Flags, DWORD DisableSidCount, PSID_AND_ATTRIBUTES SidsToDisable, DWORD DeletePrivilegeCount, PLUID_AND_ATTRIBUTES PrivilegesToDelete, DWORD RestrictedSidCount, PSID_AND_ATTRIBUTES SidsToRestrict, PHANDLE NewTokenHandle )
+{
+    static FN_CreateRestrictedToken *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateRestrictedToken", &g_Kernel32);
+    return pfn( ExistingTokenHandle, Flags, DisableSidCount, SidsToDisable, DeletePrivilegeCount, PrivilegesToDelete, RestrictedSidCount, SidsToRestrict, NewTokenHandle );
+}
+
+typedef BOOL WINAPI FN_IsTokenRestricted( HANDLE TokenHandle );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsTokenRestricted( HANDLE TokenHandle )
+{
+    static FN_IsTokenRestricted *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsTokenRestricted", &g_Kernel32);
+    return pfn( TokenHandle );
+}
+
+typedef BOOL WINAPI FN_IsTokenUntrusted( HANDLE TokenHandle );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsTokenUntrusted( HANDLE TokenHandle )
+{
+    static FN_IsTokenUntrusted *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsTokenUntrusted", &g_Kernel32);
+    return pfn( TokenHandle );
+}
+
+typedef BOOL APIENTRY FN_CheckTokenMembership( HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember );
+__declspec(dllexport) BOOL APIENTRY kPrf2Wrap_CheckTokenMembership( HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember )
+{
+    static FN_CheckTokenMembership *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CheckTokenMembership", &g_Kernel32);
+    return pfn( TokenHandle, SidToCheck, IsMember );
+}
+
+typedef BOOL WINAPI FN_RegisterWaitForSingleObject( PHANDLE phNewWaitObject, HANDLE hObject, WAITORTIMERCALLBACK Callback, PVOID Context, ULONG dwMilliseconds, ULONG dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_RegisterWaitForSingleObject( PHANDLE phNewWaitObject, HANDLE hObject, WAITORTIMERCALLBACK Callback, PVOID Context, ULONG dwMilliseconds, ULONG dwFlags )
+{
+    static FN_RegisterWaitForSingleObject *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RegisterWaitForSingleObject", &g_Kernel32);
+    return pfn( phNewWaitObject, hObject, Callback, Context, dwMilliseconds, dwFlags );
+}
+
+typedef HANDLE WINAPI FN_RegisterWaitForSingleObjectEx( HANDLE hObject, WAITORTIMERCALLBACK Callback, PVOID Context, ULONG dwMilliseconds, ULONG dwFlags );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_RegisterWaitForSingleObjectEx( HANDLE hObject, WAITORTIMERCALLBACK Callback, PVOID Context, ULONG dwMilliseconds, ULONG dwFlags )
+{
+    static FN_RegisterWaitForSingleObjectEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RegisterWaitForSingleObjectEx", &g_Kernel32);
+    return pfn( hObject, Callback, Context, dwMilliseconds, dwFlags );
+}
+
+typedef BOOL WINAPI FN_UnregisterWait( HANDLE WaitHandle );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_UnregisterWait( HANDLE WaitHandle )
+{
+    static FN_UnregisterWait *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "UnregisterWait", &g_Kernel32);
+    return pfn( WaitHandle );
+}
+
+typedef BOOL WINAPI FN_UnregisterWaitEx( HANDLE WaitHandle, HANDLE CompletionEvent );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_UnregisterWaitEx( HANDLE WaitHandle, HANDLE CompletionEvent )
+{
+    static FN_UnregisterWaitEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "UnregisterWaitEx", &g_Kernel32);
+    return pfn( WaitHandle, CompletionEvent );
+}
+
+typedef BOOL WINAPI FN_QueueUserWorkItem( LPTHREAD_START_ROUTINE Function, PVOID Context, ULONG Flags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_QueueUserWorkItem( LPTHREAD_START_ROUTINE Function, PVOID Context, ULONG Flags )
+{
+    static FN_QueueUserWorkItem *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "QueueUserWorkItem", &g_Kernel32);
+    return pfn( Function, Context, Flags );
+}
+
+typedef BOOL WINAPI FN_BindIoCompletionCallback( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_BindIoCompletionCallback( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags )
+{
+    static FN_BindIoCompletionCallback *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "BindIoCompletionCallback", &g_Kernel32);
+    return pfn( FileHandle, Function, Flags );
+}
+
+typedef HANDLE WINAPI FN_CreateTimerQueue( VOID );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateTimerQueue( VOID )
+{
+    static FN_CreateTimerQueue *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateTimerQueue", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL WINAPI FN_CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue, WAITORTIMERCALLBACK Callback, PVOID Parameter, DWORD DueTime, DWORD Period, ULONG Flags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue, WAITORTIMERCALLBACK Callback, PVOID Parameter, DWORD DueTime, DWORD Period, ULONG Flags )
+{
+    static FN_CreateTimerQueueTimer *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateTimerQueueTimer", &g_Kernel32);
+    return pfn( phNewTimer, TimerQueue, Callback, Parameter, DueTime, Period, Flags );
+}
+
+typedef BOOL WINAPI FN_ChangeTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer, ULONG DueTime, ULONG Period );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ChangeTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer, ULONG DueTime, ULONG Period )
+{
+    static FN_ChangeTimerQueueTimer *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ChangeTimerQueueTimer", &g_Kernel32);
+    return pfn( TimerQueue, Timer, DueTime, Period );
+}
+
+typedef BOOL WINAPI FN_DeleteTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer, HANDLE CompletionEvent );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DeleteTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer, HANDLE CompletionEvent )
+{
+    static FN_DeleteTimerQueueTimer *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DeleteTimerQueueTimer", &g_Kernel32);
+    return pfn( TimerQueue, Timer, CompletionEvent );
+}
+
+typedef BOOL WINAPI FN_DeleteTimerQueueEx( HANDLE TimerQueue, HANDLE CompletionEvent );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DeleteTimerQueueEx( HANDLE TimerQueue, HANDLE CompletionEvent )
+{
+    static FN_DeleteTimerQueueEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DeleteTimerQueueEx", &g_Kernel32);
+    return pfn( TimerQueue, CompletionEvent );
+}
+
+typedef HANDLE WINAPI FN_SetTimerQueueTimer( HANDLE TimerQueue, WAITORTIMERCALLBACK Callback, PVOID Parameter, DWORD DueTime, DWORD Period, BOOL PreferIo );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_SetTimerQueueTimer( HANDLE TimerQueue, WAITORTIMERCALLBACK Callback, PVOID Parameter, DWORD DueTime, DWORD Period, BOOL PreferIo )
+{
+    static FN_SetTimerQueueTimer *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetTimerQueueTimer", &g_Kernel32);
+    return pfn( TimerQueue, Callback, Parameter, DueTime, Period, PreferIo );
+}
+
+typedef BOOL WINAPI FN_CancelTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CancelTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer )
+{
+    static FN_CancelTimerQueueTimer *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CancelTimerQueueTimer", &g_Kernel32);
+    return pfn( TimerQueue, Timer );
+}
+
+typedef BOOL WINAPI FN_DeleteTimerQueue( HANDLE TimerQueue );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DeleteTimerQueue( HANDLE TimerQueue )
+{
+    static FN_DeleteTimerQueue *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DeleteTimerQueue", &g_Kernel32);
+    return pfn( TimerQueue );
+}
+
+typedef BOOL WINAPI FN_GetCurrentHwProfileA( LPHW_PROFILE_INFOA lpHwProfileInfo );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetCurrentHwProfileA( LPHW_PROFILE_INFOA lpHwProfileInfo )
+{
+    static FN_GetCurrentHwProfileA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCurrentHwProfileA", &g_Kernel32);
+    return pfn( lpHwProfileInfo );
+}
+
+typedef BOOL WINAPI FN_GetCurrentHwProfileW( LPHW_PROFILE_INFOW lpHwProfileInfo );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetCurrentHwProfileW( LPHW_PROFILE_INFOW lpHwProfileInfo )
+{
+    static FN_GetCurrentHwProfileW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCurrentHwProfileW", &g_Kernel32);
+    return pfn( lpHwProfileInfo );
+}
+
+typedef BOOL WINAPI FN_QueryPerformanceCounter( LARGE_INTEGER * lpPerformanceCount );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_QueryPerformanceCounter( LARGE_INTEGER * lpPerformanceCount )
+{
+    static FN_QueryPerformanceCounter *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "QueryPerformanceCounter", &g_Kernel32);
+    return pfn( lpPerformanceCount );
+}
+
+typedef BOOL WINAPI FN_QueryPerformanceFrequency( LARGE_INTEGER * lpFrequency );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_QueryPerformanceFrequency( LARGE_INTEGER * lpFrequency )
+{
+    static FN_QueryPerformanceFrequency *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "QueryPerformanceFrequency", &g_Kernel32);
+    return pfn( lpFrequency );
+}
+
+typedef BOOL WINAPI FN_GetVersionExA( LPOSVERSIONINFOA lpVersionInformation );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetVersionExA( LPOSVERSIONINFOA lpVersionInformation )
+{
+    static FN_GetVersionExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetVersionExA", &g_Kernel32);
+    return pfn( lpVersionInformation );
+}
+
+typedef BOOL WINAPI FN_GetVersionExW( LPOSVERSIONINFOW lpVersionInformation );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetVersionExW( LPOSVERSIONINFOW lpVersionInformation )
+{
+    static FN_GetVersionExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetVersionExW", &g_Kernel32);
+    return pfn( lpVersionInformation );
+}
+
+typedef BOOL WINAPI FN_VerifyVersionInfoA( LPOSVERSIONINFOEXA lpVersionInformation, DWORD dwTypeMask, DWORDLONG dwlConditionMask );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_VerifyVersionInfoA( LPOSVERSIONINFOEXA lpVersionInformation, DWORD dwTypeMask, DWORDLONG dwlConditionMask )
+{
+    static FN_VerifyVersionInfoA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VerifyVersionInfoA", &g_Kernel32);
+    return pfn( lpVersionInformation, dwTypeMask, dwlConditionMask );
+}
+
+typedef BOOL WINAPI FN_VerifyVersionInfoW( LPOSVERSIONINFOEXW lpVersionInformation, DWORD dwTypeMask, DWORDLONG dwlConditionMask );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_VerifyVersionInfoW( LPOSVERSIONINFOEXW lpVersionInformation, DWORD dwTypeMask, DWORDLONG dwlConditionMask )
+{
+    static FN_VerifyVersionInfoW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VerifyVersionInfoW", &g_Kernel32);
+    return pfn( lpVersionInformation, dwTypeMask, dwlConditionMask );
+}
+
+typedef BOOL WINAPI FN_GetSystemPowerStatus( LPSYSTEM_POWER_STATUS lpSystemPowerStatus );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetSystemPowerStatus( LPSYSTEM_POWER_STATUS lpSystemPowerStatus )
+{
+    static FN_GetSystemPowerStatus *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemPowerStatus", &g_Kernel32);
+    return pfn( lpSystemPowerStatus );
+}
+
+typedef BOOL WINAPI FN_SetSystemPowerState( BOOL fSuspend, BOOL fForce );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetSystemPowerState( BOOL fSuspend, BOOL fForce )
+{
+    static FN_SetSystemPowerState *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetSystemPowerState", &g_Kernel32);
+    return pfn( fSuspend, fForce );
+}
+
+typedef BOOL WINAPI FN_AllocateUserPhysicalPages( HANDLE hProcess, PULONG_PTR NumberOfPages, PULONG_PTR PageArray );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AllocateUserPhysicalPages( HANDLE hProcess, PULONG_PTR NumberOfPages, PULONG_PTR PageArray )
+{
+    static FN_AllocateUserPhysicalPages *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AllocateUserPhysicalPages", &g_Kernel32);
+    return pfn( hProcess, NumberOfPages, PageArray );
+}
+
+typedef BOOL WINAPI FN_FreeUserPhysicalPages( HANDLE hProcess, PULONG_PTR NumberOfPages, PULONG_PTR PageArray );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FreeUserPhysicalPages( HANDLE hProcess, PULONG_PTR NumberOfPages, PULONG_PTR PageArray )
+{
+    static FN_FreeUserPhysicalPages *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FreeUserPhysicalPages", &g_Kernel32);
+    return pfn( hProcess, NumberOfPages, PageArray );
+}
+
+typedef BOOL WINAPI FN_MapUserPhysicalPages( PVOID VirtualAddress, ULONG_PTR NumberOfPages, PULONG_PTR PageArray );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_MapUserPhysicalPages( PVOID VirtualAddress, ULONG_PTR NumberOfPages, PULONG_PTR PageArray )
+{
+    static FN_MapUserPhysicalPages *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MapUserPhysicalPages", &g_Kernel32);
+    return pfn( VirtualAddress, NumberOfPages, PageArray );
+}
+
+typedef BOOL WINAPI FN_MapUserPhysicalPagesScatter( PVOID * VirtualAddresses, ULONG_PTR NumberOfPages, PULONG_PTR PageArray );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_MapUserPhysicalPagesScatter( PVOID * VirtualAddresses, ULONG_PTR NumberOfPages, PULONG_PTR PageArray )
+{
+    static FN_MapUserPhysicalPagesScatter *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MapUserPhysicalPagesScatter", &g_Kernel32);
+    return pfn( VirtualAddresses, NumberOfPages, PageArray );
+}
+
+typedef HANDLE WINAPI FN_CreateJobObjectA( LPSECURITY_ATTRIBUTES lpJobAttributes, LPCSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateJobObjectA( LPSECURITY_ATTRIBUTES lpJobAttributes, LPCSTR lpName )
+{
+    static FN_CreateJobObjectA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateJobObjectA", &g_Kernel32);
+    return pfn( lpJobAttributes, lpName );
+}
+
+typedef HANDLE WINAPI FN_CreateJobObjectW( LPSECURITY_ATTRIBUTES lpJobAttributes, LPCWSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateJobObjectW( LPSECURITY_ATTRIBUTES lpJobAttributes, LPCWSTR lpName )
+{
+    static FN_CreateJobObjectW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateJobObjectW", &g_Kernel32);
+    return pfn( lpJobAttributes, lpName );
+}
+
+typedef HANDLE WINAPI FN_OpenJobObjectA( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenJobObjectA( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName )
+{
+    static FN_OpenJobObjectA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenJobObjectA", &g_Kernel32);
+    return pfn( dwDesiredAccess, bInheritHandle, lpName );
+}
+
+typedef HANDLE WINAPI FN_OpenJobObjectW( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_OpenJobObjectW( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName )
+{
+    static FN_OpenJobObjectW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "OpenJobObjectW", &g_Kernel32);
+    return pfn( dwDesiredAccess, bInheritHandle, lpName );
+}
+
+typedef BOOL WINAPI FN_AssignProcessToJobObject( HANDLE hJob, HANDLE hProcess );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AssignProcessToJobObject( HANDLE hJob, HANDLE hProcess )
+{
+    static FN_AssignProcessToJobObject *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AssignProcessToJobObject", &g_Kernel32);
+    return pfn( hJob, hProcess );
+}
+
+typedef BOOL WINAPI FN_TerminateJobObject( HANDLE hJob, UINT uExitCode );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_TerminateJobObject( HANDLE hJob, UINT uExitCode )
+{
+    static FN_TerminateJobObject *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "TerminateJobObject", &g_Kernel32);
+    return pfn( hJob, uExitCode );
+}
+
+typedef BOOL WINAPI FN_QueryInformationJobObject( HANDLE hJob, JOBOBJECTINFOCLASS JobObjectInformationClass, LPVOID lpJobObjectInformation, DWORD cbJobObjectInformationLength, LPDWORD lpReturnLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_QueryInformationJobObject( HANDLE hJob, JOBOBJECTINFOCLASS JobObjectInformationClass, LPVOID lpJobObjectInformation, DWORD cbJobObjectInformationLength, LPDWORD lpReturnLength )
+{
+    static FN_QueryInformationJobObject *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "QueryInformationJobObject", &g_Kernel32);
+    return pfn( hJob, JobObjectInformationClass, lpJobObjectInformation, cbJobObjectInformationLength, lpReturnLength );
+}
+
+typedef BOOL WINAPI FN_SetInformationJobObject( HANDLE hJob, JOBOBJECTINFOCLASS JobObjectInformationClass, LPVOID lpJobObjectInformation, DWORD cbJobObjectInformationLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetInformationJobObject( HANDLE hJob, JOBOBJECTINFOCLASS JobObjectInformationClass, LPVOID lpJobObjectInformation, DWORD cbJobObjectInformationLength )
+{
+    static FN_SetInformationJobObject *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetInformationJobObject", &g_Kernel32);
+    return pfn( hJob, JobObjectInformationClass, lpJobObjectInformation, cbJobObjectInformationLength );
+}
+
+typedef BOOL WINAPI FN_IsProcessInJob( HANDLE ProcessHandle, HANDLE JobHandle, PBOOL Result );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsProcessInJob( HANDLE ProcessHandle, HANDLE JobHandle, PBOOL Result )
+{
+    static FN_IsProcessInJob *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsProcessInJob", &g_Kernel32);
+    return pfn( ProcessHandle, JobHandle, Result );
+}
+
+typedef BOOL WINAPI FN_CreateJobSet( ULONG NumJob, PJOB_SET_ARRAY UserJobSet, ULONG Flags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_CreateJobSet( ULONG NumJob, PJOB_SET_ARRAY UserJobSet, ULONG Flags )
+{
+    static FN_CreateJobSet *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateJobSet", &g_Kernel32);
+    return pfn( NumJob, UserJobSet, Flags );
+}
+
+typedef PVOID WINAPI FN_AddVectoredExceptionHandler( ULONG First, PVECTORED_EXCEPTION_HANDLER Handler );
+__declspec(dllexport) PVOID WINAPI kPrf2Wrap_AddVectoredExceptionHandler( ULONG First, PVECTORED_EXCEPTION_HANDLER Handler )
+{
+    static FN_AddVectoredExceptionHandler *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddVectoredExceptionHandler", &g_Kernel32);
+    return pfn( First, Handler );
+}
+
+typedef ULONG WINAPI FN_RemoveVectoredExceptionHandler( PVOID Handle );
+__declspec(dllexport) ULONG WINAPI kPrf2Wrap_RemoveVectoredExceptionHandler( PVOID Handle )
+{
+    static FN_RemoveVectoredExceptionHandler *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RemoveVectoredExceptionHandler", &g_Kernel32);
+    return pfn( Handle );
+}
+
+typedef PVOID WINAPI FN_AddVectoredContinueHandler( ULONG First, PVECTORED_EXCEPTION_HANDLER Handler );
+__declspec(dllexport) PVOID WINAPI kPrf2Wrap_AddVectoredContinueHandler( ULONG First, PVECTORED_EXCEPTION_HANDLER Handler )
+{
+    static FN_AddVectoredContinueHandler *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddVectoredContinueHandler", &g_Kernel32);
+    return pfn( First, Handler );
+}
+
+typedef ULONG WINAPI FN_RemoveVectoredContinueHandler( PVOID Handle );
+__declspec(dllexport) ULONG WINAPI kPrf2Wrap_RemoveVectoredContinueHandler( PVOID Handle )
+{
+    static FN_RemoveVectoredContinueHandler *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RemoveVectoredContinueHandler", &g_Kernel32);
+    return pfn( Handle );
+}
+
+typedef HANDLE WINAPI FN_FindFirstVolumeA( LPSTR lpszVolumeName, DWORD cchBufferLength );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_FindFirstVolumeA( LPSTR lpszVolumeName, DWORD cchBufferLength )
+{
+    static FN_FindFirstVolumeA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindFirstVolumeA", &g_Kernel32);
+    return pfn( lpszVolumeName, cchBufferLength );
+}
+
+typedef HANDLE WINAPI FN_FindFirstVolumeW( LPWSTR lpszVolumeName, DWORD cchBufferLength );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_FindFirstVolumeW( LPWSTR lpszVolumeName, DWORD cchBufferLength )
+{
+    static FN_FindFirstVolumeW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindFirstVolumeW", &g_Kernel32);
+    return pfn( lpszVolumeName, cchBufferLength );
+}
+
+typedef BOOL WINAPI FN_FindNextVolumeA( HANDLE hFindVolume, LPSTR lpszVolumeName, DWORD cchBufferLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindNextVolumeA( HANDLE hFindVolume, LPSTR lpszVolumeName, DWORD cchBufferLength )
+{
+    static FN_FindNextVolumeA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindNextVolumeA", &g_Kernel32);
+    return pfn( hFindVolume, lpszVolumeName, cchBufferLength );
+}
+
+typedef BOOL WINAPI FN_FindNextVolumeW( HANDLE hFindVolume, LPWSTR lpszVolumeName, DWORD cchBufferLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindNextVolumeW( HANDLE hFindVolume, LPWSTR lpszVolumeName, DWORD cchBufferLength )
+{
+    static FN_FindNextVolumeW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindNextVolumeW", &g_Kernel32);
+    return pfn( hFindVolume, lpszVolumeName, cchBufferLength );
+}
+
+typedef BOOL WINAPI FN_FindVolumeClose( HANDLE hFindVolume );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindVolumeClose( HANDLE hFindVolume )
+{
+    static FN_FindVolumeClose *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindVolumeClose", &g_Kernel32);
+    return pfn( hFindVolume );
+}
+
+typedef HANDLE WINAPI FN_FindFirstVolumeMountPointA( LPCSTR lpszRootPathName, LPSTR lpszVolumeMountPoint, DWORD cchBufferLength );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_FindFirstVolumeMountPointA( LPCSTR lpszRootPathName, LPSTR lpszVolumeMountPoint, DWORD cchBufferLength )
+{
+    static FN_FindFirstVolumeMountPointA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindFirstVolumeMountPointA", &g_Kernel32);
+    return pfn( lpszRootPathName, lpszVolumeMountPoint, cchBufferLength );
+}
+
+typedef HANDLE WINAPI FN_FindFirstVolumeMountPointW( LPCWSTR lpszRootPathName, LPWSTR lpszVolumeMountPoint, DWORD cchBufferLength );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_FindFirstVolumeMountPointW( LPCWSTR lpszRootPathName, LPWSTR lpszVolumeMountPoint, DWORD cchBufferLength )
+{
+    static FN_FindFirstVolumeMountPointW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindFirstVolumeMountPointW", &g_Kernel32);
+    return pfn( lpszRootPathName, lpszVolumeMountPoint, cchBufferLength );
+}
+
+typedef BOOL WINAPI FN_FindNextVolumeMountPointA( HANDLE hFindVolumeMountPoint, LPSTR lpszVolumeMountPoint, DWORD cchBufferLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindNextVolumeMountPointA( HANDLE hFindVolumeMountPoint, LPSTR lpszVolumeMountPoint, DWORD cchBufferLength )
+{
+    static FN_FindNextVolumeMountPointA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindNextVolumeMountPointA", &g_Kernel32);
+    return pfn( hFindVolumeMountPoint, lpszVolumeMountPoint, cchBufferLength );
+}
+
+typedef BOOL WINAPI FN_FindNextVolumeMountPointW( HANDLE hFindVolumeMountPoint, LPWSTR lpszVolumeMountPoint, DWORD cchBufferLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindNextVolumeMountPointW( HANDLE hFindVolumeMountPoint, LPWSTR lpszVolumeMountPoint, DWORD cchBufferLength )
+{
+    static FN_FindNextVolumeMountPointW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindNextVolumeMountPointW", &g_Kernel32);
+    return pfn( hFindVolumeMountPoint, lpszVolumeMountPoint, cchBufferLength );
+}
+
+typedef BOOL WINAPI FN_FindVolumeMountPointClose( HANDLE hFindVolumeMountPoint );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindVolumeMountPointClose( HANDLE hFindVolumeMountPoint )
+{
+    static FN_FindVolumeMountPointClose *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindVolumeMountPointClose", &g_Kernel32);
+    return pfn( hFindVolumeMountPoint );
+}
+
+typedef BOOL WINAPI FN_SetVolumeMountPointA( LPCSTR lpszVolumeMountPoint, LPCSTR lpszVolumeName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetVolumeMountPointA( LPCSTR lpszVolumeMountPoint, LPCSTR lpszVolumeName )
+{
+    static FN_SetVolumeMountPointA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetVolumeMountPointA", &g_Kernel32);
+    return pfn( lpszVolumeMountPoint, lpszVolumeName );
+}
+
+typedef BOOL WINAPI FN_SetVolumeMountPointW( LPCWSTR lpszVolumeMountPoint, LPCWSTR lpszVolumeName );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetVolumeMountPointW( LPCWSTR lpszVolumeMountPoint, LPCWSTR lpszVolumeName )
+{
+    static FN_SetVolumeMountPointW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetVolumeMountPointW", &g_Kernel32);
+    return pfn( lpszVolumeMountPoint, lpszVolumeName );
+}
+
+typedef BOOL WINAPI FN_DeleteVolumeMountPointA( LPCSTR lpszVolumeMountPoint );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DeleteVolumeMountPointA( LPCSTR lpszVolumeMountPoint )
+{
+    static FN_DeleteVolumeMountPointA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DeleteVolumeMountPointA", &g_Kernel32);
+    return pfn( lpszVolumeMountPoint );
+}
+
+typedef BOOL WINAPI FN_DeleteVolumeMountPointW( LPCWSTR lpszVolumeMountPoint );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DeleteVolumeMountPointW( LPCWSTR lpszVolumeMountPoint )
+{
+    static FN_DeleteVolumeMountPointW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DeleteVolumeMountPointW", &g_Kernel32);
+    return pfn( lpszVolumeMountPoint );
+}
+
+typedef BOOL WINAPI FN_GetVolumeNameForVolumeMountPointA( LPCSTR lpszVolumeMountPoint, LPSTR lpszVolumeName, DWORD cchBufferLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetVolumeNameForVolumeMountPointA( LPCSTR lpszVolumeMountPoint, LPSTR lpszVolumeName, DWORD cchBufferLength )
+{
+    static FN_GetVolumeNameForVolumeMountPointA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetVolumeNameForVolumeMountPointA", &g_Kernel32);
+    return pfn( lpszVolumeMountPoint, lpszVolumeName, cchBufferLength );
+}
+
+typedef BOOL WINAPI FN_GetVolumeNameForVolumeMountPointW( LPCWSTR lpszVolumeMountPoint, LPWSTR lpszVolumeName, DWORD cchBufferLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetVolumeNameForVolumeMountPointW( LPCWSTR lpszVolumeMountPoint, LPWSTR lpszVolumeName, DWORD cchBufferLength )
+{
+    static FN_GetVolumeNameForVolumeMountPointW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetVolumeNameForVolumeMountPointW", &g_Kernel32);
+    return pfn( lpszVolumeMountPoint, lpszVolumeName, cchBufferLength );
+}
+
+typedef BOOL WINAPI FN_GetVolumePathNameA( LPCSTR lpszFileName, LPSTR lpszVolumePathName, DWORD cchBufferLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetVolumePathNameA( LPCSTR lpszFileName, LPSTR lpszVolumePathName, DWORD cchBufferLength )
+{
+    static FN_GetVolumePathNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetVolumePathNameA", &g_Kernel32);
+    return pfn( lpszFileName, lpszVolumePathName, cchBufferLength );
+}
+
+typedef BOOL WINAPI FN_GetVolumePathNameW( LPCWSTR lpszFileName, LPWSTR lpszVolumePathName, DWORD cchBufferLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetVolumePathNameW( LPCWSTR lpszFileName, LPWSTR lpszVolumePathName, DWORD cchBufferLength )
+{
+    static FN_GetVolumePathNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetVolumePathNameW", &g_Kernel32);
+    return pfn( lpszFileName, lpszVolumePathName, cchBufferLength );
+}
+
+typedef BOOL WINAPI FN_GetVolumePathNamesForVolumeNameA( LPCSTR lpszVolumeName, LPCH lpszVolumePathNames, DWORD cchBufferLength, PDWORD lpcchReturnLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetVolumePathNamesForVolumeNameA( LPCSTR lpszVolumeName, LPCH lpszVolumePathNames, DWORD cchBufferLength, PDWORD lpcchReturnLength )
+{
+    static FN_GetVolumePathNamesForVolumeNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetVolumePathNamesForVolumeNameA", &g_Kernel32);
+    return pfn( lpszVolumeName, lpszVolumePathNames, cchBufferLength, lpcchReturnLength );
+}
+
+typedef BOOL WINAPI FN_GetVolumePathNamesForVolumeNameW( LPCWSTR lpszVolumeName, LPWCH lpszVolumePathNames, DWORD cchBufferLength, PDWORD lpcchReturnLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetVolumePathNamesForVolumeNameW( LPCWSTR lpszVolumeName, LPWCH lpszVolumePathNames, DWORD cchBufferLength, PDWORD lpcchReturnLength )
+{
+    static FN_GetVolumePathNamesForVolumeNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetVolumePathNamesForVolumeNameW", &g_Kernel32);
+    return pfn( lpszVolumeName, lpszVolumePathNames, cchBufferLength, lpcchReturnLength );
+}
+
+typedef HANDLE WINAPI FN_CreateActCtxA( PCACTCTXA pActCtx );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateActCtxA( PCACTCTXA pActCtx )
+{
+    static FN_CreateActCtxA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateActCtxA", &g_Kernel32);
+    return pfn( pActCtx );
+}
+
+typedef HANDLE WINAPI FN_CreateActCtxW( PCACTCTXW pActCtx );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateActCtxW( PCACTCTXW pActCtx )
+{
+    static FN_CreateActCtxW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateActCtxW", &g_Kernel32);
+    return pfn( pActCtx );
+}
+
+typedef VOID WINAPI FN_AddRefActCtx( HANDLE hActCtx );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_AddRefActCtx( HANDLE hActCtx )
+{
+    static FN_AddRefActCtx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddRefActCtx", &g_Kernel32);
+    pfn( hActCtx );
+}
+
+typedef VOID WINAPI FN_ReleaseActCtx( HANDLE hActCtx );
+__declspec(dllexport) VOID WINAPI kPrf2Wrap_ReleaseActCtx( HANDLE hActCtx )
+{
+    static FN_ReleaseActCtx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReleaseActCtx", &g_Kernel32);
+    pfn( hActCtx );
+}
+
+typedef BOOL WINAPI FN_ZombifyActCtx( HANDLE hActCtx );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ZombifyActCtx( HANDLE hActCtx )
+{
+    static FN_ZombifyActCtx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ZombifyActCtx", &g_Kernel32);
+    return pfn( hActCtx );
+}
+
+typedef BOOL WINAPI FN_ActivateActCtx( HANDLE hActCtx, ULONG_PTR * lpCookie );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ActivateActCtx( HANDLE hActCtx, ULONG_PTR * lpCookie )
+{
+    static FN_ActivateActCtx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ActivateActCtx", &g_Kernel32);
+    return pfn( hActCtx, lpCookie );
+}
+
+typedef BOOL WINAPI FN_DeactivateActCtx( DWORD dwFlags, ULONG_PTR ulCookie );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_DeactivateActCtx( DWORD dwFlags, ULONG_PTR ulCookie )
+{
+    static FN_DeactivateActCtx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "DeactivateActCtx", &g_Kernel32);
+    return pfn( dwFlags, ulCookie );
+}
+
+typedef BOOL WINAPI FN_GetCurrentActCtx( HANDLE * lphActCtx );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetCurrentActCtx( HANDLE * lphActCtx )
+{
+    static FN_GetCurrentActCtx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCurrentActCtx", &g_Kernel32);
+    return pfn( lphActCtx );
+}
+
+typedef BOOL WINAPI FN_FindActCtxSectionStringA( DWORD dwFlags, const GUID * lpExtensionGuid, ULONG ulSectionId, LPCSTR lpStringToFind, PACTCTX_SECTION_KEYED_DATA ReturnedData );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindActCtxSectionStringA( DWORD dwFlags, const GUID * lpExtensionGuid, ULONG ulSectionId, LPCSTR lpStringToFind, PACTCTX_SECTION_KEYED_DATA ReturnedData )
+{
+    static FN_FindActCtxSectionStringA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindActCtxSectionStringA", &g_Kernel32);
+    return pfn( dwFlags, lpExtensionGuid, ulSectionId, lpStringToFind, ReturnedData );
+}
+
+typedef BOOL WINAPI FN_FindActCtxSectionStringW( DWORD dwFlags, const GUID * lpExtensionGuid, ULONG ulSectionId, LPCWSTR lpStringToFind, PACTCTX_SECTION_KEYED_DATA ReturnedData );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindActCtxSectionStringW( DWORD dwFlags, const GUID * lpExtensionGuid, ULONG ulSectionId, LPCWSTR lpStringToFind, PACTCTX_SECTION_KEYED_DATA ReturnedData )
+{
+    static FN_FindActCtxSectionStringW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindActCtxSectionStringW", &g_Kernel32);
+    return pfn( dwFlags, lpExtensionGuid, ulSectionId, lpStringToFind, ReturnedData );
+}
+
+typedef BOOL WINAPI FN_FindActCtxSectionGuid( DWORD dwFlags, const GUID * lpExtensionGuid, ULONG ulSectionId, const GUID * lpGuidToFind, PACTCTX_SECTION_KEYED_DATA ReturnedData );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FindActCtxSectionGuid( DWORD dwFlags, const GUID * lpExtensionGuid, ULONG ulSectionId, const GUID * lpGuidToFind, PACTCTX_SECTION_KEYED_DATA ReturnedData )
+{
+    static FN_FindActCtxSectionGuid *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FindActCtxSectionGuid", &g_Kernel32);
+    return pfn( dwFlags, lpExtensionGuid, ulSectionId, lpGuidToFind, ReturnedData );
+}
+
+typedef BOOL WINAPI FN_QueryActCtxW( DWORD dwFlags, HANDLE hActCtx, PVOID pvSubInstance, ULONG ulInfoClass, PVOID pvBuffer, SIZE_T cbBuffer, SIZE_T * pcbWrittenOrRequired );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_QueryActCtxW( DWORD dwFlags, HANDLE hActCtx, PVOID pvSubInstance, ULONG ulInfoClass, PVOID pvBuffer, SIZE_T cbBuffer, SIZE_T * pcbWrittenOrRequired )
+{
+    static FN_QueryActCtxW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "QueryActCtxW", &g_Kernel32);
+    return pfn( dwFlags, hActCtx, pvSubInstance, ulInfoClass, pvBuffer, cbBuffer, pcbWrittenOrRequired );
+}
+
+typedef BOOL WINAPI FN_ProcessIdToSessionId( DWORD dwProcessId, DWORD * pSessionId );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ProcessIdToSessionId( DWORD dwProcessId, DWORD * pSessionId )
+{
+    static FN_ProcessIdToSessionId *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ProcessIdToSessionId", &g_Kernel32);
+    return pfn( dwProcessId, pSessionId );
+}
+
+typedef DWORD WINAPI FN_WTSGetActiveConsoleSessionId( );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_WTSGetActiveConsoleSessionId( )
+{
+    static FN_WTSGetActiveConsoleSessionId *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WTSGetActiveConsoleSessionId", &g_Kernel32);
+    return pfn( );
+}
+
+typedef BOOL WINAPI FN_IsWow64Process( HANDLE hProcess, PBOOL Wow64Process );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsWow64Process( HANDLE hProcess, PBOOL Wow64Process )
+{
+    static FN_IsWow64Process *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsWow64Process", &g_Kernel32);
+    return pfn( hProcess, Wow64Process );
+}
+
+typedef BOOL WINAPI FN_GetLogicalProcessorInformation( PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, PDWORD ReturnedLength );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetLogicalProcessorInformation( PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, PDWORD ReturnedLength )
+{
+    static FN_GetLogicalProcessorInformation *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetLogicalProcessorInformation", &g_Kernel32);
+    return pfn( Buffer, ReturnedLength );
+}
+
+typedef BOOL WINAPI FN_GetNumaHighestNodeNumber( PULONG HighestNodeNumber );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetNumaHighestNodeNumber( PULONG HighestNodeNumber )
+{
+    static FN_GetNumaHighestNodeNumber *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetNumaHighestNodeNumber", &g_Kernel32);
+    return pfn( HighestNodeNumber );
+}
+
+typedef BOOL WINAPI FN_GetNumaProcessorNode( UCHAR Processor, PUCHAR NodeNumber );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetNumaProcessorNode( UCHAR Processor, PUCHAR NodeNumber )
+{
+    static FN_GetNumaProcessorNode *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetNumaProcessorNode", &g_Kernel32);
+    return pfn( Processor, NodeNumber );
+}
+
+typedef BOOL WINAPI FN_GetNumaNodeProcessorMask( UCHAR Node, PULONGLONG ProcessorMask );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetNumaNodeProcessorMask( UCHAR Node, PULONGLONG ProcessorMask )
+{
+    static FN_GetNumaNodeProcessorMask *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetNumaNodeProcessorMask", &g_Kernel32);
+    return pfn( Node, ProcessorMask );
+}
+
+typedef BOOL WINAPI FN_GetNumaAvailableMemoryNode( UCHAR Node, PULONGLONG AvailableBytes );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetNumaAvailableMemoryNode( UCHAR Node, PULONGLONG AvailableBytes )
+{
+    static FN_GetNumaAvailableMemoryNode *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetNumaAvailableMemoryNode", &g_Kernel32);
+    return pfn( Node, AvailableBytes );
+}
+
+typedef BOOL WINAPI FN_PeekConsoleInputA( IN HANDLE hConsoleInput, OUT PINPUT_RECORD lpBuffer, IN DWORD nLength, OUT LPDWORD lpNumberOfEventsRead );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_PeekConsoleInputA( IN HANDLE hConsoleInput, OUT PINPUT_RECORD lpBuffer, IN DWORD nLength, OUT LPDWORD lpNumberOfEventsRead )
+{
+    static FN_PeekConsoleInputA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "PeekConsoleInputA", &g_Kernel32);
+    return pfn( hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead );
+}
+
+typedef BOOL WINAPI FN_PeekConsoleInputW( IN HANDLE hConsoleInput, OUT PINPUT_RECORD lpBuffer, IN DWORD nLength, OUT LPDWORD lpNumberOfEventsRead );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_PeekConsoleInputW( IN HANDLE hConsoleInput, OUT PINPUT_RECORD lpBuffer, IN DWORD nLength, OUT LPDWORD lpNumberOfEventsRead )
+{
+    static FN_PeekConsoleInputW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "PeekConsoleInputW", &g_Kernel32);
+    return pfn( hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead );
+}
+
+typedef BOOL WINAPI FN_ReadConsoleInputA( IN HANDLE hConsoleInput, OUT PINPUT_RECORD lpBuffer, IN DWORD nLength, OUT LPDWORD lpNumberOfEventsRead );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadConsoleInputA( IN HANDLE hConsoleInput, OUT PINPUT_RECORD lpBuffer, IN DWORD nLength, OUT LPDWORD lpNumberOfEventsRead )
+{
+    static FN_ReadConsoleInputA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadConsoleInputA", &g_Kernel32);
+    return pfn( hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead );
+}
+
+typedef BOOL WINAPI FN_ReadConsoleInputW( IN HANDLE hConsoleInput, OUT PINPUT_RECORD lpBuffer, IN DWORD nLength, OUT LPDWORD lpNumberOfEventsRead );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadConsoleInputW( IN HANDLE hConsoleInput, OUT PINPUT_RECORD lpBuffer, IN DWORD nLength, OUT LPDWORD lpNumberOfEventsRead )
+{
+    static FN_ReadConsoleInputW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadConsoleInputW", &g_Kernel32);
+    return pfn( hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead );
+}
+
+typedef BOOL WINAPI FN_WriteConsoleInputA( IN HANDLE hConsoleInput, IN CONST INPUT_RECORD * lpBuffer, IN DWORD nLength, OUT LPDWORD lpNumberOfEventsWritten );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteConsoleInputA( IN HANDLE hConsoleInput, IN CONST INPUT_RECORD * lpBuffer, IN DWORD nLength, OUT LPDWORD lpNumberOfEventsWritten )
+{
+    static FN_WriteConsoleInputA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteConsoleInputA", &g_Kernel32);
+    return pfn( hConsoleInput, lpBuffer, nLength, lpNumberOfEventsWritten );
+}
+
+typedef BOOL WINAPI FN_WriteConsoleInputW( IN HANDLE hConsoleInput, IN CONST INPUT_RECORD * lpBuffer, IN DWORD nLength, OUT LPDWORD lpNumberOfEventsWritten );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteConsoleInputW( IN HANDLE hConsoleInput, IN CONST INPUT_RECORD * lpBuffer, IN DWORD nLength, OUT LPDWORD lpNumberOfEventsWritten )
+{
+    static FN_WriteConsoleInputW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteConsoleInputW", &g_Kernel32);
+    return pfn( hConsoleInput, lpBuffer, nLength, lpNumberOfEventsWritten );
+}
+
+typedef BOOL WINAPI FN_ReadConsoleOutputA( IN HANDLE hConsoleOutput, OUT PCHAR_INFO lpBuffer, IN COORD dwBufferSize, IN COORD dwBufferCoord, IN OUT PSMALL_RECT lpReadRegion );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadConsoleOutputA( IN HANDLE hConsoleOutput, OUT PCHAR_INFO lpBuffer, IN COORD dwBufferSize, IN COORD dwBufferCoord, IN OUT PSMALL_RECT lpReadRegion )
+{
+    static FN_ReadConsoleOutputA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadConsoleOutputA", &g_Kernel32);
+    return pfn( hConsoleOutput, lpBuffer, dwBufferSize, dwBufferCoord, lpReadRegion );
+}
+
+typedef BOOL WINAPI FN_ReadConsoleOutputW( IN HANDLE hConsoleOutput, OUT PCHAR_INFO lpBuffer, IN COORD dwBufferSize, IN COORD dwBufferCoord, IN OUT PSMALL_RECT lpReadRegion );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadConsoleOutputW( IN HANDLE hConsoleOutput, OUT PCHAR_INFO lpBuffer, IN COORD dwBufferSize, IN COORD dwBufferCoord, IN OUT PSMALL_RECT lpReadRegion )
+{
+    static FN_ReadConsoleOutputW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadConsoleOutputW", &g_Kernel32);
+    return pfn( hConsoleOutput, lpBuffer, dwBufferSize, dwBufferCoord, lpReadRegion );
+}
+
+typedef BOOL WINAPI FN_WriteConsoleOutputA( IN HANDLE hConsoleOutput, IN CONST CHAR_INFO * lpBuffer, IN COORD dwBufferSize, IN COORD dwBufferCoord, IN OUT PSMALL_RECT lpWriteRegion );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteConsoleOutputA( IN HANDLE hConsoleOutput, IN CONST CHAR_INFO * lpBuffer, IN COORD dwBufferSize, IN COORD dwBufferCoord, IN OUT PSMALL_RECT lpWriteRegion )
+{
+    static FN_WriteConsoleOutputA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteConsoleOutputA", &g_Kernel32);
+    return pfn( hConsoleOutput, lpBuffer, dwBufferSize, dwBufferCoord, lpWriteRegion );
+}
+
+typedef BOOL WINAPI FN_WriteConsoleOutputW( IN HANDLE hConsoleOutput, IN CONST CHAR_INFO * lpBuffer, IN COORD dwBufferSize, IN COORD dwBufferCoord, IN OUT PSMALL_RECT lpWriteRegion );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteConsoleOutputW( IN HANDLE hConsoleOutput, IN CONST CHAR_INFO * lpBuffer, IN COORD dwBufferSize, IN COORD dwBufferCoord, IN OUT PSMALL_RECT lpWriteRegion )
+{
+    static FN_WriteConsoleOutputW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteConsoleOutputW", &g_Kernel32);
+    return pfn( hConsoleOutput, lpBuffer, dwBufferSize, dwBufferCoord, lpWriteRegion );
+}
+
+typedef BOOL WINAPI FN_ReadConsoleOutputCharacterA( IN HANDLE hConsoleOutput, OUT LPSTR lpCharacter, IN DWORD nLength, IN COORD dwReadCoord, OUT LPDWORD lpNumberOfCharsRead );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadConsoleOutputCharacterA( IN HANDLE hConsoleOutput, OUT LPSTR lpCharacter, IN DWORD nLength, IN COORD dwReadCoord, OUT LPDWORD lpNumberOfCharsRead )
+{
+    static FN_ReadConsoleOutputCharacterA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadConsoleOutputCharacterA", &g_Kernel32);
+    return pfn( hConsoleOutput, lpCharacter, nLength, dwReadCoord, lpNumberOfCharsRead );
+}
+
+typedef BOOL WINAPI FN_ReadConsoleOutputCharacterW( IN HANDLE hConsoleOutput, OUT LPWSTR lpCharacter, IN DWORD nLength, IN COORD dwReadCoord, OUT LPDWORD lpNumberOfCharsRead );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadConsoleOutputCharacterW( IN HANDLE hConsoleOutput, OUT LPWSTR lpCharacter, IN DWORD nLength, IN COORD dwReadCoord, OUT LPDWORD lpNumberOfCharsRead )
+{
+    static FN_ReadConsoleOutputCharacterW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadConsoleOutputCharacterW", &g_Kernel32);
+    return pfn( hConsoleOutput, lpCharacter, nLength, dwReadCoord, lpNumberOfCharsRead );
+}
+
+typedef BOOL WINAPI FN_ReadConsoleOutputAttribute( IN HANDLE hConsoleOutput, OUT LPWORD lpAttribute, IN DWORD nLength, IN COORD dwReadCoord, OUT LPDWORD lpNumberOfAttrsRead );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadConsoleOutputAttribute( IN HANDLE hConsoleOutput, OUT LPWORD lpAttribute, IN DWORD nLength, IN COORD dwReadCoord, OUT LPDWORD lpNumberOfAttrsRead )
+{
+    static FN_ReadConsoleOutputAttribute *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadConsoleOutputAttribute", &g_Kernel32);
+    return pfn( hConsoleOutput, lpAttribute, nLength, dwReadCoord, lpNumberOfAttrsRead );
+}
+
+typedef BOOL WINAPI FN_WriteConsoleOutputCharacterA( IN HANDLE hConsoleOutput, IN LPCSTR lpCharacter, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfCharsWritten );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteConsoleOutputCharacterA( IN HANDLE hConsoleOutput, IN LPCSTR lpCharacter, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfCharsWritten )
+{
+    static FN_WriteConsoleOutputCharacterA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteConsoleOutputCharacterA", &g_Kernel32);
+    return pfn( hConsoleOutput, lpCharacter, nLength, dwWriteCoord, lpNumberOfCharsWritten );
+}
+
+typedef BOOL WINAPI FN_WriteConsoleOutputCharacterW( IN HANDLE hConsoleOutput, IN LPCWSTR lpCharacter, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfCharsWritten );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteConsoleOutputCharacterW( IN HANDLE hConsoleOutput, IN LPCWSTR lpCharacter, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfCharsWritten )
+{
+    static FN_WriteConsoleOutputCharacterW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteConsoleOutputCharacterW", &g_Kernel32);
+    return pfn( hConsoleOutput, lpCharacter, nLength, dwWriteCoord, lpNumberOfCharsWritten );
+}
+
+typedef BOOL WINAPI FN_WriteConsoleOutputAttribute( IN HANDLE hConsoleOutput, IN CONST WORD * lpAttribute, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfAttrsWritten );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteConsoleOutputAttribute( IN HANDLE hConsoleOutput, IN CONST WORD * lpAttribute, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfAttrsWritten )
+{
+    static FN_WriteConsoleOutputAttribute *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteConsoleOutputAttribute", &g_Kernel32);
+    return pfn( hConsoleOutput, lpAttribute, nLength, dwWriteCoord, lpNumberOfAttrsWritten );
+}
+
+typedef BOOL WINAPI FN_FillConsoleOutputCharacterA( IN HANDLE hConsoleOutput, IN CHAR cCharacter, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfCharsWritten );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FillConsoleOutputCharacterA( IN HANDLE hConsoleOutput, IN CHAR cCharacter, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfCharsWritten )
+{
+    static FN_FillConsoleOutputCharacterA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FillConsoleOutputCharacterA", &g_Kernel32);
+    return pfn( hConsoleOutput, cCharacter, nLength, dwWriteCoord, lpNumberOfCharsWritten );
+}
+
+typedef BOOL WINAPI FN_FillConsoleOutputCharacterW( IN HANDLE hConsoleOutput, IN WCHAR cCharacter, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfCharsWritten );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FillConsoleOutputCharacterW( IN HANDLE hConsoleOutput, IN WCHAR cCharacter, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfCharsWritten )
+{
+    static FN_FillConsoleOutputCharacterW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FillConsoleOutputCharacterW", &g_Kernel32);
+    return pfn( hConsoleOutput, cCharacter, nLength, dwWriteCoord, lpNumberOfCharsWritten );
+}
+
+typedef BOOL WINAPI FN_FillConsoleOutputAttribute( IN HANDLE hConsoleOutput, IN WORD wAttribute, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfAttrsWritten );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FillConsoleOutputAttribute( IN HANDLE hConsoleOutput, IN WORD wAttribute, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfAttrsWritten )
+{
+    static FN_FillConsoleOutputAttribute *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FillConsoleOutputAttribute", &g_Kernel32);
+    return pfn( hConsoleOutput, wAttribute, nLength, dwWriteCoord, lpNumberOfAttrsWritten );
+}
+
+typedef BOOL WINAPI FN_GetConsoleMode( IN HANDLE hConsoleHandle, OUT LPDWORD lpMode );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetConsoleMode( IN HANDLE hConsoleHandle, OUT LPDWORD lpMode )
+{
+    static FN_GetConsoleMode *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleMode", &g_Kernel32);
+    return pfn( hConsoleHandle, lpMode );
+}
+
+typedef BOOL WINAPI FN_GetNumberOfConsoleInputEvents( IN HANDLE hConsoleInput, OUT LPDWORD lpNumberOfEvents );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetNumberOfConsoleInputEvents( IN HANDLE hConsoleInput, OUT LPDWORD lpNumberOfEvents )
+{
+    static FN_GetNumberOfConsoleInputEvents *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetNumberOfConsoleInputEvents", &g_Kernel32);
+    return pfn( hConsoleInput, lpNumberOfEvents );
+}
+
+typedef BOOL WINAPI FN_GetConsoleScreenBufferInfo( IN HANDLE hConsoleOutput, OUT PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetConsoleScreenBufferInfo( IN HANDLE hConsoleOutput, OUT PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo )
+{
+    static FN_GetConsoleScreenBufferInfo *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleScreenBufferInfo", &g_Kernel32);
+    return pfn( hConsoleOutput, lpConsoleScreenBufferInfo );
+}
+
+typedef COORD WINAPI FN_GetLargestConsoleWindowSize( IN HANDLE hConsoleOutput );
+__declspec(dllexport) COORD WINAPI kPrf2Wrap_GetLargestConsoleWindowSize( IN HANDLE hConsoleOutput )
+{
+    static FN_GetLargestConsoleWindowSize *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetLargestConsoleWindowSize", &g_Kernel32);
+    return pfn( hConsoleOutput );
+}
+
+typedef BOOL WINAPI FN_GetConsoleCursorInfo( IN HANDLE hConsoleOutput, OUT PCONSOLE_CURSOR_INFO lpConsoleCursorInfo );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetConsoleCursorInfo( IN HANDLE hConsoleOutput, OUT PCONSOLE_CURSOR_INFO lpConsoleCursorInfo )
+{
+    static FN_GetConsoleCursorInfo *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleCursorInfo", &g_Kernel32);
+    return pfn( hConsoleOutput, lpConsoleCursorInfo );
+}
+
+typedef BOOL WINAPI FN_GetCurrentConsoleFont( IN HANDLE hConsoleOutput, IN BOOL bMaximumWindow, OUT PCONSOLE_FONT_INFO lpConsoleCurrentFont );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetCurrentConsoleFont( IN HANDLE hConsoleOutput, IN BOOL bMaximumWindow, OUT PCONSOLE_FONT_INFO lpConsoleCurrentFont )
+{
+    static FN_GetCurrentConsoleFont *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCurrentConsoleFont", &g_Kernel32);
+    return pfn( hConsoleOutput, bMaximumWindow, lpConsoleCurrentFont );
+}
+
+typedef COORD WINAPI FN_GetConsoleFontSize( IN HANDLE hConsoleOutput, IN DWORD nFont );
+__declspec(dllexport) COORD WINAPI kPrf2Wrap_GetConsoleFontSize( IN HANDLE hConsoleOutput, IN DWORD nFont )
+{
+    static FN_GetConsoleFontSize *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleFontSize", &g_Kernel32);
+    return pfn( hConsoleOutput, nFont );
+}
+
+typedef BOOL WINAPI FN_GetConsoleSelectionInfo( OUT PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetConsoleSelectionInfo( OUT PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo )
+{
+    static FN_GetConsoleSelectionInfo *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleSelectionInfo", &g_Kernel32);
+    return pfn( lpConsoleSelectionInfo );
+}
+
+typedef BOOL WINAPI FN_GetNumberOfConsoleMouseButtons( OUT LPDWORD lpNumberOfMouseButtons );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetNumberOfConsoleMouseButtons( OUT LPDWORD lpNumberOfMouseButtons )
+{
+    static FN_GetNumberOfConsoleMouseButtons *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetNumberOfConsoleMouseButtons", &g_Kernel32);
+    return pfn( lpNumberOfMouseButtons );
+}
+
+typedef BOOL WINAPI FN_SetConsoleMode( IN HANDLE hConsoleHandle, IN DWORD dwMode );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetConsoleMode( IN HANDLE hConsoleHandle, IN DWORD dwMode )
+{
+    static FN_SetConsoleMode *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetConsoleMode", &g_Kernel32);
+    return pfn( hConsoleHandle, dwMode );
+}
+
+typedef BOOL WINAPI FN_SetConsoleActiveScreenBuffer( IN HANDLE hConsoleOutput );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetConsoleActiveScreenBuffer( IN HANDLE hConsoleOutput )
+{
+    static FN_SetConsoleActiveScreenBuffer *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetConsoleActiveScreenBuffer", &g_Kernel32);
+    return pfn( hConsoleOutput );
+}
+
+typedef BOOL WINAPI FN_FlushConsoleInputBuffer( IN HANDLE hConsoleInput );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FlushConsoleInputBuffer( IN HANDLE hConsoleInput )
+{
+    static FN_FlushConsoleInputBuffer *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FlushConsoleInputBuffer", &g_Kernel32);
+    return pfn( hConsoleInput );
+}
+
+typedef BOOL WINAPI FN_SetConsoleScreenBufferSize( IN HANDLE hConsoleOutput, IN COORD dwSize );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetConsoleScreenBufferSize( IN HANDLE hConsoleOutput, IN COORD dwSize )
+{
+    static FN_SetConsoleScreenBufferSize *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetConsoleScreenBufferSize", &g_Kernel32);
+    return pfn( hConsoleOutput, dwSize );
+}
+
+typedef BOOL WINAPI FN_SetConsoleCursorPosition( IN HANDLE hConsoleOutput, IN COORD dwCursorPosition );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetConsoleCursorPosition( IN HANDLE hConsoleOutput, IN COORD dwCursorPosition )
+{
+    static FN_SetConsoleCursorPosition *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetConsoleCursorPosition", &g_Kernel32);
+    return pfn( hConsoleOutput, dwCursorPosition );
+}
+
+typedef BOOL WINAPI FN_SetConsoleCursorInfo( IN HANDLE hConsoleOutput, IN CONST CONSOLE_CURSOR_INFO * lpConsoleCursorInfo );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetConsoleCursorInfo( IN HANDLE hConsoleOutput, IN CONST CONSOLE_CURSOR_INFO * lpConsoleCursorInfo )
+{
+    static FN_SetConsoleCursorInfo *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetConsoleCursorInfo", &g_Kernel32);
+    return pfn( hConsoleOutput, lpConsoleCursorInfo );
+}
+
+typedef BOOL WINAPI FN_ScrollConsoleScreenBufferA( IN HANDLE hConsoleOutput, IN CONST SMALL_RECT * lpScrollRectangle, IN CONST SMALL_RECT * lpClipRectangle, IN COORD dwDestinationOrigin, IN CONST CHAR_INFO * lpFill );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ScrollConsoleScreenBufferA( IN HANDLE hConsoleOutput, IN CONST SMALL_RECT * lpScrollRectangle, IN CONST SMALL_RECT * lpClipRectangle, IN COORD dwDestinationOrigin, IN CONST CHAR_INFO * lpFill )
+{
+    static FN_ScrollConsoleScreenBufferA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ScrollConsoleScreenBufferA", &g_Kernel32);
+    return pfn( hConsoleOutput, lpScrollRectangle, lpClipRectangle, dwDestinationOrigin, lpFill );
+}
+
+typedef BOOL WINAPI FN_ScrollConsoleScreenBufferW( IN HANDLE hConsoleOutput, IN CONST SMALL_RECT * lpScrollRectangle, IN CONST SMALL_RECT * lpClipRectangle, IN COORD dwDestinationOrigin, IN CONST CHAR_INFO * lpFill );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ScrollConsoleScreenBufferW( IN HANDLE hConsoleOutput, IN CONST SMALL_RECT * lpScrollRectangle, IN CONST SMALL_RECT * lpClipRectangle, IN COORD dwDestinationOrigin, IN CONST CHAR_INFO * lpFill )
+{
+    static FN_ScrollConsoleScreenBufferW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ScrollConsoleScreenBufferW", &g_Kernel32);
+    return pfn( hConsoleOutput, lpScrollRectangle, lpClipRectangle, dwDestinationOrigin, lpFill );
+}
+
+typedef BOOL WINAPI FN_SetConsoleWindowInfo( IN HANDLE hConsoleOutput, IN BOOL bAbsolute, IN CONST SMALL_RECT * lpConsoleWindow );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetConsoleWindowInfo( IN HANDLE hConsoleOutput, IN BOOL bAbsolute, IN CONST SMALL_RECT * lpConsoleWindow )
+{
+    static FN_SetConsoleWindowInfo *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetConsoleWindowInfo", &g_Kernel32);
+    return pfn( hConsoleOutput, bAbsolute, lpConsoleWindow );
+}
+
+typedef BOOL WINAPI FN_SetConsoleTextAttribute( IN HANDLE hConsoleOutput, IN WORD wAttributes );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetConsoleTextAttribute( IN HANDLE hConsoleOutput, IN WORD wAttributes )
+{
+    static FN_SetConsoleTextAttribute *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetConsoleTextAttribute", &g_Kernel32);
+    return pfn( hConsoleOutput, wAttributes );
+}
+
+typedef BOOL WINAPI FN_SetConsoleCtrlHandler( IN PHANDLER_ROUTINE HandlerRoutine, IN BOOL Add );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetConsoleCtrlHandler( IN PHANDLER_ROUTINE HandlerRoutine, IN BOOL Add )
+{
+    static FN_SetConsoleCtrlHandler *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetConsoleCtrlHandler", &g_Kernel32);
+    return pfn( HandlerRoutine, Add );
+}
+
+typedef BOOL WINAPI FN_GenerateConsoleCtrlEvent( IN DWORD dwCtrlEvent, IN DWORD dwProcessGroupId );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GenerateConsoleCtrlEvent( IN DWORD dwCtrlEvent, IN DWORD dwProcessGroupId )
+{
+    static FN_GenerateConsoleCtrlEvent *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GenerateConsoleCtrlEvent", &g_Kernel32);
+    return pfn( dwCtrlEvent, dwProcessGroupId );
+}
+
+typedef BOOL WINAPI FN_AllocConsole( VOID );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AllocConsole( VOID )
+{
+    static FN_AllocConsole *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AllocConsole", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL WINAPI FN_FreeConsole( VOID );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_FreeConsole( VOID )
+{
+    static FN_FreeConsole *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FreeConsole", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL WINAPI FN_AttachConsole( IN DWORD dwProcessId );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_AttachConsole( IN DWORD dwProcessId )
+{
+    static FN_AttachConsole *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AttachConsole", &g_Kernel32);
+    return pfn( dwProcessId );
+}
+
+typedef DWORD WINAPI FN_GetConsoleTitleA( OUT LPSTR lpConsoleTitle, IN DWORD nSize );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetConsoleTitleA( OUT LPSTR lpConsoleTitle, IN DWORD nSize )
+{
+    static FN_GetConsoleTitleA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleTitleA", &g_Kernel32);
+    return pfn( lpConsoleTitle, nSize );
+}
+
+typedef DWORD WINAPI FN_GetConsoleTitleW( OUT LPWSTR lpConsoleTitle, IN DWORD nSize );
+__declspec(dllexport) DWORD WINAPI kPrf2Wrap_GetConsoleTitleW( OUT LPWSTR lpConsoleTitle, IN DWORD nSize )
+{
+    static FN_GetConsoleTitleW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleTitleW", &g_Kernel32);
+    return pfn( lpConsoleTitle, nSize );
+}
+
+typedef BOOL WINAPI FN_SetConsoleTitleA( IN LPCSTR lpConsoleTitle );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetConsoleTitleA( IN LPCSTR lpConsoleTitle )
+{
+    static FN_SetConsoleTitleA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetConsoleTitleA", &g_Kernel32);
+    return pfn( lpConsoleTitle );
+}
+
+typedef BOOL WINAPI FN_SetConsoleTitleW( IN LPCWSTR lpConsoleTitle );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetConsoleTitleW( IN LPCWSTR lpConsoleTitle )
+{
+    static FN_SetConsoleTitleW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetConsoleTitleW", &g_Kernel32);
+    return pfn( lpConsoleTitle );
+}
+
+typedef BOOL WINAPI FN_ReadConsoleA( IN HANDLE hConsoleInput, OUT LPVOID lpBuffer, IN DWORD nNumberOfCharsToRead, OUT LPDWORD lpNumberOfCharsRead, IN LPVOID lpReserved );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadConsoleA( IN HANDLE hConsoleInput, OUT LPVOID lpBuffer, IN DWORD nNumberOfCharsToRead, OUT LPDWORD lpNumberOfCharsRead, IN LPVOID lpReserved )
+{
+    static FN_ReadConsoleA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadConsoleA", &g_Kernel32);
+    return pfn( hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved );
+}
+
+typedef BOOL WINAPI FN_ReadConsoleW( IN HANDLE hConsoleInput, OUT LPVOID lpBuffer, IN DWORD nNumberOfCharsToRead, OUT LPDWORD lpNumberOfCharsRead, IN LPVOID lpReserved );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReadConsoleW( IN HANDLE hConsoleInput, OUT LPVOID lpBuffer, IN DWORD nNumberOfCharsToRead, OUT LPDWORD lpNumberOfCharsRead, IN LPVOID lpReserved )
+{
+    static FN_ReadConsoleW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReadConsoleW", &g_Kernel32);
+    return pfn( hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved );
+}
+
+typedef BOOL WINAPI FN_WriteConsoleA( IN HANDLE hConsoleOutput, IN CONST VOID * lpBuffer, IN DWORD nNumberOfCharsToWrite, OUT LPDWORD lpNumberOfCharsWritten, IN LPVOID lpReserved );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteConsoleA( IN HANDLE hConsoleOutput, IN CONST VOID * lpBuffer, IN DWORD nNumberOfCharsToWrite, OUT LPDWORD lpNumberOfCharsWritten, IN LPVOID lpReserved )
+{
+    static FN_WriteConsoleA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteConsoleA", &g_Kernel32);
+    return pfn( hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved );
+}
+
+typedef BOOL WINAPI FN_WriteConsoleW( IN HANDLE hConsoleOutput, IN CONST VOID * lpBuffer, IN DWORD nNumberOfCharsToWrite, OUT LPDWORD lpNumberOfCharsWritten, IN LPVOID lpReserved );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_WriteConsoleW( IN HANDLE hConsoleOutput, IN CONST VOID * lpBuffer, IN DWORD nNumberOfCharsToWrite, OUT LPDWORD lpNumberOfCharsWritten, IN LPVOID lpReserved )
+{
+    static FN_WriteConsoleW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WriteConsoleW", &g_Kernel32);
+    return pfn( hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved );
+}
+
+typedef HANDLE WINAPI FN_CreateConsoleScreenBuffer( IN DWORD dwDesiredAccess, IN DWORD dwShareMode, IN CONST SECURITY_ATTRIBUTES * lpSecurityAttributes, IN DWORD dwFlags, IN LPVOID lpScreenBufferData );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateConsoleScreenBuffer( IN DWORD dwDesiredAccess, IN DWORD dwShareMode, IN CONST SECURITY_ATTRIBUTES * lpSecurityAttributes, IN DWORD dwFlags, IN LPVOID lpScreenBufferData )
+{
+    static FN_CreateConsoleScreenBuffer *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateConsoleScreenBuffer", &g_Kernel32);
+    return pfn( dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwFlags, lpScreenBufferData );
+}
+
+typedef UINT WINAPI FN_GetConsoleCP( VOID );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetConsoleCP( VOID )
+{
+    static FN_GetConsoleCP *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleCP", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL WINAPI FN_SetConsoleCP( IN UINT wCodePageID );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetConsoleCP( IN UINT wCodePageID )
+{
+    static FN_SetConsoleCP *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetConsoleCP", &g_Kernel32);
+    return pfn( wCodePageID );
+}
+
+typedef UINT WINAPI FN_GetConsoleOutputCP( VOID );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetConsoleOutputCP( VOID )
+{
+    static FN_GetConsoleOutputCP *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleOutputCP", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL WINAPI FN_SetConsoleOutputCP( IN UINT wCodePageID );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetConsoleOutputCP( IN UINT wCodePageID )
+{
+    static FN_SetConsoleOutputCP *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetConsoleOutputCP", &g_Kernel32);
+    return pfn( wCodePageID );
+}
+
+typedef BOOL APIENTRY FN_GetConsoleDisplayMode( OUT LPDWORD lpModeFlags );
+__declspec(dllexport) BOOL APIENTRY kPrf2Wrap_GetConsoleDisplayMode( OUT LPDWORD lpModeFlags )
+{
+    static FN_GetConsoleDisplayMode *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleDisplayMode", &g_Kernel32);
+    return pfn( lpModeFlags );
+}
+
+typedef HWND APIENTRY FN_GetConsoleWindow( VOID );
+__declspec(dllexport) HWND APIENTRY kPrf2Wrap_GetConsoleWindow( VOID )
+{
+    static FN_GetConsoleWindow *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleWindow", &g_Kernel32);
+    return pfn ();
+}
+
+typedef DWORD APIENTRY FN_GetConsoleProcessList( OUT LPDWORD lpdwProcessList, IN DWORD dwProcessCount );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_GetConsoleProcessList( OUT LPDWORD lpdwProcessList, IN DWORD dwProcessCount )
+{
+    static FN_GetConsoleProcessList *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleProcessList", &g_Kernel32);
+    return pfn( lpdwProcessList, dwProcessCount );
+}
+
+typedef BOOL APIENTRY FN_AddConsoleAliasA( IN LPSTR Source, IN LPSTR Target, IN LPSTR ExeName );
+__declspec(dllexport) BOOL APIENTRY kPrf2Wrap_AddConsoleAliasA( IN LPSTR Source, IN LPSTR Target, IN LPSTR ExeName )
+{
+    static FN_AddConsoleAliasA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddConsoleAliasA", &g_Kernel32);
+    return pfn( Source, Target, ExeName );
+}
+
+typedef BOOL APIENTRY FN_AddConsoleAliasW( IN LPWSTR Source, IN LPWSTR Target, IN LPWSTR ExeName );
+__declspec(dllexport) BOOL APIENTRY kPrf2Wrap_AddConsoleAliasW( IN LPWSTR Source, IN LPWSTR Target, IN LPWSTR ExeName )
+{
+    static FN_AddConsoleAliasW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "AddConsoleAliasW", &g_Kernel32);
+    return pfn( Source, Target, ExeName );
+}
+
+typedef DWORD APIENTRY FN_GetConsoleAliasA( IN LPSTR Source, OUT LPSTR TargetBuffer, IN DWORD TargetBufferLength, IN LPSTR ExeName );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_GetConsoleAliasA( IN LPSTR Source, OUT LPSTR TargetBuffer, IN DWORD TargetBufferLength, IN LPSTR ExeName )
+{
+    static FN_GetConsoleAliasA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleAliasA", &g_Kernel32);
+    return pfn( Source, TargetBuffer, TargetBufferLength, ExeName );
+}
+
+typedef DWORD APIENTRY FN_GetConsoleAliasW( IN LPWSTR Source, OUT LPWSTR TargetBuffer, IN DWORD TargetBufferLength, IN LPWSTR ExeName );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_GetConsoleAliasW( IN LPWSTR Source, OUT LPWSTR TargetBuffer, IN DWORD TargetBufferLength, IN LPWSTR ExeName )
+{
+    static FN_GetConsoleAliasW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleAliasW", &g_Kernel32);
+    return pfn( Source, TargetBuffer, TargetBufferLength, ExeName );
+}
+
+typedef DWORD APIENTRY FN_GetConsoleAliasesLengthA( IN LPSTR ExeName );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_GetConsoleAliasesLengthA( IN LPSTR ExeName )
+{
+    static FN_GetConsoleAliasesLengthA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleAliasesLengthA", &g_Kernel32);
+    return pfn( ExeName );
+}
+
+typedef DWORD APIENTRY FN_GetConsoleAliasesLengthW( IN LPWSTR ExeName );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_GetConsoleAliasesLengthW( IN LPWSTR ExeName )
+{
+    static FN_GetConsoleAliasesLengthW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleAliasesLengthW", &g_Kernel32);
+    return pfn( ExeName );
+}
+
+typedef DWORD APIENTRY FN_GetConsoleAliasExesLengthA( VOID );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_GetConsoleAliasExesLengthA( VOID )
+{
+    static FN_GetConsoleAliasExesLengthA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleAliasExesLengthA", &g_Kernel32);
+    return pfn ();
+}
+
+typedef DWORD APIENTRY FN_GetConsoleAliasExesLengthW( VOID );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_GetConsoleAliasExesLengthW( VOID )
+{
+    static FN_GetConsoleAliasExesLengthW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleAliasExesLengthW", &g_Kernel32);
+    return pfn ();
+}
+
+typedef DWORD APIENTRY FN_GetConsoleAliasesA( OUT LPSTR AliasBuffer, IN DWORD AliasBufferLength, IN LPSTR ExeName );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_GetConsoleAliasesA( OUT LPSTR AliasBuffer, IN DWORD AliasBufferLength, IN LPSTR ExeName )
+{
+    static FN_GetConsoleAliasesA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleAliasesA", &g_Kernel32);
+    return pfn( AliasBuffer, AliasBufferLength, ExeName );
+}
+
+typedef DWORD APIENTRY FN_GetConsoleAliasesW( OUT LPWSTR AliasBuffer, IN DWORD AliasBufferLength, IN LPWSTR ExeName );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_GetConsoleAliasesW( OUT LPWSTR AliasBuffer, IN DWORD AliasBufferLength, IN LPWSTR ExeName )
+{
+    static FN_GetConsoleAliasesW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleAliasesW", &g_Kernel32);
+    return pfn( AliasBuffer, AliasBufferLength, ExeName );
+}
+
+typedef DWORD APIENTRY FN_GetConsoleAliasExesA( OUT LPSTR ExeNameBuffer, IN DWORD ExeNameBufferLength );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_GetConsoleAliasExesA( OUT LPSTR ExeNameBuffer, IN DWORD ExeNameBufferLength )
+{
+    static FN_GetConsoleAliasExesA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleAliasExesA", &g_Kernel32);
+    return pfn( ExeNameBuffer, ExeNameBufferLength );
+}
+
+typedef DWORD APIENTRY FN_GetConsoleAliasExesW( OUT LPWSTR ExeNameBuffer, IN DWORD ExeNameBufferLength );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_GetConsoleAliasExesW( OUT LPWSTR ExeNameBuffer, IN DWORD ExeNameBufferLength )
+{
+    static FN_GetConsoleAliasExesW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetConsoleAliasExesW", &g_Kernel32);
+    return pfn( ExeNameBuffer, ExeNameBufferLength );
+}
+
+typedef BOOL WINAPI FN_IsValidCodePage( UINT CodePage );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsValidCodePage( UINT CodePage )
+{
+    static FN_IsValidCodePage *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsValidCodePage", &g_Kernel32);
+    return pfn( CodePage );
+}
+
+typedef UINT WINAPI FN_GetACP( void );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetACP( void )
+{
+    static FN_GetACP *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetACP", &g_Kernel32);
+    return pfn ();
+}
+
+typedef UINT WINAPI FN_GetOEMCP( void );
+__declspec(dllexport) UINT WINAPI kPrf2Wrap_GetOEMCP( void )
+{
+    static FN_GetOEMCP *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetOEMCP", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL WINAPI FN_GetCPInfo( UINT CodePage, LPCPINFO lpCPInfo );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetCPInfo( UINT CodePage, LPCPINFO lpCPInfo )
+{
+    static FN_GetCPInfo *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCPInfo", &g_Kernel32);
+    return pfn( CodePage, lpCPInfo );
+}
+
+typedef BOOL WINAPI FN_GetCPInfoExA( UINT CodePage, DWORD dwFlags, LPCPINFOEXA lpCPInfoEx );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetCPInfoExA( UINT CodePage, DWORD dwFlags, LPCPINFOEXA lpCPInfoEx )
+{
+    static FN_GetCPInfoExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCPInfoExA", &g_Kernel32);
+    return pfn( CodePage, dwFlags, lpCPInfoEx );
+}
+
+typedef BOOL WINAPI FN_GetCPInfoExW( UINT CodePage, DWORD dwFlags, LPCPINFOEXW lpCPInfoEx );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetCPInfoExW( UINT CodePage, DWORD dwFlags, LPCPINFOEXW lpCPInfoEx )
+{
+    static FN_GetCPInfoExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCPInfoExW", &g_Kernel32);
+    return pfn( CodePage, dwFlags, lpCPInfoEx );
+}
+
+typedef BOOL WINAPI FN_IsDBCSLeadByte( BYTE TestChar );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsDBCSLeadByte( BYTE TestChar )
+{
+    static FN_IsDBCSLeadByte *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsDBCSLeadByte", &g_Kernel32);
+    return pfn( TestChar );
+}
+
+typedef BOOL WINAPI FN_IsDBCSLeadByteEx( UINT CodePage, BYTE TestChar );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsDBCSLeadByteEx( UINT CodePage, BYTE TestChar )
+{
+    static FN_IsDBCSLeadByteEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsDBCSLeadByteEx", &g_Kernel32);
+    return pfn( CodePage, TestChar );
+}
+
+typedef int WINAPI FN_MultiByteToWideChar( UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar );
+__declspec(dllexport) int WINAPI kPrf2Wrap_MultiByteToWideChar( UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar )
+{
+    static FN_MultiByteToWideChar *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "MultiByteToWideChar", &g_Kernel32);
+    return pfn( CodePage, dwFlags, lpMultiByteStr, cbMultiByte, lpWideCharStr, cchWideChar );
+}
+
+typedef int WINAPI FN_WideCharToMultiByte( UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar );
+__declspec(dllexport) int WINAPI kPrf2Wrap_WideCharToMultiByte( UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar )
+{
+    static FN_WideCharToMultiByte *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "WideCharToMultiByte", &g_Kernel32);
+    return pfn( CodePage, dwFlags, lpWideCharStr, cchWideChar, lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar );
+}
+
+typedef int WINAPI FN_CompareStringA( LCID Locale, DWORD dwCmpFlags, LPCSTR lpString1, int cchCount1, LPCSTR lpString2, int cchCount2 );
+__declspec(dllexport) int WINAPI kPrf2Wrap_CompareStringA( LCID Locale, DWORD dwCmpFlags, LPCSTR lpString1, int cchCount1, LPCSTR lpString2, int cchCount2 )
+{
+    static FN_CompareStringA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CompareStringA", &g_Kernel32);
+    return pfn( Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2 );
+}
+
+typedef int WINAPI FN_CompareStringW( LCID Locale, DWORD dwCmpFlags, LPCWSTR lpString1, int cchCount1, LPCWSTR lpString2, int cchCount2 );
+__declspec(dllexport) int WINAPI kPrf2Wrap_CompareStringW( LCID Locale, DWORD dwCmpFlags, LPCWSTR lpString1, int cchCount1, LPCWSTR lpString2, int cchCount2 )
+{
+    static FN_CompareStringW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CompareStringW", &g_Kernel32);
+    return pfn( Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2 );
+}
+
+typedef int WINAPI FN_LCMapStringA( LCID Locale, DWORD dwMapFlags, LPCSTR lpSrcStr, int cchSrc, LPSTR lpDestStr, int cchDest );
+__declspec(dllexport) int WINAPI kPrf2Wrap_LCMapStringA( LCID Locale, DWORD dwMapFlags, LPCSTR lpSrcStr, int cchSrc, LPSTR lpDestStr, int cchDest )
+{
+    static FN_LCMapStringA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LCMapStringA", &g_Kernel32);
+    return pfn( Locale, dwMapFlags, lpSrcStr, cchSrc, lpDestStr, cchDest );
+}
+
+typedef int WINAPI FN_LCMapStringW( LCID Locale, DWORD dwMapFlags, LPCWSTR lpSrcStr, int cchSrc, LPWSTR lpDestStr, int cchDest );
+__declspec(dllexport) int WINAPI kPrf2Wrap_LCMapStringW( LCID Locale, DWORD dwMapFlags, LPCWSTR lpSrcStr, int cchSrc, LPWSTR lpDestStr, int cchDest )
+{
+    static FN_LCMapStringW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "LCMapStringW", &g_Kernel32);
+    return pfn( Locale, dwMapFlags, lpSrcStr, cchSrc, lpDestStr, cchDest );
+}
+
+typedef int WINAPI FN_GetLocaleInfoA( LCID Locale, LCTYPE LCType, LPSTR lpLCData, int cchData );
+__declspec(dllexport) int WINAPI kPrf2Wrap_GetLocaleInfoA( LCID Locale, LCTYPE LCType, LPSTR lpLCData, int cchData )
+{
+    static FN_GetLocaleInfoA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetLocaleInfoA", &g_Kernel32);
+    return pfn( Locale, LCType, lpLCData, cchData );
+}
+
+typedef int WINAPI FN_GetLocaleInfoW( LCID Locale, LCTYPE LCType, LPWSTR lpLCData, int cchData );
+__declspec(dllexport) int WINAPI kPrf2Wrap_GetLocaleInfoW( LCID Locale, LCTYPE LCType, LPWSTR lpLCData, int cchData )
+{
+    static FN_GetLocaleInfoW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetLocaleInfoW", &g_Kernel32);
+    return pfn( Locale, LCType, lpLCData, cchData );
+}
+
+typedef BOOL WINAPI FN_SetLocaleInfoA( LCID Locale, LCTYPE LCType, LPCSTR lpLCData );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetLocaleInfoA( LCID Locale, LCTYPE LCType, LPCSTR lpLCData )
+{
+    static FN_SetLocaleInfoA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetLocaleInfoA", &g_Kernel32);
+    return pfn( Locale, LCType, lpLCData );
+}
+
+typedef BOOL WINAPI FN_SetLocaleInfoW( LCID Locale, LCTYPE LCType, LPCWSTR lpLCData );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetLocaleInfoW( LCID Locale, LCTYPE LCType, LPCWSTR lpLCData )
+{
+    static FN_SetLocaleInfoW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetLocaleInfoW", &g_Kernel32);
+    return pfn( Locale, LCType, lpLCData );
+}
+
+typedef int WINAPI FN_GetCalendarInfoA( LCID Locale, CALID Calendar, CALTYPE CalType, LPSTR lpCalData, int cchData, LPDWORD lpValue );
+__declspec(dllexport) int WINAPI kPrf2Wrap_GetCalendarInfoA( LCID Locale, CALID Calendar, CALTYPE CalType, LPSTR lpCalData, int cchData, LPDWORD lpValue )
+{
+    static FN_GetCalendarInfoA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCalendarInfoA", &g_Kernel32);
+    return pfn( Locale, Calendar, CalType, lpCalData, cchData, lpValue );
+}
+
+typedef int WINAPI FN_GetCalendarInfoW( LCID Locale, CALID Calendar, CALTYPE CalType, LPWSTR lpCalData, int cchData, LPDWORD lpValue );
+__declspec(dllexport) int WINAPI kPrf2Wrap_GetCalendarInfoW( LCID Locale, CALID Calendar, CALTYPE CalType, LPWSTR lpCalData, int cchData, LPDWORD lpValue )
+{
+    static FN_GetCalendarInfoW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCalendarInfoW", &g_Kernel32);
+    return pfn( Locale, Calendar, CalType, lpCalData, cchData, lpValue );
+}
+
+typedef BOOL WINAPI FN_SetCalendarInfoA( LCID Locale, CALID Calendar, CALTYPE CalType, LPCSTR lpCalData );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetCalendarInfoA( LCID Locale, CALID Calendar, CALTYPE CalType, LPCSTR lpCalData )
+{
+    static FN_SetCalendarInfoA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetCalendarInfoA", &g_Kernel32);
+    return pfn( Locale, Calendar, CalType, lpCalData );
+}
+
+typedef BOOL WINAPI FN_SetCalendarInfoW( LCID Locale, CALID Calendar, CALTYPE CalType, LPCWSTR lpCalData );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetCalendarInfoW( LCID Locale, CALID Calendar, CALTYPE CalType, LPCWSTR lpCalData )
+{
+    static FN_SetCalendarInfoW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetCalendarInfoW", &g_Kernel32);
+    return pfn( Locale, Calendar, CalType, lpCalData );
+}
+
+typedef int WINAPI FN_GetTimeFormatA( LCID Locale, DWORD dwFlags, CONST SYSTEMTIME * lpTime, LPCSTR lpFormat, LPSTR lpTimeStr, int cchTime );
+__declspec(dllexport) int WINAPI kPrf2Wrap_GetTimeFormatA( LCID Locale, DWORD dwFlags, CONST SYSTEMTIME * lpTime, LPCSTR lpFormat, LPSTR lpTimeStr, int cchTime )
+{
+    static FN_GetTimeFormatA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetTimeFormatA", &g_Kernel32);
+    return pfn( Locale, dwFlags, lpTime, lpFormat, lpTimeStr, cchTime );
+}
+
+typedef int WINAPI FN_GetTimeFormatW( LCID Locale, DWORD dwFlags, CONST SYSTEMTIME * lpTime, LPCWSTR lpFormat, LPWSTR lpTimeStr, int cchTime );
+__declspec(dllexport) int WINAPI kPrf2Wrap_GetTimeFormatW( LCID Locale, DWORD dwFlags, CONST SYSTEMTIME * lpTime, LPCWSTR lpFormat, LPWSTR lpTimeStr, int cchTime )
+{
+    static FN_GetTimeFormatW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetTimeFormatW", &g_Kernel32);
+    return pfn( Locale, dwFlags, lpTime, lpFormat, lpTimeStr, cchTime );
+}
+
+typedef int WINAPI FN_GetDateFormatA( LCID Locale, DWORD dwFlags, CONST SYSTEMTIME * lpDate, LPCSTR lpFormat, LPSTR lpDateStr, int cchDate );
+__declspec(dllexport) int WINAPI kPrf2Wrap_GetDateFormatA( LCID Locale, DWORD dwFlags, CONST SYSTEMTIME * lpDate, LPCSTR lpFormat, LPSTR lpDateStr, int cchDate )
+{
+    static FN_GetDateFormatA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetDateFormatA", &g_Kernel32);
+    return pfn( Locale, dwFlags, lpDate, lpFormat, lpDateStr, cchDate );
+}
+
+typedef int WINAPI FN_GetDateFormatW( LCID Locale, DWORD dwFlags, CONST SYSTEMTIME * lpDate, LPCWSTR lpFormat, LPWSTR lpDateStr, int cchDate );
+__declspec(dllexport) int WINAPI kPrf2Wrap_GetDateFormatW( LCID Locale, DWORD dwFlags, CONST SYSTEMTIME * lpDate, LPCWSTR lpFormat, LPWSTR lpDateStr, int cchDate )
+{
+    static FN_GetDateFormatW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetDateFormatW", &g_Kernel32);
+    return pfn( Locale, dwFlags, lpDate, lpFormat, lpDateStr, cchDate );
+}
+
+typedef int WINAPI FN_GetNumberFormatA( LCID Locale, DWORD dwFlags, LPCSTR lpValue, CONST NUMBERFMTA * lpFormat, LPSTR lpNumberStr, int cchNumber );
+__declspec(dllexport) int WINAPI kPrf2Wrap_GetNumberFormatA( LCID Locale, DWORD dwFlags, LPCSTR lpValue, CONST NUMBERFMTA * lpFormat, LPSTR lpNumberStr, int cchNumber )
+{
+    static FN_GetNumberFormatA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetNumberFormatA", &g_Kernel32);
+    return pfn( Locale, dwFlags, lpValue, lpFormat, lpNumberStr, cchNumber );
+}
+
+typedef int WINAPI FN_GetNumberFormatW( LCID Locale, DWORD dwFlags, LPCWSTR lpValue, CONST NUMBERFMTW * lpFormat, LPWSTR lpNumberStr, int cchNumber );
+__declspec(dllexport) int WINAPI kPrf2Wrap_GetNumberFormatW( LCID Locale, DWORD dwFlags, LPCWSTR lpValue, CONST NUMBERFMTW * lpFormat, LPWSTR lpNumberStr, int cchNumber )
+{
+    static FN_GetNumberFormatW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetNumberFormatW", &g_Kernel32);
+    return pfn( Locale, dwFlags, lpValue, lpFormat, lpNumberStr, cchNumber );
+}
+
+typedef int WINAPI FN_GetCurrencyFormatA( LCID Locale, DWORD dwFlags, LPCSTR lpValue, CONST CURRENCYFMTA * lpFormat, LPSTR lpCurrencyStr, int cchCurrency );
+__declspec(dllexport) int WINAPI kPrf2Wrap_GetCurrencyFormatA( LCID Locale, DWORD dwFlags, LPCSTR lpValue, CONST CURRENCYFMTA * lpFormat, LPSTR lpCurrencyStr, int cchCurrency )
+{
+    static FN_GetCurrencyFormatA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCurrencyFormatA", &g_Kernel32);
+    return pfn( Locale, dwFlags, lpValue, lpFormat, lpCurrencyStr, cchCurrency );
+}
+
+typedef int WINAPI FN_GetCurrencyFormatW( LCID Locale, DWORD dwFlags, LPCWSTR lpValue, CONST CURRENCYFMTW * lpFormat, LPWSTR lpCurrencyStr, int cchCurrency );
+__declspec(dllexport) int WINAPI kPrf2Wrap_GetCurrencyFormatW( LCID Locale, DWORD dwFlags, LPCWSTR lpValue, CONST CURRENCYFMTW * lpFormat, LPWSTR lpCurrencyStr, int cchCurrency )
+{
+    static FN_GetCurrencyFormatW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetCurrencyFormatW", &g_Kernel32);
+    return pfn( Locale, dwFlags, lpValue, lpFormat, lpCurrencyStr, cchCurrency );
+}
+
+typedef BOOL WINAPI FN_EnumCalendarInfoA( CALINFO_ENUMPROCA lpCalInfoEnumProc, LCID Locale, CALID Calendar, CALTYPE CalType );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumCalendarInfoA( CALINFO_ENUMPROCA lpCalInfoEnumProc, LCID Locale, CALID Calendar, CALTYPE CalType )
+{
+    static FN_EnumCalendarInfoA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumCalendarInfoA", &g_Kernel32);
+    return pfn( lpCalInfoEnumProc, Locale, Calendar, CalType );
+}
+
+typedef BOOL WINAPI FN_EnumCalendarInfoW( CALINFO_ENUMPROCW lpCalInfoEnumProc, LCID Locale, CALID Calendar, CALTYPE CalType );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumCalendarInfoW( CALINFO_ENUMPROCW lpCalInfoEnumProc, LCID Locale, CALID Calendar, CALTYPE CalType )
+{
+    static FN_EnumCalendarInfoW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumCalendarInfoW", &g_Kernel32);
+    return pfn( lpCalInfoEnumProc, Locale, Calendar, CalType );
+}
+
+typedef BOOL WINAPI FN_EnumCalendarInfoExA( CALINFO_ENUMPROCEXA lpCalInfoEnumProcEx, LCID Locale, CALID Calendar, CALTYPE CalType );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumCalendarInfoExA( CALINFO_ENUMPROCEXA lpCalInfoEnumProcEx, LCID Locale, CALID Calendar, CALTYPE CalType )
+{
+    static FN_EnumCalendarInfoExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumCalendarInfoExA", &g_Kernel32);
+    return pfn( lpCalInfoEnumProcEx, Locale, Calendar, CalType );
+}
+
+typedef BOOL WINAPI FN_EnumCalendarInfoExW( CALINFO_ENUMPROCEXW lpCalInfoEnumProcEx, LCID Locale, CALID Calendar, CALTYPE CalType );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumCalendarInfoExW( CALINFO_ENUMPROCEXW lpCalInfoEnumProcEx, LCID Locale, CALID Calendar, CALTYPE CalType )
+{
+    static FN_EnumCalendarInfoExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumCalendarInfoExW", &g_Kernel32);
+    return pfn( lpCalInfoEnumProcEx, Locale, Calendar, CalType );
+}
+
+typedef BOOL WINAPI FN_EnumTimeFormatsA( TIMEFMT_ENUMPROCA lpTimeFmtEnumProc, LCID Locale, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumTimeFormatsA( TIMEFMT_ENUMPROCA lpTimeFmtEnumProc, LCID Locale, DWORD dwFlags )
+{
+    static FN_EnumTimeFormatsA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumTimeFormatsA", &g_Kernel32);
+    return pfn( lpTimeFmtEnumProc, Locale, dwFlags );
+}
+
+typedef BOOL WINAPI FN_EnumTimeFormatsW( TIMEFMT_ENUMPROCW lpTimeFmtEnumProc, LCID Locale, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumTimeFormatsW( TIMEFMT_ENUMPROCW lpTimeFmtEnumProc, LCID Locale, DWORD dwFlags )
+{
+    static FN_EnumTimeFormatsW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumTimeFormatsW", &g_Kernel32);
+    return pfn( lpTimeFmtEnumProc, Locale, dwFlags );
+}
+
+typedef BOOL WINAPI FN_EnumDateFormatsA( DATEFMT_ENUMPROCA lpDateFmtEnumProc, LCID Locale, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumDateFormatsA( DATEFMT_ENUMPROCA lpDateFmtEnumProc, LCID Locale, DWORD dwFlags )
+{
+    static FN_EnumDateFormatsA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumDateFormatsA", &g_Kernel32);
+    return pfn( lpDateFmtEnumProc, Locale, dwFlags );
+}
+
+typedef BOOL WINAPI FN_EnumDateFormatsW( DATEFMT_ENUMPROCW lpDateFmtEnumProc, LCID Locale, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumDateFormatsW( DATEFMT_ENUMPROCW lpDateFmtEnumProc, LCID Locale, DWORD dwFlags )
+{
+    static FN_EnumDateFormatsW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumDateFormatsW", &g_Kernel32);
+    return pfn( lpDateFmtEnumProc, Locale, dwFlags );
+}
+
+typedef BOOL WINAPI FN_EnumDateFormatsExA( DATEFMT_ENUMPROCEXA lpDateFmtEnumProcEx, LCID Locale, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumDateFormatsExA( DATEFMT_ENUMPROCEXA lpDateFmtEnumProcEx, LCID Locale, DWORD dwFlags )
+{
+    static FN_EnumDateFormatsExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumDateFormatsExA", &g_Kernel32);
+    return pfn( lpDateFmtEnumProcEx, Locale, dwFlags );
+}
+
+typedef BOOL WINAPI FN_EnumDateFormatsExW( DATEFMT_ENUMPROCEXW lpDateFmtEnumProcEx, LCID Locale, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumDateFormatsExW( DATEFMT_ENUMPROCEXW lpDateFmtEnumProcEx, LCID Locale, DWORD dwFlags )
+{
+    static FN_EnumDateFormatsExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumDateFormatsExW", &g_Kernel32);
+    return pfn( lpDateFmtEnumProcEx, Locale, dwFlags );
+}
+
+typedef BOOL WINAPI FN_IsValidLanguageGroup( LGRPID LanguageGroup, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsValidLanguageGroup( LGRPID LanguageGroup, DWORD dwFlags )
+{
+    static FN_IsValidLanguageGroup *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsValidLanguageGroup", &g_Kernel32);
+    return pfn( LanguageGroup, dwFlags );
+}
+
+typedef BOOL WINAPI FN_GetNLSVersion( NLS_FUNCTION Function, LCID Locale, LPNLSVERSIONINFO lpVersionInformation );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetNLSVersion( NLS_FUNCTION Function, LCID Locale, LPNLSVERSIONINFO lpVersionInformation )
+{
+    static FN_GetNLSVersion *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetNLSVersion", &g_Kernel32);
+    return pfn( Function, Locale, lpVersionInformation );
+}
+
+typedef BOOL WINAPI FN_IsNLSDefinedString( NLS_FUNCTION Function, DWORD dwFlags, LPNLSVERSIONINFO lpVersionInformation, LPCWSTR lpString, INT cchStr );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsNLSDefinedString( NLS_FUNCTION Function, DWORD dwFlags, LPNLSVERSIONINFO lpVersionInformation, LPCWSTR lpString, INT cchStr )
+{
+    static FN_IsNLSDefinedString *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsNLSDefinedString", &g_Kernel32);
+    return pfn( Function, dwFlags, lpVersionInformation, lpString, cchStr );
+}
+
+typedef BOOL WINAPI FN_IsValidLocale( LCID Locale, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_IsValidLocale( LCID Locale, DWORD dwFlags )
+{
+    static FN_IsValidLocale *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "IsValidLocale", &g_Kernel32);
+    return pfn( Locale, dwFlags );
+}
+
+typedef int WINAPI FN_GetGeoInfoA( GEOID Location, GEOTYPE GeoType, LPSTR lpGeoData, int cchData, LANGID LangId );
+__declspec(dllexport) int WINAPI kPrf2Wrap_GetGeoInfoA( GEOID Location, GEOTYPE GeoType, LPSTR lpGeoData, int cchData, LANGID LangId )
+{
+    static FN_GetGeoInfoA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetGeoInfoA", &g_Kernel32);
+    return pfn( Location, GeoType, lpGeoData, cchData, LangId );
+}
+
+typedef int WINAPI FN_GetGeoInfoW( GEOID Location, GEOTYPE GeoType, LPWSTR lpGeoData, int cchData, LANGID LangId );
+__declspec(dllexport) int WINAPI kPrf2Wrap_GetGeoInfoW( GEOID Location, GEOTYPE GeoType, LPWSTR lpGeoData, int cchData, LANGID LangId )
+{
+    static FN_GetGeoInfoW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetGeoInfoW", &g_Kernel32);
+    return pfn( Location, GeoType, lpGeoData, cchData, LangId );
+}
+
+typedef BOOL WINAPI FN_EnumSystemGeoID( GEOCLASS GeoClass, GEOID ParentGeoId, GEO_ENUMPROC lpGeoEnumProc );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumSystemGeoID( GEOCLASS GeoClass, GEOID ParentGeoId, GEO_ENUMPROC lpGeoEnumProc )
+{
+    static FN_EnumSystemGeoID *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumSystemGeoID", &g_Kernel32);
+    return pfn( GeoClass, ParentGeoId, lpGeoEnumProc );
+}
+
+typedef GEOID WINAPI FN_GetUserGeoID( GEOCLASS GeoClass );
+__declspec(dllexport) GEOID WINAPI kPrf2Wrap_GetUserGeoID( GEOCLASS GeoClass )
+{
+    static FN_GetUserGeoID *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetUserGeoID", &g_Kernel32);
+    return pfn( GeoClass );
+}
+
+typedef BOOL WINAPI FN_SetUserGeoID( GEOID GeoId );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetUserGeoID( GEOID GeoId )
+{
+    static FN_SetUserGeoID *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetUserGeoID", &g_Kernel32);
+    return pfn( GeoId );
+}
+
+typedef LCID WINAPI FN_ConvertDefaultLocale( LCID Locale );
+__declspec(dllexport) LCID WINAPI kPrf2Wrap_ConvertDefaultLocale( LCID Locale )
+{
+    static FN_ConvertDefaultLocale *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ConvertDefaultLocale", &g_Kernel32);
+    return pfn( Locale );
+}
+
+typedef LCID WINAPI FN_GetThreadLocale( void );
+__declspec(dllexport) LCID WINAPI kPrf2Wrap_GetThreadLocale( void )
+{
+    static FN_GetThreadLocale *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetThreadLocale", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL WINAPI FN_SetThreadLocale( LCID Locale );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetThreadLocale( LCID Locale )
+{
+    static FN_SetThreadLocale *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetThreadLocale", &g_Kernel32);
+    return pfn( Locale );
+}
+
+typedef LANGID WINAPI FN_GetSystemDefaultUILanguage( void );
+__declspec(dllexport) LANGID WINAPI kPrf2Wrap_GetSystemDefaultUILanguage( void )
+{
+    static FN_GetSystemDefaultUILanguage *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemDefaultUILanguage", &g_Kernel32);
+    return pfn ();
+}
+
+typedef LANGID WINAPI FN_GetUserDefaultUILanguage( void );
+__declspec(dllexport) LANGID WINAPI kPrf2Wrap_GetUserDefaultUILanguage( void )
+{
+    static FN_GetUserDefaultUILanguage *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetUserDefaultUILanguage", &g_Kernel32);
+    return pfn ();
+}
+
+typedef LANGID WINAPI FN_GetSystemDefaultLangID( void );
+__declspec(dllexport) LANGID WINAPI kPrf2Wrap_GetSystemDefaultLangID( void )
+{
+    static FN_GetSystemDefaultLangID *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemDefaultLangID", &g_Kernel32);
+    return pfn ();
+}
+
+typedef LANGID WINAPI FN_GetUserDefaultLangID( void );
+__declspec(dllexport) LANGID WINAPI kPrf2Wrap_GetUserDefaultLangID( void )
+{
+    static FN_GetUserDefaultLangID *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetUserDefaultLangID", &g_Kernel32);
+    return pfn ();
+}
+
+typedef LCID WINAPI FN_GetSystemDefaultLCID( void );
+__declspec(dllexport) LCID WINAPI kPrf2Wrap_GetSystemDefaultLCID( void )
+{
+    static FN_GetSystemDefaultLCID *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetSystemDefaultLCID", &g_Kernel32);
+    return pfn ();
+}
+
+typedef LCID WINAPI FN_GetUserDefaultLCID( void );
+__declspec(dllexport) LCID WINAPI kPrf2Wrap_GetUserDefaultLCID( void )
+{
+    static FN_GetUserDefaultLCID *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetUserDefaultLCID", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL WINAPI FN_GetStringTypeExA( LCID Locale, DWORD dwInfoType, LPCSTR lpSrcStr, int cchSrc, LPWORD lpCharType );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetStringTypeExA( LCID Locale, DWORD dwInfoType, LPCSTR lpSrcStr, int cchSrc, LPWORD lpCharType )
+{
+    static FN_GetStringTypeExA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetStringTypeExA", &g_Kernel32);
+    return pfn( Locale, dwInfoType, lpSrcStr, cchSrc, lpCharType );
+}
+
+typedef BOOL WINAPI FN_GetStringTypeExW( LCID Locale, DWORD dwInfoType, LPCWSTR lpSrcStr, int cchSrc, LPWORD lpCharType );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetStringTypeExW( LCID Locale, DWORD dwInfoType, LPCWSTR lpSrcStr, int cchSrc, LPWORD lpCharType )
+{
+    static FN_GetStringTypeExW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetStringTypeExW", &g_Kernel32);
+    return pfn( Locale, dwInfoType, lpSrcStr, cchSrc, lpCharType );
+}
+
+typedef BOOL WINAPI FN_GetStringTypeA( LCID Locale, DWORD dwInfoType, LPCSTR lpSrcStr, int cchSrc, LPWORD lpCharType );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetStringTypeA( LCID Locale, DWORD dwInfoType, LPCSTR lpSrcStr, int cchSrc, LPWORD lpCharType )
+{
+    static FN_GetStringTypeA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetStringTypeA", &g_Kernel32);
+    return pfn( Locale, dwInfoType, lpSrcStr, cchSrc, lpCharType );
+}
+
+typedef BOOL WINAPI FN_GetStringTypeW( DWORD dwInfoType, LPCWSTR lpSrcStr, int cchSrc, LPWORD lpCharType );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetStringTypeW( DWORD dwInfoType, LPCWSTR lpSrcStr, int cchSrc, LPWORD lpCharType )
+{
+    static FN_GetStringTypeW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetStringTypeW", &g_Kernel32);
+    return pfn( dwInfoType, lpSrcStr, cchSrc, lpCharType );
+}
+
+typedef int WINAPI FN_FoldStringA( DWORD dwMapFlags, LPCSTR lpSrcStr, int cchSrc, LPSTR lpDestStr, int cchDest );
+__declspec(dllexport) int WINAPI kPrf2Wrap_FoldStringA( DWORD dwMapFlags, LPCSTR lpSrcStr, int cchSrc, LPSTR lpDestStr, int cchDest )
+{
+    static FN_FoldStringA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FoldStringA", &g_Kernel32);
+    return pfn( dwMapFlags, lpSrcStr, cchSrc, lpDestStr, cchDest );
+}
+
+typedef int WINAPI FN_FoldStringW( DWORD dwMapFlags, LPCWSTR lpSrcStr, int cchSrc, LPWSTR lpDestStr, int cchDest );
+__declspec(dllexport) int WINAPI kPrf2Wrap_FoldStringW( DWORD dwMapFlags, LPCWSTR lpSrcStr, int cchSrc, LPWSTR lpDestStr, int cchDest )
+{
+    static FN_FoldStringW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "FoldStringW", &g_Kernel32);
+    return pfn( dwMapFlags, lpSrcStr, cchSrc, lpDestStr, cchDest );
+}
+
+typedef BOOL WINAPI FN_EnumSystemLanguageGroupsA( LANGUAGEGROUP_ENUMPROCA lpLanguageGroupEnumProc, DWORD dwFlags, LONG_PTR lParam );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumSystemLanguageGroupsA( LANGUAGEGROUP_ENUMPROCA lpLanguageGroupEnumProc, DWORD dwFlags, LONG_PTR lParam )
+{
+    static FN_EnumSystemLanguageGroupsA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumSystemLanguageGroupsA", &g_Kernel32);
+    return pfn( lpLanguageGroupEnumProc, dwFlags, lParam );
+}
+
+typedef BOOL WINAPI FN_EnumSystemLanguageGroupsW( LANGUAGEGROUP_ENUMPROCW lpLanguageGroupEnumProc, DWORD dwFlags, LONG_PTR lParam );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumSystemLanguageGroupsW( LANGUAGEGROUP_ENUMPROCW lpLanguageGroupEnumProc, DWORD dwFlags, LONG_PTR lParam )
+{
+    static FN_EnumSystemLanguageGroupsW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumSystemLanguageGroupsW", &g_Kernel32);
+    return pfn( lpLanguageGroupEnumProc, dwFlags, lParam );
+}
+
+typedef BOOL WINAPI FN_EnumLanguageGroupLocalesA( LANGGROUPLOCALE_ENUMPROCA lpLangGroupLocaleEnumProc, LGRPID LanguageGroup, DWORD dwFlags, LONG_PTR lParam );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumLanguageGroupLocalesA( LANGGROUPLOCALE_ENUMPROCA lpLangGroupLocaleEnumProc, LGRPID LanguageGroup, DWORD dwFlags, LONG_PTR lParam )
+{
+    static FN_EnumLanguageGroupLocalesA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumLanguageGroupLocalesA", &g_Kernel32);
+    return pfn( lpLangGroupLocaleEnumProc, LanguageGroup, dwFlags, lParam );
+}
+
+typedef BOOL WINAPI FN_EnumLanguageGroupLocalesW( LANGGROUPLOCALE_ENUMPROCW lpLangGroupLocaleEnumProc, LGRPID LanguageGroup, DWORD dwFlags, LONG_PTR lParam );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumLanguageGroupLocalesW( LANGGROUPLOCALE_ENUMPROCW lpLangGroupLocaleEnumProc, LGRPID LanguageGroup, DWORD dwFlags, LONG_PTR lParam )
+{
+    static FN_EnumLanguageGroupLocalesW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumLanguageGroupLocalesW", &g_Kernel32);
+    return pfn( lpLangGroupLocaleEnumProc, LanguageGroup, dwFlags, lParam );
+}
+
+typedef BOOL WINAPI FN_EnumUILanguagesA( UILANGUAGE_ENUMPROCA lpUILanguageEnumProc, DWORD dwFlags, LONG_PTR lParam );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumUILanguagesA( UILANGUAGE_ENUMPROCA lpUILanguageEnumProc, DWORD dwFlags, LONG_PTR lParam )
+{
+    static FN_EnumUILanguagesA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumUILanguagesA", &g_Kernel32);
+    return pfn( lpUILanguageEnumProc, dwFlags, lParam );
+}
+
+typedef BOOL WINAPI FN_EnumUILanguagesW( UILANGUAGE_ENUMPROCW lpUILanguageEnumProc, DWORD dwFlags, LONG_PTR lParam );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumUILanguagesW( UILANGUAGE_ENUMPROCW lpUILanguageEnumProc, DWORD dwFlags, LONG_PTR lParam )
+{
+    static FN_EnumUILanguagesW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumUILanguagesW", &g_Kernel32);
+    return pfn( lpUILanguageEnumProc, dwFlags, lParam );
+}
+
+typedef BOOL WINAPI FN_EnumSystemLocalesA( LOCALE_ENUMPROCA lpLocaleEnumProc, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumSystemLocalesA( LOCALE_ENUMPROCA lpLocaleEnumProc, DWORD dwFlags )
+{
+    static FN_EnumSystemLocalesA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumSystemLocalesA", &g_Kernel32);
+    return pfn( lpLocaleEnumProc, dwFlags );
+}
+
+typedef BOOL WINAPI FN_EnumSystemLocalesW( LOCALE_ENUMPROCW lpLocaleEnumProc, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumSystemLocalesW( LOCALE_ENUMPROCW lpLocaleEnumProc, DWORD dwFlags )
+{
+    static FN_EnumSystemLocalesW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumSystemLocalesW", &g_Kernel32);
+    return pfn( lpLocaleEnumProc, dwFlags );
+}
+
+typedef BOOL WINAPI FN_EnumSystemCodePagesA( CODEPAGE_ENUMPROCA lpCodePageEnumProc, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumSystemCodePagesA( CODEPAGE_ENUMPROCA lpCodePageEnumProc, DWORD dwFlags )
+{
+    static FN_EnumSystemCodePagesA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumSystemCodePagesA", &g_Kernel32);
+    return pfn( lpCodePageEnumProc, dwFlags );
+}
+
+typedef BOOL WINAPI FN_EnumSystemCodePagesW( CODEPAGE_ENUMPROCW lpCodePageEnumProc, DWORD dwFlags );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_EnumSystemCodePagesW( CODEPAGE_ENUMPROCW lpCodePageEnumProc, DWORD dwFlags )
+{
+    static FN_EnumSystemCodePagesW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "EnumSystemCodePagesW", &g_Kernel32);
+    return pfn( lpCodePageEnumProc, dwFlags );
+}
+
+typedef DWORD APIENTRY FN_VerFindFileA( DWORD uFlags, LPSTR szFileName, LPSTR szWinDir, LPSTR szAppDir, LPSTR szCurDir, PUINT lpuCurDirLen, LPSTR szDestDir, PUINT lpuDestDirLen );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_VerFindFileA( DWORD uFlags, LPSTR szFileName, LPSTR szWinDir, LPSTR szAppDir, LPSTR szCurDir, PUINT lpuCurDirLen, LPSTR szDestDir, PUINT lpuDestDirLen )
+{
+    static FN_VerFindFileA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VerFindFileA", &g_Kernel32);
+    return pfn( uFlags, szFileName, szWinDir, szAppDir, szCurDir, lpuCurDirLen, szDestDir, lpuDestDirLen );
+}
+
+typedef DWORD APIENTRY FN_VerFindFileW( DWORD uFlags, LPWSTR szFileName, LPWSTR szWinDir, LPWSTR szAppDir, LPWSTR szCurDir, PUINT lpuCurDirLen, LPWSTR szDestDir, PUINT lpuDestDirLen );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_VerFindFileW( DWORD uFlags, LPWSTR szFileName, LPWSTR szWinDir, LPWSTR szAppDir, LPWSTR szCurDir, PUINT lpuCurDirLen, LPWSTR szDestDir, PUINT lpuDestDirLen )
+{
+    static FN_VerFindFileW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VerFindFileW", &g_Kernel32);
+    return pfn( uFlags, szFileName, szWinDir, szAppDir, szCurDir, lpuCurDirLen, szDestDir, lpuDestDirLen );
+}
+
+typedef DWORD APIENTRY FN_VerInstallFileA( DWORD uFlags, LPSTR szSrcFileName, LPSTR szDestFileName, LPSTR szSrcDir, LPSTR szDestDir, LPSTR szCurDir, LPSTR szTmpFile, PUINT lpuTmpFileLen );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_VerInstallFileA( DWORD uFlags, LPSTR szSrcFileName, LPSTR szDestFileName, LPSTR szSrcDir, LPSTR szDestDir, LPSTR szCurDir, LPSTR szTmpFile, PUINT lpuTmpFileLen )
+{
+    static FN_VerInstallFileA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VerInstallFileA", &g_Kernel32);
+    return pfn( uFlags, szSrcFileName, szDestFileName, szSrcDir, szDestDir, szCurDir, szTmpFile, lpuTmpFileLen );
+}
+
+typedef DWORD APIENTRY FN_VerInstallFileW( DWORD uFlags, LPWSTR szSrcFileName, LPWSTR szDestFileName, LPWSTR szSrcDir, LPWSTR szDestDir, LPWSTR szCurDir, LPWSTR szTmpFile, PUINT lpuTmpFileLen );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_VerInstallFileW( DWORD uFlags, LPWSTR szSrcFileName, LPWSTR szDestFileName, LPWSTR szSrcDir, LPWSTR szDestDir, LPWSTR szCurDir, LPWSTR szTmpFile, PUINT lpuTmpFileLen )
+{
+    static FN_VerInstallFileW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VerInstallFileW", &g_Kernel32);
+    return pfn( uFlags, szSrcFileName, szDestFileName, szSrcDir, szDestDir, szCurDir, szTmpFile, lpuTmpFileLen );
+}
+
+typedef DWORD APIENTRY FN_GetFileVersionInfoSizeA( LPCSTR lptstrFilename, LPDWORD lpdwHandle );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_GetFileVersionInfoSizeA( LPCSTR lptstrFilename, LPDWORD lpdwHandle )
+{
+    static FN_GetFileVersionInfoSizeA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFileVersionInfoSizeA", &g_Kernel32);
+    return pfn( lptstrFilename, lpdwHandle );
+}
+
+typedef DWORD APIENTRY FN_GetFileVersionInfoSizeW( LPCWSTR lptstrFilename, LPDWORD lpdwHandle );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_GetFileVersionInfoSizeW( LPCWSTR lptstrFilename, LPDWORD lpdwHandle )
+{
+    static FN_GetFileVersionInfoSizeW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFileVersionInfoSizeW", &g_Kernel32);
+    return pfn( lptstrFilename, lpdwHandle );
+}
+
+typedef BOOL APIENTRY FN_GetFileVersionInfoA( LPCSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData );
+__declspec(dllexport) BOOL APIENTRY kPrf2Wrap_GetFileVersionInfoA( LPCSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData )
+{
+    static FN_GetFileVersionInfoA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFileVersionInfoA", &g_Kernel32);
+    return pfn( lptstrFilename, dwHandle, dwLen, lpData );
+}
+
+typedef BOOL APIENTRY FN_GetFileVersionInfoW( LPCWSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData );
+__declspec(dllexport) BOOL APIENTRY kPrf2Wrap_GetFileVersionInfoW( LPCWSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData )
+{
+    static FN_GetFileVersionInfoW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetFileVersionInfoW", &g_Kernel32);
+    return pfn( lptstrFilename, dwHandle, dwLen, lpData );
+}
+
+typedef DWORD APIENTRY FN_VerLanguageNameA( DWORD wLang, LPSTR szLang, DWORD nSize );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_VerLanguageNameA( DWORD wLang, LPSTR szLang, DWORD nSize )
+{
+    static FN_VerLanguageNameA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VerLanguageNameA", &g_Kernel32);
+    return pfn( wLang, szLang, nSize );
+}
+
+typedef DWORD APIENTRY FN_VerLanguageNameW( DWORD wLang, LPWSTR szLang, DWORD nSize );
+__declspec(dllexport) DWORD APIENTRY kPrf2Wrap_VerLanguageNameW( DWORD wLang, LPWSTR szLang, DWORD nSize )
+{
+    static FN_VerLanguageNameW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VerLanguageNameW", &g_Kernel32);
+    return pfn( wLang, szLang, nSize );
+}
+
+typedef BOOL APIENTRY FN_VerQueryValueA( const LPVOID pBlock, LPSTR lpSubBlock, LPVOID * lplpBuffer, PUINT puLen );
+__declspec(dllexport) BOOL APIENTRY kPrf2Wrap_VerQueryValueA( const LPVOID pBlock, LPSTR lpSubBlock, LPVOID * lplpBuffer, PUINT puLen )
+{
+    static FN_VerQueryValueA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VerQueryValueA", &g_Kernel32);
+    return pfn( pBlock, lpSubBlock, lplpBuffer, puLen );
+}
+
+typedef BOOL APIENTRY FN_VerQueryValueW( const LPVOID pBlock, LPWSTR lpSubBlock, LPVOID * lplpBuffer, PUINT puLen );
+__declspec(dllexport) BOOL APIENTRY kPrf2Wrap_VerQueryValueW( const LPVOID pBlock, LPWSTR lpSubBlock, LPVOID * lplpBuffer, PUINT puLen )
+{
+    static FN_VerQueryValueW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VerQueryValueW", &g_Kernel32);
+    return pfn( pBlock, lpSubBlock, lplpBuffer, puLen );
+}
+
+typedef VOID __cdecl FN_RtlRestoreContext( IN PCONTEXT ContextRecord, IN struct _EXCEPTION_RECORD * ExceptionRecord );
+__declspec(dllexport) VOID __cdecl kPrf2Wrap_RtlRestoreContext( IN PCONTEXT ContextRecord, IN struct _EXCEPTION_RECORD * ExceptionRecord )
+{
+    static FN_RtlRestoreContext *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlRestoreContext", &g_Kernel32);
+    pfn( ContextRecord, ExceptionRecord );
+}
+
+typedef BOOLEAN __cdecl FN_RtlAddFunctionTable( IN PRUNTIME_FUNCTION FunctionTable, IN DWORD EntryCount, IN DWORD64 BaseAddress );
+__declspec(dllexport) BOOLEAN __cdecl kPrf2Wrap_RtlAddFunctionTable( IN PRUNTIME_FUNCTION FunctionTable, IN DWORD EntryCount, IN DWORD64 BaseAddress )
+{
+    static FN_RtlAddFunctionTable *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlAddFunctionTable", &g_Kernel32);
+    return pfn( FunctionTable, EntryCount, BaseAddress );
+}
+
+typedef BOOLEAN __cdecl FN_RtlInstallFunctionTableCallback( IN DWORD64 TableIdentifier, IN DWORD64 BaseAddress, IN DWORD Length, IN PGET_RUNTIME_FUNCTION_CALLBACK Callback, IN PVOID Context, IN PCWSTR OutOfProcessCallbackDll );
+__declspec(dllexport) BOOLEAN __cdecl kPrf2Wrap_RtlInstallFunctionTableCallback( IN DWORD64 TableIdentifier, IN DWORD64 BaseAddress, IN DWORD Length, IN PGET_RUNTIME_FUNCTION_CALLBACK Callback, IN PVOID Context, IN PCWSTR OutOfProcessCallbackDll )
+{
+    static FN_RtlInstallFunctionTableCallback *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlInstallFunctionTableCallback", &g_Kernel32);
+    return pfn( TableIdentifier, BaseAddress, Length, Callback, Context, OutOfProcessCallbackDll );
+}
+
+typedef BOOLEAN __cdecl FN_RtlDeleteFunctionTable( IN PRUNTIME_FUNCTION FunctionTable );
+__declspec(dllexport) BOOLEAN __cdecl kPrf2Wrap_RtlDeleteFunctionTable( IN PRUNTIME_FUNCTION FunctionTable )
+{
+    static FN_RtlDeleteFunctionTable *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlDeleteFunctionTable", &g_Kernel32);
+    return pfn( FunctionTable );
+}
+
+typedef VOID NTAPI FN_RtlInitializeSListHead( IN PSLIST_HEADER ListHead );
+__declspec(dllexport) VOID NTAPI kPrf2Wrap_RtlInitializeSListHead( IN PSLIST_HEADER ListHead )
+{
+    static FN_RtlInitializeSListHead *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlInitializeSListHead", &g_Kernel32);
+    pfn( ListHead );
+}
+
+typedef PSLIST_ENTRY NTAPI FN_RtlFirstEntrySList( IN const SLIST_HEADER * ListHead );
+__declspec(dllexport) PSLIST_ENTRY NTAPI kPrf2Wrap_RtlFirstEntrySList( IN const SLIST_HEADER * ListHead )
+{
+    static FN_RtlFirstEntrySList *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlFirstEntrySList", &g_Kernel32);
+    return pfn( ListHead );
+}
+
+typedef PSLIST_ENTRY NTAPI FN_RtlInterlockedPopEntrySList( IN PSLIST_HEADER ListHead );
+__declspec(dllexport) PSLIST_ENTRY NTAPI kPrf2Wrap_RtlInterlockedPopEntrySList( IN PSLIST_HEADER ListHead )
+{
+    static FN_RtlInterlockedPopEntrySList *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlInterlockedPopEntrySList", &g_Kernel32);
+    return pfn( ListHead );
+}
+
+typedef PSLIST_ENTRY NTAPI FN_RtlInterlockedPushEntrySList( IN PSLIST_HEADER ListHead, IN PSLIST_ENTRY ListEntry );
+__declspec(dllexport) PSLIST_ENTRY NTAPI kPrf2Wrap_RtlInterlockedPushEntrySList( IN PSLIST_HEADER ListHead, IN PSLIST_ENTRY ListEntry )
+{
+    static FN_RtlInterlockedPushEntrySList *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlInterlockedPushEntrySList", &g_Kernel32);
+    return pfn( ListHead, ListEntry );
+}
+
+typedef PSLIST_ENTRY NTAPI FN_RtlInterlockedFlushSList( IN PSLIST_HEADER ListHead );
+__declspec(dllexport) PSLIST_ENTRY NTAPI kPrf2Wrap_RtlInterlockedFlushSList( IN PSLIST_HEADER ListHead )
+{
+    static FN_RtlInterlockedFlushSList *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlInterlockedFlushSList", &g_Kernel32);
+    return pfn( ListHead );
+}
+
+typedef WORD NTAPI FN_RtlQueryDepthSList( IN PSLIST_HEADER ListHead );
+__declspec(dllexport) WORD NTAPI kPrf2Wrap_RtlQueryDepthSList( IN PSLIST_HEADER ListHead )
+{
+    static FN_RtlQueryDepthSList *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlQueryDepthSList", &g_Kernel32);
+    return pfn( ListHead );
+}
+
+typedef VOID NTAPI FN_RtlCaptureContext( OUT PCONTEXT ContextRecord );
+__declspec(dllexport) VOID NTAPI kPrf2Wrap_RtlCaptureContext( OUT PCONTEXT ContextRecord )
+{
+    static FN_RtlCaptureContext *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlCaptureContext", &g_Kernel32);
+    pfn( ContextRecord );
+}
+
+typedef SIZE_T NTAPI FN_RtlCompareMemory( const VOID * Source1, const VOID * Source2, SIZE_T Length );
+__declspec(dllexport) SIZE_T NTAPI kPrf2Wrap_RtlCompareMemory( const VOID * Source1, const VOID * Source2, SIZE_T Length )
+{
+    static FN_RtlCompareMemory *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlCompareMemory", &g_Kernel32);
+    return pfn( Source1, Source2, Length );
+}
+
+typedef ULONGLONG NTAPI FN_VerSetConditionMask( IN ULONGLONG ConditionMask, IN DWORD TypeMask, IN BYTE Condition );
+__declspec(dllexport) ULONGLONG NTAPI kPrf2Wrap_VerSetConditionMask( IN ULONGLONG ConditionMask, IN DWORD TypeMask, IN BYTE Condition )
+{
+    static FN_VerSetConditionMask *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "VerSetConditionMask", &g_Kernel32);
+    return pfn( ConditionMask, TypeMask, Condition );
+}
+
+typedef DWORD NTAPI FN_RtlSetHeapInformation( IN PVOID HeapHandle, IN HEAP_INFORMATION_CLASS HeapInformationClass, IN PVOID HeapInformation , IN SIZE_T HeapInformationLength );
+__declspec(dllexport) DWORD NTAPI kPrf2Wrap_RtlSetHeapInformation( IN PVOID HeapHandle, IN HEAP_INFORMATION_CLASS HeapInformationClass, IN PVOID HeapInformation , IN SIZE_T HeapInformationLength )
+{
+    static FN_RtlSetHeapInformation *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlSetHeapInformation", &g_Kernel32);
+    return pfn( HeapHandle, HeapInformationClass, HeapInformation , HeapInformationLength );
+}
+
+typedef DWORD NTAPI FN_RtlQueryHeapInformation( IN PVOID HeapHandle, IN HEAP_INFORMATION_CLASS HeapInformationClass, OUT PVOID HeapInformation , IN SIZE_T HeapInformationLength , OUT PSIZE_T ReturnLength );
+__declspec(dllexport) DWORD NTAPI kPrf2Wrap_RtlQueryHeapInformation( IN PVOID HeapHandle, IN HEAP_INFORMATION_CLASS HeapInformationClass, OUT PVOID HeapInformation , IN SIZE_T HeapInformationLength , OUT PSIZE_T ReturnLength )
+{
+    static FN_RtlQueryHeapInformation *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlQueryHeapInformation", &g_Kernel32);
+    return pfn( HeapHandle, HeapInformationClass, HeapInformation , HeapInformationLength , ReturnLength );
+}
+
+typedef HANDLE WINAPI FN_CreateToolhelp32Snapshot( DWORD dwFlags, DWORD th32ProcessID );
+__declspec(dllexport) HANDLE WINAPI kPrf2Wrap_CreateToolhelp32Snapshot( DWORD dwFlags, DWORD th32ProcessID )
+{
+    static FN_CreateToolhelp32Snapshot *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "CreateToolhelp32Snapshot", &g_Kernel32);
+    return pfn( dwFlags, th32ProcessID );
+}
+
+typedef BOOL WINAPI FN_Heap32ListFirst( HANDLE hSnapshot, LPHEAPLIST32 lphl );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Heap32ListFirst( HANDLE hSnapshot, LPHEAPLIST32 lphl )
+{
+    static FN_Heap32ListFirst *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Heap32ListFirst", &g_Kernel32);
+    return pfn( hSnapshot, lphl );
+}
+
+typedef BOOL WINAPI FN_Heap32ListNext( HANDLE hSnapshot, LPHEAPLIST32 lphl );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Heap32ListNext( HANDLE hSnapshot, LPHEAPLIST32 lphl )
+{
+    static FN_Heap32ListNext *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Heap32ListNext", &g_Kernel32);
+    return pfn( hSnapshot, lphl );
+}
+
+typedef BOOL WINAPI FN_Heap32First( LPHEAPENTRY32 lphe, DWORD th32ProcessID, ULONG_PTR th32HeapID );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Heap32First( LPHEAPENTRY32 lphe, DWORD th32ProcessID, ULONG_PTR th32HeapID )
+{
+    static FN_Heap32First *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Heap32First", &g_Kernel32);
+    return pfn( lphe, th32ProcessID, th32HeapID );
+}
+
+typedef BOOL WINAPI FN_Heap32Next( LPHEAPENTRY32 lphe );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Heap32Next( LPHEAPENTRY32 lphe )
+{
+    static FN_Heap32Next *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Heap32Next", &g_Kernel32);
+    return pfn( lphe );
+}
+
+typedef BOOL WINAPI FN_Toolhelp32ReadProcessMemory( DWORD th32ProcessID, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T cbRead, SIZE_T * lpNumberOfBytesRead );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Toolhelp32ReadProcessMemory( DWORD th32ProcessID, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T cbRead, SIZE_T * lpNumberOfBytesRead )
+{
+    static FN_Toolhelp32ReadProcessMemory *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Toolhelp32ReadProcessMemory", &g_Kernel32);
+    return pfn( th32ProcessID, lpBaseAddress, lpBuffer, cbRead, lpNumberOfBytesRead );
+}
+
+typedef BOOL WINAPI FN_Process32FirstW( HANDLE hSnapshot, LPPROCESSENTRY32W lppe );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Process32FirstW( HANDLE hSnapshot, LPPROCESSENTRY32W lppe )
+{
+    static FN_Process32FirstW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Process32FirstW", &g_Kernel32);
+    return pfn( hSnapshot, lppe );
+}
+
+typedef BOOL WINAPI FN_Process32NextW( HANDLE hSnapshot, LPPROCESSENTRY32W lppe );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Process32NextW( HANDLE hSnapshot, LPPROCESSENTRY32W lppe )
+{
+    static FN_Process32NextW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Process32NextW", &g_Kernel32);
+    return pfn( hSnapshot, lppe );
+}
+
+typedef BOOL WINAPI FN_Process32First( HANDLE hSnapshot, LPPROCESSENTRY32 lppe );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Process32First( HANDLE hSnapshot, LPPROCESSENTRY32 lppe )
+{
+    static FN_Process32First *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Process32First", &g_Kernel32);
+    return pfn( hSnapshot, lppe );
+}
+
+typedef BOOL WINAPI FN_Process32Next( HANDLE hSnapshot, LPPROCESSENTRY32 lppe );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Process32Next( HANDLE hSnapshot, LPPROCESSENTRY32 lppe )
+{
+    static FN_Process32Next *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Process32Next", &g_Kernel32);
+    return pfn( hSnapshot, lppe );
+}
+
+typedef BOOL WINAPI FN_Thread32First( HANDLE hSnapshot, LPTHREADENTRY32 lpte );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Thread32First( HANDLE hSnapshot, LPTHREADENTRY32 lpte )
+{
+    static FN_Thread32First *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Thread32First", &g_Kernel32);
+    return pfn( hSnapshot, lpte );
+}
+
+typedef BOOL WINAPI FN_Thread32Next( HANDLE hSnapshot, LPTHREADENTRY32 lpte );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Thread32Next( HANDLE hSnapshot, LPTHREADENTRY32 lpte )
+{
+    static FN_Thread32Next *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Thread32Next", &g_Kernel32);
+    return pfn( hSnapshot, lpte );
+}
+
+typedef BOOL WINAPI FN_Module32FirstW( HANDLE hSnapshot, LPMODULEENTRY32W lpme );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Module32FirstW( HANDLE hSnapshot, LPMODULEENTRY32W lpme )
+{
+    static FN_Module32FirstW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Module32FirstW", &g_Kernel32);
+    return pfn( hSnapshot, lpme );
+}
+
+typedef BOOL WINAPI FN_Module32NextW( HANDLE hSnapshot, LPMODULEENTRY32W lpme );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Module32NextW( HANDLE hSnapshot, LPMODULEENTRY32W lpme )
+{
+    static FN_Module32NextW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Module32NextW", &g_Kernel32);
+    return pfn( hSnapshot, lpme );
+}
+
+typedef BOOL WINAPI FN_Module32First( HANDLE hSnapshot, LPMODULEENTRY32 lpme );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Module32First( HANDLE hSnapshot, LPMODULEENTRY32 lpme )
+{
+    static FN_Module32First *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Module32First", &g_Kernel32);
+    return pfn( hSnapshot, lpme );
+}
+
+typedef BOOL WINAPI FN_Module32Next( HANDLE hSnapshot, LPMODULEENTRY32 lpme );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_Module32Next( HANDLE hSnapshot, LPMODULEENTRY32 lpme )
+{
+    static FN_Module32Next *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "Module32Next", &g_Kernel32);
+    return pfn( hSnapshot, lpme );
+}
+
+typedef BOOL WINAPI FN_ReplaceFile( LPCSTR lpReplacedFileName, LPCSTR lpReplacementFileName, LPCSTR lpBackupFileName, DWORD dwReplaceFlags, LPVOID lpExclude, LPVOID lpReserved );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_ReplaceFile( LPCSTR lpReplacedFileName, LPCSTR lpReplacementFileName, LPCSTR lpBackupFileName, DWORD dwReplaceFlags, LPVOID lpExclude, LPVOID lpReserved )
+{
+    static FN_ReplaceFile *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "ReplaceFile", &g_Kernel32);
+    return pfn( lpReplacedFileName, lpReplacementFileName, lpBackupFileName, dwReplaceFlags, lpExclude, lpReserved );
+}
+
+typedef BOOL WINAPI FN_SetConsoleCursor( PVOID pvUnknown1, PVOID pvUnknown2 );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_SetConsoleCursor( PVOID pvUnknown1, PVOID pvUnknown2 )
+{
+    static FN_SetConsoleCursor *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "SetConsoleCursor", &g_Kernel32);
+    return pfn( pvUnknown1, pvUnknown2 );
+}
+
+typedef LPCH WINAPI FN_GetEnvironmentStringsA( VOID );
+__declspec(dllexport) LPCH WINAPI kPrf2Wrap_GetEnvironmentStringsA( VOID )
+{
+    static FN_GetEnvironmentStringsA *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetEnvironmentStringsA", &g_Kernel32);
+    return pfn ();
+}
+
+typedef BOOL WINAPI FN_GetBinaryType( LPCSTR lpApplicationName, LPDWORD lpBinaryType );
+__declspec(dllexport) BOOL WINAPI kPrf2Wrap_GetBinaryType( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
+{
+    static FN_GetBinaryType *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "GetBinaryType", &g_Kernel32);
+    return pfn( lpApplicationName, lpBinaryType );
+}
+
+typedef WORD NTAPI FN_RtlCaptureStackBackTrace( DWORD FramesToSkip, DWORD FramesToCapture, PVOID * BackTrace, PDWORD BackTraceHash );
+__declspec(dllexport) WORD NTAPI kPrf2Wrap_RtlCaptureStackBackTrace( DWORD FramesToSkip, DWORD FramesToCapture, PVOID * BackTrace, PDWORD BackTraceHash )
+{
+    static FN_RtlCaptureStackBackTrace *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlCaptureStackBackTrace", &g_Kernel32);
+    return pfn( FramesToSkip, FramesToCapture, BackTrace, BackTraceHash );
+}
+
+typedef PVOID FN_RtlFillMemory( PVOID pv, int ch, SIZE_T cb );
+__declspec(dllexport) PVOID kPrf2Wrap_RtlFillMemory( PVOID pv, int ch, SIZE_T cb )
+{
+    static FN_RtlFillMemory *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlFillMemory", &g_Kernel32);
+    return pfn( pv, ch, cb );
+}
+
+typedef PVOID FN_RtlZeroMemory( PVOID pv, SIZE_T cb );
+__declspec(dllexport) PVOID kPrf2Wrap_RtlZeroMemory( PVOID pv, SIZE_T cb )
+{
+    static FN_RtlZeroMemory *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlZeroMemory", &g_Kernel32);
+    return pfn( pv, cb );
+}
+
+typedef PVOID FN_RtlMoveMemory( PVOID pvDst, PVOID pvSrc, SIZE_T cb );
+__declspec(dllexport) PVOID kPrf2Wrap_RtlMoveMemory( PVOID pvDst, PVOID pvSrc, SIZE_T cb )
+{
+    static FN_RtlMoveMemory *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlMoveMemory", &g_Kernel32);
+    return pfn( pvDst, pvSrc, cb );
+}
+
+typedef VOID NTAPI FN_RtlUnwind( PVOID TargetFrame, PVOID TargetIp, PEXCEPTION_RECORD ExceptionRecord, PVOID ReturnValue );
+__declspec(dllexport) VOID NTAPI kPrf2Wrap_RtlUnwind( PVOID TargetFrame, PVOID TargetIp, PEXCEPTION_RECORD ExceptionRecord, PVOID ReturnValue )
+{
+    static FN_RtlUnwind *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlUnwind", &g_Kernel32);
+    pfn( TargetFrame, TargetIp, ExceptionRecord, ReturnValue );
+}
+
+typedef VOID NTAPI FN_RtlUnwindEx( FRAME_POINTERS TargetFrame, PVOID TargetIp, PEXCEPTION_RECORD ExceptionRecord, PVOID ReturnValue, PCONTEXT ContextRecord, PUNWIND_HISTORY_TABLE HistoryTable );
+__declspec(dllexport) VOID NTAPI kPrf2Wrap_RtlUnwindEx( FRAME_POINTERS TargetFrame, PVOID TargetIp, PEXCEPTION_RECORD ExceptionRecord, PVOID ReturnValue, PCONTEXT ContextRecord, PUNWIND_HISTORY_TABLE HistoryTable )
+{
+    static FN_RtlUnwindEx *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlUnwindEx", &g_Kernel32);
+    pfn( TargetFrame, TargetIp, ExceptionRecord, ReturnValue, ContextRecord, HistoryTable );
+}
+
+typedef ULONGLONG WINAPI FN_RtlVirtualUnwind( ULONG HandlerType, ULONGLONG ImageBase, ULONGLONG ControlPC, PRUNTIME_FUNCTION FunctionEntry, PCONTEXT ContextRecord, PBOOLEAN InFunction, PFRAME_POINTERS EstablisherFrame, PKNONVOLATILE_CONTEXT_POINTERS ContextPointers );
+__declspec(dllexport) ULONGLONG WINAPI kPrf2Wrap_RtlVirtualUnwind( ULONG HandlerType, ULONGLONG ImageBase, ULONGLONG ControlPC, PRUNTIME_FUNCTION FunctionEntry, PCONTEXT ContextRecord, PBOOLEAN InFunction, PFRAME_POINTERS EstablisherFrame, PKNONVOLATILE_CONTEXT_POINTERS ContextPointers )
+{
+    static FN_RtlVirtualUnwind *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlVirtualUnwind", &g_Kernel32);
+    return pfn( HandlerType, ImageBase, ControlPC, FunctionEntry, ContextRecord, InFunction, EstablisherFrame, ContextPointers );
+}
+
+typedef PVOID WINAPI FN_RtlPcToFileHeader( PVOID PcValue, PVOID * BaseOfImage );
+__declspec(dllexport) PVOID WINAPI kPrf2Wrap_RtlPcToFileHeader( PVOID PcValue, PVOID * BaseOfImage )
+{
+    static FN_RtlPcToFileHeader *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlPcToFileHeader", &g_Kernel32);
+    return pfn( PcValue, BaseOfImage );
+}
+
+typedef PVOID WINAPI FN_RtlLookupFunctionEntry( ULONGLONG ControlPC, PULONGLONG ImageBase, PULONGLONG TargetGp );
+__declspec(dllexport) PVOID WINAPI kPrf2Wrap_RtlLookupFunctionEntry( ULONGLONG ControlPC, PULONGLONG ImageBase, PULONGLONG TargetGp )
+{
+    static FN_RtlLookupFunctionEntry *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlLookupFunctionEntry", &g_Kernel32);
+    return pfn( ControlPC, ImageBase, TargetGp );
+}
+
+typedef void WINAPI FN_RtlRaiseException(PEXCEPTION_RECORD pXcpRec);
+__declspec(dllexport) void WINAPI kPrf2Wrap_RtlRaiseException(PEXCEPTION_RECORD pXcpRec)
+{
+    static FN_RtlRaiseException *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "RtlRaiseException", &g_Kernel32);
+    pfn( pXcpRec);
+}
+
+typedef int WINAPI FN_uaw_lstrcmpW( LPCUWSTR lpString1, LPCUWSTR lpString2 );
+__declspec(dllexport) int WINAPI kPrf2Wrap_uaw_lstrcmpW( LPCUWSTR lpString1, LPCUWSTR lpString2 )
+{
+    static FN_uaw_lstrcmpW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "uaw_lstrcmpW", &g_Kernel32);
+    return pfn( lpString1, lpString2 );
+}
+
+typedef int WINAPI FN_uaw_lstrcmpiW( LPCUWSTR lpString1, LPCUWSTR lpString2 );
+__declspec(dllexport) int WINAPI kPrf2Wrap_uaw_lstrcmpiW( LPCUWSTR lpString1, LPCUWSTR lpString2 )
+{
+    static FN_uaw_lstrcmpiW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "uaw_lstrcmpiW", &g_Kernel32);
+    return pfn( lpString1, lpString2 );
+}
+
+typedef int WINAPI FN_uaw_lstrlenW( LPCUWSTR lpString );
+__declspec(dllexport) int WINAPI kPrf2Wrap_uaw_lstrlenW( LPCUWSTR lpString )
+{
+    static FN_uaw_lstrlenW *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "uaw_lstrlenW", &g_Kernel32);
+    return pfn( lpString );
+}
+
+typedef LPUWSTR WINAPI FN_uaw_wcschr( LPCUWSTR lpString, WCHAR wc );
+__declspec(dllexport) LPUWSTR WINAPI kPrf2Wrap_uaw_wcschr( LPCUWSTR lpString, WCHAR wc )
+{
+    static FN_uaw_wcschr *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "uaw_wcschr", &g_Kernel32);
+    return pfn( lpString, wc );
+}
+
+typedef LPUWSTR WINAPI FN_uaw_wcscpy( LPUWSTR lpDst, LPCUWSTR lpSrc );
+__declspec(dllexport) LPUWSTR WINAPI kPrf2Wrap_uaw_wcscpy( LPUWSTR lpDst, LPCUWSTR lpSrc )
+{
+    static FN_uaw_wcscpy *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "uaw_wcscpy", &g_Kernel32);
+    return pfn( lpDst, lpSrc );
+}
+
+typedef int WINAPI FN_uaw_wcsicmp( LPCUWSTR lp1, LPCUWSTR lp2 );
+__declspec(dllexport) int WINAPI kPrf2Wrap_uaw_wcsicmp( LPCUWSTR lp1, LPCUWSTR lp2 )
+{
+    static FN_uaw_wcsicmp *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "uaw_wcsicmp", &g_Kernel32);
+    return pfn( lp1, lp2 );
+}
+
+typedef SIZE_T WINAPI FN_uaw_wcslen( LPCUWSTR lp1 );
+__declspec(dllexport) SIZE_T WINAPI kPrf2Wrap_uaw_wcslen( LPCUWSTR lp1 )
+{
+    static FN_uaw_wcslen *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "uaw_wcslen", &g_Kernel32);
+    return pfn( lp1 );
+}
+
+typedef LPUWSTR WINAPI FN_uaw_wcsrchr( LPCUWSTR lpString, WCHAR wc );
+__declspec(dllexport) LPUWSTR WINAPI kPrf2Wrap_uaw_wcsrchr( LPCUWSTR lpString, WCHAR wc )
+{
+    static FN_uaw_wcsrchr *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "uaw_wcsrchr", &g_Kernel32);
+    return pfn( lpString, wc );
+}
+
+typedef LPSTR WINAPI FN_lstrcat( LPSTR lpString1, LPCSTR lpString2 );
+__declspec(dllexport) LPSTR WINAPI kPrf2Wrap_lstrcat( LPSTR lpString1, LPCSTR lpString2 )
+{
+    static FN_lstrcat *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrcat", &g_Kernel32);
+    return pfn( lpString1, lpString2 );
+}
+
+typedef int WINAPI FN_lstrcmp( LPCSTR lpString1, LPCSTR lpString2 );
+__declspec(dllexport) int WINAPI kPrf2Wrap_lstrcmp( LPCSTR lpString1, LPCSTR lpString2 )
+{
+    static FN_lstrcmp *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrcmp", &g_Kernel32);
+    return pfn( lpString1, lpString2 );
+}
+
+typedef int WINAPI FN_lstrcmpi( LPCSTR lpString1, LPCSTR lpString2 );
+__declspec(dllexport) int WINAPI kPrf2Wrap_lstrcmpi( LPCSTR lpString1, LPCSTR lpString2 )
+{
+    static FN_lstrcmpi *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrcmpi", &g_Kernel32);
+    return pfn( lpString1, lpString2 );
+}
+
+typedef LPSTR WINAPI FN_lstrcpy( LPSTR lpString1, LPCSTR lpString2 );
+__declspec(dllexport) LPSTR WINAPI kPrf2Wrap_lstrcpy( LPSTR lpString1, LPCSTR lpString2 )
+{
+    static FN_lstrcpy *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrcpy", &g_Kernel32);
+    return pfn( lpString1, lpString2 );
+}
+
+typedef LPSTR WINAPI FN_lstrcpyn( LPSTR lpString1, LPCSTR lpString2, int iMaxLength );
+__declspec(dllexport) LPSTR WINAPI kPrf2Wrap_lstrcpyn( LPSTR lpString1, LPCSTR lpString2, int iMaxLength )
+{
+    static FN_lstrcpyn *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrcpyn", &g_Kernel32);
+    return pfn( lpString1, lpString2, iMaxLength );
+}
+
+typedef int WINAPI FN_lstrlen( LPCSTR lpString );
+__declspec(dllexport) int WINAPI kPrf2Wrap_lstrlen( LPCSTR lpString )
+{
+    static FN_lstrlen *pfn = 0;
+    if (!pfn)
+        kPrf2WrapResolve((void **)&pfn, "lstrlen", &g_Kernel32);
+    return pfn( lpString );
+}
+
diff --git a/src/lib/kStuff/kProfiler2/kPrf2WinApiWrappers.c b/src/lib/kStuff/kProfiler2/kPrf2WinApiWrappers.c
new file mode 100644
index 0000000..ecb31f0
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kPrf2WinApiWrappers.c
@@ -0,0 +1,123 @@
+/* $Id: kPrf2WinApiWrappers.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * Wrappers for a number of common Windows APIs.
+ */
+
+/*
+ * Copyright (c) 2008 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define _ADVAPI32_
+#define _KERNEL32_
+#define _WIN32_WINNT 0x0600
+#define UNICODE
+#include <Windows.h>
+#include <TLHelp32.h>
+#include <k/kDefs.h>
+#include "kPrf2WinApiWrapperHlp.h"
+
+#if K_ARCH == K_ARCH_X86_32
+typedef PVOID PRUNTIME_FUNCTION;
+typedef FARPROC PGET_RUNTIME_FUNCTION_CALLBACK;
+#endif
+
+/* RtlUnwindEx is used by msvcrt on amd64, but winnt.h only defines it for IA64... */
+typedef struct _FRAME_POINTERS {
+    ULONGLONG MemoryStackFp;
+    ULONGLONG BackingStoreFp;
+} FRAME_POINTERS, *PFRAME_POINTERS;
+typedef PVOID PUNWIND_HISTORY_TABLE;
+typedef PVOID PKNONVOLATILE_CONTEXT_POINTERS;
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+KPRF2WRAPDLL g_Kernel32 =
+{
+    INVALID_HANDLE_VALUE, "KERNEL32"
+};
+
+
+/*
+ * Include the generated code.
+ */
+#include "kPrf2WinApiWrappers-kernel32.h"
+
+/* TODO (amd64):
+
+AddLocalAlternateComputerNameA
+AddLocalAlternateComputerNameW
+EnumerateLocalComputerNamesA
+EnumerateLocalComputerNamesW
+RemoveLocalAlternateComputerNameA
+RemoveLocalAlternateComputerNameW
+
+RtlLookupFunctionEntry
+RtlPcToFileHeader
+RtlRaiseException
+RtlVirtualUnwind
+
+SetConsoleCursor
+SetLocalPrimaryComputerNameA
+SetLocalPrimaryComputerNameW
+__C_specific_handler
+__misaligned_access
+_local_unwind
+
+*/
+
+
+/**
+ * The DLL Main for the Windows API wrapper DLL.
+ *
+ * @returns Success indicator.
+ * @param   hInstDll        The instance handle of the DLL. (i.e. the module handle)
+ * @param   fdwReason       The reason why we're here. This is a 'flag' for reasons of
+ *                          tradition, it's really a kind of enum.
+ * @param   pReserved       Reserved / undocumented something.
+ */
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, PVOID pReserved)
+{
+    switch (fdwReason)
+    {
+        case DLL_PROCESS_ATTACH:
+            break;
+
+        case DLL_PROCESS_DETACH:
+            break;
+
+        case DLL_THREAD_ATTACH:
+            break;
+
+        case DLL_THREAD_DETACH:
+            break;
+    }
+
+    return TRUE;
+}
+
diff --git a/src/lib/kStuff/kProfiler2/kPrf2WinApiWrappersImp-amd64.def b/src/lib/kStuff/kProfiler2/kPrf2WinApiWrappersImp-amd64.def
new file mode 100644
index 0000000..48e4198
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kPrf2WinApiWrappersImp-amd64.def
@@ -0,0 +1,854 @@
+LIBRARY kPrf2WinApiWrappers
+EXPORTS
+  ActivateActCtx=kPrf2Wrap_ActivateActCtx
+  AddAtomA=kPrf2Wrap_AddAtomA
+  AddAtomW=kPrf2Wrap_AddAtomW
+  AddConsoleAliasA=kPrf2Wrap_AddConsoleAliasA
+  AddConsoleAliasW=kPrf2Wrap_AddConsoleAliasW
+  AddRefActCtx=kPrf2Wrap_AddRefActCtx
+  AddVectoredContinueHandler=kPrf2Wrap_AddVectoredContinueHandler
+  AddVectoredExceptionHandler=kPrf2Wrap_AddVectoredExceptionHandler
+  AllocConsole=kPrf2Wrap_AllocConsole
+  AllocateUserPhysicalPages=kPrf2Wrap_AllocateUserPhysicalPages
+  AreFileApisANSI=kPrf2Wrap_AreFileApisANSI
+  AssignProcessToJobObject=kPrf2Wrap_AssignProcessToJobObject
+  AttachConsole=kPrf2Wrap_AttachConsole
+  BackupRead=kPrf2Wrap_BackupRead
+  BackupSeek=kPrf2Wrap_BackupSeek
+  BackupWrite=kPrf2Wrap_BackupWrite
+  Beep=kPrf2Wrap_Beep
+  BeginUpdateResourceA=kPrf2Wrap_BeginUpdateResourceA
+  BeginUpdateResourceW=kPrf2Wrap_BeginUpdateResourceW
+  BindIoCompletionCallback=kPrf2Wrap_BindIoCompletionCallback
+  BuildCommDCBA=kPrf2Wrap_BuildCommDCBA
+  BuildCommDCBAndTimeoutsA=kPrf2Wrap_BuildCommDCBAndTimeoutsA
+  BuildCommDCBAndTimeoutsW=kPrf2Wrap_BuildCommDCBAndTimeoutsW
+  BuildCommDCBW=kPrf2Wrap_BuildCommDCBW
+  CallNamedPipeA=kPrf2Wrap_CallNamedPipeA
+  CallNamedPipeW=kPrf2Wrap_CallNamedPipeW
+  CancelDeviceWakeupRequest=kPrf2Wrap_CancelDeviceWakeupRequest
+  CancelIo=kPrf2Wrap_CancelIo
+  CancelTimerQueueTimer=kPrf2Wrap_CancelTimerQueueTimer
+  CancelWaitableTimer=kPrf2Wrap_CancelWaitableTimer
+  ChangeTimerQueueTimer=kPrf2Wrap_ChangeTimerQueueTimer
+  CheckNameLegalDOS8Dot3A=kPrf2Wrap_CheckNameLegalDOS8Dot3A
+  CheckNameLegalDOS8Dot3W=kPrf2Wrap_CheckNameLegalDOS8Dot3W
+  CheckRemoteDebuggerPresent=kPrf2Wrap_CheckRemoteDebuggerPresent
+  ClearCommBreak=kPrf2Wrap_ClearCommBreak
+  ClearCommError=kPrf2Wrap_ClearCommError
+  CloseHandle=kPrf2Wrap_CloseHandle
+  CommConfigDialogA=kPrf2Wrap_CommConfigDialogA
+  CommConfigDialogW=kPrf2Wrap_CommConfigDialogW
+  CompareFileTime=kPrf2Wrap_CompareFileTime
+  CompareStringA=kPrf2Wrap_CompareStringA
+  CompareStringW=kPrf2Wrap_CompareStringW
+  ConnectNamedPipe=kPrf2Wrap_ConnectNamedPipe
+  ContinueDebugEvent=kPrf2Wrap_ContinueDebugEvent
+  ConvertDefaultLocale=kPrf2Wrap_ConvertDefaultLocale
+  ConvertFiberToThread=kPrf2Wrap_ConvertFiberToThread
+  ConvertThreadToFiber=kPrf2Wrap_ConvertThreadToFiber
+  ConvertThreadToFiberEx=kPrf2Wrap_ConvertThreadToFiberEx
+  CopyFileA=kPrf2Wrap_CopyFileA
+  CopyFileExA=kPrf2Wrap_CopyFileExA
+  CopyFileExW=kPrf2Wrap_CopyFileExW
+  CopyFileW=kPrf2Wrap_CopyFileW
+  CreateActCtxA=kPrf2Wrap_CreateActCtxA
+  CreateActCtxW=kPrf2Wrap_CreateActCtxW
+  CreateConsoleScreenBuffer=kPrf2Wrap_CreateConsoleScreenBuffer
+  CreateDirectoryA=kPrf2Wrap_CreateDirectoryA
+  CreateDirectoryExA=kPrf2Wrap_CreateDirectoryExA
+  CreateDirectoryExW=kPrf2Wrap_CreateDirectoryExW
+  CreateDirectoryW=kPrf2Wrap_CreateDirectoryW
+  CreateEventA=kPrf2Wrap_CreateEventA
+  CreateEventW=kPrf2Wrap_CreateEventW
+  CreateFiber=kPrf2Wrap_CreateFiber
+  CreateFiberEx=kPrf2Wrap_CreateFiberEx
+  CreateFileA=kPrf2Wrap_CreateFileA
+  CreateFileMappingA=kPrf2Wrap_CreateFileMappingA
+  CreateFileMappingW=kPrf2Wrap_CreateFileMappingW
+  CreateFileW=kPrf2Wrap_CreateFileW
+  CreateHardLinkA=kPrf2Wrap_CreateHardLinkA
+  CreateHardLinkW=kPrf2Wrap_CreateHardLinkW
+  CreateIoCompletionPort=kPrf2Wrap_CreateIoCompletionPort
+  CreateJobObjectA=kPrf2Wrap_CreateJobObjectA
+  CreateJobObjectW=kPrf2Wrap_CreateJobObjectW
+  CreateJobSet=kPrf2Wrap_CreateJobSet
+  CreateMailslotA=kPrf2Wrap_CreateMailslotA
+  CreateMailslotW=kPrf2Wrap_CreateMailslotW
+  CreateMemoryResourceNotification=kPrf2Wrap_CreateMemoryResourceNotification
+  CreateMutexA=kPrf2Wrap_CreateMutexA
+  CreateMutexW=kPrf2Wrap_CreateMutexW
+  CreateNamedPipeA=kPrf2Wrap_CreateNamedPipeA
+  CreateNamedPipeW=kPrf2Wrap_CreateNamedPipeW
+  CreatePipe=kPrf2Wrap_CreatePipe
+  CreateProcessA=kPrf2Wrap_CreateProcessA
+  CreateProcessW=kPrf2Wrap_CreateProcessW
+  CreateRemoteThread=kPrf2Wrap_CreateRemoteThread
+  CreateSemaphoreA=kPrf2Wrap_CreateSemaphoreA
+  CreateSemaphoreW=kPrf2Wrap_CreateSemaphoreW
+  CreateTapePartition=kPrf2Wrap_CreateTapePartition
+  CreateThread=kPrf2Wrap_CreateThread
+  CreateTimerQueue=kPrf2Wrap_CreateTimerQueue
+  CreateTimerQueueTimer=kPrf2Wrap_CreateTimerQueueTimer
+  CreateToolhelp32Snapshot=kPrf2Wrap_CreateToolhelp32Snapshot
+  CreateWaitableTimerA=kPrf2Wrap_CreateWaitableTimerA
+  CreateWaitableTimerW=kPrf2Wrap_CreateWaitableTimerW
+  DeactivateActCtx=kPrf2Wrap_DeactivateActCtx
+  DebugActiveProcess=kPrf2Wrap_DebugActiveProcess
+  DebugActiveProcessStop=kPrf2Wrap_DebugActiveProcessStop
+  DebugBreak=kPrf2Wrap_DebugBreak
+  DebugBreakProcess=kPrf2Wrap_DebugBreakProcess
+  DebugSetProcessKillOnExit=kPrf2Wrap_DebugSetProcessKillOnExit
+  DecodePointer=kPrf2Wrap_DecodePointer
+  DecodeSystemPointer=kPrf2Wrap_DecodeSystemPointer
+  DefineDosDeviceA=kPrf2Wrap_DefineDosDeviceA
+  DefineDosDeviceW=kPrf2Wrap_DefineDosDeviceW
+  DeleteAtom=kPrf2Wrap_DeleteAtom
+  DeleteCriticalSection=kPrf2Wrap_DeleteCriticalSection
+  DeleteFiber=kPrf2Wrap_DeleteFiber
+  DeleteFileA=kPrf2Wrap_DeleteFileA
+  DeleteFileW=kPrf2Wrap_DeleteFileW
+  DeleteTimerQueue=kPrf2Wrap_DeleteTimerQueue
+  DeleteTimerQueueEx=kPrf2Wrap_DeleteTimerQueueEx
+  DeleteTimerQueueTimer=kPrf2Wrap_DeleteTimerQueueTimer
+  DeleteVolumeMountPointA=kPrf2Wrap_DeleteVolumeMountPointA
+  DeleteVolumeMountPointW=kPrf2Wrap_DeleteVolumeMountPointW
+  DeviceIoControl=kPrf2Wrap_DeviceIoControl
+  DisableThreadLibraryCalls=kPrf2Wrap_DisableThreadLibraryCalls
+  DisconnectNamedPipe=kPrf2Wrap_DisconnectNamedPipe
+  DnsHostnameToComputerNameA=kPrf2Wrap_DnsHostnameToComputerNameA
+  DnsHostnameToComputerNameW=kPrf2Wrap_DnsHostnameToComputerNameW
+  DosDateTimeToFileTime=kPrf2Wrap_DosDateTimeToFileTime
+  DuplicateHandle=kPrf2Wrap_DuplicateHandle
+  EncodePointer=kPrf2Wrap_EncodePointer
+  EncodeSystemPointer=kPrf2Wrap_EncodeSystemPointer
+  EndUpdateResourceA=kPrf2Wrap_EndUpdateResourceA
+  EndUpdateResourceW=kPrf2Wrap_EndUpdateResourceW
+  EnterCriticalSection=kPrf2Wrap_EnterCriticalSection
+  EnumCalendarInfoA=kPrf2Wrap_EnumCalendarInfoA
+  EnumCalendarInfoExA=kPrf2Wrap_EnumCalendarInfoExA
+  EnumCalendarInfoExW=kPrf2Wrap_EnumCalendarInfoExW
+  EnumCalendarInfoW=kPrf2Wrap_EnumCalendarInfoW
+  EnumDateFormatsA=kPrf2Wrap_EnumDateFormatsA
+  EnumDateFormatsExA=kPrf2Wrap_EnumDateFormatsExA
+  EnumDateFormatsExW=kPrf2Wrap_EnumDateFormatsExW
+  EnumDateFormatsW=kPrf2Wrap_EnumDateFormatsW
+  EnumLanguageGroupLocalesA=kPrf2Wrap_EnumLanguageGroupLocalesA
+  EnumLanguageGroupLocalesW=kPrf2Wrap_EnumLanguageGroupLocalesW
+  EnumResourceLanguagesA=kPrf2Wrap_EnumResourceLanguagesA
+  EnumResourceLanguagesW=kPrf2Wrap_EnumResourceLanguagesW
+  EnumResourceNamesA=kPrf2Wrap_EnumResourceNamesA
+  EnumResourceNamesW=kPrf2Wrap_EnumResourceNamesW
+  EnumResourceTypesA=kPrf2Wrap_EnumResourceTypesA
+  EnumResourceTypesW=kPrf2Wrap_EnumResourceTypesW
+  EnumSystemCodePagesA=kPrf2Wrap_EnumSystemCodePagesA
+  EnumSystemCodePagesW=kPrf2Wrap_EnumSystemCodePagesW
+  EnumSystemFirmwareTables=kPrf2Wrap_EnumSystemFirmwareTables
+  EnumSystemGeoID=kPrf2Wrap_EnumSystemGeoID
+  EnumSystemLanguageGroupsA=kPrf2Wrap_EnumSystemLanguageGroupsA
+  EnumSystemLanguageGroupsW=kPrf2Wrap_EnumSystemLanguageGroupsW
+  EnumSystemLocalesA=kPrf2Wrap_EnumSystemLocalesA
+  EnumSystemLocalesW=kPrf2Wrap_EnumSystemLocalesW
+  EnumTimeFormatsA=kPrf2Wrap_EnumTimeFormatsA
+  EnumTimeFormatsW=kPrf2Wrap_EnumTimeFormatsW
+  EnumUILanguagesA=kPrf2Wrap_EnumUILanguagesA
+  EnumUILanguagesW=kPrf2Wrap_EnumUILanguagesW
+  EraseTape=kPrf2Wrap_EraseTape
+  EscapeCommFunction=kPrf2Wrap_EscapeCommFunction
+  ExitProcess=kPrf2Wrap_ExitProcess
+  ExitThread=kPrf2Wrap_ExitThread
+  ExpandEnvironmentStringsA=kPrf2Wrap_ExpandEnvironmentStringsA
+  ExpandEnvironmentStringsW=kPrf2Wrap_ExpandEnvironmentStringsW
+  FatalAppExitA=kPrf2Wrap_FatalAppExitA
+  FatalAppExitW=kPrf2Wrap_FatalAppExitW
+  FatalExit=kPrf2Wrap_FatalExit
+  FileTimeToDosDateTime=kPrf2Wrap_FileTimeToDosDateTime
+  FileTimeToLocalFileTime=kPrf2Wrap_FileTimeToLocalFileTime
+  FileTimeToSystemTime=kPrf2Wrap_FileTimeToSystemTime
+  FillConsoleOutputAttribute=kPrf2Wrap_FillConsoleOutputAttribute
+  FillConsoleOutputCharacterA=kPrf2Wrap_FillConsoleOutputCharacterA
+  FillConsoleOutputCharacterW=kPrf2Wrap_FillConsoleOutputCharacterW
+  FindActCtxSectionGuid=kPrf2Wrap_FindActCtxSectionGuid
+  FindActCtxSectionStringA=kPrf2Wrap_FindActCtxSectionStringA
+  FindActCtxSectionStringW=kPrf2Wrap_FindActCtxSectionStringW
+  FindAtomA=kPrf2Wrap_FindAtomA
+  FindAtomW=kPrf2Wrap_FindAtomW
+  FindClose=kPrf2Wrap_FindClose
+  FindCloseChangeNotification=kPrf2Wrap_FindCloseChangeNotification
+  FindFirstChangeNotificationA=kPrf2Wrap_FindFirstChangeNotificationA
+  FindFirstChangeNotificationW=kPrf2Wrap_FindFirstChangeNotificationW
+  FindFirstFileA=kPrf2Wrap_FindFirstFileA
+  FindFirstFileExA=kPrf2Wrap_FindFirstFileExA
+  FindFirstFileExW=kPrf2Wrap_FindFirstFileExW
+  FindFirstFileW=kPrf2Wrap_FindFirstFileW
+  FindFirstStreamW=kPrf2Wrap_FindFirstStreamW
+  FindFirstVolumeA=kPrf2Wrap_FindFirstVolumeA
+  FindFirstVolumeMountPointA=kPrf2Wrap_FindFirstVolumeMountPointA
+  FindFirstVolumeMountPointW=kPrf2Wrap_FindFirstVolumeMountPointW
+  FindFirstVolumeW=kPrf2Wrap_FindFirstVolumeW
+  FindNextChangeNotification=kPrf2Wrap_FindNextChangeNotification
+  FindNextFileA=kPrf2Wrap_FindNextFileA
+  FindNextFileW=kPrf2Wrap_FindNextFileW
+  FindNextStreamW=kPrf2Wrap_FindNextStreamW
+  FindNextVolumeA=kPrf2Wrap_FindNextVolumeA
+  FindNextVolumeMountPointA=kPrf2Wrap_FindNextVolumeMountPointA
+  FindNextVolumeMountPointW=kPrf2Wrap_FindNextVolumeMountPointW
+  FindNextVolumeW=kPrf2Wrap_FindNextVolumeW
+  FindResourceA=kPrf2Wrap_FindResourceA
+  FindResourceExA=kPrf2Wrap_FindResourceExA
+  FindResourceExW=kPrf2Wrap_FindResourceExW
+  FindResourceW=kPrf2Wrap_FindResourceW
+  FindVolumeClose=kPrf2Wrap_FindVolumeClose
+  FindVolumeMountPointClose=kPrf2Wrap_FindVolumeMountPointClose
+  FlsAlloc=kPrf2Wrap_FlsAlloc
+  FlsFree=kPrf2Wrap_FlsFree
+  FlsGetValue=kPrf2Wrap_FlsGetValue
+  FlsSetValue=kPrf2Wrap_FlsSetValue
+  FlushConsoleInputBuffer=kPrf2Wrap_FlushConsoleInputBuffer
+  FlushFileBuffers=kPrf2Wrap_FlushFileBuffers
+  FlushInstructionCache=kPrf2Wrap_FlushInstructionCache
+  FlushViewOfFile=kPrf2Wrap_FlushViewOfFile
+  FoldStringA=kPrf2Wrap_FoldStringA
+  FoldStringW=kPrf2Wrap_FoldStringW
+  FormatMessageA=kPrf2Wrap_FormatMessageA
+  FormatMessageW=kPrf2Wrap_FormatMessageW
+  FreeConsole=kPrf2Wrap_FreeConsole
+  FreeEnvironmentStringsA=kPrf2Wrap_FreeEnvironmentStringsA
+  FreeEnvironmentStringsW=kPrf2Wrap_FreeEnvironmentStringsW
+  FreeLibrary=kPrf2Wrap_FreeLibrary
+  FreeLibraryAndExitThread=kPrf2Wrap_FreeLibraryAndExitThread
+  FreeResource=kPrf2Wrap_FreeResource
+  FreeUserPhysicalPages=kPrf2Wrap_FreeUserPhysicalPages
+  GenerateConsoleCtrlEvent=kPrf2Wrap_GenerateConsoleCtrlEvent
+  GetACP=kPrf2Wrap_GetACP
+  GetAtomNameA=kPrf2Wrap_GetAtomNameA
+  GetAtomNameW=kPrf2Wrap_GetAtomNameW
+  GetBinaryType=kPrf2Wrap_GetBinaryType
+  GetBinaryTypeA=kPrf2Wrap_GetBinaryTypeA
+  GetBinaryTypeW=kPrf2Wrap_GetBinaryTypeW
+  GetCPInfo=kPrf2Wrap_GetCPInfo
+  GetCPInfoExA=kPrf2Wrap_GetCPInfoExA
+  GetCPInfoExW=kPrf2Wrap_GetCPInfoExW
+  GetCalendarInfoA=kPrf2Wrap_GetCalendarInfoA
+  GetCalendarInfoW=kPrf2Wrap_GetCalendarInfoW
+  GetCommConfig=kPrf2Wrap_GetCommConfig
+  GetCommMask=kPrf2Wrap_GetCommMask
+  GetCommModemStatus=kPrf2Wrap_GetCommModemStatus
+  GetCommProperties=kPrf2Wrap_GetCommProperties
+  GetCommState=kPrf2Wrap_GetCommState
+  GetCommTimeouts=kPrf2Wrap_GetCommTimeouts
+  GetCommandLineA=kPrf2Wrap_GetCommandLineA
+  GetCommandLineW=kPrf2Wrap_GetCommandLineW
+  GetCompressedFileSizeA=kPrf2Wrap_GetCompressedFileSizeA
+  GetCompressedFileSizeW=kPrf2Wrap_GetCompressedFileSizeW
+  GetComputerNameA=kPrf2Wrap_GetComputerNameA
+  GetComputerNameExA=kPrf2Wrap_GetComputerNameExA
+  GetComputerNameExW=kPrf2Wrap_GetComputerNameExW
+  GetComputerNameW=kPrf2Wrap_GetComputerNameW
+  GetConsoleAliasA=kPrf2Wrap_GetConsoleAliasA
+  GetConsoleAliasExesA=kPrf2Wrap_GetConsoleAliasExesA
+  GetConsoleAliasExesLengthA=kPrf2Wrap_GetConsoleAliasExesLengthA
+  GetConsoleAliasExesLengthW=kPrf2Wrap_GetConsoleAliasExesLengthW
+  GetConsoleAliasExesW=kPrf2Wrap_GetConsoleAliasExesW
+  GetConsoleAliasW=kPrf2Wrap_GetConsoleAliasW
+  GetConsoleAliasesA=kPrf2Wrap_GetConsoleAliasesA
+  GetConsoleAliasesLengthA=kPrf2Wrap_GetConsoleAliasesLengthA
+  GetConsoleAliasesLengthW=kPrf2Wrap_GetConsoleAliasesLengthW
+  GetConsoleAliasesW=kPrf2Wrap_GetConsoleAliasesW
+  GetConsoleCP=kPrf2Wrap_GetConsoleCP
+  GetConsoleCursorInfo=kPrf2Wrap_GetConsoleCursorInfo
+  GetConsoleDisplayMode=kPrf2Wrap_GetConsoleDisplayMode
+  GetConsoleFontSize=kPrf2Wrap_GetConsoleFontSize
+  GetConsoleMode=kPrf2Wrap_GetConsoleMode
+  GetConsoleOutputCP=kPrf2Wrap_GetConsoleOutputCP
+  GetConsoleProcessList=kPrf2Wrap_GetConsoleProcessList
+  GetConsoleScreenBufferInfo=kPrf2Wrap_GetConsoleScreenBufferInfo
+  GetConsoleSelectionInfo=kPrf2Wrap_GetConsoleSelectionInfo
+  GetConsoleTitleA=kPrf2Wrap_GetConsoleTitleA
+  GetConsoleTitleW=kPrf2Wrap_GetConsoleTitleW
+  GetConsoleWindow=kPrf2Wrap_GetConsoleWindow
+  GetCurrencyFormatA=kPrf2Wrap_GetCurrencyFormatA
+  GetCurrencyFormatW=kPrf2Wrap_GetCurrencyFormatW
+  GetCurrentActCtx=kPrf2Wrap_GetCurrentActCtx
+  GetCurrentConsoleFont=kPrf2Wrap_GetCurrentConsoleFont
+  GetCurrentDirectoryA=kPrf2Wrap_GetCurrentDirectoryA
+  GetCurrentDirectoryW=kPrf2Wrap_GetCurrentDirectoryW
+  GetCurrentProcess=kPrf2Wrap_GetCurrentProcess
+  GetCurrentProcessId=kPrf2Wrap_GetCurrentProcessId
+  GetCurrentProcessorNumber=kPrf2Wrap_GetCurrentProcessorNumber
+  GetCurrentThread=kPrf2Wrap_GetCurrentThread
+  GetCurrentThreadId=kPrf2Wrap_GetCurrentThreadId
+  GetDateFormatA=kPrf2Wrap_GetDateFormatA
+  GetDateFormatW=kPrf2Wrap_GetDateFormatW
+  GetDefaultCommConfigA=kPrf2Wrap_GetDefaultCommConfigA
+  GetDefaultCommConfigW=kPrf2Wrap_GetDefaultCommConfigW
+  GetDevicePowerState=kPrf2Wrap_GetDevicePowerState
+  GetDiskFreeSpaceA=kPrf2Wrap_GetDiskFreeSpaceA
+  GetDiskFreeSpaceExA=kPrf2Wrap_GetDiskFreeSpaceExA
+  GetDiskFreeSpaceExW=kPrf2Wrap_GetDiskFreeSpaceExW
+  GetDiskFreeSpaceW=kPrf2Wrap_GetDiskFreeSpaceW
+  GetDllDirectoryA=kPrf2Wrap_GetDllDirectoryA
+  GetDllDirectoryW=kPrf2Wrap_GetDllDirectoryW
+  GetDriveTypeA=kPrf2Wrap_GetDriveTypeA
+  GetDriveTypeW=kPrf2Wrap_GetDriveTypeW
+  GetEnvironmentStrings=kPrf2Wrap_GetEnvironmentStrings
+  GetEnvironmentStringsA=kPrf2Wrap_GetEnvironmentStringsA
+  GetEnvironmentStringsW=kPrf2Wrap_GetEnvironmentStringsW
+  GetEnvironmentVariableA=kPrf2Wrap_GetEnvironmentVariableA
+  GetEnvironmentVariableW=kPrf2Wrap_GetEnvironmentVariableW
+  GetExitCodeProcess=kPrf2Wrap_GetExitCodeProcess
+  GetExitCodeThread=kPrf2Wrap_GetExitCodeThread
+  GetFileAttributesA=kPrf2Wrap_GetFileAttributesA
+  GetFileAttributesExA=kPrf2Wrap_GetFileAttributesExA
+  GetFileAttributesExW=kPrf2Wrap_GetFileAttributesExW
+  GetFileAttributesW=kPrf2Wrap_GetFileAttributesW
+  GetFileInformationByHandle=kPrf2Wrap_GetFileInformationByHandle
+  GetFileSize=kPrf2Wrap_GetFileSize
+  GetFileSizeEx=kPrf2Wrap_GetFileSizeEx
+  GetFileTime=kPrf2Wrap_GetFileTime
+  GetFileType=kPrf2Wrap_GetFileType
+  GetFirmwareEnvironmentVariableA=kPrf2Wrap_GetFirmwareEnvironmentVariableA
+  GetFirmwareEnvironmentVariableW=kPrf2Wrap_GetFirmwareEnvironmentVariableW
+  GetFullPathNameA=kPrf2Wrap_GetFullPathNameA
+  GetFullPathNameW=kPrf2Wrap_GetFullPathNameW
+  GetGeoInfoA=kPrf2Wrap_GetGeoInfoA
+  GetGeoInfoW=kPrf2Wrap_GetGeoInfoW
+  GetHandleInformation=kPrf2Wrap_GetHandleInformation
+  GetLargePageMinimum=kPrf2Wrap_GetLargePageMinimum
+  GetLargestConsoleWindowSize=kPrf2Wrap_GetLargestConsoleWindowSize
+  GetLastError=kPrf2Wrap_GetLastError
+  GetLocalTime=kPrf2Wrap_GetLocalTime
+  GetLocaleInfoA=kPrf2Wrap_GetLocaleInfoA
+  GetLocaleInfoW=kPrf2Wrap_GetLocaleInfoW
+  GetLogicalDriveStringsA=kPrf2Wrap_GetLogicalDriveStringsA
+  GetLogicalDriveStringsW=kPrf2Wrap_GetLogicalDriveStringsW
+  GetLogicalDrives=kPrf2Wrap_GetLogicalDrives
+  GetLogicalProcessorInformation=kPrf2Wrap_GetLogicalProcessorInformation
+  GetLongPathNameA=kPrf2Wrap_GetLongPathNameA
+  GetLongPathNameW=kPrf2Wrap_GetLongPathNameW
+  GetMailslotInfo=kPrf2Wrap_GetMailslotInfo
+  GetModuleFileNameA=kPrf2Wrap_GetModuleFileNameA
+  GetModuleFileNameW=kPrf2Wrap_GetModuleFileNameW
+  GetModuleHandleA=kPrf2Wrap_GetModuleHandleA
+  GetModuleHandleExA=kPrf2Wrap_GetModuleHandleExA
+  GetModuleHandleExW=kPrf2Wrap_GetModuleHandleExW
+  GetModuleHandleW=kPrf2Wrap_GetModuleHandleW
+  GetNLSVersion=kPrf2Wrap_GetNLSVersion
+  GetNamedPipeHandleStateA=kPrf2Wrap_GetNamedPipeHandleStateA
+  GetNamedPipeHandleStateW=kPrf2Wrap_GetNamedPipeHandleStateW
+  GetNamedPipeInfo=kPrf2Wrap_GetNamedPipeInfo
+  GetNativeSystemInfo=kPrf2Wrap_GetNativeSystemInfo
+  GetNumaAvailableMemoryNode=kPrf2Wrap_GetNumaAvailableMemoryNode
+  GetNumaHighestNodeNumber=kPrf2Wrap_GetNumaHighestNodeNumber
+  GetNumaNodeProcessorMask=kPrf2Wrap_GetNumaNodeProcessorMask
+  GetNumaProcessorNode=kPrf2Wrap_GetNumaProcessorNode
+  GetNumberFormatA=kPrf2Wrap_GetNumberFormatA
+  GetNumberFormatW=kPrf2Wrap_GetNumberFormatW
+  GetNumberOfConsoleInputEvents=kPrf2Wrap_GetNumberOfConsoleInputEvents
+  GetNumberOfConsoleMouseButtons=kPrf2Wrap_GetNumberOfConsoleMouseButtons
+  GetOEMCP=kPrf2Wrap_GetOEMCP
+  GetOverlappedResult=kPrf2Wrap_GetOverlappedResult
+  GetPriorityClass=kPrf2Wrap_GetPriorityClass
+  GetPrivateProfileIntA=kPrf2Wrap_GetPrivateProfileIntA
+  GetPrivateProfileIntW=kPrf2Wrap_GetPrivateProfileIntW
+  GetPrivateProfileSectionA=kPrf2Wrap_GetPrivateProfileSectionA
+  GetPrivateProfileSectionNamesA=kPrf2Wrap_GetPrivateProfileSectionNamesA
+  GetPrivateProfileSectionNamesW=kPrf2Wrap_GetPrivateProfileSectionNamesW
+  GetPrivateProfileSectionW=kPrf2Wrap_GetPrivateProfileSectionW
+  GetPrivateProfileStringA=kPrf2Wrap_GetPrivateProfileStringA
+  GetPrivateProfileStringW=kPrf2Wrap_GetPrivateProfileStringW
+  GetPrivateProfileStructA=kPrf2Wrap_GetPrivateProfileStructA
+  GetPrivateProfileStructW=kPrf2Wrap_GetPrivateProfileStructW
+  GetProcAddress=kPrf2Wrap_GetProcAddress
+  GetProcessAffinityMask=kPrf2Wrap_GetProcessAffinityMask
+  GetProcessHandleCount=kPrf2Wrap_GetProcessHandleCount
+  GetProcessHeap=kPrf2Wrap_GetProcessHeap
+  GetProcessHeaps=kPrf2Wrap_GetProcessHeaps
+  GetProcessId=kPrf2Wrap_GetProcessId
+  GetProcessIdOfThread=kPrf2Wrap_GetProcessIdOfThread
+  GetProcessIoCounters=kPrf2Wrap_GetProcessIoCounters
+  GetProcessPriorityBoost=kPrf2Wrap_GetProcessPriorityBoost
+  GetProcessShutdownParameters=kPrf2Wrap_GetProcessShutdownParameters
+  GetProcessTimes=kPrf2Wrap_GetProcessTimes
+  GetProcessVersion=kPrf2Wrap_GetProcessVersion
+  GetProcessWorkingSetSize=kPrf2Wrap_GetProcessWorkingSetSize
+  GetProcessWorkingSetSizeEx=kPrf2Wrap_GetProcessWorkingSetSizeEx
+  GetProfileIntA=kPrf2Wrap_GetProfileIntA
+  GetProfileIntW=kPrf2Wrap_GetProfileIntW
+  GetProfileSectionA=kPrf2Wrap_GetProfileSectionA
+  GetProfileSectionW=kPrf2Wrap_GetProfileSectionW
+  GetProfileStringA=kPrf2Wrap_GetProfileStringA
+  GetProfileStringW=kPrf2Wrap_GetProfileStringW
+  GetQueuedCompletionStatus=kPrf2Wrap_GetQueuedCompletionStatus
+  GetShortPathNameA=kPrf2Wrap_GetShortPathNameA
+  GetShortPathNameW=kPrf2Wrap_GetShortPathNameW
+  GetStartupInfoA=kPrf2Wrap_GetStartupInfoA
+  GetStartupInfoW=kPrf2Wrap_GetStartupInfoW
+  GetStdHandle=kPrf2Wrap_GetStdHandle
+  GetStringTypeA=kPrf2Wrap_GetStringTypeA
+  GetStringTypeExA=kPrf2Wrap_GetStringTypeExA
+  GetStringTypeExW=kPrf2Wrap_GetStringTypeExW
+  GetStringTypeW=kPrf2Wrap_GetStringTypeW
+  GetSystemDefaultLCID=kPrf2Wrap_GetSystemDefaultLCID
+  GetSystemDefaultLangID=kPrf2Wrap_GetSystemDefaultLangID
+  GetSystemDefaultUILanguage=kPrf2Wrap_GetSystemDefaultUILanguage
+  GetSystemDirectoryA=kPrf2Wrap_GetSystemDirectoryA
+  GetSystemDirectoryW=kPrf2Wrap_GetSystemDirectoryW
+  GetSystemFileCacheSize=kPrf2Wrap_GetSystemFileCacheSize
+  GetSystemFirmwareTable=kPrf2Wrap_GetSystemFirmwareTable
+  GetSystemInfo=kPrf2Wrap_GetSystemInfo
+  GetSystemPowerStatus=kPrf2Wrap_GetSystemPowerStatus
+  GetSystemRegistryQuota=kPrf2Wrap_GetSystemRegistryQuota
+  GetSystemTime=kPrf2Wrap_GetSystemTime
+  GetSystemTimeAdjustment=kPrf2Wrap_GetSystemTimeAdjustment
+  GetSystemTimeAsFileTime=kPrf2Wrap_GetSystemTimeAsFileTime
+  GetSystemTimes=kPrf2Wrap_GetSystemTimes
+  GetSystemWindowsDirectoryA=kPrf2Wrap_GetSystemWindowsDirectoryA
+  GetSystemWindowsDirectoryW=kPrf2Wrap_GetSystemWindowsDirectoryW
+  GetSystemWow64DirectoryA=kPrf2Wrap_GetSystemWow64DirectoryA
+  GetSystemWow64DirectoryW=kPrf2Wrap_GetSystemWow64DirectoryW
+  GetTapeParameters=kPrf2Wrap_GetTapeParameters
+  GetTapePosition=kPrf2Wrap_GetTapePosition
+  GetTapeStatus=kPrf2Wrap_GetTapeStatus
+  GetTempFileNameA=kPrf2Wrap_GetTempFileNameA
+  GetTempFileNameW=kPrf2Wrap_GetTempFileNameW
+  GetTempPathA=kPrf2Wrap_GetTempPathA
+  GetTempPathW=kPrf2Wrap_GetTempPathW
+  GetThreadContext=kPrf2Wrap_GetThreadContext
+  GetThreadIOPendingFlag=kPrf2Wrap_GetThreadIOPendingFlag
+  GetThreadId=kPrf2Wrap_GetThreadId
+  GetThreadLocale=kPrf2Wrap_GetThreadLocale
+  GetThreadPriority=kPrf2Wrap_GetThreadPriority
+  GetThreadPriorityBoost=kPrf2Wrap_GetThreadPriorityBoost
+  GetThreadSelectorEntry=kPrf2Wrap_GetThreadSelectorEntry
+  GetThreadTimes=kPrf2Wrap_GetThreadTimes
+  GetTickCount=kPrf2Wrap_GetTickCount
+  GetTimeFormatA=kPrf2Wrap_GetTimeFormatA
+  GetTimeFormatW=kPrf2Wrap_GetTimeFormatW
+  GetTimeZoneInformation=kPrf2Wrap_GetTimeZoneInformation
+  GetUserDefaultLCID=kPrf2Wrap_GetUserDefaultLCID
+  GetUserDefaultLangID=kPrf2Wrap_GetUserDefaultLangID
+  GetUserDefaultUILanguage=kPrf2Wrap_GetUserDefaultUILanguage
+  GetUserGeoID=kPrf2Wrap_GetUserGeoID
+  GetVersion=kPrf2Wrap_GetVersion
+  GetVersionExA=kPrf2Wrap_GetVersionExA
+  GetVersionExW=kPrf2Wrap_GetVersionExW
+  GetVolumeInformationA=kPrf2Wrap_GetVolumeInformationA
+  GetVolumeInformationW=kPrf2Wrap_GetVolumeInformationW
+  GetVolumeNameForVolumeMountPointA=kPrf2Wrap_GetVolumeNameForVolumeMountPointA
+  GetVolumeNameForVolumeMountPointW=kPrf2Wrap_GetVolumeNameForVolumeMountPointW
+  GetVolumePathNameA=kPrf2Wrap_GetVolumePathNameA
+  GetVolumePathNameW=kPrf2Wrap_GetVolumePathNameW
+  GetVolumePathNamesForVolumeNameA=kPrf2Wrap_GetVolumePathNamesForVolumeNameA
+  GetVolumePathNamesForVolumeNameW=kPrf2Wrap_GetVolumePathNamesForVolumeNameW
+  GetWindowsDirectoryA=kPrf2Wrap_GetWindowsDirectoryA
+  GetWindowsDirectoryW=kPrf2Wrap_GetWindowsDirectoryW
+  GetWriteWatch=kPrf2Wrap_GetWriteWatch
+  GlobalAddAtomA=kPrf2Wrap_GlobalAddAtomA
+  GlobalAddAtomW=kPrf2Wrap_GlobalAddAtomW
+  GlobalAlloc=kPrf2Wrap_GlobalAlloc
+  GlobalCompact=kPrf2Wrap_GlobalCompact
+  GlobalDeleteAtom=kPrf2Wrap_GlobalDeleteAtom
+  GlobalFindAtomA=kPrf2Wrap_GlobalFindAtomA
+  GlobalFindAtomW=kPrf2Wrap_GlobalFindAtomW
+  GlobalFix=kPrf2Wrap_GlobalFix
+  GlobalFlags=kPrf2Wrap_GlobalFlags
+  GlobalFree=kPrf2Wrap_GlobalFree
+  GlobalGetAtomNameA=kPrf2Wrap_GlobalGetAtomNameA
+  GlobalGetAtomNameW=kPrf2Wrap_GlobalGetAtomNameW
+  GlobalHandle=kPrf2Wrap_GlobalHandle
+  GlobalLock=kPrf2Wrap_GlobalLock
+  GlobalMemoryStatus=kPrf2Wrap_GlobalMemoryStatus
+  GlobalMemoryStatusEx=kPrf2Wrap_GlobalMemoryStatusEx
+  GlobalReAlloc=kPrf2Wrap_GlobalReAlloc
+  GlobalSize=kPrf2Wrap_GlobalSize
+  GlobalUnWire=kPrf2Wrap_GlobalUnWire
+  GlobalUnfix=kPrf2Wrap_GlobalUnfix
+  GlobalUnlock=kPrf2Wrap_GlobalUnlock
+  GlobalWire=kPrf2Wrap_GlobalWire
+  Heap32First=kPrf2Wrap_Heap32First
+  Heap32ListFirst=kPrf2Wrap_Heap32ListFirst
+  Heap32ListNext=kPrf2Wrap_Heap32ListNext
+  Heap32Next=kPrf2Wrap_Heap32Next
+  HeapAlloc=kPrf2Wrap_HeapAlloc
+  HeapCompact=kPrf2Wrap_HeapCompact
+  HeapCreate=kPrf2Wrap_HeapCreate
+  HeapDestroy=kPrf2Wrap_HeapDestroy
+  HeapFree=kPrf2Wrap_HeapFree
+  HeapLock=kPrf2Wrap_HeapLock
+  HeapQueryInformation=kPrf2Wrap_HeapQueryInformation
+  HeapReAlloc=kPrf2Wrap_HeapReAlloc
+  HeapSetInformation=kPrf2Wrap_HeapSetInformation
+  HeapSize=kPrf2Wrap_HeapSize
+  HeapUnlock=kPrf2Wrap_HeapUnlock
+  HeapValidate=kPrf2Wrap_HeapValidate
+  HeapWalk=kPrf2Wrap_HeapWalk
+  InitAtomTable=kPrf2Wrap_InitAtomTable
+  InitializeCriticalSection=kPrf2Wrap_InitializeCriticalSection
+  InitializeCriticalSectionAndSpinCount=kPrf2Wrap_InitializeCriticalSectionAndSpinCount
+  InitializeSListHead=kPrf2Wrap_InitializeSListHead
+  InterlockedFlushSList=kPrf2Wrap_InterlockedFlushSList
+  InterlockedPopEntrySList=kPrf2Wrap_InterlockedPopEntrySList
+  InterlockedPushEntrySList=kPrf2Wrap_InterlockedPushEntrySList
+  IsBadCodePtr=kPrf2Wrap_IsBadCodePtr
+  IsBadHugeReadPtr=kPrf2Wrap_IsBadHugeReadPtr
+  IsBadHugeWritePtr=kPrf2Wrap_IsBadHugeWritePtr
+  IsBadReadPtr=kPrf2Wrap_IsBadReadPtr
+  IsBadStringPtrA=kPrf2Wrap_IsBadStringPtrA
+  IsBadStringPtrW=kPrf2Wrap_IsBadStringPtrW
+  IsBadWritePtr=kPrf2Wrap_IsBadWritePtr
+  IsDBCSLeadByte=kPrf2Wrap_IsDBCSLeadByte
+  IsDBCSLeadByteEx=kPrf2Wrap_IsDBCSLeadByteEx
+  IsDebuggerPresent=kPrf2Wrap_IsDebuggerPresent
+  IsNLSDefinedString=kPrf2Wrap_IsNLSDefinedString
+  IsProcessInJob=kPrf2Wrap_IsProcessInJob
+  IsProcessorFeaturePresent=kPrf2Wrap_IsProcessorFeaturePresent
+  IsSystemResumeAutomatic=kPrf2Wrap_IsSystemResumeAutomatic
+  IsValidCodePage=kPrf2Wrap_IsValidCodePage
+  IsValidLanguageGroup=kPrf2Wrap_IsValidLanguageGroup
+  IsValidLocale=kPrf2Wrap_IsValidLocale
+  IsWow64Process=kPrf2Wrap_IsWow64Process
+  LCMapStringA=kPrf2Wrap_LCMapStringA
+  LCMapStringW=kPrf2Wrap_LCMapStringW
+  LeaveCriticalSection=kPrf2Wrap_LeaveCriticalSection
+  LoadLibraryA=kPrf2Wrap_LoadLibraryA
+  LoadLibraryExA=kPrf2Wrap_LoadLibraryExA
+  LoadLibraryExW=kPrf2Wrap_LoadLibraryExW
+  LoadLibraryW=kPrf2Wrap_LoadLibraryW
+  LoadModule=kPrf2Wrap_LoadModule
+  LoadResource=kPrf2Wrap_LoadResource
+  LocalAlloc=kPrf2Wrap_LocalAlloc
+  LocalCompact=kPrf2Wrap_LocalCompact
+  LocalFileTimeToFileTime=kPrf2Wrap_LocalFileTimeToFileTime
+  LocalFlags=kPrf2Wrap_LocalFlags
+  LocalFree=kPrf2Wrap_LocalFree
+  LocalHandle=kPrf2Wrap_LocalHandle
+  LocalLock=kPrf2Wrap_LocalLock
+  LocalReAlloc=kPrf2Wrap_LocalReAlloc
+  LocalShrink=kPrf2Wrap_LocalShrink
+  LocalSize=kPrf2Wrap_LocalSize
+  LocalUnlock=kPrf2Wrap_LocalUnlock
+  LockFile=kPrf2Wrap_LockFile
+  LockFileEx=kPrf2Wrap_LockFileEx
+  LockResource=kPrf2Wrap_LockResource
+  MapUserPhysicalPages=kPrf2Wrap_MapUserPhysicalPages
+  MapUserPhysicalPagesScatter=kPrf2Wrap_MapUserPhysicalPagesScatter
+  MapViewOfFile=kPrf2Wrap_MapViewOfFile
+  MapViewOfFileEx=kPrf2Wrap_MapViewOfFileEx
+  Module32First=kPrf2Wrap_Module32First
+  Module32FirstW=kPrf2Wrap_Module32FirstW
+  Module32Next=kPrf2Wrap_Module32Next
+  Module32NextW=kPrf2Wrap_Module32NextW
+  MoveFileA=kPrf2Wrap_MoveFileA
+  MoveFileExA=kPrf2Wrap_MoveFileExA
+  MoveFileExW=kPrf2Wrap_MoveFileExW
+  MoveFileW=kPrf2Wrap_MoveFileW
+  MoveFileWithProgressA=kPrf2Wrap_MoveFileWithProgressA
+  MoveFileWithProgressW=kPrf2Wrap_MoveFileWithProgressW
+  MulDiv=kPrf2Wrap_MulDiv
+  MultiByteToWideChar=kPrf2Wrap_MultiByteToWideChar
+  NeedCurrentDirectoryForExePathA=kPrf2Wrap_NeedCurrentDirectoryForExePathA
+  NeedCurrentDirectoryForExePathW=kPrf2Wrap_NeedCurrentDirectoryForExePathW
+  OpenEventA=kPrf2Wrap_OpenEventA
+  OpenEventW=kPrf2Wrap_OpenEventW
+  OpenFile=kPrf2Wrap_OpenFile
+  OpenFileMappingA=kPrf2Wrap_OpenFileMappingA
+  OpenFileMappingW=kPrf2Wrap_OpenFileMappingW
+  OpenJobObjectA=kPrf2Wrap_OpenJobObjectA
+  OpenJobObjectW=kPrf2Wrap_OpenJobObjectW
+  OpenMutexA=kPrf2Wrap_OpenMutexA
+  OpenMutexW=kPrf2Wrap_OpenMutexW
+  OpenProcess=kPrf2Wrap_OpenProcess
+  OpenSemaphoreA=kPrf2Wrap_OpenSemaphoreA
+  OpenSemaphoreW=kPrf2Wrap_OpenSemaphoreW
+  OpenThread=kPrf2Wrap_OpenThread
+  OpenWaitableTimerA=kPrf2Wrap_OpenWaitableTimerA
+  OpenWaitableTimerW=kPrf2Wrap_OpenWaitableTimerW
+  OutputDebugStringA=kPrf2Wrap_OutputDebugStringA
+  OutputDebugStringW=kPrf2Wrap_OutputDebugStringW
+  PeekConsoleInputA=kPrf2Wrap_PeekConsoleInputA
+  PeekConsoleInputW=kPrf2Wrap_PeekConsoleInputW
+  PeekNamedPipe=kPrf2Wrap_PeekNamedPipe
+  PostQueuedCompletionStatus=kPrf2Wrap_PostQueuedCompletionStatus
+  PrepareTape=kPrf2Wrap_PrepareTape
+  Process32First=kPrf2Wrap_Process32First
+  Process32FirstW=kPrf2Wrap_Process32FirstW
+  Process32Next=kPrf2Wrap_Process32Next
+  Process32NextW=kPrf2Wrap_Process32NextW
+  ProcessIdToSessionId=kPrf2Wrap_ProcessIdToSessionId
+  PulseEvent=kPrf2Wrap_PulseEvent
+  PurgeComm=kPrf2Wrap_PurgeComm
+  QueryActCtxW=kPrf2Wrap_QueryActCtxW
+  QueryDepthSList=kPrf2Wrap_QueryDepthSList
+  QueryDosDeviceA=kPrf2Wrap_QueryDosDeviceA
+  QueryDosDeviceW=kPrf2Wrap_QueryDosDeviceW
+  QueryInformationJobObject=kPrf2Wrap_QueryInformationJobObject
+  QueryMemoryResourceNotification=kPrf2Wrap_QueryMemoryResourceNotification
+  QueryPerformanceCounter=kPrf2Wrap_QueryPerformanceCounter
+  QueryPerformanceFrequency=kPrf2Wrap_QueryPerformanceFrequency
+  QueueUserAPC=kPrf2Wrap_QueueUserAPC
+  QueueUserWorkItem=kPrf2Wrap_QueueUserWorkItem
+  RaiseException=kPrf2Wrap_RaiseException
+  ReOpenFile=kPrf2Wrap_ReOpenFile
+  ReadConsoleA=kPrf2Wrap_ReadConsoleA
+  ReadConsoleInputA=kPrf2Wrap_ReadConsoleInputA
+  ReadConsoleInputW=kPrf2Wrap_ReadConsoleInputW
+  ReadConsoleOutputA=kPrf2Wrap_ReadConsoleOutputA
+  ReadConsoleOutputAttribute=kPrf2Wrap_ReadConsoleOutputAttribute
+  ReadConsoleOutputCharacterA=kPrf2Wrap_ReadConsoleOutputCharacterA
+  ReadConsoleOutputCharacterW=kPrf2Wrap_ReadConsoleOutputCharacterW
+  ReadConsoleOutputW=kPrf2Wrap_ReadConsoleOutputW
+  ReadConsoleW=kPrf2Wrap_ReadConsoleW
+  ReadDirectoryChangesW=kPrf2Wrap_ReadDirectoryChangesW
+  ReadFile=kPrf2Wrap_ReadFile
+  ReadFileEx=kPrf2Wrap_ReadFileEx
+  ReadFileScatter=kPrf2Wrap_ReadFileScatter
+  ReadProcessMemory=kPrf2Wrap_ReadProcessMemory
+  RegisterWaitForSingleObject=kPrf2Wrap_RegisterWaitForSingleObject
+  RegisterWaitForSingleObjectEx=kPrf2Wrap_RegisterWaitForSingleObjectEx
+  ReleaseActCtx=kPrf2Wrap_ReleaseActCtx
+  ReleaseMutex=kPrf2Wrap_ReleaseMutex
+  ReleaseSemaphore=kPrf2Wrap_ReleaseSemaphore
+  RemoveDirectoryA=kPrf2Wrap_RemoveDirectoryA
+  RemoveDirectoryW=kPrf2Wrap_RemoveDirectoryW
+  RemoveVectoredContinueHandler=kPrf2Wrap_RemoveVectoredContinueHandler
+  RemoveVectoredExceptionHandler=kPrf2Wrap_RemoveVectoredExceptionHandler
+  ReplaceFile=kPrf2Wrap_ReplaceFile
+  ReplaceFileA=kPrf2Wrap_ReplaceFileA
+  ReplaceFileW=kPrf2Wrap_ReplaceFileW
+  RequestDeviceWakeup=kPrf2Wrap_RequestDeviceWakeup
+  RequestWakeupLatency=kPrf2Wrap_RequestWakeupLatency
+  ResetEvent=kPrf2Wrap_ResetEvent
+  ResetWriteWatch=kPrf2Wrap_ResetWriteWatch
+  RestoreLastError=kPrf2Wrap_RestoreLastError
+  ResumeThread=kPrf2Wrap_ResumeThread
+  RtlAddFunctionTable=kPrf2Wrap_RtlAddFunctionTable
+  RtlCaptureContext=kPrf2Wrap_RtlCaptureContext
+  RtlCaptureStackBackTrace=kPrf2Wrap_RtlCaptureStackBackTrace
+  RtlCompareMemory=kPrf2Wrap_RtlCompareMemory
+  RtlDeleteFunctionTable=kPrf2Wrap_RtlDeleteFunctionTable
+  RtlFillMemory=kPrf2Wrap_RtlFillMemory
+  RtlInstallFunctionTableCallback=kPrf2Wrap_RtlInstallFunctionTableCallback
+  RtlLookupFunctionEntry=kPrf2Wrap_RtlLookupFunctionEntry
+  RtlMoveMemory=kPrf2Wrap_RtlMoveMemory
+  RtlPcToFileHeader=kPrf2Wrap_RtlPcToFileHeader
+  RtlRaiseException=kPrf2Wrap_RtlRaiseException
+  RtlRestoreContext=kPrf2Wrap_RtlRestoreContext
+  RtlUnwind=kPrf2Wrap_RtlUnwind
+  RtlUnwindEx=kPrf2Wrap_RtlUnwindEx
+  RtlVirtualUnwind=kPrf2Wrap_RtlVirtualUnwind
+  RtlZeroMemory=kPrf2Wrap_RtlZeroMemory
+  ScrollConsoleScreenBufferA=kPrf2Wrap_ScrollConsoleScreenBufferA
+  ScrollConsoleScreenBufferW=kPrf2Wrap_ScrollConsoleScreenBufferW
+  SearchPathA=kPrf2Wrap_SearchPathA
+  SearchPathW=kPrf2Wrap_SearchPathW
+  SetCalendarInfoA=kPrf2Wrap_SetCalendarInfoA
+  SetCalendarInfoW=kPrf2Wrap_SetCalendarInfoW
+  SetCommBreak=kPrf2Wrap_SetCommBreak
+  SetCommConfig=kPrf2Wrap_SetCommConfig
+  SetCommMask=kPrf2Wrap_SetCommMask
+  SetCommState=kPrf2Wrap_SetCommState
+  SetCommTimeouts=kPrf2Wrap_SetCommTimeouts
+  SetComputerNameA=kPrf2Wrap_SetComputerNameA
+  SetComputerNameExA=kPrf2Wrap_SetComputerNameExA
+  SetComputerNameExW=kPrf2Wrap_SetComputerNameExW
+  SetComputerNameW=kPrf2Wrap_SetComputerNameW
+  SetConsoleActiveScreenBuffer=kPrf2Wrap_SetConsoleActiveScreenBuffer
+  SetConsoleCP=kPrf2Wrap_SetConsoleCP
+  SetConsoleCtrlHandler=kPrf2Wrap_SetConsoleCtrlHandler
+  SetConsoleCursor=kPrf2Wrap_SetConsoleCursor
+  SetConsoleCursorInfo=kPrf2Wrap_SetConsoleCursorInfo
+  SetConsoleCursorPosition=kPrf2Wrap_SetConsoleCursorPosition
+  SetConsoleMode=kPrf2Wrap_SetConsoleMode
+  SetConsoleOutputCP=kPrf2Wrap_SetConsoleOutputCP
+  SetConsoleScreenBufferSize=kPrf2Wrap_SetConsoleScreenBufferSize
+  SetConsoleTextAttribute=kPrf2Wrap_SetConsoleTextAttribute
+  SetConsoleTitleA=kPrf2Wrap_SetConsoleTitleA
+  SetConsoleTitleW=kPrf2Wrap_SetConsoleTitleW
+  SetConsoleWindowInfo=kPrf2Wrap_SetConsoleWindowInfo
+  SetCriticalSectionSpinCount=kPrf2Wrap_SetCriticalSectionSpinCount
+  SetCurrentDirectoryA=kPrf2Wrap_SetCurrentDirectoryA
+  SetCurrentDirectoryW=kPrf2Wrap_SetCurrentDirectoryW
+  SetDefaultCommConfigA=kPrf2Wrap_SetDefaultCommConfigA
+  SetDefaultCommConfigW=kPrf2Wrap_SetDefaultCommConfigW
+  SetDllDirectoryA=kPrf2Wrap_SetDllDirectoryA
+  SetDllDirectoryW=kPrf2Wrap_SetDllDirectoryW
+  SetEndOfFile=kPrf2Wrap_SetEndOfFile
+  SetEnvironmentStringsA=kPrf2Wrap_SetEnvironmentStringsA
+  SetEnvironmentStringsW=kPrf2Wrap_SetEnvironmentStringsW
+  SetEnvironmentVariableA=kPrf2Wrap_SetEnvironmentVariableA
+  SetEnvironmentVariableW=kPrf2Wrap_SetEnvironmentVariableW
+  SetErrorMode=kPrf2Wrap_SetErrorMode
+  SetEvent=kPrf2Wrap_SetEvent
+  SetFileApisToANSI=kPrf2Wrap_SetFileApisToANSI
+  SetFileApisToOEM=kPrf2Wrap_SetFileApisToOEM
+  SetFileAttributesA=kPrf2Wrap_SetFileAttributesA
+  SetFileAttributesW=kPrf2Wrap_SetFileAttributesW
+  SetFilePointer=kPrf2Wrap_SetFilePointer
+  SetFilePointerEx=kPrf2Wrap_SetFilePointerEx
+  SetFileShortNameA=kPrf2Wrap_SetFileShortNameA
+  SetFileShortNameW=kPrf2Wrap_SetFileShortNameW
+  SetFileTime=kPrf2Wrap_SetFileTime
+  SetFileValidData=kPrf2Wrap_SetFileValidData
+  SetFirmwareEnvironmentVariableA=kPrf2Wrap_SetFirmwareEnvironmentVariableA
+  SetFirmwareEnvironmentVariableW=kPrf2Wrap_SetFirmwareEnvironmentVariableW
+  SetHandleCount=kPrf2Wrap_SetHandleCount
+  SetHandleInformation=kPrf2Wrap_SetHandleInformation
+  SetInformationJobObject=kPrf2Wrap_SetInformationJobObject
+  SetLastError=kPrf2Wrap_SetLastError
+  SetLocalTime=kPrf2Wrap_SetLocalTime
+  SetLocaleInfoA=kPrf2Wrap_SetLocaleInfoA
+  SetLocaleInfoW=kPrf2Wrap_SetLocaleInfoW
+  SetMailslotInfo=kPrf2Wrap_SetMailslotInfo
+  SetMessageWaitingIndicator=kPrf2Wrap_SetMessageWaitingIndicator
+  SetNamedPipeHandleState=kPrf2Wrap_SetNamedPipeHandleState
+  SetPriorityClass=kPrf2Wrap_SetPriorityClass
+  SetProcessAffinityMask=kPrf2Wrap_SetProcessAffinityMask
+  SetProcessPriorityBoost=kPrf2Wrap_SetProcessPriorityBoost
+  SetProcessShutdownParameters=kPrf2Wrap_SetProcessShutdownParameters
+  SetProcessWorkingSetSize=kPrf2Wrap_SetProcessWorkingSetSize
+  SetProcessWorkingSetSizeEx=kPrf2Wrap_SetProcessWorkingSetSizeEx
+  SetStdHandle=kPrf2Wrap_SetStdHandle
+  SetSystemFileCacheSize=kPrf2Wrap_SetSystemFileCacheSize
+  SetSystemPowerState=kPrf2Wrap_SetSystemPowerState
+  SetSystemTime=kPrf2Wrap_SetSystemTime
+  SetSystemTimeAdjustment=kPrf2Wrap_SetSystemTimeAdjustment
+  SetTapeParameters=kPrf2Wrap_SetTapeParameters
+  SetTapePosition=kPrf2Wrap_SetTapePosition
+  SetThreadAffinityMask=kPrf2Wrap_SetThreadAffinityMask
+  SetThreadContext=kPrf2Wrap_SetThreadContext
+  SetThreadExecutionState=kPrf2Wrap_SetThreadExecutionState
+  SetThreadIdealProcessor=kPrf2Wrap_SetThreadIdealProcessor
+  SetThreadLocale=kPrf2Wrap_SetThreadLocale
+  SetThreadPriority=kPrf2Wrap_SetThreadPriority
+  SetThreadPriorityBoost=kPrf2Wrap_SetThreadPriorityBoost
+  SetThreadStackGuarantee=kPrf2Wrap_SetThreadStackGuarantee
+  SetTimeZoneInformation=kPrf2Wrap_SetTimeZoneInformation
+  SetTimerQueueTimer=kPrf2Wrap_SetTimerQueueTimer
+  SetUnhandledExceptionFilter=kPrf2Wrap_SetUnhandledExceptionFilter
+  SetUserGeoID=kPrf2Wrap_SetUserGeoID
+  SetVolumeLabelA=kPrf2Wrap_SetVolumeLabelA
+  SetVolumeLabelW=kPrf2Wrap_SetVolumeLabelW
+  SetVolumeMountPointA=kPrf2Wrap_SetVolumeMountPointA
+  SetVolumeMountPointW=kPrf2Wrap_SetVolumeMountPointW
+  SetWaitableTimer=kPrf2Wrap_SetWaitableTimer
+  SetupComm=kPrf2Wrap_SetupComm
+  SignalObjectAndWait=kPrf2Wrap_SignalObjectAndWait
+  SizeofResource=kPrf2Wrap_SizeofResource
+  Sleep=kPrf2Wrap_Sleep
+  SleepEx=kPrf2Wrap_SleepEx
+  SuspendThread=kPrf2Wrap_SuspendThread
+  SwitchToFiber=kPrf2Wrap_SwitchToFiber
+  SwitchToThread=kPrf2Wrap_SwitchToThread
+  SystemTimeToFileTime=kPrf2Wrap_SystemTimeToFileTime
+  SystemTimeToTzSpecificLocalTime=kPrf2Wrap_SystemTimeToTzSpecificLocalTime
+  TerminateJobObject=kPrf2Wrap_TerminateJobObject
+  TerminateProcess=kPrf2Wrap_TerminateProcess
+  TerminateThread=kPrf2Wrap_TerminateThread
+  Thread32First=kPrf2Wrap_Thread32First
+  Thread32Next=kPrf2Wrap_Thread32Next
+  TlsAlloc=kPrf2Wrap_TlsAlloc
+  TlsFree=kPrf2Wrap_TlsFree
+  TlsGetValue=kPrf2Wrap_TlsGetValue
+  TlsSetValue=kPrf2Wrap_TlsSetValue
+  Toolhelp32ReadProcessMemory=kPrf2Wrap_Toolhelp32ReadProcessMemory
+  TransactNamedPipe=kPrf2Wrap_TransactNamedPipe
+  TransmitCommChar=kPrf2Wrap_TransmitCommChar
+  TryEnterCriticalSection=kPrf2Wrap_TryEnterCriticalSection
+  TzSpecificLocalTimeToSystemTime=kPrf2Wrap_TzSpecificLocalTimeToSystemTime
+  UnhandledExceptionFilter=kPrf2Wrap_UnhandledExceptionFilter
+  UnlockFile=kPrf2Wrap_UnlockFile
+  UnlockFileEx=kPrf2Wrap_UnlockFileEx
+  UnmapViewOfFile=kPrf2Wrap_UnmapViewOfFile
+  UnregisterWait=kPrf2Wrap_UnregisterWait
+  UnregisterWaitEx=kPrf2Wrap_UnregisterWaitEx
+  UpdateResourceA=kPrf2Wrap_UpdateResourceA
+  UpdateResourceW=kPrf2Wrap_UpdateResourceW
+  VerLanguageNameA=kPrf2Wrap_VerLanguageNameA
+  VerLanguageNameW=kPrf2Wrap_VerLanguageNameW
+  VerSetConditionMask=kPrf2Wrap_VerSetConditionMask
+  VerifyVersionInfoA=kPrf2Wrap_VerifyVersionInfoA
+  VerifyVersionInfoW=kPrf2Wrap_VerifyVersionInfoW
+  VirtualAlloc=kPrf2Wrap_VirtualAlloc
+  VirtualAllocEx=kPrf2Wrap_VirtualAllocEx
+  VirtualFree=kPrf2Wrap_VirtualFree
+  VirtualFreeEx=kPrf2Wrap_VirtualFreeEx
+  VirtualLock=kPrf2Wrap_VirtualLock
+  VirtualProtect=kPrf2Wrap_VirtualProtect
+  VirtualProtectEx=kPrf2Wrap_VirtualProtectEx
+  VirtualQuery=kPrf2Wrap_VirtualQuery
+  VirtualQueryEx=kPrf2Wrap_VirtualQueryEx
+  VirtualUnlock=kPrf2Wrap_VirtualUnlock
+  WTSGetActiveConsoleSessionId=kPrf2Wrap_WTSGetActiveConsoleSessionId
+  WaitCommEvent=kPrf2Wrap_WaitCommEvent
+  WaitForDebugEvent=kPrf2Wrap_WaitForDebugEvent
+  WaitForMultipleObjects=kPrf2Wrap_WaitForMultipleObjects
+  WaitForMultipleObjectsEx=kPrf2Wrap_WaitForMultipleObjectsEx
+  WaitForSingleObject=kPrf2Wrap_WaitForSingleObject
+  WaitForSingleObjectEx=kPrf2Wrap_WaitForSingleObjectEx
+  WaitNamedPipeA=kPrf2Wrap_WaitNamedPipeA
+  WaitNamedPipeW=kPrf2Wrap_WaitNamedPipeW
+  WideCharToMultiByte=kPrf2Wrap_WideCharToMultiByte
+  WinExec=kPrf2Wrap_WinExec
+  Wow64DisableWow64FsRedirection=kPrf2Wrap_Wow64DisableWow64FsRedirection
+  Wow64EnableWow64FsRedirection=kPrf2Wrap_Wow64EnableWow64FsRedirection
+  Wow64RevertWow64FsRedirection=kPrf2Wrap_Wow64RevertWow64FsRedirection
+  WriteConsoleA=kPrf2Wrap_WriteConsoleA
+  WriteConsoleInputA=kPrf2Wrap_WriteConsoleInputA
+  WriteConsoleInputW=kPrf2Wrap_WriteConsoleInputW
+  WriteConsoleOutputA=kPrf2Wrap_WriteConsoleOutputA
+  WriteConsoleOutputAttribute=kPrf2Wrap_WriteConsoleOutputAttribute
+  WriteConsoleOutputCharacterA=kPrf2Wrap_WriteConsoleOutputCharacterA
+  WriteConsoleOutputCharacterW=kPrf2Wrap_WriteConsoleOutputCharacterW
+  WriteConsoleOutputW=kPrf2Wrap_WriteConsoleOutputW
+  WriteConsoleW=kPrf2Wrap_WriteConsoleW
+  WriteFile=kPrf2Wrap_WriteFile
+  WriteFileEx=kPrf2Wrap_WriteFileEx
+  WriteFileGather=kPrf2Wrap_WriteFileGather
+  WritePrivateProfileSectionA=kPrf2Wrap_WritePrivateProfileSectionA
+  WritePrivateProfileSectionW=kPrf2Wrap_WritePrivateProfileSectionW
+  WritePrivateProfileStringA=kPrf2Wrap_WritePrivateProfileStringA
+  WritePrivateProfileStringW=kPrf2Wrap_WritePrivateProfileStringW
+  WritePrivateProfileStructA=kPrf2Wrap_WritePrivateProfileStructA
+  WritePrivateProfileStructW=kPrf2Wrap_WritePrivateProfileStructW
+  WriteProcessMemory=kPrf2Wrap_WriteProcessMemory
+  WriteProfileSectionA=kPrf2Wrap_WriteProfileSectionA
+  WriteProfileSectionW=kPrf2Wrap_WriteProfileSectionW
+  WriteProfileStringA=kPrf2Wrap_WriteProfileStringA
+  WriteProfileStringW=kPrf2Wrap_WriteProfileStringW
+  WriteTapemark=kPrf2Wrap_WriteTapemark
+  ZombifyActCtx=kPrf2Wrap_ZombifyActCtx
+  _hread=kPrf2Wrap__hread
+  _hwrite=kPrf2Wrap__hwrite
+  _lclose=kPrf2Wrap__lclose
+  _lcreat=kPrf2Wrap__lcreat
+  _llseek=kPrf2Wrap__llseek
+  _lopen=kPrf2Wrap__lopen
+  _lread=kPrf2Wrap__lread
+  _lwrite=kPrf2Wrap__lwrite
+  lstrcat=kPrf2Wrap_lstrcat
+  lstrcatA=kPrf2Wrap_lstrcatA
+  lstrcatW=kPrf2Wrap_lstrcatW
+  lstrcmp=kPrf2Wrap_lstrcmp
+  lstrcmpA=kPrf2Wrap_lstrcmpA
+  lstrcmpW=kPrf2Wrap_lstrcmpW
+  lstrcmpi=kPrf2Wrap_lstrcmpi
+  lstrcmpiA=kPrf2Wrap_lstrcmpiA
+  lstrcmpiW=kPrf2Wrap_lstrcmpiW
+  lstrcpy=kPrf2Wrap_lstrcpy
+  lstrcpyA=kPrf2Wrap_lstrcpyA
+  lstrcpyW=kPrf2Wrap_lstrcpyW
+  lstrcpyn=kPrf2Wrap_lstrcpyn
+  lstrcpynA=kPrf2Wrap_lstrcpynA
+  lstrcpynW=kPrf2Wrap_lstrcpynW
+  lstrlen=kPrf2Wrap_lstrlen
+  lstrlenA=kPrf2Wrap_lstrlenA
+  lstrlenW=kPrf2Wrap_lstrlenW
+  uaw_lstrcmpW=kPrf2Wrap_uaw_lstrcmpW
+  uaw_lstrcmpiW=kPrf2Wrap_uaw_lstrcmpiW
+  uaw_lstrlenW=kPrf2Wrap_uaw_lstrlenW
+  uaw_wcschr=kPrf2Wrap_uaw_wcschr
+  uaw_wcscpy=kPrf2Wrap_uaw_wcscpy
+  uaw_wcsicmp=kPrf2Wrap_uaw_wcsicmp
+  uaw_wcslen=kPrf2Wrap_uaw_wcslen
+  uaw_wcsrchr=kPrf2Wrap_uaw_wcsrchr
diff --git a/src/lib/kStuff/kProfiler2/kPrf2WinApiWrappersImp-x86.def b/src/lib/kStuff/kProfiler2/kPrf2WinApiWrappersImp-x86.def
new file mode 100644
index 0000000..c1ddf85
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kPrf2WinApiWrappersImp-x86.def
@@ -0,0 +1,1682 @@
+LIBRARY kPrf2WinApiWrappers
+EXPORTS
+_ActivateActCtx at 8
+_ActivateActCtx at 8
+_AddAtomA at 4
+_AddAtomA at 4
+_AddAtomW at 4
+_AddAtomW at 4
+_AddConsoleAliasA at 12
+_AddConsoleAliasA at 12
+_AddConsoleAliasW at 12
+_AddConsoleAliasW at 12
+_AddRefActCtx at 4
+_AddRefActCtx at 4
+_AddVectoredContinueHandler at 8
+_AddVectoredContinueHandler at 8
+_AddVectoredExceptionHandler at 8
+_AddVectoredExceptionHandler at 8
+_AllocConsole at 0
+_AllocConsole at 0
+_AllocateUserPhysicalPages at 12
+_AllocateUserPhysicalPages at 12
+_AreFileApisANSI at 0
+_AreFileApisANSI at 0
+_AssignProcessToJobObject at 8
+_AssignProcessToJobObject at 8
+_AttachConsole at 4
+_AttachConsole at 4
+_BackupRead at 28
+_BackupRead at 28
+_BackupSeek at 24
+_BackupSeek at 24
+_BackupWrite at 28
+_BackupWrite at 28
+_Beep at 8
+_Beep at 8
+_BeginUpdateResourceA at 8
+_BeginUpdateResourceA at 8
+_BeginUpdateResourceW at 8
+_BeginUpdateResourceW at 8
+_BindIoCompletionCallback at 12
+_BindIoCompletionCallback at 12
+_BuildCommDCBA at 8
+_BuildCommDCBA at 8
+_BuildCommDCBAndTimeoutsA at 12
+_BuildCommDCBAndTimeoutsA at 12
+_BuildCommDCBAndTimeoutsW at 12
+_BuildCommDCBAndTimeoutsW at 12
+_BuildCommDCBW at 8
+_BuildCommDCBW at 8
+_CallNamedPipeA at 28
+_CallNamedPipeA at 28
+_CallNamedPipeW at 28
+_CallNamedPipeW at 28
+_CancelDeviceWakeupRequest at 4
+_CancelDeviceWakeupRequest at 4
+_CancelIo at 4
+_CancelIo at 4
+_CancelTimerQueueTimer at 8
+_CancelTimerQueueTimer at 8
+_CancelWaitableTimer at 4
+_CancelWaitableTimer at 4
+_ChangeTimerQueueTimer at 16
+_ChangeTimerQueueTimer at 16
+_CheckNameLegalDOS8Dot3A at 20
+_CheckNameLegalDOS8Dot3A at 20
+_CheckNameLegalDOS8Dot3W at 20
+_CheckNameLegalDOS8Dot3W at 20
+_CheckRemoteDebuggerPresent at 8
+_CheckRemoteDebuggerPresent at 8
+_ClearCommBreak at 4
+_ClearCommBreak at 4
+_ClearCommError at 12
+_ClearCommError at 12
+_CloseHandle at 4
+_CloseHandle at 4
+_CommConfigDialogA at 12
+_CommConfigDialogA at 12
+_CommConfigDialogW at 12
+_CommConfigDialogW at 12
+_CompareFileTime at 8
+_CompareFileTime at 8
+_CompareStringA at 24
+_CompareStringA at 24
+_CompareStringW at 24
+_CompareStringW at 24
+_ConnectNamedPipe at 8
+_ConnectNamedPipe at 8
+_ContinueDebugEvent at 12
+_ContinueDebugEvent at 12
+_ConvertDefaultLocale at 4
+_ConvertDefaultLocale at 4
+_ConvertFiberToThread at 0
+_ConvertFiberToThread at 0
+_ConvertThreadToFiber at 4
+_ConvertThreadToFiber at 4
+_ConvertThreadToFiberEx at 8
+_ConvertThreadToFiberEx at 8
+_CopyFileA at 12
+_CopyFileA at 12
+_CopyFileExA at 24
+_CopyFileExA at 24
+_CopyFileExW at 24
+_CopyFileExW at 24
+_CopyFileW at 12
+_CopyFileW at 12
+_CreateActCtxA at 4
+_CreateActCtxA at 4
+_CreateActCtxW at 4
+_CreateActCtxW at 4
+_CreateConsoleScreenBuffer at 20
+_CreateConsoleScreenBuffer at 20
+_CreateDirectoryA at 8
+_CreateDirectoryA at 8
+_CreateDirectoryExA at 12
+_CreateDirectoryExA at 12
+_CreateDirectoryExW at 12
+_CreateDirectoryExW at 12
+_CreateDirectoryW at 8
+_CreateDirectoryW at 8
+_CreateEventA at 16
+_CreateEventA at 16
+_CreateEventW at 16
+_CreateEventW at 16
+_CreateFiber at 12
+_CreateFiber at 12
+_CreateFiberEx at 20
+_CreateFiberEx at 20
+_CreateFileA at 28
+_CreateFileA at 28
+_CreateFileMappingA at 24
+_CreateFileMappingA at 24
+_CreateFileMappingW at 24
+_CreateFileMappingW at 24
+_CreateFileW at 28
+_CreateFileW at 28
+_CreateHardLinkA at 12
+_CreateHardLinkA at 12
+_CreateHardLinkW at 12
+_CreateHardLinkW at 12
+_CreateIoCompletionPort at 16
+_CreateIoCompletionPort at 16
+_CreateJobObjectA at 8
+_CreateJobObjectA at 8
+_CreateJobObjectW at 8
+_CreateJobObjectW at 8
+_CreateJobSet at 12
+_CreateJobSet at 12
+_CreateMailslotA at 16
+_CreateMailslotA at 16
+_CreateMailslotW at 16
+_CreateMailslotW at 16
+_CreateMemoryResourceNotification at 4
+_CreateMemoryResourceNotification at 4
+_CreateMutexA at 12
+_CreateMutexA at 12
+_CreateMutexW at 12
+_CreateMutexW at 12
+_CreateNamedPipeA at 32
+_CreateNamedPipeA at 32
+_CreateNamedPipeW at 32
+_CreateNamedPipeW at 32
+_CreatePipe at 16
+_CreatePipe at 16
+_CreateProcessA at 40
+_CreateProcessA at 40
+_CreateProcessW at 40
+_CreateProcessW at 40
+_CreateRemoteThread at 28
+_CreateRemoteThread at 28
+_CreateSemaphoreA at 16
+_CreateSemaphoreA at 16
+_CreateSemaphoreW at 16
+_CreateSemaphoreW at 16
+_CreateTapePartition at 16
+_CreateTapePartition at 16
+_CreateThread at 24
+_CreateThread at 24
+_CreateTimerQueue at 0
+_CreateTimerQueue at 0
+_CreateTimerQueueTimer at 28
+_CreateTimerQueueTimer at 28
+_CreateToolhelp32Snapshot at 8
+_CreateToolhelp32Snapshot at 8
+_CreateWaitableTimerA at 12
+_CreateWaitableTimerA at 12
+_CreateWaitableTimerW at 12
+_CreateWaitableTimerW at 12
+_DeactivateActCtx at 8
+_DeactivateActCtx at 8
+_DebugActiveProcess at 4
+_DebugActiveProcess at 4
+_DebugActiveProcessStop at 4
+_DebugActiveProcessStop at 4
+_DebugBreak at 0
+_DebugBreak at 0
+_DebugBreakProcess at 4
+_DebugBreakProcess at 4
+_DebugSetProcessKillOnExit at 4
+_DebugSetProcessKillOnExit at 4
+_DecodePointer at 4
+_DecodePointer at 4
+_DecodeSystemPointer at 4
+_DecodeSystemPointer at 4
+_DefineDosDeviceA at 12
+_DefineDosDeviceA at 12
+_DefineDosDeviceW at 12
+_DefineDosDeviceW at 12
+_DeleteAtom at 4
+_DeleteAtom at 4
+_DeleteCriticalSection at 4
+_DeleteCriticalSection at 4
+_DeleteFiber at 4
+_DeleteFiber at 4
+_DeleteFileA at 4
+_DeleteFileA at 4
+_DeleteFileW at 4
+_DeleteFileW at 4
+_DeleteTimerQueue at 4
+_DeleteTimerQueue at 4
+_DeleteTimerQueueEx at 8
+_DeleteTimerQueueEx at 8
+_DeleteTimerQueueTimer at 12
+_DeleteTimerQueueTimer at 12
+_DeleteVolumeMountPointA at 4
+_DeleteVolumeMountPointA at 4
+_DeleteVolumeMountPointW at 4
+_DeleteVolumeMountPointW at 4
+_DeviceIoControl at 32
+_DeviceIoControl at 32
+_DisableThreadLibraryCalls at 4
+_DisableThreadLibraryCalls at 4
+_DisconnectNamedPipe at 4
+_DisconnectNamedPipe at 4
+_DnsHostnameToComputerNameA at 12
+_DnsHostnameToComputerNameA at 12
+_DnsHostnameToComputerNameW at 12
+_DnsHostnameToComputerNameW at 12
+_DosDateTimeToFileTime at 12
+_DosDateTimeToFileTime at 12
+_DuplicateHandle at 28
+_DuplicateHandle at 28
+_EncodePointer at 4
+_EncodePointer at 4
+_EncodeSystemPointer at 4
+_EncodeSystemPointer at 4
+_EndUpdateResourceA at 8
+_EndUpdateResourceA at 8
+_EndUpdateResourceW at 8
+_EndUpdateResourceW at 8
+_EnterCriticalSection at 4
+_EnterCriticalSection at 4
+_EnumCalendarInfoA at 16
+_EnumCalendarInfoA at 16
+_EnumCalendarInfoExA at 16
+_EnumCalendarInfoExA at 16
+_EnumCalendarInfoExW at 16
+_EnumCalendarInfoExW at 16
+_EnumCalendarInfoW at 16
+_EnumCalendarInfoW at 16
+_EnumDateFormatsA at 12
+_EnumDateFormatsA at 12
+_EnumDateFormatsExA at 12
+_EnumDateFormatsExA at 12
+_EnumDateFormatsExW at 12
+_EnumDateFormatsExW at 12
+_EnumDateFormatsW at 12
+_EnumDateFormatsW at 12
+_EnumLanguageGroupLocalesA at 16
+_EnumLanguageGroupLocalesA at 16
+_EnumLanguageGroupLocalesW at 16
+_EnumLanguageGroupLocalesW at 16
+_EnumResourceLanguagesA at 20
+_EnumResourceLanguagesA at 20
+_EnumResourceLanguagesW at 20
+_EnumResourceLanguagesW at 20
+_EnumResourceNamesA at 16
+_EnumResourceNamesA at 16
+_EnumResourceNamesW at 16
+_EnumResourceNamesW at 16
+_EnumResourceTypesA at 12
+_EnumResourceTypesA at 12
+_EnumResourceTypesW at 12
+_EnumResourceTypesW at 12
+_EnumSystemCodePagesA at 8
+_EnumSystemCodePagesA at 8
+_EnumSystemCodePagesW at 8
+_EnumSystemCodePagesW at 8
+_EnumSystemFirmwareTables at 12
+_EnumSystemFirmwareTables at 12
+_EnumSystemGeoID at 12
+_EnumSystemGeoID at 12
+_EnumSystemLanguageGroupsA at 12
+_EnumSystemLanguageGroupsA at 12
+_EnumSystemLanguageGroupsW at 12
+_EnumSystemLanguageGroupsW at 12
+_EnumSystemLocalesA at 8
+_EnumSystemLocalesA at 8
+_EnumSystemLocalesW at 8
+_EnumSystemLocalesW at 8
+_EnumTimeFormatsA at 12
+_EnumTimeFormatsA at 12
+_EnumTimeFormatsW at 12
+_EnumTimeFormatsW at 12
+_EnumUILanguagesA at 12
+_EnumUILanguagesA at 12
+_EnumUILanguagesW at 12
+_EnumUILanguagesW at 12
+_EraseTape at 12
+_EraseTape at 12
+_EscapeCommFunction at 8
+_EscapeCommFunction at 8
+_ExitProcess at 4
+_ExitProcess at 4
+_ExitThread at 4
+_ExitThread at 4
+_ExpandEnvironmentStringsA at 12
+_ExpandEnvironmentStringsA at 12
+_ExpandEnvironmentStringsW at 12
+_ExpandEnvironmentStringsW at 12
+_FatalAppExitA at 8
+_FatalAppExitA at 8
+_FatalAppExitW at 8
+_FatalAppExitW at 8
+_FatalExit at 4
+_FatalExit at 4
+_FileTimeToDosDateTime at 12
+_FileTimeToDosDateTime at 12
+_FileTimeToLocalFileTime at 8
+_FileTimeToLocalFileTime at 8
+_FileTimeToSystemTime at 8
+_FileTimeToSystemTime at 8
+_FillConsoleOutputAttribute at 20
+_FillConsoleOutputAttribute at 20
+_FillConsoleOutputCharacterA at 20
+_FillConsoleOutputCharacterA at 20
+_FillConsoleOutputCharacterW at 20
+_FillConsoleOutputCharacterW at 20
+_FindActCtxSectionGuid at 20
+_FindActCtxSectionGuid at 20
+_FindActCtxSectionStringA at 20
+_FindActCtxSectionStringA at 20
+_FindActCtxSectionStringW at 20
+_FindActCtxSectionStringW at 20
+_FindAtomA at 4
+_FindAtomA at 4
+_FindAtomW at 4
+_FindAtomW at 4
+_FindClose at 4
+_FindClose at 4
+_FindCloseChangeNotification at 4
+_FindCloseChangeNotification at 4
+_FindFirstChangeNotificationA at 12
+_FindFirstChangeNotificationA at 12
+_FindFirstChangeNotificationW at 12
+_FindFirstChangeNotificationW at 12
+_FindFirstFileA at 8
+_FindFirstFileA at 8
+_FindFirstFileExA at 24
+_FindFirstFileExA at 24
+_FindFirstFileExW at 24
+_FindFirstFileExW at 24
+_FindFirstFileW at 8
+_FindFirstFileW at 8
+_FindFirstStreamW at 16
+_FindFirstStreamW at 16
+_FindFirstVolumeA at 8
+_FindFirstVolumeA at 8
+_FindFirstVolumeMountPointA at 12
+_FindFirstVolumeMountPointA at 12
+_FindFirstVolumeMountPointW at 12
+_FindFirstVolumeMountPointW at 12
+_FindFirstVolumeW at 8
+_FindFirstVolumeW at 8
+_FindNextChangeNotification at 4
+_FindNextChangeNotification at 4
+_FindNextFileA at 8
+_FindNextFileA at 8
+_FindNextFileW at 8
+_FindNextFileW at 8
+_FindNextStreamW at 8
+_FindNextStreamW at 8
+_FindNextVolumeA at 12
+_FindNextVolumeA at 12
+_FindNextVolumeMountPointA at 12
+_FindNextVolumeMountPointA at 12
+_FindNextVolumeMountPointW at 12
+_FindNextVolumeMountPointW at 12
+_FindNextVolumeW at 12
+_FindNextVolumeW at 12
+_FindResourceA at 12
+_FindResourceA at 12
+_FindResourceExA at 16
+_FindResourceExA at 16
+_FindResourceExW at 16
+_FindResourceExW at 16
+_FindResourceW at 12
+_FindResourceW at 12
+_FindVolumeClose at 4
+_FindVolumeClose at 4
+_FindVolumeMountPointClose at 4
+_FindVolumeMountPointClose at 4
+_FlsAlloc at 4
+_FlsAlloc at 4
+_FlsFree at 4
+_FlsFree at 4
+_FlsGetValue at 4
+_FlsGetValue at 4
+_FlsSetValue at 8
+_FlsSetValue at 8
+_FlushConsoleInputBuffer at 4
+_FlushConsoleInputBuffer at 4
+_FlushFileBuffers at 4
+_FlushFileBuffers at 4
+_FlushInstructionCache at 12
+_FlushInstructionCache at 12
+_FlushViewOfFile at 8
+_FlushViewOfFile at 8
+_FoldStringA at 20
+_FoldStringA at 20
+_FoldStringW at 20
+_FoldStringW at 20
+_FormatMessageA at 28
+_FormatMessageA at 28
+_FormatMessageW at 28
+_FormatMessageW at 28
+_FreeConsole at 0
+_FreeConsole at 0
+_FreeEnvironmentStringsA at 4
+_FreeEnvironmentStringsA at 4
+_FreeEnvironmentStringsW at 4
+_FreeEnvironmentStringsW at 4
+_FreeLibrary at 4
+_FreeLibrary at 4
+_FreeLibraryAndExitThread at 8
+_FreeLibraryAndExitThread at 8
+_FreeResource at 4
+_FreeResource at 4
+_FreeUserPhysicalPages at 12
+_FreeUserPhysicalPages at 12
+_GenerateConsoleCtrlEvent at 8
+_GenerateConsoleCtrlEvent at 8
+_GetACP at 0
+_GetACP at 0
+_GetAtomNameA at 12
+_GetAtomNameA at 12
+_GetAtomNameW at 12
+_GetAtomNameW at 12
+_GetBinaryType at 8
+_GetBinaryType at 8
+_GetBinaryTypeA at 8
+_GetBinaryTypeA at 8
+_GetBinaryTypeW at 8
+_GetBinaryTypeW at 8
+_GetCPInfo at 8
+_GetCPInfo at 8
+_GetCPInfoExA at 12
+_GetCPInfoExA at 12
+_GetCPInfoExW at 12
+_GetCPInfoExW at 12
+_GetCalendarInfoA at 24
+_GetCalendarInfoA at 24
+_GetCalendarInfoW at 24
+_GetCalendarInfoW at 24
+_GetCommConfig at 12
+_GetCommConfig at 12
+_GetCommMask at 8
+_GetCommMask at 8
+_GetCommModemStatus at 8
+_GetCommModemStatus at 8
+_GetCommProperties at 8
+_GetCommProperties at 8
+_GetCommState at 8
+_GetCommState at 8
+_GetCommTimeouts at 8
+_GetCommTimeouts at 8
+_GetCommandLineA at 0
+_GetCommandLineA at 0
+_GetCommandLineW at 0
+_GetCommandLineW at 0
+_GetCompressedFileSizeA at 8
+_GetCompressedFileSizeA at 8
+_GetCompressedFileSizeW at 8
+_GetCompressedFileSizeW at 8
+_GetComputerNameA at 8
+_GetComputerNameA at 8
+_GetComputerNameExA at 12
+_GetComputerNameExA at 12
+_GetComputerNameExW at 12
+_GetComputerNameExW at 12
+_GetComputerNameW at 8
+_GetComputerNameW at 8
+_GetConsoleAliasA at 16
+_GetConsoleAliasA at 16
+_GetConsoleAliasExesA at 8
+_GetConsoleAliasExesA at 8
+_GetConsoleAliasExesLengthA at 0
+_GetConsoleAliasExesLengthA at 0
+_GetConsoleAliasExesLengthW at 0
+_GetConsoleAliasExesLengthW at 0
+_GetConsoleAliasExesW at 8
+_GetConsoleAliasExesW at 8
+_GetConsoleAliasW at 16
+_GetConsoleAliasW at 16
+_GetConsoleAliasesA at 12
+_GetConsoleAliasesA at 12
+_GetConsoleAliasesLengthA at 4
+_GetConsoleAliasesLengthA at 4
+_GetConsoleAliasesLengthW at 4
+_GetConsoleAliasesLengthW at 4
+_GetConsoleAliasesW at 12
+_GetConsoleAliasesW at 12
+_GetConsoleCP at 0
+_GetConsoleCP at 0
+_GetConsoleCursorInfo at 8
+_GetConsoleCursorInfo at 8
+_GetConsoleDisplayMode at 4
+_GetConsoleDisplayMode at 4
+_GetConsoleFontSize at 8
+_GetConsoleFontSize at 8
+_GetConsoleMode at 8
+_GetConsoleMode at 8
+_GetConsoleOutputCP at 0
+_GetConsoleOutputCP at 0
+_GetConsoleProcessList at 8
+_GetConsoleProcessList at 8
+_GetConsoleScreenBufferInfo at 8
+_GetConsoleScreenBufferInfo at 8
+_GetConsoleSelectionInfo at 4
+_GetConsoleSelectionInfo at 4
+_GetConsoleTitleA at 8
+_GetConsoleTitleA at 8
+_GetConsoleTitleW at 8
+_GetConsoleTitleW at 8
+_GetConsoleWindow at 0
+_GetConsoleWindow at 0
+_GetCurrencyFormatA at 24
+_GetCurrencyFormatA at 24
+_GetCurrencyFormatW at 24
+_GetCurrencyFormatW at 24
+_GetCurrentActCtx at 4
+_GetCurrentActCtx at 4
+_GetCurrentConsoleFont at 12
+_GetCurrentConsoleFont at 12
+_GetCurrentDirectoryA at 8
+_GetCurrentDirectoryA at 8
+_GetCurrentDirectoryW at 8
+_GetCurrentDirectoryW at 8
+_GetCurrentProcess at 0
+_GetCurrentProcess at 0
+_GetCurrentProcessId at 0
+_GetCurrentProcessId at 0
+_GetCurrentProcessorNumber at 0
+_GetCurrentProcessorNumber at 0
+_GetCurrentThread at 0
+_GetCurrentThread at 0
+_GetCurrentThreadId at 0
+_GetCurrentThreadId at 0
+_GetDateFormatA at 24
+_GetDateFormatA at 24
+_GetDateFormatW at 24
+_GetDateFormatW at 24
+_GetDefaultCommConfigA at 12
+_GetDefaultCommConfigA at 12
+_GetDefaultCommConfigW at 12
+_GetDefaultCommConfigW at 12
+_GetDevicePowerState at 8
+_GetDevicePowerState at 8
+_GetDiskFreeSpaceA at 20
+_GetDiskFreeSpaceA at 20
+_GetDiskFreeSpaceExA at 16
+_GetDiskFreeSpaceExA at 16
+_GetDiskFreeSpaceExW at 16
+_GetDiskFreeSpaceExW at 16
+_GetDiskFreeSpaceW at 20
+_GetDiskFreeSpaceW at 20
+_GetDllDirectoryA at 8
+_GetDllDirectoryA at 8
+_GetDllDirectoryW at 8
+_GetDllDirectoryW at 8
+_GetDriveTypeA at 4
+_GetDriveTypeA at 4
+_GetDriveTypeW at 4
+_GetDriveTypeW at 4
+_GetEnvironmentStrings at 0
+_GetEnvironmentStrings at 0
+_GetEnvironmentStringsA at 0
+_GetEnvironmentStringsA at 0
+_GetEnvironmentStringsW at 0
+_GetEnvironmentStringsW at 0
+_GetEnvironmentVariableA at 12
+_GetEnvironmentVariableA at 12
+_GetEnvironmentVariableW at 12
+_GetEnvironmentVariableW at 12
+_GetExitCodeProcess at 8
+_GetExitCodeProcess at 8
+_GetExitCodeThread at 8
+_GetExitCodeThread at 8
+_GetFileAttributesA at 4
+_GetFileAttributesA at 4
+_GetFileAttributesExA at 12
+_GetFileAttributesExA at 12
+_GetFileAttributesExW at 12
+_GetFileAttributesExW at 12
+_GetFileAttributesW at 4
+_GetFileAttributesW at 4
+_GetFileInformationByHandle at 8
+_GetFileInformationByHandle at 8
+_GetFileSize at 8
+_GetFileSize at 8
+_GetFileSizeEx at 8
+_GetFileSizeEx at 8
+_GetFileTime at 16
+_GetFileTime at 16
+_GetFileType at 4
+_GetFileType at 4
+_GetFirmwareEnvironmentVariableA at 16
+_GetFirmwareEnvironmentVariableA at 16
+_GetFirmwareEnvironmentVariableW at 16
+_GetFirmwareEnvironmentVariableW at 16
+_GetFullPathNameA at 16
+_GetFullPathNameA at 16
+_GetFullPathNameW at 16
+_GetFullPathNameW at 16
+_GetGeoInfoA at 20
+_GetGeoInfoA at 20
+_GetGeoInfoW at 20
+_GetGeoInfoW at 20
+_GetHandleInformation at 8
+_GetHandleInformation at 8
+_GetLargePageMinimum at 0
+_GetLargePageMinimum at 0
+_GetLargestConsoleWindowSize at 4
+_GetLargestConsoleWindowSize at 4
+_GetLastError at 0
+_GetLastError at 0
+_GetLocalTime at 4
+_GetLocalTime at 4
+_GetLocaleInfoA at 16
+_GetLocaleInfoA at 16
+_GetLocaleInfoW at 16
+_GetLocaleInfoW at 16
+_GetLogicalDriveStringsA at 8
+_GetLogicalDriveStringsA at 8
+_GetLogicalDriveStringsW at 8
+_GetLogicalDriveStringsW at 8
+_GetLogicalDrives at 0
+_GetLogicalDrives at 0
+_GetLogicalProcessorInformation at 8
+_GetLogicalProcessorInformation at 8
+_GetLongPathNameA at 12
+_GetLongPathNameA at 12
+_GetLongPathNameW at 12
+_GetLongPathNameW at 12
+_GetMailslotInfo at 20
+_GetMailslotInfo at 20
+_GetModuleFileNameA at 12
+_GetModuleFileNameA at 12
+_GetModuleFileNameW at 12
+_GetModuleFileNameW at 12
+_GetModuleHandleA at 4
+_GetModuleHandleA at 4
+_GetModuleHandleExA at 12
+_GetModuleHandleExA at 12
+_GetModuleHandleExW at 12
+_GetModuleHandleExW at 12
+_GetModuleHandleW at 4
+_GetModuleHandleW at 4
+_GetNLSVersion at 12
+_GetNLSVersion at 12
+_GetNamedPipeHandleStateA at 28
+_GetNamedPipeHandleStateA at 28
+_GetNamedPipeHandleStateW at 28
+_GetNamedPipeHandleStateW at 28
+_GetNamedPipeInfo at 20
+_GetNamedPipeInfo at 20
+_GetNativeSystemInfo at 4
+_GetNativeSystemInfo at 4
+_GetNumaAvailableMemoryNode at 8
+_GetNumaAvailableMemoryNode at 8
+_GetNumaHighestNodeNumber at 4
+_GetNumaHighestNodeNumber at 4
+_GetNumaNodeProcessorMask at 8
+_GetNumaNodeProcessorMask at 8
+_GetNumaProcessorNode at 8
+_GetNumaProcessorNode at 8
+_GetNumberFormatA at 24
+_GetNumberFormatA at 24
+_GetNumberFormatW at 24
+_GetNumberFormatW at 24
+_GetNumberOfConsoleInputEvents at 8
+_GetNumberOfConsoleInputEvents at 8
+_GetNumberOfConsoleMouseButtons at 4
+_GetNumberOfConsoleMouseButtons at 4
+_GetOEMCP at 0
+_GetOEMCP at 0
+_GetOverlappedResult at 16
+_GetOverlappedResult at 16
+_GetPriorityClass at 4
+_GetPriorityClass at 4
+_GetPrivateProfileIntA at 16
+_GetPrivateProfileIntA at 16
+_GetPrivateProfileIntW at 16
+_GetPrivateProfileIntW at 16
+_GetPrivateProfileSectionA at 16
+_GetPrivateProfileSectionA at 16
+_GetPrivateProfileSectionNamesA at 12
+_GetPrivateProfileSectionNamesA at 12
+_GetPrivateProfileSectionNamesW at 12
+_GetPrivateProfileSectionNamesW at 12
+_GetPrivateProfileSectionW at 16
+_GetPrivateProfileSectionW at 16
+_GetPrivateProfileStringA at 24
+_GetPrivateProfileStringA at 24
+_GetPrivateProfileStringW at 24
+_GetPrivateProfileStringW at 24
+_GetPrivateProfileStructA at 20
+_GetPrivateProfileStructA at 20
+_GetPrivateProfileStructW at 20
+_GetPrivateProfileStructW at 20
+_GetProcAddress at 8
+_GetProcAddress at 8
+_GetProcessAffinityMask at 12
+_GetProcessAffinityMask at 12
+_GetProcessHandleCount at 8
+_GetProcessHandleCount at 8
+_GetProcessHeap at 0
+_GetProcessHeap at 0
+_GetProcessHeaps at 8
+_GetProcessHeaps at 8
+_GetProcessId at 4
+_GetProcessId at 4
+_GetProcessIdOfThread at 4
+_GetProcessIdOfThread at 4
+_GetProcessIoCounters at 8
+_GetProcessIoCounters at 8
+_GetProcessPriorityBoost at 8
+_GetProcessPriorityBoost at 8
+_GetProcessShutdownParameters at 8
+_GetProcessShutdownParameters at 8
+_GetProcessTimes at 20
+_GetProcessTimes at 20
+_GetProcessVersion at 4
+_GetProcessVersion at 4
+_GetProcessWorkingSetSize at 12
+_GetProcessWorkingSetSize at 12
+_GetProcessWorkingSetSizeEx at 16
+_GetProcessWorkingSetSizeEx at 16
+_GetProfileIntA at 12
+_GetProfileIntA at 12
+_GetProfileIntW at 12
+_GetProfileIntW at 12
+_GetProfileSectionA at 12
+_GetProfileSectionA at 12
+_GetProfileSectionW at 12
+_GetProfileSectionW at 12
+_GetProfileStringA at 20
+_GetProfileStringA at 20
+_GetProfileStringW at 20
+_GetProfileStringW at 20
+_GetQueuedCompletionStatus at 20
+_GetQueuedCompletionStatus at 20
+_GetShortPathNameA at 12
+_GetShortPathNameA at 12
+_GetShortPathNameW at 12
+_GetShortPathNameW at 12
+_GetStartupInfoA at 4
+_GetStartupInfoA at 4
+_GetStartupInfoW at 4
+_GetStartupInfoW at 4
+_GetStdHandle at 4
+_GetStdHandle at 4
+_GetStringTypeA at 20
+_GetStringTypeA at 20
+_GetStringTypeExA at 20
+_GetStringTypeExA at 20
+_GetStringTypeExW at 20
+_GetStringTypeExW at 20
+_GetStringTypeW at 16
+_GetStringTypeW at 16
+_GetSystemDefaultLCID at 0
+_GetSystemDefaultLCID at 0
+_GetSystemDefaultLangID at 0
+_GetSystemDefaultLangID at 0
+_GetSystemDefaultUILanguage at 0
+_GetSystemDefaultUILanguage at 0
+_GetSystemDirectoryA at 8
+_GetSystemDirectoryA at 8
+_GetSystemDirectoryW at 8
+_GetSystemDirectoryW at 8
+_GetSystemFileCacheSize at 12
+_GetSystemFileCacheSize at 12
+_GetSystemFirmwareTable at 16
+_GetSystemFirmwareTable at 16
+_GetSystemInfo at 4
+_GetSystemInfo at 4
+_GetSystemPowerStatus at 4
+_GetSystemPowerStatus at 4
+_GetSystemRegistryQuota at 8
+_GetSystemRegistryQuota at 8
+_GetSystemTime at 4
+_GetSystemTime at 4
+_GetSystemTimeAdjustment at 12
+_GetSystemTimeAdjustment at 12
+_GetSystemTimeAsFileTime at 4
+_GetSystemTimeAsFileTime at 4
+_GetSystemTimes at 12
+_GetSystemTimes at 12
+_GetSystemWindowsDirectoryA at 8
+_GetSystemWindowsDirectoryA at 8
+_GetSystemWindowsDirectoryW at 8
+_GetSystemWindowsDirectoryW at 8
+_GetSystemWow64DirectoryA at 8
+_GetSystemWow64DirectoryA at 8
+_GetSystemWow64DirectoryW at 8
+_GetSystemWow64DirectoryW at 8
+_GetTapeParameters at 16
+_GetTapeParameters at 16
+_GetTapePosition at 20
+_GetTapePosition at 20
+_GetTapeStatus at 4
+_GetTapeStatus at 4
+_GetTempFileNameA at 16
+_GetTempFileNameA at 16
+_GetTempFileNameW at 16
+_GetTempFileNameW at 16
+_GetTempPathA at 8
+_GetTempPathA at 8
+_GetTempPathW at 8
+_GetTempPathW at 8
+_GetThreadContext at 8
+_GetThreadContext at 8
+_GetThreadIOPendingFlag at 8
+_GetThreadIOPendingFlag at 8
+_GetThreadId at 4
+_GetThreadId at 4
+_GetThreadLocale at 0
+_GetThreadLocale at 0
+_GetThreadPriority at 4
+_GetThreadPriority at 4
+_GetThreadPriorityBoost at 8
+_GetThreadPriorityBoost at 8
+_GetThreadSelectorEntry at 12
+_GetThreadSelectorEntry at 12
+_GetThreadTimes at 20
+_GetThreadTimes at 20
+_GetTickCount at 0
+_GetTickCount at 0
+_GetTimeFormatA at 24
+_GetTimeFormatA at 24
+_GetTimeFormatW at 24
+_GetTimeFormatW at 24
+_GetTimeZoneInformation at 4
+_GetTimeZoneInformation at 4
+_GetUserDefaultLCID at 0
+_GetUserDefaultLCID at 0
+_GetUserDefaultLangID at 0
+_GetUserDefaultLangID at 0
+_GetUserDefaultUILanguage at 0
+_GetUserDefaultUILanguage at 0
+_GetUserGeoID at 4
+_GetUserGeoID at 4
+_GetVersion at 0
+_GetVersion at 0
+_GetVersionExA at 4
+_GetVersionExA at 4
+_GetVersionExW at 4
+_GetVersionExW at 4
+_GetVolumeInformationA at 32
+_GetVolumeInformationA at 32
+_GetVolumeInformationW at 32
+_GetVolumeInformationW at 32
+_GetVolumeNameForVolumeMountPointA at 12
+_GetVolumeNameForVolumeMountPointA at 12
+_GetVolumeNameForVolumeMountPointW at 12
+_GetVolumeNameForVolumeMountPointW at 12
+_GetVolumePathNameA at 12
+_GetVolumePathNameA at 12
+_GetVolumePathNameW at 12
+_GetVolumePathNameW at 12
+_GetVolumePathNamesForVolumeNameA at 16
+_GetVolumePathNamesForVolumeNameA at 16
+_GetVolumePathNamesForVolumeNameW at 16
+_GetVolumePathNamesForVolumeNameW at 16
+_GetWindowsDirectoryA at 8
+_GetWindowsDirectoryA at 8
+_GetWindowsDirectoryW at 8
+_GetWindowsDirectoryW at 8
+_GetWriteWatch at 24
+_GetWriteWatch at 24
+_GlobalAddAtomA at 4
+_GlobalAddAtomA at 4
+_GlobalAddAtomW at 4
+_GlobalAddAtomW at 4
+_GlobalAlloc at 8
+_GlobalAlloc at 8
+_GlobalCompact at 4
+_GlobalCompact at 4
+_GlobalDeleteAtom at 4
+_GlobalDeleteAtom at 4
+_GlobalFindAtomA at 4
+_GlobalFindAtomA at 4
+_GlobalFindAtomW at 4
+_GlobalFindAtomW at 4
+_GlobalFix at 4
+_GlobalFix at 4
+_GlobalFlags at 4
+_GlobalFlags at 4
+_GlobalFree at 4
+_GlobalFree at 4
+_GlobalGetAtomNameA at 12
+_GlobalGetAtomNameA at 12
+_GlobalGetAtomNameW at 12
+_GlobalGetAtomNameW at 12
+_GlobalHandle at 4
+_GlobalHandle at 4
+_GlobalLock at 4
+_GlobalLock at 4
+_GlobalMemoryStatus at 4
+_GlobalMemoryStatus at 4
+_GlobalMemoryStatusEx at 4
+_GlobalMemoryStatusEx at 4
+_GlobalReAlloc at 12
+_GlobalReAlloc at 12
+_GlobalSize at 4
+_GlobalSize at 4
+_GlobalUnWire at 4
+_GlobalUnWire at 4
+_GlobalUnfix at 4
+_GlobalUnfix at 4
+_GlobalUnlock at 4
+_GlobalUnlock at 4
+_GlobalWire at 4
+_GlobalWire at 4
+_Heap32First at 12
+_Heap32First at 12
+_Heap32ListFirst at 8
+_Heap32ListFirst at 8
+_Heap32ListNext at 8
+_Heap32ListNext at 8
+_Heap32Next at 4
+_Heap32Next at 4
+_HeapAlloc at 12
+_HeapAlloc at 12
+_HeapCompact at 8
+_HeapCompact at 8
+_HeapCreate at 12
+_HeapCreate at 12
+_HeapDestroy at 4
+_HeapDestroy at 4
+_HeapFree at 12
+_HeapFree at 12
+_HeapLock at 4
+_HeapLock at 4
+_HeapQueryInformation at 20
+_HeapQueryInformation at 20
+_HeapReAlloc at 16
+_HeapReAlloc at 16
+_HeapSetInformation at 16
+_HeapSetInformation at 16
+_HeapSize at 12
+_HeapSize at 12
+_HeapUnlock at 4
+_HeapUnlock at 4
+_HeapValidate at 12
+_HeapValidate at 12
+_HeapWalk at 8
+_HeapWalk at 8
+_InitAtomTable at 4
+_InitAtomTable at 4
+_InitializeCriticalSection at 4
+_InitializeCriticalSection at 4
+_InitializeCriticalSectionAndSpinCount at 8
+_InitializeCriticalSectionAndSpinCount at 8
+_InitializeSListHead at 4
+_InitializeSListHead at 4
+_InterlockedCompareExchange64 at 20
+_InterlockedCompareExchange64 at 20
+_InterlockedCompareExchange at 12
+_InterlockedCompareExchange at 12
+_InterlockedDecrement at 4
+_InterlockedDecrement at 4
+_InterlockedExchange at 8
+_InterlockedExchange at 8
+_InterlockedExchangeAdd at 8
+_InterlockedExchangeAdd at 8
+_InterlockedFlushSList at 4
+_InterlockedFlushSList at 4
+_InterlockedIncrement at 4
+_InterlockedIncrement at 4
+_InterlockedPopEntrySList at 4
+_InterlockedPopEntrySList at 4
+_InterlockedPushEntrySList at 8
+_InterlockedPushEntrySList at 8
+_IsBadCodePtr at 4
+_IsBadCodePtr at 4
+_IsBadHugeReadPtr at 8
+_IsBadHugeReadPtr at 8
+_IsBadHugeWritePtr at 8
+_IsBadHugeWritePtr at 8
+_IsBadReadPtr at 8
+_IsBadReadPtr at 8
+_IsBadStringPtrA at 8
+_IsBadStringPtrA at 8
+_IsBadStringPtrW at 8
+_IsBadStringPtrW at 8
+_IsBadWritePtr at 8
+_IsBadWritePtr at 8
+_IsDBCSLeadByte at 4
+_IsDBCSLeadByte at 4
+_IsDBCSLeadByteEx at 8
+_IsDBCSLeadByteEx at 8
+_IsDebuggerPresent at 0
+_IsDebuggerPresent at 0
+_IsNLSDefinedString at 20
+_IsNLSDefinedString at 20
+_IsProcessInJob at 12
+_IsProcessInJob at 12
+_IsProcessorFeaturePresent at 4
+_IsProcessorFeaturePresent at 4
+_IsSystemResumeAutomatic at 0
+_IsSystemResumeAutomatic at 0
+_IsValidCodePage at 4
+_IsValidCodePage at 4
+_IsValidLanguageGroup at 8
+_IsValidLanguageGroup at 8
+_IsValidLocale at 8
+_IsValidLocale at 8
+_IsWow64Process at 8
+_IsWow64Process at 8
+_LCMapStringA at 24
+_LCMapStringA at 24
+_LCMapStringW at 24
+_LCMapStringW at 24
+_LeaveCriticalSection at 4
+_LeaveCriticalSection at 4
+_LoadLibraryA at 4
+_LoadLibraryA at 4
+_LoadLibraryExA at 12
+_LoadLibraryExA at 12
+_LoadLibraryExW at 12
+_LoadLibraryExW at 12
+_LoadLibraryW at 4
+_LoadLibraryW at 4
+_LoadModule at 8
+_LoadModule at 8
+_LoadResource at 8
+_LoadResource at 8
+_LocalAlloc at 8
+_LocalAlloc at 8
+_LocalCompact at 4
+_LocalCompact at 4
+_LocalFileTimeToFileTime at 8
+_LocalFileTimeToFileTime at 8
+_LocalFlags at 4
+_LocalFlags at 4
+_LocalFree at 4
+_LocalFree at 4
+_LocalHandle at 4
+_LocalHandle at 4
+_LocalLock at 4
+_LocalLock at 4
+_LocalReAlloc at 12
+_LocalReAlloc at 12
+_LocalShrink at 8
+_LocalShrink at 8
+_LocalSize at 4
+_LocalSize at 4
+_LocalUnlock at 4
+_LocalUnlock at 4
+_LockFile at 20
+_LockFile at 20
+_LockFileEx at 24
+_LockFileEx at 24
+_LockResource at 4
+_LockResource at 4
+_MapUserPhysicalPages at 12
+_MapUserPhysicalPages at 12
+_MapUserPhysicalPagesScatter at 12
+_MapUserPhysicalPagesScatter at 12
+_MapViewOfFile at 20
+_MapViewOfFile at 20
+_MapViewOfFileEx at 24
+_MapViewOfFileEx at 24
+_Module32First at 8
+_Module32First at 8
+_Module32FirstW at 8
+_Module32FirstW at 8
+_Module32Next at 8
+_Module32Next at 8
+_Module32NextW at 8
+_Module32NextW at 8
+_MoveFileA at 8
+_MoveFileA at 8
+_MoveFileExA at 12
+_MoveFileExA at 12
+_MoveFileExW at 12
+_MoveFileExW at 12
+_MoveFileW at 8
+_MoveFileW at 8
+_MoveFileWithProgressA at 20
+_MoveFileWithProgressA at 20
+_MoveFileWithProgressW at 20
+_MoveFileWithProgressW at 20
+_MulDiv at 12
+_MulDiv at 12
+_MultiByteToWideChar at 24
+_MultiByteToWideChar at 24
+_NeedCurrentDirectoryForExePathA at 4
+_NeedCurrentDirectoryForExePathA at 4
+_NeedCurrentDirectoryForExePathW at 4
+_NeedCurrentDirectoryForExePathW at 4
+_OpenEventA at 12
+_OpenEventA at 12
+_OpenEventW at 12
+_OpenEventW at 12
+_OpenFile at 12
+_OpenFile at 12
+_OpenFileMappingA at 12
+_OpenFileMappingA at 12
+_OpenFileMappingW at 12
+_OpenFileMappingW at 12
+_OpenJobObjectA at 12
+_OpenJobObjectA at 12
+_OpenJobObjectW at 12
+_OpenJobObjectW at 12
+_OpenMutexA at 12
+_OpenMutexA at 12
+_OpenMutexW at 12
+_OpenMutexW at 12
+_OpenProcess at 12
+_OpenProcess at 12
+_OpenSemaphoreA at 12
+_OpenSemaphoreA at 12
+_OpenSemaphoreW at 12
+_OpenSemaphoreW at 12
+_OpenThread at 12
+_OpenThread at 12
+_OpenWaitableTimerA at 12
+_OpenWaitableTimerA at 12
+_OpenWaitableTimerW at 12
+_OpenWaitableTimerW at 12
+_OutputDebugStringA at 4
+_OutputDebugStringA at 4
+_OutputDebugStringW at 4
+_OutputDebugStringW at 4
+_PeekConsoleInputA at 16
+_PeekConsoleInputA at 16
+_PeekConsoleInputW at 16
+_PeekConsoleInputW at 16
+_PeekNamedPipe at 24
+_PeekNamedPipe at 24
+_PostQueuedCompletionStatus at 16
+_PostQueuedCompletionStatus at 16
+_PrepareTape at 12
+_PrepareTape at 12
+_Process32First at 8
+_Process32First at 8
+_Process32FirstW at 8
+_Process32FirstW at 8
+_Process32Next at 8
+_Process32Next at 8
+_Process32NextW at 8
+_Process32NextW at 8
+_ProcessIdToSessionId at 8
+_ProcessIdToSessionId at 8
+_PulseEvent at 4
+_PulseEvent at 4
+_PurgeComm at 8
+_PurgeComm at 8
+_QueryActCtxW at 28
+_QueryActCtxW at 28
+_QueryDepthSList at 4
+_QueryDepthSList at 4
+_QueryDosDeviceA at 12
+_QueryDosDeviceA at 12
+_QueryDosDeviceW at 12
+_QueryDosDeviceW at 12
+_QueryInformationJobObject at 20
+_QueryInformationJobObject at 20
+_QueryMemoryResourceNotification at 8
+_QueryMemoryResourceNotification at 8
+_QueryPerformanceCounter at 4
+_QueryPerformanceCounter at 4
+_QueryPerformanceFrequency at 4
+_QueryPerformanceFrequency at 4
+_QueueUserAPC at 12
+_QueueUserAPC at 12
+_QueueUserWorkItem at 12
+_QueueUserWorkItem at 12
+_RaiseException at 16
+_RaiseException at 16
+_ReOpenFile at 16
+_ReOpenFile at 16
+_ReadConsoleA at 20
+_ReadConsoleA at 20
+_ReadConsoleInputA at 16
+_ReadConsoleInputA at 16
+_ReadConsoleInputW at 16
+_ReadConsoleInputW at 16
+_ReadConsoleOutputA at 20
+_ReadConsoleOutputA at 20
+_ReadConsoleOutputAttribute at 20
+_ReadConsoleOutputAttribute at 20
+_ReadConsoleOutputCharacterA at 20
+_ReadConsoleOutputCharacterA at 20
+_ReadConsoleOutputCharacterW at 20
+_ReadConsoleOutputCharacterW at 20
+_ReadConsoleOutputW at 20
+_ReadConsoleOutputW at 20
+_ReadConsoleW at 20
+_ReadConsoleW at 20
+_ReadDirectoryChangesW at 32
+_ReadDirectoryChangesW at 32
+_ReadFile at 20
+_ReadFile at 20
+_ReadFileEx at 20
+_ReadFileEx at 20
+_ReadFileScatter at 20
+_ReadFileScatter at 20
+_ReadProcessMemory at 20
+_ReadProcessMemory at 20
+_RegisterWaitForSingleObject at 24
+_RegisterWaitForSingleObject at 24
+_RegisterWaitForSingleObjectEx at 20
+_RegisterWaitForSingleObjectEx at 20
+_ReleaseActCtx at 4
+_ReleaseActCtx at 4
+_ReleaseMutex at 4
+_ReleaseMutex at 4
+_ReleaseSemaphore at 12
+_ReleaseSemaphore at 12
+_RemoveDirectoryA at 4
+_RemoveDirectoryA at 4
+_RemoveDirectoryW at 4
+_RemoveDirectoryW at 4
+_RemoveVectoredContinueHandler at 4
+_RemoveVectoredContinueHandler at 4
+_RemoveVectoredExceptionHandler at 4
+_RemoveVectoredExceptionHandler at 4
+_ReplaceFile at 24
+_ReplaceFile at 24
+_ReplaceFileA at 24
+_ReplaceFileA at 24
+_ReplaceFileW at 24
+_ReplaceFileW at 24
+_RequestDeviceWakeup at 4
+_RequestDeviceWakeup at 4
+_RequestWakeupLatency at 4
+_RequestWakeupLatency at 4
+_ResetEvent at 4
+_ResetEvent at 4
+_ResetWriteWatch at 8
+_ResetWriteWatch at 8
+_RestoreLastError at 4
+_RestoreLastError at 4
+_ResumeThread at 4
+_ResumeThread at 4
+_RtlCaptureContext at 4
+_RtlCaptureContext at 4
+_RtlCaptureStackBackTrace at 16
+_RtlCaptureStackBackTrace at 16
+_RtlFillMemory at 12
+_RtlFillMemory at 12
+_RtlMoveMemory at 12
+_RtlMoveMemory at 12
+_RtlUnwind at 16
+_RtlUnwind at 16
+_RtlZeroMemory at 8
+_RtlZeroMemory at 8
+_ScrollConsoleScreenBufferA at 20
+_ScrollConsoleScreenBufferA at 20
+_ScrollConsoleScreenBufferW at 20
+_ScrollConsoleScreenBufferW at 20
+_SearchPathA at 24
+_SearchPathA at 24
+_SearchPathW at 24
+_SearchPathW at 24
+_SetCalendarInfoA at 16
+_SetCalendarInfoA at 16
+_SetCalendarInfoW at 16
+_SetCalendarInfoW at 16
+_SetCommBreak at 4
+_SetCommBreak at 4
+_SetCommConfig at 12
+_SetCommConfig at 12
+_SetCommMask at 8
+_SetCommMask at 8
+_SetCommState at 8
+_SetCommState at 8
+_SetCommTimeouts at 8
+_SetCommTimeouts at 8
+_SetComputerNameA at 4
+_SetComputerNameA at 4
+_SetComputerNameExA at 8
+_SetComputerNameExA at 8
+_SetComputerNameExW at 8
+_SetComputerNameExW at 8
+_SetComputerNameW at 4
+_SetComputerNameW at 4
+_SetConsoleActiveScreenBuffer at 4
+_SetConsoleActiveScreenBuffer at 4
+_SetConsoleCP at 4
+_SetConsoleCP at 4
+_SetConsoleCtrlHandler at 8
+_SetConsoleCtrlHandler at 8
+_SetConsoleCursor at 8
+_SetConsoleCursor at 8
+_SetConsoleCursorInfo at 8
+_SetConsoleCursorInfo at 8
+_SetConsoleCursorPosition at 8
+_SetConsoleCursorPosition at 8
+_SetConsoleMode at 8
+_SetConsoleMode at 8
+_SetConsoleOutputCP at 4
+_SetConsoleOutputCP at 4
+_SetConsoleScreenBufferSize at 8
+_SetConsoleScreenBufferSize at 8
+_SetConsoleTextAttribute at 8
+_SetConsoleTextAttribute at 8
+_SetConsoleTitleA at 4
+_SetConsoleTitleA at 4
+_SetConsoleTitleW at 4
+_SetConsoleTitleW at 4
+_SetConsoleWindowInfo at 12
+_SetConsoleWindowInfo at 12
+_SetCriticalSectionSpinCount at 8
+_SetCriticalSectionSpinCount at 8
+_SetCurrentDirectoryA at 4
+_SetCurrentDirectoryA at 4
+_SetCurrentDirectoryW at 4
+_SetCurrentDirectoryW at 4
+_SetDefaultCommConfigA at 12
+_SetDefaultCommConfigA at 12
+_SetDefaultCommConfigW at 12
+_SetDefaultCommConfigW at 12
+_SetDllDirectoryA at 4
+_SetDllDirectoryA at 4
+_SetDllDirectoryW at 4
+_SetDllDirectoryW at 4
+_SetEndOfFile at 4
+_SetEndOfFile at 4
+_SetEnvironmentStringsA at 4
+_SetEnvironmentStringsA at 4
+_SetEnvironmentStringsW at 4
+_SetEnvironmentStringsW at 4
+_SetEnvironmentVariableA at 8
+_SetEnvironmentVariableA at 8
+_SetEnvironmentVariableW at 8
+_SetEnvironmentVariableW at 8
+_SetErrorMode at 4
+_SetErrorMode at 4
+_SetEvent at 4
+_SetEvent at 4
+_SetFileApisToANSI at 0
+_SetFileApisToANSI at 0
+_SetFileApisToOEM at 0
+_SetFileApisToOEM at 0
+_SetFileAttributesA at 8
+_SetFileAttributesA at 8
+_SetFileAttributesW at 8
+_SetFileAttributesW at 8
+_SetFilePointer at 16
+_SetFilePointer at 16
+_SetFilePointerEx at 20
+_SetFilePointerEx at 20
+_SetFileShortNameA at 8
+_SetFileShortNameA at 8
+_SetFileShortNameW at 8
+_SetFileShortNameW at 8
+_SetFileTime at 16
+_SetFileTime at 16
+_SetFileValidData at 12
+_SetFileValidData at 12
+_SetFirmwareEnvironmentVariableA at 16
+_SetFirmwareEnvironmentVariableA at 16
+_SetFirmwareEnvironmentVariableW at 16
+_SetFirmwareEnvironmentVariableW at 16
+_SetHandleCount at 4
+_SetHandleCount at 4
+_SetHandleInformation at 12
+_SetHandleInformation at 12
+_SetInformationJobObject at 16
+_SetInformationJobObject at 16
+_SetLastError at 4
+_SetLastError at 4
+_SetLocalTime at 4
+_SetLocalTime at 4
+_SetLocaleInfoA at 12
+_SetLocaleInfoA at 12
+_SetLocaleInfoW at 12
+_SetLocaleInfoW at 12
+_SetMailslotInfo at 8
+_SetMailslotInfo at 8
+_SetMessageWaitingIndicator at 8
+_SetMessageWaitingIndicator at 8
+_SetNamedPipeHandleState at 16
+_SetNamedPipeHandleState at 16
+_SetPriorityClass at 8
+_SetPriorityClass at 8
+_SetProcessAffinityMask at 8
+_SetProcessAffinityMask at 8
+_SetProcessPriorityBoost at 8
+_SetProcessPriorityBoost at 8
+_SetProcessShutdownParameters at 8
+_SetProcessShutdownParameters at 8
+_SetProcessWorkingSetSize at 12
+_SetProcessWorkingSetSize at 12
+_SetProcessWorkingSetSizeEx at 16
+_SetProcessWorkingSetSizeEx at 16
+_SetStdHandle at 8
+_SetStdHandle at 8
+_SetSystemFileCacheSize at 12
+_SetSystemFileCacheSize at 12
+_SetSystemPowerState at 8
+_SetSystemPowerState at 8
+_SetSystemTime at 4
+_SetSystemTime at 4
+_SetSystemTimeAdjustment at 8
+_SetSystemTimeAdjustment at 8
+_SetTapeParameters at 12
+_SetTapeParameters at 12
+_SetTapePosition at 24
+_SetTapePosition at 24
+_SetThreadAffinityMask at 8
+_SetThreadAffinityMask at 8
+_SetThreadContext at 8
+_SetThreadContext at 8
+_SetThreadExecutionState at 4
+_SetThreadExecutionState at 4
+_SetThreadIdealProcessor at 8
+_SetThreadIdealProcessor at 8
+_SetThreadLocale at 4
+_SetThreadLocale at 4
+_SetThreadPriority at 8
+_SetThreadPriority at 8
+_SetThreadPriorityBoost at 8
+_SetThreadPriorityBoost at 8
+_SetThreadStackGuarantee at 4
+_SetThreadStackGuarantee at 4
+_SetTimeZoneInformation at 4
+_SetTimeZoneInformation at 4
+_SetTimerQueueTimer at 24
+_SetTimerQueueTimer at 24
+_SetUnhandledExceptionFilter at 4
+_SetUnhandledExceptionFilter at 4
+_SetUserGeoID at 4
+_SetUserGeoID at 4
+_SetVolumeLabelA at 8
+_SetVolumeLabelA at 8
+_SetVolumeLabelW at 8
+_SetVolumeLabelW at 8
+_SetVolumeMountPointA at 8
+_SetVolumeMountPointA at 8
+_SetVolumeMountPointW at 8
+_SetVolumeMountPointW at 8
+_SetWaitableTimer at 24
+_SetWaitableTimer at 24
+_SetupComm at 12
+_SetupComm at 12
+_SignalObjectAndWait at 16
+_SignalObjectAndWait at 16
+_SizeofResource at 8
+_SizeofResource at 8
+_Sleep at 4
+_Sleep at 4
+_SleepEx at 8
+_SleepEx at 8
+_SuspendThread at 4
+_SuspendThread at 4
+_SwitchToFiber at 4
+_SwitchToFiber at 4
+_SwitchToThread at 0
+_SwitchToThread at 0
+_SystemTimeToFileTime at 8
+_SystemTimeToFileTime at 8
+_SystemTimeToTzSpecificLocalTime at 12
+_SystemTimeToTzSpecificLocalTime at 12
+_TerminateJobObject at 8
+_TerminateJobObject at 8
+_TerminateProcess at 8
+_TerminateProcess at 8
+_TerminateThread at 8
+_TerminateThread at 8
+_Thread32First at 8
+_Thread32First at 8
+_Thread32Next at 8
+_Thread32Next at 8
+_TlsAlloc at 0
+_TlsAlloc at 0
+_TlsFree at 4
+_TlsFree at 4
+_TlsGetValue at 4
+_TlsGetValue at 4
+_TlsSetValue at 8
+_TlsSetValue at 8
+_Toolhelp32ReadProcessMemory at 20
+_Toolhelp32ReadProcessMemory at 20
+_TransactNamedPipe at 28
+_TransactNamedPipe at 28
+_TransmitCommChar at 8
+_TransmitCommChar at 8
+_TryEnterCriticalSection at 4
+_TryEnterCriticalSection at 4
+_TzSpecificLocalTimeToSystemTime at 12
+_TzSpecificLocalTimeToSystemTime at 12
+_UnhandledExceptionFilter at 4
+_UnhandledExceptionFilter at 4
+_UnlockFile at 20
+_UnlockFile at 20
+_UnlockFileEx at 20
+_UnlockFileEx at 20
+_UnmapViewOfFile at 4
+_UnmapViewOfFile at 4
+_UnregisterWait at 4
+_UnregisterWait at 4
+_UnregisterWaitEx at 8
+_UnregisterWaitEx at 8
+_UpdateResourceA at 24
+_UpdateResourceA at 24
+_UpdateResourceW at 24
+_UpdateResourceW at 24
+_VerLanguageNameA at 12
+_VerLanguageNameA at 12
+_VerLanguageNameW at 12
+_VerLanguageNameW at 12
+_VerSetConditionMask at 16
+_VerSetConditionMask at 16
+_VerifyVersionInfoA at 16
+_VerifyVersionInfoA at 16
+_VerifyVersionInfoW at 16
+_VerifyVersionInfoW at 16
+_VirtualAlloc at 16
+_VirtualAlloc at 16
+_VirtualAllocEx at 20
+_VirtualAllocEx at 20
+_VirtualFree at 12
+_VirtualFree at 12
+_VirtualFreeEx at 16
+_VirtualFreeEx at 16
+_VirtualLock at 8
+_VirtualLock at 8
+_VirtualProtect at 16
+_VirtualProtect at 16
+_VirtualProtectEx at 20
+_VirtualProtectEx at 20
+_VirtualQuery at 12
+_VirtualQuery at 12
+_VirtualQueryEx at 16
+_VirtualQueryEx at 16
+_VirtualUnlock at 8
+_VirtualUnlock at 8
+_WTSGetActiveConsoleSessionId at 0
+_WTSGetActiveConsoleSessionId at 0
+_WaitCommEvent at 12
+_WaitCommEvent at 12
+_WaitForDebugEvent at 8
+_WaitForDebugEvent at 8
+_WaitForMultipleObjects at 16
+_WaitForMultipleObjects at 16
+_WaitForMultipleObjectsEx at 20
+_WaitForMultipleObjectsEx at 20
+_WaitForSingleObject at 8
+_WaitForSingleObject at 8
+_WaitForSingleObjectEx at 12
+_WaitForSingleObjectEx at 12
+_WaitNamedPipeA at 8
+_WaitNamedPipeA at 8
+_WaitNamedPipeW at 8
+_WaitNamedPipeW at 8
+_WideCharToMultiByte at 32
+_WideCharToMultiByte at 32
+_WinExec at 8
+_WinExec at 8
+_Wow64DisableWow64FsRedirection at 4
+_Wow64DisableWow64FsRedirection at 4
+_Wow64EnableWow64FsRedirection at 4
+_Wow64EnableWow64FsRedirection at 4
+_Wow64RevertWow64FsRedirection at 4
+_Wow64RevertWow64FsRedirection at 4
+_WriteConsoleA at 20
+_WriteConsoleA at 20
+_WriteConsoleInputA at 16
+_WriteConsoleInputA at 16
+_WriteConsoleInputW at 16
+_WriteConsoleInputW at 16
+_WriteConsoleOutputA at 20
+_WriteConsoleOutputA at 20
+_WriteConsoleOutputAttribute at 20
+_WriteConsoleOutputAttribute at 20
+_WriteConsoleOutputCharacterA at 20
+_WriteConsoleOutputCharacterA at 20
+_WriteConsoleOutputCharacterW at 20
+_WriteConsoleOutputCharacterW at 20
+_WriteConsoleOutputW at 20
+_WriteConsoleOutputW at 20
+_WriteConsoleW at 20
+_WriteConsoleW at 20
+_WriteFile at 20
+_WriteFile at 20
+_WriteFileEx at 20
+_WriteFileEx at 20
+_WriteFileGather at 20
+_WriteFileGather at 20
+_WritePrivateProfileSectionA at 12
+_WritePrivateProfileSectionA at 12
+_WritePrivateProfileSectionW at 12
+_WritePrivateProfileSectionW at 12
+_WritePrivateProfileStringA at 16
+_WritePrivateProfileStringA at 16
+_WritePrivateProfileStringW at 16
+_WritePrivateProfileStringW at 16
+_WritePrivateProfileStructA at 20
+_WritePrivateProfileStructA at 20
+_WritePrivateProfileStructW at 20
+_WritePrivateProfileStructW at 20
+_WriteProcessMemory at 20
+_WriteProcessMemory at 20
+_WriteProfileSectionA at 8
+_WriteProfileSectionA at 8
+_WriteProfileSectionW at 8
+_WriteProfileSectionW at 8
+_WriteProfileStringA at 12
+_WriteProfileStringA at 12
+_WriteProfileStringW at 12
+_WriteProfileStringW at 12
+_WriteTapemark at 16
+_WriteTapemark at 16
+_ZombifyActCtx at 4
+_ZombifyActCtx at 4
+__hread at 12
+__hread at 12
+__hwrite at 12
+__hwrite at 12
+__lclose at 4
+__lclose at 4
+__lcreat at 8
+__lcreat at 8
+__llseek at 12
+__llseek at 12
+__lopen at 8
+__lopen at 8
+__lread at 12
+__lread at 12
+__lwrite at 12
+__lwrite at 12
+_lstrcat at 8
+_lstrcat at 8
+_lstrcatA at 8
+_lstrcatA at 8
+_lstrcatW at 8
+_lstrcatW at 8
+_lstrcmp at 8
+_lstrcmp at 8
+_lstrcmpA at 8
+_lstrcmpA at 8
+_lstrcmpW at 8
+_lstrcmpW at 8
+_lstrcmpi at 8
+_lstrcmpi at 8
+_lstrcmpiA at 8
+_lstrcmpiA at 8
+_lstrcmpiW at 8
+_lstrcmpiW at 8
+_lstrcpy at 8
+_lstrcpy at 8
+_lstrcpyA at 8
+_lstrcpyA at 8
+_lstrcpyW at 8
+_lstrcpyW at 8
+_lstrcpyn at 12
+_lstrcpyn at 12
+_lstrcpynA at 12
+_lstrcpynA at 12
+_lstrcpynW at 12
+_lstrcpynW at 12
+_lstrlen at 4
+_lstrlen at 4
+_lstrlenA at 4
+_lstrlenA at 4
+_lstrlenW at 4
+_lstrlenW at 4
diff --git a/src/lib/kStuff/kProfiler2/kPrfReader.h b/src/lib/kStuff/kProfiler2/kPrfReader.h
new file mode 100644
index 0000000..0cb1683
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kPrfReader.h
@@ -0,0 +1,45 @@
+
+
+#include <string>
+
+typedef
+
+/**
+ * Debug info cache.
+ *
+ * An objects of this class acts a frontend to the low-level
+ * debug info readers.
+ */
+class kPrfDebugInfoCache
+{
+public:
+    kPrfDebugInfoCache(unsigned cMaxModules = ~0U);
+    ~kPrfDebugInfoCache();
+
+    /** Resolves a symbol in a specific module. */
+    int findSymbol();
+    int findLine();
+};
+
+/**
+ * Internal class which does the reader job behind the API / commandline tool.
+ */
+class kPrfReader
+{
+public:
+    kPrfReader(const char *pszDataSetPath);
+    ~kPrfReader();
+
+    /** Analyses the data set. */
+    int analyse(int fSomeOptionsIHaventFiguredOutYet);
+
+    /** Writes the analysis report as HTML. */
+    int reportAsHtml(FILE *pOut);
+
+    /** Dumps the data set in a raw fashion to the specified file stream. */
+    int dump(FILE *pOut);
+
+protected:
+    /** Pointer to the debug info cache object. */
+    kPrfDebugInfoCache *pDbgCache;
+};
diff --git a/src/lib/kStuff/kProfiler2/kProfileR3.cpp b/src/lib/kStuff/kProfiler2/kProfileR3.cpp
new file mode 100644
index 0000000..9e19ee6
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kProfileR3.cpp
@@ -0,0 +1,1666 @@
+/* $Id: kProfileR3.cpp 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kProfiler Mark 2 - The Ring-3 Implementation.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <k/kDefs.h>
+#if K_OS == K_OS_WINDOWS
+# include <windows.h>
+# include <psapi.h>
+# include <malloc.h>
+# if _MSC_VER >= 1400
+#  include <intrin.h>
+#  define HAVE_INTRIN
+# endif
+
+#elif K_OS == K_OS_LINUX || K_OS == K_OS_FREEBSD
+# define KPRF_USE_PTHREAD
+# include <pthread.h>
+# include <stdint.h>
+# define KPRF_USE_MMAN
+# include <sys/mman.h>
+# include <sys/fcntl.h>
+# include <unistd.h>
+# include <stdlib.h>
+# ifndef O_BINARY
+#  define O_BINARY 0
+# endif
+
+#elif K_OS == K_OS_OS2
+# define INCL_BASE
+# include <os2.h>
+# include <stdint.h>
+# include <sys/fmutex.h>
+
+#else
+# error "not ported to this OS..."
+#endif
+
+#include <k/kDefs.h>
+#include <k/kTypes.h>
+
+/*
+ * Instantiate the header.
+ */
+#define KPRF_NAME(Suffix)               KPrf##Suffix
+#define KPRF_TYPE(Prefix,Suffix)        Prefix##KPRF##Suffix
+#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
+# define KPRF_DECL_FUNC(type, name)     extern "C"  __declspec(dllexport) type __cdecl KPRF_NAME(name)
+#else
+# define KPRF_DECL_FUNC(type, name)     extern "C" type KPRF_NAME(name)
+#endif
+#if 1
+# ifdef __GNUC__
+#  define KPRF_ASSERT(expr) do { if (!(expr)) { __asm__ __volatile__("int3\n\tnop\n\t");} } while (0)
+# else
+#  define KPRF_ASSERT(expr) do { if (!(expr)) { __debugbreak(); } } while (0)
+# endif
+#else
+# define KPRF_ASSERT(expr) do { } while (0)
+#endif
+
+#include "prfcore.h.h"
+
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/** Mutex lock type. */
+#if defined(KPRF_USE_PTHREAD)
+typedef pthread_mutex_t     KPRF_TYPE(,MUTEX);
+#elif K_OS == K_OS_WINDOWS
+typedef CRITICAL_SECTION    KPRF_TYPE(,MUTEX);
+#elif K_OS == K_OS_OS2
+typedef struct _fmutex      KPRF_TYPE(,MUTEX);
+#endif
+/** Pointer to a mutex lock. */
+typedef KPRF_TYPE(,MUTEX)  *KPRF_TYPE(P,MUTEX);
+
+
+#if defined(KPRF_USE_PTHREAD)
+/** Read/Write lock type. */
+typedef pthread_rwlock_t    KPRF_TYPE(,RWLOCK);
+#elif K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
+/** Read/Write lock state. */
+typedef enum KPRF_TYPE(,RWLOCKSTATE)
+{
+    RWLOCK_STATE_UNINITIALIZED = 0,
+    RWLOCK_STATE_SHARED,
+    RWLOCK_STATE_LOCKING,
+    RWLOCK_STATE_EXCLUSIVE,
+    RWLOCK_STATE_32BIT_HACK = 0x7fffffff
+} KPRF_TYPE(,RWLOCKSTATE);
+/** Update the state. */
+#define KPRF_RWLOCK_SETSTATE(pRWLock, enmNewState) \
+    kPrfAtomicSet32((volatile KU32 *)&(pRWLock)->enmState, (KU32)(enmNewState))
+
+/** Read/Write lock type. */
+typedef struct KPRF_TYPE(,RWLOCK)
+{
+    /** This mutex serialize the access and updating of the members
+     * of this structure. */
+    KPRF_TYPE(,MUTEX)       Mutex;
+    /** The current number of readers. */
+    KU32                    cReaders;
+    /** The number of readers waiting. */
+    KU32                    cReadersWaiting;
+    /** The current number of waiting writers. */
+    KU32                    cWritersWaiting;
+# if K_OS == K_OS_WINDOWS
+    /** The handle of the event object on which the waiting readers block. (manual reset). */
+    HANDLE                  hevReaders;
+    /** The handle of the event object on which the waiting writers block. (manual reset). */
+    HANDLE                  hevWriters;
+# elif K_OS == K_OS_OS2
+    /** The handle of the event semaphore on which the waiting readers block. */
+    HEV                     hevReaders;
+    /** The handle of the event semaphore on which the waiting writers block. */
+    HEV                     hevWriters;
+# endif
+    /** The current state of the read-write lock. */
+    KPRF_TYPE(,RWLOCKSTATE) enmState;
+} KPRF_TYPE(,RWLOCK);
+#endif
+/** Pointer to a Read/Write lock. */
+typedef KPRF_TYPE(,RWLOCK) *KPRF_TYPE(P,RWLOCK);
+
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** The TLS index / key. */
+#if K_OS == K_OS_WINDOWS
+static DWORD                g_dwThreadTLS = TLS_OUT_OF_INDEXES;
+
+#elif defined(KPRF_USE_PTHREAD)
+static pthread_key_t        g_ThreadKey = (pthread_key_t)-1;
+
+#elif K_OS == K_OS_OS2
+static KPRF_TYPE(P,THREAD) *g_ppThread = NULL;
+
+#else
+# error "Not ported to your OS - or you're missing the OS define(s)."
+#endif
+
+/** Pointer to the profiler header. */
+static KPRF_TYPE(P,HDR)     g_pHdr = NULL;
+#define KPRF_GET_HDR()                  g_pHdr
+
+/** Whether the profiler is enabled or not. */
+static bool                 g_fEnabled = false;
+#define KPRF_IS_ACTIVE()                g_fEnabled
+
+
+/** The mutex protecting the threads in g_pHdr. */
+static KPRF_TYPE(,MUTEX)   g_ThreadsMutex;
+
+/** The mutex protecting the module segments in g_pHdr. */
+static KPRF_TYPE(,MUTEX)   g_ModSegsMutex;
+
+/** The read-write lock protecting the functions in g_pHdr. */
+static KPRF_TYPE(,RWLOCK)  g_FunctionsRWLock;
+
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static KPRF_TYPE(P,THREAD) kPrfGetThreadAutoReg(void);
+#ifdef KPRF_USE_PTHREAD
+static void kPrfPThreadKeyDtor(void *pvThread);
+#endif
+
+
+/**
+ * Gets the pointer to the profiler data for the current thread.
+ *
+ * This implementation automatically adds unknown threads.
+ *
+ * @returns Pointer to the profiler thread data.
+ * @returns NULL if we're out of thread space.
+ */
+static inline KPRF_TYPE(P,THREAD) kPrfGetThread(void)
+{
+    KPRF_TYPE(P,THREAD) pThread;
+
+/* Win32/64 */
+#if K_OS == K_OS_WINDOWS
+    pThread = (KPRF_TYPE(P,THREAD))TlsGetValue(g_dwThreadTLS);
+
+/* Posix Threads */
+#elif defined(KPRF_USE_PTHREAD)
+    pThread = (KPRF_TYPE(P,THREAD))pthread_getspecific(g_ThreadKey);
+
+#elif K_OS == K_OS_OS2
+    pThread = *g_ppThread;
+
+#else
+# error not implemented
+#endif
+    if (!pThread)
+        pThread = kPrfGetThreadAutoReg();
+    return pThread;
+}
+#define KPRF_GET_THREAD()               kPrfGetThread()
+
+
+/**
+ * The the ID of the current thread.
+ *
+ * @returns The thread id.
+ */
+static inline KUPTR kPrfGetThreadId(void)
+{
+/* Win32/64 */
+#if K_OS == K_OS_WINDOWS
+    KUPTR ThreadId = (KUPTR)GetCurrentThreadId();
+
+/* Posix Threads */
+#elif defined(KPRF_USE_PTHREAD)
+    KUPTR ThreadId = (KUPTR)pthread_self();
+
+#elif K_OS == K_OS_OS2
+    PTIB pTib;
+    PPIB pPib;
+    DosGetInfoBlocks(&pTib, &pPib);
+    ThreadId = pTib->tib_ptib2->tib2_ultid;
+
+#else
+# error not implemented
+#endif
+
+    return ThreadId;
+}
+#define KPRF_GET_THREADID()             kPrfGetThreadId()
+
+
+/**
+ * The the ID of the current process.
+ *
+ * @returns The process id.
+ */
+static inline KUPTR kPrfGetProcessId(void)
+{
+/* Win32/64 */
+#if K_OS == K_OS_WINDOWS
+    KUPTR ThreadId = (KUPTR)GetProcessId(GetCurrentProcess());
+
+#elif K_OS == K_OS_OS2
+    PTIB pTib;
+    PPIB pPib;
+    DosGetInfoBlocks(&pTib, &pPib);
+    ThreadId = pPib->pib_pid;
+
+#else
+    KUPTR ThreadId = (KUPTR)getpid();
+#endif
+
+    return ThreadId;
+}
+#define KPRF_GET_PROCESSID()            kPrfGetProcessId()
+
+
+/**
+ * Sets the pointer to the profiler data for the current thread.
+ *
+ * We require fast access to the profiler thread data, so we store
+ * it in a TLS (thread local storage) item/key where the implementation
+ * allows that.
+ *
+ * @param   pThread         The pointer to the profiler thread data for the current thread.
+ */
+static inline void kPrfSetThread(KPRF_TYPE(P,THREAD) pThread)
+{
+/* Win32/64 */
+#if K_OS == K_OS_WINDOWS
+    BOOL fRc = TlsSetValue(g_dwThreadTLS, pThread);
+
+/* Posix Threads */
+#elif defined(KPRF_USE_PTHREAD)
+    int rc = pthread_setspecific(g_ThreadKey, pThread);
+
+#elif K_OS == K_OS_OS2
+    *g_ppThread = pThread;
+
+#else
+# error not implemented
+#endif
+}
+#define KPRF_SET_THREAD(pThread)        kPrfSetThread(pThread)
+
+
+/**
+ * Get the now timestamp.
+ * This must correspond to what the assembly code are doing.
+ */
+static inline KU64 kPrfNow(void)
+{
+#if defined(HAVE_INTRIN)
+    return __rdtsc();
+# else
+    union
+    {
+        KU64 u64;
+        struct
+        {
+            KU32 u32Lo;
+            KU32 u32Hi;
+        } s;
+    } u;
+# if defined(__GNUC__)
+    __asm__ __volatile__ ("rdtsc\n\t" : "=a" (u.s.u32Lo), "=d" (u.s.u32Hi));
+# else
+    __asm
+    {
+        rdtsc
+        mov     [u.s.u32Lo], eax
+        mov     [u.s.u32Hi], edx
+    }
+
+# endif
+    return u.u64;
+#endif
+}
+#define KPRF_NOW()                      kPrfNow()
+
+
+/**
+ * Atomically set a 32-bit value.
+ */
+static inline void kPrfAtomicSet32(volatile KU32 *pu32, const KU32 u32)
+{
+#if defined(HAVE_INTRIN)
+    _InterlockedExchange((long volatile *)pu32, (const long)u32);
+
+#elif defined(__GNUC__)
+    __asm__ __volatile__("xchgl %0, %1\n\t"
+                         : "=m" (*pu32)
+                         : "r" (u32));
+
+#elif _MSC_VER
+    __asm
+    {
+        mov     edx, [pu32]
+        mov     eax, [u32]
+        xchg    [edx], eax
+    }
+
+#else
+    *pu32 = u32;
+#endif
+}
+#define KPRF_ATOMIC_SET32(a,b)          kPrfAtomicSet32(a, b)
+
+
+
+/**
+ * Atomically set a 64-bit value.
+ */
+static inline void kPrfAtomicSet64(volatile KU64 *pu64, KU64 u64)
+{
+#if defined(HAVE_INTRIN) && KPRF_BITS == 64
+    _InterlockedExchange64((KI64 *)pu64, (const KI64)u64);
+
+#elif defined(__GNUC__) && KPRF_BITS == 64
+    __asm__ __volatile__("xchgq %0, %1\n\t"
+                         : "=m" (*pu64)
+                         : "r" (u64));
+
+#elif defined(__GNUC__) && KPRF_BITS == 32
+    __asm__ __volatile__("1:\n\t"
+                         "lock; cmpxchg8b %1\n\t"
+                         "jnz 1b\n\t"
+                         : "=A" (u64),
+                           "=m" (*pu64)
+                         : "0" (*pu64),
+                           "b" ( (KU32)u64 ),
+                           "c" ( (KU32)(u64 >> 32) ));
+
+#elif _MSC_VER
+    __asm
+    {
+        mov     ebx, dword ptr [u64]
+        mov     ecx, dword ptr [u64 + 4]
+        mov     esi, pu64
+        mov     eax, dword ptr [esi]
+        mov     edx, dword ptr [esi + 4]
+    retry:
+        lock cmpxchg8b [esi]
+        jnz retry
+    }
+#else
+    *pu64 = u64;
+#endif
+}
+#define KPRF_ATOMIC_SET64(a,b)          kPrfAtomicSet64(a, b)
+
+
+/**
+ * Atomically add a 32-bit integer to another.
+ */
+static inline void kPrfAtomicAdd32(volatile KU32 *pu32, const KU32 u32)
+{
+#if defined(HAVE_INTRIN)
+    _InterlockedExchangeAdd((volatile long *)pu32, (const long)u32);
+
+#elif defined(__GNUC__)
+    __asm__ __volatile__("lock; addl %0, %1\n\t"
+                         : "=m" (*pu32)
+                         : "r" (u32));
+
+#elif _MSC_VER
+    __asm
+    {
+        mov     edx, [pu32]
+        mov     eax, dword ptr [u32]
+        lock add [edx], eax
+    }
+
+#else
+    *pu32 += u32;
+#endif
+}
+#define KPRF_ATOMIC_ADD32(a,b)          kPrfAtomicAdd32(a, b)
+#define KPRF_ATOMIC_INC32(a)            kPrfAtomicAdd32(a, 1);
+#define KPRF_ATOMIC_DEC32(a)            kPrfAtomicAdd32(a, (KU32)-1);
+
+
+/**
+ * Atomically add a 64-bit integer to another.
+ * Atomically isn't quite required, just a non-corruptive manner, assuming all updates are adds.
+ */
+static inline void kPrfAtomicAdd64(volatile KU64 *pu64, const KU64 u64)
+{
+#if defined(HAVE_INTRIN) && KPRF_BITS == 64
+    _InterlockedExchangeAdd64((volatile KI64 *)pu64, (const KI64)u64);
+
+#elif defined(__GNUC__) && KPRF_BITS == 64
+    __asm__ __volatile__("lock; addq %0, %1\n\t"
+                         : "=m" (*pu64)
+                         : "r" (u64));
+
+#elif defined(__GNUC__) && KPRF_BITS == 32
+    __asm__ __volatile__("lock; addl %0, %2\n\t"
+                         "lock; adcl %1, %3\n\t"
+                         : "=m" (*(volatile KU32 *)pu64),
+                           "=m" (*((volatile KU32 *)pu64 + 1))
+                         : "r" ((KU32)u64),
+                           "r" ((KU32)(u64 >> 32)));
+
+#elif _MSC_VER
+    __asm
+    {
+        mov     edx, [pu64]
+        mov     eax, dword ptr [u64]
+        mov     ecx, dword ptr [u64 + 4]
+        lock add [edx], eax
+        lock adc [edx + 4], ecx
+    }
+
+#else
+    *pu64 += u64;
+#endif
+}
+#define KPRF_ATOMIC_ADD64(a,b)          kPrfAtomicAdd64(a, b)
+#define KPRF_ATOMIC_INC64(a)            kPrfAtomicAdd64(a, 1);
+
+
+/**
+ * Initializes a mutex.
+ *
+ * @returns 0 on success.
+ * @returns -1 on failure.
+ * @param   pMutex      The mutex to init.
+ */
+static int kPrfMutexInit(KPRF_TYPE(P,MUTEX) pMutex)
+{
+#if defined(KPRF_USE_PTHREAD)
+    if (!pthread_mutex_init(pMutex, NULL));
+        return 0;
+    return -1;
+
+#elif K_OS == K_OS_WINDOWS
+    InitializeCriticalSection(pMutex);
+    return 0;
+
+#elif K_OS == K_OS_OS2
+    if (!_fmutex_create(pMutex, 0))
+        return 0;
+    return -1;
+#endif
+}
+
+/**
+ * Deletes a mutex.
+ *
+ * @param   pMutex      The mutex to delete.
+ */
+static void kPrfMutexDelete(KPRF_TYPE(P,MUTEX) pMutex)
+{
+#if defined(KPRF_USE_PTHREAD)
+    pthread_mutex_destroy(pMutex);
+
+#elif K_OS == K_OS_WINDOWS
+    DeleteCriticalSection(pMutex);
+
+#elif K_OS == K_OS_OS2
+    _fmutex_close(pMutex);
+#endif
+}
+
+/**
+ * Locks a mutex.
+ * @param   pMutex      The mutex lock.
+ */
+static inline void kPrfMutexAcquire(KPRF_TYPE(P,MUTEX) pMutex)
+{
+#if K_OS == K_OS_WINDOWS
+    EnterCriticalSection(pMutex);
+
+#elif defined(KPRF_USE_PTHREAD)
+    pthread_mutex_lock(pMutex);
+
+#elif K_OS == K_OS_OS2
+    fmutex_request(pMutex);
+#endif
+}
+
+
+/**
+ * Unlocks a mutex.
+ * @param   pMutex      The mutex lock.
+ */
+static inline void kPrfMutexRelease(KPRF_TYPE(P,MUTEX) pMutex)
+{
+#if K_OS == K_OS_WINDOWS
+    LeaveCriticalSection(pMutex);
+
+#elif defined(KPRF_USE_PTHREAD)
+    pthread_mutex_lock(pMutex);
+
+#elif K_OS == K_OS_OS2
+    fmutex_request(pMutex);
+#endif
+}
+
+
+#define KPRF_THREADS_LOCK()             kPrfMutexAcquire(&g_ThreadsMutex)
+#define KPRF_THREADS_UNLOCK()           kPrfMutexRelease(&g_ThreadsMutex)
+
+#define KPRF_MODSEGS_LOCK()             kPrfMutexAcquire(&g_ModSegsMutex)
+#define KPRF_MODSEGS_UNLOCK()           kPrfMutexRelease(&g_ModSegsMutex)
+
+
+/**
+ * Initializes a read-write lock.
+ *
+ * @returns 0 on success.
+ * @returns -1 on failure.
+ * @param   pRWLock     The read-write lock to initialize.
+ */
+static inline int kPrfRWLockInit(KPRF_TYPE(P,RWLOCK) pRWLock)
+{
+#if defined(KPRF_USE_PTHREAD)
+    if (!pthread_rwlock_init(pRWLock, NULL))
+        return 0;
+    return -1;
+
+#elif K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
+    if (kPrfMutexInit(&pRWLock->Mutex))
+        return -1;
+    pRWLock->cReaders = 0;
+    pRWLock->cReadersWaiting = 0;
+    pRWLock->cWritersWaiting = 0;
+    pRWLock->enmState = RWLOCK_STATE_SHARED;
+# if K_OS == K_OS_WINDOWS
+    pRWLock->hevReaders = CreateEvent(NULL, TRUE, TRUE, NULL);
+    pRWLock->hevWriters = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (    pRWLock->hevReaders != INVALID_HANDLE_VALUE
+        &&  pRWLock->hevWriters != INVALID_HANDLE_VALUE)
+        return 0;
+    CloseHandle(pRWLock->hevReaders);
+    CloseHandle(pRWLock->hevWriters);
+
+# elif K_OS == K_OS_OS2
+    APIRET rc = DosCreateEventSem(NULL, &pRWLock->hevReaders, 0, TRUE);
+    if (!rc)
+    {
+        rc = DosCreateEventSem(NULL, &pRWLock->hevWriters, 0, TRUE);
+        if (!rc)
+            return 0;
+        pRWLock->hevWriters = NULLHANDLE;
+        DosCloseEventSem(pRWLock->hevReaders);
+    }
+    pRWLock->hevReaders = NULLHANDLE;
+# endif
+
+    pRWLock->enmState = RWLOCK_STATE_UNINITIALIZED;
+    kPrfMutexDelete(&pRWLock->Mutex);
+    return -1;
+#endif
+}
+
+
+/**
+ * Deleters a read-write lock.
+ *
+ * @param   pRWLock     The read-write lock to delete.
+ */
+static inline void kPrfRWLockDelete(KPRF_TYPE(P,RWLOCK) pRWLock)
+{
+#if defined(KPRF_USE_PTHREAD)
+    pthread_rwlock_destroy(pRWLock);
+
+#elif K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
+    if (pRWLock->enmState == RWLOCK_STATE_UNINITIALIZED)
+        return;
+
+    pRWLock->enmState = RWLOCK_STATE_UNINITIALIZED;
+    kPrfMutexDelete(&pRWLock->Mutex);
+    pRWLock->cReaders = 0;
+    pRWLock->cReadersWaiting = 0;
+    pRWLock->cWritersWaiting = 0;
+# if K_OS == K_OS_WINDOWS
+    CloseHandle(pRWLock->hevReaders);
+    pRWLock->hevReaders = INVALID_HANDLE_VALUE;
+    CloseHandle(pRWLock->hevWriters);
+    pRWLock->hevWriters = INVALID_HANDLE_VALUE;
+
+# elif K_OS == K_OS_OS2
+    DosCloseEventSem(pRWLock->hevReaders);
+    pRWLock->hevReaders = NULLHANDLE;
+    DosCloseEventSem(pRWLock->hevWriters);
+    pRWLock->hevWriters = NULLHANDLE;
+# endif
+#endif
+}
+
+
+/**
+ * Acquires read access to the read-write lock.
+ * @param   pRWLock     The read-write lock.
+ */
+static inline void kPrfRWLockAcquireRead(KPRF_TYPE(P,RWLOCK) pRWLock)
+{
+#if defined(KPRF_USE_PTHREAD)
+    pthread_rwlock_rdlock(pRWLock);
+
+#elif K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
+    if (pRWLock->enmState == RWLOCK_STATE_UNINITIALIZED)
+        return;
+
+    kPrfMutexAcquire(&pRWLock->Mutex);
+    if (pRWLock->enmState == RWLOCK_STATE_SHARED)
+    {
+        KPRF_ATOMIC_INC32(&pRWLock->cReaders);
+        kPrfMutexRelease(&pRWLock->Mutex);
+        return;
+    }
+
+    for (;;)
+    {
+        /* have to wait */
+        KPRF_ATOMIC_INC32(&pRWLock->cReadersWaiting);
+# if K_OS == K_OS_WINDOWS
+        HANDLE hev = pRWLock->hevReaders;
+        ResetEvent(hev);
+
+# elif K_OS == K_OS_OS2
+        HEV    hev = pRWLock->hevReaders;
+        ULONG cIgnored;
+        DosResetEventSem(hev, &cIgnored);
+
+# endif
+        kPrfMutexRelease(&pRWLock->Mutex);
+
+# if K_OS == K_OS_WINDOWS
+        switch (WaitForSingleObject(hev, INFINITE))
+        {
+            case WAIT_IO_COMPLETION:
+            case WAIT_TIMEOUT:
+            case WAIT_OBJECT_0:
+                break;
+            case WAIT_ABANDONED:
+            default:
+                return;
+        }
+
+# elif K_OS == K_OS_OS2
+        switch (DosWaitEventSem(hev, SEM_INDEFINITE_WAIT))
+        {
+            case NO_ERROR:
+            case ERROR_SEM_TIMEOUT:
+            case ERROR_TIMEOUT:
+            case ERROR_INTERRUPT:
+                break;
+            default:
+                return;
+        }
+# endif
+
+        kPrfMutexAcquire(&pRWLock->Mutex);
+        if (pRWLock->enmState == RWLOCK_STATE_SHARED)
+        {
+            KPRF_ATOMIC_INC32(&pRWLock->cReaders);
+            KPRF_ATOMIC_DEC32(&pRWLock->cReadersWaiting);
+            kPrfMutexRelease(&pRWLock->Mutex);
+            return;
+        }
+    }
+#endif
+}
+
+
+/**
+ * Releases read access to the read-write lock.
+ * @param   pRWLock     The read-write lock.
+ */
+static inline void kPrfRWLockReleaseRead(KPRF_TYPE(P,RWLOCK) pRWLock)
+{
+#if defined(KPRF_USE_PTHREAD)
+    pthread_rwlock_unlock(pRWLock);
+
+#elif K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
+    if (pRWLock->enmState == RWLOCK_STATE_UNINITIALIZED)
+        return;
+
+    /*
+     * If we're still in the shared state, or if there
+     * are more readers out there, or if there are no
+     * waiting writers, all we have to do is decrement an leave.
+     *
+     * That's the most frequent, thing and should be fast.
+     */
+    kPrfMutexAcquire(&pRWLock->Mutex);
+    KPRF_ATOMIC_DEC32(&pRWLock->cReaders);
+    if (    pRWLock->enmState == RWLOCK_STATE_SHARED
+        ||  pRWLock->cReaders
+        ||  !pRWLock->cWritersWaiting)
+    {
+        kPrfMutexRelease(&pRWLock->Mutex);
+        return;
+    }
+
+    /*
+     * Wake up one (or more on OS/2) waiting writers.
+     */
+# if K_OS == K_OS_WINDOWS
+    SetEvent(pRWLock->hevWriters);
+# elif K_OS == K_OS_OS2
+    DosPostEvent(pRWLock->hevwriters);
+# endif
+    kPrfMutexRelease(&pRWLock->Mutex);
+
+#endif
+}
+
+
+/**
+ * Acquires write access to the read-write lock.
+ * @param   pRWLock     The read-write lock.
+ */
+static inline void kPrfRWLockAcquireWrite(KPRF_TYPE(P,RWLOCK) pRWLock)
+{
+#if defined(KPRF_USE_PTHREAD)
+    pthread_rwlock_wrlock(pRWLock);
+
+#elif K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
+    if (pRWLock->enmState == RWLOCK_STATE_UNINITIALIZED)
+        return;
+
+    kPrfMutexAcquire(&pRWLock->Mutex);
+    if (    !pRWLock->cReaders
+        &&  (   pRWLock->enmState == RWLOCK_STATE_SHARED
+             || pRWLock->enmState == RWLOCK_STATE_LOCKING)
+        )
+    {
+        KPRF_RWLOCK_SETSTATE(pRWLock, RWLOCK_STATE_EXCLUSIVE);
+        kPrfMutexRelease(&pRWLock->Mutex);
+        return;
+    }
+
+    /*
+     * We'll have to wait.
+     */
+    if (pRWLock->enmState == RWLOCK_STATE_SHARED)
+        KPRF_RWLOCK_SETSTATE(pRWLock, RWLOCK_STATE_LOCKING);
+    KPRF_ATOMIC_INC32(&pRWLock->cWritersWaiting);
+    for (;;)
+    {
+# if K_OS == K_OS_WINDOWS
+        HANDLE hev = pRWLock->hevWriters;
+# elif K_OS == K_OS_OS2
+        HEV    hev = pRWLock->hevWriters;
+# endif
+        kPrfMutexRelease(&pRWLock->Mutex);
+# if K_OS == K_OS_WINDOWS
+        switch (WaitForSingleObject(hev, INFINITE))
+        {
+            case WAIT_IO_COMPLETION:
+            case WAIT_TIMEOUT:
+            case WAIT_OBJECT_0:
+                break;
+            case WAIT_ABANDONED:
+            default:
+                KPRF_ATOMIC_DEC32(&pRWLock->cWritersWaiting);
+                return;
+        }
+
+# elif K_OS == K_OS_OS2
+        switch (DosWaitEventSem(hev, SEM_INDEFINITE_WAIT))
+        {
+            case NO_ERROR:
+            case ERROR_SEM_TIMEOUT:
+            case ERROR_TIMEOUT:
+            case ERROR_INTERRUPT:
+                break;
+            default:
+                KPRF_ATOMIC_DEC32(&pRWLock->cWritersWaiting);
+                return;
+        }
+        ULONG cIgnored;
+        DosResetEventSem(hev, &cIgnored);
+# endif
+
+        /*
+         * Try acquire the lock.
+         */
+        kPrfMutexAcquire(&pRWLock->Mutex);
+        if (    !pRWLock->cReaders
+            &&  (   pRWLock->enmState == RWLOCK_STATE_SHARED
+                 || pRWLock->enmState == RWLOCK_STATE_LOCKING)
+            )
+        {
+            KPRF_RWLOCK_SETSTATE(pRWLock, RWLOCK_STATE_EXCLUSIVE);
+            KPRF_ATOMIC_DEC32(&pRWLock->cWritersWaiting);
+            kPrfMutexRelease(&pRWLock->Mutex);
+            return;
+        }
+    }
+#endif
+}
+
+
+/**
+ * Releases write access to the read-write lock.
+ * @param   pRWLock     The read-write lock.
+ */
+static inline void kPrfRWLockReleaseWrite(KPRF_TYPE(P,RWLOCK) pRWLock)
+{
+#if defined(KPRF_USE_PTHREAD)
+    pthread_rwlock_unlock(pRWLock);
+
+#elif K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
+    if (pRWLock->enmState == RWLOCK_STATE_UNINITIALIZED)
+        return;
+
+    /*
+     * The common thing is that there are noone waiting.
+     * But, before that usual paranoia.
+     */
+    kPrfMutexAcquire(&pRWLock->Mutex);
+    if (pRWLock->enmState != RWLOCK_STATE_EXCLUSIVE)
+    {
+        kPrfMutexRelease(&pRWLock->Mutex);
+        return;
+    }
+    if (    !pRWLock->cReadersWaiting
+        &&  !pRWLock->cWritersWaiting)
+    {
+        KPRF_RWLOCK_SETSTATE(pRWLock, RWLOCK_STATE_SHARED);
+        kPrfMutexRelease(&pRWLock->Mutex);
+        return;
+    }
+
+    /*
+     * Someone is waiting, wake them up as we change the state.
+     */
+# if K_OS == K_OS_WINDOWS
+    HANDLE hev = INVALID_HANDLE_VALUE;
+# elif K_OS == K_OS_OS2
+    HEV    hev = NULLHANDLE;
+# endif
+
+    if (pRWLock->cWritersWaiting)
+    {
+        KPRF_RWLOCK_SETSTATE(pRWLock, RWLOCK_STATE_LOCKING);
+        hev = pRWLock->hevWriters;
+    }
+    else
+    {
+        KPRF_RWLOCK_SETSTATE(pRWLock, RWLOCK_STATE_SHARED);
+        hev = pRWLock->hevReaders;
+    }
+# if K_OS == K_OS_WINDOWS
+    SetEvent(hev);
+# elif K_OS == K_OS_OS2
+    DosPostEvent(pRWLock->hevwriters);
+# endif
+    kPrfMutexRelease(&pRWLock->Mutex);
+
+#endif
+}
+
+#define KPRF_FUNCS_WRITE_LOCK()         kPrfRWLockAcquireWrite(&g_FunctionsRWLock)
+#define KPRF_FUNCS_WRITE_UNLOCK()       kPrfRWLockReleaseWrite(&g_FunctionsRWLock)
+#define KPRF_FUNCS_READ_LOCK()          kPrfRWLockAcquireRead(&g_FunctionsRWLock)
+#define KPRF_FUNCS_READ_UNLOCK()        kPrfRWLockReleaseRead(&g_FunctionsRWLock)
+
+
+
+
+/**
+ * Finds the module segment which the address belongs to.
+ *
+ */
+static int kPrfGetModSeg(KPRF_TYPE(,UPTR) uAddress, char *pszPath, KU32 cchPath, KU32 *piSegment,
+                         KPRF_TYPE(P,UPTR) puBasePtr, KPRF_TYPE(P,UPTR) pcbSegmentMinusOne)
+{
+#if K_OS == K_OS_WINDOWS
+    /*
+     * Enumerate the module handles.
+     */
+    HANDLE      hProcess = GetCurrentProcess();
+    DWORD       cbNeeded = 0;
+    HMODULE     hModIgnored;
+    if (    !EnumProcessModules(hProcess, &hModIgnored, sizeof(hModIgnored), &cbNeeded)
+        &&  GetLastError() != ERROR_BUFFER_OVERFLOW) /** figure out what this actually returns */
+        cbNeeded = 256 * sizeof(HMODULE);
+
+    cbNeeded += sizeof(HMODULE) * 32;
+    HMODULE *pahModules = (HMODULE *)alloca(cbNeeded);
+    if (EnumProcessModules(hProcess, pahModules, cbNeeded, &cbNeeded))
+    {
+        const unsigned cModules = cbNeeded / sizeof(HMODULE);
+        for (unsigned i = 0; i < cModules; i++)
+        {
+            __try
+            {
+                const KUPTR uImageBase = (KUPTR)pahModules[i];
+                union
+                {
+                    KU8                *pu8;
+                    PIMAGE_DOS_HEADER   pDos;
+                    PIMAGE_NT_HEADERS   pNt;
+                    PIMAGE_NT_HEADERS32 pNt32;
+                    PIMAGE_NT_HEADERS64 pNt64;
+                    KUPTR               u;
+                } u;
+                u.u = uImageBase;
+
+                /* reject modules higher than the address. */
+                if (uAddress < u.u)
+                    continue;
+
+                /* Skip past the MZ header */
+                if (u.pDos->e_magic == IMAGE_DOS_SIGNATURE)
+                    u.pu8 += u.pDos->e_lfanew;
+
+                /* Ignore anything which isn't an NT header. */
+                if (u.pNt->Signature != IMAGE_NT_SIGNATURE)
+                    continue;
+
+                /* Extract necessary info from the optional header (comes in 32-bit and 64-bit variations, we simplify a bit). */
+                KU32                    cbImage;
+                PIMAGE_SECTION_HEADER   paSHs;
+                if (u.pNt->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32))
+                {
+                    paSHs = (PIMAGE_SECTION_HEADER)(u.pNt32 + 1);
+                    cbImage = u.pNt32->OptionalHeader.SizeOfImage;
+                }
+                else if (u.pNt->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER64))
+                {
+                    paSHs = (PIMAGE_SECTION_HEADER)(u.pNt64 + 1);
+                    cbImage = u.pNt64->OptionalHeader.SizeOfImage;
+                }
+                else
+                    continue;
+
+                /* Is our address within the image size */
+                KUPTR uRVA = uAddress - (KUPTR)pahModules[i];
+                if (uRVA >= cbImage)
+                    continue;
+
+                /*
+                 * Iterate the section headers and figure which section we're in.
+                 * (segment == section + 1)
+                 */
+                const KU32 cSHs = u.pNt->FileHeader.NumberOfSections;
+                if (uRVA < paSHs[0].VirtualAddress)
+                {
+                    /* the implicit header section */
+                    *puBasePtr          = uImageBase;
+                    *pcbSegmentMinusOne = paSHs[0].VirtualAddress - 1;
+                    *piSegment          = 0;
+                }
+                else
+                {
+                    KU32 iSH = 0;
+                    for (;;)
+                    {
+                        if (iSH >= cSHs)
+                        {
+                            /* this shouldn't happen, but in case it does simply deal with it. */
+                            *puBasePtr          = paSHs[iSH - 1].VirtualAddress + paSHs[iSH - 1].Misc.VirtualSize + uImageBase;
+                            *pcbSegmentMinusOne = cbImage - *puBasePtr;
+                            *piSegment          = iSH + 1;
+                            break;
+                        }
+                        if (uRVA - paSHs[iSH].VirtualAddress < paSHs[iSH].Misc.VirtualSize)
+                        {
+                            *puBasePtr          = paSHs[iSH].VirtualAddress + uImageBase;
+                            *pcbSegmentMinusOne = paSHs[iSH].Misc.VirtualSize;
+                            *piSegment          = iSH + 1;
+                            break;
+                        }
+                        iSH++;
+                    }
+                }
+
+                /*
+                 * Finally, get the module name.
+                 * There are multiple ways, try them all before giving up.
+                 */
+                if (    !GetModuleFileNameEx(hProcess, pahModules[i], pszPath, cchPath)
+                    &&  !GetModuleFileName(pahModules[i], pszPath, cchPath)
+                    &&  !GetMappedFileName(hProcess, (PVOID)uAddress, pszPath, cchPath)
+                    &&  !GetModuleBaseName(hProcess, pahModules[i], pszPath, cchPath))
+                    *pszPath = '\0';
+                return 0;
+            }
+            __except (EXCEPTION_EXECUTE_HANDLER)
+            {
+            }
+        }
+    }
+
+#elif K_OS == K_OS_OS2
+    /*
+     * Just ask the loader.
+     */
+    ULONG   offObj = 0;
+    ULONG   iObj = 0;
+    HMODULE hmod = NULLHANDLE;
+    APIRET rc = DosQueryModFromEIP(&hmod, &iObj, cchPath, pszPath, &offObj, uAddress);
+    if (!rc)
+    {
+        *piSegment = iObj;
+        *puBasePtr = uAddress - offObj;
+        *pcbSegmentMinusOne = KPRF_ALIGN(offObj, 0x1000) - 1; /* minimum size */
+
+        /*
+         * Query the page attributes starting at the current page. The query will not enter
+         * into the next object since PAG_BASE is requested.
+         */
+        ULONG cb     = ~0UL;
+        ULONG fFlags = ~0UL;
+        uAddress &= ~(KUPTR)0xfff;
+        rc = DosQueryMem((PVOID)(uAddress, &cb, &fFlags);
+        if (!rc)
+        {
+            *pcbSegmentMinusOne = (offObj & ~(KUPTR)0xfff) + KPRF_ALIGN(cb, 0x1000) - 1;
+            if ((fFlags & PAG_BASE) && cb <= 0x1000) /* don't quite remember if PAG_BASE returns one page or not */
+            {
+                cb = ~0UL;
+                fFlags = ~0UL;
+                rc = DosQueryMem((PVOID)(uAddress + 0x1000), &cb, &fFlags);
+                if (!rc & !(fFlags & (PAG_BASE | PAG_FREE)))
+                    *pcbSegmentMinusOne += KPRF_ALIGN(cb, 0x1000);
+            }
+        }
+        return 0;
+    }
+
+#endif
+    /* The common fallback */
+    *pszPath = '\0';
+    *piSegment = 0;
+    *puBasePtr = 0;
+    *pcbSegmentMinusOne = ~(KPRF_TYPE(,UPTR))0;
+    return -1;
+}
+#define KPRF_GET_MODSEG(uAddress, pszPath, cchPath, piSegment, puBasePtr, pcbSegmentMinusOne) \
+                                        kPrfGetModSeg(uAddress, pszPath, cchPath, piSegment, puBasePtr, pcbSegmentMinusOne)
+
+
+
+
+/*
+ * Instantiate the implementation
+ */
+#include "prfcorepre.cpp.h"
+
+#include "prfcoremodseg.cpp.h"
+#include "prfcorefunction.cpp.h"
+#include "prfcore.cpp.h"
+#include "prfcoreinit.cpp.h"
+#include "prfcoreterm.cpp.h"
+
+#include "prfcorepost.cpp.h"
+
+
+
+
+
+/**
+ * Registers an unknown thread.
+ *
+ * @returns Pointer to the registered thread.
+ */
+static KPRF_TYPE(P,THREAD) kPrfGetThreadAutoReg(void)
+{
+    KUPTR uStackBasePtr;
+
+#if 0
+    /** @todo I'm sure Win32 has a way of obtaining the top and bottom of the stack, OS/2 did...
+     * Some limit stuff in posix / ansi also comes to mind... */
+
+#elif K_OS == K_OS_OS2
+    PTIB pTib;
+    PPIB pPib;
+    DosGetInfoBlocks(&pTib, &pPib); /* never fails except if you give it bad input, thus 'Get' not 'Query'. */
+    /* I never recall which of these is the right one... */
+    uStackBasePtr = (KUPTR)pTib->tib_pstack < (KUPTR)pTib->tib_pstack_limit
+        ? (KUPTR)pTib->tib_pstack
+        : (KUPTR)pTib->tib_pstack_limit;
+
+#else
+    /* the default is top of the current stack page (assuming a page to be 4KB) */
+    uStackBasePtr = (KUPTR)&uStackBasePtr;
+    uStackBasePtr = (uStackBasePtr + 0xfff) & ~(KUPTR)0xfff;
+#endif
+
+    return KPRF_NAME(RegisterThread)(uStackBasePtr, "");
+}
+
+
+/**
+ * Get a env.var. variable.
+ *
+ * @returns pszValue.
+ * @param   pszVar      The variable name.
+ * @param   pszValue    Where to store the value.
+ * @param   cchValue    The size of the value buffer.
+ * @param   pszDefault  The default value.
+ */
+static char *kPrfGetEnvString(const char *pszVar, char *pszValue, KU32 cchValue, const char *pszDefault)
+{
+#if K_OS == K_OS_WINDOWS
+    if (GetEnvironmentVariable(pszVar, pszValue, cchValue))
+        return pszValue;
+
+#elif K_OS == K_OS_OS2
+    PSZ pszValue;
+    if (    !DosScanEnv((PCSZ)pszVar, &pszValue)
+        &&  !*pszValue)
+        pszDefault = pszValue;
+
+#else
+    const char *pszTmp = getenv(pszVar);
+    if (pszTmp)
+        pszDefault = pszTmp;
+
+#endif
+
+    /*
+     * Copy the result into the buffer.
+     */
+    char *psz = pszValue;
+    while (*pszDefault && cchValue-- > 1)
+        *psz++ = *pszDefault++;
+    *psz = '\0';
+
+    return pszValue;
+}
+
+
+/**
+ * The the value of an env.var.
+ *
+ * @returns The value of the env.var.
+ * @returns The default if the value was not found.
+ * @param   pszVar      The variable name.
+ * @param   uDefault    The default value.
+ */
+static KU32 kPrfGetEnvValue(const char *pszVar, KU32 uDefault)
+{
+#if K_OS == K_OS_WINDOWS
+    char szBuf[128];
+    const char *pszValue = szBuf;
+    if (!GetEnvironmentVariable(pszVar, szBuf, sizeof(szBuf)))
+        pszValue = NULL;
+
+#elif K_OS == K_OS_OS2
+    PSZ pszValue;
+    if (DosScanEnv((PCSZ)pszVar, &pszValue))
+        pszValue = NULL;
+
+#else
+    const char *pszValue = getenv(pszVar);
+
+#endif
+
+    /*
+     * Discard the obvious stuff.
+     */
+    if (!pszValue)
+        return uDefault;
+    while (*pszValue == ' ' || *pszValue == '\t')
+        pszValue++;
+    if (!*pszValue)
+        return uDefault;
+
+    /*
+     * Interpret the value.
+     */
+    unsigned    uBase = 10;
+    KU32        uValue = 0;
+    const char *psz = pszValue;
+
+    /* prefix - only hex */
+    if (*psz == '0' && (psz[1] == 'x' || psz[1] == 'X'))
+    {
+        uBase = 16;
+        psz += 2;
+    }
+
+    /* read the value */
+    while (*psz)
+    {
+        unsigned char ch = (unsigned char)*psz;
+        if (ch >= '0' && ch <= '9')
+            ch -= '0';
+        else if (   uBase > 10
+                 && ch >= 'a' && ch <= 'f')
+            ch -= 'a' + 10;
+        else if (   uBase > 10
+                 && ch >= 'a' && ch <= 'F')
+            ch -= 'a' + 10;
+        else
+            break;
+        uValue *= uBase;
+        uValue += ch;
+        psz++;
+    }
+
+    /* postfixes */
+    switch (*psz)
+    {
+        case 'm':
+        case 'M':
+            uValue *= 1024*1024;
+            break;
+
+        case 'k':
+        case 'K':
+            uValue *= 1024;
+            break;
+    }
+
+    /*
+     * If the value is still 0, we return the default.
+     */
+    return uValue ? uValue : uDefault;
+}
+
+
+/**
+ * Allocates memory.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ * @param   cb      The amount of memory (in bytes) to allocate.
+ */
+static void *kPrfAllocMem(KU32 cb)
+{
+#if K_OS == K_OS_WINDOWS
+    void *pv = VirtualAlloc(NULL, cb, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+
+#elif defined(KPRF_USE_MMAN)
+    void *pv = mmap(NULL, cb, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+#elif K_OS == K_OS_OS2
+    void *pv;
+# ifdef INCL_DOSEXAPIS
+    if (DosAllocMemEx(&pv, cb, PAG_READ | PAG_WRITE | PAG_EXECUTE | PAG_COMMIT | OBJ_FORK))s
+# else
+    if (DosAllocMem(&pv, cb, PAG_READ | PAG_WRITE | PAG_EXECUTE | PAG_COMMIT))
+# endif
+        pvBuf = NULL;
+
+#else
+# error not implemented
+#endif
+    return pv;
+}
+
+
+/**
+ * Frees memory.
+ *
+ * @param   pv      The memory to free.
+ */
+static void kPrfFreeMem(void *pv)
+{
+#if K_OS == K_OS_WINDOWS
+    VirtualFree(pv, 0, MEM_RELEASE);
+
+#elif defined(KPRF_USE_MMAN)
+    munmap(pv, 0); /** @todo check if 0 is allowed here.. */
+
+#elif K_OS == K_OS_OS2
+# ifdef INCL_DOSEXAPIS
+    DosFreeMemEx(&pv);
+# else
+    DosFreeMem(&pv);
+# endif
+
+#else
+# error not implemented
+#endif
+}
+
+
+/**
+ * Writes a data buffer to a new file.
+ *
+ * Any existing file will be overwritten.
+ *
+ *
+ * @returns 0 on success.
+ * @returns -1 on failure.
+ *
+ * @param   pszName     The name of the file.
+ * @param   pvData      The data to write.
+ * @param   cbData      The amount of data to write.
+ */
+static int kPrfWriteFile(const char *pszName, const void *pvData, KU32 cbData)
+{
+#if K_OS == K_OS_WINDOWS
+    int rc = -1;
+    HANDLE hFile = CreateFile(pszName,GENERIC_WRITE, FILE_SHARE_READ, NULL,
+                              CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE);
+    if (hFile != INVALID_HANDLE_VALUE)
+    {
+        DWORD dwWritten;
+        if (    WriteFile(hFile, pvData, cbData, &dwWritten, NULL)
+            &&  dwWritten == cbData)
+            rc = 0;
+        CloseHandle(hFile);
+    }
+    return rc;
+
+#elif K_OS == K_OS_OS2
+    HFILE hFile;
+    ULONG ulAction = 0;
+    APIRET rc = DosOpen(pszName, &hFile, &ulAction, cbData, FILE_NORMAL,
+                        OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW,
+                        OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYWRITE | OPEN_FLAGS_NOINHERIT | OPEN_FLAGS_SEQUENTIAL,
+                        NULL);
+    if (!rc)
+    {
+        ULONG cbWritten;
+        rc = DosWrite(hFile, pvData, cbData, &cbWritten);
+        if (!rc && cbWritten != cbData)
+            rc = -1;
+        DosClose(hFile);
+    }
+    return rc ? -1 : 0;
+
+#else
+    int rc = -1;
+    int fd = open(pszName, O_WRONLY | O_CREAT | O_BINARY | O_TRUNC, 0666);
+    if (fd >= 0)
+    {
+        if (write(fd, pvData, cbData) == cbData)
+            rc = 0;
+        close(fd);
+    }
+    return rc;
+
+#endif
+}
+
+
+
+/**
+ * Initializes and start the profiling.
+ *
+ * This should typically be called from some kind of module init
+ * function, so we can start profiling upon/before entering main().
+ *
+ * @returns 0 on success
+ * @returns -1 on failure.
+ *
+ */
+int kPrfInitialize(void)
+{
+    /*
+     * Only initialize once.
+     */
+    if (KPRF_GET_HDR())
+        return 0;
+
+    /*
+     * Initial suggestions.
+     */
+    KU32    cbModSegs  = kPrfGetEnvValue("KPRF2_CBMODSEGS",  128*1024);
+    KU32    cFunctions = kPrfGetEnvValue("KPRF2_CFUNCTIONS", 8192);
+    KU32    cThreads   = kPrfGetEnvValue("KPRF2_CTHREADS",   256);
+    KU32    cStacks    = kPrfGetEnvValue("KPRF2_CSTACKS",    48);
+    KU32    cFrames    = kPrfGetEnvValue("KPRF2_CFRAMES",    448);
+    KU32    fAffinity  = kPrfGetEnvValue("KPRF2_AFFINITY",   0);
+
+    KU32    cb = KPRF_NAME(CalcSize)(cFunctions, cbModSegs, cThreads, cStacks, cFrames);
+
+    /*
+     * Allocate and initialize the data set.
+     */
+    void *pvBuf = kPrfAllocMem(cb);
+    if (!pvBuf)
+        return -1;
+
+    KPRF_TYPE(P,HDR) pHdr = KPRF_NAME(Init)(pvBuf, cb, cFunctions, cbModSegs, cThreads, cStacks, cFrames);
+    if (pHdr)
+    {
+        /*
+         * Initialize semaphores.
+         */
+        if (!kPrfMutexInit(&g_ThreadsMutex))
+        {
+            if (!kPrfMutexInit(&g_ModSegsMutex))
+            {
+                if (!kPrfRWLockInit(&g_FunctionsRWLock))
+                {
+                    /*
+                     * Allocate the TLS entry.
+                     */
+#if K_OS == K_OS_WINDOWS
+                    g_dwThreadTLS = TlsAlloc();
+                    if (g_dwThreadTLS != TLS_OUT_OF_INDEXES)
+
+#elif defined(KPRF_USE_PTHREAD)
+                    int rc = pthread_key_create(&g_ThreadKey, kPrfPThreadKeyDtor);
+                    if (!rc)
+
+#elif K_OS == K_OS_OS2
+                    int rc = DosAllocThreadLocalMemory(sizeof(void *), (PULONG*)&g_ppThread); /** @todo check if this is a count or a size. */
+                    if (!rc)
+
+#endif
+                    {
+                        /*
+                         * Apply the affinity mask, if specified.
+                         */
+                        if (fAffinity)
+                        {
+#if K_OS == K_OS_WINDOWS
+                            SetProcessAffinityMask(GetCurrentProcess(), fAffinity);
+#endif
+                        }
+
+                        g_pHdr = pHdr;
+                        g_fEnabled = true;
+                        return 0;
+                    }
+                    kPrfRWLockDelete(&g_FunctionsRWLock);
+                }
+                kPrfMutexDelete(&g_ModSegsMutex);
+            }
+            kPrfMutexDelete(&g_ThreadsMutex);
+        }
+    }
+    kPrfFreeMem(pvBuf);
+    return -1;
+}
+
+
+/**
+ * Stops, dumps, and terminates the profiling.
+ *
+ * This should typically be called from some kind of module destruction
+ * function, so we can profile parts of the termination sequence too.
+ *
+ * @returns 0 on success
+ * @returns -1 on failure.
+ *
+ */
+int kPrfTerminate(void)
+{
+    /*
+     * Stop the profiling.
+     * As a safety precaution, sleep a little bit to allow threads
+     * still at large inside profiler code some time to get out.
+     */
+    g_fEnabled = false;
+    KPRF_TYPE(P,HDR) pHdr = g_pHdr;
+    g_pHdr = NULL;
+    if (!pHdr)
+        return -1;
+
+#if K_OS == K_OS_WINDOWS
+    Sleep(10);
+#elif K_OS == K_OS_OS2
+    DosSleep(10);
+#else
+    usleep(10000);
+#endif
+
+    /*
+     * Unwind all active threads and so forth.
+     */
+    KPRF_NAME(TerminateAll)(pHdr);
+
+    /*
+     * Use the stack space to fill in process details.
+     */
+#if K_OS == K_OS_WINDOWS
+    /* all is one single string */
+    const char *pszCommandLine = GetCommandLine();
+    if (pszCommandLine)
+        KPRF_NAME(SetCommandLine)(pHdr, 1, &pszCommandLine);
+
+#elif K_OS == K_OS_OS2 || K_OS == K_OS_OS2
+    PTIB pTib;
+    PPIB pPib;
+    DosGetInfoBlocks(&pTib, &pPib);
+    if (pPib->pib_pchcmd)
+    {
+        /* Tradition say that the commandline is made up of two zero terminate strings
+         * - first the executable name, then the arguments. Similar to what unix does,
+         *   only completely mocked up because of the CMD.EXE tradition.
+         */
+        const char *apszArgs[2];
+        apszArgs[0] = pPib->pib_pchcmd;
+        apszArgs[1] = pPib->pib_pchcmd;
+        while (apszArgs[1][0])
+            apszArgs[1]++;
+        apszArgs[1]++;
+        KPRF_NAME(SetCommandLine)(pHdr, 2, apszArgs);
+    }
+
+#else
+    /* linux can read /proc/self/something I guess. Don't know about the rest... */
+
+#endif
+
+    /*
+     * Write the file to disk.
+     */
+    char szName[260 + 16];
+    kPrfGetEnvString("KPRF2_FILE", szName, sizeof(szName) - 16, "kPrf2-");
+
+    /* append the process id */
+    KUPTR pid = kPrfGetProcessId();
+    char *psz = szName;
+    while (*psz)
+        psz++;
+
+    static char s_szDigits[0x11] = "0123456789abcdef";
+    KU32 uShift = KPRF_BITS - 4;
+    while (     uShift > 0
+           &&   !(pid & (0xf << uShift)))
+        uShift -= 4;
+    *psz++ = s_szDigits[(pid >> uShift) & 0xf];
+     while (uShift > 0)
+     {
+         uShift -= 4;
+         *psz++ = s_szDigits[(pid >> uShift) & 0xf];
+     }
+
+    /* .kPrf2 */
+    *psz++ = '.';
+    *psz++ = 'k';
+    *psz++ = 'P';
+    *psz++ = 'r';
+    *psz++ = 'f';
+    *psz++ = '2';
+    *psz++ = '\0';
+
+    /* write the file. */
+    int rc = kPrfWriteFile(szName, pHdr, pHdr->cb);
+
+    /*
+     * Free resources.
+     */
+    kPrfFreeMem(pHdr);
+#if K_OS == K_OS_WINDOWS
+    TlsFree(g_dwThreadTLS);
+    g_dwThreadTLS = TLS_OUT_OF_INDEXES;
+
+#elif defined(KPRF_USE_PTHREAD)
+    pthread_key_delete(g_ThreadKey);
+    g_ThreadKey = (pthread_key_t)-1;
+
+#elif K_OS == K_OS_OS2
+    DosFreeThreadLocalMemory((PULONG)g_ppThread);
+    g_ppThread = NULL;
+
+#else
+# error "port me!"
+#endif
+
+    kPrfMutexDelete(&g_ThreadsMutex);
+    kPrfMutexDelete(&g_ModSegsMutex);
+    kPrfRWLockDelete(&g_FunctionsRWLock);
+
+    return rc;
+}
+
+
+/**
+ * Terminate the current thread.
+ */
+void kPrfTerminateThread(void)
+{
+    KPRF_NAME(DeregisterThread)();
+}
+
+
+#ifdef KPRF_USE_PTHREAD
+/**
+ * TLS destructor.
+ */
+static void kPrfPThreadKeyDtor(void *pvThread)
+{
+    KPRF_TYPE(P,HDR) pHdr = KPRF_GET_HDR();
+    if (pHdr)
+    {
+        KPRF_TYPE(P,THREAD) pThread = (KPRF_TYPE(P,THREAD))pvThread;
+        pthread_setspecific(g_ThreadKey, pvThread);
+        KPRF_NAME(TerminateThread)(pHdr, pThread, KPRF_NOW());
+        pthread_setspecific(g_ThreadKey, NULL);
+    }
+}
+#endif
+
diff --git a/src/lib/kStuff/kProfiler2/kProfileR3.h b/src/lib/kStuff/kProfiler2/kProfileR3.h
new file mode 100644
index 0000000..87938c9
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/kProfileR3.h
@@ -0,0 +1,39 @@
+/* $Id: kProfileR3.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kProfiler Mark 2 - Internal header, Ring-3.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___kProfileR3_h___
+#define ___kProfileR3_h___
+
+int kPrfInitialize(void);
+int kPrfTerminate(void);
+void kPrfTerminateThread(void);
+
+#endif
+
diff --git a/src/lib/kStuff/kProfiler2/prfamd64msc.asm b/src/lib/kStuff/kProfiler2/prfamd64msc.asm
new file mode 100644
index 0000000..87079e2
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/prfamd64msc.asm
@@ -0,0 +1,474 @@
+; $Id: prfamd64msc.asm 29 2009-07-01 20:30:29Z bird $;
+;; @file
+; kProfiler Mark 2 - Microsoft C/C++ Compiler Interaction, AMD64.
+;
+
+;
+; Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+;
+; Permission is hereby granted, free of charge, to any person
+; obtaining a copy of this software and associated documentation
+; files (the "Software"), to deal in the Software without
+; restriction, including without limitation the rights to use,
+; copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of the Software, and to permit persons to whom the
+; Software is furnished to do so, subject to the following
+; conditions:
+;
+; The above copyright notice and this permission notice shall be
+; included in all copies or substantial portions of the Software.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+; OTHER DEALINGS IN THE SOFTWARE.
+;
+
+[section .data]
+;
+g_fCalibrated:
+        dd 0
+g_OverheadAdj:
+        dd 0
+
+[section .text]
+
+extern KPRF_ENTER
+extern KPRF_LEAVE
+
+global _penter
+global _pexit
+
+;ifdef  UNDEFINED
+global common_return_path
+global common_overhead
+global common_no_overhead
+global calibrate
+global calib_inner_update_minimum
+global calib_inner_next
+global calib_outer_dec
+global calib_outer_inc
+global calib_done
+global calib_nullproc
+;endif
+
+
+;;
+; On x86 the call to this function has been observed to be put before
+; creating the stack frame, as the very first instruction in the function.
+;
+; Thus the stack layout is as follows:
+;       24      return address of the calling function.
+;       20      our return address - the address of the calling function + 5.
+;       1c      eax
+;       18      edx
+;       14      eflags
+;       10      ecx
+;       c       tsc high       - param 3
+;       8       tsc low
+;       4       frame pointer  - param 2
+;       0       function ptr   - param 1
+;
+;
+align 16
+_penter:
+        ; save volatile register and get the time stamp.
+        push    rax
+        push    rdx
+        rdtsc
+        pushfq
+        push    rcx
+        push    r8
+        push    r9
+        push    r10
+        push    r11
+        sub     rsp, 28h                ; rsp is unaligned at this point (8 pushes).
+                                        ; reserve 20h for spill, and 8 bytes for ts.
+
+        ; setting up the enter call frame
+        mov     r8d, edx
+        shl     r8, 32
+        or      r8, rax                 ; param 3 - the timestamp
+        mov     [rsp + 20h], r8         ; save the tsc for later use.
+        lea     rdx, [rsp + 8*8 + 28h]  ; Param 2 - default frame pointer
+        mov     rcx, [rdx]              ; Param 1 - The function address
+
+        ; MSC seems to put the _penter both before and after the typical sub rsp, xxh
+        ; statement as if it cannot quite make up its mind. We'll try adjust for this
+        ; to make the unwinding a bit more accurate wrt to longjmp/throw. But since
+        ; there are also an uneven amount of push/pop around the _penter/_pexit we
+        ; can never really make a perfect job of it. sigh.
+        cmp     word [rcx - 5 - 4], 08348h  ; sub rsp, imm8
+        jne     .not_byte_sub
+        cmp     byte [rcx - 5 - 2], 0ech
+        jne     .not_byte_sub
+        movzx   eax, byte [rcx - 5 - 1]     ; imm8
+        add     rdx, rax
+        jmp     .call_prf_enter
+.not_byte_sub:
+        cmp     word [rcx - 5 - 7], 08148h  ; sub rsp, imm32
+        jne     .not_dword_sub
+        cmp     byte [rcx - 5 - 5], 0ech
+        jne     .not_dword_sub
+        mov     eax, [rcx - 5 - 4]          ; imm32
+        add     rdx, rax
+;        jmp     .call_prf_enter
+.not_dword_sub:
+.call_prf_enter:
+        call    KPRF_ENTER
+        jmp     common_return_path
+
+
+;;
+; On x86 the call to this function has been observed to be put right before
+; return instruction. This fact matters since since we have to calc the same
+; stack address as in _penter.
+;
+; Thus the stack layout is as follows:
+;       24      return address of the calling function.
+;       20      our return address - the address of the calling function + 5.
+;       1c      eax
+;       18      edx
+;       14      eflags
+;       10      ecx
+;       c       tsc high       - param 3
+;       8       tsc low
+;       4       frame pointer  - param 2
+;       0       function ptr   - param 1
+;
+;
+align 16
+_pexit:
+        ; save volatile register and get the time stamp.
+        push    rax
+        push    rdx
+        rdtsc
+        pushfq
+        push    rcx
+        push    r8
+        push    r9
+        push    r10
+        push    r11
+        sub     rsp, 28h                ; rsp is unaligned at this point (8 pushes).
+                                        ; reserve 20h for spill, and 8 bytes for ts.
+
+        ; setting up the enter call frame
+        mov     r8d, edx
+        shl     r8, 32
+        or      r8, rax                 ; param 3 - the timestamp
+        mov     [rsp + 20h], r8         ; save the tsc for later use.
+        lea     rdx, [rsp + 8*8 + 28h]  ; Param 2 - frame pointer.
+        mov     rcx, [rdx]              ; Param 1 - The function address
+
+        ; MSC some times put the _pexit before the add rsp, xxh. To try match up with
+        ; any adjustments made in _penter, we'll try detect this.
+        cmp     word [rcx], 08348h      ; add rsp, imm8
+        jne     .not_byte_sub
+        cmp     byte [rcx + 2], 0c4h
+        jne     .not_byte_sub
+        movzx   eax, byte [rcx + 3]     ; imm8
+        add     rdx, rax
+        jmp     .call_prf_leave
+.not_byte_sub:
+        cmp     word [rcx], 08148h      ; add rsp, imm32
+        jne     .not_dword_sub
+        cmp     byte [rcx + 2], 0c4h
+        jne     .not_dword_sub
+        mov     eax, [rcx + 3]          ; imm32
+        add     rdx, rax
+;        jmp     .call_prf_leave
+.not_dword_sub:
+.call_prf_leave:
+        call    KPRF_LEAVE
+        jmp common_return_path
+
+
+;;
+; This is the common return path for both the enter and exit hooks.
+; It's kept common because we can then use the same overhead adjustment
+; and save some calibration efforts. It also saves space :-)
+align 16
+common_return_path:
+        ; Update overhead
+        test    rax, rax
+        jz      common_no_overhead
+        cmp     byte [g_fCalibrated wrt rip], 0
+        jnz     common_overhead
+        call    calibrate
+common_overhead:
+        mov     rcx, rax                ; rcx <- pointer to overhead counter.
+        mov     eax, [g_OverheadAdj wrt rip]; apply the adjustment before reading tsc
+        sub     [rsp + 20h], rax
+
+        rdtsc
+        shl     rdx, 32
+        or      rdx, rax                ; rdx = 64-bit timestamp
+        sub     rdx, [rsp + 20h]        ; rdx = elapsed
+        lock add [rcx], rdx             ; update counter.
+common_no_overhead:
+
+        ; restore volatile registers.
+        add     rsp, 28h
+        pop     r11
+        pop     r10
+        pop     r9
+        pop     r8
+        pop     rcx
+        popfq
+        pop     rdx
+        pop     rax
+        ret
+
+;;
+; Data rsi points to while we're calibrating.
+struc CALIBDATA
+    .Overhead   resq 1
+    .Profiled   resq 1
+    .EnterTS    resq 1
+    .Min        resq 1
+endstruc
+
+
+
+align 16
+;;
+; Do necessary calibrations.
+;
+calibrate:
+        ; prolog - save everything
+        push    rbp
+        pushfq
+        push    rax                     ; pushaq
+        push    rbx
+        push    rcx
+        push    rdx
+        push    rdi
+        push    rsi
+        push    r8
+        push    r9
+        push    r10
+        push    r11
+        push    r12
+        push    r13
+        push    r14
+        push    r15
+        mov     rbp, rsp
+
+        sub     rsp, CALIBDATA_size
+        mov     rsi, rsp                ; rsi points to the CALIBDATA
+
+        and     rsp, -16
+
+        ;
+        ; Indicate that we have finished calibrating.
+        ;
+        mov     eax, 1
+        xchg    dword [g_fCalibrated wrt rip], eax
+
+        ;
+        ; The outer loop - find the right adjustment.
+        ;
+        mov     ebx, 200h               ; loop counter.
+calib_outer_loop:
+
+        ;
+        ; The inner loop - calls the function number of times to establish a
+        ;                  good minimum value
+        ;
+        mov     ecx, 200h
+        mov     dword [rsi + CALIBDATA.Min], 0ffffffffh
+        mov     dword [rsi + CALIBDATA.Min + 4], 07fffffffh
+calib_inner_loop:
+
+        ; zero the overhead and profiled times.
+        xor     eax, eax
+        mov     [rsi + CALIBDATA.Overhead], rax
+        mov     [rsi + CALIBDATA.Profiled], rax
+        call    calib_nullproc
+
+        ; subtract the overhead
+        mov     rax, [rsi + CALIBDATA.Profiled]
+        sub     rax, [rsi + CALIBDATA.Overhead]
+
+        ; update the minimum value.
+        bt      rax, 63
+        jc near calib_outer_dec        ; if negative, just simplify and shortcut
+        cmp     rax, [rsi + CALIBDATA.Min]
+        jge     calib_inner_next
+calib_inner_update_minimum:
+        mov     [rsi + CALIBDATA.Min], rax
+calib_inner_next:
+        loop    calib_inner_loop
+
+        ; Is the minimum value acceptable?
+        test    dword [rsi + CALIBDATA.Min + 4], 80000000h
+        jnz     calib_outer_dec         ; simplify if negative.
+        cmp     dword [rsi + CALIBDATA.Min + 4], 0
+        jnz     calib_outer_inc         ; this shouldn't be possible
+        cmp     dword [rsi + CALIBDATA.Min], 1fh
+        jbe     calib_outer_dec         ; too low - 2 ticks per pair is the minimum!
+        ;cmp     dword [rsi + CALIBDATA.Min], 30h
+        ;jbe     calib_done              ; this is fine!
+        cmp     dword [rsi + CALIBDATA.Min], 70h ; - a bit weird...
+        jbe     calib_outer_next         ; do the full 200h*200h iteration
+calib_outer_inc:
+        inc     dword [g_OverheadAdj wrt rip]
+        jmp     calib_outer_next
+calib_outer_dec:
+        cmp     dword [g_OverheadAdj wrt rip], 1
+        je      calib_done
+        dec     dword [g_OverheadAdj wrt rip]
+calib_outer_next:
+        dec     ebx
+        jnz     calib_outer_loop
+calib_done:
+
+        ; epilog - restore it all.
+        mov     rsp, rbp
+        pop     r15
+        pop     r14
+        pop     r13
+        pop     r12
+        pop     r11
+        pop     r10
+        pop     r9
+        pop     r8
+        pop     rsi
+        pop     rdi
+        pop     rdx
+        pop     rcx
+        pop     rbx
+        pop     rax
+        popfq
+        pop     rbp
+        ret
+
+
+
+
+;;
+; The calibration _penter - this must be identical to the real thing except for the KPRF call.
+align 16
+calib_penter:
+        ; This part must be identical past the rdtsc.
+        push    rax
+        push    rdx
+        rdtsc
+        pushfq
+        push    rcx
+        push    r8
+        push    r9
+        push    r10
+        push    r11
+        sub     rsp, 28h                ; rsp is unaligned at this point (8 pushes).
+                                        ; reserve 20h for spill, and 8 bytes for ts.
+
+        ; store the entry / stack frame.
+        mov     r8d, edx
+        shl     r8, 32
+        or      r8, rax
+        mov     [rsp + 20h], r8
+
+        mov     [rsi + CALIBDATA.EnterTS], r8
+
+        lea     rax, [rsi + CALIBDATA.Overhead]
+        jmp     common_overhead
+
+
+;;
+; The calibration _pexit - this must be identical to the real thing except for the KPRF call.
+align 16
+calib_pexit:
+        ; This part must be identical past the rdtsc.
+        push    rax
+        push    rdx
+        rdtsc
+        pushfq
+        push    rcx
+        push    r8
+        push    r9
+        push    r10
+        push    r11
+        sub     rsp, 28h                ; rsp is unaligned at this point (8 pushes).
+                                        ; reserve 20h for spill, and 8 bytes for ts.
+
+        ; store the entry / stack frame.
+        mov     r8d, edx
+        shl     r8, 32
+        or      r8, rax
+        mov     [rsp + 20h], r8
+
+        sub     r8, [rsi + CALIBDATA.EnterTS]
+        add     [rsi + CALIBDATA.Profiled], r8
+
+        lea     rax, [rsi + CALIBDATA.EnterTS]
+        jmp     common_overhead
+
+
+;;
+; The 'function' we're profiling.
+; The general idea is that each pair should take something like 2-10 ticks.
+;
+; (Btw. If we don't use multiple pairs here, we end up with the wrong result.)
+align 16
+calib_nullproc:
+        call    calib_penter ;0
+        call    calib_pexit
+
+        call    calib_penter ;1
+        call    calib_pexit
+
+        call    calib_penter ;2
+        call    calib_pexit
+
+        call    calib_penter ;3
+        call    calib_pexit
+
+        call    calib_penter ;4
+        call    calib_pexit
+
+        call    calib_penter ;5
+        call    calib_pexit
+
+        call    calib_penter ;6
+        call    calib_pexit
+
+        call    calib_penter ;7
+        call    calib_pexit
+
+        call    calib_penter ;8
+        call    calib_pexit
+
+        call    calib_penter ;9
+        call    calib_pexit
+
+        call    calib_penter ;a
+        call    calib_pexit
+
+        call    calib_penter ;b
+        call    calib_pexit
+
+        call    calib_penter ;c
+        call    calib_pexit
+
+        call    calib_penter ;d
+        call    calib_pexit
+
+        call    calib_penter ;e
+        call    calib_pexit
+
+        call    calib_penter ;f
+        call    calib_pexit
+        ret
+
+
+;
+; Dummy stack check function.
+;
+global __chkstk
+__chkstk:
+    ret
diff --git a/src/lib/kStuff/kProfiler2/prfcore.cpp.h b/src/lib/kStuff/kProfiler2/prfcore.cpp.h
new file mode 100644
index 0000000..ac19eb7
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/prfcore.cpp.h
@@ -0,0 +1,657 @@
+/* $Id: prfcore.cpp.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kProfiler Mark 2 - Core Code Template.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * Gets a function, create a new one if necessary.
+ */
+static KPRF_TYPE(P,FUNC) KPRF_NAME(GetFunction)(KPRF_TYPE(P,HDR) pHdr, KPRF_TYPE(,UPTR) uPC)
+{
+    /*
+     * Perform a binary search of the function lookup table.
+     */
+    KPRF_TYPE(P,FUNC) paFunctions = KPRF_OFF2PTR(P,FUNC, pHdr->offFunctions, pHdr);
+
+    KPRF_FUNCS_READ_LOCK();
+    KI32 iStart = 0;
+    KI32 iLast  = pHdr->cFunctions - 1;
+    KI32 i      = iLast / 2;
+    for (;;)
+    {
+        KU32 iFunction = pHdr->aiFunctions[i];
+        KPRF_TYPE(,IPTR) iDiff = uPC - paFunctions[iFunction].uEntryPtr;
+        if (!iDiff)
+        {
+            KPRF_FUNCS_READ_UNLOCK();
+            return &paFunctions[iFunction];
+        }
+        if (iLast == iStart)
+            break;
+        if (iDiff < 0)
+            iLast = i - 1;
+        else
+            iStart = i + 1;
+        if (iLast < iStart)
+            break;
+        i = iStart + (iLast - iStart) / 2;
+    }
+    KPRF_FUNCS_READ_UNLOCK();
+
+    /*
+     * It wasn't found, try add it.
+     */
+    if (pHdr->cFunctions < pHdr->cMaxFunctions)
+        return KPRF_NAME(NewFunction)(pHdr, uPC);
+    return NULL;
+}
+
+
+/**
+ * Unwind one frame.
+ */
+static KU64* KPRF_NAME(UnwindOne)(KPRF_TYPE(P,HDR) pHdr, KPRF_TYPE(P,STACK) pStack, KPRF_TYPE(,UPTR) uPC, KU64 TS)
+{
+    /*
+     * Pop off the frame and update the frame below / thread.
+     */
+    KPRF_TYPE(P,FRAME) pFrame = &pStack->aFrames[--pStack->cFrames];
+    KU64 *pCurOverheadTicks;
+    if (pStack->cFrames)
+    {
+        KPRF_TYPE(P,FRAME) pTopFrame = pFrame - 1;
+        pTopFrame->OverheadTicks += pFrame->OverheadTicks + pFrame->CurOverheadTicks;
+        pTopFrame->SleepTicks    += pFrame->SleepTicks;
+        pTopFrame->OnTopOfStackStart = TS;
+        pTopFrame->CurOverheadTicks  = 0;
+
+        pCurOverheadTicks = &pTopFrame->CurOverheadTicks;
+    }
+    else
+    {
+        KPRF_TYPE(P,THREAD) pThread = KPRF_OFF2PTR(P,THREAD, pStack->offThread, pHdr);
+        pThread->ProfiledTicks  += TS - pFrame->OnStackStart - pFrame->CurOverheadTicks - pFrame->OverheadTicks - pFrame->SleepTicks;
+        pThread->OverheadTicks  += pFrame->OverheadTicks + pFrame->CurOverheadTicks;
+        pThread->SleepTicks     += pFrame->SleepTicks;
+
+        pCurOverheadTicks = &pThread->OverheadTicks;
+    }
+
+    /*
+     * Update the function (if any).
+     */
+    if (pFrame->offFunction)
+    {
+        KPRF_TYPE(P,FUNC) pFunc = KPRF_OFF2PTR(P,FUNC, pFrame->offFunction, pHdr);
+
+        /* Time on stack */
+        KU64 Ticks = TS - pFrame->OnStackStart;
+        Ticks -= pFrame->OverheadTicks + pFrame->CurOverheadTicks + pFrame->SleepTicks;
+/** @todo adjust overhead */
+KPRF_ASSERT(!(Ticks >> 63));
+        if (pFunc->OnStack.MinTicks > Ticks)
+            KPRF_ATOMIC_SET64(&pFunc->OnStack.MinTicks, Ticks);
+        if (pFunc->OnStack.MaxTicks < Ticks)
+            KPRF_ATOMIC_SET64(&pFunc->OnStack.MaxTicks, Ticks);
+        KPRF_ATOMIC_ADD64(&pFunc->OnStack.SumTicks, Ticks);
+
+        /* Time on top of stack */
+        Ticks = TS - pFrame->OnTopOfStackStart;
+        Ticks -= pFrame->CurOverheadTicks;
+        Ticks += pFrame->OnTopOfStackTicks;
+/** @todo adjust overhead */
+KPRF_ASSERT(!(Ticks >> 63));
+        if (pFunc->OnTopOfStack.MinTicks > Ticks)
+            KPRF_ATOMIC_SET64(&pFunc->OnTopOfStack.MinTicks, Ticks);
+        if (pFunc->OnTopOfStack.MaxTicks < Ticks)
+            KPRF_ATOMIC_SET64(&pFunc->OnTopOfStack.MaxTicks, Ticks);
+        KPRF_ATOMIC_ADD64(&pFunc->OnTopOfStack.SumTicks, Ticks);
+
+        /* calls */
+        if (pFrame->cCalls)
+            KPRF_ATOMIC_ADD64(&pFunc->cCalls, pFrame->cCalls);
+    }
+
+    return pCurOverheadTicks;
+}
+
+
+/**
+ * Unwinds the stack.
+ *
+ * On MSC+AMD64 we have to be very very careful here, because the uFramePtr cannot be trusted.
+ */
+static KU64* KPRF_NAME(UnwindInt)(KPRF_TYPE(P,HDR) pHdr, KPRF_TYPE(P,STACK) pStack, KPRF_TYPE(,UPTR) uPC, KPRF_TYPE(,UPTR) uFramePtr, KU64 TS)
+{
+    /** @todo need to deal with alternative stacks! */
+
+    /*
+     * Pop the stack until we're down below the current frame (uFramePtr).
+     */
+    KI32 iFrame = pStack->cFrames - 1;
+    KPRF_TYPE(P,FRAME) pFrame = &pStack->aFrames[iFrame];
+
+    /* the most frequent case first. */
+#if K_OS == K_OS_WINDOWS && K_ARCH == K_ARCH_AMD64
+    if (    uFramePtr == pFrame->uFramePtr
+        ||  (   pFrame->uFramePtr < uFramePtr
+             && iFrame > 0
+             && pFrame[-1].uFramePtr > uFramePtr))
+        return KPRF_NAME(UnwindOne)(pHdr, pStack, uPC, TS);
+#else
+    if (uFramePtr == pFrame->uFramePtr)
+        return KPRF_NAME(UnwindOne)(pHdr, pStack, uPC, TS);
+#endif
+
+    /* none?  */
+    if (pFrame->uFramePtr > uFramePtr)
+        return &pFrame->CurOverheadTicks;
+
+    /* one or more, possibly all */
+    KU64 *pCurOverheadTicks = KPRF_NAME(UnwindOne)(pHdr, pStack, uPC, TS);
+    pFrame--;
+    if (    iFrame > 0
+#if K_OS == K_OS_WINDOWS && K_ARCH == K_ARCH_AMD64
+        &&  pFrame->uFramePtr <= uFramePtr
+        &&  pFrame[-1].uFramePtr > uFramePtr)
+#else
+        &&  pFrame->uFramePtr <= uFramePtr)
+#endif
+    {
+        KPRF_TYPE(P,THREAD) pThread = KPRF_OFF2PTR(P,THREAD, pStack->offThread, pHdr);
+        pThread->cUnwinds++;        /* (This is the reason for what looks like a bad loop unrolling.) */
+
+        pCurOverheadTicks = KPRF_NAME(UnwindOne)(pHdr, pStack, uPC, TS);
+        iFrame -= 2;
+        pFrame--;
+#if K_OS == K_OS_WINDOWS && K_ARCH == K_ARCH_AMD64
+        while (     iFrame > 0
+               &&   pFrame->uFramePtr <= uFramePtr
+               &&   pFrame[-1].uFramePtr > uFramePtr)
+#else
+        while (     iFrame >= 0
+               &&   pFrame->uFramePtr <= uFramePtr)
+#endif
+        {
+            pCurOverheadTicks = KPRF_NAME(UnwindOne)(pHdr, pStack, uPC, TS);
+            iFrame--;
+            pFrame--;
+        }
+    }
+
+    return pCurOverheadTicks;
+}
+
+
+
+/**
+ * Enter function.
+ *
+ * @returns Where to account overhead.
+ * @returns NULL if profiling is inactive.
+ *
+ * @param   uPC         The program counter register. (not relative)
+ * @param   uFramePtr   The stack frame address. This must match the one passed to kPrfLeave. (not relative)
+ * @param   TS          The timestamp when we entered into the profiler.
+ *                      This must not be modified touched!
+ *
+ * @internal ?
+ */
+KPRF_DECL_FUNC(KU64 *, Enter)(KPRF_TYPE(,UPTR) uPC, KPRF_TYPE(,UPTR) uFramePtr, const KU64 TS)
+{
+    /*
+     * Is profiling active ?
+     */
+    if (!KPRF_IS_ACTIVE())
+        return NULL;
+
+    /*
+     * Get the header and adjust input addresses.
+     */
+    KPRF_TYPE(P,HDR)    pHdr = KPRF_GET_HDR();
+    if (!pHdr)
+        return NULL;
+    const KPRF_TYPE(,UPTR) uBasePtr = pHdr->uBasePtr;
+    if (uBasePtr)
+    {
+        uFramePtr -= uBasePtr;
+        uPC       -= uBasePtr;
+    }
+
+    /*
+     * Get the current thread. Reject unknown, inactive (in whatever way),
+     * and thread which has performed a stack switch.
+     */
+    KPRF_TYPE(P,THREAD) pThread = KPRF_GET_THREAD();
+    if (!pThread)
+        return NULL;
+    KPRF_TYPE(,THREADSTATE) enmThreadState = pThread->enmState;
+    if (    enmThreadState != KPRF_TYPE(,THREADSTATE_ACTIVE)
+        &&  enmThreadState != KPRF_TYPE(,THREADSTATE_OVERFLOWED)
+        )
+        return NULL;
+    if (pThread->uStackBasePtr < uFramePtr)                                         /* ASSUMES stack direction */
+    {
+        pThread->cStackSwitchRejects++;
+        return NULL;
+    }
+    pThread->enmState = KPRF_TYPE(,THREADSTATE_SUSPENDED);
+
+
+    /*
+     * Update the thread statistics.
+     */
+    pThread->cCalls++;
+    KPRF_TYPE(,UPTR) cbStack = pThread->uStackBasePtr - uFramePtr;                 /* ASSUMES stack direction */
+    if (pThread->cbMaxStack < cbStack)
+        pThread->cbMaxStack = cbStack;
+
+    /*
+     * Check if an longjmp or throw has taken place.
+     * This check will not work if a stack switch has taken place (can fix that later).
+     */
+    KPRF_TYPE(P,STACK) pStack = KPRF_OFF2PTR(P,STACK, pThread->offStack, pHdr);
+    KU32 iFrame = pStack->cFrames;
+    KPRF_TYPE(P,FRAME) pFrame = &pStack->aFrames[iFrame];
+    if (    iFrame
+#if K_OS == K_OS_WINDOWS && K_ARCH == K_ARCH_AMD64
+        &&  0) /* don't bother her yet because of _penter/_pexit frame problems. */
+#else
+        &&  pThread->uStackBasePtr >= uFramePtr                                     /* ASSUMES stack direction */
+        &&  pFrame[-1].uFramePtr + (KPRF_BITS - 8) / 8 < uFramePtr)                 /* ASSUMES stack direction */
+#endif
+    {
+        KPRF_NAME(UnwindInt)(pHdr, pStack, uPC, uFramePtr, TS);
+        iFrame = pStack->cFrames;
+    }
+
+    /*
+     * Allocate a new stack frame.
+     */
+    if (iFrame >= pHdr->cMaxStackFrames)
+    {
+        /* overflow */
+        pThread->enmState = KPRF_TYPE(,THREADSTATE_OVERFLOWED);
+        pThread->cOverflows += enmThreadState != KPRF_TYPE(,THREADSTATE_OVERFLOWED);
+        return &pStack->aFrames[iFrame - 1].CurOverheadTicks;
+    }
+    pStack->cFrames++;
+
+    /*
+     * Update the old top frame if any.
+     */
+    if (iFrame)
+    {
+        KPRF_TYPE(P,FRAME) pOldFrame = pFrame - 1;
+        pOldFrame->OnTopOfStackTicks += TS - pOldFrame->OnTopOfStackStart;
+        pOldFrame->cCalls++;
+    }
+
+    /*
+     * Fill in the new frame.
+     */
+    pFrame->CurOverheadTicks    = 0;
+    pFrame->OverheadTicks       = 0;
+    pFrame->SleepTicks          = 0;
+    pFrame->OnStackStart        = TS;
+    pFrame->OnTopOfStackStart   = TS;
+    pFrame->OnTopOfStackTicks   = 0;
+    pFrame->cCalls              = 0;
+    pFrame->uFramePtr           = uFramePtr;
+
+    /*
+     * Find the relevant function.
+     */
+    KPRF_TYPE(P,FUNC) pFunc = KPRF_NAME(GetFunction)(pHdr, uPC);
+    if (pFunc)
+    {
+        pFrame->offFunction = KPRF_PTR2OFF(pFunc, pHdr);
+        pFunc->cOnStack++;
+    }
+    else
+        pFrame->offFunction = 0;
+
+    /*
+     * Nearly done, We only have to reactivate the thread and account overhead.
+     * The latter is delegated to the caller.
+     */
+    pThread->enmState = KPRF_TYPE(,THREADSTATE_ACTIVE);
+    return &pFrame->CurOverheadTicks;
+}
+
+
+/**
+ * Leave function.
+ *
+ * @returns Where to account overhead.
+ * @returns NULL if profiling is inactive.
+ *
+ * @param   uPC         The program counter register.
+ * @param   uFramePtr   The stack frame address. This must match the one passed to kPrfEnter.
+ * @param   TS          The timestamp when we entered into the profiler.
+ *                      This must not be modified because the caller could be using it!
+ * @internal
+ */
+KPRF_DECL_FUNC(KU64 *, Leave)(KPRF_TYPE(,UPTR) uPC, KPRF_TYPE(,UPTR) uFramePtr, const KU64 TS)
+{
+    /*
+     * Is profiling active ?
+     */
+    if (!KPRF_IS_ACTIVE())
+        return NULL;
+
+    /*
+     * Get the header and adjust input addresses.
+     */
+    KPRF_TYPE(P,HDR)    pHdr = KPRF_GET_HDR();
+    if (!pHdr)
+        return NULL;
+    const KPRF_TYPE(,UPTR) uBasePtr = pHdr->uBasePtr;
+    if (uBasePtr)
+    {
+        uFramePtr -= uBasePtr;
+        uPC       -= uBasePtr;
+    }
+
+    /*
+     * Get the current thread and suspend profiling of the thread until we leave this function.
+     * Also reject threads which aren't active in some way.
+     */
+    KPRF_TYPE(P,THREAD) pThread = KPRF_GET_THREAD();
+    if (!pThread)
+        return NULL;
+    KPRF_TYPE(,THREADSTATE) enmThreadState = pThread->enmState;
+    if (    enmThreadState != KPRF_TYPE(,THREADSTATE_ACTIVE)
+        &&  enmThreadState != KPRF_TYPE(,THREADSTATE_OVERFLOWED)
+        )
+        return NULL;
+    KPRF_TYPE(P,STACK) pStack = KPRF_OFF2PTR(P,STACK, pThread->offStack, pHdr);
+    if (!pStack->cFrames)
+        return NULL;
+    pThread->enmState = KPRF_TYPE(,THREADSTATE_SUSPENDED);
+
+    /*
+     * Unwind the stack down to and including the entry indicated by uFramePtr.
+     * Leave it to the caller to update the overhead.
+     */
+    KU64 *pCurOverheadTicks = KPRF_NAME(UnwindInt)(pHdr, pStack, uPC, uFramePtr, TS);
+
+    pThread->enmState = enmThreadState;
+    return pCurOverheadTicks;
+}
+
+
+/**
+ * Register the current thread.
+ *
+ * A thread can only be profiled if it has been registered by a call to this function.
+ *
+ * @param   uPC             The program counter register.
+ * @param   uStackBasePtr   The base of the stack.
+ */
+KPRF_DECL_FUNC(KPRF_TYPE(P,THREAD), RegisterThread)(KPRF_TYPE(,UPTR) uStackBasePtr, const char *pszName)
+{
+    /*
+     * Get the header and adjust input address.
+     * (It doesn't matter whether we're active or not.)
+     */
+    KPRF_TYPE(P,HDR)    pHdr = KPRF_GET_HDR();
+    if (!pHdr)
+        return NULL;
+    const KPRF_TYPE(,UPTR) uBasePtr = pHdr->uBasePtr;
+    if (uBasePtr)
+        uStackBasePtr -= uBasePtr;
+
+
+    /*
+     * Allocate a thread and a stack.
+     */
+    KPRF_THREADS_LOCK();
+    if (pHdr->cThreads < pHdr->cMaxThreads)
+    {
+        KPRF_TYPE(P,STACK) pStack = KPRF_OFF2PTR(P,STACK, pHdr->offStacks, pHdr);
+        KU32               cLeft = pHdr->cMaxStacks;
+        do
+        {
+            if (!pStack->offThread)
+            {
+                /* init the stack. */
+                pStack->cFrames   = 0;
+                pStack->offThread = pHdr->offThreads + pHdr->cbThread * pHdr->cThreads++;
+                pHdr->cStacks++;
+
+                /* init the thread */
+                KPRF_TYPE(P,THREAD) pThread = KPRF_OFF2PTR(P,THREAD, pStack->offThread, pHdr);
+                pThread->ThreadId       = KPRF_GET_THREADID();
+                unsigned i = 0;
+                if (pszName)
+                    while (i < sizeof(pThread->szName) - 1 && *pszName)
+                        pThread->szName[i++] = *pszName++;
+                while (i < sizeof(pThread->szName))
+                    pThread->szName[i++] = '\0';
+                pThread->enmState       = KPRF_TYPE(,THREADSTATE_SUSPENDED);
+                pThread->Reserved0      = KPRF_TYPE(,THREADSTATE_TERMINATED);
+                pThread->uStackBasePtr  = uStackBasePtr;
+                pThread->cbMaxStack     = 0;
+                pThread->cCalls         = 0;
+                pThread->cOverflows     = 0;
+                pThread->cStackSwitchRejects = 0;
+                pThread->cUnwinds       = 0;
+                pThread->ProfiledTicks  = 0;
+                pThread->OverheadTicks  = 0;
+                pThread->SleepTicks     = 0;
+                pThread->offStack       = KPRF_PTR2OFF(pStack, pHdr);
+
+
+                /* set the thread and make it active. */
+                KPRF_THREADS_UNLOCK();
+                KPRF_SET_THREAD(pThread);
+                pThread->enmState = KPRF_TYPE(,THREADSTATE_ACTIVE);
+                return pThread;
+            }
+
+            /* next */
+            pStack = KPRF_TYPE(P,STACK)(((KPRF_TYPE(,UPTR))pStack + pHdr->cbStack));
+        } while (--cLeft > 0);
+    }
+
+    KPRF_THREADS_UNLOCK();
+    return NULL;
+}
+
+
+/**
+ * Terminates a thread.
+ *
+ * To terminate the current thread use DeregisterThread(), because that
+ * cleans up the TLS entry too.
+ *
+ * @param   pHdr        The profiler data set header.
+ * @param   pThread     The thread to terminate.
+ * @param   TS          The timestamp to use when terminating the thread.
+ */
+KPRF_DECL_FUNC(void, TerminateThread)(KPRF_TYPE(P,HDR) pHdr, KPRF_TYPE(P,THREAD) pThread, KU64 TS)
+{
+    if (pThread->enmState == KPRF_TYPE(,THREADSTATE_TERMINATED))
+        return;
+    pThread->enmState = KPRF_TYPE(,THREADSTATE_TERMINATED);
+
+    /*
+     * Unwind the entire stack.
+     */
+    if (pThread->offStack)
+    {
+        KPRF_TYPE(P,STACK) pStack = KPRF_OFF2PTR(P,STACK, pThread->offStack, pHdr);
+        for (KU32 cFrames = pStack->cFrames; cFrames > 0; cFrames--)
+            KPRF_NAME(UnwindOne)(pHdr, pStack, 0, TS);
+
+        /*
+         * Free the stack.
+         */
+        pThread->offStack = 0;
+        KPRF_THREADS_LOCK();
+        pStack->offThread = 0;
+        pHdr->cStacks--;
+        KPRF_THREADS_UNLOCK();
+    }
+}
+
+
+/**
+ * Deregister (terminate) the current thread.
+ */
+KPRF_DECL_FUNC(void, DeregisterThread)(void)
+{
+    KU64 TS = KPRF_NOW();
+
+    /*
+     * Get the header, then get the thread and mark it terminated.
+     * (It doesn't matter whether we're active or not.)
+     */
+    KPRF_TYPE(P,HDR)    pHdr = KPRF_GET_HDR();
+    if (!pHdr)
+        return;
+
+    KPRF_TYPE(P,THREAD) pThread = KPRF_GET_THREAD();
+    KPRF_SET_THREAD(NULL);
+    if (!pThread)
+        return;
+    KPRF_NAME(TerminateThread)(pHdr, pThread, TS);
+}
+
+
+/**
+ * Resumes / restarts a thread.
+ *
+ * @param   fReset  If set the stack is reset.
+ */
+KPRF_DECL_FUNC(void, ResumeThread)(int fReset)
+{
+    KU64 TS = KPRF_NOW();
+
+    /*
+     * Get the header, then get the thread and mark it terminated.
+     * (It doesn't matter whether we're active or not.)
+     */
+    KPRF_TYPE(P,HDR)    pHdr = KPRF_GET_HDR();
+    if (!pHdr)
+        return;
+
+    KPRF_TYPE(P,THREAD) pThread = KPRF_GET_THREAD();
+    if (!pThread)
+        return;
+    if (pThread->enmState != KPRF_TYPE(,THREADSTATE_SUSPENDED))
+        return;
+
+    /*
+     * Reset (unwind) the stack?
+     */
+    KPRF_TYPE(P,STACK) pStack = KPRF_OFF2PTR(P,STACK, pThread->offStack, pHdr);
+    if (fReset)
+    {
+        KU32 cFrames = pStack->cFrames;
+        while (cFrames-- > 0)
+            KPRF_NAME(UnwindOne)(pHdr, pStack, 0, TS);
+    }
+    /*
+     * If we've got any thing on the stack, we'll have to stop the sleeping period.
+     */
+    else if (pStack->cFrames > 0)
+    {
+        KPRF_TYPE(P,FRAME) pFrame = &pStack->aFrames[pStack->cFrames - 1];
+
+        /* update the sleeping time and set the start of the new top-of-stack period. */
+        pFrame->SleepTicks += TS - pFrame->OnTopOfStackStart;
+        pFrame->OnTopOfStackStart = TS;
+    }
+    /** @todo we're not accounting overhead here! */
+
+    /*
+     * We're done, switch the thread to active state.
+     */
+    pThread->enmState = KPRF_TYPE(,THREADSTATE_ACTIVE);
+}
+
+
+/**
+ * Suspend / completes a thread.
+ *
+ * The thread will be in a suspend state where the time will be accounted for as sleeping.
+ *
+ * @param   fUnwind     If set the stack is unwound and the thread statistics updated.
+ */
+KPRF_DECL_FUNC(void, SuspendThread)(int fUnwind)
+{
+    KU64 TS = KPRF_NOW();
+
+    /*
+     * Get the header, then get the thread and mark it terminated.
+     * (It doesn't matter whether we're active or not.)
+     */
+    KPRF_TYPE(P,HDR)    pHdr = KPRF_GET_HDR();
+    if (!pHdr)
+        return;
+
+    KPRF_TYPE(P,THREAD) pThread = KPRF_GET_THREAD();
+    if (!pThread)
+        return;
+    if (    pThread->enmState != KPRF_TYPE(,THREADSTATE_ACTIVE)
+        &&  pThread->enmState != KPRF_TYPE(,THREADSTATE_OVERFLOWED)
+        &&  (pThread->enmState != KPRF_TYPE(,THREADSTATE_SUSPENDED) || fUnwind))
+        return;
+
+    pThread->enmState = KPRF_TYPE(,THREADSTATE_SUSPENDED);
+
+    /*
+     * Unwind the stack?
+     */
+    KPRF_TYPE(P,STACK) pStack = KPRF_OFF2PTR(P,STACK, pThread->offStack, pHdr);
+    if (fUnwind)
+    {
+        KU32 cFrames = pStack->cFrames;
+        while (cFrames-- > 0)
+            KPRF_NAME(UnwindOne)(pHdr, pStack, 0, TS);
+    }
+    /*
+     * If we've got any thing on the stack, we'll have to record the sleeping period
+     * of the thread. If not we'll ignore it (for now at least).
+     */
+    else if (pStack->cFrames > 0)
+    {
+        KPRF_TYPE(P,FRAME) pFrame = &pStack->aFrames[pStack->cFrames - 1];
+
+        /* update the top of stack time and set the start of the sleep period. */
+        pFrame->OnTopOfStackTicks += TS - pFrame->OnTopOfStackStart;
+        pFrame->OnTopOfStackStart = TS;
+    }
+
+    /** @todo we're not accounting overhead here! */
+}
+
+
diff --git a/src/lib/kStuff/kProfiler2/prfcore.h.h b/src/lib/kStuff/kProfiler2/prfcore.h.h
new file mode 100644
index 0000000..d4413d1
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/prfcore.h.h
@@ -0,0 +1,381 @@
+/* $Id: prfcore.h.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kProfiler Mark 2 - Core Header Template.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/** @def KPRF_NAME
+ * Mixed case name macro.
+ */
+#ifndef KPRF_NAME
+# define KPRF_NAME(Name)        Name
+#endif
+
+/** @def KPRF_TYPE
+ * Upper case type name macro.
+ */
+#ifndef KPRF_TYPE
+# define KPRF_TYPE(Prefix,Name) Prefix##Name
+#endif
+
+/** @type KPRF_DECL_FUNC
+ * The calling convention used.
+ */
+#ifndef KPRF_DECL_FUNC
+# define KPRF_DECL_FUNC(type, name) type name
+#endif
+
+/** @def KPRF_BITS
+ * The bitsize of the format.
+ */
+#ifndef KPRF_BITS
+# define KPRF_BITS  32
+#endif
+
+/** @type UPTR
+ * The basic unsigned interger pointer type.
+ */
+/** @type IPTR
+ * The basic signed interger pointer type.
+ */
+#if KPRF_BITS == 16
+typedef KU16    KPRF_TYPE(,UPTR);
+typedef KI16    KPRF_TYPE(,IPTR);
+#elif KPRF_BITS == 32
+typedef KU32    KPRF_TYPE(,UPTR);
+typedef KI32    KPRF_TYPE(,IPTR);
+#elif KPRF_BITS == 64
+typedef KU64    KPRF_TYPE(,UPTR);
+typedef KI64    KPRF_TYPE(,IPTR);
+#else
+# error "KPRF_BITS has an invalid value. Supported values are 16, 32 and 64."
+#endif
+/** @type KPRF_TYPE(P,UPTR)
+ * Pointer to the basic pointer type.
+ */
+typedef KPRF_TYPE(,UPTR) *KPRF_TYPE(P,UPTR);
+
+
+/**
+ * Various constants.
+ */
+enum KPRF_TYPE(,CONSTANTS)
+{
+    /** Magic for the profiler header. (Unix Epoc) */
+    KPRF_TYPE(,HDR_MAGIC) = 0x19700101
+};
+
+
+/**
+ * The profile data header.
+ */
+typedef struct KPRF_TYPE(,HDR)
+{
+    /** [0] The magic number for file data. (KPRF_TYPE(,HDR_MAGIC)) */
+    KU32                    u32Magic;
+    /** [4] KPRF_BITS. */
+    KU32                    cFormatBits;
+    /** [8] The base address which all pointers should be relative to. */
+    KPRF_TYPE(,UPTR)        uBasePtr;
+#if KPRF_BITS <= 16
+    /** [a] Reserved. */
+    KU16                    u16Reserved;
+#endif
+#if KPRF_BITS <= 32
+    /** [c] Reserved. */
+    KU32                    u32Reserved;
+#endif
+    /** [10] The size of this data set. */
+    KU32                    cb;
+    /** [10] The allocated data set size. */
+    KU32                    cbAllocated;
+
+    /** [18] The max number of functions the function table can hold. */
+    KU32                    cMaxFunctions;
+    /** [1c] The current number of functions in the function table. */
+    KU32                    cFunctions;
+    /** [20] The offset of the function table (relative to this header). */
+    KU32                    offFunctions;
+    /** [24] The size of a function entry. */
+    KU32                    cbFunction;
+
+    /** [28] The max number of bytes the module segments can occupy. */
+    KU32                    cbMaxModSegs;
+    /** [2c] The current size of the module segment records. */
+    KU32                    cbModSegs;
+    /** [30] The offset of the module segment records (relative to this header). */
+    KU32                    offModSegs;
+
+    /** [34] The max number of threads the thread table can contain. */
+    KU32                    cMaxThreads;
+    /** [38] The current number of threads in the thread table. */
+    KU32                    cThreads;
+    /** [3c] The offset of the thread table (relative to this header). */
+    KU32                    offThreads;
+    /** [40] The size of a thread entry. */
+    KU32                    cbThread;
+
+    /** [44] The max number of stacks the stack table can contain. */
+    KU32                    cMaxStacks;
+    /** [48] The max number of stacks.
+     * Unlike the other members, the stacks can be reused. It follows that
+     * this count doesn't specify the number of used slots from the start. */
+    KU32                    cStacks;
+    /** [4c] The offset of the thread table (relative to this header).
+     * This is usually 0 in a stored data set. */
+    KU32                    offStacks;
+    /** [50] The size of a stack. */
+    KU32                    cbStack;
+    /** [54] The maxium stack depth. */
+    KU32                    cMaxStackFrames;
+
+    /** [58] The process commandline.
+     * Might not always apply is will be 0 in those cases. This is normally written
+     * where the stacks used to be.
+     */
+    KU32                    offCommandLine;
+    /** [5c] The length of the command line. (excludes the terminator). */
+    KU32                    cchCommandLine;
+
+    /** [60]  The function lookup table (it contains indexes).
+     * This is sorted by address so that a binary search can be performed.
+     * Access to this table is managed externally, but generally a read/write lock is employed. */
+    KU32                    aiFunctions[1];
+} KPRF_TYPE(,HDR);
+/** Pointer to a profiler data header. */
+typedef KPRF_TYPE(,HDR) *KPRF_TYPE(P,HDR);
+/** Pointer to a const profiler data header. */
+typedef const KPRF_TYPE(,HDR) *KPRF_TYPE(PC,HDR);
+
+
+/**
+ * Time statistics.
+ */
+typedef struct KPRF_TYPE(,TIMESTAT)      /** @todo bad names and descriptions! */
+{
+    /** The minimum period */
+    KU64 volatile           MinTicks;
+    /** The maximum period */
+    KU64 volatile           MaxTicks;
+    /** The sum of all periods. */
+    KU64 volatile           SumTicks;
+} KPRF_TYPE(,TIMESTAT);
+/** Pointer to time statistics. */
+typedef KPRF_TYPE(,TIMESTAT) *KPRF_TYPE(P,TIMESTAT);
+/** Pointer to const time statistics. */
+typedef const KPRF_TYPE(,TIMESTAT) *KPRF_TYPE(PC,TIMESTAT);
+
+
+/**
+ * A Module Segment.
+ */
+typedef struct KPRF_TYPE(,MODSEG)
+{
+    /** The address of the segment. (relative address) */
+    KPRF_TYPE(,UPTR)        uBasePtr;
+    /** The size of the segment minus one (so the entire address space can be covered). */
+    KPRF_TYPE(,UPTR)        cbSegmentMinusOne;
+    /** The segment number. (0 based) */
+    KU32                    iSegment;
+    /** Flag indicating whether this segment is loaded or not.
+     * (A 16-bit value was choosen out of convenience, all that's stored is 0 or 1 anyway.) */
+    KU16                    fLoaded;
+    /** The length of the path.
+     * This is used to calculate the length of the record: offsetof(MODSEG, szPath) + cchPath + 1 */
+    KU16                    cchPath;
+    /** The module name. */
+    char                    szPath[1];
+} KPRF_TYPE(,MODSEG);
+/** Pointer to a module segment. */
+typedef KPRF_TYPE(,MODSEG) *KPRF_TYPE(P,MODSEG);
+/** Pointer to a const module segment. */
+typedef const KPRF_TYPE(,MODSEG) *KPRF_TYPE(PC,MODSEG);
+
+
+/**
+ * The profiler data for a function.
+ */
+typedef struct KPRF_TYPE(,FUNC)
+{
+    /** The entry address of the function. (relative address)
+     * This is the return address of the entry hook (_mcount, _penter, _ProfileHook32, ...). */
+    KPRF_TYPE(,UPTR)        uEntryPtr;
+    /** Offset (relative to the profiler header) of the module segment to which this function belongs. */
+    KU32                    offModSeg;
+
+    /** The number times on the stack. */
+    KU64 volatile           cOnStack;
+    /** The number of calls made from this function. */
+    KU64 volatile           cCalls;
+
+    /** Time on stack. */
+    KPRF_TYPE(,TIMESTAT)    OnStack;
+    /** Time on top of the stack, i.e. executing. */
+    KPRF_TYPE(,TIMESTAT)    OnTopOfStack;
+
+    /** @todo recursion */
+
+} KPRF_TYPE(,FUNC);
+/** Pointer to the profiler data for a function. */
+typedef KPRF_TYPE(,FUNC)       *KPRF_TYPE(P,FUNC);
+/** Pointer to the const profiler data for a function. */
+typedef const KPRF_TYPE(,FUNC) *KPRF_TYPE(PC,FUNC);
+
+
+/**
+ * Stack frame.
+ */
+typedef struct KPRF_TYPE(,FRAME)
+{
+    /** The accumulated overhead.
+     * Over head is accumulated by the parent frame when a child is poped off the stack. */
+    KU64                    OverheadTicks;
+    /** The current (top of stack) overhead. */
+    KU64                    CurOverheadTicks;
+    /** The accumulated sleep ticks.
+     * It's possible to notify the profiler that the thread is being put into a wait/sleep/yield
+     * state. The time spent sleeping is transfered to the parent frame when poping of a child one. */
+    KU64                    SleepTicks;
+    /** The start of the on-stack period. */
+    KU64                    OnStackStart;
+    /** The accumulated time on top (excludes overhead (sleep doesn't apply here obviously)). */
+    KU64                    OnTopOfStackTicks;
+    /** The start of the current on-top-of-stack period.
+     * This is also to mark the start of a sleeping period, the ResumeThread function will always
+     * treat it as the start of the suspend period. */
+    KU64                    OnTopOfStackStart;
+    /** The number of calls made from this stack frame. */
+    KU64                    cCalls;
+    /** Stack address of this frame.
+     * This is used to detect throw and longjmp, and is also used to deal with overflow. (relative address) */
+    KPRF_TYPE(,UPTR)        uFramePtr;
+    /** Offset (relative to the profiler header) to the function record.
+     * This is 0 if we're out of function space. */
+    KU32                    offFunction;
+} KPRF_TYPE(,FRAME);
+/** Pointer to a stack frame. */
+typedef KPRF_TYPE(,FRAME) *KPRF_TYPE(P,FRAME);
+/** Pointer to a const stack frame. */
+typedef const KPRF_TYPE(,FRAME) *KPRF_TYPE(PC,FRAME);
+
+
+/**
+ * Stack.
+ */
+typedef struct KPRF_TYPE(,STACK)
+{
+    /** The offset (relative to the profiler header) of the thread owning the stack.
+     * This is zero if not in use, and non-zero if in use. */
+    KU32                        offThread;
+    /** The number of active stack frames. */
+    KU32                        cFrames;
+    /** The stack frames.
+     * The actual size of this array is specified in the header. */
+    KPRF_TYPE(,FRAME)           aFrames[1];
+} KPRF_TYPE(,STACK);
+/** Pointer to a stack. */
+typedef KPRF_TYPE(,STACK) *KPRF_TYPE(P,STACK);
+/** Pointer to a const stack. */
+typedef const KPRF_TYPE(,STACK) *KPRF_TYPE(PC,STACK);
+
+
+/**
+ * The thread state.
+ */
+typedef enum KPRF_TYPE(,THREADSTATE)
+{
+    /** The thread hasn't been used yet. */
+    KPRF_TYPE(,THREADSTATE_UNUSED) = 0,
+    /** The thread is activly being profiled.
+     * A thread is added in the suspended state and then activated when
+     * starting to execute the first function.
+     */
+    KPRF_TYPE(,THREADSTATE_ACTIVE),
+    /** The thread is currently suspended from profiling.
+     * Upon entering profiler code the thread is suspended, it's reactivated
+     * upon normal return.
+     */
+    KPRF_TYPE(,THREADSTATE_SUSPENDED),
+    /** The thread is currently suspended due of stack overflow.
+     * When we overflow the stack frame array, the thread enter the overflow state. In this
+     * state nothing is profiled but we keep looking for the exit of the top frame. */
+    KPRF_TYPE(,THREADSTATE_OVERFLOWED),
+    /** The thread is terminated.
+     * When we received a thread termination notification the thread is unwinded, statistics
+     * updated and the state changed to terminated. A terminated thread cannot be revivied. */
+    KPRF_TYPE(,THREADSTATE_TERMINATED),
+
+    /** Ensure 32-bit size. */
+    KPRF_TYPE(,THREADSTATE_32BIT_HACK) = 0x7fffffff
+} KPRF_TYPE(,THREADSTATE);
+
+
+/**
+ * Thread statistics and stack.
+ */
+typedef struct KPRF_TYPE(,THREAD)
+{
+    /** The native thread id. */
+    KU64                        ThreadId;
+    /** The thread name. (optional) */
+    char                        szName[32];
+    /** The thread current thread state. */
+    KPRF_TYPE(,THREADSTATE)     enmState;
+    /** Alignment. */
+    KPRF_TYPE(,THREADSTATE)     Reserved0;
+    /** The base pointer of the thread stack. (relative address) */
+    KPRF_TYPE(,UPTR)            uStackBasePtr;
+    /** The maximum depth of the thread stack (bytes). */
+    KPRF_TYPE(,UPTR)            cbMaxStack;
+    /** The number of calls done by this thread. */
+    KU64                        cCalls;
+    /** The number of times the stack overflowed. */
+    KU64                        cOverflows;
+    /** The number of times stack entries has been rejected because of a stack switch. */
+    KU64                        cStackSwitchRejects;
+    /** The number of times the stack has been unwinded more than one frame. */
+    KU64                        cUnwinds;
+
+    /** The profiled ticks. (This does not include sleep or overhead ticks.)
+     * This is the accumulated on-stack values for the final stack frames. */
+    KU64                        ProfiledTicks;
+    /** The accumulated overhead of this thread. */
+    KU64                        OverheadTicks;
+    /** The accumulated sleep ticks for this thread.
+     * See KPRF_TYPE(,FRAME)::SleepTicks for details. */
+    KU64                        SleepTicks;
+
+    /** The offset of the stack. */
+    KU32                        offStack;
+} KPRF_TYPE(,THREAD);
+/** Pointer to a thread. */
+typedef KPRF_TYPE(,THREAD) *KPRF_TYPE(P,THREAD);
+/** Pointer to a const thread. */
+typedef const KPRF_TYPE(,THREAD) *KPRF_TYPE(PC,THREAD);
+
+
diff --git a/src/lib/kStuff/kProfiler2/prfcorefunction.cpp.h b/src/lib/kStuff/kProfiler2/prfcorefunction.cpp.h
new file mode 100644
index 0000000..686b452
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/prfcorefunction.cpp.h
@@ -0,0 +1,127 @@
+/* $Id: prfcorefunction.cpp.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kProfiler Mark 2 - Core NewFunction Code Template.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * Creates a new function.
+ *
+ * @returns Pointer to the new function.
+ * @returns NULL if we're out of space.
+ */
+static KPRF_TYPE(P,FUNC) KPRF_NAME(NewFunction)(KPRF_TYPE(P,HDR) pHdr,KPRF_TYPE(,UPTR) uPC)
+{
+    /*
+     * First find the position of the function (it might actually have been inserted by someone else by now too).
+     */
+    KPRF_FUNCS_WRITE_LOCK();
+
+    KPRF_TYPE(P,FUNC) paFunctions = KPRF_OFF2PTR(P,FUNC, pHdr->offFunctions, pHdr);
+    KI32 iStart = 0;
+    KI32 iLast  = pHdr->cFunctions - 1;
+    KI32 i      = iLast / 2;
+    for (;;)
+    {
+        KU32 iFunction = pHdr->aiFunctions[i];
+        KPRF_TYPE(,IPTR) iDiff = uPC - paFunctions[iFunction].uEntryPtr;
+        if (!iDiff)
+        {
+            KPRF_FUNCS_WRITE_UNLOCK();
+            return &paFunctions[iFunction];
+        }
+        if (iLast == iStart)
+            break;
+        if (iDiff < 0)
+            iLast = i - 1;
+        else
+            iStart = i + 1;
+        if (iLast < iStart)
+            break;
+        i = iStart + (iLast - iStart) / 2;
+    }
+
+    /*
+     * Adjust the index so we're exactly in the right spot.
+     * (I've too much of a headache to figure out if the above loop leaves us where we should be.)
+     */
+    const KI32 iNew = pHdr->cFunctions;
+    if (paFunctions[pHdr->aiFunctions[i]].uEntryPtr > uPC)
+    {
+        while (     i > 0
+               &&   paFunctions[pHdr->aiFunctions[i - 1]].uEntryPtr > uPC)
+            i--;
+    }
+    else
+    {
+        while (     i < iNew
+               &&   paFunctions[pHdr->aiFunctions[i]].uEntryPtr < uPC)
+            i++;
+    }
+
+    /*
+     * Ensure that there still is space for the function.
+     */
+    if (iNew >= (KI32)pHdr->cMaxFunctions)
+    {
+        KPRF_FUNCS_WRITE_UNLOCK();
+        return NULL;
+    }
+    pHdr->cFunctions++;
+    KPRF_TYPE(P,FUNC) pNew = &paFunctions[iNew];
+
+    /* init the new function entry */
+    pNew->uEntryPtr  = uPC;
+    pNew->offModSeg  = 0;
+    pNew->cOnStack   = 0;
+    pNew->cCalls     = 0;
+    pNew->OnStack.MinTicks      = ~(KU64)0;
+    pNew->OnStack.MaxTicks      = 0;
+    pNew->OnStack.SumTicks      = 0;
+    pNew->OnTopOfStack.MinTicks = ~(KU64)0;
+    pNew->OnTopOfStack.MaxTicks = 0;
+    pNew->OnTopOfStack.SumTicks = 0;
+
+    /* shift the function index array and insert the new one. */
+    KI32 j = iNew;
+    while (j > i)
+    {
+        pHdr->aiFunctions[j] = pHdr->aiFunctions[j - 1];
+        j--;
+    }
+    pHdr->aiFunctions[i] = iNew;
+    KPRF_FUNCS_WRITE_UNLOCK();
+
+    /*
+     * Record the module segment (i.e. add it if it's new).
+     */
+    pNew->offModSeg = KPRF_NAME(RecordModSeg)(pHdr, uPC);
+
+    return pNew;
+}
+
diff --git a/src/lib/kStuff/kProfiler2/prfcoreinit.cpp.h b/src/lib/kStuff/kProfiler2/prfcoreinit.cpp.h
new file mode 100644
index 0000000..5a94f46
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/prfcoreinit.cpp.h
@@ -0,0 +1,191 @@
+/* $Id: prfcoreinit.cpp.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kProfiler Mark 2 - Core Initialization Code Template.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * Calculates the size of the profiler data set.
+ *
+ * @returns The size of the data set in bytes.
+ *
+ * @param   cMaxFunctions       The max number of functions.
+ * @param   cbMaxModSeg         The max bytes for module segments.
+ * @param   cMaxThreads         The max number of threads.
+ * @param   cMaxStacks          The max number of stacks. (should be less or equal to the max number of threads)
+ * @param   cMaxStackFrames     The max number of frames on each of the stacks.
+ *
+ * @remark  This function does not input checks, it only aligns it. The caller is
+ *          responsible for the input to make some sense.
+ */
+KPRF_DECL_FUNC(KU32, CalcSize)(KU32 cMaxFunctions, KU32 cbMaxModSegs, KU32 cMaxThreads, KU32 cMaxStacks, KU32 cMaxStackFrames)
+{
+    /*
+     * Normalize input.
+     */
+    KPRF_SETMIN_ALIGN(cMaxFunctions, 16, 16);
+    KPRF_SETMIN_ALIGN(cbMaxModSegs, KPRF_SIZEOF(MODSEG), 32);
+    KPRF_SETMIN_ALIGN(cMaxThreads, 1, 1);
+    KPRF_SETMIN_ALIGN(cMaxStacks, 1, 1);
+    KPRF_SETMIN_ALIGN(cMaxStackFrames, 32, 32);
+
+    /*
+     * Calc the size from the input.
+     * We do not take overflows into account, stupid user means stupid result.
+     */
+    KU32 cb = KPRF_OFFSETOF(HDR, aiFunctions[cMaxFunctions]);
+    KU32 cbTotal = KPRF_ALIGN(cb, 32);
+
+    cb = cMaxFunctions * KPRF_SIZEOF(FUNC);
+    cbTotal += KPRF_ALIGN(cb, 32);
+
+    cbTotal += cbMaxModSegs;
+
+    cb = cMaxThreads * KPRF_SIZEOF(THREAD);
+    cbTotal += KPRF_ALIGN(cb, 32);
+
+    cb = cMaxStacks * KPRF_SIZEOF(STACK);
+    cbTotal += KPRF_ALIGN(cb, 32);
+
+    cb = cMaxStackFrames * cMaxStacks * KPRF_SIZEOF(FRAME);
+    cbTotal += KPRF_ALIGN(cb, 32);
+
+    return cbTotal;
+}
+
+
+/**
+ * Initializes the profiler data set.
+ *
+ * @returns Pointer to the initialized profiler header on success.
+ * @returns NULL if the input doesn't add up.
+ *
+ * @param   pvData              Where to initialize the profiler data set.
+ * @param   cbData              The size of the available data.
+ * @param   cMaxFunctions       The max number of functions.
+ * @param   cbMaxModSeg         The max bytes for module segments.
+ * @param   cMaxThreads         The max number of threads.
+ * @param   cMaxStacks          The max number of stacks. (should be less or equal to the max number of threads)
+ * @param   cMaxStackFrames     The max number of frames on each of the stacks.
+ *
+ */
+KPRF_DECL_FUNC(KPRF_TYPE(P,HDR), Init)(void *pvData, KU32 cbData, KU32 cMaxFunctions, KU32 cbMaxModSegs,
+                                       KU32 cMaxThreads, KU32 cMaxStacks, KU32 cMaxStackFrames)
+{
+    /*
+     * Normalize the input.
+     */
+    if (!pvData)
+        return NULL;
+    KPRF_SETMIN_ALIGN(cMaxFunctions, 16, 16);
+    KPRF_SETMIN_ALIGN(cbMaxModSegs, KPRF_SIZEOF(MODSEG), 32);
+    KPRF_SETMIN_ALIGN(cMaxThreads, 1, 1);
+    KPRF_SETMIN_ALIGN(cMaxStacks, 1, 1);
+    KPRF_SETMIN_ALIGN(cMaxStackFrames, 32, 32);
+
+    /*
+     * The header.
+     */
+    KU32 off = 0;
+    KU32 cb = KPRF_OFFSETOF(HDR, aiFunctions[cMaxFunctions]);
+    cb = KPRF_ALIGN(cb, 32);
+    if (cbData < off + cb || off > off + cb)
+        return NULL;
+    KPRF_TYPE(P,HDR) pHdr = (KPRF_TYPE(P,HDR))pvData;
+
+    /* the core header */
+    pHdr->u32Magic          = 0;        /* Set at the very end */
+    pHdr->cFormatBits       = KPRF_BITS;
+    pHdr->uBasePtr          = 0;        /* Can be set afterwards using SetBasePtr. */
+#if KPRF_BITS <= 16
+    pHdr->u16Reserved       = 0;
+#endif
+#if KPRF_BITS <= 32
+    pHdr->u32Reserved       = 0;
+#endif
+    pHdr->cb                = cbData;
+    pHdr->cbAllocated       = cbData;
+
+    /* functions */
+    off += cb;
+    cb = cMaxFunctions * KPRF_SIZEOF(FUNC);
+    cb = KPRF_ALIGN(cb, 32);
+    if (cbData < off + cb || off > off + cb)
+        return NULL;
+    pHdr->cMaxFunctions     = cMaxFunctions;
+    pHdr->cFunctions        = 0;
+    pHdr->offFunctions      = off;
+    pHdr->cbFunction        = KPRF_SIZEOF(FUNC);
+
+    /* modsegs */
+    off += cb;
+    cb = KPRF_ALIGN(cbMaxModSegs, 32);
+    if (cbData < off + cb || off > off + cb)
+        return NULL;
+    pHdr->cbMaxModSegs      = cbMaxModSegs;
+    pHdr->cbModSegs         = 0;
+    pHdr->offModSegs        = off;
+
+    /* threads */
+    off += cb;
+    cb = cMaxThreads * KPRF_SIZEOF(THREAD);
+    cb = KPRF_ALIGN(cb, 32);
+    if (cbData < off + cb || off > off + cb)
+        return NULL;
+    pHdr->cMaxThreads       = cMaxThreads;
+    pHdr->cThreads          = 0;
+    pHdr->offThreads        = off;
+    pHdr->cbThread          = KPRF_SIZEOF(THREAD);
+
+    /* stacks */
+    off += cb;
+    cb = cMaxStacks * KPRF_OFFSETOF(STACK, aFrames[cMaxStackFrames]);
+    cb = KPRF_ALIGN(cb, 32);
+    if (cbData < off + cb || off > off + cb)
+        return NULL;
+    pHdr->cMaxStacks        = cMaxStacks;
+    pHdr->cStacks           = 0;
+    pHdr->offStacks         = off;
+    pHdr->cbStack           = KPRF_OFFSETOF(STACK, aFrames[cMaxStackFrames]);
+    pHdr->cMaxStackFrames   = cMaxStackFrames;
+
+    /* commandline */
+    pHdr->offCommandLine    = 0;
+    pHdr->cchCommandLine    = 0;
+
+    /* the final size */
+    pHdr->cb                = off + cb;
+
+
+    /*
+     * Done.
+     */
+    pHdr->u32Magic = KPRF_TYPE(,HDR_MAGIC);
+    return pHdr;
+}
+
diff --git a/src/lib/kStuff/kProfiler2/prfcoremodseg.cpp.h b/src/lib/kStuff/kProfiler2/prfcoremodseg.cpp.h
new file mode 100644
index 0000000..32c6e24
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/prfcoremodseg.cpp.h
@@ -0,0 +1,197 @@
+/* $Id: prfcoremodseg.cpp.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kProfiler Mark 2 - Core Module Segment Code Template.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * Adds a module segment.
+ *
+ * @returns Offset to the module if existing or successfully added
+ * @returns 0 if not found.
+ *
+ * @param   pHdr        The profiler header.
+ * @param   pModSeg     Pointer to the module segment to insert (it's copied of course).
+ * @param   off         The offset into the modseg area which has been searched.
+ *                      (This is relative to the first moddule segment record (at pHdr->offModSegs).)
+ */
+static KU32 KPRF_NAME(InsertModSeg)(KPRF_TYPE(P,HDR) pHdr, KPRF_TYPE(PC,MODSEG) pModSeg, KU32 off)
+{
+    /*
+     * Lookup the module segment, inserting it if not found (and there is room).
+     */
+    for (;;)
+    {
+        if (off >= pHdr->cbModSegs)
+        {
+            /*
+             * It was the end, let's try insert it.
+             *
+             * This is where we lock the modseg stuff. The deal is that we
+             * serialize the actual inserting without blocking lookups. This
+             * means that we may end up with potential racing inserts, but
+             * unless there is a large amount of modules being profiled that's
+             * probably not going to be much of a problem. Anyway if we race,
+             * we'll simply have to search the new additions before we add our
+             * own stuff.
+             */
+            KPRF_MODSEGS_LOCK();
+            if (off >= pHdr->cbModSegs)
+            {
+                KU32 cbModSeg = KPRF_OFFSETOF(MODSEG, szPath[pModSeg->cchPath + 1]);
+                cbModSeg = KPRF_ALIGN(cbModSeg, KPRF_SIZEOF(UPTR));
+                if (off + cbModSeg <= pHdr->cbMaxModSegs)
+                {
+                    KPRF_TYPE(P,MODSEG) pNew = KPRF_OFF2PTR(P,MODSEG, off + pHdr->offModSegs, pHdr);
+                    pNew->uBasePtr          = pModSeg->uBasePtr;
+                    pNew->cbSegmentMinusOne = pModSeg->cbSegmentMinusOne;
+                    pNew->iSegment          = pModSeg->iSegment;
+                    pNew->fLoaded           = pModSeg->fLoaded;
+                    pNew->cchPath           = pModSeg->cchPath;
+
+                    KI32 iPath = pModSeg->cchPath;
+                    do  pNew->szPath[iPath] = pModSeg->szPath[iPath];
+                    while (--iPath >= 0);
+
+                    /* commit it */
+                    KPRF_ATOMIC_SET32(&pHdr->cbModSegs, off + cbModSeg);
+                    off += pHdr->offModSegs;
+                }
+                else
+                    off = 0;
+                KPRF_MODSEGS_UNLOCK();
+                return off;
+            }
+            KPRF_MODSEGS_UNLOCK();
+            /* someone raced us, check the new entries. */
+        }
+
+        /*
+         * Match?
+         */
+        KPRF_TYPE(PC,MODSEG) pCur = KPRF_OFF2PTR(P,MODSEG, off + pHdr->offModSegs, pHdr);
+        if (    pCur->uBasePtr          == pModSeg->uBasePtr
+            &&  pCur->fLoaded           == pModSeg->fLoaded
+            &&  pCur->cchPath           == pModSeg->cchPath
+            &&  pCur->iSegment          == pModSeg->iSegment
+            &&  pCur->cbSegmentMinusOne == pModSeg->cbSegmentMinusOne
+           )
+        {
+            KI32 iPath = pModSeg->cchPath;
+            for (;;)
+            {
+                if (!iPath--)
+                    return off + pHdr->offModSegs;
+                if (pModSeg->szPath[iPath] != pCur->szPath[iPath])
+                    break;
+            }
+            /* didn't match, continue searching */
+        }
+        KU32 cbCur = KPRF_OFFSETOF(MODSEG, szPath[pCur->cchPath + 1]);
+        off += KPRF_ALIGN(cbCur, KPRF_SIZEOF(UPTR));
+    }
+}
+
+
+/**
+ * Queries data for and inserts a new module segment.
+ *
+ *
+ * @returns Offset to the module if existing or successfully added
+ * @returns 0 if not found.
+ *
+ * @param   pHdr        The profiler header.
+ * @param   uPC         Address within the module.
+ * @param   off         The offset into the modseg area which has been searched.
+ *                      (This is relative to the first moddule segment record (at pHdr->offModSegs).)
+ */
+static KU32 KPRF_NAME(NewModSeg)(KPRF_TYPE(P,HDR) pHdr, KPRF_TYPE(,UPTR) uPC, KU32 off)
+{
+    /*
+     * Query the module name and object of the function.
+     */
+#pragma pack(1)
+    struct
+    {
+        KPRF_TYPE(,MODSEG) ModSeg;
+        char               szMorePath[260];
+    } s;
+#pragma pack()
+    if (KPRF_GET_MODSEG(uPC + pHdr->uBasePtr, s.ModSeg.szPath, sizeof(s.ModSeg.szPath) + sizeof(s.szMorePath),
+                        &s.ModSeg.iSegment, &s.ModSeg.uBasePtr, &s.ModSeg.cbSegmentMinusOne))
+        return 0;
+    s.ModSeg.uBasePtr -= pHdr->uBasePtr;
+    s.ModSeg.fLoaded = 1;
+    s.ModSeg.cchPath = 0;
+    while (s.ModSeg.szPath[s.ModSeg.cchPath])
+        s.ModSeg.cchPath++;
+
+    return KPRF_NAME(InsertModSeg)(pHdr, &s.ModSeg, off);
+}
+
+
+/**
+ * Record a module segment.
+ *
+ * This is an internal worker for recording a module segment when adding
+ * a new function.
+ *
+ * @returns Offset to the module if existing or successfully added
+ * @returns 0 if not found.
+ *
+ * @param   pHdr        The profiler header.
+ * @param   uPC         Address within the module.
+ */
+static KU32 KPRF_NAME(RecordModSeg)(KPRF_TYPE(P,HDR) pHdr, KPRF_TYPE(,UPTR) uPC)
+{
+    /*
+     * Lookup the module segment, inserting it if not found (and there is room).
+     */
+    KU32 off = 0;
+    KPRF_TYPE(PC,MODSEG) pCur = KPRF_OFF2PTR(P,MODSEG, pHdr->offModSegs, pHdr);
+    const KU32 cbModSegs = pHdr->cbModSegs;
+    for (;;)
+    {
+        /* done and not found? */
+        if (off >= cbModSegs)
+            return KPRF_NAME(NewModSeg)(pHdr, uPC, off);
+
+        /*
+         * Match?
+         */
+        if (    pCur->fLoaded
+            &&  uPC - pCur->uBasePtr <= pCur->cbSegmentMinusOne)
+            return off + pHdr->offModSegs;
+
+        KU32 cbCur = KPRF_OFFSETOF(MODSEG, szPath[pCur->cchPath + 1]);
+        cbCur = KPRF_ALIGN(cbCur, KPRF_SIZEOF(UPTR));
+        off += cbCur;
+        pCur = (KPRF_TYPE(PC,MODSEG))((KU8 *)pCur + cbCur);
+    }
+}
+
diff --git a/src/lib/kStuff/kProfiler2/prfcorepost.cpp.h b/src/lib/kStuff/kProfiler2/prfcorepost.cpp.h
new file mode 100644
index 0000000..84ea2b0
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/prfcorepost.cpp.h
@@ -0,0 +1,41 @@
+/* $Id: prfcorepost.cpp.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kProfiler Mark 2 - Core Post-Code Template.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * Clean up all our defines.
+ */
+#undef KPRF_OFFSETOF
+#undef KPRF_ALIGN
+#undef KPRF_SETMIN_ALIGN
+#undef KPRF_PTR2OFF
+#undef KPRF_OFF2PTREx
+#undef KPRF_OFF2PTR
+
diff --git a/src/lib/kStuff/kProfiler2/prfcorepre.cpp.h b/src/lib/kStuff/kProfiler2/prfcorepre.cpp.h
new file mode 100644
index 0000000..50f6b6a
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/prfcorepre.cpp.h
@@ -0,0 +1,202 @@
+/* $Id: prfcorepre.cpp.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kProfiler Mark 2 - Core Pre-Code Template.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/** @def KPRF_OFF2PTR
+ * Internal helper for converting a offset to a pointer.
+ * @internal
+ */
+#define KPRF_OFF2PTR(TypePrefix, TypeName, off, pHdr) \
+    ( (KPRF_TYPE(TypePrefix, TypeName)) ((off) + (KPRF_TYPE(,UPTR))pHdr) )
+
+/** @def KPRF_PTR2OFF
+ * Internal helper for converting a pointer to a offset.
+ * @internal
+ */
+#define KPRF_PTR2OFF(ptr, pHdr) \
+    ( (KPRF_TYPE(,UPTR))(ptr) - (KPRF_TYPE(,UPTR))(pHdr) )
+
+/** @def KPRF_ALIGN
+ * The usual align macro.
+ * @internal
+ */
+#define KPRF_ALIGN(n, align) ( ((n) + ( (align) - 1)) & ~((align) - 1) )
+
+/** @def KPRF_SETMIN_ALIGN
+ * Ensures a minimum and aligned value.
+ * @internal
+ */
+#define KPRF_SETMIN_ALIGN(n, min, align) \
+    do { \
+        if ((n) < (min)) \
+            (n) = (min); \
+        else { \
+            const KU32 u32 = ((n) + ( (align) - 1)) & ~((align) - 1); \
+            if (u32 >= (n)) \
+                (n) = u32; \
+        } \
+    } while (0)
+
+/** @def KPRF_OFFSETOF
+ * My usual extended OFFSETOF macro, except this returns KU32 and mangles the type name.
+ * @internal
+ */
+#define KPRF_OFFSETOF(kPrfType, Member) ( (KU32)(KUPTR)&((KPRF_TYPE(P,kPrfType))0)->Member )
+
+/** @def PRF_SIZEOF
+ * Size of a kPrf type.
+ * @internal
+ */
+#define KPRF_SIZEOF(kPrfType)       sizeof(KPRF_TYPE(,kPrfType))
+
+
+/** @def KPRF_NOW
+ * Gets the current timestamp.
+ */
+#ifndef KPRF_NOW
+# error "KPRF_NOW isn't defined!"
+#endif
+
+/** @def KRPF_IS_ACTIVE
+ * Checks if profiling is activated or not.
+ * The idea is to use some global variable for disabling and enabling
+ * profiling in order to deal with init/term issues.
+ */
+#ifndef KPRF_IS_ACTIVE
+# define KPRF_IS_ACTIVE()           1
+#endif
+
+/** @def KPRF_GET_HDR
+ * Gets the pointer to the profiler data header.
+ */
+#ifndef KPRF_GET_HDR
+# error "KPRF_GET_HDR isn't defined!"
+#endif
+
+/** @def KPRF_GET_THREADID
+ * Gets native thread id. This must be unique.
+ */
+#ifndef KPRF_GET_THREADID
+# error "KPRF_GET_THREADID isn't defined!"
+#endif
+
+/** @def KPRF_SET_THREAD
+ * Sets the pointer to the current thread so we can get to it
+ * without doing a linear search by thread id.
+ */
+#ifndef KPRF_SET_THREAD
+# error "KPRF_SET_THREAD isn't defined!"
+#endif
+
+/** @def KPRF_GET_THREAD
+ * Gets the pointer to the current thread as set by KPRF_SET_THREAD.
+ */
+#ifndef KPRF_GET_THREAD
+# error "KPRF_GET_THREAD isn't defined!"
+#endif
+
+/** @def KPRF_MODSEGS_LOCK
+ * Lock the module segment for updating.
+ */
+#ifndef KPRF_MODSEGS_LOCK
+# define KPRF_MODSEGS_LOCK()            do { } while (0)
+#endif
+
+/** @def KPRF_MODSEGS_UNLOCK
+ * Unlock the module segments.
+ */
+#ifndef KPRF_MODSEGS_UNLOCK
+# define KPRF_MODSEGS_UNLOCK()          do { } while (0)
+#endif
+
+/** @def KPRF_THREADS_LOCK
+ * Lock the threads for updating.
+ */
+#ifndef KPRF_THREADS_LOCK
+# define KPRF_THREADS_LOCK()            do { } while (0)
+#endif
+
+/** @def KPRF_THREADS_UNLOCK
+ * Unlock the threads.
+ */
+#ifndef KPRF_THREADS_UNLOCK
+# define KPRF_THREADS_UNLOCK()          do { } while (0)
+#endif
+
+/** @def KPRF_FUNCS_READ_LOCK
+ * Lock the functions for reading.
+ */
+#ifndef KPRF_FUNCS_READ_LOCK
+# define KPRF_FUNCS_READ_LOCK()         do { } while (0)
+#endif
+
+/** @def KPRF_FUNCS_READ_UNLOCK
+ * Releases a read lock on the functions.
+ */
+#ifndef KPRF_FUNCS_READ_UNLOCK
+# define KPRF_FUNCS_READ_UNLOCK()       do { } while (0)
+#endif
+
+/** @def KPRF_FUNCS_WRITE_LOCK
+ * Lock the functions for updating.
+ */
+#ifndef KPRF_FUNCS_WRITE_LOCK
+# define KPRF_FUNCS_WRITE_LOCK()        do { } while (0)
+#endif
+
+/** @def KPRF_FUNCS_WRITE_UNLOCK
+ * Releases a write lock on the functions.
+ */
+#ifndef KPRF_FUNCS_WRITE_UNLOCK
+# define KPRF_FUNCS_WRITE_UNLOCK()      do { } while (0)
+#endif
+
+
+/** @def KPRF_ATOMIC_SET32
+ * Atomically set a 32-bit value.
+ */
+#ifndef KPRF_ATOMIC_SET32
+# define KPRF_ATOMIC_SET32(pu32, u32)   do { *(pu32) = (u32); } while (0)
+#endif
+
+/** @def KPRF_ATOMIC_SET64
+ * Atomically (well, in a safe way) adds to a 64-bit value.
+ */
+#ifndef KPRF_ATOMIC_ADD64
+# define KPRF_ATOMIC_ADD64(pu64, u64)   do { *(pu64) += (u64); } while (0)
+#endif
+
+/** @def KPRF_ATOMIC_SET64
+ * Atomically (well, in a safe way) increments a 64-bit value.
+ */
+#ifndef KPRF_ATOMIC_INC64
+# define KPRF_ATOMIC_INC64(pu64)        KPRF_ATOMIC_ADD64(pu64, 1)
+#endif
+
diff --git a/src/lib/kStuff/kProfiler2/prfcorereloc.cpp.h b/src/lib/kStuff/kProfiler2/prfcorereloc.cpp.h
new file mode 100644
index 0000000..c7fc667
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/prfcorereloc.cpp.h
@@ -0,0 +1,47 @@
+/* $Id: prfcorereloc.cpp.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kProfiler Mark 2 - Core SetBasePtr Code Template.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * Set (or modify) the base pointer for the profiler.
+ *
+ * The purpose of the base pointer is to allow profiling of relocatable code. Set the
+ * base pointer right after initializing the data set, and update it when relocating
+ * the code (both by calling this function), and Bob's your uncle! :-)
+ *
+ * @param   pHdr        The header returned from the initializer.
+ * @param   uBasePtr    The new base pointer value.
+ */
+KPRF_DECL_FUNC(void, SetBasePtr)(KPRF_TYPE(P,HDR) pHdr, KPRF_TYPE(,UPTR) uBasePtr)
+{
+    pHdr->uBasePtr = uBasePtr;
+}
+
+
diff --git a/src/lib/kStuff/kProfiler2/prfcoreterm.cpp.h b/src/lib/kStuff/kProfiler2/prfcoreterm.cpp.h
new file mode 100644
index 0000000..561fcdf
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/prfcoreterm.cpp.h
@@ -0,0 +1,142 @@
+/* $Id: prfcoreterm.cpp.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kProfiler Mark 2 - Core Termination Code Template.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * Unwinds and terminates all the threads, and frees the stack space.
+ *
+ * @returns The new data set size. (pHdr->cb)
+ * @param   pHdr        The profiler data set header.
+ */
+KPRF_DECL_FUNC(KU32, TerminateAll)(KPRF_TYPE(P,HDR) pHdr)
+{
+    KU64 TS = KPRF_NOW();
+    if (!pHdr)
+        return 0;
+
+    /*
+     * Iterate the threads and terminate all which are non-terminated.
+     */
+    KPRF_TYPE(P,THREAD) paThread = KPRF_OFF2PTR(P,THREAD, pHdr->offThreads, pHdr);
+    for (KU32 i = 0; i < pHdr->cThreads; i++)
+    {
+        KPRF_TYPE(P,THREAD) pCur = &paThread[i];
+        switch (pCur->enmState)
+        {
+            /* these states needs no work. */
+            case KPRF_TYPE(,THREADSTATE_TERMINATED):
+            case KPRF_TYPE(,THREADSTATE_UNUSED):
+            default:
+                break;
+
+            /* these are active and requires unwinding.*/
+            case KPRF_TYPE(,THREADSTATE_ACTIVE):
+            case KPRF_TYPE(,THREADSTATE_SUSPENDED):
+            case KPRF_TYPE(,THREADSTATE_OVERFLOWED):
+                KPRF_NAME(TerminateThread)(pHdr, pCur, TS);
+                break;
+        }
+    }
+
+
+    /*
+     * Free the stacks.
+     */
+    if (pHdr->offStacks)
+    {
+        /* only if the stack is at the end of the data set. */
+        const KU32 cbStacks = KPRF_ALIGN(pHdr->cMaxStacks * pHdr->cbStack, 32);
+        if (pHdr->offStacks + cbStacks == pHdr->cb)
+            pHdr->cb -= cbStacks;
+        pHdr->offStacks = 0;
+    }
+
+    return pHdr->cb;
+}
+
+
+/**
+ * Sets the commandline.
+ *
+ * This is typically done after TerminateAll, when the stacks has
+ * been freed up and there is plenty free space.
+ *
+ * @returns The new data set size. (pHdr->cb)
+ * @param   pHdr        The profiler data set header.
+ * @param   cArgs       The number of arguments in the array.
+ * @param   papszArgs   Pointer to an array of arguments.
+ */
+KPRF_DECL_FUNC(KU32, SetCommandLine)(KPRF_TYPE(P,HDR) pHdr, unsigned cArgs, const char * const *papszArgs)
+{
+    if (!pHdr)
+        return 0;
+
+    /*
+     * Any space at all?
+     */
+    if (pHdr->cb + 16 > pHdr->cbAllocated) /* 16 bytes min */
+        return pHdr->cb;
+
+    /*
+     * Encode untill we run out of space.
+     */
+    pHdr->offCommandLine = pHdr->cb;
+    char *psz = (char *)pHdr + pHdr->cb;
+    char *pszMax = (char *)pHdr + pHdr->cbAllocated - 1;
+    for (unsigned i = 0; i < cArgs && psz + 7 < pszMax; i++)
+    {
+        if (i > 0)
+            *psz++ = ' ';
+        *psz++ = '\'';
+        const char *pszArg = papszArgs[i];
+        while (psz < pszMax)
+        {
+            char ch = *pszArg++;
+            if (!ch)
+                break;
+            if (ch == '\'')
+            {
+                if (psz + 1 >= pszMax)
+                    break;
+                *psz++ = '\\';
+            }
+            *psz++ = ch;
+        }
+        if (psz < pszMax)
+            *psz++ = '\'';
+    }
+    *psz++ = '\0';
+    pHdr->cb = psz - (char *)pHdr;
+    pHdr->cchCommandLine = pHdr->cb - pHdr->offCommandLine - 1;
+
+    return pHdr->cb;
+}
+
+
diff --git a/src/lib/kStuff/kProfiler2/prfreader.cpp.h b/src/lib/kStuff/kProfiler2/prfreader.cpp.h
new file mode 100644
index 0000000..412e289
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/prfreader.cpp.h
@@ -0,0 +1,1602 @@
+/* $Id: prfreader.cpp.h 77 2016-06-22 17:03:55Z bird $ */
+/** @file
+ * kProfiler Mark 2 - Reader Code Template.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * Validates the non-header parts of a data-set.
+ *
+ * @returns true if valid.
+ * @returns false if invalid. (written description to pOut)
+ *
+ * @param   pHdr        Pointer to the data set.
+ * @param   cb          The size of the data set.
+ * @param   pOut        Where to write error messages.
+ */
+static bool KPRF_NAME(IsValid)(KPRF_TYPE(PC,HDR) pHdr, KU32 cb, FILE *pOut)
+{
+    KPRF_TYPE(,UPTR) uMaxPtr = ~(KPRF_TYPE(,UPTR))0 - pHdr->uBasePtr;
+
+    /*
+     * Iterate the module segments.
+     */
+    KU32 off = pHdr->offModSegs;
+    while (off < pHdr->offModSegs + pHdr->cbModSegs)
+    {
+        KPRF_TYPE(PC,MODSEG) pCur = KPRF_OFF2PTR(PC,MODSEG, off, pHdr);
+        KU32 cbCur = KPRF_OFFSETOF(MODSEG, szPath[pCur->cchPath + 1]);
+        cbCur = KPRF_ALIGN(cbCur, KPRF_SIZEOF(UPTR));
+        if (cbCur + off > pHdr->offModSegs + pHdr->cbModSegs)
+        {
+            fprintf(pOut, "The module segment record at 0x%x is too long!\n", off);
+            return false;
+        }
+        if (pCur->uBasePtr > uMaxPtr)
+            fprintf(pOut, "warning: The module segment record at 0x%x has a too high base address.\n", off);
+
+        if (strlen(pCur->szPath) != pCur->cchPath)
+        {
+            fprintf(pOut, "The module segment record at 0x%x has an invalid path length 0x%x it the actual length is 0x%x\n",
+                    off, pCur->cchPath, strlen(pCur->szPath));
+            return false;
+        }
+
+        /* next */
+        off += cbCur;
+    }
+
+
+    /*
+     * Iterate the functions.
+     */
+    KPRF_TYPE(PC,FUNC) paFuncs = KPRF_OFF2PTR(PC,FUNC, pHdr->offFunctions, pHdr);
+    for (KU32 i = 0; i < pHdr->cFunctions; i++)
+    {
+        KPRF_TYPE(PC,FUNC) pCur = &paFuncs[i];
+        if (pCur->uEntryPtr > uMaxPtr)
+            fprintf(pOut, "warning: Function 0x%x has a too high base address.\n", i);
+        if (pCur->offModSeg)
+        {
+            if (    pCur->offModSeg < pHdr->offModSegs
+                ||  pCur->offModSeg >= pHdr->offModSegs + pHdr->cbModSegs
+                ||  pCur->offModSeg != KPRF_ALIGN(pCur->offModSeg, sizeof(pCur->uEntryPtr))
+               )
+            {
+                fprintf(pOut, "Function 0x%x has an invalid offModSeg value (0x%x).\n", i, pCur->offModSeg);
+                return false;
+            }
+            /** @todo more validation here.. */
+        }
+    }
+
+
+    /*
+     * Validate the threads.
+     */
+    KPRF_TYPE(PC,THREAD) paThreads = KPRF_OFF2PTR(PC,THREAD, pHdr->offThreads, pHdr);
+    for (KU32 i = 0; i < pHdr->cThreads; i++)
+    {
+        KPRF_TYPE(PC,THREAD) pCur = &paThreads[i];
+        if (pCur->uStackBasePtr > uMaxPtr)
+            fprintf(pOut, "warning: Thread 0x%x has a too high base address.\n", i);
+        switch (pCur->enmState)
+        {
+            case KPRF_TYPE(,THREADSTATE_ACTIVE):
+            case KPRF_TYPE(,THREADSTATE_SUSPENDED):
+            case KPRF_TYPE(,THREADSTATE_OVERFLOWED):
+            case KPRF_TYPE(,THREADSTATE_TERMINATED):
+                break;
+            default:
+                fprintf(pOut, "Thread 0x%x has an invalid state value (0x%x).\n", i, pCur->enmState);
+                return false;
+        }
+    }
+
+
+    return true;
+}
+
+
+/**
+ * Dumps a file of a particular format.
+ *
+ * @returns 0 on success. (you might want to check the pOut state)
+ * @returns -1 on failure.
+ *
+ * @param   pHdr        Pointer to the data set.
+ * @param   pOut        The output file. This is opened for text writing.
+ * @param   pReader     The reader object.
+ */
+static int KPRF_NAME(Dump)(KPRF_TYPE(PC,HDR) pHdr, FILE *pOut)
+{
+    /*
+     * Any commandline?
+     */
+    if (pHdr->offCommandLine)
+        fprintf(pOut,
+                "Commandline: %s (%d  bytes)\n",
+                (char *)KPRF_OFF2PTR(PC,MODSEG, pHdr->offCommandLine, pHdr), /* stupid, stupid, type hacking. */
+                pHdr->cchCommandLine);
+
+    /*
+     * Dump the module segments.
+     */
+    fprintf(pOut,
+            "Module Segments: off=0x%x 0x%x/0x%x (bytes)\n"
+            "----------------\n",
+            pHdr->offModSegs, pHdr->cbModSegs, pHdr->cbMaxModSegs);
+    KU32 off = pHdr->offModSegs;
+    while (off < pHdr->offModSegs + pHdr->cbModSegs)
+    {
+        KPRF_TYPE(PC,MODSEG) pCur = KPRF_OFF2PTR(PC,MODSEG, off, pHdr);
+        KU32 cbCur = KPRF_OFFSETOF(MODSEG, szPath[pCur->cchPath + 1]);
+        cbCur = KPRF_ALIGN(cbCur, KPRF_SIZEOF(UPTR));
+
+        fprintf(pOut,
+                "0x%04x: iSegment=0x%08x uBasePtr=%" KPRF_FMT_UPTR " szPath='%s' (%d bytes)\n",
+                off, pCur->iSegment, pCur->uBasePtr, pCur->szPath, pCur->cchPath);
+
+        /* next */
+        off += cbCur;
+    }
+    fprintf(pOut, "\n");
+
+    /*
+     * Dump the functions.
+     */
+    fprintf(pOut,
+            "Functions: off=0x%x 0x%x/0x%x\n"
+            "----------\n",
+            pHdr->offFunctions, pHdr->cFunctions, pHdr->cMaxFunctions);
+    KPRF_TYPE(PC,FUNC) paFuncs = KPRF_OFF2PTR(PC,FUNC, pHdr->offFunctions, pHdr);
+    for (KU32 i = 0; i < pHdr->cFunctions; i++)
+    {
+        KPRF_TYPE(PC,FUNC) pCur = &paFuncs[i];
+        fprintf(pOut, "0x%04x: uEntryPtr=%" KPRF_FMT_UPTR " cOnStack=0x%" KPRF_FMT_X64 " cCalls=0x%" KPRF_FMT_X64 "\n"
+                      "       OnStack={0x%" KPRF_FMT_X64 ", 0x%" KPRF_FMT_X64 ", 0x%" KPRF_FMT_X64 "}\n"
+                      "  OnTopOfStack={0x%" KPRF_FMT_X64 ", 0x%" KPRF_FMT_X64 ", 0x%" KPRF_FMT_X64 "}\n",
+                i, pCur->uEntryPtr, pCur->cOnStack, pCur->cCalls,
+                pCur->OnStack.MinTicks, pCur->OnStack.MaxTicks,  pCur->OnStack.SumTicks,
+                pCur->OnTopOfStack.MinTicks, pCur->OnTopOfStack.MaxTicks,  pCur->OnTopOfStack.SumTicks);
+        if (pCur->offModSeg)
+        {
+            KPRF_TYPE(PC,MODSEG) pModSeg = KPRF_OFF2PTR(PC,MODSEG, pCur->offModSeg, pHdr);
+            fprintf(pOut, "  offModSeg=0x%08x iSegment=0x%02x uBasePtr=%" KPRF_FMT_UPTR " szPath='%s' (%d bytes)\n",
+                    pCur->offModSeg, pModSeg->iSegment, pModSeg->uBasePtr, pModSeg->szPath, pModSeg->cchPath);
+
+#if 1
+            PKDBGMOD pMod;
+            int rc = kDbgModuleOpen(&pMod, pModSeg->szPath, NULL /* pLdrMod */);
+            if (!rc)
+            {
+                KDBGSYMBOL Sym;
+                rc = kDbgModuleQuerySymbol(pMod, pModSeg->iSegment, pCur->uEntryPtr - pModSeg->uBasePtr, &Sym);
+                if (!rc)
+                {
+                    fprintf(pOut, "  %s\n", Sym.szName);
+                }
+                kDbgModuleClose(pMod);
+            }
+#endif
+
+        }
+    }
+    fprintf(pOut, "\n");
+
+    /*
+     * Dump the threads.
+     */
+    fprintf(pOut,
+            "Threads: off=0x%x 0x%x/0x%x (Stacks=0x%x/0x%x cMaxStackFrames=0x%x)\n"
+            "--------\n",
+            pHdr->offThreads, pHdr->cThreads, pHdr->cMaxThreads, pHdr->cStacks, pHdr->cMaxStacks, pHdr->cMaxStackFrames);
+    KPRF_TYPE(PC,THREAD) paThreads = KPRF_OFF2PTR(PC,THREAD, pHdr->offThreads, pHdr);
+    for (KU32 i = 0; i < pHdr->cThreads; i++)
+    {
+        KPRF_TYPE(PC,THREAD) pCur = &paThreads[i];
+        fprintf(pOut,
+                "0x%02x: ThreadId=0x%08" KPRF_FMT_X64 " enmState=%d szName='%s'\n"
+                "  uStackBasePtr=%" KPRF_FMT_UPTR " cbMaxStack=%" KPRF_FMT_UPTR "\n"
+                "  cCalls=0x%" KPRF_FMT_X64 " cOverflows=0x%" KPRF_FMT_X64 " cStackSwitchRejects=0x%" KPRF_FMT_X64 "\n"
+                "  cUnwinds=0x%" KPRF_FMT_X64 " ProfiledTicks=0x%" KPRF_FMT_X64 " OverheadTicks=0x%" KPRF_FMT_X64 "\n",
+                i, pCur->ThreadId, pCur->enmState, pCur->szName,
+                pCur->uStackBasePtr, pCur->cbMaxStack,
+                pCur->cCalls, pCur->cOverflows, pCur->cStackSwitchRejects,
+                pCur->cUnwinds, pCur->ProfiledTicks, pCur->OverheadTicks);
+    }
+
+    return 0;
+}
+
+
+/** Pointer to a report module.
+ * @internal */
+typedef struct KPRF_TYPE(,REPORTMOD) *KPRF_TYPE(P,REPORTMOD);
+/** Pointer to a report module segment.
+ * @internal */
+typedef struct KPRF_TYPE(,REPORTMODSEG) *KPRF_TYPE(P,REPORTMODSEG);
+
+
+/**
+ * A report module segment.
+ *
+ * @internal
+ */
+typedef struct KPRF_TYPE(,REPORTMODSEG)
+{
+    /** AVL node core. The key is the data set offset of the module segment record. */
+    KDBGADDR                    offSegment;
+    struct KPRF_TYPE(,REPORTMODSEG) *mpLeft;    /**< AVL left branch. */
+    struct KPRF_TYPE(,REPORTMODSEG) *mpRight;   /**< AVL rigth branch. */
+    /** Pointer to the next segment for the module. */
+    KPRF_TYPE(P,REPORTMODSEG)   pNext;
+    /** Pointer to the module segment data in the data set. */
+    KPRF_TYPE(PC,MODSEG)        pModSeg;
+    /** Pointer to the module this segment belongs to. */
+    KPRF_TYPE(P,REPORTMOD)      pMod;
+    /** The time this segment has spent on the stack.. */
+    KU64                        OnStackTicks;
+    /** The time this segment has spent on the top of the stack.. */
+    KU64                        OnTopOfStackTicks;
+    /** The number of profiled functions from this segment. */
+    KU32                        cFunctions;
+    KU8                         mHeight;        /**< AVL Subtree height. */
+} KPRF_TYPE(,REPORTMODSEG), *KPRF_TYPE(P,REPORTMODSEG);
+
+
+/**
+ * A report module segment.
+ *
+ * @internal
+ */
+typedef struct KPRF_TYPE(,REPORTMOD)
+{
+    /** The module number. */
+    KU32                        iMod;
+    /** Pointer to the next module in the list. */
+    KPRF_TYPE(P,REPORTMOD)      pNext;
+    /** Pointer to the list of segments belonging to this module. */
+    KPRF_TYPE(P,REPORTMODSEG)   pFirstSeg;
+    /** The debug module handle. */
+    PKDBGMOD                    pDbgMod;
+    /** The time this segment has spent on the stack.. */
+    KU64                        OnStackTicks;
+    /** The time this segment has spent on the top of the stack.. */
+    KU64                        OnTopOfStackTicks;
+    /** The number of profiled functions from this segment. */
+    KU32                        cFunctions;
+} KPRF_TYPE(,REPORTMOD), *KPRF_TYPE(P,REPORTMOD);
+
+
+/**
+ * A report function.
+ *
+ * @internal
+ */
+typedef struct KPRF_TYPE(,REPORTFUNC)
+{
+    /** Pointer to the function data in the data set. */
+    KPRF_TYPE(PC,FUNC)          pFunc;
+    /** Pointer to the module segment this function belongs to. (can be NULL) */
+    KPRF_TYPE(P,REPORTMODSEG)   pModSeg;
+    /** Pointer to the function symbol. */
+    PKDBGSYMBOL                 pSym;
+    /** Pointer to the function line number. */
+    PKDBGLINE                   pLine;
+} KPRF_TYPE(,REPORTFUNC), *KPRF_TYPE(P,REPORTFUNC);
+
+
+/**
+ * Compares two REPROTFUNC records to determin which has the higher on-stack time.
+ */
+static int KPRF_NAME(FuncCompareOnStack)(const void *pv1, const void *pv2)
+{
+    KPRF_TYPE(PC,FUNC) p1 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv1)->pFunc;
+    KPRF_TYPE(PC,FUNC) p2 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv2)->pFunc;
+    if (p1->OnStack.SumTicks > p2->OnStack.SumTicks)
+        return -1;
+    if (p1->OnStack.SumTicks < p2->OnStack.SumTicks)
+        return 1;
+    if (p1->OnStack.MaxTicks > p2->OnStack.MaxTicks)
+        return -1;
+    if (p1->OnStack.MaxTicks < p2->OnStack.MaxTicks)
+        return 1;
+    if (p1->OnStack.MinTicks > p2->OnStack.MinTicks)
+        return -1;
+    if (p1->OnStack.MinTicks < p2->OnStack.MinTicks)
+        return 1;
+    if (p1 < p2)
+        return -1;
+    return 1;
+}
+
+
+/**
+ * Compares two REPROTFUNC records to determin which has the higher on-stack average time.
+ */
+static int KPRF_NAME(FuncCompareOnStackAvg)(const void *pv1, const void *pv2)
+{
+    KPRF_TYPE(PC,FUNC) p1 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv1)->pFunc;
+    KPRF_TYPE(PC,FUNC) p2 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv2)->pFunc;
+    if (p1->OnStack.SumTicks / p1->cOnStack > p2->OnStack.SumTicks / p2->cOnStack)
+        return -1;
+    if (p1->OnStack.SumTicks / p1->cOnStack < p2->OnStack.SumTicks / p2->cOnStack)
+        return 1;
+    return KPRF_NAME(FuncCompareOnStack)(pv1, pv2);
+}
+
+
+/**
+ * Compares two REPROTFUNC records to determin which has the higher on-stack min time.
+ */
+static int KPRF_NAME(FuncCompareOnStackMin)(const void *pv1, const void *pv2)
+{
+    KPRF_TYPE(PC,FUNC) p1 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv1)->pFunc;
+    KPRF_TYPE(PC,FUNC) p2 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv2)->pFunc;
+    if (p1->OnStack.MinTicks > p2->OnStack.MinTicks)
+        return -1;
+    if (p1->OnStack.MinTicks < p2->OnStack.MinTicks)
+        return 1;
+    return KPRF_NAME(FuncCompareOnStack)(pv1, pv2);
+}
+
+
+/**
+ * Compares two REPROTFUNC records to determin which has the higher on-stack max time.
+ */
+static int KPRF_NAME(FuncCompareOnStackMax)(const void *pv1, const void *pv2)
+{
+    KPRF_TYPE(PC,FUNC) p1 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv1)->pFunc;
+    KPRF_TYPE(PC,FUNC) p2 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv2)->pFunc;
+    if (p1->OnStack.MaxTicks > p2->OnStack.MaxTicks)
+        return -1;
+    if (p1->OnStack.MaxTicks < p2->OnStack.MaxTicks)
+        return 1;
+    return KPRF_NAME(FuncCompareOnStack)(pv1, pv2);
+}
+
+
+/**
+ * Compares two REPROTFUNC records to determin which has the higher on-stack time.
+ */
+static int KPRF_NAME(FuncCompareOnTopOfStack)(const void *pv1, const void *pv2)
+{
+    KPRF_TYPE(PC,FUNC) p1 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv1)->pFunc;
+    KPRF_TYPE(PC,FUNC) p2 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv2)->pFunc;
+    if (p1->OnTopOfStack.SumTicks > p2->OnTopOfStack.SumTicks)
+        return -1;
+    if (p1->OnTopOfStack.SumTicks < p2->OnTopOfStack.SumTicks)
+        return 1;
+    if (p1->OnTopOfStack.MaxTicks > p2->OnTopOfStack.MaxTicks)
+        return -1;
+    if (p1->OnTopOfStack.MaxTicks < p2->OnTopOfStack.MaxTicks)
+        return 1;
+    if (p1->OnTopOfStack.MinTicks > p2->OnTopOfStack.MinTicks)
+        return -1;
+    if (p1->OnTopOfStack.MinTicks < p2->OnTopOfStack.MinTicks)
+        return 1;
+    if (p1 < p2)
+        return -1;
+    return 1;
+}
+
+
+/**
+ * Compares two REPROTFUNC records to determin which has the higher on-stack average time.
+ */
+static int KPRF_NAME(FuncCompareOnTopOfStackAvg)(const void *pv1, const void *pv2)
+{
+    KPRF_TYPE(PC,FUNC) p1 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv1)->pFunc;
+    KPRF_TYPE(PC,FUNC) p2 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv2)->pFunc;
+    if (p1->OnTopOfStack.SumTicks / p1->cOnStack > p2->OnTopOfStack.SumTicks / p2->cOnStack)
+        return -1;
+    if (p1->OnTopOfStack.SumTicks / p1->cOnStack < p2->OnTopOfStack.SumTicks / p2->cOnStack)
+        return 1;
+    return KPRF_NAME(FuncCompareOnTopOfStack)(pv1, pv2);
+}
+
+
+/**
+ * Compares two REPROTFUNC records to determin which has the higher on-stack min time.
+ */
+static int KPRF_NAME(FuncCompareOnTopOfStackMin)(const void *pv1, const void *pv2)
+{
+    KPRF_TYPE(PC,FUNC) p1 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv1)->pFunc;
+    KPRF_TYPE(PC,FUNC) p2 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv2)->pFunc;
+    if (p1->OnTopOfStack.MinTicks > p2->OnTopOfStack.MinTicks)
+        return -1;
+    if (p1->OnTopOfStack.MinTicks < p2->OnTopOfStack.MinTicks)
+        return 1;
+    return KPRF_NAME(FuncCompareOnTopOfStack)(pv1, pv2);
+}
+
+
+/**
+ * Compares two REPROTFUNC records to determin which has the higher on-stack min time.
+ */
+static int KPRF_NAME(FuncCompareOnTopOfStackMax)(const void *pv1, const void *pv2)
+{
+    KPRF_TYPE(PC,FUNC) p1 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv1)->pFunc;
+    KPRF_TYPE(PC,FUNC) p2 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv2)->pFunc;
+    if (p1->OnTopOfStack.MaxTicks > p2->OnTopOfStack.MaxTicks)
+        return -1;
+    if (p1->OnTopOfStack.MaxTicks < p2->OnTopOfStack.MaxTicks)
+        return 1;
+    return KPRF_NAME(FuncCompareOnTopOfStack)(pv1, pv2);
+}
+
+
+/**
+ * Compares two REPROTFUNC records to determin which has the higher call to count.
+ */
+static int KPRF_NAME(FuncCompareCallsTo)(const void *pv1, const void *pv2)
+{
+    KPRF_TYPE(PC,FUNC) p1 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv1)->pFunc;
+    KPRF_TYPE(PC,FUNC) p2 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv2)->pFunc;
+    if (p1->cOnStack > p2->cOnStack)
+        return -1;
+    if (p1->cOnStack < p2->cOnStack)
+        return 1;
+    return KPRF_NAME(FuncCompareOnStack)(pv1, pv2);
+}
+
+
+/**
+ * Compares two REPROTFUNC records to determin which has the higher call from count.
+ */
+static int KPRF_NAME(FuncCompareCallsFrom)(const void *pv1, const void *pv2)
+{
+    KPRF_TYPE(PC,FUNC) p1 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv1)->pFunc;
+    KPRF_TYPE(PC,FUNC) p2 = (*(KPRF_TYPE(P,REPORTFUNC) *)pv2)->pFunc;
+    if (p1->cCalls > p2->cCalls)
+        return -1;
+    if (p1->cCalls < p2->cCalls)
+        return 1;
+    return KPRF_NAME(FuncCompareOnTopOfStack)(pv1, pv2);
+}
+
+
+/**
+ * A report thread.
+ *
+ * @internal
+ */
+typedef struct KPRF_TYPE(,REPORTTHREAD)
+{
+    /** Pointer to the thread data in the data set. */
+    KPRF_TYPE(PC,THREAD)        pThread;
+} KPRF_TYPE(,REPORTTHREAD), *KPRF_TYPE(P,REPORTTHREAD);
+
+
+/**
+ * Data-set analysis report.
+ *
+ * This is an internal structure to store temporary data between the
+ * analysis stage and the priting state.
+ *
+ * @internal
+ */
+typedef struct KPRF_TYPE(,REPORT)
+{
+    /** Pointer to the data set. */
+    KPRF_TYPE(PC,HDR)           pHdr;
+
+    /** @name Data-set item wrappers.
+     * @{ */
+    /** Pointer to the array of threads. */
+    KPRF_TYPE(P,REPORTTHREAD)   paThreads;
+    /** Pointer to the array of functions. */
+    KPRF_TYPE(P,REPORTFUNC)     paFunctions;
+    /** Pointer to the head of the module list. */
+    KPRF_TYPE(P,REPORTMOD)      pFirstMod;
+    /** The number of modules in the list. */
+    KU32                        cMods;
+    /** The module segment tree. (Only kAvl cares about this.) */
+    KPRF_TYPE(P,REPORTMODSEG)   pModSegTree;
+    /** The number of module segments in the tree. */
+    KU32                        cModSegs;
+    /** @} */
+
+    /** @name Sorting.
+     * @{ */
+    /** Pointer to the array of threads. */
+    KPRF_TYPE(P,REPORTTHREAD)  *papSortedThreads;
+    /** Pointer to the array of functions. */
+    KPRF_TYPE(P,REPORTFUNC)    *papSortedFunctions;
+    /** @} */
+
+    /** @name Accumulated Thread Data.
+     * @{ */
+    /** Sum of the profiled ticks. */
+    KU64                        ProfiledTicks;
+    /** Sum of the overhead ticks. */
+    KU64                        OverheadTicks;
+    /** Sum of the sleep ticks. */
+    KU64                        SleepTicks;
+    /** Sum of calls performed. */
+    KU64                        cCalls;
+    /** @} */
+
+} KPRF_TYPE(,REPORT), *KPRF_TYPE(P,REPORT), **KPRF_TYPE(PP,REPORT);
+
+
+/* Instantiate the AVL tree code. */
+#define KAVL_CHECK_FOR_EQUAL_INSERT
+#define KAVL_MAX_STACK          32
+#define KAVL_STD_KEY_COMP
+#define mKey                    offSegment
+#define KAVLKEY                 KDBGADDR
+#define KAVLNODE                KPRF_TYPE(,REPORTMODSEG)
+#define mpRoot                  pModSegTree
+#define KAVLROOT                KPRF_TYPE(,REPORT)
+#define KAVL_FN(name)           KPRF_NAME(ReportTree ## name)
+#define KAVL_TYPE(prefix,name)  KPRF_TYPE(prefix, REPORTMODESEG ## name)
+#define KAVL_INT(name)          KPRF_NAME(REPORTMODESEGINT ## name)
+#define KAVL_DECL(type)         K_DECL_INLINE(type)
+#include <k/kAvlTmpl/kAvlBase.h>
+#include <k/kAvlTmpl/kAvlDestroy.h>
+#include <k/kAvlTmpl/kAvlGet.h>
+#include <k/kAvlTmpl/kAvlUndef.h>
+
+
+/**
+ * Allocates and initializes a report.
+ *
+ * @returns Pointer to the report on success.
+ * @returns NULL on failure.
+ */
+static KPRF_TYPE(P,REPORT) KPRF_NAME(NewReport)(KPRF_TYPE(PC,HDR) pHdr)
+{
+    /*
+     * Allocate memory for the report.
+     * Everything but the mods and modsegs is allocated in the same block as the report.
+     */
+    KSIZE cb = KPRF_ALIGN(KPRF_SIZEOF(REPORT), 32);
+    KUPTR offThreads = cb;
+    cb += KPRF_ALIGN(KPRF_SIZEOF(REPORTTHREAD) * pHdr->cThreads, 32);
+    KUPTR offFunctions = cb;
+    cb += KPRF_ALIGN(KPRF_SIZEOF(REPORTFUNC) * pHdr->cFunctions, 32);
+    KUPTR offSortedThreads = cb;
+    cb += KPRF_ALIGN(sizeof(KPRF_TYPE(P,REPORTTHREAD)) * pHdr->cThreads, 32);
+    KUPTR offSortedFunctions = cb;
+    cb += KPRF_ALIGN(sizeof(KPRF_TYPE(P,REPORTFUNC)) * pHdr->cFunctions, 32);
+    KPRF_TYPE(P,REPORT) pReport = (KPRF_TYPE(P,REPORT))malloc(cb);
+    if (!pReport)
+        return NULL;
+
+    /*
+     * Initialize it.
+     */
+    pReport->pHdr = pHdr;
+    pReport->paThreads = (KPRF_TYPE(P,REPORTTHREAD))((KU8 *)pReport + offThreads);
+    pReport->paFunctions = (KPRF_TYPE(P,REPORTFUNC))((KU8 *)pReport + offFunctions);
+    pReport->pFirstMod = NULL;
+    pReport->cMods = 0;
+    KPRF_NAME(ReportTreeInit)(pReport);
+    pReport->cModSegs = 0;
+    pReport->papSortedThreads = (KPRF_TYPE(P,REPORTTHREAD) *)((KU8 *)pReport + offSortedThreads);
+    pReport->papSortedFunctions = (KPRF_TYPE(P,REPORTFUNC) *)((KU8 *)pReport + offSortedFunctions);
+    pReport->ProfiledTicks = 0;
+    pReport->OverheadTicks = 0;
+    pReport->SleepTicks = 0;
+    pReport->cCalls = 0;
+
+    return pReport;
+}
+
+
+/**
+ * AVL callback for deleting a module segment node.
+ *
+ * @returns 0
+ * @param   pCore       The tree node to delete.
+ * @param   pvParam     User parameter, ignored.
+ */
+static int KPRF_NAME(DeleteModSeg)(KPRF_TYPE(P,REPORTMODSEG) pCore, void *pvParam)
+{
+    free(pCore);
+    return 0;
+}
+
+
+/**
+ * Releases all the resources held be a report.
+ *
+ * @param   pReport     The report to delete.
+ */
+static void KPRF_NAME(DeleteReport)(KPRF_TYPE(P,REPORT) pReport)
+{
+    /*
+     * The list and AVL.
+     */
+    while (pReport->pFirstMod)
+    {
+        KPRF_TYPE(P,REPORTMOD) pFree = pReport->pFirstMod;
+        pReport->pFirstMod = pFree->pNext;
+        kDbgModuleClose(pFree->pDbgMod);
+        free(pFree);
+    }
+
+    KPRF_NAME(ReportTreeDestroy)(pReport, KPRF_NAME(DeleteModSeg), NULL);
+
+    /*
+     * The function debug info.
+     */
+    KU32 i = pReport->pHdr->cFunctions;
+    while (i-- > 0)
+    {
+        kDbgSymbolFree(pReport->paFunctions[i].pSym);
+        kDbgLineFree(pReport->paFunctions[i].pLine);
+    }
+
+    /*
+     * The report it self.
+     */
+    pReport->pHdr = NULL;
+    free(pReport);
+}
+
+
+/**
+ * Builds the module segment tree and the list of modules.
+ *
+ * @returns 0 on success.
+ * @returns -1 on failure.
+ * @param   pReport     The report to work on.
+ */
+static int KPRF_NAME(AnalyzeModSegs)(KPRF_TYPE(P,REPORT) pReport)
+{
+    const KU32 offEnd = pReport->pHdr->offModSegs + pReport->pHdr->cbModSegs;
+    KU32 off = pReport->pHdr->offModSegs;
+    while (off < offEnd)
+    {
+        KPRF_TYPE(PC,MODSEG) pCur = KPRF_OFF2PTR(PC,MODSEG, off, pReport->pHdr);
+        KU32 cbCur = KPRF_OFFSETOF(MODSEG, szPath[pCur->cchPath + 1]);
+        cbCur = KPRF_ALIGN(cbCur, KPRF_SIZEOF(UPTR));
+
+        /*
+         * Create a new modseg record.
+         */
+        KPRF_TYPE(P,REPORTMODSEG) pSeg = (KPRF_TYPE(P,REPORTMODSEG))malloc(sizeof(*pSeg));
+        if (!pSeg)
+            return -1;
+
+        pSeg->offSegment = off;
+        pSeg->pModSeg = pCur;
+        pSeg->pMod = NULL; /* below */
+        pSeg->OnStackTicks = 0;
+        pSeg->OnTopOfStackTicks = 0;
+        pSeg->cFunctions = 0;
+
+        if (!KPRF_NAME(ReportTreeInsert)(pReport, pSeg))
+        {
+            free(pSeg);
+            return -1;
+        }
+        pReport->cModSegs++;
+
+        /*
+         * Search for the module record.
+         */
+        KPRF_TYPE(P,REPORTMOD) pMod = pReport->pFirstMod;
+        while (     pMod
+               &&   (   pMod->pFirstSeg->pModSeg->cchPath != pCur->cchPath
+                     || memcmp(pMod->pFirstSeg->pModSeg->szPath, pCur->szPath, pCur->cchPath)))
+            pMod = pMod->pNext;
+        if (pMod)
+        {
+            /** @todo sort segments */
+            pSeg->pMod = pMod;
+            pSeg->pNext = pMod->pFirstSeg;
+            pMod->pFirstSeg = pSeg;
+        }
+        else
+        {
+            KPRF_TYPE(P,REPORTMOD) pMod = (KPRF_TYPE(P,REPORTMOD))malloc(sizeof(*pMod) + pCur->cchPath);
+            if (!pMod)
+                return -1;
+            pSeg->pMod = pMod;
+            pSeg->pNext = NULL;
+            pMod->iMod = pReport->cMods++;
+            pMod->pNext = pReport->pFirstMod;
+            pReport->pFirstMod = pMod;
+            pMod->pFirstSeg = pSeg;
+            pMod->pDbgMod = NULL;
+            pMod->OnStackTicks = 0;
+            pMod->OnTopOfStackTicks = 0;
+            pMod->cFunctions = 0;
+
+            int rc = kDbgModuleOpen(&pMod->pDbgMod, pSeg->pModSeg->szPath, NULL /* kLdrMod */);
+            if (rc)
+                pMod->pDbgMod = NULL;
+        }
+
+        /* next */
+        off += cbCur;
+    }
+
+    return 0;
+}
+
+
+/**
+ * Initializes the function arrays.
+ *
+ * @returns 0 on success.
+ * @returns -1 on failure.
+ * @param   pReport     The report to work on.
+ */
+static int KPRF_NAME(AnalyseFunctions)(KPRF_TYPE(P,REPORT) pReport)
+{
+    KU32 iFunc = pReport->pHdr->cFunctions;
+    KPRF_TYPE(PC,FUNC) pFunc = KPRF_OFF2PTR(PC,FUNC, pReport->pHdr->offFunctions + iFunc * sizeof(*pFunc), pReport->pHdr);
+    KPRF_TYPE(P,REPORTFUNC) pReportFunc = &pReport->paFunctions[iFunc];
+    while (iFunc-- > 0)
+    {
+        pFunc--;
+        pReportFunc--;
+
+        pReport->papSortedFunctions[iFunc] = pReportFunc;
+        pReportFunc->pFunc = pFunc;
+        pReportFunc->pModSeg = KPRF_NAME(ReportTreeGet)(pReport, pFunc->offModSeg);
+        pReportFunc->pSym = NULL;
+        pReportFunc->pLine = NULL;
+        if (pReportFunc->pModSeg)
+        {
+            /* Collect module segment and module statistics. */
+            KPRF_TYPE(P,REPORTMODSEG) pModSeg = pReportFunc->pModSeg;
+            pModSeg->cFunctions++;
+            pModSeg->OnStackTicks += pFunc->OnStack.SumTicks;
+            pModSeg->OnTopOfStackTicks += pFunc->OnTopOfStack.SumTicks;
+
+            KPRF_TYPE(P,REPORTMOD) pMod = pModSeg->pMod;
+            pMod->cFunctions++;
+            pMod->OnStackTicks += pFunc->OnStack.SumTicks;
+            pMod->OnTopOfStackTicks += pFunc->OnTopOfStack.SumTicks;
+
+            /* Get debug info. */
+            KDBGADDR offSegment = pFunc->uEntryPtr - pModSeg->pModSeg->uBasePtr;
+            int rc = kDbgModuleQuerySymbolA(pMod->pDbgMod, pModSeg->pModSeg->iSegment, offSegment, &pReportFunc->pSym);
+            /** @todo check displacement! */
+            if (rc)
+                pReportFunc->pSym = NULL;
+            rc = kDbgModuleQueryLineA(pMod->pDbgMod, pModSeg->pModSeg->iSegment, offSegment, &pReportFunc->pLine);
+            if (rc)
+                pReportFunc->pLine = NULL;
+        }
+    }
+    return 0;
+}
+
+
+/**
+ * Initializes the thread arrays.
+ *
+ * @returns 0 on success.
+ * @returns -1 on failure.
+ * @param   pReport     The report to work on.
+ */
+static int KPRF_NAME(AnalyseThreads)(KPRF_TYPE(P,REPORT) pReport)
+{
+    KU32 iThread = pReport->pHdr->cThreads;
+    KPRF_TYPE(PC,THREAD) pThread = KPRF_OFF2PTR(PC,THREAD, pReport->pHdr->offThreads + iThread * sizeof(*pThread), pReport->pHdr);
+    KPRF_TYPE(P,REPORTTHREAD) pReportThread = &pReport->paThreads[iThread];
+    while (iThread-- > 0)
+    {
+        pThread--;
+        pReportThread--;
+
+        pReport->papSortedThreads[iThread] = pReportThread;
+        pReportThread->pThread = pThread;
+
+        /* collect statistics */
+        pReport->ProfiledTicks += pThread->ProfiledTicks;
+        pReport->OverheadTicks += pThread->OverheadTicks;
+        pReport->SleepTicks += pThread->SleepTicks;
+        pReport->cCalls += pThread->cCalls;
+
+    }
+    return 0;
+}
+
+
+/**
+ * Analyses the data set, producing a report.
+ *
+ * @returns 0 on success.
+ * @returns -1 on failure.
+ *
+ * @param   pHdr        The data set.
+ * @param   ppReport    Where to store the report.
+ */
+static int KPRF_NAME(Analyse)(KPRF_TYPE(PC,HDR) pHdr, KPRF_TYPE(PP,REPORT) ppReport)
+{
+    *ppReport = NULL;
+
+    /* allocate it */
+    KPRF_TYPE(P,REPORT) pReport = KPRF_NAME(NewReport)(pHdr);
+    if (!pReport)
+        return -1;
+
+    /* read module segments */
+    int rc = KPRF_NAME(AnalyzeModSegs)(pReport);
+    if (!rc)
+    {
+        /* read functions. */
+        rc = KPRF_NAME(AnalyseFunctions)(pReport);
+        if (!rc)
+        {
+            /* read threads */
+            rc = KPRF_NAME(AnalyseThreads)(pReport);
+            if (!rc)
+            {
+                *ppReport = pReport;
+                return 0;
+            }
+        }
+    }
+
+    KPRF_NAME(DeleteReport)(pReport);
+    return rc;
+}
+
+
+/**
+ * Writes row with 32-bit value.
+ * @internal
+ */
+static void KPRF_NAME(HtmlWriteRowU32X32)(FILE *pOut, const char *pszName, KU32 u32, const char *pszUnit)
+{
+    fprintf(pOut,
+            "  <tr>\n"
+            "    <th>%s</th>\n"
+            "    <td colspan=\"6\">%u (0x%x)%s%s</td>\n"
+            "  </tr>\n",
+            pszName,
+            u32, u32, pszUnit ? " " : "", pszUnit ? pszUnit : "");
+}
+
+
+/**
+ * Writes row with 32-bit value.
+ * @internal
+ */
+static void KPRF_NAME(HtmlWriteRowU32)(FILE *pOut, const char *pszName, KU32 u32, const char *pszUnit)
+{
+    fprintf(pOut,
+            "  <tr>\n"
+            "    <th>%s</th>\n"
+            "    <td colspan=\"6\">%u%s%s</td>\n"
+            "  </tr>\n",
+            pszName,
+            u32, pszUnit ? " " : "", pszUnit ? pszUnit : "");
+}
+
+
+/**
+ * Writes row with 64-bit value.
+ * @internal
+ */
+static void KPRF_NAME(HtmlWriteRowU64)(FILE *pOut, const char *pszName, KU64 u64, const char *pszUnit)
+{
+    fprintf(pOut,
+            "  <tr>\n"
+            "    <th>%s</th>\n"
+            "    <td colspan=\"6\">% " KPRF_FMT_U64 " (0x%" KPRF_FMT_X64 ")%s%s</td>\n"
+            "  </tr>\n",
+            pszName,
+            u64, u64, pszUnit ? " " : "", pszUnit ? pszUnit : "");
+}
+
+
+/**
+ * Writes row with 64-bit hex value.
+ * @internal
+ */
+static void KPRF_NAME(HtmlWriteRowX64)(FILE *pOut, const char *pszName, KU64 u64, const char *pszUnit)
+{
+    fprintf(pOut,
+            "  <tr>\n"
+            "    <th>%s</th>\n"
+            "    <td colspan=\"6\">0x%" KPRF_FMT_X64 "%s%s</td>\n"
+            "  </tr>\n",
+            pszName,
+            u64, pszUnit ? " " : "", pszUnit ? pszUnit : "");
+}
+
+
+/**
+ * Writes a ticks.
+ */
+static void KPRF_NAME(HtmlWriteParts)(FILE *pOut, KU64 cTicks, KU64 cTotalTicks)
+{
+    /** U+2030 PER MILLE SIGN */
+    static const KU8 s_szPerMilleSignUtf8[4] = { 0xe2, 0x80, 0xb0, 0};
+
+    if (cTicks * 100 / cTotalTicks)
+    {
+        KU32 u = (KU32)((cTicks * 1000) / cTotalTicks);
+        fprintf(pOut, "%u.%01u%%", u / 10, u %10);
+    }
+    else //if (cTicks * 100000 / cTotalTicks)
+    {
+        KU32 u = (KU32)((cTicks * 100000) / cTotalTicks);
+        fprintf(pOut, "%u.%02u%s", u / 100, u % 100, s_szPerMilleSignUtf8);
+    }
+    /*
+    else if (cTicks * 1000000 / cTotalTicks)
+        fprintf(pOut, "%u ppm", (unsigned)((cTicks * 1000000) / cTotalTicks));
+    else
+        fprintf(pOut, "%u ppb", (unsigned)((cTicks * 1000000000) / cTotalTicks));
+    */
+}
+
+
+/**
+ * Writes a ticks.
+ */
+static void KPRF_NAME(HtmlWriteTicks)(FILE *pOut, KU64 cTicks, KU64 cTotalTicks)
+{
+    fprintf(pOut, "%" KPRF_FMT_U64 "", cTicks);
+    if (cTotalTicks)
+    {
+        fprintf(pOut, "</td><td class=\"PartsRow\">");
+        KPRF_NAME(HtmlWriteParts)(pOut, cTicks, cTotalTicks);
+    }
+}
+
+
+/**
+ * Writes row with ticks value.
+ *
+ * @param   pOut            Where to write.
+ * @aaran   pszName         The row name.
+ * @param   cTicks          The tick count.
+ * @param   cTotalTicks     If non-zero, this is used for cTicks / cTotalTicks.
+ * @internal
+ */
+static void KPRF_NAME(HtmlWriteRowTicks)(FILE *pOut, const char *pszName, KU64 cTicks, KU64 cTotalTicks)
+{
+    fprintf(pOut,
+            "  <tr>\n"
+            "    <th class=\"TicksRow\">%s</th>\n"
+            "    <td class=\"TicksRow\">",
+            pszName);
+    KPRF_NAME(HtmlWriteTicks)(pOut, cTicks, cTotalTicks);
+    fprintf(pOut,
+                     "</td><td colspan=\"%d\"/>\n"
+            "  </tr>\n",
+            cTotalTicks ? 4 : 5);
+}
+
+
+/**
+ * Writes row with a time stat value.
+ *
+ * @param   pOut            Where to write.
+ * @aaran   pszName         The row name.
+ * @param   cTicks          The tick count.
+ * @param   cTotalTicks     If non-zero, this is used for cTicks / cTotalTicks.
+ * @internal
+ */
+static void KPRF_NAME(HtmlWriteRowTimeStat)(FILE *pOut, const char *pszName, KPRF_TYPE(PC,TIMESTAT) pTimeStat, KU64 cTotalTicks)
+{
+    fprintf(pOut,
+            "  <tr>\n"
+            "    <th class=\"TicksRow\">%s</th>\n"
+            "    <td class=\"TicksRow\">",
+            pszName);
+    KPRF_NAME(HtmlWriteTicks)(pOut, pTimeStat->SumTicks, cTotalTicks);
+    fprintf(pOut,    "</td>\n"
+            "    <td class=\"MinMaxTicksRow\">");
+    KPRF_NAME(HtmlWriteTicks)(pOut, pTimeStat->MinTicks, cTotalTicks);
+    fprintf(pOut,    "</td>\n"
+            "    <td class=\"MinMaxTicksRow\">");
+    KPRF_NAME(HtmlWriteTicks)(pOut, pTimeStat->MaxTicks, cTotalTicks);
+    fprintf(pOut,    "</td>\n"
+            "  </tr>\n");
+}
+
+
+/**
+ * Writes row with calls value.
+ *
+ * @param   pOut            Where to write.
+ * @aaran   pszName         The row name.
+ * @param   cCalls          The call count.
+ * @param   cTotalCalls     This is used for cCalls / cTotalCalls.
+ * @internal
+ */
+static void KPRF_NAME(HtmlWriteRowCalls)(FILE *pOut, const char *pszName, KU64 cCalls, KU64 cTotalCalls)
+{
+    fprintf(pOut,
+            "  <tr>\n"
+            "    <th class=\"CallsRow\">%s</th>\n"
+            "    <td class=\"CallsRow\">%" KPRF_FMT_U64"</td><td class=\"PartsRow\">",
+            pszName, cCalls);
+    KPRF_NAME(HtmlWriteParts)(pOut, cCalls, cTotalCalls);
+    fprintf(pOut, "</td><td colspan=4></td>"
+            "  </tr>\n");
+}
+
+
+/**
+ * Writes row with pointer value.
+ * @internal
+ */
+static void KPRF_NAME(HtmlWriteRowUPTR)(FILE *pOut, const char *pszName, KPRF_TYPE(,UPTR) uPtr, const char *pszUnit)
+{
+    fprintf(pOut,
+            "  <tr>\n"
+            "    <th>%s</th>\n"
+            "    <td colspan=\"6\">%" KPRF_FMT_UPTR "%s%s</td>\n"
+            "  </tr>\n",
+            pszName,
+            uPtr, pszUnit ? " " : "", pszUnit ? pszUnit : "");
+}
+
+
+/**
+ * Writes row with string value.
+ * @internal
+ */
+static void KPRF_NAME(HtmlWriteRowString)(FILE *pOut, const char *pszName, const char *pszClass, const char *pszFormat, ...)
+{
+    fprintf(pOut,
+             "  <tr>\n"
+             "    <th>%s</th>\n"
+             "    <td%s%s%s colspan=\"6\">",
+             pszName,
+             pszClass ? " class=\"" : "", pszClass ? pszClass : "", pszClass ? "\"" : "");
+    va_list va;
+    va_start(va, pszFormat);
+    vfprintf(pOut, pszFormat, va);
+    va_end(va);
+    fprintf(pOut,      "</td>\n"
+             "  </tr>\n");
+}
+
+
+/**
+ * The first column
+ */
+typedef enum KPRF_TYPE(,FIRSTCOLUMN)
+{
+    KPRF_TYPE(,FIRSTCOLUMN_ON_STACK) = 0,
+    KPRF_TYPE(,FIRSTCOLUMN_ON_TOP_OF_STACK),
+    KPRF_TYPE(,FIRSTCOLUMN_CALLS_TO),
+    KPRF_TYPE(,FIRSTCOLUMN_CALLS_FROM),
+    KPRF_TYPE(,FIRSTCOLUMN_MAX)
+} KPRF_TYPE(,FIRSTCOLUMN);
+
+
+/**
+ * Prints the table with the sorted functions.
+ * The tricky bit is that the sorted column should be to the left of the function name.
+ */
+static void KPRF_NAME(HtmlWriteSortedFunctions)(KPRF_TYPE(P,REPORT) pReport, FILE *pOut, const char *pszName,
+                                                const char *pszTitle, KPRF_TYPE(,FIRSTCOLUMN) enmFirst)
+{
+    fprintf(pOut,
+            "<h2><a name=\"%s\">%s</a></h2>\n"
+            "\n",
+            pszName, pszTitle);
+
+    fprintf(pOut,
+            "<table class=\"FunctionsSorted\">\n"
+            "  <tr>\n"
+            "    <th/>\n");
+    static const char *s_pszHeaders[KPRF_TYPE(,FIRSTCOLUMN_MAX) * 2] =
+    {
+        "    <th colspan=8><a href=\"#Functions-TimeOnStack\">Time On Stack</a> (ticks)</th>\n",
+        "    <th colspan=2><a href=\"#Functions-TimeOnStack\">Sum</a></th>\n"
+        "    <th colspan=2><a href=\"#Functions-TimeOnStack-Min\">Min</a></th>\n"
+        "    <th colspan=2><a href=\"#Functions-TimeOnStack-Avg\">Average</a></th>\n"
+        "    <th colspan=2><a href=\"#Functions-TimeOnStack-Max\">Max</a></th>\n",
+
+        "    <th colspan=8><a href=\"#Functions-TimeOnTopOfStack\">Time On To Top</a> (ticks)</th>\n",
+        "    <th colspan=2><a href=\"#Functions-TimeOnTopOfStack\">Sum</a></th>\n"
+        "    <th colspan=2><a href=\"#Functions-TimeOnTopOfStack-Min\">Min</a></th>\n"
+        "    <th colspan=2><a href=\"#Functions-TimeOnTopOfStack-Avg\">Average</a></th>\n"
+        "    <th colspan=2><a href=\"#Functions-TimeOnTopOfStack-Max\">Max</a></th>\n",
+
+        "    <th colspan=2><a href=\"#Functions-CallsTo\">Calls To</a></th>\n",
+        "    <th/><th/>\n",
+
+        "    <th colspan=2><a href=\"#Functions-CallsFrom\">Calls From</a></th>\n",
+        "    <th/><th/>\n",
+    };
+
+    fprintf(pOut, "%s",  s_pszHeaders[enmFirst * 2]);
+    fprintf(pOut, "    <th>Function</th>\n");
+    for (unsigned i = (enmFirst + 1) % KPRF_TYPE(,FIRSTCOLUMN_MAX); i != enmFirst; i = (i + 1) % KPRF_TYPE(,FIRSTCOLUMN_MAX))
+        fprintf(pOut, "%s",  s_pszHeaders[i * 2]);
+    fprintf(pOut,
+            "  </tr>\n"
+            "  <tr>\n"
+            "    <th/>\n");
+    fprintf(pOut, "%s",  s_pszHeaders[enmFirst * 2 + 1]);
+    fprintf(pOut, "    <th/>\n");
+    for (unsigned i = (enmFirst + 1) % KPRF_TYPE(,FIRSTCOLUMN_MAX); i != enmFirst; i = (i + 1) % KPRF_TYPE(,FIRSTCOLUMN_MAX))
+        fprintf(pOut, "%s",  s_pszHeaders[i * 2 + 1]);
+    fprintf(pOut,
+            "  </tr>\n");
+
+    for (KU32 iFunc = 0; iFunc < pReport->pHdr->cFunctions; iFunc++)
+    {
+        KPRF_TYPE(P,REPORTFUNC) pReportFunc = pReport->papSortedFunctions[iFunc];
+        KPRF_TYPE(PC,FUNC) pFunc = pReportFunc->pFunc;
+        fprintf(pOut,
+                "  <tr>\n"
+                "    <td>%u</td>\n",
+               iFunc);
+
+        unsigned i = enmFirst;
+        do
+        {
+            switch (i)
+            {
+                case KPRF_TYPE(,FIRSTCOLUMN_ON_STACK):
+                    fprintf(pOut,
+                            "    <td class=\"Ticks\">%" KPRF_FMT_U64 "</td><td class=\"Parts\">",
+                            pFunc->OnStack.SumTicks);
+                    KPRF_NAME(HtmlWriteParts)(pOut, pFunc->OnStack.SumTicks, pReport->ProfiledTicks);
+                    fprintf(pOut,       "</td>\n"
+                            "    <td class=\"MinMaxTicks\">%" KPRF_FMT_U64 "</td><td class=\"Parts\">",
+                            pFunc->OnStack.MinTicks);
+                    KPRF_NAME(HtmlWriteParts)(pOut, pFunc->OnStack.MinTicks, pReport->ProfiledTicks);
+                    fprintf(pOut,       "</td>\n"
+                            "    <td class=\"MinMaxTicks\">%" KPRF_FMT_U64 "</td><td class=\"Parts\">",
+                            pFunc->OnStack.SumTicks / pFunc->cOnStack);
+                    KPRF_NAME(HtmlWriteParts)(pOut, pFunc->OnStack.MinTicks, pReport->ProfiledTicks);
+                    fprintf(pOut,       "</td>\n"
+                            "    <td class=\"MinMaxTicks\">%" KPRF_FMT_U64 "</td><td class=\"Parts\">",
+                            pFunc->OnStack.MaxTicks);
+                    KPRF_NAME(HtmlWriteParts)(pOut, pFunc->OnStack.MaxTicks, pReport->ProfiledTicks);
+                    fprintf(pOut,       "</td>\n");
+                    break;
+
+                case KPRF_TYPE(,FIRSTCOLUMN_ON_TOP_OF_STACK):
+                    fprintf(pOut,
+                            "    <td class=\"Ticks\">%" KPRF_FMT_U64 "</td><td class=\"Parts\">",
+                            pFunc->OnTopOfStack.SumTicks);
+                    KPRF_NAME(HtmlWriteParts)(pOut, pFunc->OnTopOfStack.SumTicks, pReport->ProfiledTicks);
+                    fprintf(pOut,       "</td>\n"
+                            "    <td class=\"MinMaxTicks\">%" KPRF_FMT_U64 "</td><td class=\"Parts\">",
+                            pFunc->OnTopOfStack.MinTicks);
+                    KPRF_NAME(HtmlWriteParts)(pOut, pFunc->OnTopOfStack.MinTicks, pReport->ProfiledTicks);
+                    fprintf(pOut,       "</td>\n"
+                            "    <td class=\"MinMaxTicks\">%" KPRF_FMT_U64 "</td><td class=\"Parts\">",
+                            pFunc->OnTopOfStack.SumTicks / pFunc->cOnStack);
+                    KPRF_NAME(HtmlWriteParts)(pOut, pFunc->OnTopOfStack.MinTicks, pReport->ProfiledTicks);
+                    fprintf(pOut,       "</td>\n"
+                            "    <td class=\"MinMaxTicks\">%" KPRF_FMT_U64 "</td><td class=\"Parts\">",
+                            pFunc->OnTopOfStack.MaxTicks);
+                    KPRF_NAME(HtmlWriteParts)(pOut, pFunc->OnTopOfStack.MaxTicks, pReport->ProfiledTicks);
+                    fprintf(pOut,       "</td>\n");
+                    break;
+
+                case KPRF_TYPE(,FIRSTCOLUMN_CALLS_TO):
+                    fprintf(pOut,
+                            "    <td class=\"Calls\">%" KPRF_FMT_U64 "</td><td Class=\"Parts\">",
+                            pFunc->cOnStack);
+                    KPRF_NAME(HtmlWriteParts)(pOut, pFunc->cOnStack, pReport->cCalls);
+                    fprintf(pOut,       "</td>\n");
+                    break;
+
+                case KPRF_TYPE(,FIRSTCOLUMN_CALLS_FROM):
+                    fprintf(pOut,
+                            "    <td class=\"Calls\">%" KPRF_FMT_U64 "</td><td Class=\"Parts\">",
+                            pFunc->cCalls);
+                    KPRF_NAME(HtmlWriteParts)(pOut, pFunc->cCalls, pReport->cCalls);
+                    fprintf(pOut,       "</td>\n");
+                    break;
+
+                default:
+                    break;
+            }
+
+            /* inject the function column */
+            if (i == enmFirst)
+            {
+                fprintf(pOut,
+                        "    <td><a href=\"#Func-%u\">",
+                        (unsigned)(uintptr_t)(pReportFunc - pReport->paFunctions));
+                if (pReportFunc->pSym)
+                    fprintf(pOut, "%s</a></td>\n", pReportFunc->pSym->szName);
+                else
+                    fprintf(pOut, "%" KPRF_FMT_UPTR "</a></td>\n", pFunc->uEntryPtr);
+            }
+
+            /* next */
+            i = (i + 1) % KPRF_TYPE(,FIRSTCOLUMN_MAX);
+        } while (i != enmFirst);
+
+        fprintf(pOut,
+                "  </tr>\n");
+    }
+    fprintf(pOut,
+            "</table>\n"
+            "\n");
+
+}
+
+
+/**
+ * Writes an HTML report.
+ *
+ * @returns 0 on success.
+ * @returns -1 on failure.
+ * @param   pReport     The report to put into HTML.
+ * @param   pOut        The file stream to write the HTML to.
+ */
+static int KPRF_NAME(WriteHtmlReport)(KPRF_TYPE(P,REPORT) pReport, FILE *pOut)
+{
+    KPRF_TYPE(PC,HDR) pHdr = pReport->pHdr;
+
+    /*
+     * Write the standard html.
+     */
+    fprintf(pOut,
+            "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
+            "<html>\n"
+            "<head>\n"
+            "  <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n"
+            "  <title>kProfiler 2 - %s</title>\n"
+            "</head>\n"
+            "<style>\n"
+            "table\n"
+            "{\n"
+//            "  width: 90%%;\n"
+            "  background: #999999;\n"
+//            "  margin-top: .6em;\n"
+//            "  margin-bottom: .3em;\n"
+            "}\n"
+            "th\n"
+            "{\n"
+            "  padding: 1px 4px;\n"
+            "  background: #cccccc;\n"
+//            "  text-align: left;\n"
+            "  font-size: 90%%;\n"
+            //"  width: 30%%;\n"
+            "}\n"
+            "td\n"
+            "{\n"
+            "  padding: 1px 4px;\n"
+            "  background: #ffffff;\n"
+            "  font-size: 90%%;\n"
+            "}\n"
+            "td.Ticks\n"
+            "{\n"
+            "  text-align: right;\n"
+            "}\n"
+            "td.TicksRow\n"
+            "{\n"
+            "  text-align: right;\n"
+            "}\n"
+            "td.MinMaxTicks\n"
+            "{\n"
+            "  text-align: right;\n"
+            "}\n"
+            "td.MinMaxTicksRow\n"
+            "{\n"
+            "  text-align: right;\n"
+            "}\n"
+            "td.Parts\n"
+            "{\n"
+            "  text-align: right;\n"
+            "}\n"
+            "td.PartsRow\n"
+            "{\n"
+            "  text-align: left;\n"
+            "}\n"
+            "td.Calls\n"
+            "{\n"
+            "  text-align: right;\n"
+            "}\n"
+            "td.CallsRow\n"
+            "{\n"
+            "  text-align: right;\n"
+            "}\n"
+            "td.BlankRow\n"
+            "{\n"
+            "  background: #e0e0e0;\n"
+            "}\n"
+            "td.Name\n"
+            "{\n"
+            "  font-weight: bold;\n"
+            "}\n"
+            "table.Summary th\n"
+            "{\n"
+            "  width:200px;\n"
+            "}\n"
+            "table.Thread\n"
+            "{\n"
+            "  min-width:60%%\n"
+            "}\n"
+            "table.Thread th\n"
+            "{\n"
+            "  width:200px;\n"
+            "}\n"
+            "table.Functions\n"
+            "{\n"
+            "  width:60%%;\n"
+            "}\n"
+            "table.Functions th\n"
+            "{\n"
+            "  width:200px;\n"
+            "}\n"
+            "table.Modules\n"
+            "{\n"
+            "  width:60%%;\n"
+            "}\n"
+            "table.Modules th\n"
+            "{\n"
+            "  width:200px;\n"
+            "}\n"
+            "table.FunctionsSorted\n"
+            "{\n"
+            "}\n"
+            "</style>\n"
+            "<body topmargin=\"0\">\n"
+            ,
+            pHdr->offCommandLine
+                ? (const char *)KPRF_OFF2PTR(P,FUNC, pHdr->offCommandLine, pHdr)
+                : ""
+            );
+
+    /*
+     * Table of contents.
+     */
+    fprintf(pOut,
+            "<h2>Table of Contents</h2>\n"
+            "\n"
+            "<ul>\n"
+            "  <li><a href=\"#Summary\"  >1.0 Summary</a></li>\n"
+            "  <li><a href=\"#Functions\">2.0 Functions</a></li>\n"
+            "      <ul>\n"
+            "        <li><a href=\"#Functions-TimeOnStack\"     >2.1 Time On Stack</a></li>\n"
+            "          <ul>\n"
+            "            <li><a href=\"#Functions-TimeOnStack-Avg\"     >2.2.1 Time On Stack - Average</a></li>\n"
+            "            <li><a href=\"#Functions-TimeOnStack-Min\"     >2.2.1 Time On Stack - Min</a></li>\n"
+            "            <li><a href=\"#Functions-TimeOnStack-Max\"     >2.2.2 Time On Stack - Max</a></li>\n"
+            "          </ul>\n"
+            "        <li><a href=\"#Functions-TimeOnTopOfStack\">2.3 Time On Top Of Stack</a></li>\n"
+            "          <ul>\n"
+            "            <li><a href=\"#Functions-TimeOnTopOfStack-Avg\">2.3.1 Time On Top Of Stack - Average</a></li>\n"
+            "            <li><a href=\"#Functions-TimeOnTopOfStack-Min\">2.3.2 Time On Top Of Stack - Min</a></li>\n"
+            "            <li><a href=\"#Functions-TimeOnTopOfStack-Max\">2.3.3 Time On Top Of Stack - Max</a></li>\n"
+            "          </ul>\n"
+            "        <li><a href=\"#Functions-CallsTo\"         >2.3 Calls To</a></li>\n"
+            "        <li><a href=\"#Functions-CallsFrom\"       >2.4 Calls From</a></li>\n"
+            "        <li><a href=\"#Function-Details\"          >2.5 Function Details</a></li>\n"
+            "      </ul>\n"
+            "  <li><a href=\"#Threads\"  >3.0 Threads</a></li>\n"
+            "  <li><a href=\"#Modules\"  >4.0 Modules</a></li>\n"
+            "</ul>\n"
+            "\n"
+            "\n");
+
+    /*
+     * Summary.
+     */
+    fprintf(pOut,
+            "<h2><a name=\"Summary\">1.0 Summary</a></h2>\n"
+            "\n"
+            "<p>\n"
+            "<table class=\"Summary\">\n");
+    if (pHdr->offCommandLine)
+        KPRF_NAME(HtmlWriteRowString)(pOut, "Command Line", NULL, "%s", (const char *)KPRF_OFF2PTR(P,FUNC, pHdr->offCommandLine, pHdr));
+    KPRF_NAME(HtmlWriteRowU32X32)(pOut, "Threads", pHdr->cThreads, NULL);
+    KPRF_NAME(HtmlWriteRowU32X32)(pOut, "Modules", pReport->cMods, NULL);
+    KPRF_NAME(HtmlWriteRowU32X32)(pOut, "Functions", pHdr->cFunctions, NULL);
+    KPRF_NAME(HtmlWriteRowTicks)(pOut, "Profiled", pReport->ProfiledTicks, pReport->ProfiledTicks);
+    KPRF_NAME(HtmlWriteRowTicks)(pOut, "Sleep", pReport->SleepTicks, pReport->ProfiledTicks);
+    KPRF_NAME(HtmlWriteRowTicks)(pOut, "Overhead", pReport->OverheadTicks, pReport->ProfiledTicks + pReport->OverheadTicks);
+    KPRF_NAME(HtmlWriteRowCalls)(pOut, "Recorded Calls", pReport->cCalls, pReport->cCalls);
+    fprintf(pOut, "<tr><td class=\"BlankRow\" colspan=7> </td></tr>\n");
+    KPRF_NAME(HtmlWriteRowString)(pOut, "kProfiler Version ", NULL, "Mark 2 Alpha 1");
+    KPRF_NAME(HtmlWriteRowString)(pOut, "kProfiler Build Time ", NULL, __DATE__ " " __TIME__);
+    fprintf(pOut,
+            "</table>\n"
+            "</p>\n"
+            "\n"
+            "\n");
+
+    /*
+     * Functions.
+     */
+    fprintf(pOut,
+            "<h2><a name=\"Functions\">2.0 Functions</a></h2>\n"
+            "\n");
+
+    qsort(&pReport->papSortedFunctions[0], pHdr->cFunctions, sizeof(pReport->papSortedFunctions[0]), KPRF_NAME(FuncCompareOnStack));
+    KPRF_NAME(HtmlWriteSortedFunctions)(pReport, pOut, "Functions-TimeOnStack",     "2.1 Time On Stack", KPRF_TYPE(,FIRSTCOLUMN_ON_STACK));
+    qsort(&pReport->papSortedFunctions[0], pHdr->cFunctions, sizeof(pReport->papSortedFunctions[0]), KPRF_NAME(FuncCompareOnStackAvg));
+    KPRF_NAME(HtmlWriteSortedFunctions)(pReport, pOut, "Functions-TimeOnStack-Avg",     "2.2.1 Time On Stack - Average", KPRF_TYPE(,FIRSTCOLUMN_ON_STACK));
+    qsort(&pReport->papSortedFunctions[0], pHdr->cFunctions, sizeof(pReport->papSortedFunctions[0]), KPRF_NAME(FuncCompareOnStackMin));
+    KPRF_NAME(HtmlWriteSortedFunctions)(pReport, pOut, "Functions-TimeOnStack-Min",     "2.2.2 Time On Stack - Min", KPRF_TYPE(,FIRSTCOLUMN_ON_STACK));
+    qsort(&pReport->papSortedFunctions[0], pHdr->cFunctions, sizeof(pReport->papSortedFunctions[0]), KPRF_NAME(FuncCompareOnStackMax));
+    KPRF_NAME(HtmlWriteSortedFunctions)(pReport, pOut, "Functions-TimeOnStack-Max",     "2.2.3 Time On Stack - Max", KPRF_TYPE(,FIRSTCOLUMN_ON_STACK));
+
+    qsort(&pReport->papSortedFunctions[0], pHdr->cFunctions, sizeof(pReport->papSortedFunctions[0]), KPRF_NAME(FuncCompareOnTopOfStack));
+    KPRF_NAME(HtmlWriteSortedFunctions)(pReport, pOut, "Functions-TimeOnTopOfStack",    "2.2 Time On Top Of Stack", KPRF_TYPE(,FIRSTCOLUMN_ON_TOP_OF_STACK));
+    qsort(&pReport->papSortedFunctions[0], pHdr->cFunctions, sizeof(pReport->papSortedFunctions[0]), KPRF_NAME(FuncCompareOnTopOfStackAvg));
+    KPRF_NAME(HtmlWriteSortedFunctions)(pReport, pOut, "Functions-TimeOnTopOfStack-Avg","2.2.1 Time On Top Of Stack - Average", KPRF_TYPE(,FIRSTCOLUMN_ON_TOP_OF_STACK));
+    qsort(&pReport->papSortedFunctions[0], pHdr->cFunctions, sizeof(pReport->papSortedFunctions[0]), KPRF_NAME(FuncCompareOnTopOfStackMin));
+    KPRF_NAME(HtmlWriteSortedFunctions)(pReport, pOut, "Functions-TimeOnTopOfStack-Min","2.2.2 Time On Top Of Stack - Min", KPRF_TYPE(,FIRSTCOLUMN_ON_TOP_OF_STACK));
+    qsort(&pReport->papSortedFunctions[0], pHdr->cFunctions, sizeof(pReport->papSortedFunctions[0]), KPRF_NAME(FuncCompareOnTopOfStackMax));
+    KPRF_NAME(HtmlWriteSortedFunctions)(pReport, pOut, "Functions-TimeOnTopOfStack-Max","2.2.3 Time On Top Of Stack - Max", KPRF_TYPE(,FIRSTCOLUMN_ON_TOP_OF_STACK));
+
+    qsort(&pReport->papSortedFunctions[0], pHdr->cFunctions, sizeof(pReport->papSortedFunctions[0]), KPRF_NAME(FuncCompareCallsTo));
+    KPRF_NAME(HtmlWriteSortedFunctions)(pReport, pOut, "Functions-CallsTo",         "2.4 Calls To", KPRF_TYPE(,FIRSTCOLUMN_CALLS_TO));
+
+    qsort(&pReport->papSortedFunctions[0], pHdr->cFunctions, sizeof(pReport->papSortedFunctions[0]), KPRF_NAME(FuncCompareCallsFrom));
+    KPRF_NAME(HtmlWriteSortedFunctions)(pReport, pOut, "Functions-CallsFrom",       "2.5 Calls From", KPRF_TYPE(,FIRSTCOLUMN_CALLS_FROM));
+
+    fprintf(pOut,
+            "<h2><a name=\"Function-Details\">2.5 Function Details</a></h2>\n"
+            "\n"
+            "<p>\n"
+            "<table class=\"Functions\">\n");
+    for (KU32 iFunc = 0; iFunc < pHdr->cFunctions; iFunc++)
+    {
+        KPRF_TYPE(P,REPORTFUNC) pReportFunc = &pReport->paFunctions[iFunc];
+        KPRF_TYPE(PC,FUNC) pFunc = pReportFunc->pFunc;
+
+        fprintf(pOut,
+                "<tr><td class=\"BlankRow\" colspan=7><a name=\"Func-%u\"> </a></td></tr>\n",
+                iFunc);
+        KPRF_NAME(HtmlWriteRowU32)(pOut, "Function No.", iFunc, NULL);
+        if (pReportFunc->pSym)
+            KPRF_NAME(HtmlWriteRowString)(pOut, "Name", "Name", "%s", pReportFunc->pSym->szName);
+        if (pReportFunc->pLine)
+            KPRF_NAME(HtmlWriteRowString)(pOut, "Location", NULL, "<a href=\"file:///%s\">%s</a> Line #%d",
+                                          pReportFunc->pLine->szFile, pReportFunc->pLine->szFile, pReportFunc->pLine->iLine);
+        if (pReportFunc->pModSeg)
+        {
+            KPRF_NAME(HtmlWriteRowString)(pOut, "Module", NULL, "<a href=\"#Mod-%u\">%s</a>",
+                                          pReportFunc->pModSeg->pMod->iMod, pReportFunc->pModSeg->pModSeg->szPath);
+            KPRF_NAME(HtmlWriteRowString)(pOut, "Segment:Offset", NULL, "%x:%" KPRF_FMT_UPTR,
+                                          pReportFunc->pModSeg->pModSeg->iSegment,
+                                          pFunc->uEntryPtr - pReportFunc->pModSeg->pModSeg->uBasePtr);
+        }
+        KPRF_NAME(HtmlWriteRowUPTR)(pOut, "Address", pFunc->uEntryPtr, NULL);
+
+        KPRF_NAME(HtmlWriteRowTimeStat)(pOut, "On Stack", &pFunc->OnStack, pReport->ProfiledTicks);
+        KPRF_NAME(HtmlWriteRowTimeStat)(pOut, "On Top Of Stack", &pFunc->OnTopOfStack, pReport->ProfiledTicks);
+        KPRF_NAME(HtmlWriteRowCalls)(pOut, "Calls To", pFunc->cOnStack, pReport->cCalls);
+        KPRF_NAME(HtmlWriteRowCalls)(pOut, "Calls From", pFunc->cCalls, pReport->cCalls);
+
+        fprintf(pOut,
+                "\n");
+    }
+    fprintf(pOut,
+            "</table>\n"
+            "</p>\n"
+            "\n");
+
+    /*
+     * Threads.
+     */
+    fprintf(pOut,
+            "<h2><a name=\"Threads\">3.0 Threads</a></h2>\n"
+            "\n"
+            "<p>\n"
+            "<table class=\"Threads\">\n");
+
+    for (KU32 iThread = 0; iThread < pHdr->cThreads; iThread++)
+    {
+        KPRF_TYPE(PC,THREAD) pThread = pReport->paThreads[iThread].pThread;
+
+        fprintf(pOut,
+                "<tr><td class=\"BlankRow\" colspan=7><a name=\"Thread-%u\"> </a></td></tr>\n",
+                iThread);
+        KPRF_NAME(HtmlWriteRowU32)(pOut, "Thread No.", iThread, NULL);
+        KPRF_NAME(HtmlWriteRowX64)(pOut, "Thread Id", pThread->ThreadId, NULL);
+        if (pThread->szName[0])
+            KPRF_NAME(HtmlWriteRowString)(pOut, "Name", "Name", "%s", pThread->szName);
+        KPRF_NAME(HtmlWriteRowUPTR)(pOut, "Stack Base Address", pThread->uStackBasePtr, NULL);
+        KPRF_NAME(HtmlWriteRowUPTR)(pOut, "Max Stack Depth", pThread->cbMaxStack, "bytes");
+        //KPRF_NAME(HtmlWriteRowUPTR)(pOut, "Max Stack Depth", pThread->cMaxFrames, "frames"); /** @todo max stack frames! */
+        KPRF_NAME(HtmlWriteRowTicks)(pOut, "Profiled", pThread->ProfiledTicks, pReport->ProfiledTicks);
+        KPRF_NAME(HtmlWriteRowTicks)(pOut, "Sleep", pThread->SleepTicks, pReport->ProfiledTicks);
+        KPRF_NAME(HtmlWriteRowTicks)(pOut, "Overhead", pThread->OverheadTicks, pReport->ProfiledTicks + pReport->OverheadTicks);
+        KPRF_NAME(HtmlWriteRowCalls)(pOut, "Recorded Calls",  pThread->cCalls, pReport->cCalls);
+        KPRF_NAME(HtmlWriteRowU64)(pOut, "Unwinds", pThread->cUnwinds, NULL);
+        KPRF_NAME(HtmlWriteRowU64)(pOut, "Profiler Stack Overflows", pThread->cOverflows, NULL);
+        KPRF_NAME(HtmlWriteRowU64)(pOut, "Profiler Stack Switch Rejects", pThread->cStackSwitchRejects, NULL);
+
+        fprintf(pOut,
+                "\n");
+    }
+    fprintf(pOut,
+            "</table>\n"
+            "</p>\n"
+            "\n");
+
+
+    /*
+     * Modules.
+     */
+    fprintf(pOut,
+            "<h2><a name=\"Modules\">4.0 Modules</a></h2>\n"
+            "\n"
+            "<p>\n"
+            "<table class=\"Modules\">\n");
+
+    KPRF_TYPE(P,REPORTMOD) pMod = pReport->pFirstMod;
+    KU32 iMod = 0;
+    while (pMod)
+    {
+        fprintf(pOut,
+                "<a name=\"Mod-%u\">\n"
+                "<tr><td class=\"BlankRow\" colspan=7><a name=\"Module-%u\"> </a></td></tr>\n",
+                iMod, iMod);
+        KPRF_NAME(HtmlWriteRowU32)(pOut, "Module No.", iMod, NULL);
+        KPRF_NAME(HtmlWriteRowString)(pOut, "Name", "Name", "%s", pMod->pFirstSeg->pModSeg->szPath);
+
+        for (KPRF_TYPE(P,REPORTMODSEG) pSeg = pMod->pFirstSeg; pSeg; pSeg = pSeg->pNext)
+        {
+            char szName[64];
+            sprintf(szName, "Segment No.%u - Base", pSeg->pModSeg->iSegment);
+            KPRF_NAME(HtmlWriteRowUPTR)(pOut, szName, pSeg->pModSeg->uBasePtr, NULL);
+            sprintf(szName, "Segment No.%u - Size", pSeg->pModSeg->iSegment);
+            KPRF_NAME(HtmlWriteRowUPTR)(pOut, szName,
+                                        pSeg->pModSeg->cbSegmentMinusOne + 1 > pSeg->pModSeg->cbSegmentMinusOne
+                                        ? pSeg->pModSeg->cbSegmentMinusOne + 1
+                                        : pSeg->pModSeg->cbSegmentMinusOne,
+                                        NULL);
+        }
+
+        KPRF_NAME(HtmlWriteRowTicks)(pOut, "On Stack", pMod->OnStackTicks, pReport->ProfiledTicks);
+        KPRF_NAME(HtmlWriteRowTicks)(pOut, "On Top Of Stack", pMod->OnTopOfStackTicks, pReport->ProfiledTicks);
+        KPRF_NAME(HtmlWriteRowU32)(pOut, "Functions", pMod->cFunctions, NULL);
+
+        fprintf(pOut,
+                "\n");
+
+        /* next */
+        iMod++;
+        pMod = pMod->pNext;
+    }
+    fprintf(pOut,
+            "</table>\n"
+            "</p>\n"
+            "\n");
+
+
+    /*
+     * The End.
+     */
+    fprintf(pOut,
+            "</body>\n"
+            "</html>\n");
+    return 0;
+}
diff --git a/src/lib/kStuff/kProfiler2/prfx86msc.asm b/src/lib/kStuff/kProfiler2/prfx86msc.asm
new file mode 100644
index 0000000..c733958
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/prfx86msc.asm
@@ -0,0 +1,393 @@
+; $Id: prfx86msc.asm 29 2009-07-01 20:30:29Z bird $
+;; @file
+; kProfiler Mark 2 - Microsoft C/C++ Compiler Interaction, x86.
+;
+
+;
+; Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+;
+; Permission is hereby granted, free of charge, to any person
+; obtaining a copy of this software and associated documentation
+; files (the "Software"), to deal in the Software without
+; restriction, including without limitation the rights to use,
+; copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of the Software, and to permit persons to whom the
+; Software is furnished to do so, subject to the following
+; conditions:
+;
+; The above copyright notice and this permission notice shall be
+; included in all copies or substantial portions of the Software.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+; OTHER DEALINGS IN THE SOFTWARE.
+;
+
+[section .data]
+;
+g_fCalibrated:
+        dd 0
+g_OverheadAdj:
+        dd 0
+
+[section .text]
+
+extern KPRF_ENTER
+extern KPRF_LEAVE
+
+global __penter
+global __pexit
+
+;ifdef  UNDEFINED
+global common_return_path
+global common_overhead
+global common_no_overhead
+global calibrate
+global calib_inner_update_minimum
+global calib_inner_next
+global calib_outer_dec
+global calib_outer_inc
+global calib_done
+global calib_nullproc
+;endif
+
+
+;;
+; On x86 the call to this function has been observed to be put before
+; creating the stack frame, as the very first instruction in the function.
+;
+; Thus the stack layout is as follows:
+;       24      return address of the calling function.
+;       20      our return address - the address of the calling function + 5.
+;       1c      eax
+;       18      edx
+;       14      eflags
+;       10      ecx
+;       c       tsc high       - param 3
+;       8       tsc low
+;       4       frame pointer  - param 2
+;       0       function ptr   - param 1
+;
+;
+align 16
+__penter:
+        ; save volatile register and get the time stamp.
+        push    eax
+        push    edx
+        rdtsc
+        pushfd
+        push    ecx
+
+        ; setting up the enter call frame (cdecl).
+        sub     esp, 4 + 4 + 8
+        mov     [esp + 0ch], edx        ; Param 3 - the timestamp
+        mov     [esp + 08h], eax
+        lea     edx, [esp + 24h]        ; Param 2 - frame pointer (pointer to the return address of the function calling us)
+        mov     [esp + 04h], edx
+        mov     eax, [esp + 20h]        ; Param 1 - The function address
+        sub     eax, 5                  ; call instruction
+        mov     [esp], eax
+
+        call    KPRF_ENTER
+        jmp     common_return_path
+
+
+;;
+; On x86 the call to this function has been observed to be put right before
+; return instruction. This fact matters since since we have to calc the same
+; stack address as in _penter.
+;
+; Thus the stack layout is as follows:
+;       24      return address of the calling function.
+;       20      our return address - the address of the calling function + 5.
+;       1c      eax
+;       18      edx
+;       14      eflags
+;       10      ecx
+;       c       tsc high       - param 3
+;       8       tsc low
+;       4       frame pointer  - param 2
+;       0       function ptr   - param 1
+;
+;
+align 16
+__pexit:
+        ; save volatile register and get the time stamp.
+        push    eax
+        push    edx
+        rdtsc
+        pushfd
+        push    ecx
+
+        ; setting up the leave call frame (cdecl).
+        sub     esp, 4 + 4 + 8
+        mov     [esp + 0ch], edx        ; Param 3 - the timestamp
+        mov     [esp + 08h], eax
+        lea     edx, [esp + 24h]        ; Param 2 - frame pointer (pointer to the return address of the function calling us)
+        mov     [esp + 04h], edx
+        mov     eax, [esp + 20h]        ; Param 1 - Some address in the function.
+        sub     eax, 5                  ; call instruction
+        mov     [esp], eax
+
+        call    KPRF_LEAVE
+        jmp common_return_path
+
+
+;;
+; This is the common return path for both the enter and exit hooks.
+; It's kept common because we can then use the same overhead adjustment
+; and save some calibration efforts. It also saves space :-)
+align 16
+common_return_path:
+        ; Update overhead
+        test    eax, eax
+        jz      common_no_overhead
+        cmp     byte [g_fCalibrated], 0
+        jnz     common_overhead
+        call    calibrate
+common_overhead:
+        mov     ecx, eax                ; ecx <- pointer to overhead counter.
+        mov     eax, [g_OverheadAdj]    ; apply the adjustment before reading tsc
+        sub     [esp + 08h], eax
+        sbb     dword [esp + 0ch], 0
+
+        rdtsc
+        sub     eax, [esp + 08h]
+        sbb     edx, [esp + 0ch]
+        add     [ecx], eax
+        adc     [ecx + 4], edx
+common_no_overhead:
+        add     esp, 4 + 4 + 8
+
+        ; restore volatile registers.
+        pop     ecx
+        popfd
+        pop     edx
+        pop     eax
+        ret
+
+;;
+; Data esi points to while we're calibrating.
+struc CALIBDATA
+    .OverheadLo resd 1
+    .OverheadHi resd 1
+    .ProfiledLo resd 1
+    .ProfiledHi resd 1
+    .EnterTSLo  resd 1
+    .EnterTSHi  resd 1
+    .MinLo      resd 1
+    .MinHi      resd 1
+endstruc
+
+
+
+align 16
+;;
+; Do necessary calibrations.
+;
+calibrate:
+        ; prolog
+        push    ebp
+        mov     ebp, esp
+        pushfd
+        pushad
+        sub     esp, CALIBDATA_size
+        mov     esi, esp                ; esi points to the CALIBDATA
+
+        ;
+        ; Indicate that we have finished calibrating.
+        ;
+        mov     eax, 1
+        xchg    dword [g_fCalibrated], eax
+
+        ;
+        ; The outer loop - find the right adjustment.
+        ;
+        mov     ebx, 200h               ; loop counter.
+calib_outer_loop:
+
+        ;
+        ; The inner loop - calls the function number of times to establish a
+        ;                  good minimum value
+        ;
+        mov     ecx, 200h
+        mov     dword [esi + CALIBDATA.MinLo], 0ffffffffh
+        mov     dword [esi + CALIBDATA.MinHi], 07fffffffh
+calib_inner_loop:
+
+        ; zero the overhead and profiled times.
+        xor     eax, eax
+        mov     [esi + CALIBDATA.OverheadLo], eax
+        mov     [esi + CALIBDATA.OverheadHi], eax
+        mov     [esi + CALIBDATA.ProfiledLo], eax
+        mov     [esi + CALIBDATA.ProfiledHi], eax
+        call    calib_nullproc
+
+        ; subtract the overhead
+        mov     eax, [esi + CALIBDATA.ProfiledLo]
+        mov     edx, [esi + CALIBDATA.ProfiledHi]
+        sub     eax, [esi + CALIBDATA.OverheadLo]
+        sbb     edx, [esi + CALIBDATA.OverheadHi]
+
+        ; update the minimum value.
+        test    edx, 080000000h
+        jnz near calib_outer_dec        ; if negative, just simplify and shortcut
+        cmp     edx, [esi + CALIBDATA.MinHi]
+        jg      calib_inner_next
+        jl      calib_inner_update_minimum
+        cmp     eax, [esi + CALIBDATA.MinLo]
+        jge     calib_inner_next
+calib_inner_update_minimum:
+        mov     [esi + CALIBDATA.MinLo], eax
+        mov     [esi + CALIBDATA.MinHi], edx
+calib_inner_next:
+        loop    calib_inner_loop
+
+        ; Is the minimum value acceptable?
+        test    dword [esi + CALIBDATA.MinHi], 80000000h
+        jnz     calib_outer_dec         ; simplify if negative.
+        cmp     dword [esi + CALIBDATA.MinHi], 0
+        jnz     calib_outer_inc         ; this shouldn't be possible
+        cmp     dword [esi + CALIBDATA.MinLo], 1fh
+        jbe     calib_outer_dec         ; too low - 2 ticks per pair is the minimum!
+        cmp     dword [esi + CALIBDATA.MinLo], 30h
+        jbe     calib_done              ; this is fine!
+calib_outer_inc:
+        inc     dword [g_OverheadAdj]
+        jmp     calib_outer_next
+calib_outer_dec:
+        cmp     dword [g_OverheadAdj], 1
+        je      calib_done
+        dec     dword [g_OverheadAdj]
+calib_outer_next:
+        dec     ebx
+        jnz     calib_outer_loop
+calib_done:
+
+        ; epilog
+        add     esp, CALIBDATA_size
+        popad
+        popfd
+        leave
+        ret
+
+
+
+
+;;
+; The calibration __penter - this must be identical to the real thing except for the KPRF call.
+align 16
+calib_penter:
+        ; This part must be identical
+        push    eax
+        push    edx
+        rdtsc
+        pushfd
+        push    ecx
+
+        ; store the entry
+        mov     [esi + CALIBDATA.EnterTSLo], eax
+        mov     [esi + CALIBDATA.EnterTSHi], edx
+
+        ; create the call frame
+        push    edx
+        push    eax
+        push    0
+        push    0
+
+        lea     eax, [esi + CALIBDATA.OverheadLo]
+        jmp     common_overhead
+
+
+;;
+; The calibration __pexit - this must be identical to the real thing except for the KPRF call.
+align 16
+calib_pexit:
+        ; This part must be identical
+        push    eax
+        push    edx
+        rdtsc
+        pushfd
+        push    ecx
+
+        ; update the time
+        push    eax
+        push    edx
+        sub     eax, [esi + CALIBDATA.EnterTSLo]
+        sbb     edx, [esi + CALIBDATA.EnterTSHi]
+        add     [esi + CALIBDATA.ProfiledLo], eax
+        adc     [esi + CALIBDATA.ProfiledHi], edx
+        pop     edx
+        pop     eax
+
+        ; create the call frame
+        push    edx
+        push    eax
+        push    0
+        push    0
+
+        lea     eax, [esi + CALIBDATA.EnterTSLo]
+        jmp     common_overhead
+
+
+;;
+; The 'function' we're profiling.
+; The general idea is that each pair should take something like 2-10 ticks.
+;
+; (Btw. If we don't use multiple pairs here, we end up with the wrong result.)
+align 16
+calib_nullproc:
+        call    calib_penter ;0
+        call    calib_pexit
+
+        call    calib_penter ;1
+        call    calib_pexit
+
+        call    calib_penter ;2
+        call    calib_pexit
+
+        call    calib_penter ;3
+        call    calib_pexit
+
+        call    calib_penter ;4
+        call    calib_pexit
+
+        call    calib_penter ;5
+        call    calib_pexit
+
+        call    calib_penter ;6
+        call    calib_pexit
+
+        call    calib_penter ;7
+        call    calib_pexit
+
+        call    calib_penter ;8
+        call    calib_pexit
+
+        call    calib_penter ;9
+        call    calib_pexit
+
+        call    calib_penter ;a
+        call    calib_pexit
+
+        call    calib_penter ;b
+        call    calib_pexit
+
+        call    calib_penter ;c
+        call    calib_pexit
+
+        call    calib_penter ;d
+        call    calib_pexit
+
+        call    calib_penter ;e
+        call    calib_pexit
+
+        call    calib_penter ;f
+        call    calib_pexit
+        ret
+
diff --git a/src/lib/kStuff/kProfiler2/tst.c b/src/lib/kStuff/kProfiler2/tst.c
new file mode 100644
index 0000000..f56204c
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/tst.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+
+#ifdef _MSC_VER
+void __cdecl _penter(void);
+void __cdecl _pexit(void);
+__declspec(naked) int  naked(void)
+{
+    __asm
+    {
+        call    _penter
+        call    _pexit
+        xor     eax, eax
+        ret
+    }
+}
+
+#endif
+
+int bar(void)
+{
+    unsigned i;
+    for (i = 0; i < 1000; i += 7)
+        i += i & 1;
+    return i;
+}
+
+int foo(void)
+{
+    unsigned i, rc = 0;
+    for (i = 0; i < 1000; i++)
+        rc += bar();
+#ifdef _MSC_VER
+    for (; i < 2000; i++)
+        rc += naked();
+#endif
+    return i;
+}
+
+int main()
+{
+    int rc;
+    printf("hello");
+    fflush(stdout);
+    rc = foo();
+    printf("world\n");
+    return rc;
+}
+
diff --git a/src/lib/kStuff/kProfiler2/tstlongjmp.c b/src/lib/kStuff/kProfiler2/tstlongjmp.c
new file mode 100644
index 0000000..d6e2b49
--- /dev/null
+++ b/src/lib/kStuff/kProfiler2/tstlongjmp.c
@@ -0,0 +1,62 @@
+
+#include <setjmp.h>
+#include <time.h>
+
+/* just try trick the compiler into not optimizing stuff by
+   making it "uncertain" which path to take. */
+int always_true(void)
+{
+    time_t t = time(NULL);
+    if (t == time(NULL))
+        return 1;
+    if (t != time(NULL))
+        return 1;
+    if (t == time(NULL))
+        return 1;
+    if (t != time(NULL))
+        return 1;
+    return 0;
+}
+
+jmp_buf g_JmpBuf;
+
+int onelevel(void)
+{
+    if (always_true())
+        longjmp(g_JmpBuf, 1);
+    return 0;
+}
+
+
+int twolevels_inner(void)
+{
+    if (always_true())
+        longjmp(g_JmpBuf, 1);
+    return 0;
+}
+
+int twolevels_outer(void)
+{
+    int rc;
+    always_true();
+    rc = twolevels_inner();
+    always_true();
+    return rc;
+}
+
+
+int main()
+{
+    int rc = 1;
+
+    /* first */
+    if (!setjmp(g_JmpBuf))
+        rc = onelevel();
+
+    /* second */
+    if (!setjmp(g_JmpBuf))
+        rc = twolevels_outer();
+
+    return rc != 1;
+}
+
diff --git a/src/lib/kStuff/kRdr/Makefile.kmk b/src/lib/kStuff/kRdr/Makefile.kmk
new file mode 100644
index 0000000..357acf6
--- /dev/null
+++ b/src/lib/kStuff/kRdr/Makefile.kmk
@@ -0,0 +1,48 @@
+# $Id: Makefile.kmk 29 2009-07-01 20:30:29Z bird $
+## @file
+# kRdr - The File Provider, sub-makefile.
+#
+
+#
+# Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+DEPTH ?= ..
+SUB_DEPTH = ..
+include $(PATH_KBUILD)/subheader.kmk
+
+#
+# kRdrStatic - The file provider module.
+#
+LIBRARIES += kRdrStatic
+kRdrStatic_TEMPLATE = kStuffLIB
+kRdrStatic_DEFS = KDBG_BUILDING
+kRdrStatic_SOURCES = \
+	kRdr.cpp \
+	kRdrFile.cpp \
+	kRdrBuffered.cpp
+
+# Generate the rules
+include $(PATH_KBUILD)/subfooter.kmk
+
diff --git a/src/lib/kStuff/kRdr/kRdr.cpp b/src/lib/kStuff/kRdr/kRdr.cpp
new file mode 100644
index 0000000..5952cb1
--- /dev/null
+++ b/src/lib/kStuff/kRdr/kRdr.cpp
@@ -0,0 +1,281 @@
+/* $Id: kRdr.cpp 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kRdr - The File Provider.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#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.
+ */
+KRDR_DECL(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.
+ */
+KRDR_DECL(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.
+ */
+KRDR_DECL(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.
+ */
+KRDR_DECL(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.
+ */
+KRDR_DECL(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.
+ */
+KRDR_DECL(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.
+ */
+KRDR_DECL(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.
+ */
+KRDR_DECL(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.
+ */
+KRDR_DECL(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.
+ */
+KRDR_DECL(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.
+ */
+KRDR_DECL(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.
+ */
+KRDR_DECL(int) kRdrMap(PKRDR pRdr, void **ppvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL 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.
+ */
+KRDR_DECL(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.
+ */
+KRDR_DECL(int) kRdrProtect(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL 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.
+ */
+KRDR_DECL(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.
+ */
+KRDR_DECL(void) kRdrDone(PKRDR pRdr)
+{
+    KRDR_VALIDATE_VOID(pRdr);
+    pRdr->pOps->pfnDone(pRdr);
+}
+
diff --git a/src/lib/kStuff/kRdr/kRdrBuffered.cpp b/src/lib/kStuff/kRdr/kRdrBuffered.cpp
new file mode 100644
index 0000000..fc589cd
--- /dev/null
+++ b/src/lib/kStuff/kRdr/kRdrBuffered.cpp
@@ -0,0 +1,750 @@
+/* $Id: kRdrBuffered.cpp 79 2016-07-27 14:25:09Z bird $ */
+/** @file
+ * kRdrBuffered - Buffered File Provider.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "kRdrInternal.h"
+#include <k/kHlpAlloc.h>
+#include <k/kHlpString.h>
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * The buffered file provier instance.
+ * This is just a wrapper around another file provider.
+ */
+typedef struct KRDRBUF
+{
+    /** The file reader vtable. */
+    KRDR                Core;
+    /** The actual file provider that we're wrapping. */
+    PKRDR               pRdr;
+    /** The current file offset. */
+    KFOFF               offFile;
+    /** The file size. */
+    KFOFF               cbFile;
+    /** The offset of the buffer. */
+    KFOFF               offBuf;
+    /** The offset of the end of the buffer. */
+    KFOFF               offBufEnd;
+    /** The number of valid buffer bytes. */
+    KSIZE               cbBufValid;
+    /** The size of the buffer. */
+    KSIZE               cbBuf;
+    /** The buffer. */
+    KU8                *pbBuf;
+    /** Whether the pRdr instance should be closed together with us or not. */
+    KBOOL               fCloseIt;
+    /** Set if the buffer has been messed up by kRdrBufLineQ. */
+    KBOOL               fTainedByLineQ;
+} KRDRBUF, *PKRDRBUF;
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static void     krdrBufDone(PKRDR pRdr);
+static int      krdrBufUnmap(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments);
+static int      krdrBufProtect(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fUnprotectOrProtect);
+static int      krdrBufRefresh(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments);
+static int      krdrBufMap(PKRDR pRdr, void **ppvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fFixed);
+static KSIZE    krdrBufPageSize(PKRDR pRdr);
+static const char *krdrBufName(PKRDR pRdr);
+static KIPTR    krdrBufNativeFH(PKRDR pRdr);
+static KFOFF    krdrBufTell(PKRDR pRdr);
+static KFOFF    krdrBufSize(PKRDR pRdr);
+static int      krdrBufAllUnmap(PKRDR pRdr, const void *pvBits);
+static int      krdrBufAllMap(PKRDR pRdr, const void **ppvBits);
+static int      krdrBufRead(PKRDR pRdr, void *pvBuf, KSIZE cb, KFOFF off);
+static int      krdrBufDestroy(PKRDR pRdr);
+static int      krdrBufCreate(PPKRDR ppRdr, const char *pszFilename);
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** Native file provider operations.
+ *
+ * @remark  This is not in the file provider list as its intended for wrapping
+ *          other kRdr instances.
+ */
+static const KRDROPS g_krdrBufOps =
+{
+    "Buffered kRdr",
+    NULL,
+    krdrBufCreate,
+    krdrBufDestroy,
+    krdrBufRead,
+    krdrBufAllMap,
+    krdrBufAllUnmap,
+    krdrBufSize,
+    krdrBufTell,
+    krdrBufName,
+    krdrBufNativeFH,
+    krdrBufPageSize,
+    krdrBufMap,
+    krdrBufRefresh,
+    krdrBufProtect,
+    krdrBufUnmap,
+    krdrBufDone,
+    42
+};
+
+
+/** @copydoc KRDROPS::pfnDone */
+static void     krdrBufDone(PKRDR pRdr)
+{
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+    return pThis->pRdr->pOps->pfnDone(pThis->pRdr);
+}
+
+
+/** @copydoc KRDROPS::pfnUnmap */
+static int      krdrBufUnmap(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments)
+{
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+    return pThis->pRdr->pOps->pfnUnmap(pThis->pRdr, pvBase, cSegments, paSegments);
+}
+
+
+/** @copydoc KRDROPS::pfnProtect */
+static int      krdrBufProtect(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fUnprotectOrProtect)
+{
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+    return pThis->pRdr->pOps->pfnProtect(pThis->pRdr, pvBase, cSegments, paSegments, fUnprotectOrProtect);
+}
+
+
+/** @copydoc KRDROPS::pfnRefresh */
+static int krdrBufRefresh(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments)
+{
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+    return pThis->pRdr->pOps->pfnRefresh(pThis->pRdr, pvBase, cSegments, paSegments);
+}
+
+
+/** @copydoc KRDROPS::pfnMap */
+static int krdrBufMap(PKRDR pRdr, void **ppvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fFixed)
+{
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+    return pThis->pRdr->pOps->pfnMap(pThis->pRdr, ppvBase, cSegments, paSegments, fFixed);
+}
+
+
+/** @copydoc KRDROPS::pfnPageSize */
+static KSIZE krdrBufPageSize(PKRDR pRdr)
+{
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+    return pThis->pRdr->pOps->pfnPageSize(pThis->pRdr);
+}
+
+
+/** @copydoc KRDROPS::pfnName */
+static const char *krdrBufName(PKRDR pRdr)
+{
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+    return pThis->pRdr->pOps->pfnName(pThis->pRdr);
+}
+
+
+/** @copydoc KRDROPS::pfnNativeFH */
+static KIPTR krdrBufNativeFH(PKRDR pRdr)
+{
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+    return pThis->pRdr->pOps->pfnNativeFH(pThis->pRdr);
+}
+
+
+/** @copydoc KRDROPS::pfnTell */
+static KFOFF krdrBufTell(PKRDR pRdr)
+{
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+    return pThis->offFile;
+}
+
+
+/** @copydoc KRDROPS::pfnSize */
+static KFOFF krdrBufSize(PKRDR pRdr)
+{
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+    return pThis->cbFile;
+}
+
+
+/** @copydoc KRDROPS::pfnAllUnmap */
+static int krdrBufAllUnmap(PKRDR pRdr, const void *pvBits)
+{
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+    return pThis->pRdr->pOps->pfnAllUnmap(pThis->pRdr, pvBits);
+}
+
+
+/** @copydoc KRDROPS::pfnAllMap */
+static int krdrBufAllMap(PKRDR pRdr, const void **ppvBits)
+{
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+    return pThis->pRdr->pOps->pfnAllMap(pThis->pRdr, ppvBits);
+}
+
+
+/**
+ * Fills the buffer with file bits starting at the specified offset.
+ *
+ * @returns 0 on success, pfnRead error code on failure.
+ * @param   pThis   The instance.
+ * @param   off     Where to start reading.
+ */
+static int krdrBufFillBuffer(PKRDRBUF pThis, KFOFF off)
+{
+    kRdrAssert(off < pThis->cbFile);
+
+    /* Reposition the buffer if it's past the end of the file so that
+       we maximize its usability. We leave one unused byte at the end
+       of the buffer so kRdrBufLineQ can terminate its string properly.
+       Of course, this might end up re-reading a lot of stuff for no
+       future gain, but whatever... */
+    kRdrAssert(pThis->cbBuf <= pThis->cbFile + 1);
+    KFOFF cbLeft = pThis->cbFile - off;
+    KSIZE cbRead = pThis->cbBuf;
+    if ((KSSIZE)cbRead - 1 >= cbLeft)
+    {
+        cbRead--;
+        off = pThis->cbFile - cbRead;
+    }
+    int rc = pThis->pRdr->pOps->pfnRead(pThis->pRdr, pThis->pbBuf, cbRead, off);
+    if (!rc)
+    {
+        pThis->offBuf = off;
+        pThis->offBufEnd = off + cbRead;
+        pThis->cbBufValid = cbRead;
+    }
+    else
+    {
+        pThis->offBuf = pThis->offBufEnd = 0;
+        pThis->cbBufValid = 0;
+    }
+    pThis->fTainedByLineQ = K_FALSE;
+    return rc;
+}
+
+
+/** @copydoc KRDROPS::pfnRead */
+static int krdrBufRead(PKRDR pRdr, void *pvBuf, KSIZE cb, KFOFF off)
+{
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+
+    /*
+     * We need to validate and update the file offset before
+     * we start making partial reads from the buffer and stuff.
+     */
+    KFOFF offEnd = off + cb;
+    if (    off >= pThis->cbFile
+        ||  offEnd > pThis->cbFile
+        ||  offEnd < off)
+        return KERR_OUT_OF_RANGE; /* includes EOF. */
+    pThis->offFile = offEnd;
+    if (!cb)
+        return 0;
+
+    /*
+     * Scratch the buffer if kRdrBufLineQ has tained it.
+     */
+    if (pThis->fTainedByLineQ)
+    {
+        pThis->offBuf = pThis->offBufEnd = 0;
+        pThis->cbBufValid = 0;
+    }
+
+    /*
+     * Is any part of the request in the buffer?
+     *
+     * We will currently ignore buffer hits in the middle of the
+     * request because it's annoying to implement and it's
+     * questionable whether it'll benefit much performance wise.
+     */
+    if (pThis->cbBufValid > 0)
+    {
+        if (off >= pThis->offBuf)
+        {
+            if (off < pThis->offBufEnd)
+            {
+                /* head (or all) of the request is in the buffer. */
+                KSIZE cbMaxChunk = (KSIZE)(pThis->offBufEnd - off);
+                KSIZE cbChunk = K_MIN(cb, cbMaxChunk);
+                kHlpMemCopy(pvBuf, &pThis->pbBuf[off - pThis->offBuf], cbChunk);
+                if (cbChunk == cb)
+                    return 0;
+
+                cb -= cbChunk;
+                pvBuf = (KU8 *)pvBuf + cbChunk;
+                off += cbChunk;
+            }
+        }
+        else if (   offEnd > pThis->offBuf
+                 && offEnd <= pThis->offBufEnd)
+        {
+            /* the end of the request is in the buffer. */
+            KSIZE cbChunk = (KSIZE)(pThis->offBufEnd - (offEnd));
+            kHlpMemCopy((KU8 *)pvBuf + (pThis->offBuf - off), pThis->pbBuf, cbChunk);
+            kRdrAssert(cbChunk < cb);
+            cb -= cbChunk;
+            offEnd -= cbChunk;
+        }
+    }
+
+    /*
+     * If the buffer is larger than the read request, read a full buffer
+     * starting at the requested offset. Otherwise perform an unbuffered
+     * read.
+     */
+    if (pThis->cbBuf > cb)
+    {
+        int rc = krdrBufFillBuffer(pThis, off);
+        if (rc)
+            return rc;
+        if (pThis->offBuf == off)
+            kHlpMemCopy(pvBuf, pThis->pbBuf, cb);
+        else
+        {
+            kRdrAssert(off > pThis->offBuf);
+            kRdrAssert(off + cb <= pThis->offBufEnd);
+            kHlpMemCopy(pvBuf, pThis->pbBuf + (off - pThis->offBuf), cb);
+        }
+    }
+    else
+    {
+        int rc = pThis->pRdr->pOps->pfnRead(pThis->pRdr, pvBuf, cb, off);
+        if (rc)
+            return rc;
+    }
+    return 0;
+}
+
+
+/** @copydoc KRDROPS::pfnDestroy */
+static int krdrBufDestroy(PKRDR pRdr)
+{
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+
+    /* Close the kRdr instance that we're wrapping. */
+    if (pThis->fCloseIt)
+    {
+        int rc = pThis->pRdr->pOps->pfnDestroy(pThis->pRdr);
+        if (rc)
+            return rc;
+        pThis->fCloseIt = K_FALSE;
+        pThis->pRdr = NULL;
+    }
+
+    kHlpFree(pThis->pbBuf);
+    pThis->pbBuf = NULL;
+    kHlpFree(pRdr);
+    return 0;
+}
+
+
+/** @copydoc KRDROPS::pfnCreate */
+static int krdrBufCreate(PPKRDR ppRdr, const char *pszFilename)
+{
+    K_NOREF(ppRdr);
+    K_NOREF(pszFilename);
+    return KERR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * Worker for kRdrBufOpen and kRdrBufWrap.
+ *
+ * It's essentially kRdrBufWrap without error checking.
+ *
+ * @returns 0 on success, one of the kErrors status code on failure.
+ * @param   ppRdr           Where to store the new file provider instance.
+ * @param   pRdrWrapped     The file provider instance to buffer.
+ * @param   fCloseIt        Whether it the pRdrWrapped instance should be closed
+ *                          when the new instance is closed.
+ */
+static int krdrBufWrapIt(PPKRDR ppRdr, PKRDR pRdrWrapped, KBOOL fCloseIt)
+{
+    PKRDRBUF pThis = (PKRDRBUF)kHlpAlloc(sizeof(*pThis));
+    if (pThis)
+    {
+        pThis->Core.u32Magic = KRDR_MAGIC;
+        pThis->Core.pOps = &g_krdrBufOps;
+        pThis->pRdr = pRdrWrapped;
+        pThis->offFile = pRdrWrapped->pOps->pfnTell(pRdrWrapped);
+        pThis->cbFile = pRdrWrapped->pOps->pfnSize(pRdrWrapped);
+        pThis->offBuf = pThis->offBufEnd = 0;
+        pThis->cbBufValid = 0;
+        pThis->fCloseIt = fCloseIt;
+        pThis->fTainedByLineQ = K_FALSE;
+        if (pThis->cbFile < 128*1024)
+            pThis->cbBuf = (KSIZE)pThis->cbFile + 1; /* need space for the kRdrBufLineQ terminator. */
+        else
+            pThis->cbBuf = 64*1024;
+        pThis->pbBuf = (KU8 *)kHlpAlloc(pThis->cbBuf);
+        if (pThis->pbBuf)
+        {
+            *ppRdr = &pThis->Core;
+            return 0;
+        }
+
+        pThis->Core.u32Magic = 0;
+        kHlpFree(pThis);
+    }
+    return KERR_NO_MEMORY;
+}
+
+
+/**
+ * Opens a file provider with a buffered wrapper.
+ *
+ * @returns 0 on success, KERR_* on failure.
+ * @param   ppRdr       Where to store the buffered file reader instance on success.
+ * @param   pszFilename The name of the file that should be opened.
+ */
+KRDR_DECL(int) kRdrBufOpen(PPKRDR ppRdr, const char *pszFilename)
+{
+    kRdrAssertPtrReturn(ppRdr, KERR_INVALID_POINTER);
+    *ppRdr = NULL;
+
+    PKRDR pRdrWrapped;
+    int rc = kRdrOpen(&pRdrWrapped, pszFilename);
+    if (!rc)
+    {
+        rc = krdrBufWrapIt(ppRdr, pRdrWrapped, K_TRUE);
+        if (rc)
+            kRdrClose(pRdrWrapped);
+    }
+    return rc;
+}
+
+
+/**
+ * Creates a buffered file provider instance for an existing one.
+ *
+ * @returns 0 on success, KERR_* on failure.
+ * @param   ppRdr           Where to store the new file provider pointer.
+ * @param   pRdr            The file provider instance to wrap.
+ * @param   fCLoseIt        Whether it the wrapped reader should be automatically
+ *                          closed when the wrapper closes.
+ */
+KRDR_DECL(int) kRdrBufWrap(PPKRDR ppRdr, PKRDR pRdr, KBOOL fCloseIt)
+{
+    KRDR_VALIDATE(pRdr);
+    return krdrBufWrapIt(ppRdr, pRdr, fCloseIt);
+}
+
+
+/**
+ * Checks whether the file provider instance is of the buffered type or not.
+ *
+ * @returns K_TRUE if it is, otherwise K_FALSE.
+ * @param   pRdr            The file provider instance to check.
+ */
+KRDR_DECL(KBOOL) kRdrBufIsBuffered(PKRDR pRdr)
+{
+    KRDR_VALIDATE_EX(pRdr, K_FALSE);
+    return pRdr->pOps == &g_krdrBufOps;
+}
+
+
+/**
+ * Reads a line from a buffered file provider.
+ *
+ * The trailing '\n' or '\r\n' is stripped.
+ *
+ * @returns 0 on success. KERR_* on failure.
+ * @retval  KRDR_ERR_LINE_TOO_LONG if the line is too long to fit in the passed in buffer.
+ * @retval  KRDR_ERR_NOT_BUFFERED_RDR if pRdr isn't a buffered reader.
+ * @param   pRdr        The buffered file reader.
+ * @param   pszLine     Where to store the line.
+ * @param   cbLine      The size of the the line buffer.
+ */
+KRDR_DECL(int) kRdrBufLine(PKRDR pRdr, char *pszLine, KSIZE cbLine)
+{
+    return kRdrBufLineEx(pRdr, pszLine, &cbLine);
+}
+
+
+/**
+ * Reads a line from a buffered file provider.
+ *
+ * The trailing '\n' or '\r\n' is stripped.
+ *
+ * @returns 0 on success. KERR_* on failure.
+ * @retval  KRDR_ERR_LINE_TOO_LONG if the line is too long to fit in the passed in buffer.
+ * @retval  KRDR_ERR_NOT_BUFFERED_RDR if pRdr isn't a buffered reader.
+ * @param   pRdr        The buffered file reader.
+ * @param   pszLine     Where to store the line.
+ * @param   pcbLine     The size of the the line buffer on input, the length of the
+ *                      returned line on output.
+ */
+KRDR_DECL(int) kRdrBufLineEx(PKRDR pRdr, char *pszLine, KSIZE *pcbLine)
+{
+    /*
+     * Validate input.
+     */
+    kRdrAssertPtrReturn(pcbLine, KERR_INVALID_POINTER);
+    KSIZE cbLeft = *pcbLine;
+    *pcbLine = 0;
+    kRdrAssertReturn(cbLeft > 0, KERR_INVALID_PARAMETER);
+    KRDR_VALIDATE(pRdr);
+    kRdrAssertReturn(pRdr->pOps != &g_krdrBufOps, KRDR_ERR_NOT_BUFFERED_RDR);
+    kRdrAssertPtrReturn(pszLine, KERR_INVALID_POINTER);
+
+    /* check for EOF */
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+    if (pThis->offFile >= pThis->cbFile)
+    {
+        kRdrAssert(pThis->offFile == pThis->cbFile);
+        *pszLine = '\0';
+        *pcbLine = 0;
+        return KERR_EOF;
+    }
+
+    /*
+     * Scratch the buffer if kRdrBufLineQ has tained it.
+     */
+    if (pThis->fTainedByLineQ)
+    {
+        pThis->offBuf = pThis->offBufEnd = 0;
+        pThis->cbBufValid = 0;
+    }
+
+    /*
+     * Buffered read loop.
+     *
+     * The overflow logic is a bit fishy wrt to overflowing at an "\r\n"
+     * that arrives at a buffer boundrary. The current policy is to try
+     * our best to not to fail with overflow in the EOL sequence or EOF.
+     * If it's the end of the buffer, it will not be refilled just to
+     * check for this because that's too much work.
+     */
+    cbLeft--; /* reserve space for the terminator. */
+    char *pszOut = pszLine;
+    for (;;)
+    {
+        /*
+         * Do we need to (re-)fill the buffer or does it contain something
+         * that we can work on already?
+         */
+        if (    !pThis->cbBufValid
+            ||  pThis->offFile >= pThis->offBufEnd
+            ||  pThis->offFile < pThis->offBuf)
+        {
+            int rc = krdrBufFillBuffer(pThis, pThis->offFile);
+            if (rc)
+            {
+                *pszOut = '\0';
+                return rc;
+            }
+        }
+
+        /*
+         * Parse the buffer looking for the EOL indicator.
+         */
+        kRdrAssert(pThis->offFile >= pThis->offBuf && pThis->offFile < pThis->offBufEnd);
+        kRdrAssert(sizeof(char) == sizeof(*pThis->pbBuf));
+        const char * const pszStart = (const char *)&pThis->pbBuf[pThis->offFile - pThis->offBuf];
+        const char * const pszEnd   = (const char *)&pThis->pbBuf[pThis->cbBufValid];
+        const char *psz = pszStart;
+        while (psz < pszEnd)
+        {
+            const char ch = *psz;
+            if (ch == '\n')
+            {
+                /* found the EOL, update file position and line length. */
+                pThis->offFile += psz - pszStart + 1;
+                *pcbLine += psz - pszStart;
+
+                /* terminate the string, checking for "\r\n" first. */
+                if (    *pcbLine
+                    &&  pszOut[-1] == '\r')
+                {
+                    *pcbLine -= 1;
+                    pszOut--;
+                }
+                *pszOut = '\0';
+                return 0;
+            }
+            if (!cbLeft)
+            {
+                /* the line is *probably* too long. */
+                pThis->offFile += psz - pszStart;
+                *pcbLine += psz - pszStart;
+                *pszOut = '\0';
+
+                /* The only possible case where the line actually isn't too long
+                   is if we're at a "\r\n" sequence. We will re-fill the buffer
+                   if necessary to check for the '\n' as it's not that much work. */
+                if (    ch == '\r'
+                    &&  pThis->offFile + 2 <= pThis->cbFile)
+                {
+                    if (psz + 1 >= pszEnd)
+                    {
+                        int rc = krdrBufFillBuffer(pThis, pThis->offFile);
+                        if (rc)
+                        {
+                            *pszOut = '\0';
+                            return rc;
+                        }
+                    }
+                    psz = (const char *)&pThis->pbBuf[pThis->offFile - pThis->offBuf];
+                    kRdrAssert(*psz == '\r');
+                    if (psz[1] == '\n')
+                    {
+                        *pcbLine -= 1;
+                        pszOut[-1] = '\0';
+                        pThis->offFile += 2;
+                        return 0;
+                    }
+                }
+                return KRDR_ERR_LINE_TOO_LONG;
+            }
+
+            /* copy and advance */
+            *pszOut++ = ch;
+            cbLeft--;
+            psz++;
+        }
+
+        /* advance past the buffer and check for EOF. */
+        *pcbLine += pszEnd - pszStart;
+        pThis->offFile = pThis->offBufEnd;
+        if (pThis->offFile >= pThis->cbFile)
+        {
+            kRdrAssert(pThis->offFile == pThis->cbFile);
+            *pszOut = '\0';
+            return 0;
+        }
+    }
+}
+
+
+/**
+ * Worker for kRdrBufLineQ that searches the current buffer for EOL or EOF.
+ *
+ * When a EOF marker is found
+ *
+ *
+ * @returns NULL if EOL/EOF isn't found the buffer.
+ * @param   pThis   The buffered reader instance.
+ */
+static const char * krdrBufLineQWorker(PKRDRBUF pThis)
+{
+    kRdrAssert(pThis->offFile >= pThis->offBuf && pThis->offFile < pThis->offBufEnd);
+
+    /*
+     * Search the buffer.
+     */
+    kRdrAssert(sizeof(char) == sizeof(*pThis->pbBuf));
+    const char * const pszStart = (const char *)&pThis->pbBuf[pThis->offFile - pThis->offBuf];
+    const char * const pszEnd   = (const char *)&pThis->pbBuf[pThis->cbBufValid];
+    char *psz = (char *)pszStart;
+    while (psz < pszEnd)
+    {
+        char ch = *psz;
+        if (ch == '\n')
+        {
+            pThis->offFile += psz - pszStart;
+            pThis->fTainedByLineQ = K_TRUE;
+            *psz = '\0';
+            if (    psz > pszStart
+                &&  psz[-1] == '\r')
+                *--psz = '\0';
+            return pszStart;
+        }
+        psz++;
+    }
+
+    /*
+     * Check for EOF. There must be room for a terminator char here.
+     */
+    if (    pThis->offBufEnd >= pThis->cbFile
+        &&  (pThis->offBufEnd - pThis->offBuf) < (KSSIZE)pThis->cbBuf)
+    {
+        pThis->offFile = pThis->cbFile;
+        pThis->pbBuf[pThis->cbBufValid] = '\0';
+        return pszStart;
+    }
+
+    return NULL;
+}
+
+
+/**
+ * Get the pointer to the next next line in the buffer.
+ * The returned line is zero terminated.
+ *
+ * @returns A pointer to the line on success. This becomes invalid
+ *          upon the next call to this kRdr instance.
+ * @returns NULL on EOF, read error of if the line was too long.
+ * @param   pRdr        The buffered file reader.
+ */
+KRDR_DECL(const char *) kRdrBufLineQ(PKRDR pRdr)
+{
+    /*
+     * Validate input.
+     */
+    KRDR_VALIDATE_EX(pRdr, NULL);
+    kRdrAssertReturn(pRdr->pOps != &g_krdrBufOps, NULL);
+
+    /* check for EOF */
+    PKRDRBUF pThis = (PKRDRBUF)pRdr;
+    if (pThis->offFile >= pThis->cbFile)
+    {
+        kRdrAssert(pThis->offFile == pThis->cbFile);
+        return NULL;
+    }
+
+    /*
+     * Search the current buffer if possible
+     */
+    if (    pThis->cbBufValid
+        &&  pThis->offFile >= pThis->offBuf
+        &&  pThis->offFile < pThis->offBufEnd)
+    {
+        const char *psz = krdrBufLineQWorker(pThis);
+        if (psz)
+            return psz;
+    }
+
+    /*
+     * Fill the buffer in an optimal way and look for the EOL/EOF (again).
+     */
+    int rc = krdrBufFillBuffer(pThis, pThis->offFile);
+    if (rc)
+        return NULL;
+    return krdrBufLineQWorker(pThis);
+}
+
diff --git a/src/lib/kStuff/kRdr/kRdrFile.cpp b/src/lib/kStuff/kRdr/kRdrFile.cpp
new file mode 100644
index 0000000..27dd803
--- /dev/null
+++ b/src/lib/kStuff/kRdr/kRdrFile.cpp
@@ -0,0 +1,1308 @@
+/* $Id: kRdrFile.cpp 81 2016-08-18 22:10:38Z bird $ */
+/** @file
+ * kRdrFile - The Native File Provider
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "kRdrInternal.h"
+#include <k/kHlpAlloc.h>
+#include <k/kHlpString.h>
+#include <k/kErrors.h>
+
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+# include <k/kHlpSys.h>
+# include <sys/fcntl.h>
+# include <sys/mman.h>
+# include <unistd.h>
+
+#elif K_OS == K_OS_OS2
+# define INCL_ERRORS
+# define INCL_BASE
+# include <os2.h>
+
+#elif K_OS == K_OS_WINDOWS
+# define WIN32_NO_STATUS
+# include <Windows.h>
+# include <ntsecapi.h>
+# include <ntstatus.h>
+
+# ifdef __cplusplus
+  extern "C" {
+# endif
+
+  /** @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 PSIZE_T 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 PSIZE_T AllocationSize,
+      IN ULONG AllocationType,
+      IN ULONG Protect
+  );
+
+  NTOSAPI
+  NTSTATUS
+  NTAPI
+  NtFreeVirtualMemory(
+      IN HANDLE ProcessHandle,
+      IN OUT PVOID *BaseAddress,
+      IN OUT PSIZE_T FreeSize,
+      IN ULONG FreeType
+  );
+
+# ifdef __cplusplus
+  }
+# endif
+
+#else
+# error "port me"
+#endif
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Prepared stuff.
+ */
+typedef struct KRDRFILEPREP
+{
+    /** The address of the prepared region. */
+    void           *pv;
+    /** The size of the prepared region. */
+    KSIZE           cb;
+#if K_OS == K_OS_WINDOWS
+    /** Handle to the section created to map the file. */
+    HANDLE          hSection;
+#endif
+} KRDRFILEPREP, *PKRDRFILEPREP;
+
+/**
+ * The file provier instance for native files.
+ */
+typedef struct KRDRFILE
+{
+    /** The file reader vtable. */
+    KRDR                Core;
+    /** The file handle. */
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+    int                 File;
+#elif K_OS == K_OS_OS2
+    HFILE               File;
+#elif K_OS == K_OS_WINDOWS
+    HANDLE              File;
+#else
+# error "Port me!"
+#endif
+    /** The current file offset. */
+    KFOFF               off;
+    /** The file size. */
+    KFOFF               cb;
+    /** Array where we stuff the mapping area data. */
+    KRDRFILEPREP        aPreps[4];
+    /** The number of current preps. */
+    KU32                cPreps;
+    /** Number of mapping references. */
+    KI32                cMappings;
+    /** The memory mapping. */
+    void               *pvMapping;
+    /** The filename. */
+    char                szFilename[1];
+} KRDRFILE, *PKRDRFILE;
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static void     krdrFileDone(PKRDR pRdr);
+static int      krdrFileUnmap(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments);
+static int      krdrFileGenericUnmap(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments);
+static int      krdrFileProtect(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fUnprotectOrProtect);
+static int      krdrFileGenericProtect(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fUnprotectOrProtect);
+static int      krdrFileRefresh(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments);
+static int      krdrFileGenericRefresh(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments);
+static int      krdrFileMap(PKRDR pRdr, void **ppvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fFixed);
+static int      krdrFileGenericMap(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fFixed);
+static KSIZE   krdrFilePageSize(PKRDR pRdr);
+static const char *krdrFileName(PKRDR pRdr);
+static KIPTR    krdrFileNativeFH(PKRDR pRdr);
+static KFOFF    krdrFileTell(PKRDR pRdr);
+static KFOFF    krdrFileSize(PKRDR pRdr);
+static int      krdrFileAllUnmap(PKRDR pRdr, const void *pvBits);
+static int      krdrFileAllMap(PKRDR pRdr, const void **ppvBits);
+static int      krdrFileRead(PKRDR pRdr, void *pvBuf, KSIZE cb, KFOFF off);
+static int      krdrFileDestroy(PKRDR pRdr);
+static int      krdrFileCreate(PPKRDR ppRdr, const char *pszFilename);
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** Native file provider operations. */
+const KRDROPS g_kRdrFileOps =
+{
+    "native file",
+    NULL,
+    krdrFileCreate,
+    krdrFileDestroy,
+    krdrFileRead,
+    krdrFileAllMap,
+    krdrFileAllUnmap,
+    krdrFileSize,
+    krdrFileTell,
+    krdrFileName,
+    krdrFileNativeFH,
+    krdrFilePageSize,
+    krdrFileMap,
+    krdrFileRefresh,
+    krdrFileProtect,
+    krdrFileUnmap,
+    krdrFileDone,
+    42
+};
+
+
+#if K_OS == K_OS_WINDOWS
+/**
+ * Converts a kLdr segment protection to NT protection for a mapping.
+ *
+ * @returns Nt page protection.
+ * @param   enmProt     kLdr protection.
+ */
+static ULONG krdrFileGetNtMapProt(KPROT enmProt)
+{
+    switch (enmProt)
+    {
+        case KPROT_NOACCESS:             return PAGE_NOACCESS;
+        case KPROT_READONLY:             return PAGE_READONLY;
+        case KPROT_READWRITE:            return PAGE_READWRITE;
+        case KPROT_WRITECOPY:            return PAGE_WRITECOPY;
+        case KPROT_EXECUTE:              return PAGE_EXECUTE;
+        case KPROT_EXECUTE_READ:         return PAGE_EXECUTE_READ;
+        case KPROT_EXECUTE_READWRITE:    return PAGE_EXECUTE_READWRITE;
+        case KPROT_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 krdrFileGetNtAllocProt(KPROT enmProt)
+{
+    switch (enmProt)
+    {
+        case KPROT_NOACCESS:             return PAGE_NOACCESS;
+        case KPROT_READONLY:             return PAGE_READONLY;
+        case KPROT_WRITECOPY:
+        case KPROT_READWRITE:            return PAGE_READWRITE;
+        case KPROT_EXECUTE:              return PAGE_EXECUTE;
+        case KPROT_EXECUTE_READ:         return PAGE_EXECUTE_READ;
+        case KPROT_EXECUTE_WRITECOPY:
+        case KPROT_EXECUTE_READWRITE:    return PAGE_EXECUTE_READWRITE;
+        default:                            return ~(ULONG)0;
+    }
+}
+#endif
+
+
+/** @copydoc KRDROPS::pfnDone */
+static void     krdrFileDone(PKRDR 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 PKRDRFILEPREP krdrFileFindPrepExact(PKRDRFILE pFile, void *pv)
+{
+    KI32 i = pFile->cPreps;
+    while (i-- > 0)
+        if (pFile->aPreps[i].pv == pv)
+            return &pFile->aPreps[i];
+    return NULL;
+}
+
+
+/** @copydoc KRDROPS::pfnUnmap */
+static int      krdrFileUnmap(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments)
+{
+    PKRDRFILE        pRdrFile = (PKRDRFILE)pRdr;
+    PKRDRFILEPREP       pPrep = krdrFileFindPrepExact(pRdrFile, pvBase);
+    int                 rc;
+    if (!pPrep)
+        return KERR_INVALID_PARAMETER;
+
+#if K_OS == K_OS_WINDOWS
+    if (pPrep->hSection != NULL)
+    {
+        /** @todo implement me. */
+        return -1;
+    }
+#endif
+
+    rc = krdrFileGenericUnmap(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 krdrFileUnmap. */
+static int krdrFileGenericUnmap(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments)
+{
+    krdrFileGenericProtect(pRdr, pPrep, cSegments, paSegments, 1 /* unprotect */);
+    return kHlpPageFree(pPrep->pv, pPrep->cb);
+}
+
+
+/** @copydoc KRDROPS::pfnProtect */
+static int krdrFileProtect(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fUnprotectOrProtect)
+{
+    PKRDRFILE        pRdrFile = (PKRDRFILE)pRdr;
+    PKRDRFILEPREP    pPrep = krdrFileFindPrepExact(pRdrFile, pvBase);
+    if (!pPrep)
+        return KERR_INVALID_PARAMETER;
+
+#if K_OS == K_OS_WINDOWS
+    if (pPrep->hSection != NULL)
+    {
+        /** @todo implement me. */
+        return -1;
+    }
+#endif
+
+    return krdrFileGenericProtect(pRdr, pPrep, cSegments, paSegments, fUnprotectOrProtect);
+}
+
+
+/** Generic implementation of krdrFileProtect. */
+static int krdrFileGenericProtect(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fUnprotectOrProtect)
+{
+    KU32 i;
+
+    /*
+     * Iterate the segments and apply memory protection changes.
+     */
+    for (i = 0; i < cSegments; i++)
+    {
+        int rc;
+        void *pv;
+        KPROT enmProt;
+
+        if (paSegments[i].RVA == NIL_KLDRADDR)
+            continue;
+
+        /* calc new protection. */
+        enmProt = (KPROT)paSegments[i].enmProt; /** @todo drop cast */
+        if (fUnprotectOrProtect)
+        {
+            switch (enmProt)
+            {
+                case KPROT_NOACCESS:
+                case KPROT_READONLY:
+                case KPROT_READWRITE:
+                case KPROT_WRITECOPY:
+                    enmProt = KPROT_READWRITE;
+                    break;
+                case KPROT_EXECUTE:
+                case KPROT_EXECUTE_READ:
+                case KPROT_EXECUTE_READWRITE:
+                case KPROT_EXECUTE_WRITECOPY:
+                    enmProt = KPROT_EXECUTE_READWRITE;
+                    break;
+                default:
+                    kRdrAssert(!"bad enmProt");
+                    return -1;
+            }
+        }
+        else
+        {
+            /* copy on write -> normal write. */
+            if (enmProt == KPROT_EXECUTE_WRITECOPY)
+                enmProt = KPROT_EXECUTE_READWRITE;
+            else if (enmProt == KPROT_WRITECOPY)
+                enmProt = KPROT_READWRITE;
+        }
+
+        pv = (KU8 *)pPrep->pv + paSegments[i].RVA;
+
+        rc = kHlpPageProtect(pv, paSegments[i].cbMapped, enmProt);
+        if (rc)
+            break;
+    }
+
+    return 0;
+}
+
+
+/** @copydoc KRDROPS::pfnRefresh */
+static int      krdrFileRefresh(PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments)
+{
+    PKRDRFILE        pRdrFile = (PKRDRFILE)pRdr;
+    PKRDRFILEPREP    pPrep = krdrFileFindPrepExact(pRdrFile, pvBase);
+    if (!pPrep)
+        return KERR_INVALID_PARAMETER;
+
+#if K_OS == K_OS_WINDOWS
+    if (pPrep->hSection != NULL)
+    {
+        /** @todo implement me. */
+        return -1;
+    }
+#endif
+
+    return krdrFileGenericRefresh(pRdr, pPrep, cSegments, paSegments);
+}
+
+
+/** Generic implementation of krdrFileRefresh. */
+static int      krdrFileGenericRefresh(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments)
+{
+    int rc;
+    int rc2;
+    KU32 i;
+
+    /*
+     * Make everything writable again.
+     */
+    rc = krdrFileGenericProtect(pRdr, pPrep, cSegments, paSegments, 1 /* unprotect */);
+    if (rc)
+    {
+        krdrFileGenericProtect(pRdr, pPrep, cSegments, paSegments, 0 /* protect */);
+        return rc;
+    }
+
+    /*
+     * Clear everything.
+     */
+    /** @todo only zero the areas not covered by raw file bits. */
+    kHlpMemSet(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 = (KU8 *)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 = krdrFileGenericProtect(pRdr, pPrep, cSegments, paSegments, 0 /* protect */);
+    if (rc2 && rc)
+        rc = rc2;
+
+    return rc;
+}
+
+
+/** @copydoc KRDROPS::pfnMap */
+static int      krdrFileMap(PKRDR pRdr, void **ppvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fFixed)
+{
+    PKRDRFILE       pRdrFile = (PKRDRFILE)pRdr;
+    PKRDRFILEPREP   pPrep = &pRdrFile->aPreps[pRdrFile->cPreps];
+    KLDRSIZE        cbTotal;
+    const KSIZE     cbPage = pRdr->pOps->pfnPageSize(pRdr);
+    int             rc;
+    KU32            i;
+
+    if (pRdrFile->cPreps >= K_ELEMENTS(pRdrFile->aPreps))
+        return KRDR_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 = (KSIZE)cbTotal;
+    if (pPrep->cb != cbTotal)
+        return KLDR_ERR_ADDRESS_OVERFLOW;
+    pPrep->cb = (pPrep->cb + (cbPage - 1)) & ~(cbPage- 1);
+
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+    /** @todo */
+
+#elif K_OS == K_OS_WINDOWS
+    /*
+     * 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 = (KSIZE)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 = (KU8 *)pPrep->pv + paSegments[i].RVA;
+            if (paSegments[i].cbFile > 0)
+            {
+                SectionOffset.QuadPart = paSegments[i].offFile;
+                ViewSize = paSegments[i].cbFile;
+                fPageProt = krdrFileGetNtMapProt(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 = krdrFileGetNtAllocProt(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 = (KU8 *)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 = krdrFileGenericMap(pRdr, pPrep, cSegments, paSegments, fFixed);
+    if (!rc)
+    {
+        *ppvBase = pPrep->pv;
+        pRdrFile->cPreps++;
+    }
+
+    return rc;
+}
+
+
+/** Generic implementation of krdrFileMap. */
+static int  krdrFileGenericMap(PKRDR pRdr, PKRDRFILEPREP pPrep, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fFixed)
+{
+    int rc;
+    KU32 i;
+
+    /*
+     * Generic mapping code using kHlpPageAlloc(), kHlpPageFree() and kHlpPageProtect().
+     */
+    rc = kHlpPageAlloc(&pPrep->pv, pPrep->cb, KPROT_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 = (KU8 *)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 = krdrFileGenericProtect(pRdr, pPrep, cSegments, paSegments, 0 /* protect */);
+        if (!rc)
+            return 0;
+        krdrFileGenericProtect(pRdr, pPrep, cSegments, paSegments, 1 /* unprotect */);
+    }
+
+    /* bailout */
+    kHlpPageFree(pPrep->pv, pPrep->cb);
+    return rc;
+}
+
+
+/** @copydoc KRDROPS::pfnPageSize */
+static KSIZE   krdrFilePageSize(PKRDR pRdr)
+{
+#if K_OS == K_OS_DARWIN
+    return 0x1000; /** @todo find some header somewhere... */
+
+#elif K_OS == K_OS_LINUX
+    return 0x1000; /** @todo find some header somewhere... */
+
+#elif K_OS == K_OS_OS2
+    /* The page size on OS/2 wont change anytime soon. :-) */
+    return 0x1000;
+
+#elif K_OS == K_OS_WINDOWS
+    SYSTEM_INFO SysInfo;
+    GetSystemInfo(&SysInfo);
+    return SysInfo.dwPageSize;
+    /*return SysInfo.dwAllocationGranularity;*/
+#else
+# error "port me"
+#endif
+}
+
+
+/** @copydoc KRDROPS::pfnName */
+static const char *krdrFileName(PKRDR pRdr)
+{
+    PKRDRFILE pRdrFile = (PKRDRFILE)pRdr;
+    return &pRdrFile->szFilename[0];
+}
+
+
+static KIPTR krdrFileNativeFH(PKRDR pRdr)
+{
+    PKRDRFILE pRdrFile = (PKRDRFILE)pRdr;
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_OS2 \
+ || K_OS == K_OS_SOLARIS \
+ || K_OS == K_OS_WINDOWS
+    return (KIPTR)pRdrFile->File;
+#else
+# error "port me"
+#endif
+}
+
+
+/** @copydoc KRDROPS::pfnTell */
+static KFOFF krdrFileTell(PKRDR pRdr)
+{
+    PKRDRFILE pRdrFile = (PKRDRFILE)pRdr;
+
+    /*
+     * If the offset is undefined, try figure out what it is.
+     */
+    if (pRdrFile->off == -1)
+    {
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+        pRdrFile->off = kHlpSys_lseek(pRdrFile->File, SEEK_CUR, 0);
+        if (pRdrFile->off < 0)
+            pRdrFile->off = -1;
+
+#elif K_OS == K_OS_OS2
+        ULONG ulNew;
+        APIRET rc = DosSetFilePtr(pRdrFile->File, 0, FILE_CURRENT, &ulNew);
+        if (rc)
+            return -1;
+        pRdrFile->off = ulNew;
+
+#elif K_OS == K_OS_WINDOWS
+        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 = ((KFOFF)offHigh << 32) | offLow;
+
+#else
+# error "port me."
+#endif
+    }
+    return pRdrFile->off;
+}
+
+
+/** @copydoc KRDROPS::pfnSize */
+static KFOFF krdrFileSize(PKRDR pRdr)
+{
+    PKRDRFILE pRdrFile = (PKRDRFILE)pRdr;
+    return pRdrFile->cb;
+}
+
+
+/** @copydoc KRDROPS::pfnAllUnmap */
+static int krdrFileAllUnmap(PKRDR pRdr, const void *pvBits)
+{
+    PKRDRFILE pRdrFile = (PKRDRFILE)pRdr;
+
+    /* check for underflow */
+    if (pRdrFile->cMappings <= 0)
+        return KERR_INVALID_PARAMETER;
+
+    /* decrement usage counter, free mapping if no longer in use. */
+    if (!--pRdrFile->cMappings)
+    {
+        kHlpFree(pRdrFile->pvMapping);
+        pRdrFile->pvMapping = NULL;
+    }
+
+    return 0;
+}
+
+
+/** @copydoc KRDROPS::pfnAllMap */
+static int krdrFileAllMap(PKRDR pRdr, const void **ppvBits)
+{
+    PKRDRFILE pRdrFile = (PKRDRFILE)pRdr;
+
+    /*
+     * Do we need to map it?
+     */
+    if (!pRdrFile->pvMapping)
+    {
+        int rc;
+        KFOFF cbFile = pRdrFile->Core.pOps->pfnSize(pRdr);
+        KSIZE cb = (KSIZE)cbFile;
+        if (cb != cbFile)
+            return KERR_NO_MEMORY;
+
+        pRdrFile->pvMapping = kHlpAlloc(cb);
+        if (!pRdrFile->pvMapping)
+            return KERR_NO_MEMORY;
+        rc = pRdrFile->Core.pOps->pfnRead(pRdr, pRdrFile->pvMapping, cb, 0);
+        if (rc)
+        {
+            kHlpFree(pRdrFile->pvMapping);
+            pRdrFile->pvMapping = NULL;
+            return rc;
+        }
+        pRdrFile->cMappings = 0;
+    }
+
+    *ppvBits = pRdrFile->pvMapping;
+    pRdrFile->cMappings++;
+    return 0;
+}
+
+
+/** @copydoc KRDROPS::pfnRead */
+static int krdrFileRead(PKRDR pRdr, void *pvBuf, KSIZE cb, KFOFF off)
+{
+    PKRDRFILE pRdrFile = (PKRDRFILE)pRdr;
+
+    /*
+     * Do a seek if needed.
+     */
+    if (pRdrFile->off != off)
+    {
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+        pRdrFile->off = kHlpSys_lseek(pRdrFile->File, SEEK_SET, off);
+        if (pRdrFile->off < 0)
+        {
+            int rc = (int)-pRdrFile->off;
+            pRdrFile->off = -1;
+            return -rc;
+        }
+
+#elif K_OS == K_OS_OS2
+        ULONG ulNew;
+        APIRET rc;
+
+        rc = DosSetFilePtr(pRdrFile->File, off, FILE_BEGIN, &ulNew);
+        if (rc)
+        {
+            pRdrFile->off = -1;
+            return rc;
+        }
+
+#elif K_OS == K_OS_WINDOWS
+        LONG offHigh;
+        LONG offLow;
+
+        offHigh = (LONG)(off >> 32);
+        offLow = SetFilePointer(pRdrFile->File, (LONG)off, &offHigh, FILE_BEGIN);
+        if (    offLow != (LONG)off
+            ||  offHigh != (LONG)(off >> 32))
+        {
+            int rc = GetLastError();
+            if (!rc)
+                rc = KERR_GENERAL_FAILURE;
+            pRdrFile->off = -1;
+            return rc;
+        }
+
+#else
+# error "port me."
+#endif
+    }
+
+    /*
+     * Do the read.
+     */
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+    {
+    KSSIZE cbRead;
+
+    cbRead = kHlpSys_read(pRdrFile->File, pvBuf, cb);
+    if (cbRead != cb)
+    {
+        pRdrFile->off = -1;
+        if (cbRead < 0)
+            return -cbRead;
+        return KERR_GENERAL_FAILURE;
+    }
+    }
+
+#elif K_OS == K_OS_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 KERR_GENERAL_FAILURE;
+    }
+    }
+
+#elif K_OS == K_OS_WINDOWS
+    {
+    DWORD cbRead = 0;
+    if (!ReadFile(pRdrFile->File, pvBuf, cb, &cbRead, NULL))
+    {
+        int rc = GetLastError();
+        if (!rc)
+            rc = KERR_GENERAL_FAILURE;
+        pRdrFile->off = -1;
+        return rc;
+    }
+    if (cbRead != cb)
+    {
+        pRdrFile->off = -1;
+        return KERR_GENERAL_FAILURE;
+    }
+    }
+
+#else
+# error "port me."
+#endif
+
+    pRdrFile->off = off + cb;
+    return 0;
+}
+
+
+/** @copydoc KRDROPS::pfnDestroy */
+static int krdrFileDestroy(PKRDR pRdr)
+{
+    PKRDRFILE    pRdrFile = (PKRDRFILE)pRdr;
+    int          rc;
+
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+    rc = kHlpSys_close(pRdrFile->File);
+
+#elif K_OS == K_OS_OS2
+    rc = DosClose(pRdrFile->File);
+
+#elif K_OS == K_OS_WINDOWS
+    rc = 0;
+    if (!CloseHandle(pRdrFile->File))
+        rc = GetLastError();
+
+#else
+# error "port me"
+#endif
+
+    if (pRdrFile->pvMapping)
+    {
+        kHlpFree(pRdrFile->pvMapping);
+        pRdrFile->pvMapping = NULL;
+    }
+
+    kHlpFree(pRdr);
+    return rc;
+}
+
+
+/** @copydoc KRDROPS::pfnCreate */
+static int krdrFileCreate(PPKRDR ppRdr, const char *pszFilename)
+{
+    KSIZE       cchFilename;
+    PKRDRFILE   pRdrFile;
+
+    /*
+     * Open the file, determin its size and correct filename.
+     */
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+    int         File;
+    KFOFF       cb;
+    KFOFF       rc;
+    char        szFilename[1024];
+
+    cchFilename = kHlpStrLen(pszFilename);
+    if (cchFilename >= sizeof(szFilename))
+        return KERR_OUT_OF_RANGE;
+    kHlpMemCopy(szFilename, pszFilename, cchFilename + 1);
+    /** @todo normalize the filename. */
+
+# ifdef O_BINARY
+    File = kHlpSys_open(pszFilename, O_RDONLY | O_BINARY, 0);
+# else
+    File = kHlpSys_open(pszFilename, O_RDONLY, 0);
+# endif
+    if (File < 0)
+        return -File;
+
+    cb = kHlpSys_lseek(File, SEEK_END, 0);
+    rc = kHlpSys_lseek(File, SEEK_SET, 0);
+    if (    cb < 0
+        ||  rc < 0)
+    {
+        kHlpSys_close(File);
+        return cb < 0 ? -cb : -rc;
+    }
+
+#elif K_OS == K_OS_OS2
+    ULONG       ulAction = 0;
+    FILESTATUS3 Info;
+    APIRET      rc;
+    HFILE       File = 0;
+    KFOFF       cb;
+    char        szFilename[CCHMAXPATH];
+
+    if ((uintptr_t)pszFilename >= 0x20000000)
+    {
+        char *psz;
+        cchFilename = kHlpStrLen(szFilename);
+        psz = (char *)kHlpAllocA(cchFilename + 1);
+        kHlpMemCopy(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 K_OS == K_OS_WINDOWS
+    SECURITY_ATTRIBUTES SecAttr;
+    DWORD               High;
+    DWORD               Low;
+    int                 rc;
+    HANDLE              File;
+    KFOFF            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;
+    }
+    cb = ((KFOFF)High << 32) | Low;
+
+#else
+# error "port me"
+#endif
+
+
+    /*
+     * Allocate the reader instance.
+     */
+    cchFilename = kHlpStrLen(szFilename);
+    pRdrFile = (PKRDRFILE)kHlpAlloc(sizeof(*pRdrFile) + cchFilename);
+    if (!pRdrFile)
+    {
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+        kHlpSys_close(File);
+#elif K_OS == K_OS_OS2
+        DosClose(File);
+#elif K_OS == K_OS_WINDOWS
+        CloseHandle(File);
+#else
+# error "port me"
+#endif
+        return KERR_NO_MEMORY;
+    }
+
+    /*
+     * Initialize it and return successfully.
+     */
+    pRdrFile->Core.u32Magic = KRDR_MAGIC;
+    pRdrFile->Core.pOps = &g_kRdrFileOps;
+    pRdrFile->File = File;
+    pRdrFile->cb = cb;
+    pRdrFile->off = 0;
+    pRdrFile->cPreps = 0;
+    pRdrFile->cMappings = 0;
+    pRdrFile->pvMapping = NULL;
+    kHlpMemCopy(&pRdrFile->szFilename[0], szFilename, cchFilename + 1);
+
+    *ppRdr = &pRdrFile->Core;
+    return 0;
+}
+
diff --git a/src/lib/kStuff/kRdr/kRdrInternal.h b/src/lib/kStuff/kRdr/kRdrInternal.h
new file mode 100644
index 0000000..d8f67db
--- /dev/null
+++ b/src/lib/kStuff/kRdr/kRdrInternal.h
@@ -0,0 +1,122 @@
+/* $Id: kRdrInternal.h 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kRdr - Internal Header.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___kRdrInternal_h___
+#define ___kRdrInternal_h___
+
+#include <k/kHlpAssert.h>
+#include <k/kMagics.h>
+#include <k/kRdrAll.h>
+#include <k/kErrors.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup grp_kRdrInternal - Internals
+ * @internal
+ * @addtogroup grp_kRdr
+ * @{
+ */
+
+/** @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 (    !K_VALID_PTR(pRdr) \
+            ||  (pRdr)->u32Magic != KRDR_MAGIC \
+            ||  (pRdr)->pOps == NULL \
+           )\
+        { \
+            return; \
+        } \
+    } while (0)
+
+
+/** @name Built-in Providers
+ * @{ */
+extern const KRDROPS g_kRdrFileOps;
+/** @} */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/lib/kbuild_version.c b/src/lib/kbuild_version.c
new file mode 100644
index 0000000..962c5e7
--- /dev/null
+++ b/src/lib/kbuild_version.c
@@ -0,0 +1,64 @@
+/* $Id: kbuild_version.c 2851 2016-08-31 17:30:52Z bird $ */
+/** @file
+ * kbuild_version(), helper function.
+ */
+
+/*
+ * Copyright (c) 2007-2013 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "kbuild_version.h"
+#include <string.h>
+#include <stdio.h>
+
+
+/**
+ * Prints the kBuild version message and returns 0.
+ *
+ * @returns 0
+ * @param   argv0       The argv0.
+ */
+int kbuild_version(const char *argv0)
+{
+    const char *tmp;
+
+    /* skip the path */
+    for (tmp = strpbrk(argv0, "\\/:"); tmp; tmp = strpbrk(argv0, "\\/:"))
+        argv0 = tmp + 1;
+
+    /* find the end, ignoring extenions */
+    tmp = strrchr(argv0, '.');
+    if (!tmp)
+        tmp = strchr(argv0, '\0');
+
+    printf("%.*s - kBuild version %d.%d.%d (r%u)\n",
+           (int)(tmp - argv0), argv0,
+           KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH,
+           KBUILD_SVN_REV);
+    return 0;
+}
+
diff --git a/src/lib/kbuild_version.h b/src/lib/kbuild_version.h
new file mode 100644
index 0000000..dba3d0b
--- /dev/null
+++ b/src/lib/kbuild_version.h
@@ -0,0 +1,37 @@
+/* $Id: kbuild_version.h 2851 2016-08-31 17:30:52Z bird $ */
+/** @file
+ * kbuild_version(), helper function.
+ */
+
+/*
+ * Copyright (c) 2007-2013 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
+ */
+
+#ifndef ___lib_kbuild_version_h___
+#define ___lib_kbuild_version_h___
+
+int kbuild_version(const char *argv0);
+
+#endif
+
diff --git a/src/lib/mytypes.h b/src/lib/mytypes.h
index f546a20..877df8f 100644
--- a/src/lib/mytypes.h
+++ b/src/lib/mytypes.h
@@ -1,30 +1,35 @@
-/* $Id: mytypes.h 2442 2011-07-06 12:19:16Z bird $ */
+/* $Id: mytypes.h 2851 2016-08-31 17:30:52Z bird $ */
 /** @file
  * mytypes - wrapper that ensures the necessary uintXY_t types are defined.
  */
 
 /*
- * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ * Copyright (c) 2007-2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
  *
- * This file is part of kBuild.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
  *
- * kBuild 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 3 of the License, or
- * (at your option) any later version.
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
  *
- * kBuild 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 kBuild.  If not, see <http://www.gnu.org/licenses/>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
  *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
  */
 
-#ifndef ___mytypes_h__
-#define ___mytypes_h__
+#ifndef ___mytypes_h___
+#define ___mytypes_h___
 
 #include <stdlib.h>
 #include <stddef.h> /* MSC: intptr_t */
diff --git a/src/lib/nt/kFsCache.c b/src/lib/nt/kFsCache.c
new file mode 100644
index 0000000..dd3140b
--- /dev/null
+++ b/src/lib/nt/kFsCache.c
@@ -0,0 +1,4055 @@
+/* $Id: kFsCache.c 2879 2016-09-05 20:14:21Z bird $ */
+/** @file
+ * ntdircache.c - NT directory content cache.
+ */
+
+/*
+ * Copyright (c) 2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <k/kHlp.h>
+
+#include "nthlp.h"
+#include "ntstat.h"
+
+#include <stdio.h>
+#include <mbstring.h>
+#include <wchar.h>
+//#include <intrin.h>
+//#include <setjmp.h>
+//#include <ctype.h>
+
+
+//#include <Windows.h>
+//#include <winternl.h>
+
+#include "kFsCache.h"
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+/** @def KFSCACHE_LOG2
+ * More logging. */
+#if 0
+# define KFSCACHE_LOG2(a) KFSCACHE_LOG(a)
+#else
+# define KFSCACHE_LOG2(a) do { } while (0)
+#endif
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * Used by the code re-populating a directory.
+ */
+typedef struct KFSDIRREPOP
+{
+    /** The old papChildren array. */
+    PKFSOBJ    *papOldChildren;
+    /** Number of children in the array. */
+    KU32        cOldChildren;
+    /** The index into papOldChildren we expect to find the next entry.  */
+    KU32        iNextOldChild;
+    /** Add this to iNextOldChild . */
+    KI32        cNextOldChildInc;
+    /** Pointer to the cache (name changes). */
+    PKFSCACHE   pCache;
+} KFSDIRREPOP;
+/** Pointer to directory re-population data. */
+typedef KFSDIRREPOP *PKFSDIRREPOP;
+
+
+
+
+/**
+ * Retains a reference to a cache object, internal version.
+ *
+ * @returns pObj
+ * @param   pObj                The object.
+ */
+K_INLINE PKFSOBJ kFsCacheObjRetainInternal(PKFSOBJ pObj)
+{
+    KU32 cRefs = ++pObj->cRefs;
+    kHlpAssert(cRefs < 16384);
+    K_NOREF(cRefs);
+    return pObj;
+}
+
+
+#ifndef NDEBUG
+
+/**
+ * Debug printing.
+ * @param   pszFormat           Debug format string.
+ * @param   ...                 Format argument.
+ */
+void kFsCacheDbgPrintfV(const char *pszFormat, va_list va)
+{
+    if (1)
+    {
+        DWORD const dwSavedErr = GetLastError();
+
+        fprintf(stderr, "debug: ");
+        vfprintf(stderr, pszFormat, va);
+
+        SetLastError(dwSavedErr);
+    }
+}
+
+
+/**
+ * Debug printing.
+ * @param   pszFormat           Debug format string.
+ * @param   ...                 Format argument.
+ */
+void kFsCacheDbgPrintf(const char *pszFormat, ...)
+{
+    if (1)
+    {
+        va_list va;
+        va_start(va, pszFormat);
+        kFsCacheDbgPrintfV(pszFormat, va);
+        va_end(va);
+    }
+}
+
+#endif /* !NDEBUG */
+
+
+
+/**
+ * Hashes a string.
+ *
+ * @returns 32-bit string hash.
+ * @param   pszString           String to hash.
+ */
+static KU32 kFsCacheStrHash(const char *pszString)
+{
+    /* This algorithm was created for sdbm (a public-domain reimplementation of
+       ndbm) database library. it was found to do well in scrambling bits,
+       causing better distribution of the keys and fewer splits. it also happens
+       to be a good general hashing function with good distribution. the actual
+       function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below
+       is the faster version used in gawk. [there is even a faster, duff-device
+       version] the magic constant 65599 was picked out of thin air while
+       experimenting with different constants, and turns out to be a prime.
+       this is one of the algorithms used in berkeley db (see sleepycat) and
+       elsewhere. */
+    KU32 uHash = 0;
+    KU32 uChar;
+    while ((uChar = (unsigned char)*pszString++) != 0)
+        uHash = uChar + (uHash << 6) + (uHash << 16) - uHash;
+    return uHash;
+}
+
+
+/**
+ * Hashes a string.
+ *
+ * @returns The string length.
+ * @param   pszString           String to hash.
+ * @param   puHash              Where to return the 32-bit string hash.
+ */
+static KSIZE kFsCacheStrHashEx(const char *pszString, KU32 *puHash)
+{
+    const char * const pszStart = pszString;
+    KU32 uHash = 0;
+    KU32 uChar;
+    while ((uChar = (unsigned char)*pszString) != 0)
+    {
+        uHash = uChar + (uHash << 6) + (uHash << 16) - uHash;
+        pszString++;
+    }
+    *puHash = uHash;
+    return pszString - pszStart;
+}
+
+
+/**
+ * Hashes a substring.
+ *
+ * @returns 32-bit substring hash.
+ * @param   pchString           Pointer to the substring (not terminated).
+ * @param   cchString           The length of the substring.
+ */
+static KU32 kFsCacheStrHashN(const char *pszString, KSIZE cchString)
+{
+    KU32 uHash = 0;
+    while (cchString-- > 0)
+    {
+        KU32 uChar = (unsigned char)*pszString++;
+        uHash = uChar + (uHash << 6) + (uHash << 16) - uHash;
+    }
+    return uHash;
+}
+
+
+/**
+ * Hashes a UTF-16 string.
+ *
+ * @returns The string length in wchar_t units.
+ * @param   pwszString          String to hash.
+ * @param   puHash              Where to return the 32-bit string hash.
+ */
+static KSIZE kFsCacheUtf16HashEx(const wchar_t *pwszString, KU32 *puHash)
+{
+    const wchar_t * const pwszStart = pwszString;
+    KU32 uHash = 0;
+    KU32 uChar;
+    while ((uChar = *pwszString) != 0)
+    {
+        uHash = uChar + (uHash << 6) + (uHash << 16) - uHash;
+        pwszString++;
+    }
+    *puHash = uHash;
+    return pwszString - pwszStart;
+}
+
+
+/**
+ * Hashes a UTF-16 substring.
+ *
+ * @returns 32-bit substring hash.
+ * @param   pwcString           Pointer to the substring (not terminated).
+ * @param   cchString           The length of the substring (in wchar_t's).
+ */
+static KU32 kFsCacheUtf16HashN(const wchar_t *pwcString, KSIZE cwcString)
+{
+    KU32 uHash = 0;
+    while (cwcString-- > 0)
+    {
+        KU32 uChar = *pwcString++;
+        uHash = uChar + (uHash << 6) + (uHash << 16) - uHash;
+    }
+    return uHash;
+}
+
+
+/**
+ * For use when kFsCacheIAreEqualW hit's something non-trivial.
+ *
+ * @returns K_TRUE if equal, K_FALSE if different.
+ * @param   pwcName1            The first string.
+ * @param   pwcName2            The second string.
+ * @param   cwcName             The length of the two strings (in wchar_t's).
+ */
+KBOOL kFsCacheIAreEqualSlowW(const wchar_t *pwcName1, const wchar_t *pwcName2, KU16 cwcName)
+{
+    MY_UNICODE_STRING UniStr1 = { cwcName * sizeof(wchar_t), cwcName * sizeof(wchar_t), (wchar_t *)pwcName1 };
+    MY_UNICODE_STRING UniStr2 = { cwcName * sizeof(wchar_t), cwcName * sizeof(wchar_t), (wchar_t *)pwcName2 };
+    return g_pfnRtlEqualUnicodeString(&UniStr1, &UniStr2, TRUE /*fCaseInsensitive*/);
+}
+
+
+/**
+ * Compares two UTF-16 strings in a case-insensitive fashion.
+ *
+ * You would think we should be using _wscnicmp here instead, however it is
+ * locale dependent and defaults to ASCII upper/lower handling setlocale hasn't
+ * been called.
+ *
+ * @returns K_TRUE if equal, K_FALSE if different.
+ * @param   pwcName1            The first string.
+ * @param   pwcName2            The second string.
+ * @param   cwcName             The length of the two strings (in wchar_t's).
+ */
+K_INLINE KBOOL kFsCacheIAreEqualW(const wchar_t *pwcName1, const wchar_t *pwcName2, KU32 cwcName)
+{
+    while (cwcName > 0)
+    {
+        wchar_t wc1 = *pwcName1;
+        wchar_t wc2 = *pwcName2;
+        if (wc1 == wc2)
+        { /* not unlikely */ }
+        else if (  (KU16)wc1 < (KU16)0xc0 /* U+00C0 is the first upper/lower letter after 'z'. */
+                && (KU16)wc2 < (KU16)0xc0)
+        {
+            /* ASCII upper case. */
+            if ((KU16)wc1 - (KU16)0x61 < (KU16)26)
+                wc1 &= ~(wchar_t)0x20;
+            if ((KU16)wc2 - (KU16)0x61 < (KU16)26)
+                wc2 &= ~(wchar_t)0x20;
+            if (wc1 != wc2)
+                return K_FALSE;
+        }
+        else
+            return kFsCacheIAreEqualSlowW(pwcName1, pwcName2, (KU16)cwcName);
+
+        pwcName2++;
+        pwcName1++;
+        cwcName--;
+    }
+
+    return K_TRUE;
+}
+
+
+/**
+ * Looks for '..' in the path.
+ *
+ * @returns K_TRUE if '..' component found, K_FALSE if not.
+ * @param   pszPath             The path.
+ * @param   cchPath             The length of the path.
+ */
+static KBOOL kFsCacheHasDotDotA(const char *pszPath, KSIZE cchPath)
+{
+    const char *pchDot = (const char *)kHlpMemChr(pszPath, '.', cchPath);
+    while (pchDot)
+    {
+        if (pchDot[1] != '.')
+        {
+            pchDot++;
+            pchDot = (const char *)kHlpMemChr(pchDot, '.', &pszPath[cchPath] - pchDot);
+        }
+        else
+        {
+            char ch;
+            if (   (ch = pchDot[2]) != '\0'
+                && IS_SLASH(ch))
+            {
+                if (pchDot == pszPath)
+                    return K_TRUE;
+                ch = pchDot[-1];
+                if (   IS_SLASH(ch)
+                    || ch == ':')
+                    return K_TRUE;
+            }
+            pchDot = (const char *)kHlpMemChr(pchDot + 2, '.', &pszPath[cchPath] - pchDot - 2);
+        }
+    }
+
+    return K_FALSE;
+}
+
+
+/**
+ * Looks for '..' in the path.
+ *
+ * @returns K_TRUE if '..' component found, K_FALSE if not.
+ * @param   pwszPath            The path.
+ * @param   cwcPath             The length of the path (in wchar_t's).
+ */
+static KBOOL kFsCacheHasDotDotW(const wchar_t *pwszPath, KSIZE cwcPath)
+{
+    const wchar_t *pwcDot = wmemchr(pwszPath, '.', cwcPath);
+    while (pwcDot)
+    {
+        if (pwcDot[1] != '.')
+        {
+            pwcDot++;
+            pwcDot = wmemchr(pwcDot, '.', &pwszPath[cwcPath] - pwcDot);
+        }
+        else
+        {
+            wchar_t wch;
+            if (   (wch = pwcDot[2]) != '\0'
+                && IS_SLASH(wch))
+            {
+                if (pwcDot == pwszPath)
+                    return K_TRUE;
+                wch = pwcDot[-1];
+                if (   IS_SLASH(wch)
+                    || wch == ':')
+                    return K_TRUE;
+            }
+            pwcDot = wmemchr(pwcDot + 2, '.', &pwszPath[cwcPath] - pwcDot - 2);
+        }
+    }
+
+    return K_FALSE;
+}
+
+
+/**
+ * Creates an ANSI hash table entry for the given path.
+ *
+ * @returns The hash table entry or NULL if out of memory.
+ * @param   pCache              The hash
+ * @param   pFsObj              The resulting object.
+ * @param   pszPath             The path.
+ * @param   cchPath             The length of the path.
+ * @param   uHashPath           The hash of the path.
+ * @param   fAbsolute           Whether it can be refreshed using an absolute
+ *                              lookup or requires the slow treatment.
+ * @parma   idxMissingGen       The missing generation index.
+ * @param   idxHashTab          The hash table index of the path.
+ * @param   enmError            The lookup error.
+ */
+static PKFSHASHA kFsCacheCreatePathHashTabEntryA(PKFSCACHE pCache, PKFSOBJ pFsObj, const char *pszPath, KU32 cchPath,
+                                                 KU32 uHashPath, KU32 idxHashTab, BOOL fAbsolute, KU32 idxMissingGen,
+                                                 KFSLOOKUPERROR enmError)
+{
+    PKFSHASHA pHashEntry = (PKFSHASHA)kHlpAlloc(sizeof(*pHashEntry) + cchPath + 1);
+    if (pHashEntry)
+    {
+        pHashEntry->uHashPath       = uHashPath;
+        pHashEntry->cchPath         = (KU16)cchPath;
+        pHashEntry->fAbsolute       = fAbsolute;
+        pHashEntry->idxMissingGen   = (KU8)idxMissingGen;
+        pHashEntry->enmError        = enmError;
+        pHashEntry->pszPath         = (const char *)kHlpMemCopy(pHashEntry + 1, pszPath, cchPath + 1);
+        if (pFsObj)
+        {
+            pHashEntry->pFsObj      = kFsCacheObjRetainInternal(pFsObj);
+            pHashEntry->uCacheGen   = pFsObj->bObjType != KFSOBJ_TYPE_MISSING
+                                    ? pCache->auGenerations[       pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                    : pCache->auGenerationsMissing[pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
+            pFsObj->abUnused[0] += 1; // for debugging
+        }
+        else
+        {
+            pHashEntry->pFsObj      = NULL;
+            if (enmError != KFSLOOKUPERROR_UNSUPPORTED)
+                pHashEntry->uCacheGen = pCache->auGenerationsMissing[idxMissingGen];
+            else
+                pHashEntry->uCacheGen = KFSOBJ_CACHE_GEN_IGNORE;
+        }
+
+        pHashEntry->pNext = pCache->apAnsiPaths[idxHashTab];
+        pCache->apAnsiPaths[idxHashTab] = pHashEntry;
+
+        pCache->cbAnsiPaths += sizeof(*pHashEntry) + cchPath + 1;
+        pCache->cAnsiPaths++;
+        if (pHashEntry->pNext)
+            pCache->cAnsiPathCollisions++;
+    }
+    return pHashEntry;
+}
+
+
+/**
+ * Creates an UTF-16 hash table entry for the given path.
+ *
+ * @returns The hash table entry or NULL if out of memory.
+ * @param   pCache              The hash
+ * @param   pFsObj              The resulting object.
+ * @param   pwszPath            The path.
+ * @param   cwcPath             The length of the path (in wchar_t's).
+ * @param   uHashPath           The hash of the path.
+ * @param   fAbsolute           Whether it can be refreshed using an absolute
+ *                              lookup or requires the slow treatment.
+ * @parma   idxMissingGen       The missing generation index.
+ * @param   idxHashTab          The hash table index of the path.
+ * @param   enmError            The lookup error.
+ */
+static PKFSHASHW kFsCacheCreatePathHashTabEntryW(PKFSCACHE pCache, PKFSOBJ pFsObj, const wchar_t *pwszPath, KU32 cwcPath,
+                                                 KU32 uHashPath, KU32 idxHashTab, BOOL fAbsolute, KU32 idxMissingGen,
+                                                 KFSLOOKUPERROR enmError)
+{
+    PKFSHASHW pHashEntry = (PKFSHASHW)kHlpAlloc(sizeof(*pHashEntry) + (cwcPath + 1) * sizeof(wchar_t));
+    if (pHashEntry)
+    {
+        pHashEntry->uHashPath       = uHashPath;
+        pHashEntry->cwcPath         = cwcPath;
+        pHashEntry->fAbsolute       = fAbsolute;
+        pHashEntry->idxMissingGen   = (KU8)idxMissingGen;
+        pHashEntry->enmError        = enmError;
+        pHashEntry->pwszPath        = (const wchar_t *)kHlpMemCopy(pHashEntry + 1, pwszPath, (cwcPath + 1) * sizeof(wchar_t));
+        if (pFsObj)
+        {
+            pHashEntry->pFsObj      = kFsCacheObjRetainInternal(pFsObj);
+            pHashEntry->uCacheGen   = pFsObj->bObjType != KFSOBJ_TYPE_MISSING
+                                    ? pCache->auGenerations[       pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                    : pCache->auGenerationsMissing[pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
+            pFsObj->abUnused[0] += 1; // for debugging
+        }
+        else
+        {
+            pHashEntry->pFsObj      = NULL;
+            if (enmError != KFSLOOKUPERROR_UNSUPPORTED)
+                pHashEntry->uCacheGen = pCache->auGenerationsMissing[idxMissingGen];
+            else
+                pHashEntry->uCacheGen = KFSOBJ_CACHE_GEN_IGNORE;
+        }
+
+        pHashEntry->pNext = pCache->apUtf16Paths[idxHashTab];
+        pCache->apUtf16Paths[idxHashTab] = pHashEntry;
+
+        pCache->cbUtf16Paths += sizeof(*pHashEntry) + (cwcPath + 1) * sizeof(wchar_t);
+        pCache->cUtf16Paths++;
+        if (pHashEntry->pNext)
+            pCache->cAnsiPathCollisions++;
+    }
+    return pHashEntry;
+}
+
+
+/**
+ * Links the child in under the parent.
+ *
+ * @returns K_TRUE on success, K_FALSE if out of memory.
+ * @param   pParent             The parent node.
+ * @param   pChild              The child node.
+ */
+static KBOOL kFsCacheDirAddChild(PKFSCACHE pCache, PKFSDIR pParent, PKFSOBJ pChild, KFSLOOKUPERROR *penmError)
+{
+    if (pParent->cChildren >= pParent->cChildrenAllocated)
+    {
+        void *pvNew = kHlpRealloc(pParent->papChildren, (pParent->cChildrenAllocated + 16) * sizeof(pParent->papChildren[0]));
+        if (!pvNew)
+            return K_FALSE;
+        pParent->papChildren = (PKFSOBJ *)pvNew;
+        pParent->cChildrenAllocated += 16;
+        pCache->cbObjects += 16 * sizeof(pParent->papChildren[0]);
+    }
+    pParent->papChildren[pParent->cChildren++] = kFsCacheObjRetainInternal(pChild);
+    return K_TRUE;
+}
+
+
+/**
+ * Creates a new cache object.
+ *
+ * @returns Pointer (with 1 reference) to the new object.  The object will not
+ *          be linked to the parent directory yet.
+ *
+ *          NULL if we're out of memory.
+ *
+ * @param   pCache          The cache.
+ * @param   pParent         The parent directory.
+ * @param   pszName         The ANSI name.
+ * @param   cchName         The length of the ANSI name.
+ * @param   pwszName        The UTF-16 name.
+ * @param   cwcName         The length of the UTF-16 name.
+ * @param   pszShortName    The ANSI short name, NULL if none.
+ * @param   cchShortName    The length of the ANSI short name, 0 if none.
+ * @param   pwszShortName   The UTF-16 short name, NULL if none.
+ * @param   cwcShortName    The length of the UTF-16 short name, 0 if none.
+ * @param   bObjType        The objct type.
+ * @param   penmError       Where to explain failures.
+ */
+PKFSOBJ kFsCacheCreateObject(PKFSCACHE pCache, PKFSDIR pParent,
+                             char const *pszName, KU16 cchName, wchar_t const *pwszName, KU16 cwcName,
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                             char const *pszShortName, KU16 cchShortName, wchar_t const *pwszShortName, KU16 cwcShortName,
+#endif
+                             KU8 bObjType, KFSLOOKUPERROR *penmError)
+{
+    /*
+     * Allocate the object.
+     */
+    KBOOL const fDirish = bObjType != KFSOBJ_TYPE_FILE && bObjType != KFSOBJ_TYPE_OTHER;
+    KSIZE const cbObj   = fDirish ? sizeof(KFSDIR) : sizeof(KFSOBJ);
+    KSIZE const cbNames = (cwcName + 1) * sizeof(wchar_t)                           + cchName + 1
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                        + (cwcShortName > 0 ? (cwcShortName + 1) * sizeof(wchar_t)  + cchShortName + 1 : 0)
+#endif
+                          ;
+    PKFSOBJ pObj;
+    kHlpAssert(pCache->u32Magic == KFSCACHE_MAGIC);
+
+    pObj = (PKFSOBJ)kHlpAlloc(cbObj + cbNames);
+    if (pObj)
+    {
+        KU8 *pbExtra = (KU8 *)pObj + cbObj;
+
+        pCache->cbObjects += cbObj + cbNames;
+        pCache->cObjects++;
+
+        /*
+         * Initialize the object.
+         */
+        pObj->u32Magic      = KFSOBJ_MAGIC;
+        pObj->cRefs         = 1;
+        pObj->uCacheGen     = bObjType != KFSOBJ_TYPE_MISSING
+                            ? pCache->auGenerations[pParent->Obj.fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                            : pCache->auGenerationsMissing[pParent->Obj.fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
+        pObj->bObjType      = bObjType;
+        pObj->fHaveStats    = K_FALSE;
+        pObj->abUnused[0]   = K_FALSE;
+        pObj->abUnused[1]   = K_FALSE;
+        pObj->fFlags        = pParent->Obj.fFlags & KFSOBJ_F_INHERITED_MASK;
+        pObj->pParent       = pParent;
+        pObj->pUserDataHead = NULL;
+
+#ifdef KFSCACHE_CFG_UTF16
+        pObj->cwcParent = pParent->Obj.cwcParent + pParent->Obj.cwcName + !!pParent->Obj.cwcName;
+        pObj->pwszName  = (wchar_t *)kHlpMemCopy(pbExtra, pwszName, cwcName * sizeof(wchar_t));
+        pObj->cwcName   = cwcName;
+        pbExtra += cwcName * sizeof(wchar_t);
+        *pbExtra++ = '\0';
+        *pbExtra++ = '\0';
+# ifdef KFSCACHE_CFG_SHORT_NAMES
+        pObj->cwcShortParent = pParent->Obj.cwcShortParent + pParent->Obj.cwcShortName + !!pParent->Obj.cwcShortName;
+        if (cwcShortName)
+        {
+            pObj->pwszShortName = (wchar_t *)kHlpMemCopy(pbExtra, pwszShortName, cwcShortName * sizeof(wchar_t));
+            pObj->cwcShortName  = cwcShortName;
+            pbExtra += cwcShortName * sizeof(wchar_t);
+            *pbExtra++ = '\0';
+            *pbExtra++ = '\0';
+        }
+        else
+        {
+            pObj->pwszShortName = pObj->pwszName;
+            pObj->cwcShortName  = cwcName;
+        }
+# endif
+#endif
+        pObj->cchParent = pParent->Obj.cchParent + pParent->Obj.cchName + !!pParent->Obj.cchName;
+        pObj->pszName   = (char *)kHlpMemCopy(pbExtra, pszName, cchName);
+        pObj->cchName   = cchName;
+        pbExtra += cchName;
+        *pbExtra++ = '\0';
+# ifdef KFSCACHE_CFG_SHORT_NAMES
+        pObj->cchShortParent = pParent->Obj.cchShortParent + pParent->Obj.cchShortName + !!pParent->Obj.cchShortName;
+        if (cchShortName)
+        {
+            pObj->pszShortName = (char *)kHlpMemCopy(pbExtra, pszShortName, cchShortName);
+            pObj->cchShortName = cchShortName;
+            pbExtra += cchShortName;
+            *pbExtra++ = '\0';
+        }
+        else
+        {
+            pObj->pszShortName = pObj->pszName;
+            pObj->cchShortName = cchName;
+        }
+#endif
+        kHlpAssert(pbExtra - (KU8 *)pObj == cbObj);
+
+        /*
+         * Type specific initilization.
+         */
+        if (fDirish)
+        {
+            PKFSDIR pDirObj = (PKFSDIR)pObj;
+            pDirObj->cChildren          = 0;
+            pDirObj->cChildrenAllocated = 0;
+            pDirObj->papChildren        = NULL;
+            pDirObj->cHashTab           = 0;
+            pDirObj->paHashTab          = NULL;
+            pDirObj->hDir               = INVALID_HANDLE_VALUE;
+            pDirObj->uDevNo             = pParent->uDevNo;
+            pDirObj->iLastWrite         = 0;
+            pDirObj->fPopulated         = K_FALSE;
+        }
+    }
+    else
+        *penmError = KFSLOOKUPERROR_OUT_OF_MEMORY;
+    return pObj;
+}
+
+
+/**
+ * Creates a new object given wide char names.
+ *
+ * This function just converts the paths and calls kFsCacheCreateObject.
+ *
+ *
+ * @returns Pointer (with 1 reference) to the new object.  The object will not
+ *          be linked to the parent directory yet.
+ *
+ *          NULL if we're out of memory.
+ *
+ * @param   pCache          The cache.
+ * @param   pParent         The parent directory.
+ * @param   pszName         The ANSI name.
+ * @param   cchName         The length of the ANSI name.
+ * @param   pwszName        The UTF-16 name.
+ * @param   cwcName         The length of the UTF-16 name.
+ * @param   pwszShortName   The UTF-16 short name, NULL if none.
+ * @param   cwcShortName    The length of the UTF-16 short name, 0 if none.
+ * @param   bObjType        The objct type.
+ * @param   penmError       Where to explain failures.
+ */
+PKFSOBJ kFsCacheCreateObjectW(PKFSCACHE pCache, PKFSDIR pParent, wchar_t const *pwszName, KU32 cwcName,
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                              wchar_t const *pwszShortName, KU32 cwcShortName,
+#endif
+                              KU8 bObjType, KFSLOOKUPERROR *penmError)
+{
+    /* Convert names to ANSI first so we know their lengths. */
+    char szName[KFSCACHE_CFG_MAX_ANSI_NAME];
+    int  cchName = WideCharToMultiByte(CP_ACP, 0, pwszName, cwcName, szName, sizeof(szName) - 1, NULL, NULL);
+    if (cchName >= 0)
+    {
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+        char szShortName[12*3 + 1];
+        int  cchShortName = 0;
+        if (   cwcShortName == 0
+            || (cchShortName = WideCharToMultiByte(CP_ACP, 0, pwszShortName, cwcShortName,
+                                                   szShortName, sizeof(szShortName) - 1, NULL, NULL)) > 0)
+#endif
+        {
+            return kFsCacheCreateObject(pCache, pParent,
+                                        szName, cchName, pwszName, cwcName,
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                                        szShortName, cchShortName, pwszShortName, cwcShortName,
+#endif
+                                        bObjType, penmError);
+        }
+    }
+    *penmError = KFSLOOKUPERROR_ANSI_CONVERSION_ERROR;
+    return NULL;
+}
+
+
+/**
+ * Creates a missing object.
+ *
+ * This is used for caching negative results.
+ *
+ * @returns Pointer to the newly created object on success (already linked into
+ *          pParent).  No reference.
+ *
+ *          NULL on failure.
+ *
+ * @param   pCache              The cache.
+ * @param   pParent             The parent directory.
+ * @param   pchName             The name.
+ * @param   cchName             The length of the name.
+ * @param   penmError           Where to return failure explanations.
+ */
+static PKFSOBJ kFsCacheCreateMissingA(PKFSCACHE pCache, PKFSDIR pParent, const char *pchName, KU32 cchName,
+                                      KFSLOOKUPERROR *penmError)
+{
+    /*
+     * Just convert the name to UTF-16 and call kFsCacheCreateObject to do the job.
+     */
+    wchar_t wszName[KFSCACHE_CFG_MAX_PATH];
+    int cwcName = MultiByteToWideChar(CP_ACP, 0, pchName, cchName, wszName, KFSCACHE_CFG_MAX_UTF16_NAME - 1);
+    if (cwcName > 0)
+    {
+        /** @todo check that it actually doesn't exists before we add it.  We should not
+         *        trust the directory enumeration here, or maybe we should?? */
+
+        PKFSOBJ pMissing = kFsCacheCreateObject(pCache, pParent, pchName, cchName, wszName, cwcName,
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                                                NULL, 0, NULL, 0,
+#endif
+                                                KFSOBJ_TYPE_MISSING, penmError);
+        if (pMissing)
+        {
+            KBOOL fRc = kFsCacheDirAddChild(pCache, pParent, pMissing, penmError);
+            kFsCacheObjRelease(pCache, pMissing);
+            return fRc ? pMissing : NULL;
+        }
+        return NULL;
+    }
+    *penmError = KFSLOOKUPERROR_UTF16_CONVERSION_ERROR;
+    return NULL;
+}
+
+
+/**
+ * Creates a missing object, UTF-16 version.
+ *
+ * This is used for caching negative results.
+ *
+ * @returns Pointer to the newly created object on success (already linked into
+ *          pParent).  No reference.
+ *
+ *          NULL on failure.
+ *
+ * @param   pCache              The cache.
+ * @param   pParent             The parent directory.
+ * @param   pwcName             The name.
+ * @param   cwcName             The length of the name.
+ * @param   penmError           Where to return failure explanations.
+ */
+static PKFSOBJ kFsCacheCreateMissingW(PKFSCACHE pCache, PKFSDIR pParent, const wchar_t *pwcName, KU32 cwcName,
+                                      KFSLOOKUPERROR *penmError)
+{
+    /** @todo check that it actually doesn't exists before we add it.  We should not
+     *        trust the directory enumeration here, or maybe we should?? */
+    PKFSOBJ pMissing = kFsCacheCreateObjectW(pCache, pParent, pwcName, cwcName,
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                                             NULL, 0,
+#endif
+                                             KFSOBJ_TYPE_MISSING, penmError);
+    if (pMissing)
+    {
+        KBOOL fRc = kFsCacheDirAddChild(pCache, pParent, pMissing, penmError);
+        kFsCacheObjRelease(pCache, pMissing);
+        return fRc ? pMissing : NULL;
+    }
+    return NULL;
+}
+
+/**
+ * Worker for kFsCacheDirFindOldChild that refreshes the file ID value on an
+ * object found by name.
+ *
+ * @returns Pointer to the existing object if found, NULL if not.
+ * @param   pDirRePop       Repopulation data.
+ * @param   pCur            The object to check the names of.
+ * @param   idFile          The file ID.
+ */
+static PKFSOBJ kFsCacheDirRefreshOldChildFileId(PKFSDIRREPOP pDirRePop, PKFSOBJ pCur, KI64 idFile)
+{
+    KFSCACHE_LOG(("Refreshing %s/%s/ - %s changed file ID from %#llx -> %#llx...\n",
+                  pCur->pParent->Obj.pParent->Obj.pszName, pCur->pParent->Obj.pszName, pCur->pszName,
+                  pCur->Stats.st_ino, idFile));
+    pCur->Stats.st_ino = idFile;
+    /** @todo inform user data items...  */
+    return pCur;
+}
+
+
+/**
+ * Worker for kFsCacheDirFindOldChild that checks the names after an old object
+ * has been found the file ID.
+ *
+ * @returns Pointer to the existing object if found, NULL if not.
+ * @param   pDirRePop       Repopulation data.
+ * @param   pCur            The object to check the names of.
+ * @param   pwcName         The file name.
+ * @param   cwcName         The length of the filename (in wchar_t's).
+ * @param   pwcShortName    The short name, if present.
+ * @param   cwcShortName    The length of the short name (in wchar_t's).
+ */
+static PKFSOBJ kFsCacheDirRefreshOldChildName(PKFSDIRREPOP pDirRePop, PKFSOBJ pCur, wchar_t const *pwcName, KU32 cwcName
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                                              , wchar_t const *pwcShortName, KU32 cwcShortName
+#endif
+                                              )
+{
+    /*
+     * Convert the names to ANSI first, that way we know all the lengths.
+     */
+    char szName[KFSCACHE_CFG_MAX_ANSI_NAME];
+    int  cchName = WideCharToMultiByte(CP_ACP, 0, pwcName, cwcName, szName, sizeof(szName) - 1, NULL, NULL);
+    if (cchName >= 0)
+    {
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+        char szShortName[12*3 + 1];
+        int  cchShortName = 0;
+        if (   cwcShortName == 0
+            || (cchShortName = WideCharToMultiByte(CP_ACP, 0, pwcShortName, cwcShortName,
+                                                   szShortName, sizeof(szShortName) - 1, NULL, NULL)) > 0)
+#endif
+        {
+            /*
+             * Shortening is easy for non-directory objects, for
+             * directory object we're only good when the length doesn't change
+             * on any of the components (cchParent et al).
+             *
+             * This deals with your typical xxxx.ext.tmp -> xxxx.ext renames.
+             */
+            if (   cchName <= pCur->cchName
+#ifdef KFSCACHE_CFG_UTF16
+                && cwcName <= pCur->cwcName
+#endif
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                && (   cchShortName == 0
+                    || (   cchShortName <= pCur->cchShortName
+                        && pCur->pszShortName != pCur->pszName
+# ifdef KFSCACHE_CFG_UTF16
+                        && cwcShortName <= pCur->cwcShortName
+                        && pCur->pwszShortName != pCur->pwszName
+# endif
+                       )
+                   )
+#endif
+               )
+            {
+                if (   pCur->bObjType != KFSOBJ_TYPE_DIR
+                    || (   cchName == pCur->cchName
+#ifdef KFSCACHE_CFG_UTF16
+                        && cwcName == pCur->cwcName
+#endif
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                        && (   cchShortName == 0
+                            || (   cchShortName == pCur->cchShortName
+# ifdef KFSCACHE_CFG_UTF16
+                                && cwcShortName == pCur->cwcShortName
+                                )
+# endif
+                           )
+#endif
+                       )
+                   )
+                {
+                    KFSCACHE_LOG(("Refreshing %ls - name changed to '%*.*ls'\n", pCur->pwszName, cwcName, cwcName, pwcName));
+                    *(char *)kHlpMemPCopy((void *)pCur->pszName, szName, cchName) = '\0';
+                    pCur->cchName = cchName;
+#ifdef KFSCACHE_CFG_UTF16
+                    *(wchar_t *)kHlpMemPCopy((void *)pCur->pwszName, pwcName, cwcName * sizeof(wchar_t)) = '\0';
+                    pCur->cwcName = cwcName;
+#endif
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                    *(char *)kHlpMemPCopy((void *)pCur->pszShortName, szShortName, cchShortName) = '\0';
+                    pCur->cchShortName = cchShortName;
+# ifdef KFSCACHE_CFG_UTF16
+                    *(wchar_t *)kHlpMemPCopy((void *)pCur->pwszShortName, pwcShortName, cwcShortName * sizeof(wchar_t)) = '\0';
+                    pCur->cwcShortName = cwcShortName;
+# endif
+#endif
+                    return pCur;
+                }
+            }
+        }
+    }
+
+
+    fprintf(stderr,
+            "kFsCacheDirRefreshOldChildName - not implemented!\n"
+            "  Old name:  %#x '%ls'\n"
+            "  New name:  %#x '%*.*ls'\n"
+            "  Old short: %#x '%ls'\n"
+            "  New short: %#x '%*.*ls'\n",
+            pCur->cwcName, pCur->pwszName,
+            cwcName, cwcName, cwcName, pwcName,
+            pCur->cwcShortName, pCur->pwszShortName,
+            cwcShortName, cwcShortName, cwcShortName, pwcShortName);
+    __debugbreak();
+    /** @todo implement this.  It's not entirely straight forward, especially if
+     *        the name increases!  Also, it's something that may happend during
+     *        individual object refresh and we might want to share code... */
+
+    return pCur;
+}
+
+
+/**
+ * Worker for kFsCacheDirFindOldChild that checks the names after an old object
+ * has been found the file ID.
+ *
+ * @returns Pointer to the existing object if found, NULL if not.
+ * @param   pDirRePop       Repopulation data.
+ * @param   pCur            The object to check the names of.
+ * @param   pwcName         The file name.
+ * @param   cwcName         The length of the filename (in wchar_t's).
+ * @param   pwcShortName    The short name, if present.
+ * @param   cwcShortName    The length of the short name (in wchar_t's).
+ */
+K_INLINE PKFSOBJ kFsCacheDirCheckOldChildName(PKFSDIRREPOP pDirRePop, PKFSOBJ pCur, wchar_t const *pwcName, KU32 cwcName
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                                              , wchar_t const *pwcShortName, KU32 cwcShortName
+#endif
+                                              )
+{
+    if (   pCur->cwcName == cwcName
+        && kHlpMemComp(pCur->pwszName, pwcName, cwcName * sizeof(wchar_t)) == 0)
+    {
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+        if (cwcShortName == 0
+            ?    pCur->pwszShortName == pCur->pwszName
+              || (   pCur->cwcShortName == cwcName
+                  && kHlpMemComp(pCur->pwszShortName, pCur->pwszName, cwcName * sizeof(wchar_t)) == 0)
+            :    pCur->cwcShortName == cwcShortName
+              && kHlpMemComp(pCur->pwszShortName, pwcShortName, cwcShortName * sizeof(wchar_t)) == 0 )
+#endif
+        {
+            return pCur;
+        }
+    }
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+    return kFsCacheDirRefreshOldChildName(pDirRePop, pCur, pwcName, cwcName, pwcShortName, cwcShortName);
+#else
+    return kFsCacheDirRefreshOldChildName(pDirRePop, pCur, pwcName, cwcName);
+#endif
+}
+
+
+/**
+ * Worker for kFsCachePopuplateOrRefreshDir that locates an old child object
+ * while re-populating a directory.
+ *
+ * @returns Pointer to the existing object if found, NULL if not.
+ * @param   pDirRePop       Repopulation data.
+ * @param   idFile          The file ID, 0 if none.
+ * @param   pwcName         The file name.
+ * @param   cwcName         The length of the filename (in wchar_t's).
+ * @param   pwcShortName    The short name, if present.
+ * @param   cwcShortName    The length of the short name (in wchar_t's).
+ */
+static PKFSOBJ kFsCacheDirFindOldChildSlow(PKFSDIRREPOP pDirRePop, KI64 idFile, wchar_t const *pwcName, KU32 cwcName
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                                           , wchar_t const *pwcShortName, KU32 cwcShortName
+#endif
+                                           )
+{
+    KU32        cOldChildren  = pDirRePop->cOldChildren;
+    KU32 const  iNextOldChild = K_MIN(pDirRePop->iNextOldChild, cOldChildren - 1);
+    KU32        iCur;
+    KI32        cInc;
+    KI32        cDirLefts;
+
+    kHlpAssertReturn(cOldChildren > 0, NULL);
+
+    /*
+     * Search by file ID first, if we've got one.
+     * ASSUMES that KU32 wraps around when -1 is added to 0.
+     */
+    if (   idFile != 0
+        && idFile != KI64_MAX
+        && idFile != KI64_MIN)
+    {
+        cInc = pDirRePop->cNextOldChildInc;
+        kHlpAssert(cInc == -1 || cInc == 1);
+        for (cDirLefts = 2; cDirLefts > 0; cDirLefts--)
+        {
+            for (iCur = iNextOldChild; iCur < cOldChildren; iCur += cInc)
+            {
+                PKFSOBJ pCur = pDirRePop->papOldChildren[iCur];
+                if (pCur->Stats.st_ino == idFile)
+                {
+                    /* Remove it and check the name. */
+                    pDirRePop->cOldChildren = --cOldChildren;
+                    if (iCur < cOldChildren)
+                        pDirRePop->papOldChildren[iCur] = pDirRePop->papOldChildren[cOldChildren];
+                    else
+                        cInc = -1;
+                    pDirRePop->cNextOldChildInc = cInc;
+                    pDirRePop->iNextOldChild    = iCur + cInc;
+
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                    return kFsCacheDirCheckOldChildName(pDirRePop, pCur, pwcName, cwcName, pwcShortName, cwcShortName);
+#else
+                    return kFsCacheDirCheckOldChildName(pDirRePop, pCur, pwcName, cwcName, pwcShortName, cwcShortName);
+#endif
+                }
+            }
+            cInc = -cInc;
+        }
+    }
+
+    /*
+     * Search by name.
+     * ASSUMES that KU32 wraps around when -1 is added to 0.
+     */
+    cInc = pDirRePop->cNextOldChildInc;
+    kHlpAssert(cInc == -1 || cInc == 1);
+    for (cDirLefts = 2; cDirLefts > 0; cDirLefts--)
+    {
+        for (iCur = iNextOldChild; iCur < cOldChildren; iCur += cInc)
+        {
+            PKFSOBJ pCur = pDirRePop->papOldChildren[iCur];
+            if (   (   pCur->cwcName == cwcName
+                    && kFsCacheIAreEqualW(pCur->pwszName, pwcName, cwcName))
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                || (   pCur->cwcShortName == cwcName
+                    && pCur->pwszShortName != pCur->pwszName
+                    && kFsCacheIAreEqualW(pCur->pwszShortName, pwcName, cwcName))
+#endif
+               )
+            {
+                /* Do this first so the compiler can share the rest with the above file ID return. */
+                if (pCur->Stats.st_ino == idFile)
+                { /* likely */ }
+                else
+                    pCur = kFsCacheDirRefreshOldChildFileId(pDirRePop, pCur, idFile);
+
+                /* Remove it and check the name. */
+                pDirRePop->cOldChildren = --cOldChildren;
+                if (iCur < cOldChildren)
+                    pDirRePop->papOldChildren[iCur] = pDirRePop->papOldChildren[cOldChildren];
+                else
+                    cInc = -1;
+                pDirRePop->cNextOldChildInc = cInc;
+                pDirRePop->iNextOldChild    = iCur + cInc;
+
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                return kFsCacheDirCheckOldChildName(pDirRePop, pCur, pwcName, cwcName, pwcShortName, cwcShortName);
+#else
+                return kFsCacheDirCheckOldChildName(pDirRePop, pCur, pwcName, cwcName, pwcShortName, cwcShortName);
+#endif
+            }
+        }
+        cInc = -cInc;
+    }
+
+    return NULL;
+}
+
+
+
+/**
+ * Worker for kFsCachePopuplateOrRefreshDir that locates an old child object
+ * while re-populating a directory.
+ *
+ * @returns Pointer to the existing object if found, NULL if not.
+ * @param   pDirRePop       Repopulation data.
+ * @param   idFile          The file ID, 0 if none.
+ * @param   pwcName         The file name.
+ * @param   cwcName         The length of the filename (in wchar_t's).
+ * @param   pwcShortName    The short name, if present.
+ * @param   cwcShortName    The length of the short name (in wchar_t's).
+ */
+K_INLINE PKFSOBJ kFsCacheDirFindOldChild(PKFSDIRREPOP pDirRePop, KI64 idFile, wchar_t const *pwcName, KU32 cwcName
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                                         , wchar_t const *pwcShortName, KU32 cwcShortName
+#endif
+                                         )
+{
+    /*
+     * We only check the iNextOldChild element here, hoping that the compiler
+     * will actually inline this code, letting the slow version of the function
+     * do the rest.
+     */
+    KU32 cOldChildren = pDirRePop->cOldChildren;
+    if (cOldChildren > 0)
+    {
+        KU32 const  iNextOldChild = K_MIN(pDirRePop->iNextOldChild, cOldChildren);
+        PKFSOBJ     pCur          = pDirRePop->papOldChildren[iNextOldChild];
+
+        if (   pCur->Stats.st_ino == idFile
+            && idFile != 0
+            && idFile != KI64_MAX
+            && idFile != KI64_MIN)
+            pCur = kFsCacheDirCheckOldChildName(pDirRePop, pCur, pwcName, cwcName, pwcShortName, cwcShortName);
+        else if (   pCur->cwcName == cwcName
+                 && kHlpMemComp(pCur->pwszName,  pwcName, cwcName * sizeof(wchar_t)) == 0)
+        {
+            if (pCur->Stats.st_ino == idFile)
+            { /* likely */ }
+            else
+                pCur = kFsCacheDirRefreshOldChildFileId(pDirRePop, pCur, idFile);
+
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+            if (cwcShortName == 0
+                ?    pCur->pwszShortName == pCur->pwszName
+                  || (   pCur->cwcShortName == cwcName
+                      && kHlpMemComp(pCur->pwszShortName, pCur->pwszName, cwcName * sizeof(wchar_t)) == 0)
+                :    pCur->cwcShortName == cwcShortName
+                  && kHlpMemComp(pCur->pwszShortName, pwcShortName, cwcShortName * sizeof(wchar_t)) == 0 )
+             { /* likely */ }
+             else
+                 pCur = kFsCacheDirRefreshOldChildName(pDirRePop, pCur, pwcName, cwcName, pwcShortName, cwcShortName);
+#endif
+        }
+        else
+            pCur = NULL;
+        if (pCur)
+        {
+            /*
+             * Got a match.  Remove the child from the array, replacing it with
+             * the last element.  (This means we're reversing the second half of
+             * the elements, which is why we need cNextOldChildInc.)
+             */
+            pDirRePop->cOldChildren = --cOldChildren;
+            if (iNextOldChild < cOldChildren)
+                pDirRePop->papOldChildren[iNextOldChild] = pDirRePop->papOldChildren[cOldChildren];
+            pDirRePop->iNextOldChild = iNextOldChild + pDirRePop->cNextOldChildInc;
+            return pCur;
+        }
+
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+        return kFsCacheDirFindOldChildSlow(pDirRePop, idFile, pwcName, cwcName, pwcShortName, cwcShortName);
+#else
+        return kFsCacheDirFindOldChildSlow(pDirRePop, idFile, pwcName, cwcName);
+#endif
+    }
+
+    return NULL;
+}
+
+
+
+/**
+ * Does the initial directory populating or refreshes it if it has been
+ * invalidated.
+ *
+ * This assumes the parent directory is opened.
+ *
+ * @returns K_TRUE on success, K_FALSE on error.
+ * @param   pCache              The cache.
+ * @param   pDir                The directory.
+ * @param   penmError           Where to store K_FALSE explanation.
+ */
+static KBOOL kFsCachePopuplateOrRefreshDir(PKFSCACHE pCache, PKFSDIR pDir, KFSLOOKUPERROR *penmError)
+{
+    KBOOL                       fRefreshing = K_FALSE;
+    KFSDIRREPOP                 DirRePop    = { NULL, 0, 0, 0, NULL };
+    MY_UNICODE_STRING           UniStrStar  = { 1 * sizeof(wchar_t), 2 * sizeof(wchar_t), L"*" };
+
+    /** @todo May have to make this more flexible wrt information classes since
+     *        older windows versions (XP, w2K) might not correctly support the
+     *        ones with file ID on all file systems. */
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+    MY_FILE_INFORMATION_CLASS const enmInfoClassWithId = MyFileIdBothDirectoryInformation;
+    MY_FILE_INFORMATION_CLASS       enmInfoClass = MyFileIdBothDirectoryInformation;
+#else
+    MY_FILE_INFORMATION_CLASS const enmInfoClassWithId = MyFileIdFullDirectoryInformation;
+    MY_FILE_INFORMATION_CLASS       enmInfoClass = MyFileIdFullDirectoryInformation;
+#endif
+    MY_NTSTATUS                 rcNt;
+    MY_IO_STATUS_BLOCK          Ios;
+    union
+    {
+        /* Include the structures for better alignment. */
+        MY_FILE_ID_BOTH_DIR_INFORMATION     WithId;
+        MY_FILE_ID_FULL_DIR_INFORMATION     NoId;
+        /* Buffer padding. We're using a 56KB buffer here to avoid size troubles with CIFS and such. */
+        KU8                                 abBuf[56*1024];
+    } uBuf;
+
+
+    /*
+     * Open the directory.
+     */
+    if (pDir->hDir == INVALID_HANDLE_VALUE)
+    {
+        MY_OBJECT_ATTRIBUTES    ObjAttr;
+        MY_UNICODE_STRING       UniStr;
+
+        kHlpAssert(!pDir->fPopulated);
+
+        Ios.Information = -1;
+        Ios.u.Status    = -1;
+
+        UniStr.Buffer        = (wchar_t *)pDir->Obj.pwszName;
+        UniStr.Length        = (USHORT)(pDir->Obj.cwcName * sizeof(wchar_t));
+        UniStr.MaximumLength = UniStr.Length + sizeof(wchar_t);
+
+        kHlpAssertStmtReturn(pDir->Obj.pParent, *penmError = KFSLOOKUPERROR_INTERNAL_ERROR, K_FALSE);
+        kHlpAssertStmtReturn(pDir->Obj.pParent->hDir != INVALID_HANDLE_VALUE, *penmError = KFSLOOKUPERROR_INTERNAL_ERROR, K_FALSE);
+        MyInitializeObjectAttributes(&ObjAttr, &UniStr, OBJ_CASE_INSENSITIVE, pDir->Obj.pParent->hDir, NULL /*pSecAttr*/);
+
+        /** @todo FILE_OPEN_REPARSE_POINT? */
+        rcNt = g_pfnNtCreateFile(&pDir->hDir,
+                                 FILE_READ_DATA | FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
+                                 &ObjAttr,
+                                 &Ios,
+                                 NULL, /*cbFileInitialAlloc */
+                                 FILE_ATTRIBUTE_NORMAL,
+                                 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                                 FILE_OPEN,
+                                 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
+                                 NULL, /*pEaBuffer*/
+                                 0);   /*cbEaBuffer*/
+        if (MY_NT_SUCCESS(rcNt))
+        {  /* likely */ }
+        else
+        {
+            pDir->hDir = INVALID_HANDLE_VALUE;
+            *penmError = KFSLOOKUPERROR_DIR_OPEN_ERROR;
+            return K_FALSE;
+        }
+    }
+    /*
+     * When re-populating, we replace papChildren in the directory and pick
+     * from the old one as we go along.
+     */
+    else if (pDir->fPopulated)
+    {
+        KU32  cAllocated = K_ALIGN_Z(pDir->cChildren, 16);
+        void *pvNew      = kHlpAlloc(sizeof(pDir->papChildren[0]) * cAllocated);
+        if (pvNew)
+        {
+            DirRePop.papOldChildren     = pDir->papChildren;
+            DirRePop.cOldChildren       = pDir->cChildren;
+            DirRePop.iNextOldChild      = 0;
+            DirRePop.cNextOldChildInc   = 1;
+            DirRePop.pCache             = pCache;
+
+            pDir->cChildren             = 0;
+            pDir->cChildrenAllocated    = cAllocated;
+            pDir->papChildren           = (PKFSOBJ *)pvNew;
+        }
+        else
+        {
+            *penmError = KFSLOOKUPERROR_OUT_OF_MEMORY;
+            return K_FALSE;
+        }
+
+        fRefreshing = K_TRUE;
+    }
+    if (!fRefreshing)
+        KFSCACHE_LOG(("Populating %s...\n", pDir->Obj.pszName));
+    else
+        KFSCACHE_LOG(("Refreshing %s...\n", pDir->Obj.pszName));
+
+    /*
+     * Enumerate the directory content.
+     *
+     * Note! The "*" filter is necessary because kFsCacheRefreshObj may have
+     *       previously quried a single file name and just passing NULL would
+     *       restart that single file name query.
+     */
+    Ios.Information = -1;
+    Ios.u.Status    = -1;
+    rcNt = g_pfnNtQueryDirectoryFile(pDir->hDir,
+                                     NULL,      /* hEvent */
+                                     NULL,      /* pfnApcComplete */
+                                     NULL,      /* pvApcCompleteCtx */
+                                     &Ios,
+                                     &uBuf,
+                                     sizeof(uBuf),
+                                     enmInfoClass,
+                                     FALSE,     /* fReturnSingleEntry */
+                                     &UniStrStar, /* Filter / restart pos. */
+                                     TRUE);     /* fRestartScan */
+    while (MY_NT_SUCCESS(rcNt))
+    {
+        /*
+         * Process the entries in the buffer.
+         */
+        KSIZE offBuf = 0;
+        for (;;)
+        {
+            union
+            {
+                KU8                             *pb;
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                MY_FILE_ID_BOTH_DIR_INFORMATION *pWithId;
+                MY_FILE_BOTH_DIR_INFORMATION    *pNoId;
+#else
+                MY_FILE_ID_FULL_DIR_INFORMATION *pWithId;
+                MY_FILE_FULL_DIR_INFORMATION    *pNoId;
+#endif
+            }           uPtr;
+            PKFSOBJ     pCur;
+            KU32        offNext;
+            KU32        cbMinCur;
+            wchar_t    *pwchFilename;
+
+            /* ASSUME only the FileName member differs between the two structures. */
+            uPtr.pb = &uBuf.abBuf[offBuf];
+            if (enmInfoClass == enmInfoClassWithId)
+            {
+                pwchFilename = &uPtr.pWithId->FileName[0];
+                cbMinCur  = (KU32)((uintptr_t)&uPtr.pWithId->FileName[0] - (uintptr_t)uPtr.pWithId);
+                cbMinCur += uPtr.pNoId->FileNameLength;
+            }
+            else
+            {
+                pwchFilename = &uPtr.pNoId->FileName[0];
+                cbMinCur  = (KU32)((uintptr_t)&uPtr.pNoId->FileName[0] - (uintptr_t)uPtr.pNoId);
+                cbMinCur += uPtr.pNoId->FileNameLength;
+            }
+
+            /* We need to skip the '.' and '..' entries. */
+            if (   *pwchFilename != '.'
+                ||  uPtr.pNoId->FileNameLength > 4
+                ||  !(   uPtr.pNoId->FileNameLength == 2
+                      ||  (   uPtr.pNoId->FileNameLength == 4
+                           && pwchFilename[1] == '.') )
+               )
+            {
+                KBOOL       fRc;
+                KU8 const   bObjType = uPtr.pNoId->FileAttributes & FILE_ATTRIBUTE_DIRECTORY ? KFSOBJ_TYPE_DIR
+                                     : uPtr.pNoId->FileAttributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)
+                                     ? KFSOBJ_TYPE_OTHER : KFSOBJ_TYPE_FILE;
+
+                /*
+                 * If refreshing, we must first see if this directory entry already
+                 * exists.
+                 */
+                if (!fRefreshing)
+                    pCur = NULL;
+                else
+                {
+                    pCur = kFsCacheDirFindOldChild(&DirRePop,
+                                                   enmInfoClass == enmInfoClassWithId ? uPtr.pWithId->FileId.QuadPart : 0,
+                                                   pwchFilename, uPtr.pWithId->FileNameLength / sizeof(wchar_t)
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                                                   , uPtr.pWithId->ShortName, uPtr.pWithId->ShortNameLength / sizeof(wchar_t)
+#endif
+                                                   );
+                    if (pCur)
+                    {
+                        if (pCur->bObjType == bObjType)
+                        {
+                            if (pCur->bObjType == KFSOBJ_TYPE_DIR)
+                            {
+                                PKFSDIR pCurDir = (PKFSDIR)pCur;
+                                if (   !pCurDir->fPopulated
+                                    ||  (   pCurDir->iLastWrite == uPtr.pWithId->LastWriteTime.QuadPart
+                                         && (pCur->fFlags & KFSOBJ_F_WORKING_DIR_MTIME) ) )
+                                { /* kind of likely */ }
+                                else
+                                {
+                                    KFSCACHE_LOG(("Refreshing %s/%s/ - %s/ needs re-populating...\n",
+                                                  pDir->Obj.pParent->Obj.pszName, pDir->Obj.pszName, pCur->pszName));
+                                    pCurDir->fNeedRePopulating = K_TRUE;
+                                }
+                            }
+                        }
+                        else if (pCur->bObjType == KFSOBJ_TYPE_MISSING)
+                        {
+                            KFSCACHE_LOG(("Refreshing %s/%s/ - %s appeared as %u, was missing.\n",
+                                          pDir->Obj.pParent->Obj.pszName, pDir->Obj.pszName, pCur->pszName, bObjType));
+                            pCur->bObjType = bObjType;
+                        }
+                        else
+                        {
+                            KFSCACHE_LOG(("Refreshing %s/%s/ - %s changed type from %u to %u! Dropping old object.\n",
+                                          pDir->Obj.pParent->Obj.pszName, pDir->Obj.pszName, pCur->pszName,
+                                          pCur->bObjType, bObjType));
+                            kFsCacheObjRelease(pCache, pCur);
+                            pCur = NULL;
+                        }
+                    }
+                    else
+                        KFSCACHE_LOG(("Refreshing %s/%s/ - %*.*ls added.\n", pDir->Obj.pParent->Obj.pszName, pDir->Obj.pszName,
+                                      uPtr.pNoId->FileNameLength / sizeof(wchar_t), uPtr.pNoId->FileNameLength / sizeof(wchar_t),
+                                      pwchFilename));
+                }
+
+                if (!pCur)
+                {
+                    /*
+                     * Create the entry (not linked yet).
+                     */
+                    pCur = kFsCacheCreateObjectW(pCache, pDir, pwchFilename, uPtr.pNoId->FileNameLength / sizeof(wchar_t),
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                                                 uPtr.pNoId->ShortName, uPtr.pNoId->ShortNameLength / sizeof(wchar_t),
+#endif
+                                                 bObjType, penmError);
+                    if (!pCur)
+                        return K_FALSE;
+                    kHlpAssert(pCur->cRefs == 1);
+                }
+
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                if (enmInfoClass == enmInfoClassWithId)
+                    birdStatFillFromFileIdBothDirInfo(&pCur->Stats, uPtr.pWithId, pCur->pszName);
+                else
+                    birdStatFillFromFileBothDirInfo(&pCur->Stats, uPtr.pNoId, pCur->pszName);
+#else
+                if (enmInfoClass == enmInfoClassWithId)
+                    birdStatFillFromFileIdFullDirInfo(&pCur->Stats, uPtr.pWithId, pCur->pszName);
+                else
+                    birdStatFillFromFileFullDirInfo(&pCur->Stats, uPtr.pNoId, pCur->pszName);
+#endif
+                pCur->Stats.st_dev = pDir->uDevNo;
+                pCur->fHaveStats   = K_TRUE;
+
+                /*
+                 * Add the entry to the directory.
+                 */
+                fRc = kFsCacheDirAddChild(pCache, pDir, pCur, penmError);
+                kFsCacheObjRelease(pCache, pCur);
+                if (fRc)
+                { /* likely */ }
+                else
+                {
+                    rcNt = STATUS_NO_MEMORY;
+                    break;
+                }
+            }
+            /*
+             * When seeing '.' we update the directory info.
+             */
+            else if (uPtr.pNoId->FileNameLength == 2)
+            {
+                pDir->iLastWrite = uPtr.pNoId->LastWriteTime.QuadPart;
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                if (enmInfoClass == enmInfoClassWithId)
+                    birdStatFillFromFileIdBothDirInfo(&pDir->Obj.Stats, uPtr.pWithId, pDir->Obj.pszName);
+                else
+                    birdStatFillFromFileBothDirInfo(&pDir->Obj.Stats, uPtr.pNoId, pDir->Obj.pszName);
+#else
+                if (enmInfoClass == enmInfoClassWithId)
+                    birdStatFillFromFileIdFullDirInfo(&pDir->Obj.Stats, uPtr.pWithId, pDir->Obj.pszName);
+                else
+                    birdStatFillFromFileFullDirInfo(&pDir->Obj.Stats, uPtr.pNoId, pDir->Obj.pszName);
+#endif
+            }
+
+            /*
+             * Advance.
+             */
+            offNext = uPtr.pNoId->NextEntryOffset;
+            if (   offNext >= cbMinCur
+                && offNext < sizeof(uBuf))
+                offBuf += offNext;
+            else
+                break;
+        }
+
+        /*
+         * Read the next chunk.
+         */
+        rcNt = g_pfnNtQueryDirectoryFile(pDir->hDir,
+                                         NULL,      /* hEvent */
+                                         NULL,      /* pfnApcComplete */
+                                         NULL,      /* pvApcCompleteCtx */
+                                         &Ios,
+                                         &uBuf,
+                                         sizeof(uBuf),
+                                         enmInfoClass,
+                                         FALSE,     /* fReturnSingleEntry */
+                                         &UniStrStar, /* Filter / restart pos. */
+                                         FALSE);    /* fRestartScan */
+    }
+
+    if (rcNt == MY_STATUS_NO_MORE_FILES)
+    {
+        /*
+         * If refreshing, add missing children objects and ditch the rest.
+         * We ignore errors while adding missing children (lazy bird).
+         */
+        if (!fRefreshing)
+        { /* more likely */ }
+        else
+        {
+            while (DirRePop.cOldChildren > 0)
+            {
+                KFSLOOKUPERROR enmErrorIgn;
+                PKFSOBJ pOldChild = DirRePop.papOldChildren[--DirRePop.cOldChildren];
+                if (pOldChild->bObjType == KFSOBJ_TYPE_MISSING)
+                    kFsCacheDirAddChild(pCache, pDir, pOldChild, &enmErrorIgn);
+                else
+                {
+                    KFSCACHE_LOG(("Refreshing %s/%s/ - %s was removed.\n",
+                                  pDir->Obj.pParent->Obj.pszName, pDir->Obj.pszName, pOldChild->pszName));
+                    kHlpAssert(pOldChild->bObjType != KFSOBJ_TYPE_DIR);
+                }
+                kFsCacheObjRelease(pCache, pOldChild);
+            }
+            kHlpFree(DirRePop.papOldChildren);
+        }
+
+        /*
+         * Mark the directory as fully populated and up to date.
+         */
+        pDir->fPopulated        = K_TRUE;
+        pDir->fNeedRePopulating = K_FALSE;
+        if (pDir->Obj.uCacheGen != KFSOBJ_CACHE_GEN_IGNORE)
+            pDir->Obj.uCacheGen = pCache->auGenerations[pDir->Obj.fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
+        return K_TRUE;
+    }
+
+    /*
+     * If we failed during refresh, add back remaining old children.
+     */
+    if (!fRefreshing)
+    {
+        while (DirRePop.cOldChildren > 0)
+        {
+            KFSLOOKUPERROR enmErrorIgn;
+            PKFSOBJ pOldChild = DirRePop.papOldChildren[--DirRePop.cOldChildren];
+            kFsCacheDirAddChild(pCache, pDir, pOldChild, &enmErrorIgn);
+            kFsCacheObjRelease(pCache, pOldChild);
+        }
+        kHlpFree(DirRePop.papOldChildren);
+    }
+
+    kHlpAssertMsgFailed(("%#x\n", rcNt));
+    *penmError = KFSLOOKUPERROR_DIR_READ_ERROR;
+    return K_TRUE;
+}
+
+
+/**
+ * Does the initial directory populating or refreshes it if it has been
+ * invalidated.
+ *
+ * This assumes the parent directory is opened.
+ *
+ * @returns K_TRUE on success, K_FALSE on error.
+ * @param   pCache              The cache.
+ * @param   pDir                The directory.
+ * @param   penmError           Where to store K_FALSE explanation.  Optional.
+ */
+KBOOL kFsCacheDirEnsurePopuplated(PKFSCACHE pCache, PKFSDIR pDir, KFSLOOKUPERROR *penmError)
+{
+    KFSLOOKUPERROR enmIgnored;
+    if (   pDir->fPopulated
+        && !pDir->fNeedRePopulating
+        && (   pDir->Obj.uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+            || pDir->Obj.uCacheGen == pCache->auGenerations[pDir->Obj.fFlags & KFSOBJ_F_USE_CUSTOM_GEN]) )
+        return K_TRUE;
+    return kFsCachePopuplateOrRefreshDir(pCache, pDir, penmError ? penmError : &enmIgnored);
+}
+
+
+/**
+ * Checks whether the modified timestamp differs on this directory.
+ *
+ * @returns K_TRUE if possibly modified, K_FALSE if definitely not modified.
+ * @param   pDir                The directory..
+ */
+static KBOOL kFsCacheDirIsModified(PKFSDIR pDir)
+{
+    if (   pDir->hDir != INVALID_HANDLE_VALUE
+        && (pDir->Obj.fFlags & KFSOBJ_F_WORKING_DIR_MTIME) )
+    {
+        MY_IO_STATUS_BLOCK          Ios;
+        MY_FILE_BASIC_INFORMATION   BasicInfo;
+        MY_NTSTATUS                 rcNt;
+
+        Ios.Information = -1;
+        Ios.u.Status    = -1;
+
+        rcNt = g_pfnNtQueryInformationFile(pDir->hDir, &Ios, &BasicInfo, sizeof(BasicInfo), MyFileBasicInformation);
+        if (MY_NT_SUCCESS(rcNt))
+            return BasicInfo.LastWriteTime.QuadPart != pDir->iLastWrite;
+    }
+    /* The cache root never changes. */
+    else if (!pDir->Obj.pParent)
+        return K_FALSE;
+
+    return K_TRUE;
+}
+
+
+static KBOOL kFsCacheRefreshMissing(PKFSCACHE pCache, PKFSOBJ pMissing, KFSLOOKUPERROR *penmError)
+{
+    /*
+     * If we can, we start by checking whether the parent directory
+     * has been modified.   If it has, we need to check if this entry
+     * was added or not, most likely it wasn't added.
+     */
+    if (!kFsCacheDirIsModified(pMissing->pParent))
+    {
+        KFSCACHE_LOG(("Parent of missing not written to %s/%s\n", pMissing->pParent->Obj.pszName, pMissing->pszName));
+        pMissing->uCacheGen = pCache->auGenerationsMissing[pMissing->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
+    }
+    else
+    {
+        MY_UNICODE_STRING           UniStr;
+        MY_OBJECT_ATTRIBUTES        ObjAttr;
+        MY_FILE_BASIC_INFORMATION   BasicInfo;
+        MY_NTSTATUS                 rcNt;
+
+        UniStr.Buffer        = (wchar_t *)pMissing->pwszName;
+        UniStr.Length        = (USHORT)(pMissing->cwcName * sizeof(wchar_t));
+        UniStr.MaximumLength = UniStr.Length + sizeof(wchar_t);
+
+        kHlpAssert(pMissing->pParent->hDir != INVALID_HANDLE_VALUE);
+        MyInitializeObjectAttributes(&ObjAttr, &UniStr, OBJ_CASE_INSENSITIVE, pMissing->pParent->hDir, NULL /*pSecAttr*/);
+
+        rcNt = g_pfnNtQueryAttributesFile(&ObjAttr, &BasicInfo);
+        if (!MY_NT_SUCCESS(rcNt))
+        {
+            /*
+             * Probably more likely that a missing node stays missing.
+             */
+            pMissing->uCacheGen = pCache->auGenerationsMissing[pMissing->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
+            KFSCACHE_LOG(("Still missing %s/%s\n", pMissing->pParent->Obj.pszName, pMissing->pszName));
+        }
+        else
+        {
+            /*
+             * We must metamorphose this node.  This is tedious business
+             * because we need to check the file name casing.  We might
+             * just as well update the parent directory...
+             */
+            KU8 const   bObjType = BasicInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY ? KFSOBJ_TYPE_DIR
+                                 : BasicInfo.FileAttributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)
+                                 ? KFSOBJ_TYPE_OTHER : KFSOBJ_TYPE_FILE;
+
+            KFSCACHE_LOG(("Birth of %s/%s as %d with attribs %#x...\n",
+                          pMissing->pParent->Obj.pszName, pMissing->pszName, bObjType, BasicInfo.FileAttributes));
+            pMissing->bObjType  = bObjType;
+            pMissing->uCacheGen = pCache->auGenerations[pMissing->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
+/**
+ * @todo refresh missing object names when it appears.
+ */
+        }
+    }
+
+    return K_TRUE;
+}
+
+
+static KBOOL kFsCacheRefreshMissingIntermediateDir(PKFSCACHE pCache, PKFSOBJ pMissing, KFSLOOKUPERROR *penmError)
+{
+    if (kFsCacheRefreshMissing(pCache, pMissing, penmError))
+    {
+        if (   pMissing->bObjType == KFSOBJ_TYPE_DIR
+            || pMissing->bObjType == KFSOBJ_TYPE_MISSING)
+            return K_TRUE;
+        *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_DIR;
+    }
+
+    return K_FALSE;
+}
+
+
+/**
+ * Generic object refresh.
+ *
+ * This does not refresh the content of directories.
+ *
+ * @returns K_TRUE on success.  K_FALSE and *penmError on failure.
+ * @param   pCache              The cache.
+ * @param   pObj                The object.
+ * @param   penmError           Where to return error info.
+ */
+static KBOOL kFsCacheRefreshObj(PKFSCACHE pCache, PKFSOBJ pObj, KFSLOOKUPERROR *penmError)
+{
+    KBOOL fRc;
+
+    /*
+     * Since we generally assume nothing goes away in this cache, we only really
+     * have a hard time with negative entries.  So, missing stuff goes to
+     * complicated land.
+     */
+    if (pObj->bObjType == KFSOBJ_TYPE_MISSING)
+        fRc = kFsCacheRefreshMissing(pCache, pObj, penmError);
+    else
+    {
+        /*
+         * This object is supposed to exist, so all we need to do is query essential
+         * stats again.  Since we've already got handles on directories, there are
+         * two ways to go about this.
+         */
+        union
+        {
+            MY_FILE_NETWORK_OPEN_INFORMATION    FullInfo;
+            MY_FILE_STANDARD_INFORMATION        StdInfo;
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+            MY_FILE_ID_BOTH_DIR_INFORMATION     WithId;
+            //MY_FILE_BOTH_DIR_INFORMATION        NoId;
+#else
+            MY_FILE_ID_FULL_DIR_INFORMATION     WithId;
+            //MY_FILE_FULL_DIR_INFORMATION        NoId;
+#endif
+            KU8                                 abPadding[  sizeof(wchar_t) * KFSCACHE_CFG_MAX_UTF16_NAME
+                                                          + sizeof(MY_FILE_ID_BOTH_DIR_INFORMATION)];
+        } uBuf;
+        MY_IO_STATUS_BLOCK                      Ios;
+        MY_NTSTATUS                             rcNt;
+        if (   pObj->bObjType != KFSOBJ_TYPE_DIR
+            || ((PKFSDIR)pObj)->hDir == INVALID_HANDLE_VALUE)
+        {
+#if 1
+            /* This always works and doesn't mess up NtQueryDirectoryFile. */
+            MY_UNICODE_STRING    UniStr;
+            MY_OBJECT_ATTRIBUTES ObjAttr;
+
+            UniStr.Buffer        = (wchar_t *)pObj->pwszName;
+            UniStr.Length        = (USHORT)(pObj->cwcName * sizeof(wchar_t));
+            UniStr.MaximumLength = UniStr.Length + sizeof(wchar_t);
+
+            kHlpAssert(pObj->pParent->hDir != INVALID_HANDLE_VALUE);
+            MyInitializeObjectAttributes(&ObjAttr, &UniStr, OBJ_CASE_INSENSITIVE, pObj->pParent->hDir, NULL /*pSecAttr*/);
+
+            rcNt = g_pfnNtQueryFullAttributesFile(&ObjAttr, &uBuf.FullInfo);
+            if (MY_NT_SUCCESS(rcNt))
+            {
+                pObj->Stats.st_size          = uBuf.FullInfo.EndOfFile.QuadPart;
+                birdNtTimeToTimeSpec(uBuf.FullInfo.CreationTime.QuadPart,   &pObj->Stats.st_birthtim);
+                birdNtTimeToTimeSpec(uBuf.FullInfo.ChangeTime.QuadPart,     &pObj->Stats.st_ctim);
+                birdNtTimeToTimeSpec(uBuf.FullInfo.LastWriteTime.QuadPart,  &pObj->Stats.st_mtim);
+                birdNtTimeToTimeSpec(uBuf.FullInfo.LastAccessTime.QuadPart, &pObj->Stats.st_atim);
+                pObj->Stats.st_attribs       = uBuf.FullInfo.FileAttributes;
+                pObj->Stats.st_blksize       = 65536;
+                pObj->Stats.st_blocks        = (uBuf.FullInfo.AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1)
+                                             / BIRD_STAT_BLOCK_SIZE;
+            }
+#else
+            /* This alternative lets us keep the inode number up to date and
+               detect name case changes.
+               Update: This doesn't work on windows 7, it ignores the UniStr
+                       and continue with the "*" search. So, we're using the
+                       above query instead for the time being. */
+            MY_UNICODE_STRING    UniStr;
+# ifdef KFSCACHE_CFG_SHORT_NAMES
+            MY_FILE_INFORMATION_CLASS enmInfoClass = MyFileIdBothDirectoryInformation;
+# else
+            MY_FILE_INFORMATION_CLASS enmInfoClass = MyFileIdFullDirectoryInformation;
+# endif
+
+            UniStr.Buffer        = (wchar_t *)pObj->pwszName;
+            UniStr.Length        = (USHORT)(pObj->cwcName * sizeof(wchar_t));
+            UniStr.MaximumLength = UniStr.Length + sizeof(wchar_t);
+
+            kHlpAssert(pObj->pParent->hDir != INVALID_HANDLE_VALUE);
+
+            Ios.Information = -1;
+            Ios.u.Status    = -1;
+            rcNt = g_pfnNtQueryDirectoryFile(pObj->pParent->hDir,
+                                             NULL,      /* hEvent */
+                                             NULL,      /* pfnApcComplete */
+                                             NULL,      /* pvApcCompleteCtx */
+                                             &Ios,
+                                             &uBuf,
+                                             sizeof(uBuf),
+                                             enmInfoClass,
+                                             TRUE,      /* fReturnSingleEntry */
+                                             &UniStr,   /* Filter / restart pos. */
+                                             TRUE);     /* fRestartScan */
+
+            if (MY_NT_SUCCESS(rcNt))
+            {
+                if (pObj->Stats.st_ino == uBuf.WithId.FileId.QuadPart)
+                    KFSCACHE_LOG(("Refreshing %s/%s, no ID change...\n", pObj->pParent->Obj.pszName, pObj->pszName));
+                else if (   pObj->cwcName == uBuf.WithId.FileNameLength / sizeof(wchar_t)
+# ifdef KFSCACHE_CFG_SHORT_NAMES
+                         && (  uBuf.WithId.ShortNameLength == 0
+                             ?    pObj->pwszName == pObj->pwszShortName
+                               || (   pObj->cwcName == pObj->cwcShortName
+                                   && memcmp(pObj->pwszName, pObj->pwszShortName, pObj->cwcName * sizeof(wchar_t)) == 0)
+                             : pObj->cwcShortName == uBuf.WithId.ShortNameLength / sizeof(wchar_t)
+                               && memcmp(pObj->pwszShortName, uBuf.WithId.ShortName, uBuf.WithId.ShortNameLength) == 0
+                            )
+# endif
+                         && memcmp(pObj->pwszName, uBuf.WithId.FileName, uBuf.WithId.FileNameLength) == 0
+                         )
+                {
+                    KFSCACHE_LOG(("Refreshing %s/%s, ID changed %#llx -> %#llx...\n",
+                                  pObj->pParent->Obj.pszName, pObj->pszName, pObj->Stats.st_ino, uBuf.WithId.FileId.QuadPart));
+                    pObj->Stats.st_ino = uBuf.WithId.FileId.QuadPart;
+                }
+                else
+                {
+                    KFSCACHE_LOG(("Refreshing %s/%s, ID changed %#llx -> %#llx and names too...\n",
+                                  pObj->pParent->Obj.pszName, pObj->pszName, pObj->Stats.st_ino, uBuf.WithId.FileId.QuadPart));
+                    fprintf(stderr, "kFsCacheRefreshObj - ID + name change not implemented!!\n");
+                    __debugbreak();
+                    pObj->Stats.st_ino = uBuf.WithId.FileId.QuadPart;
+                    /** @todo implement as needed.   */
+                }
+
+                pObj->Stats.st_size          = uBuf.WithId.EndOfFile.QuadPart;
+                birdNtTimeToTimeSpec(uBuf.WithId.CreationTime.QuadPart,   &pObj->Stats.st_birthtim);
+                birdNtTimeToTimeSpec(uBuf.WithId.ChangeTime.QuadPart,     &pObj->Stats.st_ctim);
+                birdNtTimeToTimeSpec(uBuf.WithId.LastWriteTime.QuadPart,  &pObj->Stats.st_mtim);
+                birdNtTimeToTimeSpec(uBuf.WithId.LastAccessTime.QuadPart, &pObj->Stats.st_atim);
+                pObj->Stats.st_attribs       = uBuf.WithId.FileAttributes;
+                pObj->Stats.st_blksize       = 65536;
+                pObj->Stats.st_blocks        = (uBuf.WithId.AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1)
+                                             / BIRD_STAT_BLOCK_SIZE;
+            }
+#endif
+            if (MY_NT_SUCCESS(rcNt))
+            {
+                pObj->uCacheGen = pCache->auGenerations[pObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
+                fRc = K_TRUE;
+            }
+            else
+            {
+                /* ouch! */
+                kHlpAssertMsgFailed(("%#x\n", rcNt));
+                fprintf(stderr, "kFsCacheRefreshObj - rcNt=%#x on non-dir - not implemented!\n", rcNt);
+                __debugbreak();
+                fRc = K_FALSE;
+            }
+        }
+        else
+        {
+            /*
+             * An open directory.  Query information via the handle, the
+             * file ID shouldn't have been able to change, so we can use
+             * NtQueryInformationFile.  Right...
+             */
+            PKFSDIR pDir = (PKFSDIR)pObj;
+            Ios.Information = -1;
+            Ios.u.Status    = -1;
+            rcNt = g_pfnNtQueryInformationFile(pDir->hDir, &Ios, &uBuf.FullInfo, sizeof(uBuf.FullInfo),
+                                               MyFileNetworkOpenInformation);
+            if (MY_NT_SUCCESS(rcNt))
+                rcNt = Ios.u.Status;
+            if (MY_NT_SUCCESS(rcNt))
+            {
+                pObj->Stats.st_size          = uBuf.FullInfo.EndOfFile.QuadPart;
+                birdNtTimeToTimeSpec(uBuf.FullInfo.CreationTime.QuadPart,   &pObj->Stats.st_birthtim);
+                birdNtTimeToTimeSpec(uBuf.FullInfo.ChangeTime.QuadPart,     &pObj->Stats.st_ctim);
+                birdNtTimeToTimeSpec(uBuf.FullInfo.LastWriteTime.QuadPart,  &pObj->Stats.st_mtim);
+                birdNtTimeToTimeSpec(uBuf.FullInfo.LastAccessTime.QuadPart, &pObj->Stats.st_atim);
+                pObj->Stats.st_attribs       = uBuf.FullInfo.FileAttributes;
+                pObj->Stats.st_blksize       = 65536;
+                pObj->Stats.st_blocks        = (uBuf.FullInfo.AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1)
+                                             / BIRD_STAT_BLOCK_SIZE;
+
+                if (   pDir->iLastWrite == uBuf.FullInfo.LastWriteTime.QuadPart
+                    && (pObj->fFlags & KFSOBJ_F_WORKING_DIR_MTIME) )
+                    KFSCACHE_LOG(("Refreshing %s/%s/ - no re-populating necessary.\n",
+                                  pObj->pParent->Obj.pszName, pObj->pszName));
+                else
+                {
+                    KFSCACHE_LOG(("Refreshing %s/%s/ - needs re-populating...\n",
+                                  pObj->pParent->Obj.pszName, pObj->pszName));
+                    pDir->fNeedRePopulating = K_TRUE;
+#if 0
+                    /* Refresh the link count. */
+                    rcNt = g_pfnNtQueryInformationFile(pDir->hDir, &Ios, &StdInfo, sizeof(StdInfo), FileStandardInformation);
+                    if (MY_NT_SUCCESS(rcNt))
+                        rcNt = Ios.s.Status;
+                    if (MY_NT_SUCCESS(rcNt))
+                        pObj->Stats.st_nlink = StdInfo.NumberOfLinks;
+#endif
+                }
+            }
+            if (MY_NT_SUCCESS(rcNt))
+            {
+                pObj->uCacheGen = pCache->auGenerations[pObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
+                fRc = K_TRUE;
+            }
+            else
+            {
+                /* ouch! */
+                kHlpAssertMsgFailed(("%#x\n", rcNt));
+                fprintf(stderr, "kFsCacheRefreshObj - rcNt=%#x on dir - not implemented!\n", rcNt);
+                __debugbreak();
+                fRc = K_FALSE;
+            }
+        }
+    }
+
+    return fRc;
+}
+
+
+
+/**
+ * Looks up a drive letter.
+ *
+ * Will enter the drive if necessary.
+ *
+ * @returns Pointer to the root directory of the drive or an update-to-date
+ *          missing node.
+ * @param   pCache              The cache.
+ * @param   chLetter            The uppercased drive letter.
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ */
+static PKFSOBJ kFswCacheLookupDrive(PKFSCACHE pCache, char chLetter, KFSLOOKUPERROR *penmError)
+{
+    KU32 const          uHash = chLetter - 'A';
+    KU32                cLeft;
+    PKFSOBJ            *ppCur;
+
+    MY_UNICODE_STRING   NtPath;
+    wchar_t             wszTmp[8];
+    char                szTmp[4];
+
+    /*
+     * Custom drive letter hashing.
+     */
+    if (pCache->RootDir.paHashTab)
+    {
+        /** @todo PKFSOBJHASH pHash = */
+    }
+
+    /*
+     * Special cased lookup.
+     */
+    cLeft = pCache->RootDir.cChildren;
+    ppCur = pCache->RootDir.papChildren;
+    while (cLeft-- > 0)
+    {
+        PKFSOBJ pCur = *ppCur++;
+        if (   pCur->cchName == 2
+            && pCur->pszName[0] == chLetter
+            && pCur->pszName[1] == ':')
+        {
+            if (pCur->bObjType == KFSOBJ_TYPE_DIR)
+                return pCur;
+            kHlpAssert(pCur->bObjType == KFSOBJ_TYPE_MISSING);
+            if (kFsCacheRefreshMissingIntermediateDir(pCache, pCur, penmError))
+                return pCur;
+            return NULL;
+        }
+    }
+
+    /*
+     * Need to add it.  We always keep the drive letters open for the benefit
+     * of kFsCachePopuplateOrRefreshDir and others.
+     */
+    wszTmp[0] = szTmp[0] = chLetter;
+    wszTmp[1] = szTmp[1] = ':';
+    wszTmp[2] = szTmp[2] = '\\';
+    wszTmp[3] = '.';
+    wszTmp[4] = '\0';
+    szTmp[2] = '\0';
+
+    NtPath.Buffer        = NULL;
+    NtPath.Length        = 0;
+    NtPath.MaximumLength = 0;
+    if (g_pfnRtlDosPathNameToNtPathName_U(wszTmp, &NtPath, NULL, NULL))
+    {
+        HANDLE      hDir;
+        MY_NTSTATUS rcNt;
+        rcNt = birdOpenFileUniStr(&NtPath,
+                                  FILE_READ_DATA  | FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
+                                  FILE_ATTRIBUTE_NORMAL,
+                                  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                                  FILE_OPEN,
+                                  FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
+                                  OBJ_CASE_INSENSITIVE,
+                                  &hDir);
+        birdFreeNtPath(&NtPath);
+        if (MY_NT_SUCCESS(rcNt))
+        {
+            PKFSDIR pDir = (PKFSDIR)kFsCacheCreateObject(pCache, &pCache->RootDir, szTmp, 2, wszTmp, 2,
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                                                         NULL, 0, NULL, 0,
+#endif
+                                                         KFSOBJ_TYPE_DIR, penmError);
+            if (pDir)
+            {
+                /*
+                 * We need a little bit of extra info for a drive root.  These things are typically
+                 * inherited by subdirectories down the tree, so, we do it all here for till that changes.
+                 */
+                union
+                {
+                    MY_FILE_FS_VOLUME_INFORMATION       VolInfo;
+                    MY_FILE_FS_ATTRIBUTE_INFORMATION    FsAttrInfo;
+                    char abPadding[sizeof(MY_FILE_FS_VOLUME_INFORMATION) + 512];
+                } uBuf;
+                MY_IO_STATUS_BLOCK Ios;
+                KBOOL fRc;
+
+                kHlpAssert(pDir->hDir == INVALID_HANDLE_VALUE);
+                pDir->hDir = hDir;
+
+                if (birdStatHandle(hDir, &pDir->Obj.Stats, pDir->Obj.pszName) == 0)
+                {
+                    pDir->Obj.fHaveStats = K_TRUE;
+                    pDir->uDevNo = pDir->Obj.Stats.st_dev;
+                }
+                else
+                {
+                    /* Just in case. */
+                    pDir->Obj.fHaveStats = K_FALSE;
+                    rcNt = birdQueryVolumeDeviceNumber(hDir, &uBuf.VolInfo, sizeof(uBuf), &pDir->uDevNo);
+                    kHlpAssertMsg(MY_NT_SUCCESS(rcNt), ("%#x\n", rcNt));
+                }
+
+                /* Get the file system. */
+                pDir->Obj.fFlags &= ~(KFSOBJ_F_NTFS | KFSOBJ_F_WORKING_DIR_MTIME);
+                Ios.Information = -1;
+                Ios.u.Status    = -1;
+                rcNt = g_pfnNtQueryVolumeInformationFile(hDir, &Ios, &uBuf.FsAttrInfo, sizeof(uBuf),
+                                                         MyFileFsAttributeInformation);
+                if (MY_NT_SUCCESS(rcNt))
+                    rcNt = Ios.u.Status;
+                if (MY_NT_SUCCESS(rcNt))
+                {
+                    if (   uBuf.FsAttrInfo.FileSystemName[0] == 'N'
+                        && uBuf.FsAttrInfo.FileSystemName[1] == 'T'
+                        && uBuf.FsAttrInfo.FileSystemName[2] == 'F'
+                        && uBuf.FsAttrInfo.FileSystemName[3] == 'S'
+                        && uBuf.FsAttrInfo.FileSystemName[4] == '\0')
+                    {
+                        DWORD dwDriveType = GetDriveTypeW(wszTmp);
+                        if (   dwDriveType == DRIVE_FIXED
+                            || dwDriveType == DRIVE_RAMDISK)
+                            pDir->Obj.fFlags |= KFSOBJ_F_NTFS | KFSOBJ_F_WORKING_DIR_MTIME;
+                    }
+                }
+
+                /*
+                 * Link the new drive letter into the root dir.
+                 */
+                fRc = kFsCacheDirAddChild(pCache, &pCache->RootDir, &pDir->Obj, penmError);
+                kFsCacheObjRelease(pCache, &pDir->Obj);
+                return fRc ? &pDir->Obj : NULL;
+            }
+
+            g_pfnNtClose(hDir);
+            return NULL;
+        }
+
+        /* Assume it doesn't exist if this happens... This may be a little to
+           restrictive wrt status code checks. */
+        kHlpAssertMsgStmtReturn(   rcNt == MY_STATUS_OBJECT_NAME_NOT_FOUND
+                                || rcNt == MY_STATUS_OBJECT_PATH_NOT_FOUND
+                                || rcNt == MY_STATUS_OBJECT_PATH_INVALID
+                                || rcNt == MY_STATUS_OBJECT_PATH_SYNTAX_BAD,
+                                ("%#x\n", rcNt),
+                                *penmError = KFSLOOKUPERROR_DIR_OPEN_ERROR,
+                                NULL);
+    }
+    else
+    {
+        kHlpAssertFailed();
+        *penmError = KFSLOOKUPERROR_OUT_OF_MEMORY;
+        return NULL;
+    }
+
+    /*
+     * Maybe create a missing entry.
+     */
+    if (pCache->fFlags & KFSCACHE_F_MISSING_OBJECTS)
+    {
+        PKFSOBJ pMissing = kFsCacheCreateObject(pCache, &pCache->RootDir, szTmp, 2, wszTmp, 2,
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                                        NULL, 0, NULL, 0,
+#endif
+                                        KFSOBJ_TYPE_MISSING, penmError);
+        if (pMissing)
+        {
+            KBOOL fRc = kFsCacheDirAddChild(pCache, &pCache->RootDir, pMissing, penmError);
+            kFsCacheObjRelease(pCache, pMissing);
+            return fRc ? pMissing : NULL;
+        }
+    }
+    else
+    {
+        /** @todo this isn't necessary correct for a root spec.   */
+        *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_FOUND;
+    }
+    return NULL;
+}
+
+
+/**
+ * Look up a child node, ANSI version.
+ *
+ * @returns Pointer to the child if found, NULL if not.
+ * @param   pCache              The cache.
+ * @param   pParent             The parent directory to search.
+ * @param   pchName             The child name to search for (not terminated).
+ * @param   cchName             The length of the child name.
+ */
+static PKFSOBJ kFsCacheFindChildA(PKFSCACHE pCache, PKFSDIR pParent, const char *pchName, KU32 cchName)
+{
+    /* Check for '.' first. */
+    if (cchName != 1 || *pchName != '.')
+    {
+        KU32        cLeft;
+        PKFSOBJ    *ppCur;
+
+        if (pParent->paHashTab != NULL)
+        {
+            /** @todo directory hash table lookup.   */
+        }
+
+        /* Linear search. */
+        cLeft = pParent->cChildren;
+        ppCur = pParent->papChildren;
+        while (cLeft-- > 0)
+        {
+            PKFSOBJ pCur = *ppCur++;
+            if (   (   pCur->cchName == cchName
+                    && _mbsnicmp(pCur->pszName, pchName, cchName) == 0)
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                || (   pCur->cchShortName == cchName
+                    && pCur->pszShortName != pCur->pszName
+                    && _mbsnicmp(pCur->pszShortName, pchName, cchName) == 0)
+#endif
+               )
+                return pCur;
+        }
+        return NULL;
+    }
+    return &pParent->Obj;
+}
+
+
+/**
+ * Look up a child node, UTF-16 version.
+ *
+ * @returns Pointer to the child if found, NULL if not.
+ * @param   pCache              The cache.
+ * @param   pParent             The parent directory to search.
+ * @param   pwcName             The child name to search for (not terminated).
+ * @param   cwcName             The length of the child name (in wchar_t's).
+ */
+static PKFSOBJ kFsCacheFindChildW(PKFSCACHE pCache, PKFSDIR pParent, const wchar_t *pwcName, KU32 cwcName)
+{
+    /* Check for '.' first. */
+    if (cwcName != 1 || *pwcName != '.')
+    {
+        KU32        cLeft;
+        PKFSOBJ    *ppCur;
+
+        if (pParent->paHashTab != NULL)
+        {
+            /** @todo directory hash table lookup.   */
+        }
+
+        /* Linear search. */
+        cLeft = pParent->cChildren;
+        ppCur = pParent->papChildren;
+        while (cLeft-- > 0)
+        {
+            PKFSOBJ pCur = *ppCur++;
+            if (   (   pCur->cwcName == cwcName
+                    && kFsCacheIAreEqualW(pCur->pwszName, pwcName, cwcName))
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                || (   pCur->cwcShortName == cwcName
+                    && pCur->pwszShortName != pCur->pwszName
+                    && kFsCacheIAreEqualW(pCur->pwszShortName, pwcName, cwcName))
+#endif
+               )
+                return pCur;
+        }
+        return NULL;
+    }
+    return &pParent->Obj;
+}
+
+
+/**
+ * Looks up a UNC share, ANSI version.
+ *
+ * We keep both the server and share in the root directory entry.  This means we
+ * have to clean up the entry name before we can insert it.
+ *
+ * @returns Pointer to the share root directory or an update-to-date missing
+ *          node.
+ * @param   pCache              The cache.
+ * @param   pszPath             The path.
+ * @param   poff                Where to return the root dire.
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ */
+static PKFSOBJ kFswCacheLookupUncShareA(PKFSCACHE pCache, const char *pszPath, KU32 *poff, KFSLOOKUPERROR *penmError)
+{
+#if 0 /* later */
+    KU32 offStartServer;
+    KU32 offEndServer;
+    KU32 offStartShare;
+
+    KU32 offEnd = 2;
+    while (IS_SLASH(pszPath[offEnd]))
+        offEnd++;
+
+    offStartServer = offEnd;
+    while (   (ch = pszPath[offEnd]) != '\0'
+           && !IS_SLASH(ch))
+        offEnd++;
+    offEndServer = offEnd;
+
+    if (ch != '\0')
+    { /* likely */ }
+    else
+    {
+        *penmError = KFSLOOKUPERROR_NOT_FOUND;
+        return NULL;
+    }
+
+    while (IS_SLASH(pszPath[offEnd]))
+        offEnd++;
+    offStartServer = offEnd;
+    while (   (ch = pszPath[offEnd]) != '\0'
+           && !IS_SLASH(ch))
+        offEnd++;
+#endif
+    *penmError = KFSLOOKUPERROR_UNSUPPORTED;
+    return NULL;
+}
+
+
+/**
+ * Looks up a UNC share, UTF-16 version.
+ *
+ * We keep both the server and share in the root directory entry.  This means we
+ * have to clean up the entry name before we can insert it.
+ *
+ * @returns Pointer to the share root directory or an update-to-date missing
+ *          node.
+ * @param   pCache              The cache.
+ * @param   pwszPath            The path.
+ * @param   poff                Where to return the root dire.
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ */
+static PKFSOBJ kFswCacheLookupUncShareW(PKFSCACHE pCache, const wchar_t *pwszPath, KU32 *poff, KFSLOOKUPERROR *penmError)
+{
+#if 0 /* later */
+    KU32 offStartServer;
+    KU32 offEndServer;
+    KU32 offStartShare;
+
+    KU32 offEnd = 2;
+    while (IS_SLASH(pwszPath[offEnd]))
+        offEnd++;
+
+    offStartServer = offEnd;
+    while (   (ch = pwszPath[offEnd]) != '\0'
+           && !IS_SLASH(ch))
+        offEnd++;
+    offEndServer = offEnd;
+
+    if (ch != '\0')
+    { /* likely */ }
+    else
+    {
+        *penmError = KFSLOOKUPERROR_NOT_FOUND;
+        return NULL;
+    }
+
+    while (IS_SLASH(pwszPath[offEnd]))
+        offEnd++;
+    offStartServer = offEnd;
+    while (   (ch = pwszPath[offEnd]) != '\0'
+           && !IS_SLASH(ch))
+        offEnd++;
+#endif
+    *penmError = KFSLOOKUPERROR_UNSUPPORTED;
+    return NULL;
+}
+
+
+/**
+ * Walks an full path relative to the given directory, ANSI version.
+ *
+ * This will create any missing nodes while walking.
+ *
+ * The caller will have to do the path hash table insertion of the result.
+ *
+ * @returns Pointer to the tree node corresponding to @a pszPath.
+ *          NULL on lookup failure, see @a penmError for details.
+ * @param   pCache              The cache.
+ * @param   pParent             The directory to start the lookup in.
+ * @param   pszPath             The path to walk.
+ * @param   cchPath             The length of the path.
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ * @param   ppLastAncestor      Where to return the last parent element found
+ *                              (referenced) in case of error an path/file not
+ *                              found problem.  Optional.
+ */
+PKFSOBJ kFsCacheLookupRelativeToDirA(PKFSCACHE pCache, PKFSDIR pParent, const char *pszPath, KU32 cchPath,
+                                     KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor)
+{
+    /*
+     * Walk loop.
+     */
+    KU32 off = 0;
+    if (ppLastAncestor)
+        *ppLastAncestor = NULL;
+    for (;;)
+    {
+        PKFSOBJ pChild;
+
+        /*
+         * Find the end of the component, counting trailing slashes.
+         */
+        char    ch;
+        KU32    cchSlashes = 0;
+        KU32    offEnd     = off + 1;
+        while ((ch = pszPath[offEnd]) != '\0')
+        {
+            if (!IS_SLASH(ch))
+                offEnd++;
+            else
+            {
+                do
+                    cchSlashes++;
+                while (IS_SLASH(pszPath[offEnd + cchSlashes]));
+                break;
+            }
+        }
+
+        /*
+         * Do we need to populate or refresh this directory first?
+         */
+        if (   pParent->fPopulated
+            && (   pParent->Obj.uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+                || pParent->Obj.uCacheGen == pCache->auGenerations[pParent->Obj.fFlags & KFSOBJ_F_USE_CUSTOM_GEN]) )
+        { /* likely */ }
+        else if (kFsCachePopuplateOrRefreshDir(pCache, pParent, penmError))
+        { /* likely */ }
+        else
+            return NULL;
+
+        /*
+         * Search the current node for the name.
+         *
+         * If we don't find it, we may insert a missing node depending on
+         * the cache configuration.
+         */
+        pChild = kFsCacheFindChildA(pCache, pParent, &pszPath[off], offEnd - off);
+        if (pChild != NULL)
+        { /* probably likely */ }
+        else
+        {
+            if (pCache->fFlags & KFSCACHE_F_MISSING_OBJECTS)
+                pChild = kFsCacheCreateMissingA(pCache, pParent, &pszPath[off], offEnd - off, penmError);
+            if (cchSlashes == 0 || offEnd + cchSlashes >= cchPath)
+            {
+                if (pChild)
+                    return kFsCacheObjRetainInternal(pChild);
+                *penmError = KFSLOOKUPERROR_NOT_FOUND;
+            }
+            else
+                *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_FOUND;
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
+            return NULL;
+        }
+
+        /* Advance off and check if we're done already. */
+        off = offEnd + cchSlashes;
+        if (   cchSlashes == 0
+            || off >= cchPath)
+        {
+            if (   pChild->bObjType != KFSOBJ_TYPE_MISSING
+                || pChild->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+                || pChild->uCacheGen == pCache->auGenerationsMissing[pChild->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                || kFsCacheRefreshMissing(pCache, pChild, penmError) )
+            { /* likely */ }
+            else
+                return NULL;
+            return kFsCacheObjRetainInternal(pChild);
+        }
+
+        /*
+         * Check that it's a directory.  If a missing entry, we may have to
+         * refresh it and re-examin it.
+         */
+        if (pChild->bObjType == KFSOBJ_TYPE_DIR)
+            pParent = (PKFSDIR)pChild;
+        else if (pChild->bObjType != KFSOBJ_TYPE_MISSING)
+        {
+            *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_DIR;
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
+            return NULL;
+        }
+        else if (   pChild->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+                 || pChild->uCacheGen == pCache->auGenerationsMissing[pChild->fFlags & KFSOBJ_F_USE_CUSTOM_GEN])
+        {
+            *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_FOUND;
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
+            return NULL;
+        }
+        else if (kFsCacheRefreshMissingIntermediateDir(pCache, pChild, penmError))
+            pParent = (PKFSDIR)pChild;
+        else
+        {
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
+            return NULL;
+        }
+    }
+
+    return NULL;
+
+}
+
+
+/**
+ * Walks an full path relative to the given directory, UTF-16 version.
+ *
+ * This will create any missing nodes while walking.
+ *
+ * The caller will have to do the path hash table insertion of the result.
+ *
+ * @returns Pointer to the tree node corresponding to @a pszPath.
+ *          NULL on lookup failure, see @a penmError for details.
+ * @param   pCache              The cache.
+ * @param   pParent             The directory to start the lookup in.
+ * @param   pszPath             The path to walk.  No dot-dot bits allowed!
+ * @param   cchPath             The length of the path.
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ * @param   ppLastAncestor      Where to return the last parent element found
+ *                              (referenced) in case of error an path/file not
+ *                              found problem.  Optional.
+ */
+PKFSOBJ kFsCacheLookupRelativeToDirW(PKFSCACHE pCache, PKFSDIR pParent, const wchar_t *pwszPath, KU32 cwcPath,
+                                     KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor)
+{
+    /*
+     * Walk loop.
+     */
+    KU32 off = 0;
+    if (ppLastAncestor)
+        *ppLastAncestor = NULL;
+    for (;;)
+    {
+        PKFSOBJ pChild;
+
+        /*
+         * Find the end of the component, counting trailing slashes.
+         */
+        wchar_t wc;
+        KU32    cwcSlashes = 0;
+        KU32    offEnd     = off + 1;
+        while ((wc = pwszPath[offEnd]) != '\0')
+        {
+            if (!IS_SLASH(wc))
+                offEnd++;
+            else
+            {
+                do
+                    cwcSlashes++;
+                while (IS_SLASH(pwszPath[offEnd + cwcSlashes]));
+                break;
+            }
+        }
+
+        /*
+         * Do we need to populate or refresh this directory first?
+         */
+        if (   pParent->fPopulated
+            && (   pParent->Obj.uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+                || pParent->Obj.uCacheGen == pCache->auGenerations[pParent->Obj.fFlags & KFSOBJ_F_USE_CUSTOM_GEN]) )
+        { /* likely */ }
+        else if (kFsCachePopuplateOrRefreshDir(pCache, pParent, penmError))
+        { /* likely */ }
+        else
+            return NULL;
+
+        /*
+         * Search the current node for the name.
+         *
+         * If we don't find it, we may insert a missing node depending on
+         * the cache configuration.
+         */
+        pChild = kFsCacheFindChildW(pCache, pParent, &pwszPath[off], offEnd - off);
+        if (pChild != NULL)
+        { /* probably likely */ }
+        else
+        {
+            if (pCache->fFlags & KFSCACHE_F_MISSING_OBJECTS)
+                pChild = kFsCacheCreateMissingW(pCache, pParent, &pwszPath[off], offEnd - off, penmError);
+            if (cwcSlashes == 0 || offEnd + cwcSlashes >= cwcPath)
+            {
+                if (pChild)
+                    return kFsCacheObjRetainInternal(pChild);
+                *penmError = KFSLOOKUPERROR_NOT_FOUND;
+            }
+            else
+                *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_FOUND;
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
+            return NULL;
+        }
+
+        /* Advance off and check if we're done already. */
+        off = offEnd + cwcSlashes;
+        if (   cwcSlashes == 0
+            || off >= cwcPath)
+        {
+            if (   pChild->bObjType != KFSOBJ_TYPE_MISSING
+                || pChild->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+                || pChild->uCacheGen == pCache->auGenerationsMissing[pChild->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                || kFsCacheRefreshMissing(pCache, pChild, penmError) )
+            { /* likely */ }
+            else
+                return NULL;
+            return kFsCacheObjRetainInternal(pChild);
+        }
+
+        /*
+         * Check that it's a directory.  If a missing entry, we may have to
+         * refresh it and re-examin it.
+         */
+        if (pChild->bObjType == KFSOBJ_TYPE_DIR)
+            pParent = (PKFSDIR)pChild;
+        else if (pChild->bObjType != KFSOBJ_TYPE_MISSING)
+        {
+            *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_DIR;
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
+            return NULL;
+        }
+        else if (   pChild->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+                 || pChild->uCacheGen == pCache->auGenerationsMissing[pChild->fFlags & KFSOBJ_F_USE_CUSTOM_GEN])
+        {
+            *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_FOUND;
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
+            return NULL;
+        }
+        else if (kFsCacheRefreshMissingIntermediateDir(pCache, pChild, penmError))
+            pParent = (PKFSDIR)pChild;
+        else
+        {
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
+            return NULL;
+        }
+    }
+
+    return NULL;
+
+}
+
+/**
+ * Walk the file system tree for the given absolute path, entering it into the
+ * hash table.
+ *
+ * This will create any missing nodes while walking.
+ *
+ * The caller will have to do the path hash table insertion of the result.
+ *
+ * @returns Pointer to the tree node corresponding to @a pszPath.
+ *          NULL on lookup failure, see @a penmError for details.
+ * @param   pCache              The cache.
+ * @param   pszPath             The path to walk. No dot-dot bits allowed!
+ * @param   cchPath             The length of the path.
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ * @param   ppLastAncestor      Where to return the last parent element found
+ *                              (referenced) in case of error an path/file not
+ *                              found problem.  Optional.
+ */
+static PKFSOBJ kFsCacheLookupAbsoluteA(PKFSCACHE pCache, const char *pszPath, KU32 cchPath,
+                                       KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor)
+{
+    PKFSOBJ     pRoot;
+    KU32        cchSlashes;
+    KU32        offEnd;
+
+    KFSCACHE_LOG2(("kFsCacheLookupAbsoluteA(%s)\n", pszPath));
+
+    /*
+     * The root "directory" needs special handling, so we keep it outside the
+     * main search loop. (Special: Cannot enumerate it, UNCs, ++.)
+     */
+    cchSlashes = 0;
+    if (   pszPath[1] == ':'
+        && IS_ALPHA(pszPath[0]))
+    {
+        /* Drive letter. */
+        offEnd = 2;
+        kHlpAssert(IS_SLASH(pszPath[2]));
+        pRoot = kFswCacheLookupDrive(pCache, toupper(pszPath[0]), penmError);
+    }
+    else if (   IS_SLASH(pszPath[0])
+             && IS_SLASH(pszPath[1]) )
+        pRoot = kFswCacheLookupUncShareA(pCache, pszPath, &offEnd, penmError);
+    else
+    {
+        *penmError = KFSLOOKUPERROR_UNSUPPORTED;
+        return NULL;
+    }
+    if (pRoot)
+    { /* likely */ }
+    else
+        return NULL;
+
+    /* Count slashes trailing the root spec. */
+    if (offEnd < cchPath)
+    {
+        kHlpAssert(IS_SLASH(pszPath[offEnd]));
+        do
+            cchSlashes++;
+        while (IS_SLASH(pszPath[offEnd + cchSlashes]));
+    }
+
+    /* Done already? */
+    if (offEnd >= cchPath)
+    {
+        if (   pRoot->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+            || pRoot->uCacheGen == (  pRoot->bObjType != KFSOBJ_TYPE_MISSING
+                                    ? pCache->auGenerations[       pRoot->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                    : pCache->auGenerationsMissing[pRoot->fFlags & KFSOBJ_F_USE_CUSTOM_GEN])
+            || kFsCacheRefreshObj(pCache, pRoot, penmError))
+            return kFsCacheObjRetainInternal(pRoot);
+        return NULL;
+    }
+
+    /* Check that we've got a valid result and not a cached negative one. */
+    if (pRoot->bObjType == KFSOBJ_TYPE_DIR)
+    { /* likely */ }
+    else
+    {
+        kHlpAssert(pRoot->bObjType == KFSOBJ_TYPE_MISSING);
+        kHlpAssert(   pRoot->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+                   || pRoot->uCacheGen == pCache->auGenerationsMissing[pRoot->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]);
+        return pRoot;
+    }
+
+    /*
+     * Now that we've found a valid root directory, lookup the
+     * remainder of the path starting with it.
+     */
+    return kFsCacheLookupRelativeToDirA(pCache, (PKFSDIR)pRoot, &pszPath[offEnd + cchSlashes],
+                                        cchPath - offEnd - cchSlashes, penmError, ppLastAncestor);
+}
+
+
+/**
+ * Walk the file system tree for the given absolute path, UTF-16 version.
+ *
+ * This will create any missing nodes while walking.
+ *
+ * The caller will have to do the path hash table insertion of the result.
+ *
+ * @returns Pointer to the tree node corresponding to @a pszPath.
+ *          NULL on lookup failure, see @a penmError for details.
+ * @param   pCache              The cache.
+ * @param   pwszPath            The path to walk.
+ * @param   cwcPath             The length of the path (in wchar_t's).
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ * @param   ppLastAncestor      Where to return the last parent element found
+ *                              (referenced) in case of error an path/file not
+ *                              found problem.  Optional.
+ */
+static PKFSOBJ kFsCacheLookupAbsoluteW(PKFSCACHE pCache, const wchar_t *pwszPath, KU32 cwcPath,
+                                       KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor)
+{
+    PKFSDIR     pParent = &pCache->RootDir;
+    PKFSOBJ     pRoot;
+    KU32        off;
+    KU32        cwcSlashes;
+    KU32        offEnd;
+
+    KFSCACHE_LOG2(("kFsCacheLookupAbsoluteW(%ls)\n", pwszPath));
+
+    /*
+     * The root "directory" needs special handling, so we keep it outside the
+     * main search loop. (Special: Cannot enumerate it, UNCs, ++.)
+     */
+    cwcSlashes = 0;
+    off        = 0;
+    if (   pwszPath[1] == ':'
+        && IS_ALPHA(pwszPath[0]))
+    {
+        /* Drive letter. */
+        offEnd = 2;
+        kHlpAssert(IS_SLASH(pwszPath[2]));
+        pRoot = kFswCacheLookupDrive(pCache, toupper(pwszPath[0]), penmError);
+    }
+    else if (   IS_SLASH(pwszPath[0])
+             && IS_SLASH(pwszPath[1]) )
+        pRoot = kFswCacheLookupUncShareW(pCache, pwszPath, &offEnd, penmError);
+    else
+    {
+        *penmError = KFSLOOKUPERROR_UNSUPPORTED;
+        return NULL;
+    }
+    if (pRoot)
+    { /* likely */ }
+    else
+        return NULL;
+
+    /* Count slashes trailing the root spec. */
+    if (offEnd < cwcPath)
+    {
+        kHlpAssert(IS_SLASH(pwszPath[offEnd]));
+        do
+            cwcSlashes++;
+        while (IS_SLASH(pwszPath[offEnd + cwcSlashes]));
+    }
+
+    /* Done already? */
+    if (offEnd >= cwcPath)
+    {
+        if (   pRoot->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+            || pRoot->uCacheGen == (pRoot->bObjType != KFSOBJ_TYPE_MISSING
+                                    ? pCache->auGenerations[       pRoot->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                    : pCache->auGenerationsMissing[pRoot->fFlags & KFSOBJ_F_USE_CUSTOM_GEN])
+            || kFsCacheRefreshObj(pCache, pRoot, penmError))
+            return kFsCacheObjRetainInternal(pRoot);
+        return NULL;
+    }
+
+    /* Check that we've got a valid result and not a cached negative one. */
+    if (pRoot->bObjType == KFSOBJ_TYPE_DIR)
+    { /* likely */ }
+    else
+    {
+        kHlpAssert(pRoot->bObjType == KFSOBJ_TYPE_MISSING);
+        kHlpAssert(   pRoot->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+                   || pRoot->uCacheGen == pCache->auGenerationsMissing[pRoot->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]);
+        return pRoot;
+    }
+
+    /*
+     * Now that we've found a valid root directory, lookup the
+     * remainder of the path starting with it.
+     */
+    return kFsCacheLookupRelativeToDirW(pCache, (PKFSDIR)pRoot, &pwszPath[offEnd + cwcSlashes],
+                                        cwcPath - offEnd - cwcSlashes, penmError, ppLastAncestor);
+}
+
+
+/**
+ * This deals with paths that are relative and paths that contains '..'
+ * elements, ANSI version.
+ *
+ * @returns Pointer to object corresponding to @a pszPath on success.
+ *          NULL if this isn't a path we care to cache.
+ *
+ * @param   pCache              The cache.
+ * @param   pszPath             The path.
+ * @param   cchPath             The length of the path.
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ * @param   ppLastAncestor      Where to return the last parent element found
+ *                              (referenced) in case of error an path/file not
+ *                              found problem.  Optional.
+ */
+static PKFSOBJ kFsCacheLookupSlowA(PKFSCACHE pCache, const char *pszPath, KU32 cchPath,
+                                   KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor)
+{
+    /*
+     * We just call GetFullPathNameA here to do the job as getcwd and _getdcwd
+     * ends up calling it anyway.
+     */
+    char szFull[KFSCACHE_CFG_MAX_PATH];
+    UINT cchFull = GetFullPathNameA(pszPath, sizeof(szFull), szFull, NULL);
+    if (   cchFull >= 3
+        && cchFull < sizeof(szFull))
+    {
+        PKFSOBJ pFsObj;
+        KFSCACHE_LOG2(("kFsCacheLookupSlowA(%s)\n", pszPath));
+        pFsObj = kFsCacheLookupAbsoluteA(pCache, szFull, cchFull, penmError, ppLastAncestor);
+
+#if 0 /* No need to do this until it's actually queried. */
+        /* Cache the resulting path. */
+        if (   pFsObj
+            || (pCache->fFlags & KFSCACHE_F_MISSING_PATHS)
+            || *penmError == KFSLOOKUPERROR_UNSUPPORTED)
+        {
+            KU32 uHashPath = kFsCacheStrHash(szFull);
+            kFsCacheCreatePathHashTabEntryA(pCache, pFsObj, pszPath, cchPath, uHashPath,
+                                            uHashPath % K_ELEMENTS(pCache->apAnsiPaths), *penmError);
+        }
+#endif
+        return pFsObj;
+    }
+
+    /* The path is too long! */
+    kHlpAssertMsgFailed(("'%s' -> cchFull=%u\n", pszPath, cchFull));
+    *penmError = KFSLOOKUPERROR_PATH_TOO_LONG;
+    return NULL;
+}
+
+
+/**
+ * This deals with paths that are relative and paths that contains '..'
+ * elements, UTF-16 version.
+ *
+ * @returns Pointer to object corresponding to @a pszPath on success.
+ *          NULL if this isn't a path we care to cache.
+ *
+ * @param   pCache              The cache.
+ * @param   pwszPath            The path.
+ * @param   cwcPath             The length of the path (in wchar_t's).
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ * @param   ppLastAncestor      Where to return the last parent element found
+ *                              (referenced) in case of error an path/file not
+ *                              found problem.  Optional.
+ */
+static PKFSOBJ kFsCacheLookupSlowW(PKFSCACHE pCache, const wchar_t *pwszPath, KU32 wcwPath,
+                                   KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor)
+{
+    /*
+     * We just call GetFullPathNameA here to do the job as getcwd and _getdcwd
+     * ends up calling it anyway.
+     */
+    wchar_t wszFull[KFSCACHE_CFG_MAX_PATH];
+    UINT cwcFull = GetFullPathNameW(pwszPath, KFSCACHE_CFG_MAX_PATH, wszFull, NULL);
+    if (   cwcFull >= 3
+        && cwcFull < KFSCACHE_CFG_MAX_PATH)
+    {
+        PKFSOBJ pFsObj;
+        KFSCACHE_LOG2(("kFsCacheLookupSlowA(%ls)\n", pwszPath));
+        pFsObj = kFsCacheLookupAbsoluteW(pCache, wszFull, cwcFull, penmError, ppLastAncestor);
+
+#if 0 /* No need to do this until it's actually queried. */
+        /* Cache the resulting path. */
+        if (   pFsObj
+            || (pCache->fFlags & KFSCACHE_F_MISSING_PATHS)
+            || *penmError == KFSLOOKUPERROR_UNSUPPORTED)
+        {
+            KU32 uHashPath = kFsCacheStrHash(szFull);
+            kFsCacheCreatePathHashTabEntryA(pCache, pFsObj, pszPath, cchPath, uHashPath,
+                                            uHashPath % K_ELEMENTS(pCache->apAnsiPaths), *penmError);
+        }
+#endif
+        return pFsObj;
+    }
+
+    /* The path is too long! */
+    kHlpAssertMsgFailed(("'%ls' -> cwcFull=%u\n", pwszPath, cwcFull));
+    *penmError = KFSLOOKUPERROR_PATH_TOO_LONG;
+    return NULL;
+}
+
+
+/**
+ * Refreshes a path hash that has expired, ANSI version.
+ *
+ * @returns pHash on success, NULL if removed.
+ * @param   pCache              The cache.
+ * @param   pHashEntry          The path hash.
+ * @param   idxHashTab          The hash table entry.
+ */
+static PKFSHASHA kFsCacheRefreshPathA(PKFSCACHE pCache, PKFSHASHA pHashEntry, KU32 idxHashTab)
+{
+    PKFSOBJ pLastAncestor = NULL;
+    if (!pHashEntry->pFsObj)
+    {
+        if (pHashEntry->fAbsolute)
+            pHashEntry->pFsObj = kFsCacheLookupAbsoluteA(pCache, pHashEntry->pszPath, pHashEntry->cchPath,
+                                                         &pHashEntry->enmError, &pLastAncestor);
+        else
+            pHashEntry->pFsObj = kFsCacheLookupSlowA(pCache, pHashEntry->pszPath, pHashEntry->cchPath,
+                                                     &pHashEntry->enmError, &pLastAncestor);
+    }
+    else
+    {
+        KU8             bOldType = pHashEntry->pFsObj->bObjType;
+        KFSLOOKUPERROR  enmError;
+        if (kFsCacheRefreshObj(pCache, pHashEntry->pFsObj, &enmError))
+        {
+            if (pHashEntry->pFsObj->bObjType == bOldType)
+            { }
+            else
+            {
+                kFsCacheObjRelease(pCache, pHashEntry->pFsObj);
+                if (pHashEntry->fAbsolute)
+                    pHashEntry->pFsObj = kFsCacheLookupAbsoluteA(pCache, pHashEntry->pszPath, pHashEntry->cchPath,
+                                                                 &pHashEntry->enmError, &pLastAncestor);
+                else
+                    pHashEntry->pFsObj = kFsCacheLookupSlowA(pCache, pHashEntry->pszPath, pHashEntry->cchPath,
+                                                             &pHashEntry->enmError, &pLastAncestor);
+            }
+        }
+        else
+        {
+            fprintf(stderr, "kFsCacheRefreshPathA - refresh failure handling not implemented!\n");
+            __debugbreak();
+            /** @todo just remove this entry.   */
+            return NULL;
+        }
+    }
+
+    if (pLastAncestor && !pHashEntry->pFsObj)
+        pHashEntry->idxMissingGen = pLastAncestor->fFlags & KFSOBJ_F_USE_CUSTOM_GEN;
+    pHashEntry->uCacheGen = !pHashEntry->pFsObj
+                          ? pCache->auGenerationsMissing[pHashEntry->idxMissingGen]
+                          : pHashEntry->pFsObj->bObjType == KFSOBJ_TYPE_MISSING
+                          ? pCache->auGenerationsMissing[pHashEntry->pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                          : pCache->auGenerations[       pHashEntry->pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
+    if (pLastAncestor)
+        kFsCacheObjRelease(pCache, pLastAncestor);
+    return pHashEntry;
+}
+
+
+/**
+ * Refreshes a path hash that has expired, UTF-16 version.
+ *
+ * @returns pHash on success, NULL if removed.
+ * @param   pCache              The cache.
+ * @param   pHashEntry          The path hash.
+ * @param   idxHashTab          The hash table entry.
+ */
+static PKFSHASHW kFsCacheRefreshPathW(PKFSCACHE pCache, PKFSHASHW pHashEntry, KU32 idxHashTab)
+{
+    PKFSOBJ pLastAncestor = NULL;
+    if (!pHashEntry->pFsObj)
+    {
+        if (pHashEntry->fAbsolute)
+            pHashEntry->pFsObj = kFsCacheLookupAbsoluteW(pCache, pHashEntry->pwszPath, pHashEntry->cwcPath,
+                                                         &pHashEntry->enmError, &pLastAncestor);
+        else
+            pHashEntry->pFsObj = kFsCacheLookupSlowW(pCache, pHashEntry->pwszPath, pHashEntry->cwcPath,
+                                                     &pHashEntry->enmError, &pLastAncestor);
+    }
+    else
+    {
+        KU8             bOldType = pHashEntry->pFsObj->bObjType;
+        KFSLOOKUPERROR  enmError;
+        if (kFsCacheRefreshObj(pCache, pHashEntry->pFsObj, &enmError))
+        {
+            if (pHashEntry->pFsObj->bObjType == bOldType)
+            { }
+            else
+            {
+                kFsCacheObjRelease(pCache, pHashEntry->pFsObj);
+                if (pHashEntry->fAbsolute)
+                    pHashEntry->pFsObj = kFsCacheLookupAbsoluteW(pCache, pHashEntry->pwszPath, pHashEntry->cwcPath,
+                                                                 &pHashEntry->enmError, &pLastAncestor);
+                else
+                    pHashEntry->pFsObj = kFsCacheLookupSlowW(pCache, pHashEntry->pwszPath, pHashEntry->cwcPath,
+                                                             &pHashEntry->enmError, &pLastAncestor);
+            }
+        }
+        else
+        {
+            fprintf(stderr, "kFsCacheRefreshPathW - refresh failure handling not implemented!\n");
+            __debugbreak();
+            /** @todo just remove this entry.   */
+            return NULL;
+        }
+    }
+    if (pLastAncestor && !pHashEntry->pFsObj)
+        pHashEntry->idxMissingGen = pLastAncestor->fFlags & KFSOBJ_F_USE_CUSTOM_GEN;
+    pHashEntry->uCacheGen = !pHashEntry->pFsObj
+                          ? pCache->auGenerationsMissing[pHashEntry->idxMissingGen]
+                          : pHashEntry->pFsObj->bObjType == KFSOBJ_TYPE_MISSING
+                          ? pCache->auGenerationsMissing[pHashEntry->pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                          : pCache->auGenerations[       pHashEntry->pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
+    if (pLastAncestor)
+        kFsCacheObjRelease(pCache, pLastAncestor);
+    return pHashEntry;
+}
+
+
+/**
+ * Internal lookup worker that looks up a KFSOBJ for the given ANSI path with
+ * length and hash.
+ *
+ * This will first try the hash table.  If not in the hash table, the file
+ * system cache tree is walked, missing bits filled in and finally a hash table
+ * entry is created.
+ *
+ * Only drive letter paths are cachable.  We don't do any UNC paths at this
+ * point.
+ *
+ * @returns Reference to object corresponding to @a pszPath on success, this
+ *          must be released by kFsCacheObjRelease.
+ *          NULL if not a path we care to cache.
+ * @param   pCache              The cache.
+ * @param   pchPath             The path to lookup.
+ * @param   cchPath             The path length.
+ * @param   uHashPath           The hash of the path.
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ */
+static PKFSOBJ kFsCacheLookupHashedA(PKFSCACHE pCache, const char *pchPath, KU32 cchPath, KU32 uHashPath,
+                                     KFSLOOKUPERROR *penmError)
+{
+    /*
+     * Do hash table lookup of the path.
+     */
+    KU32        idxHashTab = uHashPath % K_ELEMENTS(pCache->apAnsiPaths);
+    PKFSHASHA   pHashEntry = pCache->apAnsiPaths[idxHashTab];
+    kHlpAssert(pCache->u32Magic == KFSCACHE_MAGIC);
+    if (pHashEntry)
+    {
+        do
+        {
+            if (   pHashEntry->uHashPath == uHashPath
+                && pHashEntry->cchPath   == cchPath
+                && kHlpMemComp(pHashEntry->pszPath, pchPath, cchPath) == 0)
+            {
+                PKFSOBJ pFsObj;
+                if (   pHashEntry->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+                    || pHashEntry->uCacheGen == (  (pFsObj = pHashEntry->pFsObj) != NULL
+                                                 ? pFsObj->bObjType != KFSOBJ_TYPE_MISSING
+                                                   ? pCache->auGenerations[       pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                                   : pCache->auGenerationsMissing[pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                                 : pCache->auGenerationsMissing[pHashEntry->idxMissingGen])
+                    || (pHashEntry = kFsCacheRefreshPathA(pCache, pHashEntry, idxHashTab)) )
+                {
+                    pCache->cLookups++;
+                    pCache->cPathHashHits++;
+                    KFSCACHE_LOG2(("kFsCacheLookupA(%*.*s) - hit %p\n", cchPath, cchPath, pchPath, pHashEntry->pFsObj));
+                    *penmError = pHashEntry->enmError;
+                    if (pHashEntry->pFsObj)
+                        return kFsCacheObjRetainInternal(pHashEntry->pFsObj);
+                    return NULL;
+                }
+                break;
+            }
+            pHashEntry = pHashEntry->pNext;
+        } while (pHashEntry);
+    }
+
+    /*
+     * Create an entry for it by walking the file system cache and filling in the blanks.
+     */
+    if (   cchPath > 0
+        && cchPath < KFSCACHE_CFG_MAX_PATH)
+    {
+        PKFSOBJ pFsObj;
+        KBOOL   fAbsolute;
+        PKFSOBJ pLastAncestor = NULL;
+
+        /* Is absolute without any '..' bits? */
+        if (   cchPath >= 3
+            && (   (   pchPath[1] == ':'    /* Drive letter */
+                    && IS_SLASH(pchPath[2])
+                    && IS_ALPHA(pchPath[0]) )
+                || (   IS_SLASH(pchPath[0]) /* UNC */
+                    && IS_SLASH(pchPath[1]) ) )
+            && !kFsCacheHasDotDotA(pchPath, cchPath) )
+        {
+            pFsObj = kFsCacheLookupAbsoluteA(pCache, pchPath, cchPath, penmError, &pLastAncestor);
+            fAbsolute = K_TRUE;
+        }
+        else
+        {
+            pFsObj = kFsCacheLookupSlowA(pCache, pchPath, cchPath, penmError, &pLastAncestor);
+            fAbsolute = K_FALSE;
+        }
+        if (   pFsObj
+            || (   (pCache->fFlags & KFSCACHE_F_MISSING_PATHS)
+                && *penmError != KFSLOOKUPERROR_PATH_TOO_LONG)
+            || *penmError == KFSLOOKUPERROR_UNSUPPORTED )
+            kFsCacheCreatePathHashTabEntryA(pCache, pFsObj, pchPath, cchPath, uHashPath, idxHashTab, fAbsolute,
+                                            pLastAncestor ? pLastAncestor->bObjType & KFSOBJ_F_USE_CUSTOM_GEN : 0, *penmError);
+        if (pLastAncestor)
+            kFsCacheObjRelease(pCache, pLastAncestor);
+
+        pCache->cLookups++;
+        if (pFsObj)
+            pCache->cWalkHits++;
+        return pFsObj;
+    }
+
+    *penmError = KFSLOOKUPERROR_PATH_TOO_LONG;
+    return NULL;
+}
+
+
+/**
+ * Internal lookup worker that looks up a KFSOBJ for the given UTF-16 path with
+ * length and hash.
+ *
+ * This will first try the hash table.  If not in the hash table, the file
+ * system cache tree is walked, missing bits filled in and finally a hash table
+ * entry is created.
+ *
+ * Only drive letter paths are cachable.  We don't do any UNC paths at this
+ * point.
+ *
+ * @returns Reference to object corresponding to @a pwcPath on success, this
+ *          must be released by kFsCacheObjRelease.
+ *          NULL if not a path we care to cache.
+ * @param   pCache              The cache.
+ * @param   pwcPath             The path to lookup.
+ * @param   cwcPath             The length of the path (in wchar_t's).
+ * @param   uHashPath           The hash of the path.
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ */
+static PKFSOBJ kFsCacheLookupHashedW(PKFSCACHE pCache, const wchar_t *pwcPath, KU32 cwcPath, KU32 uHashPath,
+                                     KFSLOOKUPERROR *penmError)
+{
+    /*
+     * Do hash table lookup of the path.
+     */
+    KU32        idxHashTab = uHashPath % K_ELEMENTS(pCache->apAnsiPaths);
+    PKFSHASHW   pHashEntry = pCache->apUtf16Paths[idxHashTab];
+    kHlpAssert(pCache->u32Magic == KFSCACHE_MAGIC);
+    if (pHashEntry)
+    {
+        do
+        {
+            if (   pHashEntry->uHashPath == uHashPath
+                && pHashEntry->cwcPath   == cwcPath
+                && kHlpMemComp(pHashEntry->pwszPath, pwcPath, cwcPath) == 0)
+            {
+                PKFSOBJ pFsObj;
+                if (   pHashEntry->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+                    || pHashEntry->uCacheGen == ((pFsObj = pHashEntry->pFsObj) != NULL
+                                                 ? pFsObj->bObjType != KFSOBJ_TYPE_MISSING
+                                                   ? pCache->auGenerations[       pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                                   : pCache->auGenerationsMissing[pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                                 : pCache->auGenerationsMissing[pHashEntry->idxMissingGen])
+                    || (pHashEntry = kFsCacheRefreshPathW(pCache, pHashEntry, idxHashTab)) )
+                {
+                    pCache->cLookups++;
+                    pCache->cPathHashHits++;
+                    KFSCACHE_LOG2(("kFsCacheLookupW(%*.*ls) - hit %p\n", cwcPath, cwcPath, pwcPath, pHashEntry->pFsObj));
+                    *penmError = pHashEntry->enmError;
+                    if (pHashEntry->pFsObj)
+                        return kFsCacheObjRetainInternal(pHashEntry->pFsObj);
+                    return NULL;
+                }
+                break;
+            }
+            pHashEntry = pHashEntry->pNext;
+        } while (pHashEntry);
+    }
+
+    /*
+     * Create an entry for it by walking the file system cache and filling in the blanks.
+     */
+    if (   cwcPath > 0
+        && cwcPath < KFSCACHE_CFG_MAX_PATH)
+    {
+        PKFSOBJ pFsObj;
+        KBOOL   fAbsolute;
+        PKFSOBJ pLastAncestor = NULL;
+
+        /* Is absolute without any '..' bits? */
+        if (   cwcPath >= 3
+            && (   (   pwcPath[1] == ':'    /* Drive letter */
+                    && IS_SLASH(pwcPath[2])
+                    && IS_ALPHA(pwcPath[0]) )
+                || (   IS_SLASH(pwcPath[0]) /* UNC */
+                    && IS_SLASH(pwcPath[1]) ) )
+            && !kFsCacheHasDotDotW(pwcPath, cwcPath) )
+        {
+            pFsObj = kFsCacheLookupAbsoluteW(pCache, pwcPath, cwcPath, penmError, &pLastAncestor);
+            fAbsolute = K_TRUE;
+        }
+        else
+        {
+            pFsObj = kFsCacheLookupSlowW(pCache, pwcPath, cwcPath, penmError, &pLastAncestor);
+            fAbsolute = K_FALSE;
+        }
+        if (   pFsObj
+            || (   (pCache->fFlags & KFSCACHE_F_MISSING_PATHS)
+                && *penmError != KFSLOOKUPERROR_PATH_TOO_LONG)
+            || *penmError == KFSLOOKUPERROR_UNSUPPORTED )
+            kFsCacheCreatePathHashTabEntryW(pCache, pFsObj, pwcPath, cwcPath, uHashPath, idxHashTab, fAbsolute,
+                                            pLastAncestor ? pLastAncestor->bObjType & KFSOBJ_F_USE_CUSTOM_GEN : 0, *penmError);
+        if (pLastAncestor)
+            kFsCacheObjRelease(pCache, pLastAncestor);
+
+        pCache->cLookups++;
+        if (pFsObj)
+            pCache->cWalkHits++;
+        return pFsObj;
+    }
+
+    *penmError = KFSLOOKUPERROR_PATH_TOO_LONG;
+    return NULL;
+}
+
+
+
+/**
+ * Looks up a KFSOBJ for the given ANSI path.
+ *
+ * This will first try the hash table.  If not in the hash table, the file
+ * system cache tree is walked, missing bits filled in and finally a hash table
+ * entry is created.
+ *
+ * Only drive letter paths are cachable.  We don't do any UNC paths at this
+ * point.
+ *
+ * @returns Reference to object corresponding to @a pszPath on success, this
+ *          must be released by kFsCacheObjRelease.
+ *          NULL if not a path we care to cache.
+ * @param   pCache              The cache.
+ * @param   pszPath             The path to lookup.
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ */
+PKFSOBJ kFsCacheLookupA(PKFSCACHE pCache, const char *pszPath, KFSLOOKUPERROR *penmError)
+{
+    KU32 uHashPath;
+    KU32 cchPath = (KU32)kFsCacheStrHashEx(pszPath, &uHashPath);
+    return kFsCacheLookupHashedA(pCache, pszPath, cchPath, uHashPath, penmError);
+}
+
+
+/**
+ * Looks up a KFSOBJ for the given UTF-16 path.
+ *
+ * This will first try the hash table.  If not in the hash table, the file
+ * system cache tree is walked, missing bits filled in and finally a hash table
+ * entry is created.
+ *
+ * Only drive letter paths are cachable.  We don't do any UNC paths at this
+ * point.
+ *
+ * @returns Reference to object corresponding to @a pwszPath on success, this
+ *          must be released by kFsCacheObjRelease.
+ *          NULL if not a path we care to cache.
+ * @param   pCache              The cache.
+ * @param   pwszPath            The path to lookup.
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ */
+PKFSOBJ kFsCacheLookupW(PKFSCACHE pCache, const wchar_t *pwszPath, KFSLOOKUPERROR *penmError)
+{
+    KU32 uHashPath;
+    KU32 cwcPath = (KU32)kFsCacheUtf16HashEx(pwszPath, &uHashPath);
+    return kFsCacheLookupHashedW(pCache, pwszPath, cwcPath, uHashPath, penmError);
+}
+
+
+/**
+ * Looks up a KFSOBJ for the given ANSI path.
+ *
+ * This will first try the hash table.  If not in the hash table, the file
+ * system cache tree is walked, missing bits filled in and finally a hash table
+ * entry is created.
+ *
+ * Only drive letter paths are cachable.  We don't do any UNC paths at this
+ * point.
+ *
+ * @returns Reference to object corresponding to @a pchPath on success, this
+ *          must be released by kFsCacheObjRelease.
+ *          NULL if not a path we care to cache.
+ * @param   pCache              The cache.
+ * @param   pchPath             The path to lookup (does not need to be nul
+ *                              terminated).
+ * @param   cchPath             The path length.
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ */
+PKFSOBJ kFsCacheLookupWithLengthA(PKFSCACHE pCache, const char *pchPath, KSIZE cchPath, KFSLOOKUPERROR *penmError)
+{
+    return kFsCacheLookupHashedA(pCache, pchPath, (KU32)cchPath, kFsCacheStrHashN(pchPath, cchPath), penmError);
+}
+
+
+/**
+ * Looks up a KFSOBJ for the given UTF-16 path.
+ *
+ * This will first try the hash table.  If not in the hash table, the file
+ * system cache tree is walked, missing bits filled in and finally a hash table
+ * entry is created.
+ *
+ * Only drive letter paths are cachable.  We don't do any UNC paths at this
+ * point.
+ *
+ * @returns Reference to object corresponding to @a pwchPath on success, this
+ *          must be released by kFsCacheObjRelease.
+ *          NULL if not a path we care to cache.
+ * @param   pCache              The cache.
+ * @param   pwcPath             The path to lookup (does not need to be nul
+ *                              terminated).
+ * @param   cwcPath             The path length (in wchar_t's).
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ */
+PKFSOBJ kFsCacheLookupWithLengthW(PKFSCACHE pCache, const wchar_t *pwcPath, KSIZE cwcPath, KFSLOOKUPERROR *penmError)
+{
+    return kFsCacheLookupHashedW(pCache, pwcPath, (KU32)cwcPath, kFsCacheUtf16HashN(pwcPath, cwcPath), penmError);
+}
+
+
+/**
+ * Wrapper around kFsCacheLookupA that drops KFSOBJ_TYPE_MISSING and returns
+ * KFSLOOKUPERROR_NOT_FOUND instead.
+ *
+ * @returns Reference to object corresponding to @a pszPath on success, this
+ *          must be released by kFsCacheObjRelease.
+ *          NULL if not a path we care to cache.
+ * @param   pCache              The cache.
+ * @param   pszPath             The path to lookup.
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ */
+PKFSOBJ kFsCacheLookupNoMissingA(PKFSCACHE pCache, const char *pszPath, KFSLOOKUPERROR *penmError)
+{
+    PKFSOBJ pObj = kFsCacheLookupA(pCache, pszPath, penmError);
+    if (pObj)
+    {
+        if (pObj->bObjType != KFSOBJ_TYPE_MISSING)
+            return pObj;
+
+        kFsCacheObjRelease(pCache, pObj);
+        *penmError = KFSLOOKUPERROR_NOT_FOUND;
+    }
+    return NULL;
+}
+
+
+/**
+ * Wrapper around kFsCacheLookupW that drops KFSOBJ_TYPE_MISSING and returns
+ * KFSLOOKUPERROR_NOT_FOUND instead.
+ *
+ * @returns Reference to object corresponding to @a pszPath on success, this
+ *          must be released by kFsCacheObjRelease.
+ *          NULL if not a path we care to cache.
+ * @param   pCache              The cache.
+ * @param   pwszPath            The path to lookup.
+ * @param   penmError           Where to return details as to why the lookup
+ *                              failed.
+ */
+PKFSOBJ kFsCacheLookupNoMissingW(PKFSCACHE pCache, const wchar_t *pwszPath, KFSLOOKUPERROR *penmError)
+{
+    PKFSOBJ pObj = kFsCacheLookupW(pCache, pwszPath, penmError);
+    if (pObj)
+    {
+        if (pObj->bObjType != KFSOBJ_TYPE_MISSING)
+            return pObj;
+
+        kFsCacheObjRelease(pCache, pObj);
+        *penmError = KFSLOOKUPERROR_NOT_FOUND;
+    }
+    return NULL;
+}
+
+
+/**
+ * Destroys a cache object which has a zero reference count.
+ *
+ * @returns 0
+ * @param   pCache              The cache.
+ * @param   pObj                The object.
+ */
+KU32 kFsCacheObjDestroy(PKFSCACHE pCache, PKFSOBJ pObj)
+{
+    kHlpAssert(pObj->cRefs == 0);
+    kHlpAssert(pObj->pParent == NULL);
+    kHlpAssert(pObj->u32Magic == KFSOBJ_MAGIC);
+
+    KFSCACHE_LOG(("Destroying %s/%s, type=%d\n", pObj->pParent ? pObj->pParent->Obj.pszName : "", pObj->pszName, pObj->bObjType));
+    if (pObj->abUnused[1] != 0)
+    {
+        fprintf(stderr, "Destroying %s/%s, type=%d, path hash entries: %d!\n", pObj->pParent ? pObj->pParent->Obj.pszName : "",
+                pObj->pszName, pObj->bObjType, pObj->abUnused[0]);
+        __debugbreak();
+    }
+
+    /*
+     * Invalidate the structure.
+     */
+    pObj->u32Magic = ~KFSOBJ_MAGIC;
+
+    /*
+     * Destroy any user data first.
+     */
+    while (pObj->pUserDataHead != NULL)
+    {
+        PKFSUSERDATA pUserData = pObj->pUserDataHead;
+        pObj->pUserDataHead = pUserData->pNext;
+        if (pUserData->pfnDestructor)
+            pUserData->pfnDestructor(pCache, pObj, pUserData);
+        kHlpFree(pUserData);
+    }
+
+    /*
+     * Do type specific destruction
+     */
+    switch (pObj->bObjType)
+    {
+        case KFSOBJ_TYPE_MISSING:
+            /* nothing else to do here */
+            pCache->cbObjects -= sizeof(KFSDIR);
+            break;
+
+        case KFSOBJ_TYPE_DIR:
+        {
+            PKFSDIR pDir = (PKFSDIR)pObj;
+            KU32    cChildren = pDir->cChildren;
+            pCache->cbObjects -= sizeof(*pDir)
+                               + K_ALIGN_Z(cChildren, 16) * sizeof(pDir->papChildren)
+                               + pDir->cHashTab * sizeof(pDir->paHashTab);
+
+            pDir->cChildren   = 0;
+            while (cChildren-- > 0)
+                kFsCacheObjRelease(pCache, pDir->papChildren[cChildren]);
+            kHlpFree(pDir->papChildren);
+            pDir->papChildren = NULL;
+
+            kHlpFree(pDir->paHashTab);
+            pDir->paHashTab = NULL;
+            break;
+        }
+
+        case KFSOBJ_TYPE_FILE:
+        case KFSOBJ_TYPE_OTHER:
+            pCache->cbObjects -= sizeof(*pObj);
+            break;
+
+        default:
+            return 0;
+    }
+
+    /*
+     * Common bits.
+     */
+    pCache->cbObjects -= pObj->cchName + 1;
+#ifdef KFSCACHE_CFG_UTF16
+    pCache->cbObjects -= (pObj->cwcName + 1) * sizeof(wchar_t);
+#endif
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+    if (pObj->pszName != pObj->pszShortName)
+    {
+        pCache->cbObjects -= pObj->cchShortName + 1;
+# ifdef KFSCACHE_CFG_UTF16
+        pCache->cbObjects -= (pObj->cwcShortName + 1) * sizeof(wchar_t);
+# endif
+    }
+#endif
+    pCache->cObjects--;
+
+    kHlpFree(pObj);
+    return 0;
+}
+
+
+/**
+ * Releases a reference to a cache object.
+ *
+ * @returns New reference count.
+ * @param   pCache              The cache.
+ * @param   pObj                The object.
+ */
+KU32 kFsCacheObjRelease(PKFSCACHE pCache, PKFSOBJ pObj)
+{
+    if (pObj)
+    {
+        KU32 cRefs;
+        kHlpAssert(pCache->u32Magic == KFSCACHE_MAGIC);
+        kHlpAssert(pObj->u32Magic == KFSOBJ_MAGIC);
+
+        cRefs = --pObj->cRefs;
+        if (cRefs)
+            return cRefs;
+        return kFsCacheObjDestroy(pCache, pObj);
+    }
+    return 0;
+}
+
+
+/**
+ * Retains a reference to a cahce object.
+ *
+ * @returns New reference count.
+ * @param   pObj                The object.
+ */
+KU32 kFsCacheObjRetain(PKFSOBJ pObj)
+{
+    KU32 cRefs;
+    kHlpAssert(pCache->u32Magic == KFSCACHE_MAGIC);
+    kHlpAssert(pObj->u32Magic == KFSOBJ_MAGIC);
+
+    cRefs = ++pObj->cRefs;
+    kHlpAssert(cRefs < 16384);
+    return cRefs;
+}
+
+
+/**
+ * Associates an item of user data with the given object.
+ *
+ * If the data needs cleaning up before being free, set the
+ * PKFSUSERDATA::pfnDestructor member of the returned structure.
+ *
+ * @returns Pointer to the user data on success.
+ *          NULL if out of memory or key already in use.
+ *
+ * @param   pCache              The cache.
+ * @param   pObj                The object.
+ * @param   uKey                The user data key.
+ * @param   cbUserData          The size of the user data.
+ */
+PKFSUSERDATA kFsCacheObjAddUserData(PKFSCACHE pCache, PKFSOBJ pObj, KUPTR uKey, KSIZE cbUserData)
+{
+    kHlpAssert(cbUserData >= sizeof(*pNew));
+    if (kFsCacheObjGetUserData(pCache, pObj, uKey) == NULL)
+    {
+        PKFSUSERDATA pNew = (PKFSUSERDATA)kHlpAllocZ(cbUserData);
+        if (pNew)
+        {
+            pNew->uKey          = uKey;
+            pNew->pfnDestructor = NULL;
+            pNew->pNext         = pObj->pUserDataHead;
+            pObj->pUserDataHead = pNew;
+            return pNew;
+        }
+    }
+
+    return NULL;
+}
+
+
+/**
+ * Retrieves an item of user data associated with the given object.
+ *
+ * @returns Pointer to the associated user data if found, otherwise NULL.
+ * @param   pCache              The cache.
+ * @param   pObj                The object.
+ * @param   uKey                The user data key.
+ */
+PKFSUSERDATA kFsCacheObjGetUserData(PKFSCACHE pCache, PKFSOBJ pObj, KUPTR uKey)
+{
+    PKFSUSERDATA pCur;
+
+    kHlpAssert(pCache->u32Magic == KFSCACHE_MAGIC);
+    kHlpAssert(pObj->u32Magic == KFSOBJ_MAGIC);
+
+    for (pCur = pObj->pUserDataHead; pCur; pCur = pCur->pNext)
+        if (pCur->uKey == uKey)
+            return pCur;
+    return NULL;
+}
+
+
+/**
+ * Gets the full path to @a pObj, ANSI version.
+ *
+ * @returns K_TRUE on success, K_FALSE on buffer overflow (nothing stored).
+ * @param   pObj                The object to get the full path to.
+ * @param   pszPath             Where to return the path
+ * @param   cbPath              The size of the output buffer.
+ * @param   chSlash             The slash to use.
+ */
+KBOOL kFsCacheObjGetFullPathA(PKFSOBJ pObj, char *pszPath, KSIZE cbPath, char chSlash)
+{
+    KSIZE off = pObj->cchParent;
+    kHlpAssert(pObj->u32Magic == KFSOBJ_MAGIC);
+    if (off > 0)
+    {
+        KSIZE offEnd = off + pObj->cchName;
+        if (offEnd < cbPath)
+        {
+            PKFSDIR pAncestor;
+
+            pszPath[off + pObj->cchName] = '\0';
+            memcpy(&pszPath[off], pObj->pszName, pObj->cchName);
+
+            for (pAncestor = pObj->pParent; off > 0; pAncestor = pAncestor->Obj.pParent)
+            {
+                kHlpAssert(off > 1);
+                kHlpAssert(pAncestor != NULL);
+                kHlpAssert(pAncestor->Obj.cchName > 0);
+                pszPath[--off] = chSlash;
+                off -= pAncestor->Obj.cchName;
+                kHlpAssert(pAncestor->Obj.cchParent == off);
+                memcpy(&pszPath[off], pAncestor->Obj.pszName, pAncestor->Obj.cchName);
+            }
+            return K_TRUE;
+        }
+    }
+    else
+    {
+        KBOOL const fDriveLetter = pObj->cchName == 2 && pObj->pszName[2] == ':';
+        off = pObj->cchName;
+        if (off + fDriveLetter < cbPath)
+        {
+            memcpy(pszPath, pObj->pszName, off);
+            if (fDriveLetter)
+                pszPath[off++] = chSlash;
+            pszPath[off] = '\0';
+            return K_TRUE;
+        }
+    }
+
+    return K_FALSE;
+}
+
+
+/**
+ * Gets the full path to @a pObj, UTF-16 version.
+ *
+ * @returns K_TRUE on success, K_FALSE on buffer overflow (nothing stored).
+ * @param   pObj                The object to get the full path to.
+ * @param   pszPath             Where to return the path
+ * @param   cbPath              The size of the output buffer.
+ * @param   wcSlash             The slash to use.
+ */
+KBOOL kFsCacheObjGetFullPathW(PKFSOBJ pObj, wchar_t *pwszPath, KSIZE cwcPath, wchar_t wcSlash)
+{
+    KSIZE off = pObj->cwcParent;
+    kHlpAssert(pObj->u32Magic == KFSOBJ_MAGIC);
+    if (off > 0)
+    {
+        KSIZE offEnd = off + pObj->cwcName;
+        if (offEnd < cwcPath)
+        {
+            PKFSDIR pAncestor;
+
+            pwszPath[off + pObj->cwcName] = '\0';
+            memcpy(&pwszPath[off], pObj->pwszName, pObj->cwcName * sizeof(wchar_t));
+
+            for (pAncestor = pObj->pParent; off > 0; pAncestor = pAncestor->Obj.pParent)
+            {
+                kHlpAssert(off > 1);
+                kHlpAssert(pAncestor != NULL);
+                kHlpAssert(pAncestor->Obj.cwcName > 0);
+                pwszPath[--off] = wcSlash;
+                off -= pAncestor->Obj.cwcName;
+                kHlpAssert(pAncestor->Obj.cwcParent == off);
+                memcpy(&pwszPath[off], pAncestor->Obj.pwszName, pAncestor->Obj.cwcName * sizeof(wchar_t));
+            }
+            return K_TRUE;
+        }
+    }
+    else
+    {
+        KBOOL const fDriveLetter = pObj->cchName == 2 && pObj->pszName[2] == ':';
+        off = pObj->cwcName;
+        if (off + fDriveLetter < cwcPath)
+        {
+            memcpy(pwszPath, pObj->pwszName, off * sizeof(wchar_t));
+            if (fDriveLetter)
+                pwszPath[off++] = wcSlash;
+            pwszPath[off] = '\0';
+            return K_TRUE;
+        }
+    }
+
+    return K_FALSE;
+}
+
+
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+
+/**
+ * Gets the full short path to @a pObj, ANSI version.
+ *
+ * @returns K_TRUE on success, K_FALSE on buffer overflow (nothing stored).
+ * @param   pObj                The object to get the full path to.
+ * @param   pszPath             Where to return the path
+ * @param   cbPath              The size of the output buffer.
+ * @param   chSlash             The slash to use.
+ */
+KBOOL kFsCacheObjGetFullShortPathA(PKFSOBJ pObj, char *pszPath, KSIZE cbPath, char chSlash)
+{
+    KSIZE off = pObj->cchShortParent;
+    kHlpAssert(pObj->u32Magic == KFSOBJ_MAGIC);
+    if (off > 0)
+    {
+        KSIZE offEnd = off + pObj->cchShortName;
+        if (offEnd < cbPath)
+        {
+            PKFSDIR pAncestor;
+
+            pszPath[off + pObj->cchShortName] = '\0';
+            memcpy(&pszPath[off], pObj->pszShortName, pObj->cchShortName);
+
+            for (pAncestor = pObj->pParent; off > 0; pAncestor = pAncestor->Obj.pParent)
+            {
+                kHlpAssert(off > 1);
+                kHlpAssert(pAncestor != NULL);
+                kHlpAssert(pAncestor->Obj.cchShortName > 0);
+                pszPath[--off] = chSlash;
+                off -= pAncestor->Obj.cchShortName;
+                kHlpAssert(pAncestor->Obj.cchShortParent == off);
+                memcpy(&pszPath[off], pAncestor->Obj.pszShortName, pAncestor->Obj.cchShortName);
+            }
+            return K_TRUE;
+        }
+    }
+    else
+    {
+        KBOOL const fDriveLetter = pObj->cchShortName == 2 && pObj->pszShortName[2] == ':';
+        off = pObj->cchShortName;
+        if (off + fDriveLetter < cbPath)
+        {
+            memcpy(pszPath, pObj->pszShortName, off);
+            if (fDriveLetter)
+                pszPath[off++] = chSlash;
+            pszPath[off] = '\0';
+            return K_TRUE;
+        }
+    }
+
+    return K_FALSE;
+}
+
+
+/**
+ * Gets the full short path to @a pObj, UTF-16 version.
+ *
+ * @returns K_TRUE on success, K_FALSE on buffer overflow (nothing stored).
+ * @param   pObj                The object to get the full path to.
+ * @param   pszPath             Where to return the path
+ * @param   cbPath              The size of the output buffer.
+ * @param   wcSlash             The slash to use.
+ */
+KBOOL kFsCacheObjGetFullShortPathW(PKFSOBJ pObj, wchar_t *pwszPath, KSIZE cwcPath, wchar_t wcSlash)
+{
+    KSIZE off = pObj->cwcShortParent;
+    kHlpAssert(pObj->u32Magic == KFSOBJ_MAGIC);
+    if (off > 0)
+    {
+        KSIZE offEnd = off + pObj->cwcShortName;
+        if (offEnd < cwcPath)
+        {
+            PKFSDIR pAncestor;
+
+            pwszPath[off + pObj->cwcShortName] = '\0';
+            memcpy(&pwszPath[off], pObj->pwszShortName, pObj->cwcShortName * sizeof(wchar_t));
+
+            for (pAncestor = pObj->pParent; off > 0; pAncestor = pAncestor->Obj.pParent)
+            {
+                kHlpAssert(off > 1);
+                kHlpAssert(pAncestor != NULL);
+                kHlpAssert(pAncestor->Obj.cwcShortName > 0);
+                pwszPath[--off] = wcSlash;
+                off -= pAncestor->Obj.cwcShortName;
+                kHlpAssert(pAncestor->Obj.cwcShortParent == off);
+                memcpy(&pwszPath[off], pAncestor->Obj.pwszShortName, pAncestor->Obj.cwcShortName * sizeof(wchar_t));
+            }
+            return K_TRUE;
+        }
+    }
+    else
+    {
+        KBOOL const fDriveLetter = pObj->cchShortName == 2 && pObj->pszShortName[2] == ':';
+        off = pObj->cwcShortName;
+        if (off + fDriveLetter < cwcPath)
+        {
+            memcpy(pwszPath, pObj->pwszShortName, off * sizeof(wchar_t));
+            if (fDriveLetter)
+                pwszPath[off++] = wcSlash;
+            pwszPath[off] = '\0';
+            return K_TRUE;
+        }
+    }
+
+    return K_FALSE;
+}
+
+#endif /* KFSCACHE_CFG_SHORT_NAMES */
+
+
+
+/**
+ * Read the specified bits from the files into the given buffer, simple version.
+ *
+ * @returns K_TRUE on success (all requested bytes read),
+ *          K_FALSE on any kind of failure.
+ *
+ * @param   pCache              The cache.
+ * @param   pFileObj            The file object.
+ * @param   offStart            Where to start reading.
+ * @param   pvBuf               Where to store what we read.
+ * @param   cbToRead            How much to read (exact).
+ */
+KBOOL kFsCacheFileSimpleOpenReadClose(PKFSCACHE pCache, PKFSOBJ pFileObj, KU64 offStart, void *pvBuf, KSIZE cbToRead)
+{
+    /*
+     * Open the file relative to the parent directory.
+     */
+    MY_NTSTATUS             rcNt;
+    HANDLE                  hFile;
+    MY_IO_STATUS_BLOCK      Ios;
+    MY_OBJECT_ATTRIBUTES    ObjAttr;
+    MY_UNICODE_STRING       UniStr;
+
+    kHlpAssertReturn(pFileObj->bObjType == KFSOBJ_TYPE_FILE, K_FALSE);
+    kHlpAssert(pFileObj->pParent);
+    kHlpAssertReturn(pFileObj->pParent->hDir != INVALID_HANDLE_VALUE, K_FALSE);
+    kHlpAssertReturn(offStart == 0, K_FALSE); /** @todo when needed */
+
+    Ios.Information = -1;
+    Ios.u.Status    = -1;
+
+    UniStr.Buffer        = (wchar_t *)pFileObj->pwszName;
+    UniStr.Length        = (USHORT)(pFileObj->cwcName * sizeof(wchar_t));
+    UniStr.MaximumLength = UniStr.Length + sizeof(wchar_t);
+
+    MyInitializeObjectAttributes(&ObjAttr, &UniStr, OBJ_CASE_INSENSITIVE, pFileObj->pParent->hDir, NULL /*pSecAttr*/);
+
+    rcNt = g_pfnNtCreateFile(&hFile,
+                             GENERIC_READ | SYNCHRONIZE,
+                             &ObjAttr,
+                             &Ios,
+                             NULL, /*cbFileInitialAlloc */
+                             FILE_ATTRIBUTE_NORMAL,
+                             FILE_SHARE_READ,
+                             FILE_OPEN,
+                             FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+                             NULL, /*pEaBuffer*/
+                             0);   /*cbEaBuffer*/
+    if (MY_NT_SUCCESS(rcNt))
+    {
+        LARGE_INTEGER offFile;
+        offFile.QuadPart = offStart;
+
+        Ios.Information = -1;
+        Ios.u.Status    = -1;
+        rcNt = g_pfnNtReadFile(hFile, NULL /*hEvent*/, NULL /*pfnApcComplete*/, NULL /*pvApcCtx*/, &Ios,
+                               pvBuf, (KU32)cbToRead, !offStart ? &offFile : NULL, NULL /*puKey*/);
+        if (MY_NT_SUCCESS(rcNt))
+            rcNt = Ios.u.Status;
+        if (MY_NT_SUCCESS(rcNt))
+        {
+            if (Ios.Information == cbToRead)
+            {
+                g_pfnNtClose(hFile);
+                return K_TRUE;
+            }
+            KFSCACHE_LOG(("Error reading %#x bytes from '%ls': Information=%p\n", pFileObj->pwszName, Ios.Information));
+        }
+        else
+            KFSCACHE_LOG(("Error reading %#x bytes from '%ls': %#x\n", pFileObj->pwszName, rcNt));
+        g_pfnNtClose(hFile);
+    }
+    else
+        KFSCACHE_LOG(("Error opening '%ls' for caching: %#x\n", pFileObj->pwszName, rcNt));
+    return K_FALSE;
+}
+
+
+/**
+ * Invalidate all cache entries of missing files.
+ *
+ * @param   pCache      The cache.
+ */
+void kFsCacheInvalidateMissing(PKFSCACHE pCache)
+{
+    kHlpAssert(pCache->u32Magic == KFSOBJ_MAGIC);
+    pCache->auGenerationsMissing[0]++;
+    kHlpAssert(pCache->uGenerationMissing < KU32_MAX);
+    KFSCACHE_LOG(("Invalidate missing %#x\n", pCache->auGenerationsMissing[0]));
+}
+
+
+/**
+ * Invalidate all cache entries (regular, custom & missing).
+ *
+ * @param   pCache      The cache.
+ */
+void kFsCacheInvalidateAll(PKFSCACHE pCache)
+{
+    kHlpAssert(pCache->u32Magic == KFSOBJ_MAGIC);
+
+    pCache->auGenerationsMissing[0]++;
+    kHlpAssert(pCache->auGenerationsMissing[0] < KU32_MAX);
+    pCache->auGenerationsMissing[1]++;
+    kHlpAssert(pCache->auGenerationsMissing[1] < KU32_MAX);
+
+    pCache->auGenerations[0]++;
+    kHlpAssert(pCache->auGenerations[0] < KU32_MAX);
+    pCache->auGenerations[1]++;
+    kHlpAssert(pCache->auGenerations[1] < KU32_MAX);
+
+    KFSCACHE_LOG(("Invalidate all - default: %#x/%#x,  custom: %#x/%#x\n",
+                  pCache->auGenerationsMissing[0], pCache->auGenerations[0],
+                  pCache->auGenerationsMissing[1], pCache->auGenerations[1]));
+}
+
+
+/**
+ * Invalidate all cache entries with custom generation handling set.
+ *
+ * @see     kFsCacheSetupCustomRevisionForTree, KFSOBJ_F_USE_CUSTOM_GEN
+ * @param   pCache      The cache.
+ */
+void kFsCacheInvalidateCustomMissing(PKFSCACHE pCache)
+{
+    kHlpAssert(pCache->u32Magic == KFSOBJ_MAGIC);
+    pCache->auGenerationsMissing[1]++;
+    kHlpAssert(pCache->auGenerationsMissing[1] < KU32_MAX);
+    KFSCACHE_LOG(("Invalidate missing custom %#x\n", pCache->auGenerationsMissing[1]));
+}
+
+
+/**
+ * Invalidate all cache entries with custom generation handling set, both
+ * missing and regular present entries.
+ *
+ * @see     kFsCacheSetupCustomRevisionForTree, KFSOBJ_F_USE_CUSTOM_GEN
+ * @param   pCache      The cache.
+ */
+void kFsCacheInvalidateCustomBoth(PKFSCACHE pCache)
+{
+    kHlpAssert(pCache->u32Magic == KFSOBJ_MAGIC);
+    pCache->auGenerations[1]++;
+    kHlpAssert(pCache->auGenerations[1] < KU32_MAX);
+    pCache->auGenerationsMissing[1]++;
+    kHlpAssert(pCache->auGenerationsMissing[1] < KU32_MAX);
+    KFSCACHE_LOG(("Invalidate both custom %#x/%#x\n", pCache->auGenerationsMissing[1], pCache->auGenerations[1]));
+}
+
+
+
+/**
+ * Applies the given flags to all the objects in a tree.
+ *
+ * @param   pRoot               Where to start applying the flag changes.
+ * @param   fAndMask            The AND mask.
+ * @param   fOrMask             The OR mask.
+ */
+static void kFsCacheApplyFlagsToTree(PKFSDIR pRoot, KU32 fAndMask, KU32 fOrMask)
+{
+    PKFSOBJ    *ppCur = ((PKFSDIR)pRoot)->papChildren;
+    KU32        cLeft = ((PKFSDIR)pRoot)->cChildren;
+    while (cLeft-- > 0)
+    {
+        PKFSOBJ pCur = *ppCur++;
+        if (pCur->bObjType != KFSOBJ_TYPE_DIR)
+            pCur->fFlags = (fAndMask & pCur->fFlags) | fOrMask;
+        else
+            kFsCacheApplyFlagsToTree((PKFSDIR)pCur, fAndMask, fOrMask);
+    }
+
+    pRoot->Obj.fFlags = (fAndMask & pRoot->Obj.fFlags) | fOrMask;
+}
+
+
+/**
+ * Sets up using custom revisioning for the specified directory tree or file.
+ *
+ * There are some restrictions of the current implementation:
+ *      - If the root of the sub-tree is ever deleted from the cache (i.e.
+ *        deleted in real life and reflected in the cache), the setting is lost.
+ *      - It is not automatically applied to the lookup paths caches.
+ *
+ * @returns K_TRUE on success, K_FALSE on failure.
+ * @param   pCache              The cache.
+ * @param   pRoot               The root of the subtree.  A non-directory is
+ *                              fine, like a missing node.
+ */
+KBOOL kFsCacheSetupCustomRevisionForTree(PKFSCACHE pCache, PKFSOBJ pRoot)
+{
+    if (pRoot)
+    {
+        if (pRoot->bObjType == KFSOBJ_TYPE_DIR)
+            kFsCacheApplyFlagsToTree((PKFSDIR)pRoot, KU32_MAX, KFSOBJ_F_USE_CUSTOM_GEN);
+        else
+            pRoot->fFlags |= KFSOBJ_F_USE_CUSTOM_GEN;
+        return K_TRUE;
+    }
+    return K_FALSE;
+}
+
+
+PKFSCACHE kFsCacheCreate(KU32 fFlags)
+{
+    PKFSCACHE pCache;
+    birdResolveImports();
+
+    pCache = (PKFSCACHE)kHlpAllocZ(sizeof(*pCache));
+    if (pCache)
+    {
+        /* Dummy root dir entry. */
+        pCache->RootDir.Obj.u32Magic        = KFSOBJ_MAGIC;
+        pCache->RootDir.Obj.cRefs           = 1;
+        pCache->RootDir.Obj.uCacheGen       = KFSOBJ_CACHE_GEN_IGNORE;
+        pCache->RootDir.Obj.bObjType        = KFSOBJ_TYPE_DIR;
+        pCache->RootDir.Obj.fHaveStats      = K_FALSE;
+        pCache->RootDir.Obj.pParent         = NULL;
+        pCache->RootDir.Obj.pszName         = "";
+        pCache->RootDir.Obj.cchName         = 0;
+        pCache->RootDir.Obj.cchParent       = 0;
+#ifdef KFSCACHE_CFG_UTF16
+        pCache->RootDir.Obj.cwcName         = 0;
+        pCache->RootDir.Obj.cwcParent       = 0;
+        pCache->RootDir.Obj.pwszName        = L"";
+#endif
+
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+        pCache->RootDir.Obj.pszShortName    = NULL;
+        pCache->RootDir.Obj.cchShortName    = 0;
+        pCache->RootDir.Obj.cchShortParent  = 0;
+# ifdef KFSCACHE_CFG_UTF16
+        pCache->RootDir.Obj.cwcShortName;
+        pCache->RootDir.Obj.cwcShortParent;
+        pCache->RootDir.Obj.pwszShortName;
+# endif
+#endif
+        pCache->RootDir.cChildren           = 0;
+        pCache->RootDir.cChildrenAllocated  = 0;
+        pCache->RootDir.papChildren         = NULL;
+        pCache->RootDir.hDir                = INVALID_HANDLE_VALUE;
+        pCache->RootDir.cHashTab            = 251;
+        pCache->RootDir.paHashTab           = (PKFSOBJHASH)kHlpAllocZ(  pCache->RootDir.cHashTab
+                                                                      * sizeof(pCache->RootDir.paHashTab[0]));
+        if (pCache->RootDir.paHashTab)
+        {
+            /* The cache itself. */
+            pCache->u32Magic        = KFSCACHE_MAGIC;
+            pCache->fFlags          = fFlags;
+            pCache->auGenerations[0]        = KU32_MAX / 4;
+            pCache->auGenerations[1]        = KU32_MAX / 32;
+            pCache->auGenerationsMissing[0] = KU32_MAX / 256;
+            pCache->auGenerationsMissing[1] = 1;
+            pCache->cObjects        = 1;
+            pCache->cbObjects       = sizeof(pCache->RootDir) + pCache->RootDir.cHashTab * sizeof(pCache->RootDir.paHashTab[0]);
+            pCache->cPathHashHits   = 0;
+            pCache->cWalkHits       = 0;
+            pCache->cAnsiPaths      = 0;
+            pCache->cAnsiPathCollisions = 0;
+            pCache->cbAnsiPaths     = 0;
+#ifdef KFSCACHE_CFG_UTF16
+            pCache->cUtf16Paths     = 0;
+            pCache->cUtf16PathCollisions = 0;
+            pCache->cbUtf16Paths    = 0;
+#endif
+            return pCache;
+        }
+
+        kHlpFree(pCache);
+    }
+    return NULL;
+}
+
diff --git a/src/lib/nt/kFsCache.h b/src/lib/nt/kFsCache.h
new file mode 100644
index 0000000..2f306d7
--- /dev/null
+++ b/src/lib/nt/kFsCache.h
@@ -0,0 +1,488 @@
+/* $Id: kFsCache.h 2868 2016-09-04 01:28:12Z bird $ */
+/** @file
+ * kFsCache.c - NT directory content cache.
+ */
+
+/*
+ * Copyright (c) 2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
+ */
+
+#ifndef ___lib_nt_kFsCache_h___
+#define ___lib_nt_kFsCache_h___
+
+
+#include <k/kHlp.h>
+#include "ntstat.h"
+#ifndef NDEBUG
+# include <stdarg.h>
+#endif
+
+
+/** @def KFSCACHE_CFG_UTF16
+ * Whether to compile in the UTF-16 names support. */
+#define KFSCACHE_CFG_UTF16                  1
+/** @def KFSCACHE_CFG_SHORT_NAMES
+ * Whether to compile in the short name support. */
+#define KFSCACHE_CFG_SHORT_NAMES            1
+/** @def KFSCACHE_CFG_PATH_HASH_TAB_SIZE
+ * Size of the path hash table. */
+#define KFSCACHE_CFG_PATH_HASH_TAB_SIZE     16381
+/** The max length paths we consider. */
+#define KFSCACHE_CFG_MAX_PATH               1024
+/** The max ANSI name length. */
+#define KFSCACHE_CFG_MAX_ANSI_NAME          (256*3 + 16)
+/** The max UTF-16 name length. */
+#define KFSCACHE_CFG_MAX_UTF16_NAME         (256*2 + 16)
+
+
+
+/** Special KFSOBJ::uCacheGen number indicating that it does not apply. */
+#define KFSOBJ_CACHE_GEN_IGNORE             KU32_MAX
+
+
+/** @name KFSOBJ_TYPE_XXX - KFSOBJ::bObjType
+ * @{  */
+/** Directory, type KFSDIR. */
+#define KFSOBJ_TYPE_DIR         KU8_C(0x01)
+/** Regular file - type KFSOBJ. */
+#define KFSOBJ_TYPE_FILE        KU8_C(0x02)
+/** Other file - type KFSOBJ. */
+#define KFSOBJ_TYPE_OTHER       KU8_C(0x03)
+/** Caching of a negative result - type KFSOBJ.
+ * @remarks We will allocate enough space for the largest cache node, so this
+ *          can metamorph into any other object should it actually turn up.  */
+#define KFSOBJ_TYPE_MISSING     KU8_C(0x04)
+///** Invalidated entry flag. */
+//#define KFSOBJ_TYPE_F_INVALID   KU8_C(0x20)
+/** @} */
+
+/** @name KFSOBJ_F_XXX - KFSOBJ::fFlags
+ * @{ */
+ /** Use custom generation.
+  * @remarks This is given the value 1, as we use it as an index into
+  *          KFSCACHE::auGenerations, 0 being the default. */
+#define KFSOBJ_F_USE_CUSTOM_GEN         KU32_C(0x00000001)
+
+/** Whether the file system update the modified timestamp of directories
+ * when something is removed from it or added to it.
+ * @remarks They say NTFS is the only windows filesystem doing this.  */
+#define KFSOBJ_F_WORKING_DIR_MTIME      KU32_C(0x00000002)
+/** NTFS file system volume. */
+#define KFSOBJ_F_NTFS                   KU32_C(0x80000000)
+/** Flags that are automatically inherited. */
+#define KFSOBJ_F_INHERITED_MASK         KU32_C(0xffffffff)
+/** @} */
+
+
+#define IS_ALPHA(ch) ( ((ch) >= 'A' && (ch) <= 'Z') || ((ch) >= 'a' && (ch) <= 'z') )
+#define IS_SLASH(ch) ((ch) == '\\' || (ch) == '/')
+
+
+
+
+/** Pointer to a cache. */
+typedef struct KFSCACHE *PKFSCACHE;
+/** Pointer to a core object.  */
+typedef struct KFSOBJ *PKFSOBJ;
+/** Pointer to a directory object.  */
+typedef struct KFSDIR *PKFSDIR;
+/** Pointer to a directory hash table entry. */
+typedef struct KFSOBJHASH *PKFSOBJHASH;
+
+
+/**
+ * Directory hash table entry.
+ *
+ * There can be two of these per directory entry when the short name differs
+ * from the long name.
+ */
+typedef struct KFSOBJHASH
+{
+    /** Pointer to the next entry with the same hash. */
+    PKFSOBJHASH         pNext;
+    /** Pointer to the object. */
+    PKFSOBJ             pObj;
+} KFSOBJHASH;
+
+
+/** Pointer to a user data item. */
+typedef struct KFSUSERDATA *PKFSUSERDATA;
+/**
+ * User data item associated with a cache node.
+ */
+typedef struct KFSUSERDATA
+{
+    /** Pointer to the next piece of user data. */
+    PKFSUSERDATA    pNext;
+    /** The key identifying this user. */
+    KUPTR           uKey;
+    /** The destructor. */
+    void (*pfnDestructor)(PKFSCACHE pCache, PKFSOBJ pObj, PKFSUSERDATA pData);
+} KFSUSERDATA;
+
+
+/**
+ * Base cache node.
+ */
+typedef struct KFSOBJ
+{
+    /** Magic value (KFSOBJ_MAGIC). */
+    KU32                u32Magic;
+    /** Number of references. */
+    KU32 volatile       cRefs;
+    /** The cache generation, see KFSOBJ_CACHE_GEN_IGNORE. */
+    KU32                uCacheGen;
+    /** The object type, KFSOBJ_TYPE_XXX.   */
+    KU8                 bObjType;
+    /** Set if the Stats member is valid, clear if not. */
+    KBOOL               fHaveStats;
+    /** Unused flags. */
+    KBOOL               abUnused[2];
+    /** Flags, KFSOBJ_F_XXX. */
+    KU32                fFlags;
+
+    /** Pointer to the parent (directory).
+     * This is only NULL for a root. */
+    PKFSDIR             pParent;
+
+    /** The directory name.  (Allocated after the structure.) */
+    const char         *pszName;
+    /** The length of pszName. */
+    KU16                cchName;
+    /** The length of the parent path (up to where pszName starts).
+     * @note This is valuable when constructing an absolute path to this node by
+     *       means of the parent pointer (no need for recursion). */
+    KU16                cchParent;
+#ifdef KFSCACHE_CFG_UTF16
+    /** The length of pwszName (in wchar_t's). */
+    KU16                cwcName;
+    /** The length of the parent UTF-16 path (in wchar_t's).
+     * @note This is valuable when constructing an absolute path to this node by
+     *       means of the parent pointer (no need for recursion). */
+    KU16                cwcParent;
+    /** The UTF-16 object name.  (Allocated after the structure.) */
+    const wchar_t      *pwszName;
+#endif
+
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+    /** The short object name.  (Allocated after the structure, could be same
+     *  as pszName.) */
+    const char         *pszShortName;
+    /** The length of pszShortName. */
+    KU16                cchShortName;
+    /** The length of the short parent path (up to where pszShortName starts). */
+    KU16                cchShortParent;
+# ifdef KFSCACHE_CFG_UTF16
+    /** The length of pwszShortName (in wchar_t's). */
+    KU16                cwcShortName;
+    /** The length of the short parent UTF-16 path (in wchar_t's). */
+    KU16                cwcShortParent;
+    /** The UTF-16 short object name.  (Allocated after the structure, possibly
+     *  same as pwszName.) */
+    const wchar_t      *pwszShortName;
+# endif
+#endif
+
+    /** Pointer to the first user data item */
+    PKFSUSERDATA        pUserDataHead;
+
+    /** Stats - only valid when fHaveStats is set. */
+    BirdStat_T          Stats;
+} KFSOBJ;
+
+/** The magic for a KFSOBJ structure (Thelonious Sphere Monk). */
+#define KFSOBJ_MAGIC                KU32_C(0x19171010)
+
+
+/**
+ * Directory node in the cache.
+ */
+typedef struct KFSDIR
+{
+    /** The core object information. */
+    KFSOBJ             Obj;
+
+    /** Child objects. */
+    PKFSOBJ            *papChildren;
+    /** The number of child objects. */
+    KU32                cChildren;
+    /** The allocated size of papChildren. */
+    KU32                cChildrenAllocated;
+
+    /** Pointer to the hash table.
+     * @todo this isn't quite there yet, structure wise. sigh.  */
+    PKFSOBJHASH         paHashTab;
+    /** The size of the hash table.
+     * @remarks The hash table is optional and only used when there are a lot of
+     *          entries in the directory. */
+    KU32                cHashTab;
+
+    /** Handle to the directory (we generally keep it open). */
+#ifndef DECLARE_HANDLE
+    KUPTR               hDir;
+#else
+    HANDLE              hDir;
+#endif
+    /** The device number we queried/inherited when opening it. */
+    KU64                uDevNo;
+
+    /** The last write time sampled the last time the directory was refreshed.
+     * @remarks May differ from st_mtim because it will be updated when the
+     *          parent directory is refreshed. */
+    KI64                iLastWrite;
+
+    /** Set if populated. */
+    KBOOL               fPopulated;
+    /** Set if it needs re-populated. */
+    KBOOL               fNeedRePopulating;
+} KFSDIR;
+
+
+/**
+ * Lookup errors.
+ */
+typedef enum KFSLOOKUPERROR
+{
+    /** Lookup was a success. */
+    KFSLOOKUPERROR_SUCCESS = 0,
+    /** A path component was not found. */
+    KFSLOOKUPERROR_PATH_COMP_NOT_FOUND,
+    /** A path component is not a directory. */
+    KFSLOOKUPERROR_PATH_COMP_NOT_DIR,
+    /** The final path entry is not a directory (trailing slash). */
+    KFSLOOKUPERROR_NOT_DIR,
+    /** Not found. */
+    KFSLOOKUPERROR_NOT_FOUND,
+    /** The path is too long. */
+    KFSLOOKUPERROR_PATH_TOO_LONG,
+    /** Unsupported path type. */
+    KFSLOOKUPERROR_UNSUPPORTED,
+    /** We're out of memory. */
+    KFSLOOKUPERROR_OUT_OF_MEMORY,
+
+    /** Error opening directory. */
+    KFSLOOKUPERROR_DIR_OPEN_ERROR,
+    /** Error reading directory. */
+    KFSLOOKUPERROR_DIR_READ_ERROR,
+    /** UTF-16 to ANSI conversion error. */
+    KFSLOOKUPERROR_ANSI_CONVERSION_ERROR,
+    /** ANSI to UTF-16 conversion error. */
+    KFSLOOKUPERROR_UTF16_CONVERSION_ERROR,
+    /** Internal error. */
+    KFSLOOKUPERROR_INTERNAL_ERROR
+} KFSLOOKUPERROR;
+
+
+/** Pointer to an ANSI path hash table entry. */
+typedef struct KFSHASHA *PKFSHASHA;
+/**
+ * ANSI file system path hash table entry.
+ * The path hash table allows us to skip parsing and walking a path.
+ */
+typedef struct KFSHASHA
+{
+    /** Next entry with the same hash table slot. */
+    PKFSHASHA           pNext;
+    /** Path hash value. */
+    KU32                uHashPath;
+    /** The path length. */
+    KU16                cchPath;
+    /** Set if aboslute path.   */
+    KBOOL               fAbsolute;
+    /** Index into KFSCACHE:auGenerationsMissing when pFsObj is NULL. */
+    KU8                 idxMissingGen;
+    /** The cache generation ID. */
+    KU32                uCacheGen;
+    /** The lookup error (when pFsObj is NULL). */
+    KFSLOOKUPERROR      enmError;
+    /** The path.  (Allocated after the structure.) */
+    const char         *pszPath;
+    /** Pointer to the matching FS object.
+     * This is NULL for negative path entries? */
+    PKFSOBJ             pFsObj;
+} KFSHASHA;
+
+
+#ifdef KFSCACHE_CFG_UTF16
+/** Pointer to an UTF-16 path hash table entry. */
+typedef struct KFSHASHW *PKFSHASHW;
+/**
+ * UTF-16 file system path hash table entry. The path hash table allows us
+ * to skip parsing and walking a path.
+ */
+typedef struct KFSHASHW
+{
+    /** Next entry with the same hash table slot. */
+    PKFSHASHW           pNext;
+    /** Path hash value. */
+    KU32                uHashPath;
+    /** The path length (in wchar_t units). */
+    KU16                cwcPath;
+    /** Set if aboslute path.   */
+    KBOOL               fAbsolute;
+    /** Index into KFSCACHE:auGenerationsMissing when pFsObj is NULL. */
+    KU8                 idxMissingGen;
+    /** The cache generation ID. */
+    KU32                uCacheGen;
+    /** The lookup error (when pFsObj is NULL). */
+    KFSLOOKUPERROR      enmError;
+    /** The path.  (Allocated after the structure.) */
+    const wchar_t      *pwszPath;
+    /** Pointer to the matching FS object.
+     * This is NULL for negative path entries? */
+    PKFSOBJ             pFsObj;
+} KFSHASHW;
+#endif
+
+
+/** @name KFSCACHE_F_XXX
+ * @{ */
+/** Whether to cache missing directory entries (KFSOBJ_TYPE_MISSING). */
+#define KFSCACHE_F_MISSING_OBJECTS  KU32_C(0x00000001)
+/** Whether to cache missing paths. */
+#define KFSCACHE_F_MISSING_PATHS    KU32_C(0x00000002)
+/** @} */
+
+
+/**
+ * Directory cache instance.
+ */
+typedef struct KFSCACHE
+{
+    /** Magic value (KFSCACHE_MAGIC). */
+    KU32                u32Magic;
+    /** Cache flags. */
+    KU32                fFlags;
+
+    /** The default and custom cache generations for stuff that exists, indexed by
+     *  KFSOBJ_F_USE_CUSTOM_GEN.
+     *
+     * The custom generation can be used to invalidate parts of the file system that
+     * are known to be volatile without triggering refreshing of the more static
+     * parts.  Like the 'out' directory in a kBuild setup or a 'TEMP' directory are
+     * expected to change and you need to invalidate the caching of these frequently
+     * to stay on top of things.  Whereas the sources, headers, compilers, sdk,
+     * ddks, windows directory and such generally doesn't change all that often.
+     */
+    KU32                auGenerations[2];
+    /** The current cache generation for missing objects, negative results, ++.
+     * This comes with a custom variant too.  Indexed by KFSOBJ_F_USE_CUSTOM_GEN. */
+    KU32                auGenerationsMissing[2];
+
+    /** Number of cache objects. */
+    KSIZE               cObjects;
+    /** Memory occupied by the cache object structures. */
+    KSIZE               cbObjects;
+    /** Number of lookups. */
+    KSIZE               cLookups;
+    /** Number of hits in the path hash tables. */
+    KSIZE               cPathHashHits;
+    /** Number of hits walking the file system hierarchy. */
+    KSIZE               cWalkHits;
+
+    /** The root directory. */
+    KFSDIR              RootDir;
+
+    /** File system hash table for ANSI filename strings. */
+    PKFSHASHA           apAnsiPaths[KFSCACHE_CFG_PATH_HASH_TAB_SIZE];
+    /** Number of paths in the apAnsiPaths hash table. */
+    KSIZE               cAnsiPaths;
+    /** Number of collisions in the apAnsiPaths hash table. */
+    KSIZE               cAnsiPathCollisions;
+    /** Amount of memory used by the path entries. */
+    KSIZE               cbAnsiPaths;
+
+#ifdef KFSCACHE_CFG_UTF16
+    /** Number of paths in the apUtf16Paths hash table. */
+    KSIZE               cUtf16Paths;
+    /** Number of collisions in the apUtf16Paths hash table. */
+    KSIZE               cUtf16PathCollisions;
+    /** Amount of memory used by the UTF-16 path entries. */
+    KSIZE               cbUtf16Paths;
+    /** File system hash table for UTF-16 filename strings. */
+    PKFSHASHW           apUtf16Paths[KFSCACHE_CFG_PATH_HASH_TAB_SIZE];
+#endif
+} KFSCACHE;
+
+/** Magic value for KFSCACHE::u32Magic (Jon Batiste).  */
+#define KFSCACHE_MAGIC              KU32_C(0x19861111)
+
+
+/** @def KW_LOG
+ * Generic logging.
+ * @param a     Argument list for kFsCacheDbgPrintf  */
+#ifdef NDEBUG
+# define KFSCACHE_LOG(a) do { } while (0)
+#else
+# define KFSCACHE_LOG(a) kFsCacheDbgPrintf a
+void        kFsCacheDbgPrintfV(const char *pszFormat, va_list va);
+void        kFsCacheDbgPrintf(const char *pszFormat, ...);
+#endif
+
+
+KBOOL       kFsCacheDirEnsurePopuplated(PKFSCACHE pCache, PKFSDIR pDir, KFSLOOKUPERROR *penmError);
+KBOOL       kFsCacheDirAddChild(PKFSCACHE pCache, PKFSDIR pParent, PKFSOBJ pChild, KFSLOOKUPERROR *penmError);
+PKFSOBJ     kFsCacheCreateObject(PKFSCACHE pCache, PKFSDIR pParent,
+                                 char const *pszName, KU16 cchName, wchar_t const *pwszName, KU16 cwcName,
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                                 char const *pszShortName, KU16 cchShortName, wchar_t const *pwszShortName, KU16 cwcShortName,
+#endif
+                                 KU8 bObjType, KFSLOOKUPERROR *penmError);
+PKFSOBJ     kFsCacheCreateObjectW(PKFSCACHE pCache, PKFSDIR pParent, wchar_t const *pwszName, KU32 cwcName,
+#ifdef KFSCACHE_CFG_SHORT_NAMES
+                                  wchar_t const *pwszShortName, KU32 cwcShortName,
+#endif
+                                  KU8 bObjType, KFSLOOKUPERROR *penmError);
+PKFSOBJ     kFsCacheLookupA(PKFSCACHE pCache, const char *pszPath, KFSLOOKUPERROR *penmError);
+PKFSOBJ     kFsCacheLookupW(PKFSCACHE pCache, const wchar_t *pwszPath, KFSLOOKUPERROR *penmError);
+PKFSOBJ     kFsCacheLookupRelativeToDirA(PKFSCACHE pCache, PKFSDIR pParent, const char *pszPath, KU32 cchPath,
+                                         KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor);
+PKFSOBJ     kFsCacheLookupRelativeToDirW(PKFSCACHE pCache, PKFSDIR pParent, const wchar_t *pwszPath, KU32 cwcPath,
+                                         KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor);
+PKFSOBJ     kFsCacheLookupWithLengthA(PKFSCACHE pCache, const char *pchPath, KSIZE cchPath, KFSLOOKUPERROR *penmError);
+PKFSOBJ     kFsCacheLookupWithLengthW(PKFSCACHE pCache, const wchar_t *pwcPath, KSIZE cwcPath, KFSLOOKUPERROR *penmError);
+PKFSOBJ     kFsCacheLookupNoMissingA(PKFSCACHE pCache, const char *pszPath, KFSLOOKUPERROR *penmError);
+PKFSOBJ     kFsCacheLookupNoMissingW(PKFSCACHE pCache, const wchar_t *pwszPath, KFSLOOKUPERROR *penmError);
+
+
+KU32        kFsCacheObjRelease(PKFSCACHE pCache, PKFSOBJ pObj);
+KU32        kFsCacheObjRetain(PKFSOBJ pObj);
+PKFSUSERDATA kFsCacheObjAddUserData(PKFSCACHE pCache, PKFSOBJ pObj, KUPTR uKey, KSIZE cbUserData);
+PKFSUSERDATA kFsCacheObjGetUserData(PKFSCACHE pCache, PKFSOBJ pObj, KUPTR uKey);
+KBOOL       kFsCacheObjGetFullPathA(PKFSOBJ pObj, char *pszPath, KSIZE cbPath, char chSlash);
+KBOOL       kFsCacheObjGetFullPathW(PKFSOBJ pObj, wchar_t *pwszPath, KSIZE cwcPath, wchar_t wcSlash);
+KBOOL       kFsCacheObjGetFullShortPathA(PKFSOBJ pObj, char *pszPath, KSIZE cbPath, char chSlash);
+KBOOL       kFsCacheObjGetFullShortPathW(PKFSOBJ pObj, wchar_t *pwszPath, KSIZE cwcPath, wchar_t wcSlash);
+
+KBOOL       kFsCacheFileSimpleOpenReadClose(PKFSCACHE pCache, PKFSOBJ pFileObj, KU64 offStart, void *pvBuf, KSIZE cbToRead);
+
+PKFSCACHE   kFsCacheCreate(KU32 fFlags);
+void        kFsCacheDestroy(PKFSCACHE);
+void        kFsCacheInvalidateMissing(PKFSCACHE pCache);
+void        kFsCacheInvalidateAll(PKFSCACHE pCache);
+void        kFsCacheInvalidateCustomMissing(PKFSCACHE pCache);
+void        kFsCacheInvalidateCustomBoth(PKFSCACHE pCache);
+KBOOL       kFsCacheSetupCustomRevisionForTree(PKFSCACHE pCache, PKFSOBJ pRoot);
+
+#endif
diff --git a/src/lib/nt/nthlp.h b/src/lib/nt/nthlp.h
index 47914f9..467daaf 100644
--- a/src/lib/nt/nthlp.h
+++ b/src/lib/nt/nthlp.h
@@ -1,4 +1,4 @@
-/* $Id: nthlp.h 2713 2013-11-21 21:11:00Z bird $ */
+/* $Id: nthlp.h 2862 2016-09-02 02:39:56Z bird $ */
 /** @file
  * MSC + NT helper functions.
  */
@@ -32,6 +32,7 @@
 #define ___nt_nthlp_h
 
 #include "ntstuff.h"
+#include "nttypes.h"
 
 
 /** Lazy resolving of the NTDLL imports. */
@@ -66,5 +67,13 @@ int         birdDosToNtPath(const char *pszPath, MY_UNICODE_STRING *pNtPath);
 void        birdFreeNtPath(MY_UNICODE_STRING *pNtPath);
 
 
+static __inline void birdNtTimeToTimeSpec(__int64 iNtTime, BirdTimeSpec_T *pTimeSpec)
+{
+    iNtTime -= BIRD_NT_EPOCH_OFFSET_UNIX_100NS;
+    pTimeSpec->tv_sec  = iNtTime / 10000000;
+    pTimeSpec->tv_nsec = (iNtTime % 10000000) * 100;
+}
+
+
 #endif
 
diff --git a/src/lib/nt/nthlpcore.c b/src/lib/nt/nthlpcore.c
index 9452da6..a6e0d7e 100644
--- a/src/lib/nt/nthlpcore.c
+++ b/src/lib/nt/nthlpcore.c
@@ -1,4 +1,4 @@
-/* $Id: nthlpcore.c 2715 2013-12-06 17:41:35Z bird $ */
+/* $Id: nthlpcore.c 2862 2016-09-02 02:39:56Z bird $ */
 /** @file
  * MSC + NT core helpers functions and globals.
  */
@@ -45,14 +45,22 @@ MY_NTSTATUS (WINAPI *g_pfnNtClose)(HANDLE);
 MY_NTSTATUS (WINAPI *g_pfnNtCreateFile)(PHANDLE, MY_ACCESS_MASK, MY_OBJECT_ATTRIBUTES *, MY_IO_STATUS_BLOCK *,
                                         PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
 MY_NTSTATUS (WINAPI *g_pfnNtDeleteFile)(MY_OBJECT_ATTRIBUTES *);
+MY_NTSTATUS (WINAPI *g_pfnNtReadFile)(HANDLE hFile, HANDLE hEvent, MY_IO_APC_ROUTINE *pfnApc, PVOID pvApcCtx,
+                                      MY_IO_STATUS_BLOCK *, PVOID pvBuf, ULONG cbToRead, PLARGE_INTEGER poffFile,
+                                      PULONG puKey);
 MY_NTSTATUS (WINAPI *g_pfnNtQueryInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *, PVOID, LONG, MY_FILE_INFORMATION_CLASS);
 MY_NTSTATUS (WINAPI *g_pfnNtQueryVolumeInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *, PVOID, LONG, MY_FS_INFORMATION_CLASS);
 MY_NTSTATUS (WINAPI *g_pfnNtQueryDirectoryFile)(HANDLE, HANDLE, MY_IO_APC_ROUTINE *, PVOID, MY_IO_STATUS_BLOCK *,
                                                 PVOID, ULONG, MY_FILE_INFORMATION_CLASS, BOOLEAN,
                                                 MY_UNICODE_STRING *, BOOLEAN);
+MY_NTSTATUS (WINAPI *g_pfnNtQueryAttributesFile)(MY_OBJECT_ATTRIBUTES *, MY_FILE_BASIC_INFORMATION *);
+MY_NTSTATUS (WINAPI *g_pfnNtQueryFullAttributesFile)(MY_OBJECT_ATTRIBUTES *, MY_FILE_NETWORK_OPEN_INFORMATION *);
 MY_NTSTATUS (WINAPI *g_pfnNtSetInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *, PVOID, LONG, MY_FILE_INFORMATION_CLASS);
 BOOLEAN     (WINAPI *g_pfnRtlDosPathNameToNtPathName_U)(PCWSTR, MY_UNICODE_STRING *, PCWSTR *, MY_RTL_RELATIVE_NAME_U *);
 MY_NTSTATUS (WINAPI *g_pfnRtlAnsiStringToUnicodeString)(MY_UNICODE_STRING *, MY_ANSI_STRING const *, BOOLEAN);
+BOOLEAN     (WINAPI *g_pfnRtlEqualUnicodeString)(MY_UNICODE_STRING const *, MY_UNICODE_STRING const *, BOOLEAN);
+BOOLEAN     (WINAPI *g_pfnRtlEqualString)(MY_ANSI_STRING const *, MY_ANSI_STRING const *, BOOLEAN);
+UCHAR       (WINAPI *g_pfnRtlUpperChar)(UCHAR uch);
 
 
 static struct
@@ -64,12 +72,18 @@ static struct
     { (FARPROC *)&g_pfnNtClose,                         "NtClose" },
     { (FARPROC *)&g_pfnNtCreateFile,                    "NtCreateFile" },
     { (FARPROC *)&g_pfnNtDeleteFile,                    "NtDeleteFile" },
+    { (FARPROC *)&g_pfnNtReadFile,                      "NtReadFile" },
     { (FARPROC *)&g_pfnNtQueryInformationFile,          "NtQueryInformationFile" },
     { (FARPROC *)&g_pfnNtQueryVolumeInformationFile,    "NtQueryVolumeInformationFile" },
     { (FARPROC *)&g_pfnNtQueryDirectoryFile,            "NtQueryDirectoryFile" },
+    { (FARPROC *)&g_pfnNtQueryAttributesFile,           "NtQueryAttributesFile" },
+    { (FARPROC *)&g_pfnNtQueryFullAttributesFile,       "NtQueryFullAttributesFile" },
     { (FARPROC *)&g_pfnNtSetInformationFile,            "NtSetInformationFile" },
     { (FARPROC *)&g_pfnRtlDosPathNameToNtPathName_U,    "RtlDosPathNameToNtPathName_U" },
     { (FARPROC *)&g_pfnRtlAnsiStringToUnicodeString,    "RtlAnsiStringToUnicodeString" },
+    { (FARPROC *)&g_pfnRtlEqualUnicodeString,           "RtlEqualUnicodeString" },
+    { (FARPROC *)&g_pfnRtlEqualString,                  "RtlEqualString" },
+    { (FARPROC *)&g_pfnRtlUpperChar,                    "RtlUpperChar" },
 };
 /** Set to 1 if we've successfully resolved the imports, otherwise 0. */
 int g_fResolvedNtImports = 0;
diff --git a/src/lib/nt/ntstat.c b/src/lib/nt/ntstat.c
index d6a4a3a..0c85692 100644
--- a/src/lib/nt/ntstat.c
+++ b/src/lib/nt/ntstat.c
@@ -1,4 +1,4 @@
-/* $Id: ntstat.c 2710 2013-11-21 14:40:10Z bird $ */
+/* $Id: ntstat.c 2880 2016-09-05 20:36:26Z bird $ */
 /** @file
  * MSC + NT stat, lstat and fstat.
  */
@@ -175,22 +175,47 @@ static unsigned short birdFileInfoToMode(HANDLE hFile, ULONG fAttribs, const cha
 }
 
 
-static void birdNtTimeToTimeSpec(__int64 iNtTime, BirdTimeSpec_T *pTimeSpec)
+/**
+ * Fills in a stat structure from an MY_FILE_ID_FULL_DIR_INFORMATION entry.
+ *
+ * @param   pStat               The stat structure.
+ * @param   pBuf                The MY_FILE_ID_FULL_DIR_INFORMATION entry.
+ * @param   pszPath             Optionally, the path for X bit checks.
+ * @remarks Caller sets st_dev.
+ */
+void birdStatFillFromFileIdFullDirInfo(BirdStat_T *pStat, MY_FILE_ID_FULL_DIR_INFORMATION const *pBuf, const char *pszPath)
 {
-    iNtTime -= BIRD_NT_EPOCH_OFFSET_UNIX_100NS;
-    pTimeSpec->tv_sec  = iNtTime / 10000000;
-    pTimeSpec->tv_nsec = (iNtTime % 10000000) * 100;
+    pStat->st_mode          = birdFileInfoToMode(INVALID_HANDLE_VALUE, pBuf->FileAttributes, pszPath,
+                                                 NULL, &pStat->st_dirsymlink);
+    pStat->st_padding0[0]   = 0;
+    pStat->st_padding0[1]   = 0;
+    pStat->st_size          = pBuf->EndOfFile.QuadPart;
+    birdNtTimeToTimeSpec(pBuf->CreationTime.QuadPart,   &pStat->st_birthtim);
+    birdNtTimeToTimeSpec(pBuf->ChangeTime.QuadPart,     &pStat->st_ctim);
+    birdNtTimeToTimeSpec(pBuf->LastWriteTime.QuadPart,  &pStat->st_mtim);
+    birdNtTimeToTimeSpec(pBuf->LastAccessTime.QuadPart, &pStat->st_atim);
+    pStat->st_ino           = pBuf->FileId.QuadPart;
+    pStat->st_nlink         = 1;
+    pStat->st_rdev          = 0;
+    pStat->st_uid           = 0;
+    pStat->st_gid           = 0;
+    pStat->st_padding1      = 0;
+    pStat->st_attribs       = pBuf->FileAttributes;
+    pStat->st_blksize       = 65536;
+    pStat->st_blocks        = (pBuf->AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1)
+                            / BIRD_STAT_BLOCK_SIZE;
 }
 
 
 /**
- * Fills in a stat structure from an MY_FILE_ID_FULL_DIR_INFORMATION entry.
+ * Fills in a stat structure from an MY_FILE_ID_BOTH_DIR_INFORMATION entry.
  *
  * @param   pStat               The stat structure.
- * @param   pBuf                The MY_FILE_ID_FULL_DIR_INFORMATION entry.
+ * @param   pBuf                The MY_FILE_ID_BOTH_DIR_INFORMATION entry.
  * @param   pszPath             Optionally, the path for X bit checks.
+ * @remarks Caller sets st_dev.
  */
-void birdStatFillFromFileIdFullDirInfo(BirdStat_T *pStat, MY_FILE_ID_FULL_DIR_INFORMATION const *pBuf, const char *pszPath)
+void birdStatFillFromFileIdBothDirInfo(BirdStat_T *pStat, MY_FILE_ID_BOTH_DIR_INFORMATION const *pBuf, const char *pszPath)
 {
     pStat->st_mode          = birdFileInfoToMode(INVALID_HANDLE_VALUE, pBuf->FileAttributes, pszPath,
                                                  NULL, &pStat->st_dirsymlink);
@@ -206,9 +231,40 @@ void birdStatFillFromFileIdFullDirInfo(BirdStat_T *pStat, MY_FILE_ID_FULL_DIR_IN
     pStat->st_rdev          = 0;
     pStat->st_uid           = 0;
     pStat->st_gid           = 0;
-    pStat->st_padding1[0]   = 0;
-    pStat->st_padding1[1]   = 0;
-    pStat->st_padding1[2]   = 0;
+    pStat->st_padding1      = 0;
+    pStat->st_attribs       = pBuf->FileAttributes;
+    pStat->st_blksize       = 65536;
+    pStat->st_blocks        = (pBuf->AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1)
+                            / BIRD_STAT_BLOCK_SIZE;
+}
+
+
+/**
+ * Fills in a stat structure from an MY_FILE_BOTH_DIR_INFORMATION entry.
+ *
+ * @param   pStat               The stat structure.
+ * @param   pBuf                The MY_FILE_BOTH_DIR_INFORMATION entry.
+ * @param   pszPath             Optionally, the path for X bit checks.
+ * @remarks Caller sets st_dev.
+ */
+void birdStatFillFromFileBothDirInfo(BirdStat_T *pStat, MY_FILE_BOTH_DIR_INFORMATION const *pBuf, const char *pszPath)
+{
+    pStat->st_mode          = birdFileInfoToMode(INVALID_HANDLE_VALUE, pBuf->FileAttributes, pszPath,
+                                                 NULL, &pStat->st_dirsymlink);
+    pStat->st_padding0[0]   = 0;
+    pStat->st_padding0[1]   = 0;
+    pStat->st_size          = pBuf->EndOfFile.QuadPart;
+    birdNtTimeToTimeSpec(pBuf->CreationTime.QuadPart,   &pStat->st_birthtim);
+    birdNtTimeToTimeSpec(pBuf->ChangeTime.QuadPart,     &pStat->st_ctim);
+    birdNtTimeToTimeSpec(pBuf->LastWriteTime.QuadPart,  &pStat->st_mtim);
+    birdNtTimeToTimeSpec(pBuf->LastAccessTime.QuadPart, &pStat->st_atim);
+    pStat->st_ino           = 0;
+    pStat->st_nlink         = 1;
+    pStat->st_rdev          = 0;
+    pStat->st_uid           = 0;
+    pStat->st_gid           = 0;
+    pStat->st_padding1      = 0;
+    pStat->st_attribs       = pBuf->FileAttributes;
     pStat->st_blksize       = 65536;
     pStat->st_blocks        = (pBuf->AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1)
                             / BIRD_STAT_BLOCK_SIZE;
@@ -246,9 +302,8 @@ int birdStatHandle(HANDLE hFile, BirdStat_T *pStat, const char *pszPath)
             pStat->st_rdev          = 0;
             pStat->st_uid           = 0;
             pStat->st_gid           = 0;
-            pStat->st_padding1[0]   = 0;
-            pStat->st_padding1[1]   = 0;
-            pStat->st_padding1[2]   = 0;
+            pStat->st_padding1      = 0;
+            pStat->st_attribs       = pAll->StandardInformation.FileAttributes;
             pStat->st_blksize       = 65536;
             pStat->st_blocks        = (pAll->StandardInformation.AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1)
                                     / BIRD_STAT_BLOCK_SIZE;
@@ -321,9 +376,8 @@ int birdStatHandle(HANDLE hFile, BirdStat_T *pStat, const char *pszPath)
         pStat->st_rdev          = 0;
         pStat->st_uid           = 0;
         pStat->st_gid           = 0;
-        pStat->st_padding1[0]   = 0;
-        pStat->st_padding1[1]   = 0;
-        pStat->st_padding1[2]   = 0;
+        pStat->st_padding1      = 0;
+        pStat->st_attribs       = BasicInfo.FileAttributes;
         pStat->st_blksize       = 65536;
         pStat->st_blocks        = (StdInfo.AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1)
                                 / BIRD_STAT_BLOCK_SIZE;
@@ -358,6 +412,53 @@ int birdStatHandle(HANDLE hFile, BirdStat_T *pStat, const char *pszPath)
 }
 
 
+/**
+ * Generates a device number from the volume information.
+ *
+ * @returns Device number.
+ * @param   pVolInfo            Volume information.
+ */
+unsigned __int64 birdVolumeInfoToDeviceNumber(const MY_FILE_FS_VOLUME_INFORMATION *pVolInfo)
+{
+    return pVolInfo->VolumeSerialNumber
+         | (pVolInfo->VolumeCreationTime.QuadPart << 32);
+}
+
+
+/**
+ * Quries the volume information and generates a device number from it.
+ *
+ * @returns NT status code.
+ * @param   hFile               The file/dir/whatever to query the volume info
+ *                              and device number for.
+ * @param   pVolInfo            User provided buffer for volume information.
+ * @param   cbVolInfo           The size of the buffer.
+ * @param   puDevNo             Where to return the device number.  This is set
+ *                              to zero on failure.
+ */
+MY_NTSTATUS birdQueryVolumeDeviceNumber(HANDLE hFile, MY_FILE_FS_VOLUME_INFORMATION *pVolInfo, size_t cbVolInfo,
+                                        unsigned __int64 *puDevNo)
+{
+    MY_IO_STATUS_BLOCK  Ios;
+    MY_NTSTATUS         rcNt;
+
+    Ios.u.Status    = -1;
+    Ios.Information = -1;
+
+    pVolInfo->VolumeSerialNumber = 0;
+    pVolInfo->VolumeCreationTime.QuadPart = 0;
+
+    rcNt = g_pfnNtQueryVolumeInformationFile(hFile, &Ios, pVolInfo, (LONG)cbVolInfo, MyFileFsVolumeInformation);
+    if (MY_NT_SUCCESS(rcNt))
+    {
+        *puDevNo = birdVolumeInfoToDeviceNumber(pVolInfo);
+        return Ios.u.Status;
+    }
+    *puDevNo = 0;
+    return rcNt;
+}
+
+
 static int birdStatInternal(const char *pszPath, BirdStat_T *pStat, int fFollow)
 {
     int rc;
@@ -428,21 +529,11 @@ static int birdStatInternal(const char *pszPath, BirdStat_T *pStat, int fFollow)
                     birdStatFillFromFileIdFullDirInfo(pStat, pBuf, pszPath);
 
                     /* Get the serial number, reusing the buffer from above. */
-                    rcNt = g_pfnNtQueryVolumeInformationFile(hFile, &Ios, pBuf, cbBuf, MyFileFsVolumeInformation);
-                    if (MY_NT_SUCCESS(rcNt))
-                        rcNt = Ios.u.Status;
+                    rcNt = birdQueryVolumeDeviceNumber(hFile, (MY_FILE_FS_VOLUME_INFORMATION *)pBuf, cbBuf, &pStat->st_dev);
                     if (MY_NT_SUCCESS(rcNt))
-                    {
-                        MY_FILE_FS_VOLUME_INFORMATION const *pVolInfo = (MY_FILE_FS_VOLUME_INFORMATION const *)pBuf;
-                        pStat->st_dev       = pVolInfo->VolumeSerialNumber
-                                            | (pVolInfo->VolumeCreationTime.QuadPart << 32);
                         rc = 0;
-                    }
                     else
-                    {
-                        pStat->st_dev       = 0;
                         rc = birdSetErrnoFromNt(rcNt);
-                    }
                 }
 
                 birdFreeNtPath(&NameUniStr);
@@ -503,9 +594,8 @@ int birdStatOnFd(int fd, BirdStat_T *pStat)
                 pStat->st_rdev              = 0;
                 pStat->st_uid               = 0;
                 pStat->st_gid               = 0;
-                pStat->st_padding1[0]       = 0;
-                pStat->st_padding1[1]       = 0;
-                pStat->st_padding1[2]       = 0;
+                pStat->st_padding1          = 0;
+                pStat->st_attribs           = fFileType == FILE_TYPE_PIPE ? FILE_ATTRIBUTE_NORMAL : FILE_ATTRIBUTE_DEVICE;
                 pStat->st_blksize           = 512;
                 pStat->st_blocks            = 0;
                 if (fFileType == FILE_TYPE_PIPE)
@@ -533,6 +623,35 @@ int birdStatOnFd(int fd, BirdStat_T *pStat)
 
 
 /**
+ * Special case that only gets the file size and nothing else.
+ */
+int birdStatOnFdJustSize(int fd, __int64 *pcbFile)
+{
+    int     rc;
+    HANDLE  hFile = (HANDLE)_get_osfhandle(fd);
+    if (hFile != INVALID_HANDLE_VALUE)
+    {
+        LARGE_INTEGER cbLocal;
+        if (GetFileSizeEx(hFile, &cbLocal))
+        {
+            *pcbFile = cbLocal.QuadPart;
+            rc = 0;
+        }
+        else
+        {
+            BirdStat_T Stat;
+            rc = birdStatOnFd(fd, &Stat);
+            if (rc == 0)
+                *pcbFile = Stat.st_size;
+        }
+    }
+    else
+        rc = -1;
+    return rc;
+}
+
+
+/**
  * Implements UNIX stat().
  */
 int birdStatFollowLink(const char *pszPath, BirdStat_T *pStat)
@@ -578,8 +697,13 @@ static int birdStatOnlyInternal(const char *pszPath, int fFollowLink, MY_FILE_BA
         }
         birdCloseFile(hFile);
 
-        if (!MY_NT_SUCCESS(rcNt))
+        if (MY_NT_SUCCESS(rcNt))
+            rc = 0;
+        else
+        {
             birdSetErrnoFromNt(rcNt);
+            rc = -1;
+        }
     }
     else
     {
diff --git a/src/lib/nt/ntstat.h b/src/lib/nt/ntstat.h
index fa5dd24..35bd4b4 100644
--- a/src/lib/nt/ntstat.h
+++ b/src/lib/nt/ntstat.h
@@ -1,4 +1,4 @@
-/* $Id: ntstat.h 2708 2013-11-21 10:26:40Z bird $ */
+/* $Id: ntstat.h 2858 2016-09-01 15:12:24Z bird $ */
 /** @file
  * MSC + NT stat, lstat and fstat implementation and wrappers.
  */
@@ -62,7 +62,8 @@ typedef struct BirdStat
     unsigned __int16    st_rdev;
     __int16             st_uid;
     __int16             st_gid;
-    unsigned __int16    st_padding1[3];
+    unsigned __int16    st_padding1;
+    unsigned __int32    st_attribs;
     unsigned __int32    st_blksize;
     __int64             st_blocks;
 } BirdStat_T;
@@ -77,9 +78,16 @@ typedef struct BirdStat
 int birdStatFollowLink(const char *pszPath, BirdStat_T *pStat);
 int birdStatOnLink(const char *pszPath, BirdStat_T *pStat);
 int birdStatOnFd(int fd, BirdStat_T *pStat);
+int birdStatOnFdJustSize(int fd, __int64 *pcbFile);
 int birdStatModTimeOnly(const char *pszPath, BirdTimeSpec_T *pTimeSpec, int fFollowLink);
 #ifdef ___nt_ntstuff_h
+int  birdStatHandle(HANDLE hFile, BirdStat_T *pStat, const char *pszPath);
 void birdStatFillFromFileIdFullDirInfo(BirdStat_T *pStat, MY_FILE_ID_FULL_DIR_INFORMATION const *pBuf, const char *pszPath);
+void birdStatFillFromFileIdBothDirInfo(BirdStat_T *pStat, MY_FILE_ID_BOTH_DIR_INFORMATION const *pBuf, const char *pszPath);
+void birdStatFillFromFileBothDirInfo(BirdStat_T *pStat, MY_FILE_BOTH_DIR_INFORMATION const *pBuf, const char *pszPath);
+MY_NTSTATUS birdQueryVolumeDeviceNumber(HANDLE hFile, MY_FILE_FS_VOLUME_INFORMATION *pVolInfo, size_t cbVolInfo,
+                                        unsigned __int64 *puDevNo);
+unsigned __int64 birdVolumeInfoToDeviceNumber(MY_FILE_FS_VOLUME_INFORMATION const *pVolInfo);
 #endif
 
 #define STAT_REDEFINED_ALREADY
diff --git a/src/lib/nt/ntstuff.h b/src/lib/nt/ntstuff.h
index 3341e10..a784ebc 100644
--- a/src/lib/nt/ntstuff.h
+++ b/src/lib/nt/ntstuff.h
@@ -1,4 +1,4 @@
-/* $Id: ntstuff.h 2713 2013-11-21 21:11:00Z bird $ */
+/* $Id: ntstuff.h 2862 2016-09-02 02:39:56Z bird $ */
 /** @file
  * Definitions, types, prototypes and globals for NT.
  */
@@ -35,6 +35,7 @@
 #define timeval timeval_Windows
 #define WIN32_NO_STATUS
 #include <Windows.h>
+#include <winternl.h>
 #undef WIN32_NO_STATUS
 #include <ntstatus.h>
 #undef timeval
@@ -113,6 +114,17 @@ typedef struct MY_FILE_STANDARD_INFORMATION
     BOOLEAN         Directory;
 } MY_FILE_STANDARD_INFORMATION;
 
+typedef struct MY_FILE_NETWORK_OPEN_INFORMATION
+{
+    LARGE_INTEGER   CreationTime;
+    LARGE_INTEGER   LastAccessTime;
+    LARGE_INTEGER   LastWriteTime;
+    LARGE_INTEGER   ChangeTime;
+    LARGE_INTEGER   AllocationSize;
+    LARGE_INTEGER   EndOfFile;
+    ULONG           FileAttributes;
+} MY_FILE_NETWORK_OPEN_INFORMATION;
+
 typedef struct MY_FILE_INTERNAL_INFORMATION
 {
     LARGE_INTEGER   IndexNumber;
@@ -199,6 +211,48 @@ typedef struct MY_FILE_ID_FULL_DIR_INFORMATION
 /** The sizeof(MY_FILE_NAMES_INFORMATION) without the FileName. */
 #define MIN_SIZEOF_MY_FILE_ID_FULL_DIR_INFORMATION  ( (size_t)&((MY_FILE_ID_FULL_DIR_INFORMATION *)0)->FileName )
 
+typedef struct MY_FILE_BOTH_DIR_INFORMATION
+{
+    ULONG           NextEntryOffset;
+    ULONG           FileIndex;
+    LARGE_INTEGER   CreationTime;
+    LARGE_INTEGER   LastAccessTime;
+    LARGE_INTEGER   LastWriteTime;
+    LARGE_INTEGER   ChangeTime;
+    LARGE_INTEGER   EndOfFile;
+    LARGE_INTEGER   AllocationSize;
+    ULONG           FileAttributes;
+    ULONG           FileNameLength;
+    ULONG           EaSize;
+    CCHAR           ShortNameLength;
+    WCHAR           ShortName[12];
+    WCHAR           FileName[1];
+} MY_FILE_BOTH_DIR_INFORMATION;
+/** The sizeof(MY_FILE_BOTH_DIR_INFORMATION) without the FileName. */
+#define MIN_SIZEOF_MY_FILE_BOTH_DIR_INFORMATION  ( (size_t)&((MY_FILE_BOTH_DIR_INFORMATION *)0)->FileName )
+
+
+typedef struct MY_FILE_ID_BOTH_DIR_INFORMATION
+{
+    ULONG           NextEntryOffset;
+    ULONG           FileIndex;
+    LARGE_INTEGER   CreationTime;
+    LARGE_INTEGER   LastAccessTime;
+    LARGE_INTEGER   LastWriteTime;
+    LARGE_INTEGER   ChangeTime;
+    LARGE_INTEGER   EndOfFile;
+    LARGE_INTEGER   AllocationSize;
+    ULONG           FileAttributes;
+    ULONG           FileNameLength;
+    ULONG           EaSize;
+    CCHAR           ShortNameLength;
+    WCHAR           ShortName[12];
+    LARGE_INTEGER   FileId;
+    WCHAR           FileName[1];
+} MY_FILE_ID_BOTH_DIR_INFORMATION;
+/** The sizeof(MY_FILE_NAMES_INFORMATION) without the FileName. */
+#define MIN_SIZEOF_MY_FILE_ID_BOTH_DIR_INFORMATION  ( (size_t)&((MY_FILE_ID_BOTH_DIR_INFORMATION *)0)->FileName )
+
 
 typedef struct MY_FILE_DISPOSITION_INFORMATION
 {
@@ -276,6 +330,14 @@ typedef struct MY_FILE_FS_VOLUME_INFORMATION
     WCHAR           VolumeLabel[1];
 } MY_FILE_FS_VOLUME_INFORMATION;
 
+typedef struct _MY_FILE_FS_ATTRIBUTE_INFORMATION
+{
+    ULONG           FileSystemAttributes;
+    LONG            MaximumComponentNameLength;
+    ULONG           FileSystemNameLength;
+    WCHAR           FileSystemName[1];
+} MY_FILE_FS_ATTRIBUTE_INFORMATION;
+
 typedef enum MY_FSINFOCLASS
 {
     MyFileFsVolumeInformation                      = 1,
@@ -357,6 +419,11 @@ typedef struct MY_RTL_RELATIVE_NAME_U
 #define MY_NT_SUCCESS(a_ntRc)               ((MY_NTSTATUS)(a_ntRc) >= 0)
 #define MY_NT_FAILURE(a_ntRc)               ((MY_NTSTATUS)(a_ntRc) <  0)
 #define MY_STATUS_NO_MORE_FILES             ((MY_NTSTATUS)0x80000006)
+#define MY_STATUS_OBJECT_NAME_INVALID       ((MY_NTSTATUS)0xc0000033)
+#define MY_STATUS_OBJECT_NAME_NOT_FOUND     ((MY_NTSTATUS)0xc0000034)
+#define MY_STATUS_OBJECT_PATH_INVALID       ((MY_NTSTATUS)0xc0000039)
+#define MY_STATUS_OBJECT_PATH_NOT_FOUND     ((MY_NTSTATUS)0xc000003a)
+#define MY_STATUS_OBJECT_PATH_SYNTAX_BAD    ((MY_NTSTATUS)0xc000003b)
 /** @}  */
 
 
@@ -367,6 +434,9 @@ extern MY_NTSTATUS (WINAPI * g_pfnNtClose)(HANDLE);
 extern MY_NTSTATUS (WINAPI * g_pfnNtCreateFile)(PHANDLE, MY_ACCESS_MASK, MY_OBJECT_ATTRIBUTES *, MY_IO_STATUS_BLOCK *,
                                                 PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
 extern MY_NTSTATUS (WINAPI * g_pfnNtDeleteFile)(MY_OBJECT_ATTRIBUTES *);
+extern MY_NTSTATUS (WINAPI * g_pfnNtReadFile)(HANDLE hFile, HANDLE hEvent, MY_IO_APC_ROUTINE *pfnApc, PVOID pvApcCtx,
+                                              MY_IO_STATUS_BLOCK *, PVOID pvBuf, ULONG cbToRead, PLARGE_INTEGER poffFile,
+                                              PULONG  puKey);
 extern MY_NTSTATUS (WINAPI * g_pfnNtQueryInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *,
                                                           PVOID, LONG, MY_FILE_INFORMATION_CLASS);
 extern MY_NTSTATUS (WINAPI * g_pfnNtQueryVolumeInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *,
@@ -374,9 +444,16 @@ extern MY_NTSTATUS (WINAPI * g_pfnNtQueryVolumeInformationFile)(HANDLE, MY_IO_ST
 extern MY_NTSTATUS (WINAPI * g_pfnNtQueryDirectoryFile)(HANDLE, HANDLE, MY_IO_APC_ROUTINE *, PVOID, MY_IO_STATUS_BLOCK *,
                                                         PVOID, ULONG, MY_FILE_INFORMATION_CLASS, BOOLEAN,
                                                         MY_UNICODE_STRING *, BOOLEAN);
+extern MY_NTSTATUS (WINAPI * g_pfnNtQueryAttributesFile)(MY_OBJECT_ATTRIBUTES *, MY_FILE_BASIC_INFORMATION *);
+extern MY_NTSTATUS (WINAPI * g_pfnNtQueryFullAttributesFile)(MY_OBJECT_ATTRIBUTES *, MY_FILE_NETWORK_OPEN_INFORMATION *);
 extern MY_NTSTATUS (WINAPI * g_pfnNtSetInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *, PVOID, LONG, MY_FILE_INFORMATION_CLASS);
 extern BOOLEAN     (WINAPI * g_pfnRtlDosPathNameToNtPathName_U)(PCWSTR, MY_UNICODE_STRING *, PCWSTR *, MY_RTL_RELATIVE_NAME_U *);
 extern MY_NTSTATUS (WINAPI * g_pfnRtlAnsiStringToUnicodeString)(MY_UNICODE_STRING *, MY_ANSI_STRING const *, BOOLEAN);
+extern BOOLEAN     (WINAPI * g_pfnRtlEqualUnicodeString)(MY_UNICODE_STRING const *pUniStr1, MY_UNICODE_STRING const *pUniStr2,
+                                                         BOOLEAN fCaseInsensitive);
+extern BOOLEAN     (WINAPI * g_pfnRtlEqualString)(MY_ANSI_STRING const *pAnsiStr1, MY_ANSI_STRING const *pAnsiStr2,
+                                                  BOOLEAN fCaseInsensitive);
+extern UCHAR       (WINAPI * g_pfnRtlUpperChar)(UCHAR uch);
 
 
 /** @} */
diff --git a/src/lib/nt_fullpath.c b/src/lib/nt_fullpath.c
index 3b59826..7d3ed74 100644
--- a/src/lib/nt_fullpath.c
+++ b/src/lib/nt_fullpath.c
@@ -1,4 +1,4 @@
-/* $Id: nt_fullpath.c 2455 2011-07-07 23:16:02Z bird $ */
+/* $Id: nt_fullpath.c 2849 2016-08-30 14:28:46Z bird $ */
 /** @file
  * fixcase - fixes the case of paths, windows specific.
  */
@@ -33,6 +33,9 @@
 #include <ctype.h>
 #include <direct.h>
 
+#include "nt_fullpath.h"
+
+
 /*
  * Corrects the case of a path.
  * Expects a fullpath!
diff --git a/src/lib/mytypes.h b/src/lib/nt_fullpath.h
similarity index 59%
copy from src/lib/mytypes.h
copy to src/lib/nt_fullpath.h
index f546a20..3e3f83f 100644
--- a/src/lib/mytypes.h
+++ b/src/lib/nt_fullpath.h
@@ -1,10 +1,10 @@
-/* $Id: mytypes.h 2442 2011-07-06 12:19:16Z bird $ */
+/* $Id: nt_fullpath.h 2849 2016-08-30 14:28:46Z bird $ */
 /** @file
- * mytypes - wrapper that ensures the necessary uintXY_t types are defined.
+ * fixcase - fixes the case of paths, windows specific.
  */
 
 /*
- * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ * Copyright (c) 2004-2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
  *
  * This file is part of kBuild.
  *
@@ -23,20 +23,19 @@
  *
  */
 
-#ifndef ___mytypes_h__
-#define ___mytypes_h__
+#ifndef ___lib_nt_fullpath_h___
+#define ___lib_nt_fullpath_h___
+
+#ifdef __cpluslus
+extern "C"
+#endif
+
+extern void nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull);
+extern void nt_fullpath_cached(const char *pszPath, char *pszFull, size_t cchFull);
 
-#include <stdlib.h>
-#include <stddef.h> /* MSC: intptr_t */
-#include <sys/types.h>
 
-#if defined(_MSC_VER)
-typedef unsigned int uint32_t;
-typedef signed int int32_t;
-typedef unsigned char uint8_t;
-typedef signed char int8_t;
-#else
-# include <stdint.h>
+#ifdef __cpluslus
+}
 #endif
 
 #endif
diff --git a/src/lib/nt_fullpath_cached.c b/src/lib/nt_fullpath_cached.c
new file mode 100644
index 0000000..3692f0d
--- /dev/null
+++ b/src/lib/nt_fullpath_cached.c
@@ -0,0 +1,136 @@
+/* $Id: nt_fullpath_cached.c 2849 2016-08-30 14:28:46Z bird $ */
+/** @file
+ * fixcase - fixes the case of paths, windows specific.
+ */
+
+/*
+ * Copyright (c) 2004-2010 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * kBuild 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 kBuild.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <Windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <direct.h>
+#include <assert.h>
+
+#include "nt_fullpath.h"
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+typedef struct NTFULLPATHENTRY
+{
+    /** Pointer to the next entry with the same hash table index. */
+    struct NTFULLPATHENTRY *pNext;
+    /** The input hash. */
+    unsigned                uHash;
+    /** The input length. */
+    unsigned                cchInput;
+    /** Length of the result. */
+    unsigned                cchResult;
+    /** The result string (stored immediately after this structure). */
+    const char             *pszResult;
+    /** The input string (variable length). */
+    char                    szInput[1];
+} NTFULLPATHENTRY;
+typedef NTFULLPATHENTRY *PNTFULLPATHENTRY;
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** Number of result in the nt_fullpath cache.  */
+size_t              g_cNtFullPathHashEntries = 0;
+/** Number of bytes used for nt_fullpath cache result entries. */
+size_t              g_cbNtFullPathHashEntries = 0;
+/** Number of hash table collsioins in the nt_fullpath cache.  */
+size_t              g_cNtFullPathHashCollisions = 0;
+/** Hash table. */
+PNTFULLPATHENTRY    g_apNtFullPathHashTab[16381];
+
+
+/**
+ * A nt_fullpath frontend which caches the result of previous calls.
+ */
+void
+nt_fullpath_cached(const char *pszPath, char *pszFull, size_t cchFull)
+{
+    PNTFULLPATHENTRY        pEntry;
+    unsigned                cchInput;
+    unsigned                idx;
+    unsigned                cchResult;
+
+    /* We use the sdbm hash algorithm here (see kDep.c for full details). */
+    unsigned const char    *puch = (unsigned const char *)pszPath;
+    unsigned                uHash = 0;
+    unsigned                uChar;
+    while ((uChar = *puch++) != 0)
+        uHash = uChar + (uHash << 6) + (uHash << 16) - uHash;
+
+    cchInput = (unsigned)((uintptr_t)&puch[-1] - (uintptr_t)pszPath);
+
+    /* Do the cache lookup. */
+    idx = uHash % (sizeof(g_apNtFullPathHashTab) / sizeof(g_apNtFullPathHashTab[0]));
+    for (pEntry = g_apNtFullPathHashTab[idx]; pEntry != NULL; pEntry = pEntry->pNext)
+        if (   pEntry->uHash == uHash
+            && pEntry->cchInput == cchInput
+            && memcmp(pEntry->szInput, pszPath, cchInput) == 0)
+        {
+            if (cchFull > pEntry->cchResult)
+                memcpy(pszFull, pEntry->pszResult, pEntry->cchResult + 1);
+            else
+            {
+                assert(0);
+                memcpy(pszFull, pEntry->pszResult, cchFull);
+                pszFull[cchFull - 1] = '\0';
+            }
+            return;
+        }
+
+    /* Make the call... */
+    nt_fullpath(pszPath, pszFull, cchFull);
+
+    /* ... and cache the result. */
+    cchResult = (unsigned)strlen(pszFull);
+    pEntry = malloc(sizeof(*pEntry) + cchInput + cchResult + 1);
+    if (pEntry)
+    {
+        g_cbNtFullPathHashEntries += sizeof(*pEntry) + cchInput + cchResult + 1;
+        pEntry->cchInput  = cchInput;
+        pEntry->cchResult = cchResult;
+        pEntry->pszResult = &pEntry->szInput[cchInput + 1];
+        pEntry->uHash     = uHash;
+        memcpy(pEntry->szInput, pszPath, cchInput + 1);
+        memcpy((char *)pEntry->pszResult, pszFull, cchResult + 1);
+
+        pEntry->pNext = g_apNtFullPathHashTab[idx];
+        if (pEntry->pNext)
+            g_cNtFullPathHashCollisions++;
+        g_apNtFullPathHashTab[idx] = pEntry;
+
+        g_cNtFullPathHashEntries++;
+    }
+}
+
diff --git a/src/lib/quote_argv.c b/src/lib/quote_argv.c
new file mode 100644
index 0000000..9c4559a
--- /dev/null
+++ b/src/lib/quote_argv.c
@@ -0,0 +1,209 @@
+/* $Id: quote_argv.c 2851 2016-08-31 17:30:52Z bird $ */
+/** @file
+ * quote_argv - Correctly quote argv for spawn, windows specific.
+ */
+
+/*
+ * Copyright (c) 2007-2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "quote_argv.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifndef KBUILD_OS_WINDOWS
+# error "KBUILD_OS_WINDOWS not defined"
+#endif
+
+
+/**
+ * Checks if this is an Watcom option where we must just pass thru the string
+ * as-is.
+ *
+ * This is currnetly only used for -d (defining macros).
+ *
+ * @returns 1 if pass-thru, 0 if not.
+ * @param   pszArg          The argument to consider.
+ */
+static int isWatcomPassThruOption(const char *pszArg)
+{
+    char ch = *pszArg++;
+    if (ch != '-' && ch != '/')
+        return 0;
+    ch = *pszArg++;
+    switch (ch)
+    {
+        /* Example: -d+VAR="string-value" */
+        case 'd':
+            if (ch == '+')
+                ch = *pszArg++;
+            if (!isalpha(ch) && ch != '_')
+                return 0;
+            return 1;
+
+        default:
+            return 0;
+    }
+}
+
+
+/**
+ * Replaces arguments in need of quoting.
+ *
+ * For details on how MSC parses the command line, see "Parsing C Command-Line
+ * Arguments": http://msdn.microsoft.com/en-us/library/a1y7w461.aspx
+ *
+ * @param   argc                The argument count.
+ * @param   argv                The argument vector.
+ * @param   fWatcomBrainDamage  Set if we're catering for wcc, wcc386 or similar
+ *                              OpenWatcom tools.  They seem to follow some
+ *                              ancient or home made quoting convention.
+ * @param   fFreeOrLeak         Whether to free replaced argv members
+ *                              (non-zero), or just leak them (zero).  This
+ *                              depends on which argv you're working on.
+ *                              Suggest doing the latter if it's main()'s argv.
+ */
+void quote_argv(int argc, char **argv, int fWatcomBrainDamage, int fFreeOrLeak)
+{
+    int i;
+    for (i = 0; i < argc; i++)
+    {
+        char *const pszOrgOrg = argv[i];
+        const char *pszOrg    = pszOrgOrg;
+        size_t      cchOrg    = strlen(pszOrg);
+        const char *pszQuotes = (const char *)memchr(pszOrg, '"', cchOrg);
+        const char *pszProblem = NULL;
+        if (   pszQuotes
+            || cchOrg == 0
+            || (pszProblem = (const char *)memchr(pszOrg, ' ',  cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '\t', cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '\n', cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '\r', cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '&',  cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '>',  cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '<',  cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '|',  cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '%',  cchOrg)) != NULL
+            || (pszProblem = (const char *)memchr(pszOrg, '\'', cchOrg)) != NULL
+            || (   !fWatcomBrainDamage
+                && (pszProblem = (const char *)memchr(pszOrg, '=',  cchOrg)) != NULL)
+            )
+        {
+            char   ch;
+            int    fComplicated = pszQuotes || (cchOrg > 0 && pszOrg[cchOrg - 1] == '\\');
+            size_t cchNew       = fComplicated ? cchOrg * 2 + 2 : cchOrg + 2;
+            char  *pszNew       = (char *)malloc(cchNew + 1 /*term*/ + 3 /*passthru hack*/);
+
+            argv[i] = pszNew;
+
+            /* Watcom does not grok stuff like "-i=c:\program files\watcom\h",
+               it think it's a source specification. In that case the quote
+               must follow the equal sign. */
+            if (fWatcomBrainDamage)
+            {
+                size_t cchUnquoted  = 0;
+                if (pszOrg[0] == '@') /* Response file quoting: @"file name.rsp" */
+                    cchUnquoted = 1;
+                else if (pszOrg[0] == '-' || pszOrg[0] == '/') /* Switch quoting. */
+                {
+                    if (isWatcomPassThruOption(pszOrg))
+                        cchUnquoted = strlen(pszOrg) + 1;
+                    else
+                    {
+                        const char *pszNeedQuoting = (const char *)memchr(pszOrg, '=', cchOrg); /* For -i=dir and similar. */
+                        if (   pszNeedQuoting == NULL
+                            || (uintptr_t)pszNeedQuoting > (uintptr_t)(pszProblem ? pszProblem : pszQuotes))
+                            pszNeedQuoting = pszProblem ? pszProblem : pszQuotes;
+                        else
+                            pszNeedQuoting++;
+                        cchUnquoted = pszNeedQuoting - pszOrg;
+                    }
+                }
+                if (cchUnquoted)
+                {
+                    memcpy(pszNew, pszOrg, cchUnquoted);
+                    pszNew += cchUnquoted;
+                    pszOrg += cchUnquoted;
+                    cchOrg -= cchUnquoted;
+                }
+            }
+
+            *pszNew++ = '"';
+            if (fComplicated)
+            {
+                while ((ch = *pszOrg++) != '\0')
+                {
+                    if (ch == '"')
+                    {
+                        *pszNew++ = '\\';
+                        *pszNew++ = '"';
+                    }
+                    else if (ch == '\\')
+                    {
+                        /* Backslashes are a bit complicated, they depends on
+                           whether a quotation mark follows them or not.  They
+                           only require escaping if one does. */
+                        unsigned cSlashes = 1;
+                        while ((ch = *pszOrg) == '\\')
+                        {
+                            pszOrg++;
+                            cSlashes++;
+                        }
+                        if (ch == '"' || ch == '\0') /* We put a " at the EOS. */
+                        {
+                            while (cSlashes-- > 0)
+                            {
+                                *pszNew++ = '\\';
+                                *pszNew++ = '\\';
+                            }
+                        }
+                        else
+                            while (cSlashes-- > 0)
+                                *pszNew++ = '\\';
+                    }
+                    else
+                        *pszNew++ = ch;
+                }
+            }
+            else
+            {
+                memcpy(pszNew, pszOrg, cchOrg);
+                pszNew += cchOrg;
+            }
+            *pszNew++ = '"';
+            *pszNew = '\0';
+
+            if (fFreeOrLeak)
+                free(pszOrgOrg);
+        }
+    }
+
+    /*for (i = 0; i < argc; i++) fprintf(stderr, "argv[%u]=%s;;\n", i, argv[i]);*/
+}
+
diff --git a/src/lib/quote_argv.h b/src/lib/quote_argv.h
new file mode 100644
index 0000000..3f6b42e
--- /dev/null
+++ b/src/lib/quote_argv.h
@@ -0,0 +1,39 @@
+/* $Id: quote_argv.h 2851 2016-08-31 17:30:52Z bird $ */
+/** @file
+ * quote_argv - Correctly quote argv for spawn, windows specific.
+ */
+
+/*
+ * Copyright (c) 2007-2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
+ */
+
+
+#ifndef ___quote_argv_h___
+#define ___quote_argv_h___
+
+#include "mytypes.h"
+extern void quote_argv(int argc, char **argv, int fWatcomBrainDamage, int fFreeOrLeak);
+
+#endif
+
diff --git a/src/lib/quoted_spawn.c b/src/lib/quoted_spawn.c
index 648a3a9..f06aca4 100644
--- a/src/lib/quoted_spawn.c
+++ b/src/lib/quoted_spawn.c
@@ -1,28 +1,34 @@
-/* $Id: quoted_spawn.c 2413 2010-09-11 17:43:04Z bird $ */
+/* $Id: quoted_spawn.c 2851 2016-08-31 17:30:52Z bird $ */
 /** @file
  * quote_spawn - Correctly Quote The _spawnvp arguments, windows specific.
  */
 
 /*
- * Copyright (c) 2010 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ * Copyright (c) 2010-2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
  *
- * This file is part of kBuild.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
  *
- * kBuild 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 3 of the License, or
- * (at your option) any later version.
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
  *
- * kBuild 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 kBuild.  If not, see <http://www.gnu.org/licenses/>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
  *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
  */
 
+
 /*******************************************************************************
 *   Header Files                                                               *
 *******************************************************************************/
diff --git a/src/lib/quoted_spawn.h b/src/lib/quoted_spawn.h
index ae8310d..3c2ccb6 100644
--- a/src/lib/quoted_spawn.h
+++ b/src/lib/quoted_spawn.h
@@ -1,26 +1,31 @@
-/* $Id: quoted_spawn.h 2413 2010-09-11 17:43:04Z bird $ */
+/* $Id: quoted_spawn.h 2851 2016-08-31 17:30:52Z bird $ */
 /** @file
  * quote_spawn - Correctly Quote The _spawnvp arguments, windows specific.
  */
 
 /*
- * Copyright (c) 2010 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ * Copyright (c) 2010-2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
  *
- * This file is part of kBuild.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
  *
- * kBuild 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 3 of the License, or
- * (at your option) any later version.
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
  *
- * kBuild 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 kBuild.  If not, see <http://www.gnu.org/licenses/>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
  *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
  */
 
 
diff --git a/src/lib/restartable-syscall-wrappers.c b/src/lib/restartable-syscall-wrappers.c
index f2ec221..9f593a5 100644
--- a/src/lib/restartable-syscall-wrappers.c
+++ b/src/lib/restartable-syscall-wrappers.c
@@ -1,4 +1,4 @@
-/* $Id: restartable-syscall-wrappers.c 2507 2011-07-24 15:42:39Z bird $ */
+/* $Id: restartable-syscall-wrappers.c 2851 2016-08-31 17:30:52Z bird $ */
 /** @file
  * restartable-syscall-wrappers.c - Workaround for annoying S11 "features".
  *
@@ -12,23 +12,28 @@
  */
 
 /*
- * Copyright (c) 2011 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ * Copyright (c) 2011-2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
  *
- * This file is part of kBuild.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
  *
- * kBuild 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 3 of the License, or
- * (at your option) any later version.
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
  *
- * kBuild 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 kBuild.  If not, see <http://www.gnu.org/licenses/>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
  *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
  */
 
 
diff --git a/src/lib/wrapper.c b/src/lib/wrapper.c
index fd097b7..8753fce 100644
--- a/src/lib/wrapper.c
+++ b/src/lib/wrapper.c
@@ -1,28 +1,34 @@
-/* $Id: wrapper.c 2413 2010-09-11 17:43:04Z bird $ */
+/* $Id: wrapper.c 2851 2016-08-31 17:30:52Z bird $ */
 /** @file
  * Wrapper program for various debugging purposes.
  */
 
 /*
- * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ * Copyright (c) 2007-2016 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
  *
- * This file is part of kBuild.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
  *
- * kBuild 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 3 of the License, or
- * (at your option) any later version.
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
  *
- * kBuild 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 kBuild.  If not, see <http://www.gnu.org/licenses/>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
  *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
  */
 
+
 /*******************************************************************************
 *   Header Files                                                               *
 *******************************************************************************/
@@ -35,6 +41,7 @@
 # include <unistd.h>
 #endif
 
+
 int main(int argc, char **argv, char **envp)
 {
     const char *pszLogTo        = getenv("WRAPPER_LOGTO");
@@ -88,3 +95,4 @@ int main(int argc, char **argv, char **envp)
 
     return pszRetVal ? atol(pszRetVal) : 1;
 }
+
diff --git a/src/sed/Makefile.kmk b/src/sed/Makefile.kmk
index 290a64e..7a6bc2f 100644
--- a/src/sed/Makefile.kmk
+++ b/src/sed/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 2546 2011-10-01 19:49:54Z bird $
+# $Id: Makefile.kmk 2829 2016-08-15 10:52:09Z bird $
 ## @file
 # Sub-Makefile for kmk_sed.
 #
@@ -36,6 +36,7 @@ kmk_sed_DEPS = \
 	$(kmk_sed_0_OUTDIR)/config.h \
 	$(kmk_sed_0_OUTDIR)/regex.h
 kmk_sed_CLEAN = $(kmk_sed_DEPS)
+kmk_sed_CFLAGS.solaris = -std=gnu99
 kmk_sed_INCS = \
 	$(kmk_sed_0_OUTDIR) \
 	. \
@@ -78,11 +79,8 @@ kmk_sed_SOURCES.openbsd = \
 	lib/getline.c
 kmk_sed_SOURCES.solaris = \
 	lib/strverscmp.c \
-	lib/obstack.c
-ifdef KBUILD_SOLARIS_10
-kmk_sed_SOURCES.solaris += \
+	lib/obstack.c \
 	lib/getline.c
-endif
 kmk_sed_SOURCES.win = \
 	lib/strverscmp.c \
 	lib/obstack.c \

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-virtualbox/kbuild.git



More information about the Pkg-virtualbox-commits mailing list