]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
UBUNTU: ubuntu: vbox -- update to 5.1.28-dfsg-1
authorSeth Forshee <seth.forshee@canonical.com>
Tue, 19 Sep 2017 01:12:12 +0000 (20:12 -0500)
committerSeth Forshee <seth.forshee@canonical.com>
Mon, 29 Jan 2018 13:44:58 +0000 (07:44 -0600)
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
244 files changed:
ubuntu/vbox/BOM [new file with mode: 0644]
ubuntu/vbox/Makefile [new file with mode: 0644]
ubuntu/vbox/dkms.conf [new file with mode: 0644]
ubuntu/vbox/include/VBox/HGSMI/HGSMI.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/HGSMI/HGSMIChSetup.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/HGSMI/HGSMIChannels.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/HGSMI/HGSMIDefs.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/HGSMI/HGSMIMemAlloc.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/Hardware/VBoxVideoVBE.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/VBoxGuest.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/VBoxGuest2.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/VBoxGuestLib.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/VBoxGuestLibSharedFolders.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/VBoxGuestMangling.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/VBoxVideo.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/VBoxVideoGuest.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/VMMDev.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/VMMDev2.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/cdefs.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/err.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/hgcmsvc.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/log.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/ostypes.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/param.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/shflsvc.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/types.h [new file with mode: 0644]
ubuntu/vbox/include/VBox/version.h [new file with mode: 0644]
ubuntu/vbox/include/internal/assert.h [new file with mode: 0644]
ubuntu/vbox/include/internal/initterm.h [new file with mode: 0644]
ubuntu/vbox/include/internal/iprt.h [new file with mode: 0644]
ubuntu/vbox/include/internal/lockvalidator.h [new file with mode: 0644]
ubuntu/vbox/include/internal/magics.h [new file with mode: 0644]
ubuntu/vbox/include/internal/mem.h [new file with mode: 0644]
ubuntu/vbox/include/internal/memobj.h [new file with mode: 0644]
ubuntu/vbox/include/internal/process.h [new file with mode: 0644]
ubuntu/vbox/include/internal/sched.h [new file with mode: 0644]
ubuntu/vbox/include/internal/string.h [new file with mode: 0644]
ubuntu/vbox/include/internal/thread.h [new file with mode: 0644]
ubuntu/vbox/include/internal/time.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/alloc.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/alloca.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/asm-amd64-x86.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/asm-math.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/asm.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/assert.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/avl.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/cdefs.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/cpuset.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/ctype.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/err.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/errno.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/fs.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/heap.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/initterm.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/latin1.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/list.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/lockvalidator.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/log.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/mangling.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/mem.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/memobj.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/mp.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/net.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/nocrt/limits.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/param.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/path.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/power.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/process.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/semaphore.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/spinlock.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/stdarg.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/stdint.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/string.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/thread.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/time.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/timer.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/types.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/uint64.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/uni.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/utf16.h [new file with mode: 0644]
ubuntu/vbox/include/iprt/x86.h [new file with mode: 0644]
ubuntu/vbox/include/the-linux-kernel.h [new file with mode: 0644]
ubuntu/vbox/r0drv/alloc-r0drv.c [new file with mode: 0644]
ubuntu/vbox/r0drv/alloc-r0drv.h [new file with mode: 0644]
ubuntu/vbox/r0drv/generic/semspinmutex-r0drv-generic.c [new file with mode: 0644]
ubuntu/vbox/r0drv/initterm-r0drv.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/RTLogWriteDebugger-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/alloc-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/assert-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/initterm-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/memobj-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/memuserkernel-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/mp-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/mpnotification-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/process-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/semevent-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/semeventmulti-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/semfastmutex-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/semmutex-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/spinlock-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/string.h [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/the-linux-kernel.h [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/thread-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/thread2-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/time-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/timer-r0drv-linux.c [new file with mode: 0644]
ubuntu/vbox/r0drv/linux/waitqueue-r0drv-linux.h [new file with mode: 0644]
ubuntu/vbox/r0drv/memobj-r0drv.c [new file with mode: 0644]
ubuntu/vbox/r0drv/mp-r0drv.h [new file with mode: 0644]
ubuntu/vbox/r0drv/mpnotification-r0drv.c [new file with mode: 0644]
ubuntu/vbox/r0drv/power-r0drv.h [new file with mode: 0644]
ubuntu/vbox/r0drv/powernotification-r0drv.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/GenericRequest.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/HGCMInternal.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/Init.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/Makefile [new file with mode: 0644]
ubuntu/vbox/vboxguest/Makefile.include.footer [new file with mode: 0644]
ubuntu/vbox/vboxguest/Makefile.include.header [new file with mode: 0644]
ubuntu/vbox/vboxguest/PhysHeap.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/SysHlp.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/SysHlp.h [new file with mode: 0644]
ubuntu/vbox/vboxguest/VBGLInternal.h [new file with mode: 0644]
ubuntu/vbox/vboxguest/VBox/log-vbox.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/VBox/logbackdoor.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/VBoxGuest-linux.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/VBoxGuest.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/VBoxGuestIDC-unix.c.h [new file with mode: 0644]
ubuntu/vbox/vboxguest/VBoxGuestInternal.h [new file with mode: 0644]
ubuntu/vbox/vboxguest/VBoxGuestLog.h [new file with mode: 0644]
ubuntu/vbox/vboxguest/VMMDev.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/alloc/alloc.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/alloc/heapsimple.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/err/RTErrConvertFromErrno.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/err/RTErrConvertToErrno.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/log/log.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/log/logcom.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/log/logellipsis.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/log/logformat.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/log/logrel.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/log/logrelellipsis.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/math/gcc/divdi3.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/math/gcc/moddi3.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/math/gcc/qdivrem.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/math/gcc/quad.h [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/math/gcc/udivdi3.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/math/gcc/udivmoddi4.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/math/gcc/umoddi3.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/misc/RTAssertMsg1Weak.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2Add.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2AddWeak.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2AddWeakV.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2Weak.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2WeakV.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/misc/assert.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/misc/thread.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/string/RTStrCopy.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/string/RTStrCopyEx.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/string/RTStrCopyP.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/string/strformat.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/string/strformatrt.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/string/strformattype.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/string/strprintf.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/string/strtonum.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/table/avl_Base.cpp.h [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/table/avl_Destroy.cpp.h [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/table/avl_DoWithAll.cpp.h [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/table/avl_Get.cpp.h [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/table/avl_GetBestFit.cpp.h [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/table/avl_RemoveBestFit.cpp.h [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/table/avlpv.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/common/time/time.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/generic/RTAssertShouldPanic-generic.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/generic/RTLogWriteStdErr-stub-generic.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/generic/RTLogWriteStdOut-stub-generic.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/generic/RTMpGetCoreCount-generic.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/generic/RTSemEventMultiWait-2-ex-generic.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/generic/RTSemEventMultiWaitNoResume-2-ex-generic.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/generic/RTSemEventWait-2-ex-generic.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/generic/RTSemEventWaitNoResume-2-ex-generic.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/generic/errvars-generic.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/generic/mppresent-generic.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/generic/rtStrFormatKernelAddress-generic.c [new file with mode: 0644]
ubuntu/vbox/vboxguest/include [new symlink]
ubuntu/vbox/vboxguest/product-generated.h [new file with mode: 0644]
ubuntu/vbox/vboxguest/r0drv [new symlink]
ubuntu/vbox/vboxguest/revision-generated.h [new file with mode: 0644]
ubuntu/vbox/vboxguest/version-generated.h [new file with mode: 0644]
ubuntu/vbox/vboxsf/GenericRequest.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/HGCM.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/Init.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/Makefile [new file with mode: 0644]
ubuntu/vbox/vboxsf/Makefile.include.footer [new file with mode: 0644]
ubuntu/vbox/vboxsf/Makefile.include.header [new file with mode: 0644]
ubuntu/vbox/vboxsf/PhysHeap.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/SysHlp.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/SysHlp.h [new file with mode: 0644]
ubuntu/vbox/vboxsf/VBGLInternal.h [new file with mode: 0644]
ubuntu/vbox/vboxsf/VBoxGuestLog.h [new file with mode: 0644]
ubuntu/vbox/vboxsf/VBoxGuestR0LibSharedFolders.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/VMMDev.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/VbglR0CanUsePhysPageList.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/dirops.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/divdi3.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/include [new symlink]
ubuntu/vbox/vboxsf/lnkops.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/moddi3.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/product-generated.h [new file with mode: 0644]
ubuntu/vbox/vboxsf/qdivrem.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/quad.h [new file with mode: 0644]
ubuntu/vbox/vboxsf/r0drv [new symlink]
ubuntu/vbox/vboxsf/regops.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/revision-generated.h [new file with mode: 0644]
ubuntu/vbox/vboxsf/udivdi3.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/udivmoddi4.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/umoddi3.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/utils.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/vbsfmount.h [new file with mode: 0644]
ubuntu/vbox/vboxsf/version-generated.h [new file with mode: 0644]
ubuntu/vbox/vboxsf/vfsmod.c [new file with mode: 0644]
ubuntu/vbox/vboxsf/vfsmod.h [new file with mode: 0644]
ubuntu/vbox/vboxvideo/HGSMIBase.c [new file with mode: 0644]
ubuntu/vbox/vboxvideo/HGSMICommon.c [new file with mode: 0644]
ubuntu/vbox/vboxvideo/HGSMIMemAlloc.c [new file with mode: 0644]
ubuntu/vbox/vboxvideo/Makefile [new file with mode: 0644]
ubuntu/vbox/vboxvideo/Makefile.include.footer [new file with mode: 0644]
ubuntu/vbox/vboxvideo/Makefile.include.header [new file with mode: 0644]
ubuntu/vbox/vboxvideo/Modesetting.c [new file with mode: 0644]
ubuntu/vbox/vboxvideo/VBVABase.c [new file with mode: 0644]
ubuntu/vbox/vboxvideo/heapoffset.c [new file with mode: 0644]
ubuntu/vbox/vboxvideo/include [new symlink]
ubuntu/vbox/vboxvideo/product-generated.h [new file with mode: 0644]
ubuntu/vbox/vboxvideo/r0drv [new symlink]
ubuntu/vbox/vboxvideo/revision-generated.h [new file with mode: 0644]
ubuntu/vbox/vboxvideo/vbox_drv.c [new file with mode: 0644]
ubuntu/vbox/vboxvideo/vbox_drv.h [new file with mode: 0644]
ubuntu/vbox/vboxvideo/vbox_dummy.c [new file with mode: 0644]
ubuntu/vbox/vboxvideo/vbox_fb.c [new file with mode: 0644]
ubuntu/vbox/vboxvideo/vbox_irq.c [new file with mode: 0644]
ubuntu/vbox/vboxvideo/vbox_main.c [new file with mode: 0644]
ubuntu/vbox/vboxvideo/vbox_mode.c [new file with mode: 0644]
ubuntu/vbox/vboxvideo/vbox_prime.c [new file with mode: 0644]
ubuntu/vbox/vboxvideo/vbox_ttm.c [new file with mode: 0644]
ubuntu/vbox/vboxvideo/version-generated.h [new file with mode: 0644]

diff --git a/ubuntu/vbox/BOM b/ubuntu/vbox/BOM
new file mode 100644 (file)
index 0000000..7695230
--- /dev/null
@@ -0,0 +1,2 @@
+Source: http://ports.ubuntu.com/pool/multiverse/v/virtualbox/virtualbox-guest-dkms_5.1.28-dfsg-1_all.deb
+Version: 5.1.28-dfsg-1
diff --git a/ubuntu/vbox/Makefile b/ubuntu/vbox/Makefile
new file mode 100644 (file)
index 0000000..8434d74
--- /dev/null
@@ -0,0 +1,3 @@
+.NOTPARALLEL:
+
+obj-m = vboxguest/ vboxsf/ vboxvideo/
diff --git a/ubuntu/vbox/dkms.conf b/ubuntu/vbox/dkms.conf
new file mode 100644 (file)
index 0000000..2da0d9f
--- /dev/null
@@ -0,0 +1,13 @@
+PACKAGE_NAME="virtualbox-guest"
+PACKAGE_VERSION="5.1.28"
+CLEAN="rm -f *.*o"
+BUILT_MODULE_NAME[0]="vboxguest"
+BUILT_MODULE_LOCATION[0]="vboxguest"
+DEST_MODULE_LOCATION[0]="/updates"
+BUILT_MODULE_NAME[1]="vboxsf"
+BUILT_MODULE_LOCATION[1]="vboxsf"
+DEST_MODULE_LOCATION[1]="/updates"
+BUILT_MODULE_NAME[2]="vboxvideo"
+BUILT_MODULE_LOCATION[2]="vboxvideo"
+DEST_MODULE_LOCATION[2]="/updates"
+AUTOINSTALL="yes"
diff --git a/ubuntu/vbox/include/VBox/HGSMI/HGSMI.h b/ubuntu/vbox/include/VBox/HGSMI/HGSMI.h
new file mode 100644 (file)
index 0000000..3938904
--- /dev/null
@@ -0,0 +1,264 @@
+/** @file
+ *
+ * VBox Host Guest Shared Memory Interface (HGSMI).
+ * Host/Guest shared part.
+ */
+
+/*
+ * 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.
+ */
+
+
+#ifndef ___VBox_HGSMI_HGSMI_h
+#define ___VBox_HGSMI_HGSMI_h
+
+#include <iprt/assert.h>
+#include <iprt/types.h>
+
+#include <VBox/HGSMI/HGSMIDefs.h>
+#include <VBox/HGSMI/HGSMIChannels.h>
+#include <VBox/HGSMI/HGSMIMemAlloc.h>
+
+/*
+ * Basic mechanism for the HGSMI is to prepare and pass data buffer to the host and the guest.
+ * Data inside these buffers are opaque for the HGSMI and are interpreted by higher levels.
+ *
+ * Every shared memory buffer passed between the guest/host has the following structure:
+ *
+ * HGSMIBUFFERHEADER header;
+ * uint8_t data[header.u32BufferSize];
+ * HGSMIBUFFERTAIL tail;
+ *
+ * Note: Offset of the 'header' in the memory is used for virtual hardware IO.
+ *
+ * Buffers are verifyed using the offset and the content of the header and the tail,
+ * which are constant during a call.
+ *
+ * Invalid buffers are ignored.
+ *
+ * Actual 'data' is not verifyed, as it is expected that the data can be changed by the
+ * called function.
+ *
+ * Since only the offset of the buffer is passed in a IO operation, the header and tail
+ * must contain:
+ *     * size of data in this buffer;
+ *     * checksum for buffer verification.
+ *
+ * For segmented transfers:
+ *     * the sequence identifier;
+ *     * offset of the current segment in the sequence;
+ *     * total bytes in the transfer.
+ *
+ * Additionally contains:
+ *     * the channel ID;
+ *     * the channel information.
+ */
+
+typedef struct HGSMIHEAP
+{
+    HGSMIAREA area; /* Description. */
+    HGSMIMADATA ma; /* Memory allocator */
+} HGSMIHEAP;
+
+/* The size of the array of channels. Array indexes are uint8_t. Note: the value must not be changed. */
+#define HGSMI_NUMBER_OF_CHANNELS 0x100
+
+/* Channel handler called when the guest submits a buffer. */
+typedef DECLCALLBACK(int) FNHGSMICHANNELHANDLER(void *pvHandler, uint16_t u16ChannelInfo, void *pvBuffer, HGSMISIZE cbBuffer);
+typedef FNHGSMICHANNELHANDLER *PFNHGSMICHANNELHANDLER;
+
+/* Information about a handler: pfn + context. */
+typedef struct _HGSMICHANNELHANDLER
+{
+    PFNHGSMICHANNELHANDLER pfnHandler;
+    void *pvHandler;
+} HGSMICHANNELHANDLER;
+
+/* Channel description. */
+typedef struct _HGSMICHANNEL
+{
+    HGSMICHANNELHANDLER handler;       /* The channel handler. */
+    const char *pszName;               /* NULL for hardcoded channels or RTStrDup'ed name. */
+    uint8_t u8Channel;                 /* The channel id, equal to the channel index in the array. */
+    uint8_t u8Flags;                   /* HGSMI_CH_F_* */
+} HGSMICHANNEL;
+
+typedef struct _HGSMICHANNELINFO
+{
+    HGSMICHANNEL Channels[HGSMI_NUMBER_OF_CHANNELS]; /* Channel handlers indexed by the channel id.
+                                                      * The array is accessed under the instance lock.
+                                                      */
+}  HGSMICHANNELINFO;
+
+
+RT_C_DECLS_BEGIN
+
+DECLINLINE(HGSMIBUFFERHEADER *) HGSMIBufferHeaderFromPtr(void *pvBuffer)
+{
+    return (HGSMIBUFFERHEADER *)pvBuffer;
+}
+
+DECLINLINE(uint8_t *) HGSMIBufferDataFromPtr(void *pvBuffer)
+{
+    return (uint8_t *)pvBuffer + sizeof(HGSMIBUFFERHEADER);
+}
+
+DECLINLINE(HGSMIBUFFERTAIL *) HGSMIBufferTailFromPtr(void *pvBuffer,
+                                                     uint32_t u32DataSize)
+{
+    return (HGSMIBUFFERTAIL *)(HGSMIBufferDataFromPtr(pvBuffer) + u32DataSize);
+}
+
+DECLINLINE(HGSMISIZE) HGSMIBufferMinimumSize(void)
+{
+    return sizeof(HGSMIBUFFERHEADER) + sizeof(HGSMIBUFFERTAIL);
+}
+
+DECLINLINE(HGSMIBUFFERHEADER *) HGSMIBufferHeaderFromData(const void *pvData)
+{
+    return (HGSMIBUFFERHEADER *)((uint8_t *)pvData - sizeof(HGSMIBUFFERHEADER));
+}
+
+DECLINLINE(HGSMISIZE) HGSMIBufferRequiredSize(uint32_t u32DataSize)
+{
+    return HGSMIBufferMinimumSize() + u32DataSize;
+}
+
+DECLINLINE(HGSMIOFFSET) HGSMIPointerToOffset(const HGSMIAREA *pArea,
+                                             const void *pv)
+{
+    return pArea->offBase + (HGSMIOFFSET)((uint8_t *)pv - pArea->pu8Base);
+}
+
+DECLINLINE(void *) HGSMIOffsetToPointer(const HGSMIAREA *pArea,
+                                        HGSMIOFFSET offBuffer)
+{
+    return pArea->pu8Base + (offBuffer - pArea->offBase);
+}
+
+DECLINLINE(uint8_t *) HGSMIBufferDataFromOffset(const HGSMIAREA *pArea,
+                                                HGSMIOFFSET offBuffer)
+{
+    void *pvBuffer = HGSMIOffsetToPointer(pArea, offBuffer);
+    return HGSMIBufferDataFromPtr(pvBuffer);
+}
+
+DECLINLINE(HGSMIOFFSET) HGSMIBufferOffsetFromData(const HGSMIAREA *pArea,
+                                                  void *pvData)
+{
+    HGSMIBUFFERHEADER *pHeader = HGSMIBufferHeaderFromData(pvData);
+    return HGSMIPointerToOffset(pArea, pHeader);
+}
+
+DECLINLINE(uint8_t *) HGSMIBufferDataAndChInfoFromOffset(const HGSMIAREA *pArea,
+                                                         HGSMIOFFSET offBuffer,
+                                                         uint16_t *pu16ChannelInfo)
+{
+    HGSMIBUFFERHEADER *pHeader = (HGSMIBUFFERHEADER *)HGSMIOffsetToPointer(pArea, offBuffer);
+    *pu16ChannelInfo = pHeader->u16ChannelInfo;
+    return HGSMIBufferDataFromPtr(pHeader);
+}
+
+uint32_t HGSMIChecksum(HGSMIOFFSET offBuffer,
+                       const HGSMIBUFFERHEADER *pHeader,
+                       const HGSMIBUFFERTAIL *pTail);
+
+int HGSMIAreaInitialize(HGSMIAREA *pArea,
+                        void *pvBase,
+                        HGSMISIZE cbArea,
+                        HGSMIOFFSET offBase);
+
+void HGSMIAreaClear(HGSMIAREA *pArea);
+
+DECLINLINE(bool) HGSMIAreaContainsOffset(const HGSMIAREA *pArea, HGSMIOFFSET off)
+{
+    return off >= pArea->offBase && off - pArea->offBase < pArea->cbArea;
+}
+
+DECLINLINE(bool) HGSMIAreaContainsPointer(const HGSMIAREA *pArea, const void *pv)
+{
+    return (uintptr_t)pv >= (uintptr_t)pArea->pu8Base && (uintptr_t)pv - (uintptr_t)pArea->pu8Base < pArea->cbArea;
+}
+
+HGSMIOFFSET HGSMIBufferInitializeSingle(const HGSMIAREA *pArea,
+                                        HGSMIBUFFERHEADER *pHeader,
+                                        HGSMISIZE cbBuffer,
+                                        uint8_t u8Channel,
+                                        uint16_t u16ChannelInfo);
+
+int HGSMIHeapSetup(HGSMIHEAP *pHeap,
+                   void *pvBase,
+                   HGSMISIZE cbArea,
+                   HGSMIOFFSET offBase,
+                   const HGSMIENV *pEnv);
+
+void HGSMIHeapDestroy(HGSMIHEAP *pHeap);
+
+void *HGSMIHeapBufferAlloc(HGSMIHEAP *pHeap,
+                           HGSMISIZE cbBuffer);
+
+void HGSMIHeapBufferFree(HGSMIHEAP *pHeap,
+                         void *pvBuf);
+
+void *HGSMIHeapAlloc(HGSMIHEAP *pHeap,
+                     HGSMISIZE cbData,
+                     uint8_t u8Channel,
+                     uint16_t u16ChannelInfo);
+
+void HGSMIHeapFree(HGSMIHEAP *pHeap,
+                   void *pvData);
+
+DECLINLINE(const HGSMIAREA *) HGSMIHeapArea(HGSMIHEAP *pHeap)
+{
+    return &pHeap->area;
+}
+
+DECLINLINE(HGSMIOFFSET) HGSMIHeapOffset(HGSMIHEAP *pHeap)
+{
+    return HGSMIHeapArea(pHeap)->offBase;
+}
+
+DECLINLINE(HGSMISIZE) HGSMIHeapSize(HGSMIHEAP *pHeap)
+{
+    return HGSMIHeapArea(pHeap)->cbArea;
+}
+
+DECLINLINE(HGSMIOFFSET) HGSMIHeapBufferOffset(HGSMIHEAP *pHeap,
+                                              void *pvData)
+{
+    return HGSMIBufferOffsetFromData(HGSMIHeapArea(pHeap), pvData);
+}
+
+HGSMICHANNEL *HGSMIChannelFindById(HGSMICHANNELINFO *pChannelInfo,
+                                   uint8_t u8Channel);
+
+int HGSMIChannelRegister(HGSMICHANNELINFO *pChannelInfo,
+                         uint8_t u8Channel,
+                         const char *pszName,
+                         PFNHGSMICHANNELHANDLER pfnChannelHandler,
+                         void *pvChannelHandler);
+
+int HGSMIBufferProcess(const HGSMIAREA *pArea,
+                       HGSMICHANNELINFO *pChannelInfo,
+                       HGSMIOFFSET offBuffer);
+RT_C_DECLS_END
+
+#endif /* !___VBox_HGSMI_HGSMI_h */
+
diff --git a/ubuntu/vbox/include/VBox/HGSMI/HGSMIChSetup.h b/ubuntu/vbox/include/VBox/HGSMI/HGSMIChSetup.h
new file mode 100644 (file)
index 0000000..cf9ca94
--- /dev/null
@@ -0,0 +1,77 @@
+/** @file
+ * VBox Host Guest Shared Memory Interface (HGSMI), sHost/Guest shared part.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBox_HGSMI_HGSMIChSetup_h
+#define ___VBox_HGSMI_HGSMIChSetup_h
+
+#include <VBox/HGSMI/HGSMI.h>
+
+/* HGSMI setup and configuration channel commands and data structures. */
+#define HGSMI_CC_HOST_FLAGS_LOCATION 0 /* Tell the host the location of HGSMIHOSTFLAGS structure,
+                                        * where the host can write information about pending
+                                        * buffers, etc, and which can be quickly polled by
+                                        * the guest without a need to port IO.
+                                        */
+
+typedef struct HGSMIBUFFERLOCATION
+{
+    HGSMIOFFSET offLocation;
+    HGSMISIZE   cbLocation;
+} HGSMIBUFFERLOCATION;
+AssertCompileSize(HGSMIBUFFERLOCATION, 8);
+
+/* HGSMI setup and configuration data structures. */
+/* host->guest commands pending, should be accessed under FIFO lock only */
+#define HGSMIHOSTFLAGS_COMMANDS_PENDING    UINT32_C(0x1)
+/* IRQ is fired, should be accessed under VGAState::lock only  */
+#define HGSMIHOSTFLAGS_IRQ                 UINT32_C(0x2)
+#ifdef VBOX_WITH_WDDM
+/* one or more guest commands is completed, should be accessed under FIFO lock only */
+# define HGSMIHOSTFLAGS_GCOMMAND_COMPLETED UINT32_C(0x4)
+/* watchdog timer interrupt flag (used for debugging), should be accessed under VGAState::lock only */
+# define HGSMIHOSTFLAGS_WATCHDOG           UINT32_C(0x8)
+#endif
+/* vsync interrupt flag, should be accessed under VGAState::lock only */
+#define HGSMIHOSTFLAGS_VSYNC               UINT32_C(0x10)
+/** monitor hotplug flag, should be accessed under VGAState::lock only */
+#define HGSMIHOSTFLAGS_HOTPLUG             UINT32_C(0x20)
+/** Cursor capability state change flag, should be accessed under
+ * VGAState::lock only.  @see VBVACONF32. */
+#define HGSMIHOSTFLAGS_CURSOR_CAPABILITIES UINT32_C(0x40)
+
+typedef struct HGSMIHOSTFLAGS
+{
+    /* host flags can be accessed and modified in multiple threads concurrently,
+     * e.g. CrOpenGL HGCM and GUI threads when to completing HGSMI 3D and Video Accel respectively,
+     * EMT thread when dealing with HGSMI command processing, etc.
+     * Besides settings/cleaning flags atomically, some each flag has its own special sync restrictions,
+     * see commants for flags definitions above */
+    volatile uint32_t u32HostFlags;
+    uint32_t au32Reserved[3];
+} HGSMIHOSTFLAGS;
+AssertCompileSize(HGSMIHOSTFLAGS, 16);
+
+#endif
+
diff --git a/ubuntu/vbox/include/VBox/HGSMI/HGSMIChannels.h b/ubuntu/vbox/include/VBox/HGSMI/HGSMIChannels.h
new file mode 100644 (file)
index 0000000..1d992fb
--- /dev/null
@@ -0,0 +1,64 @@
+/** @file
+ *
+ * VBox Host Guest Shared Memory Interface (HGSMI).
+ * Host/Guest shared part.
+ * Channel identifiers.
+ */
+
+/*
+ * 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.
+ */
+
+
+#ifndef __HGSMIChannels_h__
+#define __HGSMIChannels_h__
+
+
+/* Each channel has an 8 bit identifier. There are a number of predefined
+ * (hardcoded) channels.
+ *
+ * HGSMI_CH_HGSMI channel can be used to map a string channel identifier
+ * to a free 16 bit numerical value. values are allocated in range
+ * [HGSMI_CH_STRING_FIRST;HGSMI_CH_STRING_LAST].
+ *
+ */
+
+
+/* Predefined channel identifiers. Used internally by VBOX to simplify the channel setup. */
+#define HGSMI_CH_RESERVED     (0x00) /* A reserved channel value. */
+
+#define HGSMI_CH_HGSMI        (0x01) /* HGCMI: setup and configuration channel. */
+
+#define HGSMI_CH_VBVA         (0x02) /* Graphics: VBVA. */
+#define HGSMI_CH_SEAMLESS     (0x03) /* Graphics: Seamless with a single guest region. */
+#define HGSMI_CH_SEAMLESS2    (0x04) /* Graphics: Seamless with separate host windows. */
+#define HGSMI_CH_OPENGL       (0x05) /* Graphics: OpenGL HW acceleration. */
+
+
+/* Dynamically allocated channel identifiers. */
+#define HGSMI_CH_STRING_FIRST (0x20) /* The first channel index to be used for string mappings (inclusive). */
+#define HGSMI_CH_STRING_LAST  (0xff) /* The last channel index for string mappings (inclusive). */
+
+
+/* Check whether the channel identifier is allocated for a dynamic channel. */
+#define HGSMI_IS_DYNAMIC_CHANNEL(_channel) (((uint8_t)(_channel) & 0xE0) != 0)
+
+
+#endif /* !__HGSMIChannels_h__*/
diff --git a/ubuntu/vbox/include/VBox/HGSMI/HGSMIDefs.h b/ubuntu/vbox/include/VBox/HGSMI/HGSMIDefs.h
new file mode 100644 (file)
index 0000000..50b6595
--- /dev/null
@@ -0,0 +1,123 @@
+/** @file
+ *
+ * VBox Host Guest Shared Memory Interface (HGSMI).
+ * Host/Guest shared part: types and defines.
+ */
+
+/*
+ * 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.
+ */
+
+
+#ifndef ___VBox_HGSMI_HGSMIDefs_h
+#define ___VBox_HGSMI_HGSMIDefs_h
+
+#include <iprt/assert.h>
+#include <iprt/types.h>
+
+/* HGSMI uses 32 bit offsets and sizes. */
+typedef uint32_t HGSMISIZE;
+typedef uint32_t HGSMIOFFSET;
+
+#define HGSMIOFFSET_VOID ((HGSMIOFFSET)~0)
+
+/* Describes a shared memory area buffer.
+ * Used for calculations with offsets and for buffers verification.
+ */
+typedef struct HGSMIAREA
+{
+    uint8_t     *pu8Base; /* The starting address of the area. Corresponds to offset 'offBase'. */
+    HGSMIOFFSET  offBase; /* The starting offset of the area. */
+    HGSMIOFFSET  offLast; /* The last valid offset:
+                           * offBase + cbArea - 1 - (sizeof(header) + sizeof(tail)).
+                           */
+    HGSMISIZE    cbArea;  /* Size of the area. */
+} HGSMIAREA;
+
+
+/* The buffer description flags. */
+#define HGSMI_BUFFER_HEADER_F_SEQ_MASK     0x03 /* Buffer sequence type mask. */
+#define HGSMI_BUFFER_HEADER_F_SEQ_SINGLE   0x00 /* Single buffer, not a part of a sequence. */
+#define HGSMI_BUFFER_HEADER_F_SEQ_START    0x01 /* The first buffer in a sequence. */
+#define HGSMI_BUFFER_HEADER_F_SEQ_CONTINUE 0x02 /* A middle buffer in a sequence. */
+#define HGSMI_BUFFER_HEADER_F_SEQ_END      0x03 /* The last buffer in a sequence. */
+
+
+#pragma pack(1)
+/* 16 bytes buffer header. */
+typedef struct HGSMIBUFFERHEADER
+{
+    uint32_t    u32DataSize;            /* Size of data that follows the header. */
+
+    uint8_t     u8Flags;                /* The buffer description: HGSMI_BUFFER_HEADER_F_* */
+
+    uint8_t     u8Channel;              /* The channel the data must be routed to. */
+    uint16_t    u16ChannelInfo;         /* Opaque to the HGSMI, used by the channel. */
+
+    union {
+        uint8_t au8Union[8];            /* Opaque placeholder to make the union 8 bytes. */
+
+        struct
+        {                               /* HGSMI_BUFFER_HEADER_F_SEQ_SINGLE */
+            uint32_t u32Reserved1;      /* A reserved field, initialize to 0. */
+            uint32_t u32Reserved2;      /* A reserved field, initialize to 0. */
+        } Buffer;
+
+        struct
+        {                               /* HGSMI_BUFFER_HEADER_F_SEQ_START */
+            uint32_t u32SequenceNumber; /* The sequence number, the same for all buffers in the sequence. */
+            uint32_t u32SequenceSize;   /* The total size of the sequence. */
+        } SequenceStart;
+
+        struct
+        {                               /* HGSMI_BUFFER_HEADER_F_SEQ_CONTINUE and HGSMI_BUFFER_HEADER_F_SEQ_END */
+            uint32_t u32SequenceNumber; /* The sequence number, the same for all buffers in the sequence. */
+            uint32_t u32SequenceOffset; /* Data offset in the entire sequence. */
+        } SequenceContinue;
+    } u;
+} HGSMIBUFFERHEADER;
+
+/* 8 bytes buffer tail. */
+typedef struct HGSMIBUFFERTAIL
+{
+    uint32_t    u32Reserved;        /* Reserved, must be initialized to 0. */
+    uint32_t    u32Checksum;        /* Verifyer for the buffer header and offset and for first 4 bytes of the tail. */
+} HGSMIBUFFERTAIL;
+#pragma pack()
+
+AssertCompileSize(HGSMIBUFFERHEADER, 16);
+AssertCompileSize(HGSMIBUFFERTAIL, 8);
+
+/* The size of the array of channels. Array indexes are uint8_t. Note: the value must not be changed. */
+#define HGSMI_NUMBER_OF_CHANNELS 0x100
+
+typedef struct HGSMIENV
+{
+    /* Environment context pointer. */
+    void *pvEnv;
+
+    /* Allocate system memory. */
+    DECLCALLBACKMEMBER(void *, pfnAlloc)(void *pvEnv, HGSMISIZE cb);
+
+    /* Free system memory. */
+    DECLCALLBACKMEMBER(void, pfnFree)(void *pvEnv, void *pv);
+} HGSMIENV;
+
+#endif /* !___VBox_HGSMI_HGSMIDefs_h */
diff --git a/ubuntu/vbox/include/VBox/HGSMI/HGSMIMemAlloc.h b/ubuntu/vbox/include/VBox/HGSMI/HGSMIMemAlloc.h
new file mode 100644 (file)
index 0000000..8273676
--- /dev/null
@@ -0,0 +1,100 @@
+/** @file
+ *
+ * VBox Host Guest Shared Memory Interface (HGSMI).
+ * Memory allocator.
+ */
+
+/*
+ * Copyright (C) 2014-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.
+ */
+
+
+#ifndef ___VBox_HGSMI_HGSMIMemAlloc_h
+#define ___VBox_HGSMI_HGSMIMemAlloc_h
+
+#include <VBox/HGSMI/HGSMIDefs.h>
+#include <iprt/list.h>
+
+
+/* Descriptor. */
+#define HGSMI_MA_DESC_OFFSET_MASK UINT32_C(0xFFFFFFE0)
+#define HGSMI_MA_DESC_FREE_MASK   UINT32_C(0x00000010)
+#define HGSMI_MA_DESC_ORDER_MASK  UINT32_C(0x0000000F)
+
+#define HGSMI_MA_DESC_OFFSET(d)  ((d) & HGSMI_MA_DESC_OFFSET_MASK)
+#define HGSMI_MA_DESC_IS_FREE(d) (((d) & HGSMI_MA_DESC_FREE_MASK) != 0)
+#define HGSMI_MA_DESC_ORDER(d)   ((d) & HGSMI_MA_DESC_ORDER_MASK)
+
+#define HGSMI_MA_DESC_ORDER_BASE UINT32_C(5)
+
+#define HGSMI_MA_BLOCK_SIZE_MIN (UINT32_C(1) << (HGSMI_MA_DESC_ORDER_BASE + 0))
+#define HGSMI_MA_BLOCK_SIZE_MAX (UINT32_C(1) << (HGSMI_MA_DESC_ORDER_BASE + HGSMI_MA_DESC_ORDER_MASK))
+
+/* HGSMI_MA_DESC_ORDER_BASE must correspond to HGSMI_MA_DESC_OFFSET_MASK. */
+AssertCompile((~HGSMI_MA_DESC_OFFSET_MASK + 1) == HGSMI_MA_BLOCK_SIZE_MIN);
+
+
+typedef struct HGSMIMABLOCK
+{
+    RTLISTNODE nodeBlock;
+    RTLISTNODE nodeFree;
+    HGSMIOFFSET descriptor;
+} HGSMIMABLOCK;
+
+typedef struct HGSMIMADATA
+{
+    HGSMIAREA area;
+    HGSMIENV env;
+    HGSMISIZE cbMaxBlock;
+
+    uint32_t cBlocks;                                           /* How many blocks in the listBlocks. */
+    RTLISTANCHOR listBlocks;                                    /* All memory blocks, sorted. */
+    RTLISTANCHOR aListFreeBlocks[HGSMI_MA_DESC_ORDER_MASK + 1]; /* For free blocks of each order. */
+} HGSMIMADATA;
+
+RT_C_DECLS_BEGIN
+
+int HGSMIMAInit(HGSMIMADATA *pMA, const HGSMIAREA *pArea,
+                HGSMIOFFSET *paDescriptors, uint32_t cDescriptors, HGSMISIZE cbMaxBlock,
+                const HGSMIENV *pEnv);
+void HGSMIMAUninit(HGSMIMADATA *pMA);
+
+void *HGSMIMAAlloc(HGSMIMADATA *pMA, HGSMISIZE cb);
+void HGSMIMAFree(HGSMIMADATA *pMA, void *pv);
+
+HGSMIMABLOCK *HGSMIMASearchOffset(HGSMIMADATA *pMA, HGSMIOFFSET off);
+
+uint32_t HGSMIPopCnt32(uint32_t u32);
+
+DECLINLINE(HGSMISIZE) HGSMIMAOrder2Size(HGSMIOFFSET order)
+{
+    return (UINT32_C(1) << (HGSMI_MA_DESC_ORDER_BASE + order));
+}
+
+DECLINLINE(HGSMIOFFSET) HGSMIMASize2Order(HGSMISIZE cb)
+{
+    HGSMIOFFSET order = HGSMIPopCnt32(cb - 1) - HGSMI_MA_DESC_ORDER_BASE;
+    Assert(HGSMIMAOrder2Size(order) == cb);
+    return order;
+}
+
+RT_C_DECLS_END
+
+#endif /* !___VBox_HGSMI_HGSMIMemAlloc_h */
diff --git a/ubuntu/vbox/include/VBox/Hardware/VBoxVideoVBE.h b/ubuntu/vbox/include/VBox/Hardware/VBoxVideoVBE.h
new file mode 100644 (file)
index 0000000..988ce83
--- /dev/null
@@ -0,0 +1,87 @@
+/** @file
+ * VirtualBox graphics card port I/O 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.
+ */
+
+#ifndef ___VBox_Hardware_VBoxVideoVBE_h
+#define ___VBox_Hardware_VBoxVideoVBE_h
+
+/* GUEST <-> HOST Communication API */
+
+/** @todo FIXME: Either dynamicly ask host for this or put somewhere high in
+ *               physical memory like 0xE0000000. */
+
+#define VBE_DISPI_BANK_ADDRESS          0xA0000
+#define VBE_DISPI_BANK_SIZE_KB          64
+
+#define VBE_DISPI_MAX_XRES              16384
+#define VBE_DISPI_MAX_YRES              16384
+#define VBE_DISPI_MAX_BPP               32
+
+#define VBE_DISPI_IOPORT_INDEX          0x01CE
+#define VBE_DISPI_IOPORT_DATA           0x01CF
+
+#define VBE_DISPI_IOPORT_DAC_WRITE_INDEX  0x03C8
+#define VBE_DISPI_IOPORT_DAC_DATA         0x03C9
+
+#define VBE_DISPI_INDEX_ID              0x0
+#define VBE_DISPI_INDEX_XRES            0x1
+#define VBE_DISPI_INDEX_YRES            0x2
+#define VBE_DISPI_INDEX_BPP             0x3
+#define VBE_DISPI_INDEX_ENABLE          0x4
+#define VBE_DISPI_INDEX_BANK            0x5
+#define VBE_DISPI_INDEX_VIRT_WIDTH      0x6
+#define VBE_DISPI_INDEX_VIRT_HEIGHT     0x7
+#define VBE_DISPI_INDEX_X_OFFSET        0x8
+#define VBE_DISPI_INDEX_Y_OFFSET        0x9
+#define VBE_DISPI_INDEX_VBOX_VIDEO      0xa
+#define VBE_DISPI_INDEX_FB_BASE_HI      0xb
+
+#define VBE_DISPI_ID0                   0xB0C0
+#define VBE_DISPI_ID1                   0xB0C1
+#define VBE_DISPI_ID2                   0xB0C2
+#define VBE_DISPI_ID3                   0xB0C3
+#define VBE_DISPI_ID4                   0xB0C4
+
+#define VBE_DISPI_ID_VBOX_VIDEO         0xBE00
+/* The VBOX interface id. Indicates support for VBVA shared memory interface. */
+#define VBE_DISPI_ID_HGSMI              0xBE01
+#define VBE_DISPI_ID_ANYX               0xBE02
+
+#define VBE_DISPI_DISABLED              0x00
+#define VBE_DISPI_ENABLED               0x01
+#define VBE_DISPI_GETCAPS               0x02
+#define VBE_DISPI_8BIT_DAC              0x20
+/** @note this definition is a BOCHS legacy, used only in the video BIOS
+ *        code and ignored by the emulated hardware. */
+#define VBE_DISPI_LFB_ENABLED           0x40
+#define VBE_DISPI_NOCLEARMEM            0x80
+
+#define VGA_PORT_HGSMI_HOST             0x3b0
+#define VGA_PORT_HGSMI_GUEST            0x3d0
+
+/* this should be in sync with monitorCount <xsd:maxInclusive value="64"/> in src/VBox/Main/xml/VirtualBox-settings-common.xsd */
+#define VBOX_VIDEO_MAX_SCREENS 64
+
+#endif /* !___VBox_Hardware_VBoxVideoVBE_h */
+
diff --git a/ubuntu/vbox/include/VBox/VBoxGuest.h b/ubuntu/vbox/include/VBox/VBoxGuest.h
new file mode 100644 (file)
index 0000000..431a238
--- /dev/null
@@ -0,0 +1,565 @@
+/** @file
+ * VBoxGuest - VirtualBox Guest Additions Driver Interface. (ADD,DEV)
+ *
+ * @remarks This is in the process of being split up and usage cleaned up.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBox_VBoxGuest_h
+#define ___VBox_VBoxGuest_h
+
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <iprt/assert.h>
+#include <VBox/VMMDev2.h>
+#include <VBox/VBoxGuest2.h>
+
+
+/** @defgroup grp_vboxguest  VirtualBox Guest Additions Device Driver
+ *
+ * Also know as VBoxGuest.
+ *
+ * @{
+ */
+
+/** @defgroup grp_vboxguest_ioc  VirtualBox Guest Additions Driver Interface
+ * @{
+ */
+
+/** @todo It would be nice if we could have two defines without paths. */
+
+/** @def VBOXGUEST_DEVICE_NAME
+ * The support device name. */
+/** @def VBOXGUEST_USER_DEVICE_NAME
+ * The support device name of the user accessible device node. */
+
+#if defined(RT_OS_OS2)
+# define VBOXGUEST_DEVICE_NAME          "\\Dev\\VBoxGst$"
+
+#elif defined(RT_OS_WINDOWS)
+# define VBOXGUEST_DEVICE_NAME          "\\\\.\\VBoxGuest"
+
+/** The support service name. */
+# define VBOXGUEST_SERVICE_NAME         "VBoxGuest"
+/** Global name for Win2k+ */
+# define VBOXGUEST_DEVICE_NAME_GLOBAL   "\\\\.\\Global\\VBoxGuest"
+/** Win32 driver name */
+# define VBOXGUEST_DEVICE_NAME_NT       L"\\Device\\VBoxGuest"
+/** Device name. */
+# define VBOXGUEST_DEVICE_NAME_DOS      L"\\DosDevices\\VBoxGuest"
+
+#elif defined(RT_OS_HAIKU)
+# define VBOXGUEST_DEVICE_NAME          "/dev/misc/vboxguest"
+
+#else /* (PORTME) */
+# define VBOXGUEST_DEVICE_NAME          "/dev/vboxguest"
+# if defined(RT_OS_LINUX)
+#  define VBOXGUEST_USER_DEVICE_NAME    "/dev/vboxuser"
+# endif
+#endif
+
+#ifndef VBOXGUEST_USER_DEVICE_NAME
+# define VBOXGUEST_USER_DEVICE_NAME     VBOXGUEST_DEVICE_NAME
+#endif
+
+/** Fictive start address of the hypervisor physical memory for MmMapIoSpace. */
+#define VBOXGUEST_HYPERVISOR_PHYSICAL_START     UINT32_C(0xf8000000)
+
+#ifdef RT_OS_DARWIN
+/** Cookie used to fend off some unwanted clients to the IOService. */
+# define VBOXGUEST_DARWIN_IOSERVICE_COOKIE      UINT32_C(0x56426f78) /* 'VBox' */
+#endif
+
+#if !defined(IN_RC) && !defined(IN_RING0_AGNOSTIC) && !defined(IPRT_NO_CRT)
+
+/** @name VBoxGuest IOCTL codes and structures.
+ *
+ * The range 0..15 is for basic driver communication.
+ * The range 16..31 is for HGCM communication.
+ * The range 32..47 is reserved for future use.
+ * The range 48..63 is for OS specific communication.
+ * The 7th bit is reserved for future hacks.
+ * The 8th bit is reserved for distinguishing between 32-bit and 64-bit
+ * processes in future 64-bit guest additions.
+ *
+ * @remarks When creating new IOCtl interfaces keep in mind that not all OSes supports
+ *          reporting back the output size. (This got messed up a little bit in VBoxDrv.)
+ *
+ *          The request size is also a little bit tricky as it's passed as part of the
+ *          request code on unix. The size field is 14 bits on Linux, 12 bits on *BSD,
+ *          13 bits Darwin, and 8-bits on Solaris. All the BSDs and Darwin kernels
+ *          will make use of the size field, while Linux and Solaris will not. We're of
+ *          course using the size to validate and/or map/lock the request, so it has
+ *          to be valid.
+ *
+ *          For Solaris we will have to do something special though, 255 isn't
+ *          sufficient for all we need. A 4KB restriction (BSD) is probably not
+ *          too problematic (yet) as a general one.
+ *
+ *          More info can be found in SUPDRVIOC.h and related sources.
+ *
+ * @remarks If adding interfaces that only has input or only has output, some new macros
+ *          needs to be created so the most efficient IOCtl data buffering method can be
+ *          used.
+ * @{
+ */
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_SPARC64)
+# define VBOXGUEST_IOCTL_FLAG     128
+#elif defined(RT_ARCH_X86) || defined(RT_ARCH_SPARC)
+# define VBOXGUEST_IOCTL_FLAG     0
+#else
+# error "dunno which arch this is!"
+#endif
+/** @} */
+
+/** Ring-3 request wrapper for big requests.
+ *
+ * This is necessary because the ioctl number scheme on many Unixy OSes (esp. Solaris)
+ * only allows a relatively small size to be encoded into the request. So, for big
+ * request this generic form is used instead. */
+typedef struct VBGLBIGREQ
+{
+    /** Magic value (VBGLBIGREQ_MAGIC). */
+    uint32_t    u32Magic;
+    /** The size of the data buffer. */
+    uint32_t    cbData;
+    /** The user address of the data buffer. */
+    RTR3PTR     pvDataR3;
+#if HC_ARCH_BITS == 32
+    uint32_t    u32Padding;
+#endif
+/** @todo r=bird: We need a 'rc' field for passing VBox status codes. Reused
+ *        some input field as rc on output. */
+} VBGLBIGREQ;
+/** Pointer to a request wrapper for solaris guests. */
+typedef VBGLBIGREQ *PVBGLBIGREQ;
+/** Pointer to a const request wrapper for solaris guests. */
+typedef const VBGLBIGREQ *PCVBGLBIGREQ;
+
+/** The VBGLBIGREQ::u32Magic value (Ryuu Murakami). */
+#define VBGLBIGREQ_MAGIC                            0x19520219
+
+
+#if defined(RT_OS_WINDOWS)
+/** @todo Remove IOCTL_CODE later! Integrate it in VBOXGUEST_IOCTL_CODE below. */
+/** @todo r=bird: IOCTL_CODE is supposedly defined in some header included by Windows.h or ntddk.h, which is why it wasn't in the #if 0 earlier. See HostDrivers/Support/SUPDrvIOC.h... */
+# define IOCTL_CODE(DeviceType, Function, Method, Access, DataSize_ignored) \
+  ( ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
+# define VBOXGUEST_IOCTL_CODE_(Function, Size)      IOCTL_CODE(FILE_DEVICE_UNKNOWN, 2048 + (Function), METHOD_BUFFERED, FILE_WRITE_ACCESS, 0)
+# define VBOXGUEST_IOCTL_STRIP_SIZE(Code)           (Code)
+
+#elif defined(RT_OS_OS2)
+  /* No automatic buffering, size not encoded. */
+# define VBOXGUEST_IOCTL_CATEGORY                   0xc2
+# define VBOXGUEST_IOCTL_CODE_(Function, Size)      ((unsigned char)(Function))
+# define VBOXGUEST_IOCTL_CATEGORY_FAST              0xc3 /**< Also defined in VBoxGuestA-os2.asm. */
+# define VBOXGUEST_IOCTL_CODE_FAST_(Function)       ((unsigned char)(Function))
+# define VBOXGUEST_IOCTL_STRIP_SIZE(Code)           (Code)
+
+#elif defined(RT_OS_SOLARIS)
+  /* No automatic buffering, size limited to 255 bytes => use VBGLBIGREQ for everything. */
+# include <sys/ioccom.h>
+# define VBOXGUEST_IOCTL_CODE_(Function, Size)      _IOWRN('V', (Function), sizeof(VBGLBIGREQ))
+# define VBOXGUEST_IOCTL_CODE_FAST_(Function)       _IO(  'V', (Function))
+# define VBOXGUEST_IOCTL_STRIP_SIZE(Code)           (Code)
+
+#elif defined(RT_OS_LINUX)
+  /* No automatic buffering, size limited to 16KB. */
+# include <linux/ioctl.h>
+# define VBOXGUEST_IOCTL_CODE_(Function, Size)      _IOC(_IOC_READ|_IOC_WRITE, 'V', (Function), (Size))
+# define VBOXGUEST_IOCTL_CODE_FAST_(Function)       _IO(  'V', (Function))
+# define VBOXGUEST_IOCTL_STRIP_SIZE(Code)           VBOXGUEST_IOCTL_CODE_(_IOC_NR((Code)), 0)
+
+#elif defined(RT_OS_HAIKU)
+  /* No automatic buffering, size not encoded. */
+  /** @todo do something better */
+# define VBOXGUEST_IOCTL_CODE_(Function, Size)      (0x56420000 | (Function))
+# define VBOXGUEST_IOCTL_CODE_FAST_(Function)       (0x56420000 | (Function))
+# define VBOXGUEST_IOCTL_STRIP_SIZE(Code)           (Code)
+
+#elif defined(RT_OS_FREEBSD) || defined(RT_OS_NETBSD) /** @todo r=bird: Please do it like SUPDRVIOC to keep it as similar as possible. */
+# include <sys/ioccom.h>
+
+# define VBOXGUEST_IOCTL_CODE_(Function, Size)      _IOWR('V', (Function), VBGLBIGREQ)
+# define VBOXGUEST_IOCTL_CODE_FAST_(Function)       _IO(  'V', (Function))
+# define VBOXGUEST_IOCTL_STRIP_SIZE(Code)           IOCBASECMD(Code)
+
+#else /* BSD Like */
+  /* Automatic buffering, size limited to 4KB on *BSD and 8KB on Darwin - commands the limit, 4KB. */
+# include <sys/ioccom.h>
+# define VBOXGUEST_IOCTL_CODE_(Function, Size)      _IOC(IOC_INOUT, 'V', (Function), (Size))
+# define VBOXGUEST_IOCTL_CODE_FAST_(Function)       _IO('V', (Function))
+# define VBOXGUEST_IOCTL_STRIP_SIZE(uIOCtl)         ( (uIOCtl) & ~_IOC(0,0,0,IOCPARM_MASK) )
+#endif
+
+#define VBOXGUEST_IOCTL_CODE(Function, Size)        VBOXGUEST_IOCTL_CODE_((Function) | VBOXGUEST_IOCTL_FLAG, Size)
+#define VBOXGUEST_IOCTL_CODE_FAST(Function)         VBOXGUEST_IOCTL_CODE_FAST_((Function) | VBOXGUEST_IOCTL_FLAG)
+
+/* Define 32 bit codes to support 32 bit applications requests in the 64 bit guest driver. */
+#ifdef RT_ARCH_AMD64
+# define VBOXGUEST_IOCTL_CODE_32(Function, Size)    VBOXGUEST_IOCTL_CODE_(Function, Size)
+# define VBOXGUEST_IOCTL_CODE_FAST_32(Function)     VBOXGUEST_IOCTL_CODE_FAST_(Function)
+#endif /* RT_ARCH_AMD64 */
+
+
+
+/** IOCTL to VBoxGuest to query the VMMDev IO port region start.
+ * @remarks Ring-0 only. */
+#define VBOXGUEST_IOCTL_GETVMMDEVPORT               VBOXGUEST_IOCTL_CODE(1, sizeof(VBoxGuestPortInfo))
+
+#pragma pack(4)
+typedef struct VBoxGuestPortInfo
+{
+    uint32_t portAddress;
+    struct VMMDevMemory *pVMMDevMemory;
+} VBoxGuestPortInfo;
+
+
+/** IOCTL to VBoxGuest to wait for a VMMDev host notification */
+#define VBOXGUEST_IOCTL_WAITEVENT                   VBOXGUEST_IOCTL_CODE_(2, sizeof(VBoxGuestWaitEventInfo))
+
+/** @name Result codes for VBoxGuestWaitEventInfo::u32Result
+ * @{
+ */
+/** Successful completion, an event occurred. */
+#define VBOXGUEST_WAITEVENT_OK          (0)
+/** Successful completion, timed out. */
+#define VBOXGUEST_WAITEVENT_TIMEOUT     (1)
+/** Wait was interrupted. */
+#define VBOXGUEST_WAITEVENT_INTERRUPTED (2)
+/** An error occurred while processing the request. */
+#define VBOXGUEST_WAITEVENT_ERROR       (3)
+/** @} */
+
+/** Input and output buffers layout of the IOCTL_VBOXGUEST_WAITEVENT */
+typedef struct VBoxGuestWaitEventInfo
+{
+    /** timeout in milliseconds */
+    uint32_t u32TimeoutIn;
+    /** events to wait for */
+    uint32_t u32EventMaskIn;
+    /** result code */
+    uint32_t u32Result;
+    /** events occurred */
+    uint32_t u32EventFlagsOut;
+} VBoxGuestWaitEventInfo;
+AssertCompileSize(VBoxGuestWaitEventInfo, 16);
+
+
+/** IOCTL to VBoxGuest to perform a VMM request
+ * @remark  The data buffer for this IOCtl has an variable size, keep this in mind
+ *          on systems where this matters. */
+#define VBOXGUEST_IOCTL_VMMREQUEST(Size)            VBOXGUEST_IOCTL_CODE_(3, (Size))
+
+
+/** IOCTL to VBoxGuest to control event filter mask. */
+#define VBOXGUEST_IOCTL_CTL_FILTER_MASK             VBOXGUEST_IOCTL_CODE_(4, sizeof(VBoxGuestFilterMaskInfo))
+
+/** Input and output buffer layout of the IOCTL_VBOXGUEST_CTL_FILTER_MASK. */
+typedef struct VBoxGuestFilterMaskInfo
+{
+    uint32_t u32OrMask;
+    uint32_t u32NotMask;
+} VBoxGuestFilterMaskInfo;
+AssertCompileSize(VBoxGuestFilterMaskInfo, 8);
+#pragma pack()
+
+/** IOCTL to VBoxGuest to interrupt (cancel) any pending WAITEVENTs and return.
+ * Handled inside the guest additions and not seen by the host at all.
+ * @see VBOXGUEST_IOCTL_WAITEVENT */
+#define VBOXGUEST_IOCTL_CANCEL_ALL_WAITEVENTS       VBOXGUEST_IOCTL_CODE_(5, 0)
+
+/** IOCTL to VBoxGuest to perform backdoor logging.
+ * The argument is a string buffer of the specified size. */
+#define VBOXGUEST_IOCTL_LOG(Size)                   VBOXGUEST_IOCTL_CODE_(6, (Size))
+
+/** IOCTL to VBoxGuest to check memory ballooning.
+ * The guest kernel module / device driver will ask the host for the current size of
+ * the balloon and adjust the size. Or it will set fHandledInR0 = false and R3 is
+ * responsible for allocating memory and calling R0 (VBOXGUEST_IOCTL_CHANGE_BALLOON). */
+#define VBOXGUEST_IOCTL_CHECK_BALLOON               VBOXGUEST_IOCTL_CODE_(7, sizeof(VBoxGuestCheckBalloonInfo))
+
+/** Output buffer layout of the VBOXGUEST_IOCTL_CHECK_BALLOON. */
+typedef struct VBoxGuestCheckBalloonInfo
+{
+    /** The size of the balloon in chunks of 1MB. */
+    uint32_t cBalloonChunks;
+    /** false = handled in R0, no further action required.
+     *   true = allocate balloon memory in R3. */
+    uint32_t fHandleInR3;
+} VBoxGuestCheckBalloonInfo;
+AssertCompileSize(VBoxGuestCheckBalloonInfo, 8);
+
+
+/** IOCTL to VBoxGuest to supply or revoke one chunk for ballooning.
+ * The guest kernel module / device driver will lock down supplied memory or
+ * unlock reclaimed memory and then forward the physical addresses of the
+ * changed balloon chunk to the host. */
+#define VBOXGUEST_IOCTL_CHANGE_BALLOON              VBOXGUEST_IOCTL_CODE_(8, sizeof(VBoxGuestChangeBalloonInfo))
+
+/** Input buffer layout of the VBOXGUEST_IOCTL_CHANGE_BALLOON request.
+ * Information about a memory chunk used to inflate or deflate the balloon. */
+typedef struct VBoxGuestChangeBalloonInfo
+{
+    /** Address of the chunk. */
+    uint64_t u64ChunkAddr;
+    /** true = inflate, false = deflate. */
+    uint32_t fInflate;
+    /** Alignment padding. */
+    uint32_t u32Align;
+} VBoxGuestChangeBalloonInfo;
+AssertCompileSize(VBoxGuestChangeBalloonInfo, 16);
+
+/** IOCTL to VBoxGuest to write guest core. */
+#define VBOXGUEST_IOCTL_WRITE_CORE_DUMP             VBOXGUEST_IOCTL_CODE(9, sizeof(VBoxGuestWriteCoreDump))
+
+/** Input and output buffer layout of the VBOXGUEST_IOCTL_WRITE_CORE
+ *  request. */
+typedef struct VBoxGuestWriteCoreDump
+{
+    /** Flags (reserved, MBZ). */
+    uint32_t fFlags;
+} VBoxGuestWriteCoreDump;
+AssertCompileSize(VBoxGuestWriteCoreDump, 4);
+
+/** IOCTL to VBoxGuest to update the mouse status features. */
+# define VBOXGUEST_IOCTL_SET_MOUSE_STATUS           VBOXGUEST_IOCTL_CODE_(10, sizeof(uint32_t))
+
+#ifdef VBOX_WITH_HGCM
+/** IOCTL to VBoxGuest to connect to a HGCM service. */
+# define VBOXGUEST_IOCTL_HGCM_CONNECT               VBOXGUEST_IOCTL_CODE(16, sizeof(VBoxGuestHGCMConnectInfo))
+
+/** IOCTL to VBoxGuest to disconnect from a HGCM service. */
+# define VBOXGUEST_IOCTL_HGCM_DISCONNECT            VBOXGUEST_IOCTL_CODE(17, sizeof(VBoxGuestHGCMDisconnectInfo))
+
+/** IOCTL to VBoxGuest to make a call to a HGCM service.
+ * @see VBoxGuestHGCMCallInfo */
+# define VBOXGUEST_IOCTL_HGCM_CALL(Size)            VBOXGUEST_IOCTL_CODE(18, (Size))
+
+/** IOCTL to VBoxGuest to make a timed call to a HGCM service. */
+# define VBOXGUEST_IOCTL_HGCM_CALL_TIMED(Size)      VBOXGUEST_IOCTL_CODE(20, (Size))
+
+/** IOCTL to VBoxGuest passed from the Kernel Mode driver, but containing a user mode data in VBoxGuestHGCMCallInfo
+ * the driver received from the UM. Called in the context of the process passing the data.
+ * @see VBoxGuestHGCMCallInfo */
+# define VBOXGUEST_IOCTL_HGCM_CALL_USERDATA(Size)   VBOXGUEST_IOCTL_CODE(21, (Size))
+
+# ifdef RT_ARCH_AMD64
+/** @name IOCTL numbers that 32-bit clients, like the Windows OpenGL guest
+ *        driver, will use when taking to a 64-bit driver.
+ * @remarks These are only used by the driver implementation!
+ * @{*/
+#  define VBOXGUEST_IOCTL_HGCM_CONNECT_32           VBOXGUEST_IOCTL_CODE_32(16, sizeof(VBoxGuestHGCMConnectInfo))
+#  define VBOXGUEST_IOCTL_HGCM_DISCONNECT_32        VBOXGUEST_IOCTL_CODE_32(17, sizeof(VBoxGuestHGCMDisconnectInfo))
+#  define VBOXGUEST_IOCTL_HGCM_CALL_32(Size)        VBOXGUEST_IOCTL_CODE_32(18, (Size))
+#  define VBOXGUEST_IOCTL_HGCM_CALL_TIMED_32(Size)  VBOXGUEST_IOCTL_CODE_32(20, (Size))
+/** @} */
+# endif /* RT_ARCH_AMD64 */
+
+/** Get the pointer to the first HGCM parameter.  */
+# define VBOXGUEST_HGCM_CALL_PARMS(a)             ( (HGCMFunctionParameter   *)((uint8_t *)(a) + sizeof(VBoxGuestHGCMCallInfo)) )
+/** Get the pointer to the first HGCM parameter in a 32-bit request.  */
+# define VBOXGUEST_HGCM_CALL_PARMS32(a)           ( (HGCMFunctionParameter32 *)((uint8_t *)(a) + sizeof(VBoxGuestHGCMCallInfo)) )
+
+#endif /* VBOX_WITH_HGCM */
+
+#ifdef VBOX_WITH_DPC_LATENCY_CHECKER
+/** IOCTL to VBoxGuest to perform DPC latency tests, printing the result in
+ * the release log on the host.  Takes no data, returns no data. */
+# define VBOXGUEST_IOCTL_DPC_LATENCY_CHECKER        VBOXGUEST_IOCTL_CODE_(30, 0)
+#endif
+
+/** IOCTL to for setting the mouse driver callback. (kernel only) */
+/** @note The callback will be called in interrupt context with the VBoxGuest
+ * device event spinlock held. */
+#define VBOXGUEST_IOCTL_SET_MOUSE_NOTIFY_CALLBACK   VBOXGUEST_IOCTL_CODE(31, sizeof(VBoxGuestMouseSetNotifyCallback))
+
+typedef DECLCALLBACK(void) FNVBOXGUESTMOUSENOTIFY(void *pfnUser);
+typedef FNVBOXGUESTMOUSENOTIFY *PFNVBOXGUESTMOUSENOTIFY;
+
+/** Input buffer for VBOXGUEST_IOCTL_INTERNAL_SET_MOUSE_NOTIFY_CALLBACK. */
+typedef struct VBoxGuestMouseSetNotifyCallback
+{
+    /**
+     * Mouse notification callback.
+     *
+     * @param   pvUser      The callback argument.
+     */
+    PFNVBOXGUESTMOUSENOTIFY      pfnNotify;
+    /** The callback argument*/
+    void                       *pvUser;
+} VBoxGuestMouseSetNotifyCallback;
+
+
+typedef enum VBOXGUESTCAPSACQUIRE_FLAGS
+{
+    VBOXGUESTCAPSACQUIRE_FLAGS_NONE = 0,
+    /* configures VBoxGuest to use the specified caps in Acquire mode, w/o making any caps acquisition/release.
+     * so far it is only possible to set acquire mode for caps, but not clear it,
+     * so u32NotMask is ignored for this request */
+    VBOXGUESTCAPSACQUIRE_FLAGS_CONFIG_ACQUIRE_MODE,
+    /* to ensure enum is 32bit*/
+    VBOXGUESTCAPSACQUIRE_FLAGS_32bit = 0x7fffffff
+} VBOXGUESTCAPSACQUIRE_FLAGS;
+
+typedef struct VBoxGuestCapsAquire
+{
+    /* result status
+     * VINF_SUCCESS - on success
+     * VERR_RESOURCE_BUSY    - some caps in the u32OrMask are acquired by some other VBoxGuest connection.
+     *                         NOTE: no u32NotMask caps are cleaned in this case, i.e. no modifications are done on failure
+     * VER_INVALID_PARAMETER - invalid Caps are specified with either u32OrMask or u32NotMask. No modifications are done on failure.
+     */
+    int32_t rc;
+    /* Acquire command */
+    VBOXGUESTCAPSACQUIRE_FLAGS enmFlags;
+    /* caps to acquire, OR-ed VMMDEV_GUEST_SUPPORTS_XXX flags */
+    uint32_t u32OrMask;
+    /* caps to release, OR-ed VMMDEV_GUEST_SUPPORTS_XXX flags */
+    uint32_t u32NotMask;
+} VBoxGuestCapsAquire;
+
+/** IOCTL to for Acquiring/Releasing Guest Caps
+ * This is used for multiple purposes:
+ * 1. By doing Acquire r3 client application (e.g. VBoxTray) claims it will use
+ *    the given connection for performing operations like Seamles or Auto-resize,
+ *    thus, if the application terminates, the driver will automatically cleanup the caps reported to host,
+ *    so that host knows guest does not support them anymore
+ * 2. In a multy-user environment this will not allow r3 applications (like VBoxTray)
+ *    running in different user sessions simultaneously to interfere with each other.
+ *    An r3 client application (like VBoxTray) is responsible for Acquiring/Releasing caps properly as needed.
+ **/
+#define VBOXGUEST_IOCTL_GUEST_CAPS_ACQUIRE          VBOXGUEST_IOCTL_CODE(32, sizeof(VBoxGuestCapsAquire))
+
+/** IOCTL to VBoxGuest to set guest capabilities. */
+#define VBOXGUEST_IOCTL_SET_GUEST_CAPABILITIES      VBOXGUEST_IOCTL_CODE_(33, sizeof(VBoxGuestSetCapabilitiesInfo))
+
+/** Input and output buffer layout of the VBOXGUEST_IOCTL_SET_GUEST_CAPABILITIES
+ *  IOCtl. */
+typedef struct VBoxGuestSetCapabilitiesInfo
+{
+    uint32_t u32OrMask;
+    uint32_t u32NotMask;
+} VBoxGuestSetCapabilitiesInfo;
+AssertCompileSize(VBoxGuestSetCapabilitiesInfo, 8);
+
+
+#ifdef RT_OS_OS2
+
+/**
+ * The data buffer layout for the IDC entry point (AttachDD).
+ *
+ * @remark  This is defined in multiple 16-bit headers / sources.
+ *          Some places it's called VBGOS2IDC to short things a bit.
+ */
+typedef struct VBOXGUESTOS2IDCCONNECT
+{
+    /** VMMDEV_VERSION. */
+    uint32_t u32Version;
+    /** Opaque session handle. */
+    uint32_t u32Session;
+
+    /**
+     * The 32-bit service entry point.
+     *
+     * @returns VBox status code.
+     * @param   u32Session          The above session handle.
+     * @param   iFunction           The requested function.
+     * @param   pvData              The input/output data buffer. The caller ensures that this
+     *                              cannot be swapped out, or that it's acceptable to take a
+     *                              page in fault in the current context. If the request doesn't
+     *                              take input or produces output, apssing NULL is okay.
+     * @param   cbData              The size of the data buffer.
+     * @param   pcbDataReturned     Where to store the amount of data that's returned.
+     *                              This can be NULL if pvData is NULL.
+     */
+    DECLCALLBACKMEMBER(int, pfnServiceEP)(uint32_t u32Session, unsigned iFunction, void *pvData, size_t cbData, size_t *pcbDataReturned);
+
+    /** The 16-bit service entry point for C code (cdecl).
+     *
+     * It's the same as the 32-bit entry point, but the types has
+     * changed to 16-bit equivalents.
+     *
+     * @code
+     * int far cdecl
+     * VBoxGuestOs2IDCService16(uint32_t u32Session, uint16_t iFunction,
+     *                          void far *fpvData, uint16_t cbData, uint16_t far *pcbDataReturned);
+     * @endcode
+     */
+    RTFAR16 fpfnServiceEP;
+
+    /** The 16-bit service entry point for Assembly code (register).
+     *
+     * This is just a wrapper around fpfnServiceEP to simplify calls
+     * from 16-bit assembly code.
+     *
+     * @returns (e)ax: VBox status code; cx: The amount of data returned.
+     *
+     * @param   u32Session          eax   - The above session handle.
+     * @param   iFunction           dl    - The requested function.
+     * @param   pvData              es:bx - The input/output data buffer.
+     * @param   cbData              cx    - The size of the data buffer.
+     */
+    RTFAR16 fpfnServiceAsmEP;
+} VBOXGUESTOS2IDCCONNECT;
+/** Pointer to VBOXGUESTOS2IDCCONNECT buffer. */
+typedef VBOXGUESTOS2IDCCONNECT *PVBOXGUESTOS2IDCCONNECT;
+
+/** OS/2 specific: IDC client disconnect request.
+ *
+ * This takes no input and it doesn't return anything. Obviously this
+ * is only recognized if it arrives thru the IDC service EP.
+ */
+# define VBOXGUEST_IOCTL_OS2_IDC_DISCONNECT     VBOXGUEST_IOCTL_CODE(48, sizeof(uint32_t))
+
+#endif /* RT_OS_OS2 */
+
+#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD)
+
+/* Private IOCtls between user space and the kernel video driver.  DRM private
+ * IOCtls always have the type 'd' and a number between 0x40 and 0x99 (0x9F?) */
+
+# define VBOX_DRM_IOCTL(a) (0x40 + DRM_VBOX_ ## a)
+
+/** Stop using HGSMI in the kernel driver until it is re-enabled, so that a
+ *  user-space driver can use it.  It must be re-enabled before the kernel
+ *  driver can be used again in a sensible way. */
+/** @note These IOCtls was removed from the code, but are left here as
+ * templates as we may need similar ones in future. */
+# define DRM_VBOX_DISABLE_HGSMI    0
+# define DRM_IOCTL_VBOX_DISABLE_HGSMI    VBOX_DRM_IOCTL(DISABLE_HGSMI)
+# define VBOXVIDEO_IOCTL_DISABLE_HGSMI   _IO('d', DRM_IOCTL_VBOX_DISABLE_HGSMI)
+/** Enable HGSMI in the kernel driver after it was previously disabled. */
+# define DRM_VBOX_ENABLE_HGSMI     1
+# define DRM_IOCTL_VBOX_ENABLE_HGSMI     VBOX_DRM_IOCTL(ENABLE_HGSMI)
+# define VBOXVIDEO_IOCTL_ENABLE_HGSMI    _IO('d', DRM_IOCTL_VBOX_ENABLE_HGSMI)
+
+#endif /* RT_OS_LINUX || RT_OS_SOLARIS || RT_OS_FREEBSD */
+
+#endif /* !defined(IN_RC) && !defined(IN_RING0_AGNOSTIC) && !defined(IPRT_NO_CRT) */
+
+/** @} */
+
+/** @} */
+#endif
+
diff --git a/ubuntu/vbox/include/VBox/VBoxGuest2.h b/ubuntu/vbox/include/VBox/VBoxGuest2.h
new file mode 100644 (file)
index 0000000..6bd1f30
--- /dev/null
@@ -0,0 +1,112 @@
+/** @file
+ * VBoxGuest - VirtualBox Guest Additions Driver Interface, Mixed Up Mess.
+ * (ADD,DEV)
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBox_VBoxGuest2_h
+#define ___VBox_VBoxGuest2_h
+
+#include <iprt/assert.h>
+
+#ifdef VBOX_WITH_HGCM
+# include <VBox/VMMDev2.h>
+
+/** @addtogroup grp_vmmdev
+ * @{ */
+
+/**
+ * HGCM connect info structure.
+ *
+ * This is used by VBOXGUEST_IOCTL_HGCM_CONNECT and in VbglR0.
+ *
+ * @ingroup grp_vboxguest
+ */
+# pragma pack(1) /* explicit packing for good measure. */
+typedef struct VBoxGuestHGCMConnectInfo
+{
+    int32_t result;           /**< OUT */
+    HGCMServiceLocation Loc;  /**< IN */
+    uint32_t u32ClientID;     /**< OUT */
+} VBoxGuestHGCMConnectInfo;
+AssertCompileSize(VBoxGuestHGCMConnectInfo, 4+4+128+4);
+# pragma pack()
+
+
+/**
+ * HGCM connect info structure.
+ *
+ * This is used by VBOXGUEST_IOCTL_HGCM_DISCONNECT and in VbglR0.
+ *
+ * @ingroup grp_vboxguest
+ */
+typedef struct VBoxGuestHGCMDisconnectInfo
+{
+    int32_t result;           /**< OUT */
+    uint32_t u32ClientID;     /**< IN */
+} VBoxGuestHGCMDisconnectInfo;
+AssertCompileSize(VBoxGuestHGCMDisconnectInfo, 8);
+
+/**
+ * HGCM call info structure.
+ *
+ * This is used by VBOXGUEST_IOCTL_HGCM_CALL.
+ *
+ * @ingroup grp_vboxguest
+ */
+typedef struct VBoxGuestHGCMCallInfo
+{
+    int32_t result;           /**< OUT Host HGCM return code.*/
+    uint32_t u32ClientID;     /**< IN  The id of the caller. */
+    uint32_t u32Function;     /**< IN  Function number. */
+    uint32_t cParms;          /**< IN  How many parms. */
+    /* Parameters follow in form HGCMFunctionParameter aParms[cParms] */
+} VBoxGuestHGCMCallInfo;
+AssertCompileSize(VBoxGuestHGCMCallInfo, 16);
+
+
+/**
+ * HGCM call info structure.
+ *
+ * This is used by VBOXGUEST_IOCTL_HGCM_CALL_TIMED.
+ *
+ * @ingroup grp_vboxguest
+ */
+# pragma pack(1) /* explicit packing for good measure. */
+typedef struct VBoxGuestHGCMCallInfoTimed
+{
+    uint32_t u32Timeout;         /**< IN  How long to wait for completion before cancelling the call. */
+    uint32_t fInterruptible;     /**< IN  Is this request interruptible? */
+    VBoxGuestHGCMCallInfo info;  /**< IN/OUT The rest of the call information.  Placed after the timeout
+                                  * so that the parameters follow as they would for a normal call. */
+    /* Parameters follow in form HGCMFunctionParameter aParms[cParms] */
+} VBoxGuestHGCMCallInfoTimed;
+AssertCompileSize(VBoxGuestHGCMCallInfoTimed, 8+16);
+# pragma pack()
+
+/** @} */
+
+#endif /* VBOX_WITH_HGCM */
+
+#endif
+
diff --git a/ubuntu/vbox/include/VBox/VBoxGuestLib.h b/ubuntu/vbox/include/VBox/VBoxGuestLib.h
new file mode 100644 (file)
index 0000000..a6bd49d
--- /dev/null
@@ -0,0 +1,858 @@
+/** @file
+ * VBoxGuestLib - VirtualBox Guest Additions Library.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBox_VBoxGuestLib_h
+#define ___VBox_VBoxGuestLib_h
+
+#include <VBox/types.h>
+#include <VBox/VMMDev2.h>
+#include <VBox/VMMDev.h>     /* grumble */
+#ifdef IN_RING0
+# include <VBox/VBoxGuest.h>
+# include <VBox/VBoxGuest2.h>
+#endif
+
+
+/** @defgroup grp_vboxguest_lib     VirtualBox Guest Additions Library
+ * @ingroup grp_vboxguest
+ * @{
+ */
+
+/** @page pg_guest_lib  VirtualBox Guest Library
+ *
+ * This is a library for abstracting the additions driver interface. There are
+ * multiple versions of the library depending on the context. The main
+ * distinction is between kernel and user mode where the interfaces are very
+ * different.
+ *
+ *
+ * @section sec_guest_lib_ring0     Ring-0
+ *
+ * In ring-0 there are two version:
+ *  - VBOX_LIB_VBGL_R0_BASE / VBoxGuestR0LibBase for the VBoxGuest main driver,
+ *    who is responsible for managing the VMMDev virtual hardware.
+ *  - VBOX_LIB_VBGL_R0 / VBoxGuestR0Lib for other (client) guest drivers.
+ *
+ *
+ * The library source code and the header have a define VBGL_VBOXGUEST, which is
+ * defined for VBoxGuest and undefined for other drivers. Drivers must choose
+ * right library in their makefiles and set VBGL_VBOXGUEST accordingly.
+ *
+ * The libraries consists of:
+ *  - common code to be used by both VBoxGuest and other drivers;
+ *  - VBoxGuest specific code;
+ *  - code for other drivers which communicate with VBoxGuest via an IOCTL.
+ *
+ *
+ * @section sec_guest_lib_ring3     Ring-3
+ *
+ * There are more variants of the library here:
+ *  - VBOX_LIB_VBGL_R3 / VBoxGuestR3Lib for programs.
+ *  - VBOX_LIB_VBGL_R3_XFREE86 / VBoxGuestR3LibXFree86 for old style XFree
+ *    drivers which uses special loader and or symbol resolving strategy.
+ *  - VBOX_LIB_VBGL_R3_SHARED / VBoxGuestR3LibShared for shared objects / DLLs /
+ *    Dylibs.
+ *
+ */
+
+RT_C_DECLS_BEGIN
+
+/** HGCM client ID.
+ * @todo Promote to VBox/types.h  */
+typedef uint32_t HGCMCLIENTID;
+
+
+/** @defgroup grp_vboxguest_lib_r0     Ring-0 interface.
+ * @{
+ */
+#if defined(IN_RING0) && !defined(IN_RING0_AGNOSTIC)
+/** @def DECLR0VBGL
+ * Declare a VBGL ring-0 API with the right calling convention and visibilitiy.
+ * @param type      Return type.  */
+# ifdef RT_OS_DARWIN /** @todo probably apply to all, but don't want a forest fire on our hands right now. */
+#  define DECLR0VBGL(type) DECLHIDDEN(type) VBOXCALL
+# else
+#  define DECLR0VBGL(type) type VBOXCALL
+# endif
+# define DECLVBGL(type) DECLR0VBGL(type)
+
+
+# ifdef VBGL_VBOXGUEST
+
+/**
+ * The library initialization function to be used by the main
+ * VBoxGuest system driver.
+ *
+ * @return VBox status code.
+ */
+DECLVBGL(int) VbglInitPrimary(RTIOPORT portVMMDev, struct VMMDevMemory *pVMMDevMemory);
+
+# else
+
+/**
+ * The library initialization function to be used by all drivers
+ * other than the main VBoxGuest system driver.
+ *
+ * @return VBox status code.
+ */
+DECLVBGL(int) VbglInitClient(void);
+
+# endif
+
+/**
+ * The library termination function.
+ */
+DECLVBGL(void) VbglTerminate (void);
+
+
+/** @name Generic request functions.
+ * @{
+ */
+
+/**
+ * Allocate memory for generic request and initialize the request header.
+ *
+ * @returns VBox status code.
+ * @param   ppReq       Where to return the pointer to the allocated memory.
+ * @param   cbReq       Size of memory block required for the request.
+ * @param   enmReqType  the generic request type.
+ */
+DECLVBGL(int) VbglGRAlloc(VMMDevRequestHeader **ppReq, size_t cbReq, VMMDevRequestType enmReqType);
+
+/**
+ * Perform the generic request.
+ *
+ * @param pReq     pointer the request structure.
+ *
+ * @return VBox status code.
+ */
+DECLVBGL(int) VbglGRPerform (VMMDevRequestHeader *pReq);
+
+/**
+ * Free the generic request memory.
+ *
+ * @param pReq     pointer the request structure.
+ *
+ * @return VBox status code.
+ */
+DECLVBGL(void) VbglGRFree (VMMDevRequestHeader *pReq);
+
+/**
+ * Verify the generic request header.
+ *
+ * @param pReq     pointer the request header structure.
+ * @param cbReq    size of the request memory block. It should be equal to the request size
+ *                 for fixed size requests. It can be greater than the request size for
+ *                 variable size requests.
+ *
+ * @return VBox status code.
+ */
+DECLVBGL(int) VbglGRVerify (const VMMDevRequestHeader *pReq, size_t cbReq);
+/** @} */
+
+# ifdef VBOX_WITH_HGCM
+
+#  ifdef VBGL_VBOXGUEST
+
+/**
+ * Callback function called from HGCM helpers when a wait for request
+ * completion IRQ is required.
+ *
+ * @returns VINF_SUCCESS, VERR_INTERRUPT or VERR_TIMEOUT.
+ * @param   pvData      VBoxGuest pointer to be passed to callback.
+ * @param   u32Data     VBoxGuest 32 bit value to be passed to callback.
+ */
+typedef DECLCALLBACK(int) FNVBGLHGCMCALLBACK(VMMDevHGCMRequestHeader *pHeader, void *pvData, uint32_t u32Data);
+/** Pointer to a FNVBGLHGCMCALLBACK. */
+typedef FNVBGLHGCMCALLBACK *PFNVBGLHGCMCALLBACK;
+
+/**
+ * Perform a connect request. That is locate required service and
+ * obtain a client identifier for future access.
+ *
+ * @note This function can NOT handle cancelled requests!
+ *
+ * @param   pConnectInfo        The request data.
+ * @param   pfnAsyncCallback    Required pointer to function that is calledwhen
+ *                              host returns VINF_HGCM_ASYNC_EXECUTE. VBoxGuest
+ *                              implements waiting for an IRQ in this function.
+ * @param   pvAsyncData         An arbitrary VBoxGuest pointer to be passed to callback.
+ * @param   u32AsyncData        An arbitrary VBoxGuest 32 bit value to be passed to callback.
+ *
+ * @return  VBox status code.
+ */
+
+DECLR0VBGL(int) VbglR0HGCMInternalConnect (VBoxGuestHGCMConnectInfo *pConnectInfo,
+                                           PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);
+
+
+/**
+ * Perform a disconnect request. That is tell the host that
+ * the client will not call the service anymore.
+ *
+ * @note This function can NOT handle cancelled requests!
+ *
+ * @param   pDisconnectInfo     The request data.
+ * @param   pfnAsyncCallback    Required pointer to function that is called when
+ *                              host returns VINF_HGCM_ASYNC_EXECUTE. VBoxGuest
+ *                              implements waiting for an IRQ in this function.
+ * @param   pvAsyncData         An arbitrary VBoxGuest pointer to be passed to callback.
+ * @param   u32AsyncData        An arbitrary VBoxGuest 32 bit value to be passed to
+ *                              callback.
+ *
+ * @return  VBox status code.
+ */
+
+DECLR0VBGL(int) VbglR0HGCMInternalDisconnect (VBoxGuestHGCMDisconnectInfo *pDisconnectInfo,
+                                              PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);
+
+/** Call a HGCM service.
+ *
+ * @note This function can deal with cancelled requests.
+ *
+ * @param   pCallInfo           The request data.
+ * @param   fFlags              Flags, see VBGLR0_HGCMCALL_F_XXX.
+ * @param   pfnAsyncCallback    Required pointer to function that is called when
+ *                              host returns VINF_HGCM_ASYNC_EXECUTE. VBoxGuest
+ *                              implements waiting for an IRQ in this function.
+ * @param   pvAsyncData         An arbitrary VBoxGuest pointer to be passed to callback.
+ * @param   u32AsyncData        An arbitrary VBoxGuest 32 bit value to be passed to callback.
+ *
+ * @return VBox status code.
+ */
+DECLR0VBGL(int) VbglR0HGCMInternalCall (VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
+                                        PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);
+
+/** Call a HGCM service. (32 bits packet structure in a 64 bits guest)
+ *
+ * @note This function can deal with cancelled requests.
+ *
+ * @param   pCallInfo           The request data.
+ * @param   fFlags              Flags, see VBGLR0_HGCMCALL_F_XXX.
+ * @param   pfnAsyncCallback    Required pointer to function that is called when
+ *                              host returns VINF_HGCM_ASYNC_EXECUTE. VBoxGuest
+ *                              implements waiting for an IRQ in this function.
+ * @param   pvAsyncData         An arbitrary VBoxGuest pointer to be passed to callback.
+ * @param   u32AsyncData        An arbitrary VBoxGuest 32 bit value to be passed to callback.
+ *
+ * @return  VBox status code.
+ */
+DECLR0VBGL(int) VbglR0HGCMInternalCall32 (VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
+                                          PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);
+
+/** @name VbglR0HGCMInternalCall flags
+ * @{ */
+/** User mode request.
+ * Indicates that only user mode addresses are permitted as parameters. */
+#define VBGLR0_HGCMCALL_F_USER          UINT32_C(0)
+/** Kernel mode request.
+ * Indicates that kernel mode addresses are permitted as parameters. Whether or
+ * not user mode addresses are permitted is, unfortunately, OS specific. The
+ * following OSes allows user mode addresses: Windows, TODO.
+ */
+#define VBGLR0_HGCMCALL_F_KERNEL        UINT32_C(1)
+/** Mode mask. */
+#define VBGLR0_HGCMCALL_F_MODE_MASK     UINT32_C(1)
+/** @} */
+
+#  else  /* !VBGL_VBOXGUEST */
+
+struct VBGLHGCMHANDLEDATA;
+typedef struct VBGLHGCMHANDLEDATA *VBGLHGCMHANDLE;
+
+/** @name HGCM functions
+ * @{
+ */
+
+/**
+ * Connect to a service.
+ *
+ * @param pHandle     Pointer to variable that will hold a handle to be used
+ *                    further in VbglHGCMCall and VbglHGCMClose.
+ * @param pData       Connection information structure.
+ *
+ * @return VBox status code.
+ */
+DECLVBGL(int) VbglHGCMConnect (VBGLHGCMHANDLE *pHandle, VBoxGuestHGCMConnectInfo *pData);
+
+/**
+ * Connect to a service.
+ *
+ * @param handle      Handle of the connection.
+ * @param pData       Disconnect request information structure.
+ *
+ * @return VBox status code.
+ */
+DECLVBGL(int) VbglHGCMDisconnect (VBGLHGCMHANDLE handle, VBoxGuestHGCMDisconnectInfo *pData);
+
+/**
+ * Call to a service.
+ *
+ * @param handle      Handle of the connection.
+ * @param pData       Call request information structure, including function parameters.
+ * @param cbData      Length in bytes of data.
+ *
+ * @return VBox status code.
+ */
+DECLVBGL(int) VbglHGCMCall (VBGLHGCMHANDLE handle, VBoxGuestHGCMCallInfo *pData, uint32_t cbData);
+
+/**
+ * Call to a service with user-mode data received by the calling driver from the User-Mode process.
+ * The call must be done in the context of a calling process.
+ *
+ * @param handle      Handle of the connection.
+ * @param pData       Call request information structure, including function parameters.
+ * @param cbData      Length in bytes of data.
+ *
+ * @return VBox status code.
+ */
+DECLVBGL(int) VbglHGCMCallUserData (VBGLHGCMHANDLE handle, VBoxGuestHGCMCallInfo *pData, uint32_t cbData);
+
+/**
+ * Call to a service with timeout.
+ *
+ * @param handle      Handle of the connection.
+ * @param pData       Call request information structure, including function parameters.
+ * @param cbData      Length in bytes of data.
+ * @param cMillies    Timeout in milliseconds.  Use RT_INDEFINITE_WAIT to wait forever.
+ *
+ * @return VBox status code.
+ */
+DECLVBGL(int) VbglHGCMCallTimed(VBGLHGCMHANDLE handle, VBoxGuestHGCMCallInfoTimed *pData, uint32_t cbData);
+/** @} */
+
+/** @name Undocumented helpers for talking to the Chromium OpenGL Host Service
+ * @{ */
+typedef VBGLHGCMHANDLE VBGLCRCTLHANDLE;
+DECLVBGL(int) VbglR0CrCtlCreate(VBGLCRCTLHANDLE *phCtl);
+DECLVBGL(int) VbglR0CrCtlDestroy(VBGLCRCTLHANDLE hCtl);
+DECLVBGL(int) VbglR0CrCtlConConnect(VBGLCRCTLHANDLE hCtl, HGCMCLIENTID *pidClient);
+DECLVBGL(int) VbglR0CrCtlConDisconnect(VBGLCRCTLHANDLE hCtl, HGCMCLIENTID idClient);
+DECLVBGL(int) VbglR0CrCtlConCall(VBGLCRCTLHANDLE hCtl, struct VBoxGuestHGCMCallInfo *pCallInfo, int cbCallInfo);
+DECLVBGL(int) VbglR0CrCtlConCallUserData(VBGLCRCTLHANDLE hCtl, struct VBoxGuestHGCMCallInfo *pCallInfo, int cbCallInfo);
+/** @} */
+
+#  endif /* !VBGL_VBOXGUEST */
+
+# endif /* VBOX_WITH_HGCM */
+
+
+/**
+ * Initialize the heap.
+ *
+ * @returns VBox status code.
+ */
+DECLVBGL(int) VbglPhysHeapInit (void);
+
+/**
+ * Shutdown the heap.
+ */
+DECLVBGL(void) VbglPhysHeapTerminate (void);
+
+/**
+ * Allocate a memory block.
+ *
+ * @returns Virtual address of the allocated memory block.
+ * @param cbSize    Size of block to be allocated.
+ */
+DECLVBGL(void *) VbglPhysHeapAlloc (uint32_t cbSize);
+
+/**
+ * Get physical address of memory block pointed by the virtual address.
+ *
+ * @note WARNING!
+ *       The function does not acquire the Heap mutex!
+ *       When calling the function make sure that the pointer is a valid one and
+ *       is not being deallocated.  This function can NOT be used for verifying
+ *       if the given pointer is a valid one allocated from the heap.
+ *
+ * @param   pv      Virtual address of memory block.
+ * @returns Physical address of the memory block.
+ */
+DECLVBGL(uint32_t)  VbglPhysHeapGetPhysAddr(void *pv);
+
+/**
+ * Free a memory block.
+ *
+ * @param   pv    Virtual address of memory block.
+ */
+DECLVBGL(void)      VbglPhysHeapFree(void *pv);
+
+DECLVBGL(int) VbglQueryVMMDevMemory (VMMDevMemory **ppVMMDevMemory);
+DECLR0VBGL(bool) VbglR0CanUsePhysPageList(void);
+
+# ifndef VBOX_GUEST
+/** @name Mouse
+ * @{ */
+DECLVBGL(int)     VbglSetMouseNotifyCallback(PFNVBOXGUESTMOUSENOTIFY pfnNotify, void *pvUser);
+DECLVBGL(int)     VbglGetMouseStatus(uint32_t *pfFeatures, uint32_t *px, uint32_t *py);
+DECLVBGL(int)     VbglSetMouseStatus(uint32_t fFeatures);
+/** @}  */
+# endif /* VBOX_GUEST */
+
+#endif /* IN_RING0 && !IN_RING0_AGNOSTIC */
+
+/** @} */
+
+
+/** @defgroup grp_vboxguest_lib_r3      Ring-3 interface.
+ * @{
+ */
+#ifdef IN_RING3
+
+/** @def VBGLR3DECL
+ * Ring 3 VBGL declaration.
+ * @param   type    The return type of the function declaration.
+ */
+# define VBGLR3DECL(type) DECLHIDDEN(type) VBOXCALL
+
+/** @name General-purpose functions
+ * @{ */
+VBGLR3DECL(int)     VbglR3Init(void);
+VBGLR3DECL(int)     VbglR3InitUser(void);
+VBGLR3DECL(void)    VbglR3Term(void);
+# ifdef ___iprt_time_h
+VBGLR3DECL(int)     VbglR3GetHostTime(PRTTIMESPEC pTime);
+# endif
+VBGLR3DECL(int)     VbglR3InterruptEventWaits(void);
+VBGLR3DECL(int)     VbglR3WriteLog(const char *pch, size_t cch);
+VBGLR3DECL(int)     VbglR3CtlFilterMask(uint32_t fOr, uint32_t fNot);
+VBGLR3DECL(int)     VbglR3Daemonize(bool fNoChDir, bool fNoClose, bool fRespawn, unsigned *pcRespawn);
+VBGLR3DECL(int)     VbglR3PidFile(const char *pszPath, PRTFILE phFile);
+VBGLR3DECL(void)    VbglR3ClosePidFile(const char *pszPath, RTFILE hFile);
+VBGLR3DECL(int)     VbglR3SetGuestCaps(uint32_t fOr, uint32_t fNot);
+VBGLR3DECL(int)     VbglR3WaitEvent(uint32_t fMask, uint32_t cMillies, uint32_t *pfEvents);
+
+VBGLR3DECL(int)     VbglR3ReportAdditionsStatus(VBoxGuestFacilityType Facility, VBoxGuestFacilityStatus StatusCurrent,
+                                                uint32_t fFlags);
+VBGLR3DECL(int)     VbglR3GetAdditionsVersion(char **ppszVer, char **ppszVerEx, char **ppszRev);
+VBGLR3DECL(int)     VbglR3GetAdditionsInstallationPath(char **ppszPath);
+VBGLR3DECL(int)     VbglR3GetSessionId(uint64_t *pu64IdSession);
+
+/** @} */
+
+/** @name Shared clipboard
+ * @{ */
+VBGLR3DECL(int)     VbglR3ClipboardConnect(HGCMCLIENTID *pidClient);
+VBGLR3DECL(int)     VbglR3ClipboardDisconnect(HGCMCLIENTID idClient);
+VBGLR3DECL(int)     VbglR3ClipboardGetHostMsg(HGCMCLIENTID idClient, uint32_t *pMsg, uint32_t *pfFormats);
+VBGLR3DECL(int)     VbglR3ClipboardReadData(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb, uint32_t *pcb);
+VBGLR3DECL(int)     VbglR3ClipboardReportFormats(HGCMCLIENTID idClient, uint32_t fFormats);
+VBGLR3DECL(int)     VbglR3ClipboardWriteData(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb);
+/** @} */
+
+/** @name Seamless mode
+ * @{ */
+VBGLR3DECL(int)     VbglR3SeamlessSetCap(bool fState);
+VBGLR3DECL(int)     VbglR3SeamlessWaitEvent(VMMDevSeamlessMode *pMode);
+VBGLR3DECL(int)     VbglR3SeamlessSendRects(uint32_t cRects, PRTRECT pRects);
+VBGLR3DECL(int)     VbglR3SeamlessGetLastEvent(VMMDevSeamlessMode *pMode);
+
+/** @}  */
+
+/** @name Mouse
+ * @{ */
+VBGLR3DECL(int)     VbglR3GetMouseStatus(uint32_t *pfFeatures, uint32_t *px, uint32_t *py);
+VBGLR3DECL(int)     VbglR3SetMouseStatus(uint32_t fFeatures);
+/** @}  */
+
+/** @name Video
+ * @{ */
+VBGLR3DECL(int)     VbglR3VideoAccelEnable(bool fEnable);
+VBGLR3DECL(int)     VbglR3VideoAccelFlush(void);
+VBGLR3DECL(int)     VbglR3SetPointerShape(uint32_t fFlags, uint32_t xHot, uint32_t yHot, uint32_t cx, uint32_t cy,
+                                          const void *pvImg, size_t cbImg);
+VBGLR3DECL(int)     VbglR3SetPointerShapeReq(struct VMMDevReqMousePointer *pReq);
+/** @}  */
+
+/** @name Display
+ * @{ */
+/** The folder for the video mode hint unix domain socket on Unix-like guests.
+ * @note This can be safely changed as all users are rebuilt in lock-step. */
+#define VBGLR3HOSTDISPSOCKETPATH "/tmp/.VBoxService"
+/** The path to the video mode hint unix domain socket on Unix-like guests. */
+#define VBGLR3HOSTDISPSOCKET        VBGLR3VIDEOMODEHINTSOCKETPATH "/VideoModeHint"
+
+/** The folder for saving video mode hints to between sessions. */
+#define VBGLR3HOSTDISPSAVEDMODEPATH "/var/lib/VBoxGuestAdditions"
+/** The path to the file for saving video mode hints to between sessions. */
+#define VBGLR3HOSTDISPSAVEDMODE     VBGLR3HOSTDISPSAVEDMODEPATH "/SavedVideoModes"
+
+VBGLR3DECL(int)     VbglR3GetDisplayChangeRequest(uint32_t *pcx, uint32_t *pcy, uint32_t *pcBits, uint32_t *piDisplay,
+                                                  uint32_t *pdx, uint32_t *pdy, bool *pfEnabled, bool *pfChangeOrigin, bool fAck);
+VBGLR3DECL(bool)    VbglR3HostLikesVideoMode(uint32_t cx, uint32_t cy, uint32_t cBits);
+VBGLR3DECL(int)     VbglR3VideoModeGetHighestSavedScreen(unsigned *pcScreen);
+VBGLR3DECL(int)     VbglR3SaveVideoMode(unsigned cScreen, unsigned cx, unsigned cy, unsigned cBits,
+                                        unsigned x, unsigned y, bool fEnabled);
+VBGLR3DECL(int)     VbglR3RetrieveVideoMode(unsigned cScreen, unsigned *pcx, unsigned *pcy, unsigned *pcBits,
+                                            unsigned *px, unsigned *py, bool *pfEnabled);
+/** @}  */
+
+/** @name VM Statistics
+ * @{ */
+VBGLR3DECL(int)     VbglR3StatQueryInterval(uint32_t *pu32Interval);
+VBGLR3DECL(int)     VbglR3StatReport(VMMDevReportGuestStats *pReq);
+/** @}  */
+
+/** @name Memory ballooning
+ * @{ */
+VBGLR3DECL(int)     VbglR3MemBalloonRefresh(uint32_t *pcChunks, bool *pfHandleInR3);
+VBGLR3DECL(int)     VbglR3MemBalloonChange(void *pv, bool fInflate);
+/** @}  */
+
+/** @name Core Dump
+ * @{ */
+VBGLR3DECL(int)     VbglR3WriteCoreDump(void);
+
+/** @}  */
+
+# ifdef VBOX_WITH_GUEST_PROPS
+/** @name Guest properties
+ * @{ */
+/** @todo Docs. */
+typedef struct VBGLR3GUESTPROPENUM VBGLR3GUESTPROPENUM;
+/** @todo Docs. */
+typedef VBGLR3GUESTPROPENUM *PVBGLR3GUESTPROPENUM;
+VBGLR3DECL(int)     VbglR3GuestPropConnect(uint32_t *pidClient);
+VBGLR3DECL(int)     VbglR3GuestPropDisconnect(HGCMCLIENTID idClient);
+VBGLR3DECL(int)     VbglR3GuestPropWrite(HGCMCLIENTID idClient, const char *pszName, const char *pszValue, const char *pszFlags);
+VBGLR3DECL(int)     VbglR3GuestPropWriteValue(HGCMCLIENTID idClient, const char *pszName, const char *pszValue);
+VBGLR3DECL(int)     VbglR3GuestPropWriteValueV(HGCMCLIENTID idClient, const char *pszName,
+                                               const char *pszValueFormat, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+VBGLR3DECL(int)     VbglR3GuestPropWriteValueF(HGCMCLIENTID idClient, const char *pszName,
+                                               const char *pszValueFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+VBGLR3DECL(int)     VbglR3GuestPropRead(HGCMCLIENTID idClient, const char *pszName, void *pvBuf, uint32_t cbBuf, char **ppszValue,
+                                        uint64_t *pu64Timestamp, char **ppszFlags, uint32_t *pcbBufActual);
+VBGLR3DECL(int)     VbglR3GuestPropReadValue(uint32_t ClientId, const char *pszName, char *pszValue, uint32_t cchValue,
+                                             uint32_t *pcchValueActual);
+VBGLR3DECL(int)     VbglR3GuestPropReadValueAlloc(HGCMCLIENTID idClient, const char *pszName, char **ppszValue);
+VBGLR3DECL(void)    VbglR3GuestPropReadValueFree(char *pszValue);
+VBGLR3DECL(int)     VbglR3GuestPropEnumRaw(HGCMCLIENTID idClient, const char *paszPatterns, char *pcBuf, uint32_t cbBuf,
+                                           uint32_t *pcbBufActual);
+VBGLR3DECL(int)     VbglR3GuestPropEnum(HGCMCLIENTID idClient, char const * const *ppaszPatterns, uint32_t cPatterns,
+                                        PVBGLR3GUESTPROPENUM *ppHandle, char const **ppszName, char const **ppszValue,
+                                        uint64_t *pu64Timestamp, char const **ppszFlags);
+VBGLR3DECL(int)     VbglR3GuestPropEnumNext(PVBGLR3GUESTPROPENUM pHandle, char const **ppszName, char const **ppszValue,
+                                            uint64_t *pu64Timestamp, char const **ppszFlags);
+VBGLR3DECL(void)    VbglR3GuestPropEnumFree(PVBGLR3GUESTPROPENUM pHandle);
+VBGLR3DECL(int)     VbglR3GuestPropDelete(HGCMCLIENTID idClient, const char *pszName);
+VBGLR3DECL(int)     VbglR3GuestPropDelSet(HGCMCLIENTID idClient, char const * const *papszPatterns, uint32_t cPatterns);
+VBGLR3DECL(int)     VbglR3GuestPropWait(HGCMCLIENTID idClient, const char *pszPatterns, void *pvBuf, uint32_t cbBuf,
+                                        uint64_t u64Timestamp, uint32_t cMillies, char ** ppszName, char **ppszValue,
+                                        uint64_t *pu64Timestamp, char **ppszFlags, uint32_t *pcbBufActual);
+/** @}  */
+
+/** @name Guest user handling / reporting.
+ * @{ */
+VBGLR3DECL(int)     VbglR3GuestUserReportState(const char *pszUser, const char *pszDomain, VBoxGuestUserState enmState,
+                                               uint8_t *pbDetails, uint32_t cbDetails);
+/** @}  */
+
+/** @name Host version handling
+ * @{ */
+VBGLR3DECL(int)     VbglR3HostVersionCheckForUpdate(HGCMCLIENTID idClient, bool *pfUpdate, char **ppszHostVersion,
+                                                    char **ppszGuestVersion);
+VBGLR3DECL(int)     VbglR3HostVersionLastCheckedLoad(HGCMCLIENTID idClient, char **ppszVer);
+VBGLR3DECL(int)     VbglR3HostVersionLastCheckedStore(HGCMCLIENTID idClient, const char *pszVer);
+/** @}  */
+# endif /* VBOX_WITH_GUEST_PROPS defined */
+
+# ifdef VBOX_WITH_SHARED_FOLDERS
+/** @name Shared folders
+ * @{ */
+/**
+ * Structure containing mapping information for a shared folder.
+ */
+typedef struct VBGLR3SHAREDFOLDERMAPPING
+{
+    /** Mapping status. */
+    uint32_t u32Status;
+    /** Root handle. */
+    uint32_t u32Root;
+} VBGLR3SHAREDFOLDERMAPPING;
+/** Pointer to a shared folder mapping information structure. */
+typedef VBGLR3SHAREDFOLDERMAPPING *PVBGLR3SHAREDFOLDERMAPPING;
+/** Pointer to a const shared folder mapping information structure. */
+typedef VBGLR3SHAREDFOLDERMAPPING const *PCVBGLR3SHAREDFOLDERMAPPING;
+
+VBGLR3DECL(int)     VbglR3SharedFolderConnect(uint32_t *pidClient);
+VBGLR3DECL(int)     VbglR3SharedFolderDisconnect(HGCMCLIENTID idClient);
+VBGLR3DECL(bool)    VbglR3SharedFolderExists(HGCMCLIENTID idClient, const char *pszShareName);
+VBGLR3DECL(int)     VbglR3SharedFolderGetMappings(HGCMCLIENTID idClient, bool fAutoMountOnly,
+                                                  PVBGLR3SHAREDFOLDERMAPPING *ppaMappings, uint32_t *pcMappings);
+VBGLR3DECL(void)    VbglR3SharedFolderFreeMappings(PVBGLR3SHAREDFOLDERMAPPING paMappings);
+VBGLR3DECL(int)     VbglR3SharedFolderGetName(HGCMCLIENTID  idClient,uint32_t u32Root, char **ppszName);
+VBGLR3DECL(int)     VbglR3SharedFolderGetMountPrefix(char **ppszPrefix);
+VBGLR3DECL(int)     VbglR3SharedFolderGetMountDir(char **ppszDir);
+/** @}  */
+# endif /* VBOX_WITH_SHARED_FOLDERS defined */
+
+# ifdef VBOX_WITH_GUEST_CONTROL
+/** @name Guest control
+ * @{ */
+
+/**
+ * Structure containing the context required for
+ * either retrieving or sending a HGCM guest control
+ * commands from or to the host.
+ *
+ * Note: Do not change parameter order without also
+ *       adapting all structure initializers.
+ */
+typedef struct VBGLR3GUESTCTRLCMDCTX
+{
+    /** @todo This struct could be handy if we want to implement
+     *        a second communication channel, e.g. via TCP/IP.
+     *        Use a union for the HGCM stuff then. */
+
+    /** IN: HGCM client ID to use for
+     *      communication. */
+    uint32_t uClientID;
+    /** IN/OUT: Context ID to retrieve
+     *          or to use. */
+    uint32_t uContextID;
+    /** IN: Protocol version to use. */
+    uint32_t uProtocol;
+    /** OUT: Number of parameters retrieved. */
+    uint32_t uNumParms;
+} VBGLR3GUESTCTRLCMDCTX, *PVBGLR3GUESTCTRLCMDCTX;
+
+/* General message handling on the guest. */
+VBGLR3DECL(int) VbglR3GuestCtrlConnect(uint32_t *pidClient);
+VBGLR3DECL(int) VbglR3GuestCtrlDisconnect(uint32_t uClientId);
+VBGLR3DECL(int) VbglR3GuestCtrlMsgFilterSet(uint32_t uClientId, uint32_t uValue, uint32_t uMaskAdd, uint32_t uMaskRemove);
+VBGLR3DECL(int) VbglR3GuestCtrlMsgFilterUnset(uint32_t uClientId);
+VBGLR3DECL(int) VbglR3GuestCtrlMsgReply(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc);
+VBGLR3DECL(int) VbglR3GuestCtrlMsgReplyEx(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, uint32_t uType,
+                                          void *pvPayload, uint32_t cbPayload);
+VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t uClientId);
+VBGLR3DECL(int) VbglR3GuestCtrlMsgWaitFor(uint32_t uClientId, uint32_t *puMsg, uint32_t *puNumParms);
+VBGLR3DECL(int) VbglR3GuestCtrlCancelPendingWaits(HGCMCLIENTID idClient);
+/* Guest session handling. */
+VBGLR3DECL(int) VbglR3GuestCtrlSessionClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t fFlags);
+VBGLR3DECL(int) VbglR3GuestCtrlSessionNotify(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uType, uint32_t uResult);
+VBGLR3DECL(int) VbglR3GuestCtrlSessionGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puProtocol, char *pszUser, uint32_t cbUser,
+                                              char *pszPassword, uint32_t  cbPassword, char *pszDomain, uint32_t cbDomain,
+                                              uint32_t *pfFlags, uint32_t *pidSession);
+VBGLR3DECL(int) VbglR3GuestCtrlSessionGetClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *pfFlags, uint32_t *pidSession);
+/* Guest path handling. */
+VBGLR3DECL(int) VbglR3GuestCtrlPathGetRename(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszSource, uint32_t cbSource, char *pszDest,
+                                             uint32_t cbDest, uint32_t *pfFlags);
+/* Guest process execution. */
+VBGLR3DECL(int) VbglR3GuestCtrlProcGetStart(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszCmd, uint32_t cbCmd, uint32_t *pfFlags,
+                                            char *pszArgs, uint32_t cbArgs, uint32_t *puNumArgs, char *pszEnv, uint32_t *pcbEnv,
+                                            uint32_t *puNumEnvVars, char *pszUser, uint32_t cbUser, char *pszPassword,
+                                            uint32_t cbPassword, uint32_t *puTimeoutMS, uint32_t *puPriority,
+                                            uint64_t *puAffinity, uint32_t cbAffinity, uint32_t *pcAffinity);
+VBGLR3DECL(int) VbglR3GuestCtrlProcGetTerminate(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puPID);
+VBGLR3DECL(int) VbglR3GuestCtrlProcGetInput(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puPID, uint32_t *pfFlags, void *pvData,
+                                            uint32_t cbData, uint32_t *pcbSize);
+VBGLR3DECL(int) VbglR3GuestCtrlProcGetOutput(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puPID, uint32_t *puHandle, uint32_t *pfFlags);
+VBGLR3DECL(int) VbglR3GuestCtrlProcGetWaitFor(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puPID, uint32_t *puWaitFlags,
+                                              uint32_t *puTimeoutMS);
+/* Guest native directory handling. */
+VBGLR3DECL(int) VbglR3GuestCtrlDirGetRemove(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszPath, uint32_t cbPath, uint32_t *pfFlags);
+/* Guest native file handling. */
+VBGLR3DECL(int) VbglR3GuestCtrlFileGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszFileName, uint32_t cbFileName, char *pszOpenMode,
+                                           uint32_t cbOpenMode, char *pszDisposition, uint32_t cbDisposition, char *pszSharing,
+                                           uint32_t cbSharing, uint32_t *puCreationMode, uint64_t *puOffset);
+VBGLR3DECL(int) VbglR3GuestCtrlFileGetClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle);
+VBGLR3DECL(int) VbglR3GuestCtrlFileGetRead(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint32_t *puToRead);
+VBGLR3DECL(int) VbglR3GuestCtrlFileGetReadAt(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle,
+                                             uint32_t *puToRead, uint64_t *poffRead);
+VBGLR3DECL(int) VbglR3GuestCtrlFileGetWrite(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle,
+                                            void *pvData, uint32_t cbData, uint32_t *pcbActual);
+VBGLR3DECL(int) VbglR3GuestCtrlFileGetWriteAt(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, void *pvData, uint32_t cbData,
+                                              uint32_t *pcbActual, uint64_t *poffWrite);
+VBGLR3DECL(int) VbglR3GuestCtrlFileGetSeek(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle,
+                                           uint32_t *puSeekMethod, uint64_t *poffSeek);
+VBGLR3DECL(int) VbglR3GuestCtrlFileGetTell(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle);
+/* Guest -> Host. */
+VBGLR3DECL(int) VbglR3GuestCtrlFileCbOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint32_t uFileHandle);
+VBGLR3DECL(int) VbglR3GuestCtrlFileCbClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc);
+VBGLR3DECL(int) VbglR3GuestCtrlFileCbError(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc);
+VBGLR3DECL(int) VbglR3GuestCtrlFileCbRead(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, void *pvData, uint32_t cbData);
+VBGLR3DECL(int) VbglR3GuestCtrlFileCbWrite(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint32_t uWritten);
+VBGLR3DECL(int) VbglR3GuestCtrlFileCbSeek(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t uOffActual);
+VBGLR3DECL(int) VbglR3GuestCtrlFileCbTell(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t uOffActual);
+VBGLR3DECL(int) VbglR3GuestCtrlProcCbStatus(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uPID, uint32_t uStatus, uint32_t fFlags,
+                                            void *pvData, uint32_t cbData);
+VBGLR3DECL(int) VbglR3GuestCtrlProcCbOutput(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uPID, uint32_t uHandle, uint32_t fFlags,
+                                            void *pvData, uint32_t cbData);
+VBGLR3DECL(int) VbglR3GuestCtrlProcCbStatusInput(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t u32PID, uint32_t uStatus,
+                                                 uint32_t fFlags, uint32_t cbWritten);
+
+/** @}  */
+# endif /* VBOX_WITH_GUEST_CONTROL defined */
+
+/** @name Auto-logon handling
+ * @{ */
+VBGLR3DECL(int)     VbglR3AutoLogonReportStatus(VBoxGuestFacilityStatus enmStatus);
+VBGLR3DECL(bool)    VbglR3AutoLogonIsRemoteSession(void);
+/** @}  */
+
+/** @name User credentials handling
+ * @{ */
+VBGLR3DECL(int)     VbglR3CredentialsQueryAvailability(void);
+VBGLR3DECL(int)     VbglR3CredentialsRetrieve(char **ppszUser, char **ppszPassword, char **ppszDomain);
+VBGLR3DECL(int)     VbglR3CredentialsRetrieveUtf16(PRTUTF16 *ppwszUser, PRTUTF16 *ppwszPassword, PRTUTF16 *ppwszDomain);
+VBGLR3DECL(void)    VbglR3CredentialsDestroy(char *pszUser, char *pszPassword, char *pszDomain, uint32_t cPasses);
+VBGLR3DECL(void)    VbglR3CredentialsDestroyUtf16(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszDomain,
+                                                  uint32_t cPasses);
+/** @}  */
+
+/** @name CPU hotplug monitor
+ * @{ */
+VBGLR3DECL(int)     VbglR3CpuHotPlugInit(void);
+VBGLR3DECL(int)     VbglR3CpuHotPlugTerm(void);
+VBGLR3DECL(int)     VbglR3CpuHotPlugWaitForEvent(VMMDevCpuEventType *penmEventType, uint32_t *pidCpuCore, uint32_t *pidCpuPackage);
+/** @} */
+
+/** @name Page sharing
+ * @{ */
+VBGLR3DECL(int)     VbglR3RegisterSharedModule(char *pszModuleName, char *pszVersion, RTGCPTR64  GCBaseAddr, uint32_t cbModule,
+                                               unsigned cRegions, VMMDEVSHAREDREGIONDESC *pRegions);
+VBGLR3DECL(int)     VbglR3UnregisterSharedModule(char *pszModuleName, char *pszVersion, RTGCPTR64  GCBaseAddr, uint32_t cbModule);
+VBGLR3DECL(int)     VbglR3CheckSharedModules(void);
+VBGLR3DECL(bool)    VbglR3PageSharingIsEnabled(void);
+VBGLR3DECL(int)     VbglR3PageIsShared(RTGCPTR pPage, bool *pfShared, uint64_t *puPageFlags);
+/** @} */
+
+# ifdef VBOX_WITH_DRAG_AND_DROP
+/** @name Drag and Drop
+ * @{ */
+/**
+ * Structure containing the context required for
+ * either retrieving or sending a HGCM guest drag'n drop
+ * commands from or to the host.
+ *
+ * Note: Do not change parameter order without also
+ *       adapting all structure initializers.
+ */
+typedef struct VBGLR3GUESTDNDCMDCTX
+{
+    /** @todo This struct could be handy if we want to implement
+     *        a second communication channel, e.g. via TCP/IP.
+     *        Use a union for the HGCM stuff then. */
+
+    /** HGCM client ID to use for communication. */
+    uint32_t uClientID;
+    /** The VM's current session ID. */
+    uint64_t uSessionID;
+    /** Protocol version to use. */
+    uint32_t uProtocol;
+    /** Number of parameters retrieved for the current command. */
+    uint32_t uNumParms;
+    /** Max chunk size (in bytes) for data transfers. */
+    uint32_t cbMaxChunkSize;
+} VBGLR3GUESTDNDCMDCTX, *PVBGLR3GUESTDNDCMDCTX;
+
+typedef struct VBGLR3DNDHGCMEVENT
+{
+    uint32_t uType;               /** The event type this struct contains. */
+    uint32_t uScreenId;           /** Screen ID this request belongs to. */
+    char    *pszFormats;          /** Format list (\r\n separated). */
+    uint32_t cbFormats;           /** Size (in bytes) of pszFormats (\0 included). */
+    union
+    {
+        struct
+        {
+            uint32_t uXpos;       /** X position of guest screen. */
+            uint32_t uYpos;       /** Y position of guest screen. */
+            uint32_t uDefAction;  /** Proposed DnD action. */
+            uint32_t uAllActions; /** Allowed DnD actions. */
+        } a; /** Values used in init, move and drop event type. */
+        struct
+        {
+            void    *pvData;      /** Data request. */
+            uint32_t cbData;      /** Size (in bytes) of pvData. */
+        } b; /** Values used in drop data event type. */
+    } u;
+} VBGLR3DNDHGCMEVENT;
+typedef VBGLR3DNDHGCMEVENT *PVBGLR3DNDHGCMEVENT;
+typedef const PVBGLR3DNDHGCMEVENT CPVBGLR3DNDHGCMEVENT;
+VBGLR3DECL(int)     VbglR3DnDConnect(PVBGLR3GUESTDNDCMDCTX pCtx);
+VBGLR3DECL(int)     VbglR3DnDDisconnect(PVBGLR3GUESTDNDCMDCTX pCtx);
+
+VBGLR3DECL(int)     VbglR3DnDRecvNextMsg(PVBGLR3GUESTDNDCMDCTX pCtx, CPVBGLR3DNDHGCMEVENT pEvent);
+
+VBGLR3DECL(int)     VbglR3DnDHGSendAckOp(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t uAction);
+VBGLR3DECL(int)     VbglR3DnDHGSendReqData(PVBGLR3GUESTDNDCMDCTX pCtx, const char *pcszFormat);
+VBGLR3DECL(int)     VbglR3DnDHGSendProgress(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t uStatus, uint8_t uPercent, int rcErr);
+#  ifdef VBOX_WITH_DRAG_AND_DROP_GH
+VBGLR3DECL(int)     VbglR3DnDGHSendAckPending(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t uDefAction, uint32_t uAllActions, const char* pcszFormats, uint32_t cbFormats);
+VBGLR3DECL(int)     VbglR3DnDGHSendData(PVBGLR3GUESTDNDCMDCTX pCtx, const char *pszFormat, void *pvData, uint32_t cbData);
+VBGLR3DECL(int)     VbglR3DnDGHSendError(PVBGLR3GUESTDNDCMDCTX pCtx, int rcOp);
+#  endif /* VBOX_WITH_DRAG_AND_DROP_GH */
+/** @} */
+# endif /* VBOX_WITH_DRAG_AND_DROP */
+
+/* Generic Host Channel Service. */
+VBGLR3DECL(int)  VbglR3HostChannelInit(uint32_t *pu32HGCMClientId);
+VBGLR3DECL(void) VbglR3HostChannelTerm(uint32_t u32HGCMClientId);
+VBGLR3DECL(int)  VbglR3HostChannelAttach(uint32_t *pu32ChannelHandle, uint32_t u32HGCMClientId,
+                                         const char *pszName, uint32_t u32Flags);
+VBGLR3DECL(void) VbglR3HostChannelDetach(uint32_t u32ChannelHandle, uint32_t u32HGCMClientId);
+VBGLR3DECL(int)  VbglR3HostChannelSend(uint32_t u32ChannelHandle, uint32_t u32HGCMClientId,
+                                       void *pvData, uint32_t cbData);
+VBGLR3DECL(int)  VbglR3HostChannelRecv(uint32_t u32ChannelHandle, uint32_t u32HGCMClientId,
+                                       void *pvData, uint32_t cbData,
+                                       uint32_t *pu32SizeReceived, uint32_t *pu32SizeRemaining);
+VBGLR3DECL(int)  VbglR3HostChannelControl(uint32_t u32ChannelHandle, uint32_t u32HGCMClientId,
+                                         uint32_t u32Code, void *pvParm, uint32_t cbParm,
+                                         void *pvData, uint32_t cbData, uint32_t *pu32SizeDataReturned);
+VBGLR3DECL(int)  VbglR3HostChannelEventWait(uint32_t *pu32ChannelHandle, uint32_t u32HGCMClientId,
+                                            uint32_t *pu32EventId, void *pvParm, uint32_t cbParm,
+                                            uint32_t *pu32SizeReturned);
+VBGLR3DECL(int)  VbglR3HostChannelEventCancel(uint32_t u32ChannelHandle, uint32_t u32HGCMClientId);
+VBGLR3DECL(int)  VbglR3HostChannelQuery(const char *pszName, uint32_t u32HGCMClientId, uint32_t u32Code,
+                                        void *pvParm, uint32_t cbParm, void *pvData, uint32_t cbData,
+                                        uint32_t *pu32SizeDataReturned);
+
+/** @name Mode hint storage
+ * @{ */
+VBGLR3DECL(int) VbglR3ReadVideoMode(unsigned cDisplay, unsigned *cx,
+                                    unsigned *cy, unsigned *cBPP, unsigned *x,
+                                    unsigned *y, unsigned *fEnabled);
+VBGLR3DECL(int) VbglR3WriteVideoMode(unsigned cDisplay, unsigned cx,
+                                     unsigned cy, unsigned cBPP, unsigned x,
+                                     unsigned y, unsigned fEnabled);
+/** @} */
+
+/** @name Generic HGCM
+ * @{ */
+VBGLR3DECL(int)     VbglR3HGCMConnect(const char *pszServiceName, HGCMCLIENTID *pidClient);
+VBGLR3DECL(int)     VbglR3HGCMDisconnect(HGCMCLIENTID idClient);
+/** @} */
+
+#endif /* IN_RING3 */
+/** @} */
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/VBox/VBoxGuestLibSharedFolders.h b/ubuntu/vbox/include/VBox/VBoxGuestLibSharedFolders.h
new file mode 100644 (file)
index 0000000..8cd1ccb
--- /dev/null
@@ -0,0 +1,120 @@
+/* $Id: VBoxGuestLibSharedFolders.h $ */
+/** @file
+ * VBoxGuestLib - Central calls header.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBox_VBoxGuestLibSharedFolders_h_
+#define ___VBox_VBoxGuestLibSharedFolders_h_
+
+#include <VBox/VBoxGuestLib.h>
+#include <VBox/shflsvc.h>
+
+RT_C_DECLS_BEGIN
+
+
+/** @addtogroup grp_vboxguest_lib_r0
+ * @{
+ */
+
+typedef struct VBGLSFCLIENT
+{
+    HGCMCLIENTID idClient;
+    VBGLHGCMHANDLE handle;
+} VBGLSFCLIENT;
+typedef VBGLSFCLIENT *PVBGLSFCLIENT;
+
+typedef struct VBGLSFMAP
+{
+    SHFLROOT root;
+} VBGLSFMAP, *PVBGLSFMAP;
+
+DECLVBGL(int)  VbglR0SfInit(void);
+DECLVBGL(void) VbglR0SfTerm(void);
+DECLVBGL(int)  VbglR0SfConnect(PVBGLSFCLIENT pClient);
+DECLVBGL(void) VbglR0SfDisconnect(PVBGLSFCLIENT pClient);
+
+DECLVBGL(int)  VbglR0SfQueryMappings(PVBGLSFCLIENT pClient, SHFLMAPPING paMappings[], uint32_t *pcMappings);
+
+DECLVBGL(int)  VbglR0SfQueryMapName(PVBGLSFCLIENT pClient, SHFLROOT root, SHFLSTRING *pString, uint32_t size);
+
+/**
+ * Create a new file or folder or open an existing one in a shared folder.  Proxies
+ * to vbsfCreate in the host shared folder service.
+ *
+ * @returns IPRT status code, but see note below
+ * @param   pClient      Host-guest communication connection
+ * @param   pMap         The mapping for the shared folder in which the file
+ *                       or folder is to be created
+ * @param   pParsedPath  The path of the file or folder relative to the shared
+ *                       folder
+ * @param   pCreateParms Parameters for file/folder creation.  See the
+ *                       structure description in shflsvc.h
+ * @retval  pCreateParms See the structure description in shflsvc.h
+ *
+ * @note This function reports errors as follows.  The return value is always
+ *       VINF_SUCCESS unless an exceptional condition occurs - out of
+ *       memory, invalid arguments, etc.  If the file or folder could not be
+ *       opened or created, pCreateParms->Handle will be set to
+ *       SHFL_HANDLE_NIL on return.  In this case the value in
+ *       pCreateParms->Result provides information as to why (e.g.
+ *       SHFL_FILE_EXISTS).  pCreateParms->Result is also set on success
+ *       as additional information.
+ */
+DECLVBGL(int)  VbglR0SfCreate(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, PSHFLSTRING pParsedPath, PSHFLCREATEPARMS pCreateParms);
+
+DECLVBGL(int)  VbglR0SfClose(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE Handle);
+DECLVBGL(int)  VbglR0SfRemove(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, PSHFLSTRING pParsedPath, uint32_t flags);
+DECLVBGL(int)  VbglR0SfRename(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, PSHFLSTRING pSrcPath, PSHFLSTRING pDestPath, uint32_t flags);
+DECLVBGL(int)  VbglR0SfFlush(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile);
+
+DECLVBGL(int)  VbglR0SfRead(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer, bool fLocked);
+DECLVBGL(int)  VbglR0SfReadPageList(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile, uint64_t offset, uint32_t *pcbBuffer,
+                                    uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages);
+DECLVBGL(int)  VbglR0SfWrite(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile, uint64_t offset,
+                             uint32_t *pcbBuffer,  uint8_t *pBuffer, bool fLocked);
+DECLVBGL(int)  VbglR0SfWritePhysCont(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile, uint64_t offset,
+                                     uint32_t *pcbBuffer, RTCCPHYS PhysBuffer);
+DECLVBGL(int)  VbglR0SfWritePageList(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile, uint64_t offset, uint32_t *pcbBuffer,
+                                     uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages);
+
+DECLVBGL(int)  VbglR0SfLock(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile, uint64_t offset, uint64_t cbSize, uint32_t fLock);
+
+DECLVBGL(int)  VbglR0SfDirInfo(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,PSHFLSTRING ParsedPath, uint32_t flags,
+                               uint32_t index, uint32_t *pcbBuffer, PSHFLDIRINFO pBuffer, uint32_t *pcFiles);
+DECLVBGL(int)  VbglR0SfFsInfo(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile, uint32_t flags, uint32_t *pcbBuffer, PSHFLDIRINFO pBuffer);
+
+DECLVBGL(int)  VbglR0SfMapFolder(PVBGLSFCLIENT pClient, PSHFLSTRING szFolderName, PVBGLSFMAP pMap);
+DECLVBGL(int)  VbglR0SfUnmapFolder(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap);
+DECLVBGL(int)  VbglR0SfSetUtf8(PVBGLSFCLIENT pClient);
+
+DECLVBGL(int)  VbglR0SfReadLink(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, PSHFLSTRING ParsedPath, uint32_t pcbBuffer, uint8_t *pBuffer);
+DECLVBGL(int)  VbglR0SfSymlink(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, PSHFLSTRING pNewPath, PSHFLSTRING pOldPath, PSHFLFSOBJINFO pBuffer);
+DECLVBGL(int)  VbglR0SfSetSymlinks(PVBGLSFCLIENT pClient);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/VBox/VBoxGuestMangling.h b/ubuntu/vbox/include/VBox/VBoxGuestMangling.h
new file mode 100644 (file)
index 0000000..508c55d
--- /dev/null
@@ -0,0 +1,32 @@
+/** @file
+ * VBoxGuest - Mangling of IPRT symbols for guest drivers.
+ *
+ * This is included via a compiler directive on platforms with a global kernel
+ * symbol name space (i.e. not Windows, OS/2 and Mac OS X (?)).
+ */
+
+/*
+ * Copyright (C) 2011-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.
+ */
+
+
+#define RT_MANGLER(symbol)   VBoxGuest_##symbol
+#include <iprt/mangling.h>
+
diff --git a/ubuntu/vbox/include/VBox/VBoxVideo.h b/ubuntu/vbox/include/VBox/VBoxVideo.h
new file mode 100644 (file)
index 0000000..337ef5b
--- /dev/null
@@ -0,0 +1,2019 @@
+/** @file
+ * VirtualBox Video interface.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBox_VBoxVideo_h
+#define ___VBox_VBoxVideo_h
+
+#include <VBox/VMMDev.h>
+#include <VBox/Hardware/VBoxVideoVBE.h>
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+/*
+ * The last 4096 bytes of the guest VRAM contains the generic info for all
+ * DualView chunks: sizes and offsets of chunks. This is filled by miniport.
+ *
+ * Last 4096 bytes of each chunk contain chunk specific data: framebuffer info,
+ * etc. This is used exclusively by the corresponding instance of a display driver.
+ *
+ * The VRAM layout:
+ *     Last 4096 bytes - Adapter information area.
+ *     4096 bytes aligned miniport heap (value specified in the config rouded up).
+ *     Slack - what left after dividing the VRAM.
+ *     4096 bytes aligned framebuffers:
+ *       last 4096 bytes of each framebuffer is the display information area.
+ *
+ * The Virtual Graphics Adapter information in the guest VRAM is stored by the
+ * guest video driver using structures prepended by VBOXVIDEOINFOHDR.
+ *
+ * When the guest driver writes dword 0 to the VBE_DISPI_INDEX_VBOX_VIDEO
+ * the host starts to process the info. The first element at the start of
+ * the 4096 bytes region should be normally be a LINK that points to
+ * actual information chain. That way the guest driver can have some
+ * fixed layout of the information memory block and just rewrite
+ * the link to point to relevant memory chain.
+ *
+ * The processing stops at the END element.
+ *
+ * The host can access the memory only when the port IO is processed.
+ * All data that will be needed later must be copied from these 4096 bytes.
+ * But other VRAM can be used by host until the mode is disabled.
+ *
+ * The guest driver writes dword 0xffffffff to the VBE_DISPI_INDEX_VBOX_VIDEO
+ * to disable the mode.
+ *
+ * VBE_DISPI_INDEX_VBOX_VIDEO is used to read the configuration information
+ * from the host and issue commands to the host.
+ *
+ * The guest writes the VBE_DISPI_INDEX_VBOX_VIDEO index register, the the
+ * following operations with the VBE data register can be performed:
+ *
+ * Operation            Result
+ * write 16 bit value   NOP
+ * read 16 bit value    count of monitors
+ * write 32 bit value   sets the vbox command value and the command processed by the host
+ * read 32 bit value    result of the last vbox command is returned
+ */
+
+#define VBOX_VIDEO_PRIMARY_SCREEN 0
+#define VBOX_VIDEO_NO_SCREEN ~0
+
+/* The size of the information. */
+/*
+ * The minimum HGSMI heap size is PAGE_SIZE (4096 bytes) and is a restriction of the
+ * runtime heapsimple API. Use minimum 2 pages here, because the info area also may
+ * contain other data (for example HGSMIHOSTFLAGS structure).
+ */
+#ifndef VBOX_XPDM_MINIPORT
+# define VBVA_ADAPTER_INFORMATION_SIZE (64*_1K)
+#else
+#define VBVA_ADAPTER_INFORMATION_SIZE  (16*_1K)
+#define VBVA_DISPLAY_INFORMATION_SIZE  (64*_1K)
+#endif
+#define VBVA_MIN_BUFFER_SIZE           (64*_1K)
+
+
+/* The value for port IO to let the adapter to interpret the adapter memory. */
+#define VBOX_VIDEO_DISABLE_ADAPTER_MEMORY        0xFFFFFFFF
+
+/* The value for port IO to let the adapter to interpret the adapter memory. */
+#define VBOX_VIDEO_INTERPRET_ADAPTER_MEMORY      0x00000000
+
+/* The value for port IO to let the adapter to interpret the display memory.
+ * The display number is encoded in low 16 bits.
+ */
+#define VBOX_VIDEO_INTERPRET_DISPLAY_MEMORY_BASE 0x00010000
+
+
+/* The end of the information. */
+#define VBOX_VIDEO_INFO_TYPE_END          0
+/* Instructs the host to fetch the next VBOXVIDEOINFOHDR at the given offset of VRAM. */
+#define VBOX_VIDEO_INFO_TYPE_LINK         1
+/* Information about a display memory position. */
+#define VBOX_VIDEO_INFO_TYPE_DISPLAY      2
+/* Information about a screen. */
+#define VBOX_VIDEO_INFO_TYPE_SCREEN       3
+/* Information about host notifications for the driver. */
+#define VBOX_VIDEO_INFO_TYPE_HOST_EVENTS  4
+/* Information about non-volatile guest VRAM heap. */
+#define VBOX_VIDEO_INFO_TYPE_NV_HEAP      5
+/* VBVA enable/disable. */
+#define VBOX_VIDEO_INFO_TYPE_VBVA_STATUS  6
+/* VBVA flush. */
+#define VBOX_VIDEO_INFO_TYPE_VBVA_FLUSH   7
+/* Query configuration value. */
+#define VBOX_VIDEO_INFO_TYPE_QUERY_CONF32 8
+
+
+#pragma pack(1)
+typedef struct VBOXVIDEOINFOHDR
+{
+    uint8_t u8Type;
+    uint8_t u8Reserved;
+    uint16_t u16Length;
+} VBOXVIDEOINFOHDR;
+
+
+typedef struct VBOXVIDEOINFOLINK
+{
+    /* Relative offset in VRAM */
+    int32_t i32Offset;
+} VBOXVIDEOINFOLINK;
+
+
+/* Resides in adapter info memory. Describes a display VRAM chunk. */
+typedef struct VBOXVIDEOINFODISPLAY
+{
+    /* Index of the framebuffer assigned by guest. */
+    uint32_t u32Index;
+
+    /* Absolute offset in VRAM of the framebuffer to be displayed on the monitor. */
+    uint32_t u32Offset;
+
+    /* The size of the memory that can be used for the screen. */
+    uint32_t u32FramebufferSize;
+
+    /* The size of the memory that is used for the Display information.
+     * The information is at u32Offset + u32FramebufferSize
+     */
+    uint32_t u32InformationSize;
+
+} VBOXVIDEOINFODISPLAY;
+
+
+/* Resides in display info area, describes the current video mode. */
+#define VBOX_VIDEO_INFO_SCREEN_F_NONE   0x00
+#define VBOX_VIDEO_INFO_SCREEN_F_ACTIVE 0x01
+
+typedef struct VBOXVIDEOINFOSCREEN
+{
+    /* Physical X origin relative to the primary screen. */
+    int32_t xOrigin;
+
+    /* Physical Y origin relative to the primary screen. */
+    int32_t yOrigin;
+
+    /* The scan line size in bytes. */
+    uint32_t u32LineSize;
+
+    /* Width of the screen. */
+    uint16_t u16Width;
+
+    /* Height of the screen. */
+    uint16_t u16Height;
+
+    /* Color depth. */
+    uint8_t bitsPerPixel;
+
+    /* VBOX_VIDEO_INFO_SCREEN_F_* */
+    uint8_t u8Flags;
+} VBOXVIDEOINFOSCREEN;
+
+/* The guest initializes the structure to 0. The positions of the structure in the
+ * display info area must not be changed, host will update the structure. Guest checks
+ * the events and modifies the structure as a response to host.
+ */
+#define VBOX_VIDEO_INFO_HOST_EVENTS_F_NONE        0x00000000
+#define VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET  0x00000080
+
+typedef struct VBOXVIDEOINFOHOSTEVENTS
+{
+    /* Host events. */
+    uint32_t fu32Events;
+} VBOXVIDEOINFOHOSTEVENTS;
+
+/* Resides in adapter info memory. Describes the non-volatile VRAM heap. */
+typedef struct VBOXVIDEOINFONVHEAP
+{
+    /* Absolute offset in VRAM of the start of the heap. */
+    uint32_t u32HeapOffset;
+
+    /* The size of the heap. */
+    uint32_t u32HeapSize;
+
+} VBOXVIDEOINFONVHEAP;
+
+/* Display information area. */
+typedef struct VBOXVIDEOINFOVBVASTATUS
+{
+    /* Absolute offset in VRAM of the start of the VBVA QUEUE. 0 to disable VBVA. */
+    uint32_t u32QueueOffset;
+
+    /* The size of the VBVA QUEUE. 0 to disable VBVA. */
+    uint32_t u32QueueSize;
+
+} VBOXVIDEOINFOVBVASTATUS;
+
+typedef struct VBOXVIDEOINFOVBVAFLUSH
+{
+    uint32_t u32DataStart;
+
+    uint32_t u32DataEnd;
+
+} VBOXVIDEOINFOVBVAFLUSH;
+
+#define VBOX_VIDEO_QCI32_MONITOR_COUNT       0
+#define VBOX_VIDEO_QCI32_OFFSCREEN_HEAP_SIZE 1
+
+typedef struct VBOXVIDEOINFOQUERYCONF32
+{
+    uint32_t u32Index;
+
+    uint32_t u32Value;
+
+} VBOXVIDEOINFOQUERYCONF32;
+#pragma pack()
+
+#ifdef VBOX_WITH_VIDEOHWACCEL
+#pragma pack(1)
+
+#define VBOXVHWA_VERSION_MAJ 0
+#define VBOXVHWA_VERSION_MIN 0
+#define VBOXVHWA_VERSION_BLD 6
+#define VBOXVHWA_VERSION_RSV 0
+
+typedef enum
+{
+    VBOXVHWACMD_TYPE_SURF_CANCREATE = 1,
+    VBOXVHWACMD_TYPE_SURF_CREATE,
+    VBOXVHWACMD_TYPE_SURF_DESTROY,
+    VBOXVHWACMD_TYPE_SURF_LOCK,
+    VBOXVHWACMD_TYPE_SURF_UNLOCK,
+    VBOXVHWACMD_TYPE_SURF_BLT,
+    VBOXVHWACMD_TYPE_SURF_FLIP,
+    VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE,
+    VBOXVHWACMD_TYPE_SURF_OVERLAY_SETPOSITION,
+    VBOXVHWACMD_TYPE_SURF_COLORKEY_SET,
+    VBOXVHWACMD_TYPE_QUERY_INFO1,
+    VBOXVHWACMD_TYPE_QUERY_INFO2,
+    VBOXVHWACMD_TYPE_ENABLE,
+    VBOXVHWACMD_TYPE_DISABLE,
+    VBOXVHWACMD_TYPE_HH_CONSTRUCT,
+    VBOXVHWACMD_TYPE_HH_RESET
+#ifdef VBOX_WITH_WDDM
+    , VBOXVHWACMD_TYPE_SURF_GETINFO
+    , VBOXVHWACMD_TYPE_SURF_COLORFILL
+#endif
+    , VBOXVHWACMD_TYPE_HH_DISABLE
+    , VBOXVHWACMD_TYPE_HH_ENABLE
+    , VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEBEGIN
+    , VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEEND
+    , VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEPERFORM
+    , VBOXVHWACMD_TYPE_HH_SAVESTATE_LOADPERFORM
+} VBOXVHWACMD_TYPE;
+
+/* the command processing was asynch, set by the host to indicate asynch command completion
+ * must not be cleared once set, the command completion is performed by issuing a host->guest completion command
+ * while keeping this flag unchanged */
+#define VBOXVHWACMD_FLAG_HG_ASYNCH               0x00010000
+/* asynch completion is performed by issuing the event */
+#define VBOXVHWACMD_FLAG_GH_ASYNCH_EVENT         0x00000001
+/* issue interrupt on asynch completion */
+#define VBOXVHWACMD_FLAG_GH_ASYNCH_IRQ           0x00000002
+/* guest does not do any op on completion of this command, the host may copy the command and indicate that it does not need the command anymore
+ * by setting the VBOXVHWACMD_FLAG_HG_ASYNCH_RETURNED flag */
+#define VBOXVHWACMD_FLAG_GH_ASYNCH_NOCOMPLETION  0x00000004
+/* the host has copied the VBOXVHWACMD_FLAG_GH_ASYNCH_NOCOMPLETION command and returned it to the guest */
+#define VBOXVHWACMD_FLAG_HG_ASYNCH_RETURNED      0x00020000
+/* this is the host->host cmd, i.e. a configuration command posted by the host to the framebuffer */
+#define VBOXVHWACMD_FLAG_HH_CMD                  0x10000000
+
+typedef struct VBOXVHWACMD
+{
+    VBOXVHWACMD_TYPE enmCmd; /* command type */
+    volatile int32_t rc; /* command result */
+    int32_t iDisplay; /* display index */
+    volatile int32_t Flags; /* ored VBOXVHWACMD_FLAG_xxx values */
+    uint64_t GuestVBVAReserved1; /* field internally used by the guest VBVA cmd handling, must NOT be modified by clients */
+    uint64_t GuestVBVAReserved2; /* field internally used by the guest VBVA cmd handling, must NOT be modified by clients */
+    volatile uint32_t cRefs;
+    int32_t Reserved;
+    union
+    {
+        struct VBOXVHWACMD *pNext;
+        uint32_t             offNext;
+        uint64_t Data; /* the body is 64-bit aligned */
+    } u;
+    char body[1];
+} VBOXVHWACMD;
+
+#define VBOXVHWACMD_HEADSIZE() (RT_OFFSETOF(VBOXVHWACMD, body))
+#define VBOXVHWACMD_SIZE_FROMBODYSIZE(_s) (VBOXVHWACMD_HEADSIZE() + (_s))
+#define VBOXVHWACMD_SIZE(_tCmd) (VBOXVHWACMD_SIZE_FROMBODYSIZE(sizeof(_tCmd)))
+typedef unsigned int VBOXVHWACMD_LENGTH;
+typedef uint64_t VBOXVHWA_SURFHANDLE;
+#define VBOXVHWA_SURFHANDLE_INVALID 0ULL
+#define VBOXVHWACMD_BODY(_p, _t) ((_t*)(_p)->body)
+#define VBOXVHWACMD_HEAD(_pb) ((VBOXVHWACMD*)((uint8_t *)(_pb) - RT_OFFSETOF(VBOXVHWACMD, body)))
+
+typedef struct VBOXVHWA_RECTL
+{
+    int32_t left;
+    int32_t top;
+    int32_t right;
+    int32_t bottom;
+} VBOXVHWA_RECTL;
+
+typedef struct VBOXVHWA_COLORKEY
+{
+    uint32_t low;
+    uint32_t high;
+} VBOXVHWA_COLORKEY;
+
+typedef struct VBOXVHWA_PIXELFORMAT
+{
+    uint32_t flags;
+    uint32_t fourCC;
+    union
+    {
+        uint32_t rgbBitCount;
+        uint32_t yuvBitCount;
+    } c;
+
+    union
+    {
+        uint32_t rgbRBitMask;
+        uint32_t yuvYBitMask;
+    } m1;
+
+    union
+    {
+        uint32_t rgbGBitMask;
+        uint32_t yuvUBitMask;
+    } m2;
+
+    union
+    {
+        uint32_t rgbBBitMask;
+        uint32_t yuvVBitMask;
+    } m3;
+
+    union
+    {
+        uint32_t rgbABitMask;
+    } m4;
+
+    uint32_t Reserved;
+} VBOXVHWA_PIXELFORMAT;
+
+typedef struct VBOXVHWA_SURFACEDESC
+{
+    uint32_t flags;
+    uint32_t height;
+    uint32_t width;
+    uint32_t pitch;
+    uint32_t sizeX;
+    uint32_t sizeY;
+    uint32_t cBackBuffers;
+    uint32_t Reserved;
+    VBOXVHWA_COLORKEY DstOverlayCK;
+    VBOXVHWA_COLORKEY DstBltCK;
+    VBOXVHWA_COLORKEY SrcOverlayCK;
+    VBOXVHWA_COLORKEY SrcBltCK;
+    VBOXVHWA_PIXELFORMAT PixelFormat;
+    uint32_t surfCaps;
+    uint32_t Reserved2;
+    VBOXVHWA_SURFHANDLE hSurf;
+    uint64_t offSurface;
+} VBOXVHWA_SURFACEDESC;
+
+typedef struct VBOXVHWA_BLTFX
+{
+    uint32_t flags;
+    uint32_t rop;
+    uint32_t rotationOp;
+    uint32_t rotation;
+    uint32_t fillColor;
+    uint32_t Reserved;
+    VBOXVHWA_COLORKEY DstCK;
+    VBOXVHWA_COLORKEY SrcCK;
+} VBOXVHWA_BLTFX;
+
+typedef struct VBOXVHWA_OVERLAYFX
+{
+    uint32_t flags;
+    uint32_t Reserved1;
+    uint32_t fxFlags;
+    uint32_t Reserved2;
+    VBOXVHWA_COLORKEY DstCK;
+    VBOXVHWA_COLORKEY SrcCK;
+} VBOXVHWA_OVERLAYFX;
+
+#define VBOXVHWA_CAPS_BLT               0x00000040
+#define VBOXVHWA_CAPS_BLTCOLORFILL      0x04000000
+#define VBOXVHWA_CAPS_BLTFOURCC         0x00000100
+#define VBOXVHWA_CAPS_BLTSTRETCH        0x00000200
+#define VBOXVHWA_CAPS_BLTQUEUE          0x00000080
+
+#define VBOXVHWA_CAPS_OVERLAY           0x00000800
+#define VBOXVHWA_CAPS_OVERLAYFOURCC     0x00002000
+#define VBOXVHWA_CAPS_OVERLAYSTRETCH    0x00004000
+#define VBOXVHWA_CAPS_OVERLAYCANTCLIP   0x00001000
+
+#define VBOXVHWA_CAPS_COLORKEY          0x00400000
+#define VBOXVHWA_CAPS_COLORKEYHWASSIST  0x01000000
+
+#define VBOXVHWA_SCAPS_BACKBUFFER       0x00000004
+#define VBOXVHWA_SCAPS_COMPLEX          0x00000008
+#define VBOXVHWA_SCAPS_FLIP             0x00000010
+#define VBOXVHWA_SCAPS_FRONTBUFFER      0x00000020
+#define VBOXVHWA_SCAPS_OFFSCREENPLAIN   0x00000040
+#define VBOXVHWA_SCAPS_OVERLAY          0x00000080
+#define VBOXVHWA_SCAPS_PRIMARYSURFACE   0x00000200
+#define VBOXVHWA_SCAPS_SYSTEMMEMORY     0x00000800
+#define VBOXVHWA_SCAPS_VIDEOMEMORY      0x00004000
+#define VBOXVHWA_SCAPS_VISIBLE          0x00008000
+#define VBOXVHWA_SCAPS_LOCALVIDMEM      0x10000000
+
+#define VBOXVHWA_PF_PALETTEINDEXED8     0x00000020
+#define VBOXVHWA_PF_RGB                 0x00000040
+#define VBOXVHWA_PF_RGBTOYUV            0x00000100
+#define VBOXVHWA_PF_YUV                 0x00000200
+#define VBOXVHWA_PF_FOURCC              0x00000004
+
+#define VBOXVHWA_LOCK_DISCARDCONTENTS   0x00002000
+
+#define VBOXVHWA_CFG_ENABLED            0x00000001
+
+#define VBOXVHWA_SD_BACKBUFFERCOUNT     0x00000020
+#define VBOXVHWA_SD_CAPS                0x00000001
+#define VBOXVHWA_SD_CKDESTBLT           0x00004000
+#define VBOXVHWA_SD_CKDESTOVERLAY       0x00002000
+#define VBOXVHWA_SD_CKSRCBLT            0x00010000
+#define VBOXVHWA_SD_CKSRCOVERLAY        0x00008000
+#define VBOXVHWA_SD_HEIGHT              0x00000002
+#define VBOXVHWA_SD_PITCH               0x00000008
+#define VBOXVHWA_SD_PIXELFORMAT         0x00001000
+/*#define VBOXVHWA_SD_REFRESHRATE       0x00040000*/
+#define VBOXVHWA_SD_WIDTH               0x00000004
+
+#define VBOXVHWA_CKEYCAPS_DESTBLT                  0x00000001
+#define VBOXVHWA_CKEYCAPS_DESTBLTCLRSPACE          0x00000002
+#define VBOXVHWA_CKEYCAPS_DESTBLTCLRSPACEYUV       0x00000004
+#define VBOXVHWA_CKEYCAPS_DESTBLTYUV               0x00000008
+#define VBOXVHWA_CKEYCAPS_DESTOVERLAY              0x00000010
+#define VBOXVHWA_CKEYCAPS_DESTOVERLAYCLRSPACE      0x00000020
+#define VBOXVHWA_CKEYCAPS_DESTOVERLAYCLRSPACEYUV   0x00000040
+#define VBOXVHWA_CKEYCAPS_DESTOVERLAYONEACTIVE     0x00000080
+#define VBOXVHWA_CKEYCAPS_DESTOVERLAYYUV           0x00000100
+#define VBOXVHWA_CKEYCAPS_SRCBLT                   0x00000200
+#define VBOXVHWA_CKEYCAPS_SRCBLTCLRSPACE           0x00000400
+#define VBOXVHWA_CKEYCAPS_SRCBLTCLRSPACEYUV        0x00000800
+#define VBOXVHWA_CKEYCAPS_SRCBLTYUV                0x00001000
+#define VBOXVHWA_CKEYCAPS_SRCOVERLAY               0x00002000
+#define VBOXVHWA_CKEYCAPS_SRCOVERLAYCLRSPACE       0x00004000
+#define VBOXVHWA_CKEYCAPS_SRCOVERLAYCLRSPACEYUV    0x00008000
+#define VBOXVHWA_CKEYCAPS_SRCOVERLAYONEACTIVE      0x00010000
+#define VBOXVHWA_CKEYCAPS_SRCOVERLAYYUV            0x00020000
+#define VBOXVHWA_CKEYCAPS_NOCOSTOVERLAY            0x00040000
+
+#define VBOXVHWA_BLT_COLORFILL                      0x00000400
+#define VBOXVHWA_BLT_DDFX                           0x00000800
+#define VBOXVHWA_BLT_EXTENDED_FLAGS                 0x40000000
+#define VBOXVHWA_BLT_EXTENDED_LINEAR_CONTENT        0x00000004
+#define VBOXVHWA_BLT_EXTENDED_PRESENTATION_STRETCHFACTOR 0x00000010
+#define VBOXVHWA_BLT_KEYDESTOVERRIDE                0x00004000
+#define VBOXVHWA_BLT_KEYSRCOVERRIDE                 0x00010000
+#define VBOXVHWA_BLT_LAST_PRESENTATION              0x20000000
+#define VBOXVHWA_BLT_PRESENTATION                   0x10000000
+#define VBOXVHWA_BLT_ROP                            0x00020000
+
+
+#define VBOXVHWA_OVER_DDFX                          0x00080000
+#define VBOXVHWA_OVER_HIDE                          0x00000200
+#define VBOXVHWA_OVER_KEYDEST                       0x00000400
+#define VBOXVHWA_OVER_KEYDESTOVERRIDE               0x00000800
+#define VBOXVHWA_OVER_KEYSRC                        0x00001000
+#define VBOXVHWA_OVER_KEYSRCOVERRIDE                0x00002000
+#define VBOXVHWA_OVER_SHOW                          0x00004000
+
+#define VBOXVHWA_CKEY_COLORSPACE                    0x00000001
+#define VBOXVHWA_CKEY_DESTBLT                       0x00000002
+#define VBOXVHWA_CKEY_DESTOVERLAY                   0x00000004
+#define VBOXVHWA_CKEY_SRCBLT                        0x00000008
+#define VBOXVHWA_CKEY_SRCOVERLAY                    0x00000010
+
+#define VBOXVHWA_BLT_ARITHSTRETCHY                  0x00000001
+#define VBOXVHWA_BLT_MIRRORLEFTRIGHT                0x00000002
+#define VBOXVHWA_BLT_MIRRORUPDOWN                   0x00000004
+
+#define VBOXVHWA_OVERFX_ARITHSTRETCHY               0x00000001
+#define VBOXVHWA_OVERFX_MIRRORLEFTRIGHT             0x00000002
+#define VBOXVHWA_OVERFX_MIRRORUPDOWN                0x00000004
+
+#define VBOXVHWA_CAPS2_CANRENDERWINDOWED            0x00080000
+#define VBOXVHWA_CAPS2_WIDESURFACES                 0x00001000
+#define VBOXVHWA_CAPS2_COPYFOURCC                   0x00008000
+/*#define VBOXVHWA_CAPS2_FLIPINTERVAL                 0x00200000*/
+/*#define VBOXVHWA_CAPS2_FLIPNOVSYNC                  0x00400000*/
+
+
+#define VBOXVHWA_OFFSET64_VOID        (UINT64_MAX)
+
+typedef struct VBOXVHWA_VERSION
+{
+    uint32_t maj;
+    uint32_t min;
+    uint32_t bld;
+    uint32_t reserved;
+} VBOXVHWA_VERSION;
+
+#define VBOXVHWA_VERSION_INIT(_pv) do { \
+        (_pv)->maj = VBOXVHWA_VERSION_MAJ; \
+        (_pv)->min = VBOXVHWA_VERSION_MIN; \
+        (_pv)->bld = VBOXVHWA_VERSION_BLD; \
+        (_pv)->reserved = VBOXVHWA_VERSION_RSV; \
+        } while(0)
+
+typedef struct VBOXVHWACMD_QUERYINFO1
+{
+    union
+    {
+        struct
+        {
+            VBOXVHWA_VERSION guestVersion;
+        } in;
+
+        struct
+        {
+            uint32_t cfgFlags;
+            uint32_t caps;
+
+            uint32_t caps2;
+            uint32_t colorKeyCaps;
+
+            uint32_t stretchCaps;
+            uint32_t surfaceCaps;
+
+            uint32_t numOverlays;
+            uint32_t curOverlays;
+
+            uint32_t numFourCC;
+            uint32_t reserved;
+        } out;
+    } u;
+} VBOXVHWACMD_QUERYINFO1;
+
+typedef struct VBOXVHWACMD_QUERYINFO2
+{
+    uint32_t numFourCC;
+    uint32_t FourCC[1];
+} VBOXVHWACMD_QUERYINFO2;
+
+#define VBOXVHWAINFO2_SIZE(_cFourCC) RT_OFFSETOF(VBOXVHWACMD_QUERYINFO2, FourCC[_cFourCC])
+
+typedef struct VBOXVHWACMD_SURF_CANCREATE
+{
+    VBOXVHWA_SURFACEDESC SurfInfo;
+    union
+    {
+        struct
+        {
+            uint32_t bIsDifferentPixelFormat;
+            uint32_t Reserved;
+        } in;
+
+        struct
+        {
+            int32_t ErrInfo;
+        } out;
+    } u;
+} VBOXVHWACMD_SURF_CANCREATE;
+
+typedef struct VBOXVHWACMD_SURF_CREATE
+{
+    VBOXVHWA_SURFACEDESC SurfInfo;
+} VBOXVHWACMD_SURF_CREATE;
+
+#ifdef VBOX_WITH_WDDM
+typedef struct VBOXVHWACMD_SURF_GETINFO
+{
+    VBOXVHWA_SURFACEDESC SurfInfo;
+} VBOXVHWACMD_SURF_GETINFO;
+#endif
+
+typedef struct VBOXVHWACMD_SURF_DESTROY
+{
+    union
+    {
+        struct
+        {
+            VBOXVHWA_SURFHANDLE hSurf;
+        } in;
+    } u;
+} VBOXVHWACMD_SURF_DESTROY;
+
+typedef struct VBOXVHWACMD_SURF_LOCK
+{
+    union
+    {
+        struct
+        {
+            VBOXVHWA_SURFHANDLE hSurf;
+            uint64_t offSurface;
+            uint32_t flags;
+            uint32_t rectValid;
+            VBOXVHWA_RECTL rect;
+        } in;
+    } u;
+} VBOXVHWACMD_SURF_LOCK;
+
+typedef struct VBOXVHWACMD_SURF_UNLOCK
+{
+    union
+    {
+        struct
+        {
+            VBOXVHWA_SURFHANDLE hSurf;
+            uint32_t xUpdatedMemValid;
+            uint32_t reserved;
+            VBOXVHWA_RECTL xUpdatedMemRect;
+        } in;
+    } u;
+} VBOXVHWACMD_SURF_UNLOCK;
+
+typedef struct VBOXVHWACMD_SURF_BLT
+{
+    uint64_t DstGuestSurfInfo;
+    uint64_t SrcGuestSurfInfo;
+    union
+    {
+        struct
+        {
+            VBOXVHWA_SURFHANDLE hDstSurf;
+            uint64_t offDstSurface;
+            VBOXVHWA_RECTL dstRect;
+            VBOXVHWA_SURFHANDLE hSrcSurf;
+            uint64_t offSrcSurface;
+            VBOXVHWA_RECTL srcRect;
+            uint32_t flags;
+            uint32_t xUpdatedSrcMemValid;
+            VBOXVHWA_BLTFX desc;
+            VBOXVHWA_RECTL xUpdatedSrcMemRect;
+        } in;
+    } u;
+} VBOXVHWACMD_SURF_BLT;
+
+#ifdef VBOX_WITH_WDDM
+typedef struct VBOXVHWACMD_SURF_COLORFILL
+{
+    union
+    {
+        struct
+        {
+            VBOXVHWA_SURFHANDLE hSurf;
+            uint64_t offSurface;
+            uint32_t u32Reserved;
+            uint32_t cRects;
+            VBOXVHWA_RECTL aRects[1];
+        } in;
+    } u;
+} VBOXVHWACMD_SURF_COLORFILL;
+#endif
+
+typedef struct VBOXVHWACMD_SURF_FLIP
+{
+    uint64_t TargGuestSurfInfo;
+    uint64_t CurrGuestSurfInfo;
+    union
+    {
+        struct
+        {
+            VBOXVHWA_SURFHANDLE hTargSurf;
+            uint64_t offTargSurface;
+            VBOXVHWA_SURFHANDLE hCurrSurf;
+            uint64_t offCurrSurface;
+            uint32_t flags;
+            uint32_t xUpdatedTargMemValid;
+            VBOXVHWA_RECTL xUpdatedTargMemRect;
+        } in;
+    } u;
+} VBOXVHWACMD_SURF_FLIP;
+
+typedef struct VBOXVHWACMD_SURF_COLORKEY_SET
+{
+    union
+    {
+        struct
+        {
+            VBOXVHWA_SURFHANDLE hSurf;
+            uint64_t offSurface;
+            VBOXVHWA_COLORKEY CKey;
+            uint32_t flags;
+            uint32_t reserved;
+        } in;
+    } u;
+} VBOXVHWACMD_SURF_COLORKEY_SET;
+
+#define VBOXVHWACMD_SURF_OVERLAY_UPDATE_F_SRCMEMRECT 0x00000001
+#define VBOXVHWACMD_SURF_OVERLAY_UPDATE_F_DSTMEMRECT 0x00000002
+
+typedef struct VBOXVHWACMD_SURF_OVERLAY_UPDATE
+{
+    union
+    {
+        struct
+        {
+            VBOXVHWA_SURFHANDLE hDstSurf;
+            uint64_t offDstSurface;
+            VBOXVHWA_RECTL dstRect;
+            VBOXVHWA_SURFHANDLE hSrcSurf;
+            uint64_t offSrcSurface;
+            VBOXVHWA_RECTL srcRect;
+            uint32_t flags;
+            uint32_t xFlags;
+            VBOXVHWA_OVERLAYFX desc;
+            VBOXVHWA_RECTL xUpdatedSrcMemRect;
+            VBOXVHWA_RECTL xUpdatedDstMemRect;
+        } in;
+    } u;
+}VBOXVHWACMD_SURF_OVERLAY_UPDATE;
+
+typedef struct VBOXVHWACMD_SURF_OVERLAY_SETPOSITION
+{
+    union
+    {
+        struct
+        {
+            VBOXVHWA_SURFHANDLE hDstSurf;
+            uint64_t offDstSurface;
+            VBOXVHWA_SURFHANDLE hSrcSurf;
+            uint64_t offSrcSurface;
+            uint32_t xPos;
+            uint32_t yPos;
+            uint32_t flags;
+            uint32_t reserved;
+        } in;
+    } u;
+} VBOXVHWACMD_SURF_OVERLAY_SETPOSITION;
+
+typedef struct VBOXVHWACMD_HH_CONSTRUCT
+{
+    void    *pVM;
+    /* VRAM info for the backend to be able to properly translate VRAM offsets */
+    void    *pvVRAM;
+    uint32_t cbVRAM;
+} VBOXVHWACMD_HH_CONSTRUCT;
+
+typedef struct VBOXVHWACMD_HH_SAVESTATE_SAVEPERFORM
+{
+    struct SSMHANDLE * pSSM;
+} VBOXVHWACMD_HH_SAVESTATE_SAVEPERFORM;
+
+typedef struct VBOXVHWACMD_HH_SAVESTATE_LOADPERFORM
+{
+    struct SSMHANDLE * pSSM;
+} VBOXVHWACMD_HH_SAVESTATE_LOADPERFORM;
+
+typedef DECLCALLBACK(void) FNVBOXVHWA_HH_CALLBACK(void*);
+typedef FNVBOXVHWA_HH_CALLBACK *PFNVBOXVHWA_HH_CALLBACK;
+
+#define VBOXVHWA_HH_CALLBACK_SET(_pCmd, _pfn, _parg) \
+    do { \
+        (_pCmd)->GuestVBVAReserved1 = (uint64_t)(uintptr_t)(_pfn); \
+        (_pCmd)->GuestVBVAReserved2 = (uint64_t)(uintptr_t)(_parg); \
+    }while(0)
+
+#define VBOXVHWA_HH_CALLBACK_GET(_pCmd) ((PFNVBOXVHWA_HH_CALLBACK)(_pCmd)->GuestVBVAReserved1)
+#define VBOXVHWA_HH_CALLBACK_GET_ARG(_pCmd) ((void*)(_pCmd)->GuestVBVAReserved2)
+
+#pragma pack()
+#endif /* #ifdef VBOX_WITH_VIDEOHWACCEL */
+
+/* All structures are without alignment. */
+#pragma pack(1)
+
+typedef struct VBVAHOSTFLAGS
+{
+    uint32_t u32HostEvents;
+    uint32_t u32SupportedOrders;
+} VBVAHOSTFLAGS;
+
+typedef struct VBVABUFFER
+{
+    VBVAHOSTFLAGS hostFlags;
+
+    /* The offset where the data start in the buffer. */
+    uint32_t off32Data;
+    /* The offset where next data must be placed in the buffer. */
+    uint32_t off32Free;
+
+    /* The queue of record descriptions. */
+    VBVARECORD aRecords[VBVA_MAX_RECORDS];
+    uint32_t indexRecordFirst;
+    uint32_t indexRecordFree;
+
+    /* Space to leave free in the buffer when large partial records are transferred. */
+    uint32_t cbPartialWriteThreshold;
+
+    uint32_t cbData;
+    uint8_t  au8Data[1]; /* variable size for the rest of the VBVABUFFER area in VRAM. */
+} VBVABUFFER;
+
+#define VBVA_MAX_RECORD_SIZE (128*_1M)
+
+/* guest->host commands */
+#define VBVA_QUERY_CONF32 1
+#define VBVA_SET_CONF32   2
+#define VBVA_INFO_VIEW    3
+#define VBVA_INFO_HEAP    4
+#define VBVA_FLUSH        5
+#define VBVA_INFO_SCREEN  6
+#define VBVA_ENABLE       7
+#define VBVA_MOUSE_POINTER_SHAPE 8
+#ifdef VBOX_WITH_VIDEOHWACCEL
+# define VBVA_VHWA_CMD    9
+#endif /* # ifdef VBOX_WITH_VIDEOHWACCEL */
+#ifdef VBOX_WITH_VDMA
+# define VBVA_VDMA_CTL   10 /* setup G<->H DMA channel info */
+# define VBVA_VDMA_CMD    11 /* G->H DMA command             */
+#endif
+#define VBVA_INFO_CAPS   12 /* informs host about HGSMI caps. see VBVACAPS below */
+#define VBVA_SCANLINE_CFG    13 /* configures scanline, see VBVASCANLINECFG below */
+#define VBVA_SCANLINE_INFO   14 /* requests scanline info, see VBVASCANLINEINFO below */
+#define VBVA_CMDVBVA_SUBMIT  16 /* inform host about VBVA Command submission */
+#define VBVA_CMDVBVA_FLUSH   17 /* inform host about VBVA Command submission */
+#define VBVA_CMDVBVA_CTL     18 /* G->H DMA command             */
+#define VBVA_QUERY_MODE_HINTS 19 /* Query most recent mode hints sent. */
+/** Report the guest virtual desktop position and size for mapping host and
+ * guest pointer positions. */
+#define VBVA_REPORT_INPUT_MAPPING 20
+/** Report the guest cursor position and query the host position. */
+#define VBVA_CURSOR_POSITION 21
+
+/* host->guest commands */
+#define VBVAHG_EVENT              1
+#define VBVAHG_DISPLAY_CUSTOM     2
+#ifdef VBOX_WITH_VDMA
+#define VBVAHG_SHGSMI_COMPLETION  3
+#endif
+
+#ifdef VBOX_WITH_VIDEOHWACCEL
+#define VBVAHG_DCUSTOM_VHWA_CMDCOMPLETE 1
+#pragma pack(1)
+typedef struct VBVAHOSTCMDVHWACMDCOMPLETE
+{
+    uint32_t offCmd;
+}VBVAHOSTCMDVHWACMDCOMPLETE;
+#pragma pack()
+#endif /* # ifdef VBOX_WITH_VIDEOHWACCEL */
+
+#pragma pack(1)
+typedef enum
+{
+    VBVAHOSTCMD_OP_EVENT = 1,
+    VBVAHOSTCMD_OP_CUSTOM
+}VBVAHOSTCMD_OP_TYPE;
+
+typedef struct VBVAHOSTCMDEVENT
+{
+    uint64_t pEvent;
+}VBVAHOSTCMDEVENT;
+
+
+typedef struct VBVAHOSTCMD
+{
+    /* destination ID if >=0 specifies display index, otherwize the command is directed to the miniport */
+    int32_t iDstID;
+    int32_t customOpCode;
+    union
+    {
+        struct VBVAHOSTCMD *pNext;
+        uint32_t             offNext;
+        uint64_t Data; /* the body is 64-bit aligned */
+    } u;
+    char body[1];
+}VBVAHOSTCMD;
+
+#define VBVAHOSTCMD_SIZE(_size) (sizeof(VBVAHOSTCMD) + (_size))
+#define VBVAHOSTCMD_BODY(_pCmd, _tBody) ((_tBody*)(_pCmd)->body)
+#define VBVAHOSTCMD_HDR(_pBody) ((VBVAHOSTCMD*)(((uint8_t*)_pBody) - RT_OFFSETOF(VBVAHOSTCMD, body)))
+#define VBVAHOSTCMD_HDRSIZE (RT_OFFSETOF(VBVAHOSTCMD, body))
+
+#pragma pack()
+
+/* VBVACONF32::u32Index */
+#define VBOX_VBVA_CONF32_MONITOR_COUNT  0
+#define VBOX_VBVA_CONF32_HOST_HEAP_SIZE 1
+/** Returns VINF_SUCCESS if the host can report mode hints via VBVA.
+ * Set value to VERR_NOT_SUPPORTED before calling. */
+#define VBOX_VBVA_CONF32_MODE_HINT_REPORTING  2
+/** Returns VINF_SUCCESS if the host can report guest cursor enabled status via
+ * VBVA.  Set value to VERR_NOT_SUPPORTED before calling. */
+#define VBOX_VBVA_CONF32_GUEST_CURSOR_REPORTING  3
+/** Returns the currently available host cursor capabilities.  Available if
+ * VBVACONF32::VBOX_VBVA_CONF32_GUEST_CURSOR_REPORTING returns success.
+ * @see VMMDevReqMouseStatus::mouseFeatures. */
+#define VBOX_VBVA_CONF32_CURSOR_CAPABILITIES  4
+/** Returns the supported flags in VBVAINFOSCREEN::u8Flags. */
+#define VBOX_VBVA_CONF32_SCREEN_FLAGS 5
+/** Returns the max size of VBVA record. */
+#define VBOX_VBVA_CONF32_MAX_RECORD_SIZE 6
+
+typedef struct VBVACONF32
+{
+    uint32_t u32Index;
+    uint32_t u32Value;
+} VBVACONF32;
+
+typedef struct VBVAINFOVIEW
+{
+    /* Index of the screen, assigned by the guest. */
+    uint32_t u32ViewIndex;
+
+    /* The screen offset in VRAM, the framebuffer starts here. */
+    uint32_t u32ViewOffset;
+
+    /* The size of the VRAM memory that can be used for the view. */
+    uint32_t u32ViewSize;
+
+    /* The recommended maximum size of the VRAM memory for the screen. */
+    uint32_t u32MaxScreenSize;
+} VBVAINFOVIEW;
+
+typedef struct VBVAINFOHEAP
+{
+    /* Absolute offset in VRAM of the start of the heap. */
+    uint32_t u32HeapOffset;
+
+    /* The size of the heap. */
+    uint32_t u32HeapSize;
+
+} VBVAINFOHEAP;
+
+typedef struct VBVAFLUSH
+{
+    uint32_t u32Reserved;
+
+} VBVAFLUSH;
+
+typedef struct VBVACMDVBVASUBMIT
+{
+    uint32_t u32Reserved;
+} VBVACMDVBVASUBMIT;
+
+/* flush is requested because due to guest command buffer overflow */
+#define VBVACMDVBVAFLUSH_F_GUEST_BUFFER_OVERFLOW 1
+
+typedef struct VBVACMDVBVAFLUSH
+{
+    uint32_t u32Flags;
+} VBVACMDVBVAFLUSH;
+
+
+/* VBVAINFOSCREEN::u8Flags */
+#define VBVA_SCREEN_F_NONE     0x0000
+#define VBVA_SCREEN_F_ACTIVE   0x0001
+/** The virtual monitor has been disabled by the guest and should be removed
+ * by the host and ignored for purposes of pointer position calculation. */
+#define VBVA_SCREEN_F_DISABLED 0x0002
+/** The virtual monitor has been blanked by the guest and should be blacked
+ * out by the host. */
+#define VBVA_SCREEN_F_BLANK    0x0004
+/** The virtual monitor has been blanked by the guest and should be blacked
+ * out by the host using the previous mode values for width. height, etc. */
+#define VBVA_SCREEN_F_BLANK2   0x0008
+
+typedef struct VBVAINFOSCREEN
+{
+    /* Which view contains the screen. */
+    uint32_t u32ViewIndex;
+
+    /* Physical X origin relative to the primary screen. */
+    int32_t i32OriginX;
+
+    /* Physical Y origin relative to the primary screen. */
+    int32_t i32OriginY;
+
+    /* Offset of visible framebuffer relative to the framebuffer start. */
+    uint32_t u32StartOffset;
+
+    /* The scan line size in bytes. */
+    uint32_t u32LineSize;
+
+    /* Width of the screen. */
+    uint32_t u32Width;
+
+    /* Height of the screen. */
+    uint32_t u32Height;
+
+    /* Color depth. */
+    uint16_t u16BitsPerPixel;
+
+    /* VBVA_SCREEN_F_* */
+    uint16_t u16Flags;
+} VBVAINFOSCREEN;
+
+
+/* VBVAENABLE::u32Flags */
+#define VBVA_F_NONE    0x00000000
+#define VBVA_F_ENABLE  0x00000001
+#define VBVA_F_DISABLE 0x00000002
+/* extended VBVA to be used with WDDM */
+#define VBVA_F_EXTENDED 0x00000004
+/* vbva offset is absolute VRAM offset */
+#define VBVA_F_ABSOFFSET 0x00000008
+
+typedef struct VBVAENABLE
+{
+    uint32_t u32Flags;
+    uint32_t u32Offset;
+    int32_t  i32Result;
+} VBVAENABLE;
+
+typedef struct VBVAENABLE_EX
+{
+    VBVAENABLE Base;
+    uint32_t u32ScreenId;
+} VBVAENABLE_EX;
+
+
+typedef struct VBVAMOUSEPOINTERSHAPE
+{
+    /* The host result. */
+    int32_t i32Result;
+
+    /* VBOX_MOUSE_POINTER_* bit flags. */
+    uint32_t fu32Flags;
+
+    /* X coordinate of the hot spot. */
+    uint32_t u32HotX;
+
+    /* Y coordinate of the hot spot. */
+    uint32_t u32HotY;
+
+    /* Width of the pointer in pixels. */
+    uint32_t u32Width;
+
+    /* Height of the pointer in scanlines. */
+    uint32_t u32Height;
+
+    /* Pointer data.
+     *
+     ****
+     * The data consists of 1 bpp AND mask followed by 32 bpp XOR (color) mask.
+     *
+     * For pointers without alpha channel the XOR mask pixels are 32 bit values: (lsb)BGR0(msb).
+     * For pointers with alpha channel the XOR mask consists of (lsb)BGRA(msb) 32 bit values.
+     *
+     * Guest driver must create the AND mask for pointers with alpha channel, so if host does not
+     * support alpha, the pointer could be displayed as a normal color pointer. The AND mask can
+     * be constructed from alpha values. For example alpha value >= 0xf0 means bit 0 in the AND mask.
+     *
+     * The AND mask is 1 bpp bitmap with byte aligned scanlines. Size of AND mask,
+     * therefore, is cbAnd = (width + 7) / 8 * height. The padding bits at the
+     * end of any scanline are undefined.
+     *
+     * The XOR mask follows the AND mask on the next 4 bytes aligned offset:
+     * uint8_t *pXor = pAnd + (cbAnd + 3) & ~3
+     * Bytes in the gap between the AND and the XOR mask are undefined.
+     * XOR mask scanlines have no gap between them and size of XOR mask is:
+     * cXor = width * 4 * height.
+     ****
+     *
+     * Preallocate 4 bytes for accessing actual data as p->au8Data.
+     */
+    uint8_t au8Data[4];
+
+} VBVAMOUSEPOINTERSHAPE;
+
+/* the guest driver can handle asynch guest cmd completion by reading the command offset from io port */
+#define VBVACAPS_COMPLETEGCMD_BY_IOREAD 0x00000001
+/* the guest driver can handle video adapter IRQs */
+#define VBVACAPS_IRQ                    0x00000002
+/** The guest can read video mode hints sent via VBVA. */
+#define VBVACAPS_VIDEO_MODE_HINTS       0x00000004
+/** The guest can switch to a software cursor on demand. */
+#define VBVACAPS_DISABLE_CURSOR_INTEGRATION 0x00000008
+/** The guest does not depend on host handling the VBE registers. */
+#define VBVACAPS_USE_VBVA_ONLY 0x00000010
+typedef struct VBVACAPS
+{
+    int32_t rc;
+    uint32_t fCaps;
+} VBVACAPS;
+
+/* makes graphics device generate IRQ on VSYNC */
+#define VBVASCANLINECFG_ENABLE_VSYNC_IRQ        0x00000001
+/* guest driver may request the current scanline */
+#define VBVASCANLINECFG_ENABLE_SCANLINE_INFO    0x00000002
+/* request the current refresh period, returned in u32RefreshPeriodMs */
+#define VBVASCANLINECFG_QUERY_REFRESH_PERIOD    0x00000004
+/* set new refresh period specified in u32RefreshPeriodMs.
+ * if used with VBVASCANLINECFG_QUERY_REFRESH_PERIOD,
+ * u32RefreshPeriodMs is set to the previous refresh period on return */
+#define VBVASCANLINECFG_SET_REFRESH_PERIOD      0x00000008
+
+typedef struct VBVASCANLINECFG
+{
+    int32_t rc;
+    uint32_t fFlags;
+    uint32_t u32RefreshPeriodMs;
+    uint32_t u32Reserved;
+} VBVASCANLINECFG;
+
+typedef struct VBVASCANLINEINFO
+{
+    int32_t rc;
+    uint32_t u32ScreenId;
+    uint32_t u32InVBlank;
+    uint32_t u32ScanLine;
+} VBVASCANLINEINFO;
+
+/** Query the most recent mode hints received from the host. */
+typedef struct VBVAQUERYMODEHINTS
+{
+    /** The maximum number of screens to return hints for. */
+    uint16_t cHintsQueried;
+    /** The size of the mode hint structures directly following this one. */
+    uint16_t cbHintStructureGuest;
+    /** The return code for the operation.  Initialise to VERR_NOT_SUPPORTED. */
+    int32_t  rc;
+} VBVAQUERYMODEHINTS;
+
+/** Structure in which a mode hint is returned.  The guest allocates an array
+ *  of these immediately after the VBVAQUERYMODEHINTS structure.  To accomodate
+ *  future extensions, the VBVAQUERYMODEHINTS structure specifies the size of
+ *  the VBVAMODEHINT structures allocated by the guest, and the host only fills
+ *  out structure elements which fit into that size.  The host should fill any
+ *  unused members (e.g. dx, dy) or structure space on the end with ~0.  The
+ *  whole structure can legally be set to ~0 to skip a screen. */
+typedef struct VBVAMODEHINT
+{
+    uint32_t magic;
+    uint32_t cx;
+    uint32_t cy;
+    uint32_t cBPP;  /* Which has never been used... */
+    uint32_t cDisplay;
+    uint32_t dx;  /**< X offset into the virtual frame-buffer. */
+    uint32_t dy;  /**< Y offset into the virtual frame-buffer. */
+    uint32_t fEnabled;  /* Not fFlags.  Add new members for new flags. */
+} VBVAMODEHINT;
+
+#define VBVAMODEHINT_MAGIC UINT32_C(0x0801add9)
+
+/** Report the rectangle relative to which absolute pointer events should be
+ *  expressed.  This information remains valid until the next VBVA resize event
+ *  for any screen, at which time it is reset to the bounding rectangle of all
+ *  virtual screens and must be re-set.
+ *  @see VBVA_REPORT_INPUT_MAPPING. */
+typedef struct VBVAREPORTINPUTMAPPING
+{
+    int32_t x;    /**< Upper left X co-ordinate relative to the first screen. */
+    int32_t y;    /**< Upper left Y co-ordinate relative to the first screen. */
+    uint32_t cx;  /**< Rectangle width. */
+    uint32_t cy;  /**< Rectangle height. */
+} VBVAREPORTINPUTMAPPING;
+
+/** Report the guest cursor position and query the host one.  The host may wish
+ *  to use the guest information to re-position its own cursor (though this is
+ *  currently unlikely).
+ *  @see VBVA_CURSOR_POSITION */
+typedef struct VBVACURSORPOSITION
+{
+    uint32_t fReportPosition;  /**< Are we reporting a position? */
+    uint32_t x;                /**< Guest cursor X position */
+    uint32_t y;                /**< Guest cursor Y position */
+} VBVACURSORPOSITION;
+
+#pragma pack()
+
+typedef uint64_t VBOXVIDEOOFFSET;
+
+#define VBOXVIDEOOFFSET_VOID ((VBOXVIDEOOFFSET)~0)
+
+#pragma pack(1)
+
+/*
+ * VBOXSHGSMI made on top HGSMI and allows receiving notifications
+ * about G->H command completion
+ */
+/* SHGSMI command header */
+typedef struct VBOXSHGSMIHEADER
+{
+    uint64_t pvNext;    /*<- completion processing queue */
+    uint32_t fFlags;    /*<- see VBOXSHGSMI_FLAG_XXX Flags */
+    uint32_t cRefs;     /*<- command referece count */
+    uint64_t u64Info1;  /*<- contents depends on the fFlags value */
+    uint64_t u64Info2;  /*<- contents depends on the fFlags value */
+} VBOXSHGSMIHEADER, *PVBOXSHGSMIHEADER;
+
+typedef enum
+{
+    VBOXVDMACMD_TYPE_UNDEFINED         = 0,
+    VBOXVDMACMD_TYPE_DMA_PRESENT_BLT   = 1,
+    VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER,
+    VBOXVDMACMD_TYPE_DMA_BPB_FILL,
+    VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY,
+    VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL,
+    VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP,
+    VBOXVDMACMD_TYPE_DMA_NOP,
+    VBOXVDMACMD_TYPE_CHROMIUM_CMD, /* chromium cmd */
+    VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER_VRAMSYS,
+    VBOXVDMACMD_TYPE_CHILD_STATUS_IRQ /* make the device notify child (monitor) state change IRQ */
+} VBOXVDMACMD_TYPE;
+
+#pragma pack()
+
+/* the command processing was asynch, set by the host to indicate asynch command completion
+ * must not be cleared once set, the command completion is performed by issuing a host->guest completion command
+ * while keeping this flag unchanged */
+#define VBOXSHGSMI_FLAG_HG_ASYNCH               0x00010000
+#if 0
+/* if set     - asynch completion is performed by issuing the event,
+ * if cleared - asynch completion is performed by calling a callback */
+#define VBOXSHGSMI_FLAG_GH_ASYNCH_EVENT         0x00000001
+#endif
+/* issue interrupt on asynch completion, used for critical G->H commands,
+ * i.e. for completion of which guest is waiting. */
+#define VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ           0x00000002
+/* guest does not do any op on completion of this command,
+ * the host may copy the command and indicate that it does not need the command anymore
+ * by not setting VBOXSHGSMI_FLAG_HG_ASYNCH */
+#define VBOXSHGSMI_FLAG_GH_ASYNCH_NOCOMPLETION  0x00000004
+/* guest requires the command to be processed asynchronously,
+ * not setting VBOXSHGSMI_FLAG_HG_ASYNCH by the host in this case is treated as command failure */
+#define VBOXSHGSMI_FLAG_GH_ASYNCH_FORCE         0x00000008
+/* force IRQ on cmd completion */
+#define VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ_FORCE     0x00000010
+/* an IRQ-level callback is associated with the command */
+#define VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ  0x00000020
+/* guest expects this command to be completed synchronously */
+#define VBOXSHGSMI_FLAG_GH_SYNCH                0x00000040
+
+
+DECLINLINE(uint8_t *) VBoxSHGSMIBufferData (const VBOXSHGSMIHEADER* pHeader)
+{
+    return (uint8_t *)pHeader + sizeof (VBOXSHGSMIHEADER);
+}
+
+#define VBoxSHGSMIBufferHeaderSize() (sizeof (VBOXSHGSMIHEADER))
+
+DECLINLINE(PVBOXSHGSMIHEADER) VBoxSHGSMIBufferHeader (const void *pvData)
+{
+    return (PVBOXSHGSMIHEADER)((uint8_t *)pvData - sizeof (VBOXSHGSMIHEADER));
+}
+
+#ifdef VBOX_WITH_VDMA
+# pragma pack(1)
+
+/* VDMA - Video DMA */
+
+/* VDMA Control API */
+/* VBOXVDMA_CTL::u32Flags */
+typedef enum
+{
+    VBOXVDMA_CTL_TYPE_NONE = 0,
+    VBOXVDMA_CTL_TYPE_ENABLE,
+    VBOXVDMA_CTL_TYPE_DISABLE,
+    VBOXVDMA_CTL_TYPE_FLUSH,
+    VBOXVDMA_CTL_TYPE_WATCHDOG
+} VBOXVDMA_CTL_TYPE;
+
+typedef struct VBOXVDMA_CTL
+{
+    VBOXVDMA_CTL_TYPE enmCtl;
+    uint32_t u32Offset;
+    int32_t  i32Result;
+} VBOXVDMA_CTL, *PVBOXVDMA_CTL;
+
+typedef struct VBOXVDMA_RECTL
+{
+    int16_t left;
+    int16_t top;
+    uint16_t width;
+    uint16_t height;
+} VBOXVDMA_RECTL, *PVBOXVDMA_RECTL;
+
+typedef enum
+{
+    VBOXVDMA_PIXEL_FORMAT_UNKNOWN      =  0,
+    VBOXVDMA_PIXEL_FORMAT_R8G8B8       = 20,
+    VBOXVDMA_PIXEL_FORMAT_A8R8G8B8     = 21,
+    VBOXVDMA_PIXEL_FORMAT_X8R8G8B8     = 22,
+    VBOXVDMA_PIXEL_FORMAT_R5G6B5       = 23,
+    VBOXVDMA_PIXEL_FORMAT_X1R5G5B5     = 24,
+    VBOXVDMA_PIXEL_FORMAT_A1R5G5B5     = 25,
+    VBOXVDMA_PIXEL_FORMAT_A4R4G4B4     = 26,
+    VBOXVDMA_PIXEL_FORMAT_R3G3B2       = 27,
+    VBOXVDMA_PIXEL_FORMAT_A8           = 28,
+    VBOXVDMA_PIXEL_FORMAT_A8R3G3B2     = 29,
+    VBOXVDMA_PIXEL_FORMAT_X4R4G4B4     = 30,
+    VBOXVDMA_PIXEL_FORMAT_A2B10G10R10  = 31,
+    VBOXVDMA_PIXEL_FORMAT_A8B8G8R8     = 32,
+    VBOXVDMA_PIXEL_FORMAT_X8B8G8R8     = 33,
+    VBOXVDMA_PIXEL_FORMAT_G16R16       = 34,
+    VBOXVDMA_PIXEL_FORMAT_A2R10G10B10  = 35,
+    VBOXVDMA_PIXEL_FORMAT_A16B16G16R16 = 36,
+    VBOXVDMA_PIXEL_FORMAT_A8P8         = 40,
+    VBOXVDMA_PIXEL_FORMAT_P8           = 41,
+    VBOXVDMA_PIXEL_FORMAT_L8           = 50,
+    VBOXVDMA_PIXEL_FORMAT_A8L8         = 51,
+    VBOXVDMA_PIXEL_FORMAT_A4L4         = 52,
+    VBOXVDMA_PIXEL_FORMAT_V8U8         = 60,
+    VBOXVDMA_PIXEL_FORMAT_L6V5U5       = 61,
+    VBOXVDMA_PIXEL_FORMAT_X8L8V8U8     = 62,
+    VBOXVDMA_PIXEL_FORMAT_Q8W8V8U8     = 63,
+    VBOXVDMA_PIXEL_FORMAT_V16U16       = 64,
+    VBOXVDMA_PIXEL_FORMAT_W11V11U10    = 65,
+    VBOXVDMA_PIXEL_FORMAT_A2W10V10U10  = 67
+} VBOXVDMA_PIXEL_FORMAT;
+
+typedef struct VBOXVDMA_SURF_DESC
+{
+    uint32_t width;
+    uint32_t height;
+    VBOXVDMA_PIXEL_FORMAT format;
+    uint32_t bpp;
+    uint32_t pitch;
+    uint32_t fFlags;
+} VBOXVDMA_SURF_DESC, *PVBOXVDMA_SURF_DESC;
+
+/*typedef uint64_t VBOXVDMAPHADDRESS;*/
+typedef uint64_t VBOXVDMASURFHANDLE;
+
+/* region specified as a rectangle, otherwize it is a size of memory pointed to by phys address */
+#define VBOXVDMAOPERAND_FLAGS_RECTL       0x1
+/* Surface handle is valid */
+#define VBOXVDMAOPERAND_FLAGS_PRIMARY        0x2
+/* address is offset in VRAM */
+#define VBOXVDMAOPERAND_FLAGS_VRAMOFFSET  0x4
+
+
+/* VBOXVDMACBUF_DR::phBuf specifies offset in VRAM */
+#define VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET 0x00000001
+/* command buffer follows the VBOXVDMACBUF_DR in VRAM, VBOXVDMACBUF_DR::phBuf is ignored */
+#define VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR  0x00000002
+
+/*
+ * We can not submit the DMA command via VRAM since we do not have control over
+ * DMA command buffer [de]allocation, i.e. we only control the buffer contents.
+ * In other words the system may call one of our callbacks to fill a command buffer
+ * with the necessary commands and then discard the buffer w/o any notification.
+ *
+ * We have only DMA command buffer physical address at submission time.
+ *
+ * so the only way is to */
+typedef struct VBOXVDMACBUF_DR
+{
+    uint16_t fFlags;
+    uint16_t cbBuf;
+    /* RT_SUCCESS()     - on success
+     * VERR_INTERRUPTED - on preemption
+     * VERR_xxx         - on error */
+    int32_t  rc;
+    union
+    {
+        uint64_t phBuf;
+        VBOXVIDEOOFFSET offVramBuf;
+    } Location;
+    uint64_t aGuestData[7];
+} VBOXVDMACBUF_DR, *PVBOXVDMACBUF_DR;
+
+#define VBOXVDMACBUF_DR_TAIL(_pCmd, _t) ( (_t*)(((uint8_t*)(_pCmd)) + sizeof (VBOXVDMACBUF_DR)) )
+#define VBOXVDMACBUF_DR_FROM_TAIL(_pCmd) ( (VBOXVDMACBUF_DR*)(((uint8_t*)(_pCmd)) - sizeof (VBOXVDMACBUF_DR)) )
+
+typedef struct VBOXVDMACMD
+{
+    VBOXVDMACMD_TYPE enmType;
+    uint32_t u32CmdSpecific;
+} VBOXVDMACMD, *PVBOXVDMACMD;
+
+#define VBOXVDMACMD_HEADER_SIZE() sizeof (VBOXVDMACMD)
+#define VBOXVDMACMD_SIZE_FROMBODYSIZE(_s) (VBOXVDMACMD_HEADER_SIZE() + (_s))
+#define VBOXVDMACMD_SIZE(_t) (VBOXVDMACMD_SIZE_FROMBODYSIZE(sizeof (_t)))
+#define VBOXVDMACMD_BODY(_pCmd, _t) ( (_t*)(((uint8_t*)(_pCmd)) + VBOXVDMACMD_HEADER_SIZE()) )
+#define VBOXVDMACMD_BODY_SIZE(_s) ( (_s) - VBOXVDMACMD_HEADER_SIZE() )
+#define VBOXVDMACMD_FROM_BODY(_pCmd) ( (VBOXVDMACMD*)(((uint8_t*)(_pCmd)) - VBOXVDMACMD_HEADER_SIZE()) )
+#define VBOXVDMACMD_BODY_FIELD_OFFSET(_ot, _t, _f) ( (_ot)(uintptr_t)( VBOXVDMACMD_BODY(0, uint8_t) + RT_OFFSETOF(_t, _f) ) )
+
+typedef struct VBOXVDMACMD_DMA_PRESENT_BLT
+{
+    VBOXVIDEOOFFSET offSrc;
+    VBOXVIDEOOFFSET offDst;
+    VBOXVDMA_SURF_DESC srcDesc;
+    VBOXVDMA_SURF_DESC dstDesc;
+    VBOXVDMA_RECTL srcRectl;
+    VBOXVDMA_RECTL dstRectl;
+    uint32_t u32Reserved;
+    uint32_t cDstSubRects;
+    VBOXVDMA_RECTL aDstSubRects[1];
+} VBOXVDMACMD_DMA_PRESENT_BLT, *PVBOXVDMACMD_DMA_PRESENT_BLT;
+
+typedef struct VBOXVDMACMD_DMA_PRESENT_SHADOW2PRIMARY
+{
+    VBOXVDMA_RECTL Rect;
+} VBOXVDMACMD_DMA_PRESENT_SHADOW2PRIMARY, *PVBOXVDMACMD_DMA_PRESENT_SHADOW2PRIMARY;
+
+
+#define VBOXVDMACMD_DMA_BPB_TRANSFER_F_SRC_VRAMOFFSET 0x00000001
+#define VBOXVDMACMD_DMA_BPB_TRANSFER_F_DST_VRAMOFFSET 0x00000002
+
+typedef struct VBOXVDMACMD_DMA_BPB_TRANSFER
+{
+    uint32_t cbTransferSize;
+    uint32_t fFlags;
+    union
+    {
+        uint64_t phBuf;
+        VBOXVIDEOOFFSET offVramBuf;
+    } Src;
+    union
+    {
+        uint64_t phBuf;
+        VBOXVIDEOOFFSET offVramBuf;
+    } Dst;
+} VBOXVDMACMD_DMA_BPB_TRANSFER, *PVBOXVDMACMD_DMA_BPB_TRANSFER;
+
+#define VBOXVDMACMD_SYSMEMEL_F_PAGELIST 0x00000001
+
+typedef struct VBOXVDMACMD_SYSMEMEL
+{
+    uint32_t cPages;
+    uint32_t fFlags;
+    uint64_t phBuf[1];
+} VBOXVDMACMD_SYSMEMEL, *PVBOXVDMACMD_SYSMEMEL;
+
+#define VBOXVDMACMD_SYSMEMEL_NEXT(_pEl) (((_pEl)->fFlags & VBOXVDMACMD_SYSMEMEL_F_PAGELIST) ? \
+        ((PVBOXVDMACMD_SYSMEMEL)(((uint8_t*)(_pEl))+RT_OFFSETOF(VBOXVDMACMD_SYSMEMEL, phBuf[(_pEl)->cPages]))) \
+        : \
+        ((_pEl)+1)
+
+#define VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS_SYS2VRAM 0x00000001
+
+typedef struct VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS
+{
+    uint32_t cTransferPages;
+    uint32_t fFlags;
+    VBOXVIDEOOFFSET offVramBuf;
+    VBOXVDMACMD_SYSMEMEL FirstEl;
+} VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS, *PVBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS;
+
+typedef struct VBOXVDMACMD_DMA_BPB_FILL
+{
+    VBOXVIDEOOFFSET offSurf;
+    uint32_t cbFillSize;
+    uint32_t u32FillPattern;
+} VBOXVDMACMD_DMA_BPB_FILL, *PVBOXVDMACMD_DMA_BPB_FILL;
+
+#define VBOXVDMA_CHILD_STATUS_F_CONNECTED    0x01
+#define VBOXVDMA_CHILD_STATUS_F_DISCONNECTED 0x02
+#define VBOXVDMA_CHILD_STATUS_F_ROTATED      0x04
+
+typedef struct VBOXVDMA_CHILD_STATUS
+{
+    uint32_t iChild;
+    uint8_t  fFlags;
+    uint8_t  u8RotationAngle;
+    uint16_t u16Reserved;
+} VBOXVDMA_CHILD_STATUS, *PVBOXVDMA_CHILD_STATUS;
+
+/* apply the aInfos are applied to all targets, the iTarget is ignored */
+#define VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL 0x00000001
+
+typedef struct VBOXVDMACMD_CHILD_STATUS_IRQ
+{
+    uint32_t cInfos;
+    uint32_t fFlags;
+    VBOXVDMA_CHILD_STATUS aInfos[1];
+} VBOXVDMACMD_CHILD_STATUS_IRQ, *PVBOXVDMACMD_CHILD_STATUS_IRQ;
+
+# pragma pack()
+#endif /* #ifdef VBOX_WITH_VDMA */
+
+#pragma pack(1)
+typedef struct VBOXVDMACMD_CHROMIUM_BUFFER
+{
+    VBOXVIDEOOFFSET offBuffer;
+    uint32_t cbBuffer;
+    uint32_t u32GuestData;
+    uint64_t u64GuestData;
+} VBOXVDMACMD_CHROMIUM_BUFFER, *PVBOXVDMACMD_CHROMIUM_BUFFER;
+
+typedef struct VBOXVDMACMD_CHROMIUM_CMD
+{
+    uint32_t cBuffers;
+    uint32_t u32Reserved;
+    VBOXVDMACMD_CHROMIUM_BUFFER aBuffers[1];
+} VBOXVDMACMD_CHROMIUM_CMD, *PVBOXVDMACMD_CHROMIUM_CMD;
+
+typedef enum
+{
+    VBOXVDMACMD_CHROMIUM_CTL_TYPE_UNKNOWN = 0,
+    VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP,
+    VBOXVDMACMD_CHROMIUM_CTL_TYPE_SAVESTATE_BEGIN,
+    VBOXVDMACMD_CHROMIUM_CTL_TYPE_SAVESTATE_END,
+    VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_MAINCB,
+    VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRCONNECT,
+    VBOXVDMACMD_CHROMIUM_CTL_TYPE_SIZEHACK = 0x7fffffff
+} VBOXVDMACMD_CHROMIUM_CTL_TYPE;
+
+typedef struct VBOXVDMACMD_CHROMIUM_CTL
+{
+    VBOXVDMACMD_CHROMIUM_CTL_TYPE enmType;
+    uint32_t cbCmd;
+} VBOXVDMACMD_CHROMIUM_CTL, *PVBOXVDMACMD_CHROMIUM_CTL;
+
+
+typedef struct PDMIDISPLAYVBVACALLBACKS *HCRHGSMICMDCOMPLETION;
+typedef DECLCALLBACK(int) FNCRHGSMICMDCOMPLETION(HCRHGSMICMDCOMPLETION hCompletion, PVBOXVDMACMD_CHROMIUM_CMD pCmd, int rc);
+typedef FNCRHGSMICMDCOMPLETION *PFNCRHGSMICMDCOMPLETION;
+
+/* tells whether 3D backend has some 3D overlay data displayed */
+typedef DECLCALLBACK(bool) FNCROGLHASDATA(void);
+typedef FNCROGLHASDATA *PFNCROGLHASDATA;
+
+/* same as PFNCROGLHASDATA, but for specific screen */
+typedef DECLCALLBACK(bool) FNCROGLHASDATAFORSCREEN(uint32_t i32ScreenID);
+typedef FNCROGLHASDATAFORSCREEN *PFNCROGLHASDATAFORSCREEN;
+
+/* callbacks chrogl gives to main */
+typedef struct CR_MAIN_INTERFACE
+{
+    PFNCROGLHASDATA pfnHasData;
+    PFNCROGLHASDATAFORSCREEN pfnHasDataForScreen;
+} CR_MAIN_INTERFACE;
+
+typedef struct VBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB
+{
+    VBOXVDMACMD_CHROMIUM_CTL Hdr;
+    /*in*/
+    HCRHGSMICMDCOMPLETION hCompletion;
+    PFNCRHGSMICMDCOMPLETION pfnCompletion;
+    /*out*/
+    CR_MAIN_INTERFACE MainInterface;
+} VBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB, *PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB;
+
+typedef struct VBOXCRCON_SERVER *HVBOXCRCON_SERVER;
+typedef struct PDMIDISPLAYVBVACALLBACKS* HVBOXCRCON_CLIENT;
+
+typedef struct VBOXCRCON_3DRGN_CLIENT* HVBOXCRCON_3DRGN_CLIENT;
+typedef struct VBOXCRCON_3DRGN_ASYNCCLIENT* HVBOXCRCON_3DRGN_ASYNCCLIENT;
+
+/* server callbacks */
+/* submit chromium cmd */
+typedef DECLCALLBACK(int) FNVBOXCRCON_SVR_CRCMD(HVBOXCRCON_SERVER hServer, PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd);
+typedef FNVBOXCRCON_SVR_CRCMD *PFNVBOXCRCON_SVR_CRCMD;
+
+/* submit chromium control cmd */
+typedef DECLCALLBACK(int) FNVBOXCRCON_SVR_CRCTL(HVBOXCRCON_SERVER hServer, PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCmd);
+typedef FNVBOXCRCON_SVR_CRCTL *PFNVBOXCRCON_SVR_CRCTL;
+
+/* request 3D data.
+ * The protocol is the following:
+ * 1. if there is no 3D data displayed on screen, returns VINF_EOF immediately w/o calling any PFNVBOXCRCON_3DRGN_XXX callbacks
+ * 2. otherwise calls PFNVBOXCRCON_3DRGN_ONSUBMIT, submits the "regions get" request to the CrOpenGL server to process it asynchronously and returns VINF_SUCCESS
+ * 2.a on "regions get" request processing calls PFNVBOXCRCON_3DRGN_BEGIN,
+ * 2.b then PFNVBOXCRCON_3DRGN_REPORT zero or more times for each 3D region,
+ * 2.c and then PFNVBOXCRCON_3DRGN_END
+ * 3. returns VERR_XXX code on failure
+ * */
+typedef DECLCALLBACK(int) FNVBOXCRCON_SVR_3DRGN_GET(HVBOXCRCON_SERVER hServer, HVBOXCRCON_3DRGN_CLIENT hRgnClient, uint32_t idScreen);
+typedef FNVBOXCRCON_SVR_3DRGN_GET *PFNVBOXCRCON_SVR_3DRGN_GET;
+
+/* 3D Regions Client callbacks */
+/* called from the PFNVBOXCRCON_SVR_3DRGN_GET callback in case server has 3D data and is going to process the request asynchronously,
+ * see comments for PFNVBOXCRCON_SVR_3DRGN_GET above */
+typedef DECLCALLBACK(int) FNVBOXCRCON_3DRGN_ONSUBMIT(HVBOXCRCON_3DRGN_CLIENT hRgnClient, uint32_t idScreen, HVBOXCRCON_3DRGN_ASYNCCLIENT *phRgnAsyncClient);
+typedef FNVBOXCRCON_3DRGN_ONSUBMIT *PFNVBOXCRCON_3DRGN_ONSUBMIT;
+
+/* called from the "regions get" command processing thread, to indicate that the "regions get" is started.
+ * see comments for PFNVBOXCRCON_SVR_3DRGN_GET above */
+typedef DECLCALLBACK(int) FNVBOXCRCON_3DRGN_BEGIN(HVBOXCRCON_3DRGN_ASYNCCLIENT hRgnAsyncClient, uint32_t idScreen);
+typedef FNVBOXCRCON_3DRGN_BEGIN *PFNVBOXCRCON_3DRGN_BEGIN;
+
+/* called from the "regions get" command processing thread, to report a 3D region.
+ * see comments for PFNVBOXCRCON_SVR_3DRGN_GET above */
+typedef DECLCALLBACK(int) FNVBOXCRCON_3DRGN_REPORT(HVBOXCRCON_3DRGN_ASYNCCLIENT hRgnAsyncClient, uint32_t idScreen, void *pvData, uint32_t cbStride, const RTRECT *pRect);
+typedef FNVBOXCRCON_3DRGN_REPORT *PFNVBOXCRCON_3DRGN_REPORT;
+
+/* called from the "regions get" command processing thread, to indicate that the "regions get" is completed.
+ * see comments for PFNVBOXCRCON_SVR_3DRGN_GET above */
+typedef DECLCALLBACK(int) FNVBOXCRCON_3DRGN_END(HVBOXCRCON_3DRGN_ASYNCCLIENT hRgnAsyncClient, uint32_t idScreen);
+typedef FNVBOXCRCON_3DRGN_END *PFNVBOXCRCON_3DRGN_END;
+
+
+/* client callbacks */
+/* complete chromium cmd */
+typedef DECLCALLBACK(int) FNVBOXCRCON_CLT_CRCTL_COMPLETE(HVBOXCRCON_CLIENT hClient, PVBOXVDMACMD_CHROMIUM_CTL pCtl, int rc);
+typedef FNVBOXCRCON_CLT_CRCTL_COMPLETE *PFNVBOXCRCON_CLT_CRCTL_COMPLETE;
+
+/* complete chromium control cmd */
+typedef DECLCALLBACK(int) FNVBOXCRCON_CLT_CRCMD_COMPLETE(HVBOXCRCON_CLIENT hClient, PVBOXVDMACMD_CHROMIUM_CMD pCmd, int rc);
+typedef FNVBOXCRCON_CLT_CRCMD_COMPLETE *PFNVBOXCRCON_CLT_CRCMD_COMPLETE;
+
+typedef struct VBOXCRCON_SERVER_CALLBACKS
+{
+    HVBOXCRCON_SERVER hServer;
+    PFNVBOXCRCON_SVR_CRCMD pfnCrCmd;
+    PFNVBOXCRCON_SVR_CRCTL pfnCrCtl;
+    PFNVBOXCRCON_SVR_3DRGN_GET pfn3DRgnGet;
+} VBOXCRCON_SERVER_CALLBACKS, *PVBOXCRCON_SERVER_CALLBACKS;
+
+typedef struct VBOXCRCON_CLIENT_CALLBACKS
+{
+    HVBOXCRCON_CLIENT hClient;
+    PFNVBOXCRCON_CLT_CRCMD_COMPLETE pfnCrCmdComplete;
+    PFNVBOXCRCON_CLT_CRCTL_COMPLETE pfnCrCtlComplete;
+    PFNVBOXCRCON_3DRGN_ONSUBMIT pfn3DRgnOnSubmit;
+    PFNVBOXCRCON_3DRGN_BEGIN pfn3DRgnBegin;
+    PFNVBOXCRCON_3DRGN_REPORT pfn3DRgnReport;
+    PFNVBOXCRCON_3DRGN_END pfn3DRgnEnd;
+} VBOXCRCON_CLIENT_CALLBACKS, *PVBOXCRCON_CLIENT_CALLBACKS;
+
+/* issued by Main to establish connection between Main and CrOpenGL service */
+typedef struct VBOXVDMACMD_CHROMIUM_CTL_CRCONNECT
+{
+    VBOXVDMACMD_CHROMIUM_CTL Hdr;
+    /*input (filled by Client) :*/
+    /*class VMMDev*/void *pVMMDev;
+    VBOXCRCON_CLIENT_CALLBACKS ClientCallbacks;
+    /*output (filled by Server) :*/
+    VBOXCRCON_SERVER_CALLBACKS ServerCallbacks;
+} VBOXVDMACMD_CHROMIUM_CTL_CRCONNECT, *PVBOXVDMACMD_CHROMIUM_CTL_CRCONNECT;
+
+/* ring command buffer dr */
+#define VBOXCMDVBVA_STATE_SUBMITTED   1
+#define VBOXCMDVBVA_STATE_CANCELLED   2
+#define VBOXCMDVBVA_STATE_IN_PROGRESS 3
+/* the "completed" state is signalled via the ring buffer values */
+
+/* CrHgsmi command */
+#define VBOXCMDVBVA_OPTYPE_CRCMD                        1
+/* blit command that does blitting of allocations identified by VRAM offset or host id
+ * for VRAM-offset ones the size and format are same as primary */
+#define VBOXCMDVBVA_OPTYPE_BLT                          2
+/* flip */
+#define VBOXCMDVBVA_OPTYPE_FLIP                         3
+/* ColorFill */
+#define VBOXCMDVBVA_OPTYPE_CLRFILL                      4
+/* allocation paging transfer request */
+#define VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER              5
+/* allocation paging fill request */
+#define VBOXCMDVBVA_OPTYPE_PAGING_FILL                  6
+/* same as VBOXCMDVBVA_OPTYPE_NOP, but contains VBOXCMDVBVA_HDR data */
+#define VBOXCMDVBVA_OPTYPE_NOPCMD                       7
+/* actual command is stored in guest system memory */
+#define VBOXCMDVBVA_OPTYPE_SYSMEMCMD                    8
+/* complex command - i.e. can contain multiple commands
+ * i.e. the VBOXCMDVBVA_OPTYPE_COMPLEXCMD VBOXCMDVBVA_HDR is followed
+ * by one or more VBOXCMDVBVA_HDR commands.
+ * Each command's size is specified in it's VBOXCMDVBVA_HDR's u32FenceID field */
+#define VBOXCMDVBVA_OPTYPE_COMPLEXCMD                   9
+
+/* nop - is a one-bit command. The buffer size to skip is determined by VBVA buffer size */
+#define VBOXCMDVBVA_OPTYPE_NOP                          0x80
+
+/* u8Flags flags */
+/* transfer from RAM to Allocation */
+#define VBOXCMDVBVA_OPF_PAGING_TRANSFER_IN                  0x80
+
+#define VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8           0
+#define VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8           1
+#define VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID         2
+
+#define VBOXCMDVBVA_OPF_BLT_TYPE_MASK                       3
+
+
+#define VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8       0
+
+#define VBOXCMDVBVA_OPF_CLRFILL_TYPE_MASK                   1
+
+
+/* blit direction is from first operand to second */
+#define VBOXCMDVBVA_OPF_BLT_DIR_IN_2                        0x10
+/* operand 1 contains host id */
+#define VBOXCMDVBVA_OPF_OPERAND1_ISID                       0x20
+/* operand 2 contains host id */
+#define VBOXCMDVBVA_OPF_OPERAND2_ISID                       0x40
+/* primary hint id is src */
+#define VBOXCMDVBVA_OPF_PRIMARY_HINT_SRC                    0x80
+
+/* trying to make the header as small as possible,
+ * we'd have pretty few op codes actually, so 8bit is quite enough,
+ * we will be able to extend it in any way. */
+typedef struct VBOXCMDVBVA_HDR
+{
+    /* one VBOXCMDVBVA_OPTYPE_XXX, except NOP, see comments above */
+    uint8_t u8OpCode;
+    /* command-specific
+     * VBOXCMDVBVA_OPTYPE_CRCMD                     - must be null
+     * VBOXCMDVBVA_OPTYPE_BLT                       - OR-ed VBOXCMDVBVA_OPF_ALLOC_XXX flags
+     * VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER           - must be null
+     * VBOXCMDVBVA_OPTYPE_PAGING_FILL               - must be null
+     * VBOXCMDVBVA_OPTYPE_NOPCMD                    - must be null
+     * VBOXCMDVBVA_OPTYPE_NOP                       - not applicable (as the entire VBOXCMDVBVA_HDR is not valid) */
+    uint8_t u8Flags;
+    /* one of VBOXCMDVBVA_STATE_XXX*/
+    volatile uint8_t u8State;
+    union
+    {
+        /* result, 0 on success, otherwise contains the failure code TBD */
+        int8_t i8Result;
+        uint8_t u8PrimaryID;
+    } u;
+    union
+    {
+        /* complex command (VBOXCMDVBVA_OPTYPE_COMPLEXCMD) element data */
+        struct
+        {
+            /* command length */
+            uint16_t u16CbCmdHost;
+            /* guest-specific data, host expects it to be NULL */
+            uint16_t u16CbCmdGuest;
+        } complexCmdEl;
+        /* DXGK DDI fence ID */
+        uint32_t u32FenceID;
+    } u2;
+} VBOXCMDVBVA_HDR;
+
+typedef uint32_t VBOXCMDVBVAOFFSET;
+typedef uint64_t VBOXCMDVBVAPHADDR;
+typedef uint32_t VBOXCMDVBVAPAGEIDX;
+
+typedef struct VBOXCMDVBVA_CRCMD_BUFFER
+{
+    uint32_t cbBuffer;
+    VBOXCMDVBVAOFFSET offBuffer;
+} VBOXCMDVBVA_CRCMD_BUFFER;
+
+typedef struct VBOXCMDVBVA_CRCMD_CMD
+{
+    uint32_t cBuffers;
+    VBOXCMDVBVA_CRCMD_BUFFER aBuffers[1];
+} VBOXCMDVBVA_CRCMD_CMD;
+
+typedef struct VBOXCMDVBVA_CRCMD
+{
+    VBOXCMDVBVA_HDR Hdr;
+    VBOXCMDVBVA_CRCMD_CMD Cmd;
+} VBOXCMDVBVA_CRCMD;
+
+typedef struct VBOXCMDVBVA_ALLOCINFO
+{
+    union
+    {
+        VBOXCMDVBVAOFFSET offVRAM;
+        uint32_t id;
+    } u;
+} VBOXCMDVBVA_ALLOCINFO;
+
+typedef struct VBOXCMDVBVA_ALLOCDESC
+{
+    VBOXCMDVBVA_ALLOCINFO Info;
+    uint16_t u16Width;
+    uint16_t u16Height;
+} VBOXCMDVBVA_ALLOCDESC;
+
+typedef struct VBOXCMDVBVA_RECT
+{
+   /** Coordinates of affected rectangle. */
+   int16_t xLeft;
+   int16_t yTop;
+   int16_t xRight;
+   int16_t yBottom;
+} VBOXCMDVBVA_RECT;
+
+typedef struct VBOXCMDVBVA_POINT
+{
+   int16_t x;
+   int16_t y;
+} VBOXCMDVBVA_POINT;
+
+typedef struct VBOXCMDVBVA_BLT_HDR
+{
+    VBOXCMDVBVA_HDR Hdr;
+    VBOXCMDVBVA_POINT Pos;
+} VBOXCMDVBVA_BLT_HDR;
+
+typedef struct VBOXCMDVBVA_BLT_PRIMARY
+{
+    VBOXCMDVBVA_BLT_HDR Hdr;
+    VBOXCMDVBVA_ALLOCINFO alloc;
+    /* the rects count is determined from the command size */
+    VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_BLT_PRIMARY;
+
+typedef struct VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8
+{
+    VBOXCMDVBVA_BLT_HDR Hdr;
+    VBOXCMDVBVA_ALLOCDESC alloc;
+    /* the rects count is determined from the command size */
+    VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8;
+
+typedef struct VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID
+{
+    VBOXCMDVBVA_BLT_HDR Hdr;
+    VBOXCMDVBVA_ALLOCINFO alloc;
+    uint32_t id;
+    /* the rects count is determined from the command size */
+    VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID;
+
+typedef struct VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8
+{
+    VBOXCMDVBVA_BLT_HDR Hdr;
+    VBOXCMDVBVA_ALLOCDESC alloc1;
+    VBOXCMDVBVA_ALLOCINFO info2;
+    /* the rects count is determined from the command size */
+    VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8;
+
+typedef struct VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8
+{
+    VBOXCMDVBVA_BLT_HDR Hdr;
+    VBOXCMDVBVA_ALLOCDESC alloc1;
+    VBOXCMDVBVA_ALLOCDESC alloc2;
+    /* the rects count is determined from the command size */
+    VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8;
+
+#define VBOXCMDVBVA_SIZEOF_BLTSTRUCT_MAX (sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
+
+typedef struct VBOXCMDVBVA_FLIP
+{
+    VBOXCMDVBVA_HDR Hdr;
+    VBOXCMDVBVA_ALLOCINFO src;
+    VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_FLIP;
+
+#define VBOXCMDVBVA_SIZEOF_FLIPSTRUCT_MIN (RT_OFFSETOF(VBOXCMDVBVA_FLIP, aRects))
+
+typedef struct VBOXCMDVBVA_CLRFILL_HDR
+{
+    VBOXCMDVBVA_HDR Hdr;
+    uint32_t u32Color;
+} VBOXCMDVBVA_CLRFILL_HDR;
+
+typedef struct VBOXCMDVBVA_CLRFILL_PRIMARY
+{
+    VBOXCMDVBVA_CLRFILL_HDR Hdr;
+    VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_CLRFILL_PRIMARY;
+
+typedef struct VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8
+{
+    VBOXCMDVBVA_CLRFILL_HDR Hdr;
+    VBOXCMDVBVA_ALLOCDESC dst;
+    VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8;
+
+#define VBOXCMDVBVA_SIZEOF_CLRFILLSTRUCT_MAX (sizeof (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8))
+
+#if 0
+#define VBOXCMDVBVA_SYSMEMEL_CPAGES_MAX  0x1000
+
+typedef struct VBOXCMDVBVA_SYSMEMEL
+{
+    uint32_t cPagesAfterFirst  : 12;
+    uint32_t iPage1            : 20;
+    uint32_t iPage2;
+} VBOXCMDVBVA_SYSMEMEL;
+#endif
+
+typedef struct VBOXCMDVBVA_PAGING_TRANSFER_DATA
+{
+    /* for now can only contain offVRAM.
+     * paging transfer can NOT be initiated for allocations having host 3D object (hostID) associated */
+    VBOXCMDVBVA_ALLOCINFO Alloc;
+    VBOXCMDVBVAPAGEIDX aPageNumbers[1];
+} VBOXCMDVBVA_PAGING_TRANSFER_DATA;
+
+typedef struct VBOXCMDVBVA_PAGING_TRANSFER
+{
+    VBOXCMDVBVA_HDR Hdr;
+    VBOXCMDVBVA_PAGING_TRANSFER_DATA Data;
+} VBOXCMDVBVA_PAGING_TRANSFER;
+
+typedef struct VBOXCMDVBVA_PAGING_FILL
+{
+    VBOXCMDVBVA_HDR Hdr;
+    uint32_t u32CbFill;
+    uint32_t u32Pattern;
+    /* paging transfer can NOT be initiated for allocations having host 3D object (hostID) associated */
+    VBOXCMDVBVAOFFSET offVRAM;
+} VBOXCMDVBVA_PAGING_FILL;
+
+typedef struct VBOXCMDVBVA_SYSMEMCMD
+{
+    VBOXCMDVBVA_HDR Hdr;
+    VBOXCMDVBVAPHADDR phCmd;
+} VBOXCMDVBVA_SYSMEMCMD;
+
+#define VBOXCMDVBVACTL_TYPE_ENABLE     1
+#define VBOXCMDVBVACTL_TYPE_3DCTL      2
+#define VBOXCMDVBVACTL_TYPE_RESIZE     3
+
+typedef struct VBOXCMDVBVA_CTL
+{
+    uint32_t u32Type;
+    int32_t i32Result;
+} VBOXCMDVBVA_CTL;
+
+typedef struct VBOXCMDVBVA_CTL_ENABLE
+{
+    VBOXCMDVBVA_CTL Hdr;
+    VBVAENABLE Enable;
+} VBOXCMDVBVA_CTL_ENABLE;
+
+#define VBOXCMDVBVA_SCREENMAP_SIZE(_elType) ((VBOX_VIDEO_MAX_SCREENS + sizeof (_elType) - 1) / sizeof (_elType))
+#define VBOXCMDVBVA_SCREENMAP_DECL(_elType, _name) _elType _name[VBOXCMDVBVA_SCREENMAP_SIZE(_elType)]
+
+typedef struct VBOXCMDVBVA_RESIZE_ENTRY
+{
+    VBVAINFOSCREEN Screen;
+    VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
+} VBOXCMDVBVA_RESIZE_ENTRY;
+
+typedef struct VBOXCMDVBVA_RESIZE
+{
+    VBOXCMDVBVA_RESIZE_ENTRY aEntries[1];
+} VBOXCMDVBVA_RESIZE;
+
+typedef struct VBOXCMDVBVA_CTL_RESIZE
+{
+    VBOXCMDVBVA_CTL Hdr;
+    VBOXCMDVBVA_RESIZE Resize;
+} VBOXCMDVBVA_CTL_RESIZE;
+
+#define VBOXCMDVBVA3DCTL_TYPE_CONNECT     1
+#define VBOXCMDVBVA3DCTL_TYPE_DISCONNECT  2
+#define VBOXCMDVBVA3DCTL_TYPE_CMD         3
+
+typedef struct VBOXCMDVBVA_3DCTL
+{
+    uint32_t u32Type;
+    uint32_t u32CmdClientId;
+} VBOXCMDVBVA_3DCTL;
+
+typedef struct VBOXCMDVBVA_3DCTL_CONNECT
+{
+    VBOXCMDVBVA_3DCTL Hdr;
+    uint32_t u32MajorVersion;
+    uint32_t u32MinorVersion;
+    uint64_t u64Pid;
+} VBOXCMDVBVA_3DCTL_CONNECT;
+
+typedef struct VBOXCMDVBVA_3DCTL_CMD
+{
+    VBOXCMDVBVA_3DCTL Hdr;
+    VBOXCMDVBVA_HDR Cmd;
+} VBOXCMDVBVA_3DCTL_CMD;
+
+typedef struct VBOXCMDVBVA_CTL_3DCTL_CMD
+{
+    VBOXCMDVBVA_CTL Hdr;
+    VBOXCMDVBVA_3DCTL_CMD Cmd;
+} VBOXCMDVBVA_CTL_3DCTL_CMD;
+
+typedef struct VBOXCMDVBVA_CTL_3DCTL_CONNECT
+{
+    VBOXCMDVBVA_CTL Hdr;
+    VBOXCMDVBVA_3DCTL_CONNECT Connect;
+} VBOXCMDVBVA_CTL_3DCTL_CONNECT;
+
+typedef struct VBOXCMDVBVA_CTL_3DCTL
+{
+    VBOXCMDVBVA_CTL Hdr;
+    VBOXCMDVBVA_3DCTL Ctl;
+} VBOXCMDVBVA_CTL_3DCTL;
+
+#pragma pack()
+
+
+#ifdef VBOXVDMA_WITH_VBVA
+# pragma pack(1)
+
+typedef struct VBOXVDMAVBVACMD
+{
+    HGSMIOFFSET offCmd;
+} VBOXVDMAVBVACMD;
+
+#pragma pack()
+#endif
+
+#endif
diff --git a/ubuntu/vbox/include/VBox/VBoxVideoGuest.h b/ubuntu/vbox/include/VBox/VBoxVideoGuest.h
new file mode 100644 (file)
index 0000000..b935924
--- /dev/null
@@ -0,0 +1,345 @@
+/** @file
+ * VBox Host Guest Shared Memory Interface (HGSMI).
+ * OS-independent guest structures.
+ */
+
+/*
+ * 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.
+ */
+
+
+#ifndef ___VBox_VBoxVideoGuest_h___
+#define ___VBox_VBoxVideoGuest_h___
+
+#include <VBox/HGSMI/HGSMI.h>
+#include <VBox/HGSMI/HGSMIChSetup.h>
+#include <VBox/VBoxVideo.h>
+
+#ifdef VBOX_XPDM_MINIPORT
+# include <iprt/nt/miniport.h>
+# include <ntddvdeo.h> /* sdk, clean */
+# include <iprt/nt/Video.h>
+#elif defined VBOX_GUESTR3XORGMOD
+# include <compiler.h>
+#else
+# include <iprt/asm-amd64-x86.h>
+#endif
+
+#ifdef VBOX_WDDM_MINIPORT
+# include "wddm/VBoxMPShgsmi.h"
+ typedef VBOXSHGSMI HGSMIGUESTCMDHEAP;
+# define HGSMIGUESTCMDHEAP_GET(_p) (&(_p)->Heap)
+#else
+ typedef HGSMIHEAP HGSMIGUESTCMDHEAP;
+# define HGSMIGUESTCMDHEAP_GET(_p) (_p)
+#endif
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Structure grouping the context needed for submitting commands to the host
+ * via HGSMI
+ */
+typedef struct HGSMIGUESTCOMMANDCONTEXT
+{
+    /** Information about the memory heap located in VRAM from which data
+     * structures to be sent to the host are allocated. */
+    HGSMIGUESTCMDHEAP heapCtx;
+    /** The I/O port used for submitting commands to the host by writing their
+     * offsets into the heap. */
+    RTIOPORT port;
+} HGSMIGUESTCOMMANDCONTEXT, *PHGSMIGUESTCOMMANDCONTEXT;
+
+
+/**
+ * Structure grouping the context needed for receiving commands from the host
+ * via HGSMI
+ */
+typedef struct HGSMIHOSTCOMMANDCONTEXT
+{
+    /** Information about the memory area located in VRAM in which the host
+     * places data structures to be read by the guest. */
+    HGSMIAREA areaCtx;
+    /** Convenience structure used for matching host commands to handlers. */
+    /** @todo handlers are registered individually in code rather than just
+     * passing a static structure in order to gain extra flexibility.  There is
+     * currently no expected usage case for this though.  Is the additional
+     * complexity really justified? */
+    HGSMICHANNELINFO channels;
+    /** Flag to indicate that one thread is currently processing the command
+     * queue. */
+    volatile bool fHostCmdProcessing;
+    /* Pointer to the VRAM location where the HGSMI host flags are kept. */
+    volatile HGSMIHOSTFLAGS *pfHostFlags;
+    /** The I/O port used for receiving commands from the host as offsets into
+     * the memory area and sending back confirmations (command completion,
+     * IRQ acknowlegement). */
+    RTIOPORT port;
+} HGSMIHOSTCOMMANDCONTEXT, *PHGSMIHOSTCOMMANDCONTEXT;
+
+
+/**
+ * Structure grouping the context needed for sending graphics acceleration
+ * information to the host via VBVA.  Each screen has its own VBVA buffer.
+ */
+typedef struct VBVABUFFERCONTEXT
+{
+    /** Offset of the buffer in the VRAM section for the screen */
+    uint32_t    offVRAMBuffer;
+    /** Length of the buffer in bytes */
+    uint32_t    cbBuffer;
+    /** This flag is set if we wrote to the buffer faster than the host could
+     * read it. */
+    bool        fHwBufferOverflow;
+    /** The VBVA record that we are currently preparing for the host, NULL if
+     * none. */
+    struct VBVARECORD *pRecord;
+    /** Pointer to the VBVA buffer mapped into the current address space.  Will
+     * be NULL if VBVA is not enabled. */
+    struct VBVABUFFER *pVBVA;
+} VBVABUFFERCONTEXT, *PVBVABUFFERCONTEXT;
+
+/** @name Helper functions
+ * @{ */
+/** Write an 8-bit value to an I/O port. */
+DECLINLINE(void) VBoxVideoCmnPortWriteUchar(RTIOPORT Port, uint8_t Value)
+{
+#ifdef VBOX_XPDM_MINIPORT
+    VideoPortWritePortUchar((PUCHAR)Port, Value);
+#elif defined VBOX_GUESTR3XORGMOD
+    outb(Port, Value);
+#else  /** @todo make these explicit */
+    ASMOutU8(Port, Value);
+#endif
+}
+
+/** Write a 16-bit value to an I/O port. */
+DECLINLINE(void) VBoxVideoCmnPortWriteUshort(RTIOPORT Port, uint16_t Value)
+{
+#ifdef VBOX_XPDM_MINIPORT
+    VideoPortWritePortUshort((PUSHORT)Port,Value);
+#elif defined VBOX_GUESTR3XORGMOD
+    outw(Port, Value);
+#else
+    ASMOutU16(Port, Value);
+#endif
+}
+
+/** Write a 32-bit value to an I/O port. */
+DECLINLINE(void) VBoxVideoCmnPortWriteUlong(RTIOPORT Port, uint32_t Value)
+{
+#ifdef VBOX_XPDM_MINIPORT
+    VideoPortWritePortUlong((PULONG)Port,Value);
+#elif defined VBOX_GUESTR3XORGMOD
+    outl(Port, Value);
+#else
+    ASMOutU32(Port, Value);
+#endif
+}
+
+/** Read an 8-bit value from an I/O port. */
+DECLINLINE(uint8_t) VBoxVideoCmnPortReadUchar(RTIOPORT Port)
+{
+#ifdef VBOX_XPDM_MINIPORT
+    return VideoPortReadPortUchar((PUCHAR)Port);
+#elif defined VBOX_GUESTR3XORGMOD
+    return inb(Port);
+#else
+    return ASMInU8(Port);
+#endif
+}
+
+/** Read a 16-bit value from an I/O port. */
+DECLINLINE(uint16_t) VBoxVideoCmnPortReadUshort(RTIOPORT Port)
+{
+#ifdef VBOX_XPDM_MINIPORT
+    return VideoPortReadPortUshort((PUSHORT)Port);
+#elif defined VBOX_GUESTR3XORGMOD
+    return inw(Port);
+#else
+    return ASMInU16(Port);
+#endif
+}
+
+/** Read a 32-bit value from an I/O port. */
+DECLINLINE(uint32_t) VBoxVideoCmnPortReadUlong(RTIOPORT Port)
+{
+#ifdef VBOX_XPDM_MINIPORT
+    return VideoPortReadPortUlong((PULONG)Port);
+#elif defined VBOX_GUESTR3XORGMOD
+    return inl(Port);
+#else
+    return ASMInU32(Port);
+#endif
+}
+
+/** @}  */
+
+/** @name Base HGSMI APIs
+ * @{ */
+
+/** Acknowlege an IRQ. */
+DECLINLINE(void) VBoxHGSMIClearIrq(PHGSMIHOSTCOMMANDCONTEXT pCtx)
+{
+    VBoxVideoCmnPortWriteUlong(pCtx->port, HGSMIOFFSET_VOID);
+}
+
+DECLHIDDEN(void)     VBoxHGSMIHostCmdComplete(PHGSMIHOSTCOMMANDCONTEXT pCtx,
+                                              void *pvMem);
+DECLHIDDEN(void)     VBoxHGSMIProcessHostQueue(PHGSMIHOSTCOMMANDCONTEXT pCtx);
+DECLHIDDEN(bool)     VBoxHGSMIIsSupported(void);
+DECLHIDDEN(void *)   VBoxHGSMIBufferAlloc(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                          HGSMISIZE cbData,
+                                          uint8_t u8Ch,
+                                          uint16_t u16Op);
+DECLHIDDEN(void)     VBoxHGSMIBufferFree(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                         void *pvBuffer);
+DECLHIDDEN(int)      VBoxHGSMIBufferSubmit(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                           void *pvBuffer);
+DECLHIDDEN(void)     VBoxHGSMIGetBaseMappingInfo(uint32_t cbVRAM,
+                                                 uint32_t *poffVRAMBaseMapping,
+                                                 uint32_t *pcbMapping,
+                                                 uint32_t *poffGuestHeapMemory,
+                                                 uint32_t *pcbGuestHeapMemory,
+                                                 uint32_t *poffHostFlags);
+DECLHIDDEN(int)      VBoxHGSMIReportFlagsLocation(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                                  HGSMIOFFSET offLocation);
+DECLHIDDEN(int)      VBoxHGSMISendCapsInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                           uint32_t fCaps);
+/** @todo we should provide a cleanup function too as part of the API */
+DECLHIDDEN(int)      VBoxHGSMISetupGuestContext(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                                void *pvGuestHeapMemory,
+                                                uint32_t cbGuestHeapMemory,
+                                                uint32_t offVRAMGuestHeapMemory,
+                                                const HGSMIENV *pEnv);
+DECLHIDDEN(void)     VBoxHGSMIGetHostAreaMapping(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                                 uint32_t cbVRAM,
+                                                 uint32_t offVRAMBaseMapping,
+                                                 uint32_t *poffVRAMHostArea,
+                                                 uint32_t *pcbHostArea);
+DECLHIDDEN(void)     VBoxHGSMISetupHostContext(PHGSMIHOSTCOMMANDCONTEXT pCtx,
+                                               void *pvBaseMapping,
+                                               uint32_t offHostFlags,
+                                               void *pvHostAreaMapping,
+                                               uint32_t offVRAMHostArea,
+                                               uint32_t cbHostArea);
+DECLHIDDEN(int)      VBoxHGSMISendHostCtxInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                              HGSMIOFFSET offVRAMFlagsLocation,
+                                              uint32_t fCaps,
+                                              uint32_t offVRAMHostArea,
+                                              uint32_t cbHostArea);
+DECLHIDDEN(int)      VBoxQueryConfHGSMI(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                    uint32_t u32Index, uint32_t *pulValue);
+DECLHIDDEN(int)      VBoxQueryConfHGSMIDef(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                           uint32_t u32Index, uint32_t u32DefValue, uint32_t *pulValue);
+DECLHIDDEN(int)      VBoxHGSMIUpdatePointerShape(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                                 uint32_t fFlags,
+                                                 uint32_t cHotX,
+                                                 uint32_t cHotY,
+                                                 uint32_t cWidth,
+                                                 uint32_t cHeight,
+                                                 uint8_t *pPixels,
+                                                 uint32_t cbLength);
+DECLHIDDEN(int)      VBoxHGSMICursorPosition(PHGSMIGUESTCOMMANDCONTEXT pCtx, bool fReportPosition, uint32_t x, uint32_t y,
+                                             uint32_t *pxHost, uint32_t *pyHost);
+
+/** @}  */
+
+/** @name VBVA APIs
+ * @{ */
+DECLHIDDEN(bool) VBoxVBVAEnable(PVBVABUFFERCONTEXT pCtx,
+                                PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+                                struct VBVABUFFER *pVBVA, int32_t cScreen);
+DECLHIDDEN(void) VBoxVBVADisable(PVBVABUFFERCONTEXT pCtx,
+                                 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+                                 int32_t cScreen);
+DECLHIDDEN(bool) VBoxVBVABufferBeginUpdate(PVBVABUFFERCONTEXT pCtx,
+                                           PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx);
+DECLHIDDEN(void) VBoxVBVABufferEndUpdate(PVBVABUFFERCONTEXT pCtx);
+DECLHIDDEN(bool) VBoxVBVAWrite(PVBVABUFFERCONTEXT pCtx,
+                               PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+                               const void *pv, uint32_t cb);
+DECLHIDDEN(bool) VBoxVBVAOrderSupported(PVBVABUFFERCONTEXT pCtx, unsigned code);
+DECLHIDDEN(void) VBoxVBVASetupBufferContext(PVBVABUFFERCONTEXT pCtx,
+                                            uint32_t offVRAMBuffer,
+                                            uint32_t cbBuffer);
+
+/** @}  */
+
+/** @name Modesetting APIs
+ * @{ */
+
+DECLHIDDEN(uint32_t) VBoxHGSMIGetMonitorCount(PHGSMIGUESTCOMMANDCONTEXT pCtx);
+DECLHIDDEN(uint32_t) VBoxVideoGetVRAMSize(void);
+DECLHIDDEN(bool)     VBoxVideoAnyWidthAllowed(void);
+DECLHIDDEN(uint16_t) VBoxHGSMIGetScreenFlags(PHGSMIGUESTCOMMANDCONTEXT pCtx);
+
+struct VBVAINFOVIEW;
+/**
+ * Callback funtion called from @a VBoxHGSMISendViewInfo to initialise
+ * the @a VBVAINFOVIEW structure for each screen.
+ *
+ * @returns  iprt status code
+ * @param  pvData  context data for the callback, passed to @a
+ *                 VBoxHGSMISendViewInfo along with the callback
+ * @param  pInfo   array of @a VBVAINFOVIEW structures to be filled in
+ * @todo  explicitly pass the array size
+ */
+typedef DECLCALLBACK(int) FNHGSMIFILLVIEWINFO(void *pvData,
+                                              struct VBVAINFOVIEW *pInfo,
+                                              uint32_t cViews);
+/** Pointer to a FNHGSMIFILLVIEWINFO callback */
+typedef FNHGSMIFILLVIEWINFO *PFNHGSMIFILLVIEWINFO;
+
+DECLHIDDEN(int)      VBoxHGSMISendViewInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                           uint32_t u32Count,
+                                           PFNHGSMIFILLVIEWINFO pfnFill,
+                                           void *pvData);
+DECLHIDDEN(void)     VBoxVideoSetModeRegisters(uint16_t cWidth, uint16_t cHeight,
+                                               uint16_t cVirtWidth, uint16_t cBPP,
+                                               uint16_t fFlags,
+                                               uint16_t cx, uint16_t cy);
+DECLHIDDEN(bool)     VBoxVideoGetModeRegisters(uint16_t *pcWidth,
+                                               uint16_t *pcHeight,
+                                               uint16_t *pcVirtWidth,
+                                               uint16_t *pcBPP,
+                                               uint16_t *pfFlags);
+DECLHIDDEN(void)     VBoxVideoDisableVBE(void);
+DECLHIDDEN(void)     VBoxHGSMIProcessDisplayInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                                 uint32_t cDisplay,
+                                                 int32_t  cOriginX,
+                                                 int32_t  cOriginY,
+                                                 uint32_t offStart,
+                                                 uint32_t cbPitch,
+                                                 uint32_t cWidth,
+                                                 uint32_t cHeight,
+                                                 uint16_t cBPP,
+                                                 uint16_t fFlags);
+DECLHIDDEN(int)      VBoxHGSMIUpdateInputMapping(PHGSMIGUESTCOMMANDCONTEXT pCtx, int32_t  cOriginX, int32_t  cOriginY,
+                                                 uint32_t cWidth, uint32_t cHeight);
+DECLHIDDEN(int) VBoxHGSMIGetModeHints(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                      unsigned cScreens, VBVAMODEHINT *paHints);
+
+/** @}  */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/VBox/VMMDev.h b/ubuntu/vbox/include/VBox/VMMDev.h
new file mode 100644 (file)
index 0000000..59933fc
--- /dev/null
@@ -0,0 +1,2210 @@
+/** @file
+ * Virtual Device for Guest <-> VMM/Host communication (ADD,DEV).
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBox_VMMDev_h
+#define ___VBox_VMMDev_h
+
+#include <VBox/cdefs.h>
+#include <VBox/param.h>                 /* for the PCI IDs. */
+#include <VBox/types.h>
+#include <VBox/err.h>
+#include <VBox/ostypes.h>
+#include <VBox/VMMDev2.h>
+#include <iprt/assert.h>
+
+
+#pragma pack(4) /* force structure dword packing here. */
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup grp_vmmdev    VMM Device
+ *
+ * @note This interface cannot be changed, it can only be extended!
+ *
+ * @{
+ */
+
+
+/** Size of VMMDev RAM region accessible by guest.
+ * Must be big enough to contain VMMDevMemory structure (see further down).
+ * For now: 4 megabyte.
+ */
+#define VMMDEV_RAM_SIZE                                     (4 * 256 * PAGE_SIZE)
+
+/** Size of VMMDev heap region accessible by guest.
+ *  (Must be a power of two (pci range).)
+ */
+#define VMMDEV_HEAP_SIZE                                    (4 * PAGE_SIZE)
+
+/** Port for generic request interface (relative offset). */
+#define VMMDEV_PORT_OFF_REQUEST                             0
+
+
+/** @name VMMDev events.
+ *
+ * Used mainly by VMMDevReq_AcknowledgeEvents/VMMDevEvents and version 1.3 of
+ * VMMDevMemory.
+ *
+ * @{
+ */
+/** Host mouse capabilities has been changed. */
+#define VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED             RT_BIT(0)
+/** HGCM event. */
+#define VMMDEV_EVENT_HGCM                                   RT_BIT(1)
+/** A display change request has been issued. */
+#define VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST                 RT_BIT(2)
+/** Credentials are available for judgement. */
+#define VMMDEV_EVENT_JUDGE_CREDENTIALS                      RT_BIT(3)
+/** The guest has been restored. */
+#define VMMDEV_EVENT_RESTORED                               RT_BIT(4)
+/** Seamless mode state changed. */
+#define VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST           RT_BIT(5)
+/** Memory balloon size changed. */
+#define VMMDEV_EVENT_BALLOON_CHANGE_REQUEST                 RT_BIT(6)
+/** Statistics interval changed. */
+#define VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST     RT_BIT(7)
+/** VRDP status changed. */
+#define VMMDEV_EVENT_VRDP                                   RT_BIT(8)
+/** New mouse position data available. */
+#define VMMDEV_EVENT_MOUSE_POSITION_CHANGED                 RT_BIT(9)
+/** CPU hotplug event occurred. */
+#define VMMDEV_EVENT_CPU_HOTPLUG                            RT_BIT(10)
+/** The mask of valid events, for sanity checking. */
+#define VMMDEV_EVENT_VALID_EVENT_MASK                       UINT32_C(0x000007ff)
+/** @} */
+
+
+/** @defgroup grp_vmmdev_req    VMMDev Generic Request Interface
+ * @{
+ */
+
+/** @name Current version of the VMMDev interface.
+ *
+ * Additions are allowed to work only if
+ * additions_major == vmmdev_current && additions_minor <= vmmdev_current.
+ * Additions version is reported to host (VMMDev) by VMMDevReq_ReportGuestInfo.
+ *
+ * @remarks These defines also live in the 16-bit and assembly versions of this
+ *          header.
+ */
+#define VMMDEV_VERSION                      0x00010004
+#define VMMDEV_VERSION_MAJOR                (VMMDEV_VERSION >> 16)
+#define VMMDEV_VERSION_MINOR                (VMMDEV_VERSION & 0xffff)
+/** @} */
+
+/** Maximum request packet size. */
+#define VMMDEV_MAX_VMMDEVREQ_SIZE           _1M
+/** Maximum number of HGCM parameters. */
+#define VMMDEV_MAX_HGCM_PARMS               1024
+/** Maximum total size of hgcm buffers in one call. */
+#define VMMDEV_MAX_HGCM_DATA_SIZE           UINT32_C(0x7FFFFFFF)
+
+/**
+ * VMMDev request types.
+ * @note when updating this, adjust vmmdevGetRequestSize() as well
+ */
+typedef enum
+{
+    VMMDevReq_InvalidRequest             =  0,
+    VMMDevReq_GetMouseStatus             =  1,
+    VMMDevReq_SetMouseStatus             =  2,
+    VMMDevReq_SetPointerShape            =  3,
+    VMMDevReq_GetHostVersion             =  4,
+    VMMDevReq_Idle                       =  5,
+    VMMDevReq_GetHostTime                = 10,
+    VMMDevReq_GetHypervisorInfo          = 20,
+    VMMDevReq_SetHypervisorInfo          = 21,
+    VMMDevReq_RegisterPatchMemory        = 22, /* since version 3.0.6 */
+    VMMDevReq_DeregisterPatchMemory      = 23, /* since version 3.0.6 */
+    VMMDevReq_SetPowerStatus             = 30,
+    VMMDevReq_AcknowledgeEvents          = 41,
+    VMMDevReq_CtlGuestFilterMask         = 42,
+    VMMDevReq_ReportGuestInfo            = 50,
+    VMMDevReq_ReportGuestInfo2           = 58, /* since version 3.2.0 */
+    VMMDevReq_ReportGuestStatus          = 59, /* since version 3.2.8 */
+    VMMDevReq_ReportGuestUserState       = 74, /* since version 4.3 */
+    /**
+     * Retrieve a display resize request sent by the host using
+     * @a IDisplay:setVideoModeHint.  Deprecated.
+     *
+     * Similar to @a VMMDevReq_GetDisplayChangeRequest2, except that it only
+     * considers host requests sent for the first virtual display.  This guest
+     * request should not be used in new guest code, and the results are
+     * undefined if a guest mixes calls to this and
+     * @a VMMDevReq_GetDisplayChangeRequest2.
+     */
+    VMMDevReq_GetDisplayChangeRequest    = 51,
+    VMMDevReq_VideoModeSupported         = 52,
+    VMMDevReq_GetHeightReduction         = 53,
+    /**
+     * Retrieve a display resize request sent by the host using
+     * @a IDisplay:setVideoModeHint.
+     *
+     * Queries a display resize request sent from the host.  If the
+     * @a eventAck member is sent to true and there is an unqueried
+     * request available for one of the virtual display then that request will
+     * be returned.  If several displays have unqueried requests the lowest
+     * numbered display will be chosen first.  Only the most recent unseen
+     * request for each display is remembered.
+     * If @a eventAck is set to false, the last host request queried with
+     * @a eventAck set is resent, or failing that the most recent received from
+     * the host.  If no host request was ever received then all zeros are
+     * returned.
+     */
+    VMMDevReq_GetDisplayChangeRequest2   = 54,
+    VMMDevReq_ReportGuestCapabilities    = 55,
+    VMMDevReq_SetGuestCapabilities       = 56,
+    VMMDevReq_VideoModeSupported2        = 57, /* since version 3.2.0 */
+    VMMDevReq_GetDisplayChangeRequestEx  = 80, /* since version 4.2.4 */
+#ifdef VBOX_WITH_HGCM
+    VMMDevReq_HGCMConnect                = 60,
+    VMMDevReq_HGCMDisconnect             = 61,
+#ifdef VBOX_WITH_64_BITS_GUESTS
+    VMMDevReq_HGCMCall32                 = 62,
+    VMMDevReq_HGCMCall64                 = 63,
+#else
+    VMMDevReq_HGCMCall                   = 62,
+#endif /* VBOX_WITH_64_BITS_GUESTS */
+    VMMDevReq_HGCMCancel                 = 64,
+    VMMDevReq_HGCMCancel2                = 65,
+#endif
+    VMMDevReq_VideoAccelEnable           = 70,
+    VMMDevReq_VideoAccelFlush            = 71,
+    VMMDevReq_VideoSetVisibleRegion      = 72,
+    VMMDevReq_GetSeamlessChangeRequest   = 73,
+    VMMDevReq_QueryCredentials           = 100,
+    VMMDevReq_ReportCredentialsJudgement = 101,
+    VMMDevReq_ReportGuestStats           = 110,
+    VMMDevReq_GetMemBalloonChangeRequest = 111,
+    VMMDevReq_GetStatisticsChangeRequest = 112,
+    VMMDevReq_ChangeMemBalloon           = 113,
+    VMMDevReq_GetVRDPChangeRequest       = 150,
+    VMMDevReq_LogString                  = 200,
+    VMMDevReq_GetCpuHotPlugRequest       = 210,
+    VMMDevReq_SetCpuHotPlugStatus        = 211,
+    VMMDevReq_RegisterSharedModule       = 212,
+    VMMDevReq_UnregisterSharedModule     = 213,
+    VMMDevReq_CheckSharedModules         = 214,
+    VMMDevReq_GetPageSharingStatus       = 215,
+    VMMDevReq_DebugIsPageShared          = 216,
+    VMMDevReq_GetSessionId               = 217, /* since version 3.2.8 */
+    VMMDevReq_WriteCoreDump              = 218,
+    VMMDevReq_GuestHeartbeat             = 219,
+    VMMDevReq_HeartbeatConfigure         = 220,
+    VMMDevReq_SizeHack                   = 0x7fffffff
+} VMMDevRequestType;
+
+#ifdef VBOX_WITH_64_BITS_GUESTS
+/*
+ * Constants and structures are redefined for the guest.
+ *
+ * Host code MUST always use either *32 or *64 variant explicitely.
+ * Host source code will use VBOX_HGCM_HOST_CODE define to catch undefined
+ * data types and constants.
+ *
+ * This redefinition means that the new additions builds will use
+ * the *64 or *32 variants depending on the current architecture bit count (ARCH_BITS).
+ */
+# ifndef VBOX_HGCM_HOST_CODE
+#  if ARCH_BITS == 64
+#   define VMMDevReq_HGCMCall VMMDevReq_HGCMCall64
+#  elif ARCH_BITS == 32
+#   define VMMDevReq_HGCMCall VMMDevReq_HGCMCall32
+#  else
+#   error "Unsupported ARCH_BITS"
+#  endif
+# endif /* !VBOX_HGCM_HOST_CODE */
+#endif /* VBOX_WITH_64_BITS_GUESTS */
+
+/** Version of VMMDevRequestHeader structure. */
+#define VMMDEV_REQUEST_HEADER_VERSION (0x10001)
+
+
+/**
+ * Generic VMMDev request header.
+ */
+typedef struct
+{
+    /** IN: Size of the structure in bytes (including body). */
+    uint32_t size;
+    /** IN: Version of the structure.  */
+    uint32_t version;
+    /** IN: Type of the request. */
+    VMMDevRequestType requestType;
+    /** OUT: Return code. */
+    int32_t  rc;
+    /** Reserved field no.1. MBZ. */
+    uint32_t reserved1;
+    /** Reserved field no.2. MBZ. */
+    uint32_t reserved2;
+} VMMDevRequestHeader;
+AssertCompileSize(VMMDevRequestHeader, 24);
+
+
+/**
+ * Mouse status request structure.
+ *
+ * Used by VMMDevReq_GetMouseStatus and VMMDevReq_SetMouseStatus.
+ */
+typedef struct
+{
+    /** header */
+    VMMDevRequestHeader header;
+    /** Mouse feature mask. See VMMDEV_MOUSE_*. */
+    uint32_t mouseFeatures;
+    /** Mouse x position. */
+    int32_t pointerXPos;
+    /** Mouse y position. */
+    int32_t pointerYPos;
+} VMMDevReqMouseStatus;
+AssertCompileSize(VMMDevReqMouseStatus, 24+12);
+
+/** @name Mouse capability bits (VMMDevReqMouseStatus::mouseFeatures).
+ * @{ */
+/** The guest can (== wants to) handle absolute coordinates.  */
+#define VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE                     RT_BIT(0)
+/** The host can (== wants to) send absolute coordinates.
+ * (Input not captured.) */
+#define VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE                    RT_BIT(1)
+/** The guest can *NOT* switch to software cursor and therefore depends on the
+ * host cursor.
+ *
+ * When guest additions are installed and the host has promised to display the
+ * cursor itself, the guest installs a hardware mouse driver. Don't ask the
+ * guest to switch to a software cursor then. */
+#define VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR                RT_BIT(2)
+/** The host does NOT provide support for drawing the cursor itself. */
+#define VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER                  RT_BIT(3)
+/** The guest can read VMMDev events to find out about pointer movement */
+#define VMMDEV_MOUSE_NEW_PROTOCOL                           RT_BIT(4)
+/** If the guest changes the status of the
+ * VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR bit, the host will honour this */
+#define VMMDEV_MOUSE_HOST_RECHECKS_NEEDS_HOST_CURSOR        RT_BIT(5)
+/** The host supplies an absolute pointing device.  The Guest Additions may
+ * wish to use this to decide whether to install their own driver */
+#define VMMDEV_MOUSE_HOST_HAS_ABS_DEV                       RT_BIT(6)
+/** The mask of all VMMDEV_MOUSE_* flags */
+#define VMMDEV_MOUSE_MASK                                   UINT32_C(0x0000007f)
+/** The mask of guest capability changes for which notification events should
+ * be sent */
+#define VMMDEV_MOUSE_NOTIFY_HOST_MASK \
+      (VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE | VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR)
+/** The mask of all capabilities which the guest can legitimately change */
+#define VMMDEV_MOUSE_GUEST_MASK \
+      (VMMDEV_MOUSE_NOTIFY_HOST_MASK | VMMDEV_MOUSE_NEW_PROTOCOL)
+/** The mask of host capability changes for which notification events should
+ * be sent */
+#define VMMDEV_MOUSE_NOTIFY_GUEST_MASK \
+      VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE
+/** The mask of all capabilities which the host can legitimately change */
+#define VMMDEV_MOUSE_HOST_MASK \
+      (  VMMDEV_MOUSE_NOTIFY_GUEST_MASK \
+       | VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER \
+       | VMMDEV_MOUSE_HOST_RECHECKS_NEEDS_HOST_CURSOR \
+       | VMMDEV_MOUSE_HOST_HAS_ABS_DEV)
+/** @} */
+
+/** @name Absolute mouse reporting range
+ * @{ */
+/** @todo Should these be here?  They are needed by both host and guest. */
+/** The minumum value our pointing device can return. */
+#define VMMDEV_MOUSE_RANGE_MIN 0
+/** The maximum value our pointing device can return. */
+#define VMMDEV_MOUSE_RANGE_MAX 0xFFFF
+/** The full range our pointing device can return. */
+#define VMMDEV_MOUSE_RANGE (VMMDEV_MOUSE_RANGE_MAX - VMMDEV_MOUSE_RANGE_MIN)
+/** @} */
+
+
+/**
+ * Mouse pointer shape/visibility change request.
+ *
+ * Used by VMMDevReq_SetPointerShape. The size is variable.
+ */
+typedef struct VMMDevReqMousePointer
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** VBOX_MOUSE_POINTER_* bit flags. */
+    uint32_t fFlags;
+    /** x coordinate of hot spot. */
+    uint32_t xHot;
+    /** y coordinate of hot spot. */
+    uint32_t yHot;
+    /** Width of the pointer in pixels. */
+    uint32_t width;
+    /** Height of the pointer in scanlines. */
+    uint32_t height;
+    /** Pointer data.
+     *
+     ****
+     * The data consists of 1 bpp AND mask followed by 32 bpp XOR (color) mask.
+     *
+     * For pointers without alpha channel the XOR mask pixels are 32 bit values: (lsb)BGR0(msb).
+     * For pointers with alpha channel the XOR mask consists of (lsb)BGRA(msb) 32 bit values.
+     *
+     * Guest driver must create the AND mask for pointers with alpha channel, so if host does not
+     * support alpha, the pointer could be displayed as a normal color pointer. The AND mask can
+     * be constructed from alpha values. For example alpha value >= 0xf0 means bit 0 in the AND mask.
+     *
+     * The AND mask is 1 bpp bitmap with byte aligned scanlines. Size of AND mask,
+     * therefore, is cbAnd = (width + 7) / 8 * height. The padding bits at the
+     * end of any scanline are undefined.
+     *
+     * The XOR mask follows the AND mask on the next 4 bytes aligned offset:
+     * uint8_t *pXor = pAnd + (cbAnd + 3) & ~3
+     * Bytes in the gap between the AND and the XOR mask are undefined.
+     * XOR mask scanlines have no gap between them and size of XOR mask is:
+     * cXor = width * 4 * height.
+     ****
+     *
+     * Preallocate 4 bytes for accessing actual data as p->pointerData.
+     */
+    char pointerData[4];
+} VMMDevReqMousePointer;
+AssertCompileSize(VMMDevReqMousePointer, 24+24);
+
+/**
+ * Get the size that a VMMDevReqMousePointer request should have for a given
+ * size of cursor, including the trailing cursor image and mask data.
+ * @note an "empty" request still has the four preallocated bytes of data
+ *
+ * @returns the size
+ * @param  width   the cursor width
+ * @param  height  the cursor height
+ */
+DECLINLINE(size_t) vmmdevGetMousePointerReqSize(uint32_t width, uint32_t height)
+{
+    size_t cbBase = RT_OFFSETOF(VMMDevReqMousePointer, pointerData);
+    size_t cbMask = (width + 7) / 8 * height;
+    size_t cbArgb = width * height * 4;
+    return RT_MAX(cbBase + ((cbMask + 3) & ~3) + cbArgb,
+                  sizeof(VMMDevReqMousePointer));
+}
+
+/** @name VMMDevReqMousePointer::fFlags
+ * @note The VBOX_MOUSE_POINTER_* flags are used in the guest video driver,
+ *       values must be <= 0x8000 and must not be changed. (try make more sense
+ *       of this, please).
+ * @{
+ */
+/** pointer is visible */
+#define VBOX_MOUSE_POINTER_VISIBLE (0x0001)
+/** pointer has alpha channel */
+#define VBOX_MOUSE_POINTER_ALPHA   (0x0002)
+/** pointerData contains new pointer shape */
+#define VBOX_MOUSE_POINTER_SHAPE   (0x0004)
+/** @} */
+
+
+/**
+ * String log request structure.
+ *
+ * Used by VMMDevReq_LogString.
+ * @deprecated  Use the IPRT logger or VbglR3WriteLog instead.
+ */
+typedef struct
+{
+    /** header */
+    VMMDevRequestHeader header;
+    /** variable length string data */
+    char szString[1];
+} VMMDevReqLogString;
+AssertCompileSize(VMMDevReqLogString, 24+4);
+
+
+/**
+ * VirtualBox host version request structure.
+ *
+ * Used by VMMDevReq_GetHostVersion.
+ *
+ * @remarks VBGL uses this to detect the precense of new features in the
+ *          interface.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Major version. */
+    uint16_t major;
+    /** Minor version. */
+    uint16_t minor;
+    /** Build number. */
+    uint32_t build;
+    /** SVN revision. */
+    uint32_t revision;
+    /** Feature mask. */
+    uint32_t features;
+} VMMDevReqHostVersion;
+AssertCompileSize(VMMDevReqHostVersion, 24+16);
+
+/** @name VMMDevReqHostVersion::features
+ * @{ */
+/** Physical page lists are supported by HGCM. */
+#define VMMDEV_HVF_HGCM_PHYS_PAGE_LIST  RT_BIT(0)
+/** @} */
+
+
+/**
+ * Guest capabilities structure.
+ *
+ * Used by VMMDevReq_ReportGuestCapabilities.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Capabilities (VMMDEV_GUEST_*). */
+    uint32_t caps;
+} VMMDevReqGuestCapabilities;
+AssertCompileSize(VMMDevReqGuestCapabilities, 24+4);
+
+/**
+ * Guest capabilities structure, version 2.
+ *
+ * Used by VMMDevReq_SetGuestCapabilities.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Mask of capabilities to be added. */
+    uint32_t u32OrMask;
+    /** Mask of capabilities to be removed. */
+    uint32_t u32NotMask;
+} VMMDevReqGuestCapabilities2;
+AssertCompileSize(VMMDevReqGuestCapabilities2, 24+8);
+
+/** @name Guest capability bits.
+ * Used by VMMDevReq_ReportGuestCapabilities and VMMDevReq_SetGuestCapabilities.
+ * @{ */
+/** The guest supports seamless display rendering. */
+#define VMMDEV_GUEST_SUPPORTS_SEAMLESS                      RT_BIT_32(0)
+/** The guest supports mapping guest to host windows. */
+#define VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING     RT_BIT_32(1)
+/** The guest graphical additions are active.
+ * Used for fast activation and deactivation of certain graphical operations
+ * (e.g. resizing & seamless). The legacy VMMDevReq_ReportGuestCapabilities
+ * request sets this automatically, but VMMDevReq_SetGuestCapabilities does
+ * not. */
+#define VMMDEV_GUEST_SUPPORTS_GRAPHICS                      RT_BIT_32(2)
+/** The mask of valid events, for sanity checking. */
+#define VMMDEV_GUEST_CAPABILITIES_MASK                      UINT32_C(0x00000007)
+/** @} */
+
+
+/**
+ * Idle request structure.
+ *
+ * Used by VMMDevReq_Idle.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+} VMMDevReqIdle;
+AssertCompileSize(VMMDevReqIdle, 24);
+
+
+/**
+ * Host time request structure.
+ *
+ * Used by VMMDevReq_GetHostTime.
+ */
+typedef struct
+{
+    /** Header */
+    VMMDevRequestHeader header;
+    /** OUT: Time in milliseconds since unix epoch. */
+    uint64_t time;
+} VMMDevReqHostTime;
+AssertCompileSize(VMMDevReqHostTime, 24+8);
+
+
+/**
+ * Hypervisor info structure.
+ *
+ * Used by VMMDevReq_GetHypervisorInfo and VMMDevReq_SetHypervisorInfo.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Guest virtual address of proposed hypervisor start.
+     * Not used by VMMDevReq_GetHypervisorInfo.
+     * @todo Make this 64-bit compatible? */
+    RTGCPTR32 hypervisorStart;
+    /** Hypervisor size in bytes. */
+    uint32_t hypervisorSize;
+} VMMDevReqHypervisorInfo;
+AssertCompileSize(VMMDevReqHypervisorInfo, 24+8);
+
+/** @name Default patch memory size .
+ * Used by VMMDevReq_RegisterPatchMemory and VMMDevReq_DeregisterPatchMemory.
+ * @{ */
+#define VMMDEV_GUEST_DEFAULT_PATCHMEM_SIZE          8192
+/** @} */
+
+/**
+ * Patching memory structure. (locked executable & read-only page from the guest's perspective)
+ *
+ * Used by VMMDevReq_RegisterPatchMemory and VMMDevReq_DeregisterPatchMemory
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Guest virtual address of the patching page(s). */
+    RTGCPTR64           pPatchMem;
+    /** Patch page size in bytes. */
+    uint32_t            cbPatchMem;
+} VMMDevReqPatchMemory;
+AssertCompileSize(VMMDevReqPatchMemory, 24+12);
+
+
+/**
+ * Guest power requests.
+ *
+ * See VMMDevReq_SetPowerStatus and VMMDevPowerStateRequest.
+ */
+typedef enum
+{
+    VMMDevPowerState_Invalid   = 0,
+    VMMDevPowerState_Pause     = 1,
+    VMMDevPowerState_PowerOff  = 2,
+    VMMDevPowerState_SaveState = 3,
+    VMMDevPowerState_SizeHack = 0x7fffffff
+} VMMDevPowerState;
+AssertCompileSize(VMMDevPowerState, 4);
+
+/**
+ * VM power status structure.
+ *
+ * Used by VMMDevReq_SetPowerStatus.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Power state request. */
+    VMMDevPowerState powerState;
+} VMMDevPowerStateRequest;
+AssertCompileSize(VMMDevPowerStateRequest, 24+4);
+
+
+/**
+ * Pending events structure.
+ *
+ * Used by VMMDevReq_AcknowledgeEvents.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** OUT: Pending event mask. */
+    uint32_t events;
+} VMMDevEvents;
+AssertCompileSize(VMMDevEvents, 24+4);
+
+
+/**
+ * Guest event filter mask control.
+ *
+ * Used by VMMDevReq_CtlGuestFilterMask.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Mask of events to be added to the filter. */
+    uint32_t u32OrMask;
+    /** Mask of events to be removed from the filter. */
+    uint32_t u32NotMask;
+} VMMDevCtlGuestFilterMask;
+AssertCompileSize(VMMDevCtlGuestFilterMask, 24+8);
+
+
+/**
+ * Guest information structure.
+ *
+ * Used by VMMDevReportGuestInfo and PDMIVMMDEVCONNECTOR::pfnUpdateGuestVersion.
+ */
+typedef struct VBoxGuestInfo
+{
+    /** The VMMDev interface version expected by additions.
+      * *Deprecated*, do not use anymore! Will be removed. */
+    uint32_t interfaceVersion;
+    /** Guest OS type. */
+    VBOXOSTYPE osType;
+} VBoxGuestInfo;
+AssertCompileSize(VBoxGuestInfo, 8);
+
+/**
+ * Guest information report.
+ *
+ * Used by VMMDevReq_ReportGuestInfo.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Guest information. */
+    VBoxGuestInfo guestInfo;
+} VMMDevReportGuestInfo;
+AssertCompileSize(VMMDevReportGuestInfo, 24+8);
+
+
+/**
+ * Guest information structure, version 2.
+ *
+ * Used by VMMDevReportGuestInfo2 and PDMIVMMDEVCONNECTOR::pfnUpdateGuestVersion2.
+ */
+typedef struct VBoxGuestInfo2
+{
+    /** Major version. */
+    uint16_t additionsMajor;
+    /** Minor version. */
+    uint16_t additionsMinor;
+    /** Build number. */
+    uint32_t additionsBuild;
+    /** SVN revision. */
+    uint32_t additionsRevision;
+    /** Feature mask, currently unused. */
+    uint32_t additionsFeatures;
+    /** The intentional meaning of this field was:
+     * Some additional information, for example 'Beta 1' or something like that.
+     *
+     * The way it was implemented was implemented: VBOX_VERSION_STRING.
+     *
+     * This means the first three members are duplicated in this field (if the guest
+     * build config is sane). So, the user must check this and chop it off before
+     * usage.  There is, because of the Main code's blind trust in the field's
+     * content, no way back. */
+    char     szName[128];
+} VBoxGuestInfo2;
+AssertCompileSize(VBoxGuestInfo2, 144);
+
+/**
+ * Guest information report, version 2.
+ *
+ * Used by VMMDevReq_ReportGuestInfo2.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Guest information. */
+    VBoxGuestInfo2 guestInfo;
+} VMMDevReportGuestInfo2;
+AssertCompileSize(VMMDevReportGuestInfo2, 24+144);
+
+
+/**
+ * The guest facility.
+ * This needs to be kept in sync with AdditionsFacilityType of the Main API!
+ */
+typedef enum
+{
+    VBoxGuestFacilityType_Unknown         = 0,
+    VBoxGuestFacilityType_VBoxGuestDriver = 20,
+    VBoxGuestFacilityType_AutoLogon       = 90,  /* VBoxGINA / VBoxCredProv / pam_vbox. */
+    VBoxGuestFacilityType_VBoxService     = 100,
+    VBoxGuestFacilityType_VBoxTrayClient  = 101, /* VBoxTray (Windows), VBoxClient (Linux, Unix). */
+    VBoxGuestFacilityType_Seamless        = 1000,
+    VBoxGuestFacilityType_Graphics        = 1100,
+    VBoxGuestFacilityType_All             = 0x7ffffffe,
+    VBoxGuestFacilityType_SizeHack        = 0x7fffffff
+} VBoxGuestFacilityType;
+AssertCompileSize(VBoxGuestFacilityType, 4);
+
+
+/**
+ * The current guest status of a facility.
+ * This needs to be kept in sync with AdditionsFacilityStatus of the Main API!
+ *
+ * @remarks r=bird: Pretty please, for future types like this, simply do a
+ *          linear allocation without any gaps.  This stuff is impossible work
+ *          efficiently with, let alone validate.  Applies to the other facility
+ *          enums too.
+ */
+typedef enum
+{
+    VBoxGuestFacilityStatus_Inactive    = 0,
+    VBoxGuestFacilityStatus_Paused      = 1,
+    VBoxGuestFacilityStatus_PreInit     = 20,
+    VBoxGuestFacilityStatus_Init        = 30,
+    VBoxGuestFacilityStatus_Active      = 50,
+    VBoxGuestFacilityStatus_Terminating = 100,
+    VBoxGuestFacilityStatus_Terminated  = 101,
+    VBoxGuestFacilityStatus_Failed  =     800,
+    VBoxGuestFacilityStatus_Unknown     = 999,
+    VBoxGuestFacilityStatus_SizeHack    = 0x7fffffff
+} VBoxGuestFacilityStatus;
+AssertCompileSize(VBoxGuestFacilityStatus, 4);
+
+
+/**
+ * The facility class.
+ * This needs to be kept in sync with AdditionsFacilityClass of the Main API!
+ */
+typedef enum
+{
+    VBoxGuestFacilityClass_None       = 0,
+    VBoxGuestFacilityClass_Driver     = 10,
+    VBoxGuestFacilityClass_Service    = 30,
+    VBoxGuestFacilityClass_Program    = 50,
+    VBoxGuestFacilityClass_Feature    = 100,
+    VBoxGuestFacilityClass_ThirdParty = 999,
+    VBoxGuestFacilityClass_All        = 0x7ffffffe,
+    VBoxGuestFacilityClass_SizeHack   = 0x7fffffff
+} VBoxGuestFacilityClass;
+AssertCompileSize(VBoxGuestFacilityClass, 4);
+
+
+/**
+ * Guest status structure.
+ *
+ * Used by VMMDevReqGuestStatus.
+ */
+typedef struct VBoxGuestStatus
+{
+    /** Facility the status is indicated for. */
+    VBoxGuestFacilityType facility;
+    /** Current guest status. */
+    VBoxGuestFacilityStatus status;
+    /** Flags, not used at the moment. */
+    uint32_t flags;
+} VBoxGuestStatus;
+AssertCompileSize(VBoxGuestStatus, 12);
+
+/**
+ * Guest Additions status structure.
+ *
+ * Used by VMMDevReq_ReportGuestStatus.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Guest information. */
+    VBoxGuestStatus guestStatus;
+} VMMDevReportGuestStatus;
+AssertCompileSize(VMMDevReportGuestStatus, 24+12);
+
+
+/**
+ * The current status of specific guest user.
+ * This needs to be kept in sync with GuestUserState of the Main API!
+ */
+typedef enum VBoxGuestUserState
+{
+    VBoxGuestUserState_Unknown            = 0,
+    VBoxGuestUserState_LoggedIn           = 1,
+    VBoxGuestUserState_LoggedOut          = 2,
+    VBoxGuestUserState_Locked             = 3,
+    VBoxGuestUserState_Unlocked           = 4,
+    VBoxGuestUserState_Disabled           = 5,
+    VBoxGuestUserState_Idle               = 6,
+    VBoxGuestUserState_InUse              = 7,
+    VBoxGuestUserState_Created            = 8,
+    VBoxGuestUserState_Deleted            = 9,
+    VBoxGuestUserState_SessionChanged     = 10,
+    VBoxGuestUserState_CredentialsChanged = 11,
+    VBoxGuestUserState_RoleChanged        = 12,
+    VBoxGuestUserState_GroupAdded         = 13,
+    VBoxGuestUserState_GroupRemoved       = 14,
+    VBoxGuestUserState_Elevated           = 15,
+    VBoxGuestUserState_SizeHack           = 0x7fffffff
+} VBoxGuestUserState;
+AssertCompileSize(VBoxGuestUserState, 4);
+
+
+/**
+ * Guest user status updates.
+ */
+typedef struct VBoxGuestUserStatus
+{
+    /** The guest user state to send. */
+    VBoxGuestUserState  state;
+    /** Size (in bytes) of szUser. */
+    uint32_t            cbUser;
+    /** Size (in bytes) of szDomain. */
+    uint32_t            cbDomain;
+    /** Size (in bytes) of aDetails. */
+    uint32_t            cbDetails;
+    /** Note: Here begins the dynamically
+     *        allocated region. */
+    /** Guest user to report state for. */
+    char                szUser[1];
+    /** Domain the guest user is bound to. */
+    char                szDomain[1];
+    /** Optional details of the state. */
+    uint8_t             aDetails[1];
+} VBoxGuestUserStatus;
+AssertCompileSize(VBoxGuestUserStatus, 20);
+
+
+/**
+ * Guest user status structure.
+ *
+ * Used by VMMDevReq_ReportGuestUserStatus.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Guest user status. */
+    VBoxGuestUserStatus status;
+} VMMDevReportGuestUserState;
+AssertCompileSize(VMMDevReportGuestUserState, 24+20);
+
+
+/**
+ * Guest statistics structure.
+ *
+ * Used by VMMDevReportGuestStats and PDMIVMMDEVCONNECTOR::pfnReportStatistics.
+ */
+typedef struct VBoxGuestStatistics
+{
+    /** Virtual CPU ID. */
+    uint32_t        u32CpuId;
+    /** Reported statistics. */
+    uint32_t        u32StatCaps;
+    /** Idle CPU load (0-100) for last interval. */
+    uint32_t        u32CpuLoad_Idle;
+    /** Kernel CPU load (0-100) for last interval. */
+    uint32_t        u32CpuLoad_Kernel;
+    /** User CPU load (0-100) for last interval. */
+    uint32_t        u32CpuLoad_User;
+    /** Nr of threads. */
+    uint32_t        u32Threads;
+    /** Nr of processes. */
+    uint32_t        u32Processes;
+    /** Nr of handles. */
+    uint32_t        u32Handles;
+    /** Memory load (0-100). */
+    uint32_t        u32MemoryLoad;
+    /** Page size of guest system. */
+    uint32_t        u32PageSize;
+    /** Total physical memory (in 4KB pages). */
+    uint32_t        u32PhysMemTotal;
+    /** Available physical memory (in 4KB pages). */
+    uint32_t        u32PhysMemAvail;
+    /** Ballooned physical memory (in 4KB pages). */
+    uint32_t        u32PhysMemBalloon;
+    /** Total number of committed memory (which is not necessarily in-use) (in 4KB pages). */
+    uint32_t        u32MemCommitTotal;
+    /** Total amount of memory used by the kernel (in 4KB pages). */
+    uint32_t        u32MemKernelTotal;
+    /** Total amount of paged memory used by the kernel (in 4KB pages). */
+    uint32_t        u32MemKernelPaged;
+    /** Total amount of nonpaged memory used by the kernel (in 4KB pages). */
+    uint32_t        u32MemKernelNonPaged;
+    /** Total amount of memory used for the system cache (in 4KB pages). */
+    uint32_t        u32MemSystemCache;
+    /** Pagefile size (in 4KB pages). */
+    uint32_t        u32PageFileSize;
+} VBoxGuestStatistics;
+AssertCompileSize(VBoxGuestStatistics, 19*4);
+
+/** @name Guest statistics values (VBoxGuestStatistics::u32StatCaps).
+ * @{ */
+#define VBOX_GUEST_STAT_CPU_LOAD_IDLE       RT_BIT(0)
+#define VBOX_GUEST_STAT_CPU_LOAD_KERNEL     RT_BIT(1)
+#define VBOX_GUEST_STAT_CPU_LOAD_USER       RT_BIT(2)
+#define VBOX_GUEST_STAT_THREADS             RT_BIT(3)
+#define VBOX_GUEST_STAT_PROCESSES           RT_BIT(4)
+#define VBOX_GUEST_STAT_HANDLES             RT_BIT(5)
+#define VBOX_GUEST_STAT_MEMORY_LOAD         RT_BIT(6)
+#define VBOX_GUEST_STAT_PHYS_MEM_TOTAL      RT_BIT(7)
+#define VBOX_GUEST_STAT_PHYS_MEM_AVAIL      RT_BIT(8)
+#define VBOX_GUEST_STAT_PHYS_MEM_BALLOON    RT_BIT(9)
+#define VBOX_GUEST_STAT_MEM_COMMIT_TOTAL    RT_BIT(10)
+#define VBOX_GUEST_STAT_MEM_KERNEL_TOTAL    RT_BIT(11)
+#define VBOX_GUEST_STAT_MEM_KERNEL_PAGED    RT_BIT(12)
+#define VBOX_GUEST_STAT_MEM_KERNEL_NONPAGED RT_BIT(13)
+#define VBOX_GUEST_STAT_MEM_SYSTEM_CACHE    RT_BIT(14)
+#define VBOX_GUEST_STAT_PAGE_FILE_SIZE      RT_BIT(15)
+/** @} */
+
+/**
+ * Guest statistics command structure.
+ *
+ * Used by VMMDevReq_ReportGuestStats.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Guest information. */
+    VBoxGuestStatistics guestStats;
+} VMMDevReportGuestStats;
+AssertCompileSize(VMMDevReportGuestStats, 24+19*4);
+
+
+/** Memory balloon change request structure. */
+#define VMMDEV_MAX_MEMORY_BALLOON(PhysMemTotal)     ( (9 * (PhysMemTotal)) / 10 )
+
+/**
+ * Poll for ballooning change request.
+ *
+ * Used by VMMDevReq_GetMemBalloonChangeRequest.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Balloon size in megabytes. */
+    uint32_t            cBalloonChunks;
+    /** Guest ram size in megabytes. */
+    uint32_t            cPhysMemChunks;
+    /** Setting this to VMMDEV_EVENT_BALLOON_CHANGE_REQUEST indicates that the
+     * request is a response to that event.
+     * (Don't confuse this with VMMDevReq_AcknowledgeEvents.) */
+    uint32_t            eventAck;
+} VMMDevGetMemBalloonChangeRequest;
+AssertCompileSize(VMMDevGetMemBalloonChangeRequest, 24+12);
+
+
+/**
+ * Change the size of the balloon.
+ *
+ * Used by VMMDevReq_ChangeMemBalloon.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** The number of pages in the array. */
+    uint32_t            cPages;
+    /** true = inflate, false = deflate.  */
+    uint32_t            fInflate;
+    /** Physical address (RTGCPHYS) of each page, variable size. */
+    RTGCPHYS            aPhysPage[1];
+} VMMDevChangeMemBalloon;
+AssertCompileSize(VMMDevChangeMemBalloon, 24+16);
+
+/** @name The ballooning chunk size which VMMDev works at.
+ * @{ */
+#define VMMDEV_MEMORY_BALLOON_CHUNK_PAGES            (_1M/4096)
+#define VMMDEV_MEMORY_BALLOON_CHUNK_SIZE             (VMMDEV_MEMORY_BALLOON_CHUNK_PAGES*4096)
+/** @} */
+
+
+/**
+ * Guest statistics interval change request structure.
+ *
+ * Used by VMMDevReq_GetStatisticsChangeRequest.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** The interval in seconds. */
+    uint32_t            u32StatInterval;
+    /** Setting this to VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST indicates
+     * that the request is a response to that event.
+     * (Don't confuse this with VMMDevReq_AcknowledgeEvents.) */
+    uint32_t            eventAck;
+} VMMDevGetStatisticsChangeRequest;
+AssertCompileSize(VMMDevGetStatisticsChangeRequest, 24+8);
+
+
+/** The size of a string field in the credentials request (including '\\0').
+ * @see VMMDevCredentials  */
+#define VMMDEV_CREDENTIALS_SZ_SIZE          128
+
+/**
+ * Credentials request structure.
+ *
+ * Used by VMMDevReq_QueryCredentials.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** IN/OUT: Request flags. */
+    uint32_t u32Flags;
+    /** OUT: User name (UTF-8). */
+    char szUserName[VMMDEV_CREDENTIALS_SZ_SIZE];
+    /** OUT: Password (UTF-8). */
+    char szPassword[VMMDEV_CREDENTIALS_SZ_SIZE];
+    /** OUT: Domain name (UTF-8). */
+    char szDomain[VMMDEV_CREDENTIALS_SZ_SIZE];
+} VMMDevCredentials;
+AssertCompileSize(VMMDevCredentials, 24+4+3*128);
+
+/** @name Credentials request flag (VMMDevCredentials::u32Flags)
+ * @{ */
+/** query from host whether credentials are present */
+#define VMMDEV_CREDENTIALS_QUERYPRESENCE     RT_BIT(1)
+/** read credentials from host (can be combined with clear) */
+#define VMMDEV_CREDENTIALS_READ              RT_BIT(2)
+/** clear credentials on host (can be combined with read) */
+#define VMMDEV_CREDENTIALS_CLEAR             RT_BIT(3)
+/** read credentials for judgement in the guest */
+#define VMMDEV_CREDENTIALS_READJUDGE         RT_BIT(8)
+/** clear credentials for judegement on the host */
+#define VMMDEV_CREDENTIALS_CLEARJUDGE        RT_BIT(9)
+/** report credentials acceptance by guest */
+#define VMMDEV_CREDENTIALS_JUDGE_OK          RT_BIT(10)
+/** report credentials denial by guest */
+#define VMMDEV_CREDENTIALS_JUDGE_DENY        RT_BIT(11)
+/** report that no judgement could be made by guest */
+#define VMMDEV_CREDENTIALS_JUDGE_NOJUDGEMENT RT_BIT(12)
+
+/** flag telling the guest that credentials are present */
+#define VMMDEV_CREDENTIALS_PRESENT           RT_BIT(16)
+/** flag telling guest that local logons should be prohibited */
+#define VMMDEV_CREDENTIALS_NOLOCALLOGON      RT_BIT(17)
+/** @} */
+
+
+/**
+ * Seamless mode change request structure.
+ *
+ * Used by VMMDevReq_GetSeamlessChangeRequest.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+
+    /** New seamless mode. */
+    VMMDevSeamlessMode mode;
+    /** Setting this to VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST indicates
+     * that the request is a response to that event.
+     * (Don't confuse this with VMMDevReq_AcknowledgeEvents.) */
+    uint32_t eventAck;
+} VMMDevSeamlessChangeRequest;
+AssertCompileSize(VMMDevSeamlessChangeRequest, 24+8);
+AssertCompileMemberOffset(VMMDevSeamlessChangeRequest, eventAck, 24+4);
+
+
+/**
+ * Display change request structure.
+ *
+ * Used by VMMDevReq_GetDisplayChangeRequest.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Horizontal pixel resolution (0 = do not change). */
+    uint32_t xres;
+    /** Vertical pixel resolution (0 = do not change). */
+    uint32_t yres;
+    /** Bits per pixel (0 = do not change). */
+    uint32_t bpp;
+    /** Setting this to VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST indicates
+     * that the request is a response to that event.
+     * (Don't confuse this with VMMDevReq_AcknowledgeEvents.) */
+    uint32_t eventAck;
+} VMMDevDisplayChangeRequest;
+AssertCompileSize(VMMDevDisplayChangeRequest, 24+16);
+
+
+/**
+ * Display change request structure, version 2.
+ *
+ * Used by VMMDevReq_GetDisplayChangeRequest2.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Horizontal pixel resolution (0 = do not change). */
+    uint32_t xres;
+    /** Vertical pixel resolution (0 = do not change). */
+    uint32_t yres;
+    /** Bits per pixel (0 = do not change). */
+    uint32_t bpp;
+    /** Setting this to VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST indicates
+     * that the request is a response to that event.
+     * (Don't confuse this with VMMDevReq_AcknowledgeEvents.) */
+    uint32_t eventAck;
+    /** 0 for primary display, 1 for the first secondary, etc. */
+    uint32_t display;
+} VMMDevDisplayChangeRequest2;
+AssertCompileSize(VMMDevDisplayChangeRequest2, 24+20);
+
+
+/**
+ * Display change request structure, version Extended.
+ *
+ * Used by VMMDevReq_GetDisplayChangeRequestEx.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Horizontal pixel resolution (0 = do not change). */
+    uint32_t xres;
+    /** Vertical pixel resolution (0 = do not change). */
+    uint32_t yres;
+    /** Bits per pixel (0 = do not change). */
+    uint32_t bpp;
+    /** Setting this to VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST indicates
+     * that the request is a response to that event.
+     * (Don't confuse this with VMMDevReq_AcknowledgeEvents.) */
+    uint32_t eventAck;
+    /** 0 for primary display, 1 for the first secondary, etc. */
+    uint32_t display;
+    /** New OriginX of secondary virtual screen */
+    uint32_t cxOrigin;
+    /** New OriginY of secondary virtual screen  */
+    uint32_t cyOrigin;
+    /** Change in origin of the secondary virtaul scree is
+     *  required */
+    bool fChangeOrigin;
+    /** secondary virtual screen enabled or disabled */
+    bool fEnabled;
+} VMMDevDisplayChangeRequestEx;
+AssertCompileSize(VMMDevDisplayChangeRequestEx, 24+32);
+
+
+/**
+ * Video mode supported request structure.
+ *
+ * Used by VMMDevReq_VideoModeSupported.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** IN: Horizontal pixel resolution. */
+    uint32_t width;
+    /** IN: Vertical pixel resolution. */
+    uint32_t height;
+    /** IN: Bits per pixel. */
+    uint32_t bpp;
+    /** OUT: Support indicator. */
+    bool fSupported;
+} VMMDevVideoModeSupportedRequest;
+AssertCompileSize(VMMDevVideoModeSupportedRequest, 24+16);
+
+/**
+ * Video mode supported request structure for a specific display.
+ *
+ * Used by VMMDevReq_VideoModeSupported2.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** IN: The guest display number. */
+    uint32_t display;
+    /** IN: Horizontal pixel resolution. */
+    uint32_t width;
+    /** IN: Vertical pixel resolution. */
+    uint32_t height;
+    /** IN: Bits per pixel. */
+    uint32_t bpp;
+    /** OUT: Support indicator. */
+    bool fSupported;
+} VMMDevVideoModeSupportedRequest2;
+AssertCompileSize(VMMDevVideoModeSupportedRequest2, 24+20);
+
+/**
+ * Video modes height reduction request structure.
+ *
+ * Used by VMMDevReq_GetHeightReduction.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** OUT: Height reduction in pixels. */
+    uint32_t heightReduction;
+} VMMDevGetHeightReductionRequest;
+AssertCompileSize(VMMDevGetHeightReductionRequest, 24+4);
+
+
+/**
+ * VRDP change request structure.
+ *
+ * Used by VMMDevReq_GetVRDPChangeRequest.
+ */
+typedef struct
+{
+    /** Header */
+    VMMDevRequestHeader header;
+    /** Whether VRDP is active or not. */
+    uint8_t u8VRDPActive;
+    /** The configured experience level for active VRDP. */
+    uint32_t u32VRDPExperienceLevel;
+} VMMDevVRDPChangeRequest;
+AssertCompileSize(VMMDevVRDPChangeRequest, 24+8);
+AssertCompileMemberOffset(VMMDevVRDPChangeRequest, u8VRDPActive, 24);
+AssertCompileMemberOffset(VMMDevVRDPChangeRequest, u32VRDPExperienceLevel, 24+4);
+
+/** @name VRDP Experience level (VMMDevVRDPChangeRequest::u32VRDPExperienceLevel)
+ * @{ */
+#define VRDP_EXPERIENCE_LEVEL_ZERO     0 /**< Theming disabled. */
+#define VRDP_EXPERIENCE_LEVEL_LOW      1 /**< Full window dragging and desktop wallpaper disabled. */
+#define VRDP_EXPERIENCE_LEVEL_MEDIUM   2 /**< Font smoothing, gradients. */
+#define VRDP_EXPERIENCE_LEVEL_HIGH     3 /**< Animation effects disabled. */
+#define VRDP_EXPERIENCE_LEVEL_FULL     4 /**< Everything enabled. */
+/** @} */
+
+
+/**
+ * VBVA enable request structure.
+ *
+ * Used by VMMDevReq_VideoAccelEnable.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** 0 - disable, !0 - enable. */
+    uint32_t u32Enable;
+    /** The size of VBVAMEMORY::au8RingBuffer expected by driver.
+     *  The host will refuse to enable VBVA if the size is not equal to
+     *  VBVA_RING_BUFFER_SIZE.
+     */
+    uint32_t cbRingBuffer;
+    /** Guest initializes the status to 0. Host sets appropriate VBVA_F_STATUS_ flags. */
+    uint32_t fu32Status;
+} VMMDevVideoAccelEnable;
+AssertCompileSize(VMMDevVideoAccelEnable, 24+12);
+
+/** @name VMMDevVideoAccelEnable::fu32Status.
+ * @{ */
+#define VBVA_F_STATUS_ACCEPTED (0x01)
+#define VBVA_F_STATUS_ENABLED  (0x02)
+/** @} */
+
+
+/**
+ * VBVA flush request structure.
+ *
+ * Used by VMMDevReq_VideoAccelFlush.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+} VMMDevVideoAccelFlush;
+AssertCompileSize(VMMDevVideoAccelFlush, 24);
+
+
+/**
+ * VBVA set visible region request structure.
+ *
+ * Used by VMMDevReq_VideoSetVisibleRegion.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Number of rectangles */
+    uint32_t cRect;
+    /** Rectangle array.
+     * @todo array is spelled aRects[1].  */
+    RTRECT Rect;
+} VMMDevVideoSetVisibleRegion;
+AssertCompileSize(RTRECT, 16);
+AssertCompileSize(VMMDevVideoSetVisibleRegion, 24+4+16);
+
+/**
+ * CPU event types.
+ */
+typedef enum
+{
+    VMMDevCpuStatusType_Invalid  = 0,
+    VMMDevCpuStatusType_Disable  = 1,
+    VMMDevCpuStatusType_Enable   = 2,
+    VMMDevCpuStatusType_SizeHack = 0x7fffffff
+} VMMDevCpuStatusType;
+
+/**
+ * CPU hotplug event status request.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Status type */
+    VMMDevCpuStatusType enmStatusType;
+} VMMDevCpuHotPlugStatusRequest;
+AssertCompileSize(VMMDevCpuHotPlugStatusRequest, 24+4);
+
+/**
+ * Get the ID of the changed CPU and event type.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Event type */
+    VMMDevCpuEventType  enmEventType;
+    /** core id of the CPU changed */
+    uint32_t            idCpuCore;
+    /** package id of the CPU changed */
+    uint32_t            idCpuPackage;
+} VMMDevGetCpuHotPlugRequest;
+AssertCompileSize(VMMDevGetCpuHotPlugRequest, 24+4+4+4);
+
+
+/**
+ * Shared region description
+ */
+typedef struct VMMDEVSHAREDREGIONDESC
+{
+    RTGCPTR64           GCRegionAddr;
+    uint32_t            cbRegion;
+    uint32_t            u32Alignment;
+} VMMDEVSHAREDREGIONDESC;
+AssertCompileSize(VMMDEVSHAREDREGIONDESC, 16);
+
+#define VMMDEVSHAREDREGIONDESC_MAX          32
+
+/**
+ * Shared module registration
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader         header;
+    /** Shared module size. */
+    uint32_t                    cbModule;
+    /** Number of included region descriptors */
+    uint32_t                    cRegions;
+    /** Base address of the shared module. */
+    RTGCPTR64                   GCBaseAddr;
+    /** Guest OS type. */
+    VBOXOSFAMILY                enmGuestOS;
+    /** Alignment. */
+    uint32_t                    u32Align;
+    /** Module name */
+    char                        szName[128];
+    /** Module version */
+    char                        szVersion[16];
+    /** Shared region descriptor(s). */
+    VMMDEVSHAREDREGIONDESC      aRegions[1];
+} VMMDevSharedModuleRegistrationRequest;
+AssertCompileSize(VMMDevSharedModuleRegistrationRequest, 24+4+4+8+4+4+128+16+16);
+
+
+/**
+ * Shared module unregistration
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader         header;
+    /** Shared module size. */
+    uint32_t                    cbModule;
+    /** Align at 8 byte boundary. */
+    uint32_t                    u32Alignment;
+    /** Base address of the shared module. */
+    RTGCPTR64                   GCBaseAddr;
+    /** Module name */
+    char                        szName[128];
+    /** Module version */
+    char                        szVersion[16];
+} VMMDevSharedModuleUnregistrationRequest;
+AssertCompileSize(VMMDevSharedModuleUnregistrationRequest, 24+4+4+8+128+16);
+
+
+/**
+ * Shared module periodic check
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader         header;
+} VMMDevSharedModuleCheckRequest;
+AssertCompileSize(VMMDevSharedModuleCheckRequest, 24);
+
+/**
+ * Paging sharing enabled query
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader         header;
+    /** Enabled flag (out) */
+    bool                        fEnabled;
+    /** Alignment */
+    bool                        fAlignment[3];
+} VMMDevPageSharingStatusRequest;
+AssertCompileSize(VMMDevPageSharingStatusRequest, 24+4);
+
+
+/**
+ * Page sharing status query (debug build only)
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader         header;
+    /** Page address. */
+    RTGCPTR                     GCPtrPage;
+    /** Page flags. */
+    uint64_t                    uPageFlags;
+    /** Shared flag (out) */
+    bool                        fShared;
+    /** Alignment */
+    bool                        fAlignment[3];
+} VMMDevPageIsSharedRequest;
+
+/**
+ * Session id request structure.
+ *
+ * Used by VMMDevReq_GetSessionId.
+ */
+typedef struct
+{
+    /** Header */
+    VMMDevRequestHeader header;
+    /** OUT: unique session id; the id will be different after each start, reset or restore of the VM */
+    uint64_t            idSession;
+} VMMDevReqSessionId;
+AssertCompileSize(VMMDevReqSessionId, 24+8);
+
+
+/**
+ * Write Core Dump request.
+ *
+ * Used by VMMDevReq_WriteCoreDump.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** Flags (reserved, MBZ). */
+    uint32_t            fFlags;
+} VMMDevReqWriteCoreDump;
+AssertCompileSize(VMMDevReqWriteCoreDump, 24+4);
+
+/** Heart beat check state structure.
+ *  Used by VMMDevReq_HeartbeatConfigure. */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** OUT: Guest heartbeat interval in nanosec. */
+    uint64_t    cNsInterval;
+    /** Heartbeat check flag. */
+    bool fEnabled;
+} VMMDevReqHeartbeat;
+AssertCompileSize(VMMDevReqHeartbeat, 24+12);
+
+
+
+#ifdef VBOX_WITH_HGCM
+
+/** @name HGCM flags.
+ * @{
+ */
+# define VBOX_HGCM_REQ_DONE      RT_BIT_32(VBOX_HGCM_REQ_DONE_BIT)
+# define VBOX_HGCM_REQ_DONE_BIT  0
+# define VBOX_HGCM_REQ_CANCELLED (0x2)
+/** @} */
+
+/**
+ * HGCM request header.
+ */
+typedef struct VMMDevHGCMRequestHeader
+{
+    /** Request header. */
+    VMMDevRequestHeader header;
+
+    /** HGCM flags. */
+    uint32_t fu32Flags;
+
+    /** Result code. */
+    int32_t result;
+} VMMDevHGCMRequestHeader;
+AssertCompileSize(VMMDevHGCMRequestHeader, 24+8);
+
+/**
+ * HGCM connect request structure.
+ *
+ * Used by VMMDevReq_HGCMConnect.
+ */
+typedef struct
+{
+    /** HGCM request header. */
+    VMMDevHGCMRequestHeader header;
+
+    /** IN: Description of service to connect to. */
+    HGCMServiceLocation loc;
+
+    /** OUT: Client identifier assigned by local instance of HGCM. */
+    uint32_t u32ClientID;
+} VMMDevHGCMConnect;
+AssertCompileSize(VMMDevHGCMConnect, 32+132+4);
+
+
+/**
+ * HGCM disconnect request structure.
+ *
+ * Used by VMMDevReq_HGCMDisconnect.
+ */
+typedef struct
+{
+    /** HGCM request header. */
+    VMMDevHGCMRequestHeader header;
+
+    /** IN: Client identifier. */
+    uint32_t u32ClientID;
+} VMMDevHGCMDisconnect;
+AssertCompileSize(VMMDevHGCMDisconnect, 32+4);
+
+/**
+ * HGCM parameter type.
+ */
+typedef enum
+{
+    VMMDevHGCMParmType_Invalid            = 0,
+    VMMDevHGCMParmType_32bit              = 1,
+    VMMDevHGCMParmType_64bit              = 2,
+    VMMDevHGCMParmType_PhysAddr           = 3,  /**< @deprecated Doesn't work, use PageList. */
+    VMMDevHGCMParmType_LinAddr            = 4,  /**< In and Out */
+    VMMDevHGCMParmType_LinAddr_In         = 5,  /**< In  (read;  host<-guest) */
+    VMMDevHGCMParmType_LinAddr_Out        = 6,  /**< Out (write; host->guest) */
+    VMMDevHGCMParmType_LinAddr_Locked     = 7,  /**< Locked In and Out */
+    VMMDevHGCMParmType_LinAddr_Locked_In  = 8,  /**< Locked In  (read;  host<-guest) */
+    VMMDevHGCMParmType_LinAddr_Locked_Out = 9,  /**< Locked Out (write; host->guest) */
+    VMMDevHGCMParmType_PageList           = 10, /**< Physical addresses of locked pages for a buffer. */
+    VMMDevHGCMParmType_SizeHack           = 0x7fffffff
+} HGCMFunctionParameterType;
+AssertCompileSize(HGCMFunctionParameterType, 4);
+
+# ifdef VBOX_WITH_64_BITS_GUESTS
+/**
+ * HGCM function parameter, 32-bit client.
+ */
+typedef struct
+{
+    HGCMFunctionParameterType type;
+    union
+    {
+        uint32_t   value32;
+        uint64_t   value64;
+        struct
+        {
+            uint32_t size;
+
+            union
+            {
+                RTGCPHYS32 physAddr;
+                RTGCPTR32  linearAddr;
+            } u;
+        } Pointer;
+        struct
+        {
+            uint32_t size;   /**< Size of the buffer described by the page list. */
+            uint32_t offset; /**< Relative to the request header, valid if size != 0. */
+        } PageList;
+    } u;
+#  ifdef __cplusplus
+    void SetUInt32(uint32_t u32)
+    {
+        type = VMMDevHGCMParmType_32bit;
+        u.value64 = 0; /* init unused bits to 0 */
+        u.value32 = u32;
+    }
+
+    int GetUInt32(uint32_t *pu32)
+    {
+        if (type == VMMDevHGCMParmType_32bit)
+        {
+            *pu32 = u.value32;
+            return VINF_SUCCESS;
+        }
+        return VERR_INVALID_PARAMETER;
+    }
+
+    void SetUInt64(uint64_t u64)
+    {
+        type      = VMMDevHGCMParmType_64bit;
+        u.value64 = u64;
+    }
+
+    int GetUInt64(uint64_t *pu64)
+    {
+        if (type == VMMDevHGCMParmType_64bit)
+        {
+            *pu64 = u.value64;
+            return VINF_SUCCESS;
+        }
+        return VERR_INVALID_PARAMETER;
+    }
+
+    void SetPtr(void *pv, uint32_t cb)
+    {
+        type                    = VMMDevHGCMParmType_LinAddr;
+        u.Pointer.size          = cb;
+        u.Pointer.u.linearAddr  = (RTGCPTR32)(uintptr_t)pv;
+    }
+#  endif /* __cplusplus */
+} HGCMFunctionParameter32;
+AssertCompileSize(HGCMFunctionParameter32, 4+8);
+
+/**
+ * HGCM function parameter, 64-bit client.
+ */
+typedef struct
+{
+    HGCMFunctionParameterType type;
+    union
+    {
+        uint32_t   value32;
+        uint64_t   value64;
+        struct
+        {
+            uint32_t size;
+
+            union
+            {
+                RTGCPHYS64 physAddr;
+                RTGCPTR64  linearAddr;
+            } u;
+        } Pointer;
+        struct
+        {
+            uint32_t size;   /**< Size of the buffer described by the page list. */
+            uint32_t offset; /**< Relative to the request header, valid if size != 0. */
+        } PageList;
+    } u;
+#  ifdef __cplusplus
+    void SetUInt32(uint32_t u32)
+    {
+        type = VMMDevHGCMParmType_32bit;
+        u.value64 = 0; /* init unused bits to 0 */
+        u.value32 = u32;
+    }
+
+    int GetUInt32(uint32_t *pu32)
+    {
+        if (type == VMMDevHGCMParmType_32bit)
+        {
+            *pu32 = u.value32;
+            return VINF_SUCCESS;
+        }
+        return VERR_INVALID_PARAMETER;
+    }
+
+    void SetUInt64(uint64_t u64)
+    {
+        type      = VMMDevHGCMParmType_64bit;
+        u.value64 = u64;
+    }
+
+    int GetUInt64(uint64_t *pu64)
+    {
+        if (type == VMMDevHGCMParmType_64bit)
+        {
+            *pu64 = u.value64;
+            return VINF_SUCCESS;
+        }
+        return VERR_INVALID_PARAMETER;
+    }
+
+    void SetPtr(void *pv, uint32_t cb)
+    {
+        type                    = VMMDevHGCMParmType_LinAddr;
+        u.Pointer.size          = cb;
+        u.Pointer.u.linearAddr  = (uintptr_t)pv;
+    }
+#  endif /** __cplusplus */
+} HGCMFunctionParameter64;
+AssertCompileSize(HGCMFunctionParameter64, 4+12);
+
+/* Redefine the structure type for the guest code. */
+#  ifndef VBOX_HGCM_HOST_CODE
+#   if ARCH_BITS == 64
+#     define HGCMFunctionParameter  HGCMFunctionParameter64
+#   elif ARCH_BITS == 32
+#     define HGCMFunctionParameter  HGCMFunctionParameter32
+#   else
+#    error "Unsupported sizeof (void *)"
+#   endif
+#  endif /* !VBOX_HGCM_HOST_CODE */
+
+# else /* !VBOX_WITH_64_BITS_GUESTS */
+
+/**
+ * HGCM function parameter, 32-bit client.
+ *
+ * @todo If this is the same as HGCMFunctionParameter32, why the duplication?
+ */
+typedef struct
+{
+    HGCMFunctionParameterType type;
+    union
+    {
+        uint32_t   value32;
+        uint64_t   value64;
+        struct
+        {
+            uint32_t size;
+
+            union
+            {
+                RTGCPHYS32 physAddr;
+                RTGCPTR32  linearAddr;
+            } u;
+        } Pointer;
+        struct
+        {
+            uint32_t size;   /**< Size of the buffer described by the page list. */
+            uint32_t offset; /**< Relative to the request header, valid if size != 0. */
+        } PageList;
+    } u;
+#  ifdef __cplusplus
+    void SetUInt32(uint32_t u32)
+    {
+        type = VMMDevHGCMParmType_32bit;
+        u.value64 = 0; /* init unused bits to 0 */
+        u.value32 = u32;
+    }
+
+    int GetUInt32(uint32_t *pu32)
+    {
+        if (type == VMMDevHGCMParmType_32bit)
+        {
+            *pu32 = u.value32;
+            return VINF_SUCCESS;
+        }
+        return VERR_INVALID_PARAMETER;
+    }
+
+    void SetUInt64(uint64_t u64)
+    {
+        type      = VMMDevHGCMParmType_64bit;
+        u.value64 = u64;
+    }
+
+    int GetUInt64(uint64_t *pu64)
+    {
+        if (type == VMMDevHGCMParmType_64bit)
+        {
+            *pu64 = u.value64;
+            return VINF_SUCCESS;
+        }
+        return VERR_INVALID_PARAMETER;
+    }
+
+    void SetPtr(void *pv, uint32_t cb)
+    {
+        type                    = VMMDevHGCMParmType_LinAddr;
+        u.Pointer.size          = cb;
+        u.Pointer.u.linearAddr  = (uintptr_t)pv;
+    }
+#  endif /* __cplusplus */
+} HGCMFunctionParameter;
+AssertCompileSize(HGCMFunctionParameter, 4+8);
+# endif /* !VBOX_WITH_64_BITS_GUESTS */
+
+/**
+ * HGCM call request structure.
+ *
+ * Used by VMMDevReq_HGCMCall, VMMDevReq_HGCMCall32 and VMMDevReq_HGCMCall64.
+ */
+typedef struct
+{
+    /* request header */
+    VMMDevHGCMRequestHeader header;
+
+    /** IN: Client identifier. */
+    uint32_t u32ClientID;
+    /** IN: Service function number. */
+    uint32_t u32Function;
+    /** IN: Number of parameters. */
+    uint32_t cParms;
+    /** Parameters follow in form: HGCMFunctionParameter aParms[X]; */
+} VMMDevHGCMCall;
+AssertCompileSize(VMMDevHGCMCall, 32+12);
+
+/** @name Direction of data transfer (HGCMPageListInfo::flags). Bit flags.
+ * @{ */
+#define VBOX_HGCM_F_PARM_DIRECTION_NONE      UINT32_C(0x00000000)
+#define VBOX_HGCM_F_PARM_DIRECTION_TO_HOST   UINT32_C(0x00000001)
+#define VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST UINT32_C(0x00000002)
+#define VBOX_HGCM_F_PARM_DIRECTION_BOTH      UINT32_C(0x00000003)
+/** Macro for validating that the specified flags are valid. */
+#define VBOX_HGCM_F_PARM_ARE_VALID(fFlags) \
+    (   (fFlags) > VBOX_HGCM_F_PARM_DIRECTION_NONE \
+     && (fFlags) < VBOX_HGCM_F_PARM_DIRECTION_BOTH )
+/** @} */
+
+/**
+ * VMMDevHGCMParmType_PageList points to this structure to actually describe the
+ * buffer.
+ */
+typedef struct
+{
+    uint32_t flags;        /**< VBOX_HGCM_F_PARM_*. */
+    uint16_t offFirstPage; /**< Offset in the first page where data begins. */
+    uint16_t cPages;       /**< Number of pages. */
+    RTGCPHYS64 aPages[1];  /**< Page addresses. */
+} HGCMPageListInfo;
+AssertCompileSize(HGCMPageListInfo, 4+2+2+8);
+
+
+/** Get the pointer to the first parmater of a HGCM call request.  */
+# define VMMDEV_HGCM_CALL_PARMS(a)   ((HGCMFunctionParameter *)((uint8_t *)(a) + sizeof (VMMDevHGCMCall)))
+/** Get the pointer to the first parmater of a 32-bit HGCM call request.  */
+# define VMMDEV_HGCM_CALL_PARMS32(a) ((HGCMFunctionParameter32 *)((uint8_t *)(a) + sizeof (VMMDevHGCMCall)))
+
+# ifdef VBOX_WITH_64_BITS_GUESTS
+/* Explicit defines for the host code. */
+#  ifdef VBOX_HGCM_HOST_CODE
+#   define VMMDEV_HGCM_CALL_PARMS32(a) ((HGCMFunctionParameter32 *)((uint8_t *)(a) + sizeof (VMMDevHGCMCall)))
+#   define VMMDEV_HGCM_CALL_PARMS64(a) ((HGCMFunctionParameter64 *)((uint8_t *)(a) + sizeof (VMMDevHGCMCall)))
+#  endif /* VBOX_HGCM_HOST_CODE */
+# endif /* VBOX_WITH_64_BITS_GUESTS */
+
+# define VBOX_HGCM_MAX_PARMS 32
+
+/**
+ * HGCM cancel request structure.
+ *
+ * The Cancel request is issued using the same physical memory address as was
+ * used for the corresponding initial HGCMCall.
+ *
+ * Used by VMMDevReq_HGCMCancel.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevHGCMRequestHeader header;
+} VMMDevHGCMCancel;
+AssertCompileSize(VMMDevHGCMCancel, 32);
+
+/**
+ * HGCM cancel request structure, version 2.
+ *
+ * Used by VMMDevReq_HGCMCancel2.
+ *
+ * VINF_SUCCESS when cancelled.
+ * VERR_NOT_FOUND if the specified request cannot be found.
+ * VERR_INVALID_PARAMETER if the address is invalid valid.
+ */
+typedef struct
+{
+    /** Header. */
+    VMMDevRequestHeader header;
+    /** The physical address of the request to cancel. */
+    RTGCPHYS32 physReqToCancel;
+} VMMDevHGCMCancel2;
+AssertCompileSize(VMMDevHGCMCancel2, 24+4);
+
+#endif /* VBOX_WITH_HGCM */
+
+
+/**
+ * Inline helper to determine the request size for the given operation.
+ * Returns 0 if the given operation is not handled and/or supported.
+ *
+ * @returns Size.
+ * @param   requestType     The VMMDev request type.
+ */
+DECLINLINE(size_t) vmmdevGetRequestSize(VMMDevRequestType requestType)
+{
+    switch (requestType)
+    {
+        case VMMDevReq_GetMouseStatus:
+        case VMMDevReq_SetMouseStatus:
+            return sizeof(VMMDevReqMouseStatus);
+        case VMMDevReq_SetPointerShape:
+            return sizeof(VMMDevReqMousePointer);
+        case VMMDevReq_GetHostVersion:
+            return sizeof(VMMDevReqHostVersion);
+        case VMMDevReq_Idle:
+            return sizeof(VMMDevReqIdle);
+        case VMMDevReq_GetHostTime:
+            return sizeof(VMMDevReqHostTime);
+        case VMMDevReq_GetHypervisorInfo:
+        case VMMDevReq_SetHypervisorInfo:
+            return sizeof(VMMDevReqHypervisorInfo);
+        case VMMDevReq_RegisterPatchMemory:
+        case VMMDevReq_DeregisterPatchMemory:
+            return sizeof(VMMDevReqPatchMemory);
+        case VMMDevReq_SetPowerStatus:
+            return sizeof(VMMDevPowerStateRequest);
+        case VMMDevReq_AcknowledgeEvents:
+            return sizeof(VMMDevEvents);
+        case VMMDevReq_ReportGuestInfo:
+            return sizeof(VMMDevReportGuestInfo);
+        case VMMDevReq_ReportGuestInfo2:
+            return sizeof(VMMDevReportGuestInfo2);
+        case VMMDevReq_ReportGuestStatus:
+            return sizeof(VMMDevReportGuestStatus);
+        case VMMDevReq_ReportGuestUserState:
+            return sizeof(VMMDevReportGuestUserState);
+        case VMMDevReq_GetDisplayChangeRequest:
+            return sizeof(VMMDevDisplayChangeRequest);
+        case VMMDevReq_GetDisplayChangeRequest2:
+            return sizeof(VMMDevDisplayChangeRequest2);
+        case VMMDevReq_GetDisplayChangeRequestEx:
+            return sizeof(VMMDevDisplayChangeRequestEx);
+        case VMMDevReq_VideoModeSupported:
+            return sizeof(VMMDevVideoModeSupportedRequest);
+        case VMMDevReq_GetHeightReduction:
+            return sizeof(VMMDevGetHeightReductionRequest);
+        case VMMDevReq_ReportGuestCapabilities:
+            return sizeof(VMMDevReqGuestCapabilities);
+        case VMMDevReq_SetGuestCapabilities:
+            return sizeof(VMMDevReqGuestCapabilities2);
+#ifdef VBOX_WITH_HGCM
+        case VMMDevReq_HGCMConnect:
+            return sizeof(VMMDevHGCMConnect);
+        case VMMDevReq_HGCMDisconnect:
+            return sizeof(VMMDevHGCMDisconnect);
+#ifdef VBOX_WITH_64_BITS_GUESTS
+        case VMMDevReq_HGCMCall32:
+            return sizeof(VMMDevHGCMCall);
+        case VMMDevReq_HGCMCall64:
+            return sizeof(VMMDevHGCMCall);
+#else
+        case VMMDevReq_HGCMCall:
+            return sizeof(VMMDevHGCMCall);
+#endif /* VBOX_WITH_64_BITS_GUESTS */
+        case VMMDevReq_HGCMCancel:
+            return sizeof(VMMDevHGCMCancel);
+#endif /* VBOX_WITH_HGCM */
+        case VMMDevReq_VideoAccelEnable:
+            return sizeof(VMMDevVideoAccelEnable);
+        case VMMDevReq_VideoAccelFlush:
+            return sizeof(VMMDevVideoAccelFlush);
+        case VMMDevReq_VideoSetVisibleRegion:
+            /* The original protocol didn't consider a guest with NO visible
+             * windows */
+            return sizeof(VMMDevVideoSetVisibleRegion) - sizeof(RTRECT);
+        case VMMDevReq_GetSeamlessChangeRequest:
+            return sizeof(VMMDevSeamlessChangeRequest);
+        case VMMDevReq_QueryCredentials:
+            return sizeof(VMMDevCredentials);
+        case VMMDevReq_ReportGuestStats:
+            return sizeof(VMMDevReportGuestStats);
+        case VMMDevReq_GetMemBalloonChangeRequest:
+            return sizeof(VMMDevGetMemBalloonChangeRequest);
+        case VMMDevReq_GetStatisticsChangeRequest:
+            return sizeof(VMMDevGetStatisticsChangeRequest);
+        case VMMDevReq_ChangeMemBalloon:
+            return sizeof(VMMDevChangeMemBalloon);
+        case VMMDevReq_GetVRDPChangeRequest:
+            return sizeof(VMMDevVRDPChangeRequest);
+        case VMMDevReq_LogString:
+            return sizeof(VMMDevReqLogString);
+        case VMMDevReq_CtlGuestFilterMask:
+            return sizeof(VMMDevCtlGuestFilterMask);
+        case VMMDevReq_GetCpuHotPlugRequest:
+            return sizeof(VMMDevGetCpuHotPlugRequest);
+        case VMMDevReq_SetCpuHotPlugStatus:
+            return sizeof(VMMDevCpuHotPlugStatusRequest);
+        case VMMDevReq_RegisterSharedModule:
+            return sizeof(VMMDevSharedModuleRegistrationRequest);
+        case VMMDevReq_UnregisterSharedModule:
+            return sizeof(VMMDevSharedModuleUnregistrationRequest);
+        case VMMDevReq_CheckSharedModules:
+            return sizeof(VMMDevSharedModuleCheckRequest);
+        case VMMDevReq_GetPageSharingStatus:
+            return sizeof(VMMDevPageSharingStatusRequest);
+        case VMMDevReq_DebugIsPageShared:
+            return sizeof(VMMDevPageIsSharedRequest);
+        case VMMDevReq_GetSessionId:
+            return sizeof(VMMDevReqSessionId);
+        case VMMDevReq_HeartbeatConfigure:
+            return sizeof(VMMDevReqHeartbeat);
+        case VMMDevReq_GuestHeartbeat:
+            return sizeof(VMMDevRequestHeader);
+        default:
+            break;
+    }
+
+    return 0;
+}
+
+
+/**
+ * Initializes a request structure.
+ *
+ * @returns VBox status code.
+ * @param   req             The request structure to initialize.
+ * @param   type            The request type.
+ */
+DECLINLINE(int) vmmdevInitRequest(VMMDevRequestHeader *req, VMMDevRequestType type)
+{
+    uint32_t requestSize;
+    if (!req)
+        return VERR_INVALID_PARAMETER;
+    requestSize = (uint32_t)vmmdevGetRequestSize(type);
+    if (!requestSize)
+        return VERR_INVALID_PARAMETER;
+    req->size        = requestSize;
+    req->version     = VMMDEV_REQUEST_HEADER_VERSION;
+    req->requestType = type;
+    req->rc          = VERR_GENERAL_FAILURE;
+    req->reserved1   = 0;
+    req->reserved2   = 0;
+    return VINF_SUCCESS;
+}
+
+/** @} */
+
+
+/**
+ * VBVA command header.
+ *
+ * @todo Where does this fit in?
+ */
+typedef struct VBVACMDHDR
+{
+   /** Coordinates of affected rectangle. */
+   int16_t x;
+   int16_t y;
+   uint16_t w;
+   uint16_t h;
+} VBVACMDHDR;
+AssertCompileSize(VBVACMDHDR, 8);
+
+/** @name VBVA ring defines.
+ *
+ * The VBVA ring buffer is suitable for transferring large (< 2GB) amount of
+ * data. For example big bitmaps which do not fit to the buffer.
+ *
+ * Guest starts writing to the buffer by initializing a record entry in the
+ * aRecords queue. VBVA_F_RECORD_PARTIAL indicates that the record is being
+ * written. As data is written to the ring buffer, the guest increases off32End
+ * for the record.
+ *
+ * The host reads the aRecords on flushes and processes all completed records.
+ * When host encounters situation when only a partial record presents and
+ * cbRecord & ~VBVA_F_RECORD_PARTIAL >= VBVA_RING_BUFFER_SIZE -
+ * VBVA_RING_BUFFER_THRESHOLD, the host fetched all record data and updates
+ * off32Head. After that on each flush the host continues fetching the data
+ * until the record is completed.
+ *
+ */
+#define VBVA_RING_BUFFER_SIZE        (_4M - _1K)
+#define VBVA_RING_BUFFER_THRESHOLD   (4 * _1K)
+
+#define VBVA_MAX_RECORDS (64)
+
+#define VBVA_F_MODE_ENABLED         UINT32_C(0x00000001)
+#define VBVA_F_MODE_VRDP            UINT32_C(0x00000002)
+#define VBVA_F_MODE_VRDP_RESET      UINT32_C(0x00000004)
+#define VBVA_F_MODE_VRDP_ORDER_MASK UINT32_C(0x00000008)
+
+#define VBVA_F_STATE_PROCESSING     UINT32_C(0x00010000)
+
+#define VBVA_F_RECORD_PARTIAL       UINT32_C(0x80000000)
+/** @} */
+
+/**
+ * VBVA record.
+ */
+typedef struct VBVARECORD
+{
+    /** The length of the record. Changed by guest. */
+    uint32_t cbRecord;
+} VBVARECORD;
+AssertCompileSize(VBVARECORD, 4);
+
+
+/**
+ * VBVA memory layout.
+ *
+ * This is a subsection of the VMMDevMemory structure.
+ */
+typedef struct VBVAMEMORY
+{
+    /** VBVA_F_MODE_*. */
+    uint32_t fu32ModeFlags;
+
+    /** The offset where the data start in the buffer. */
+    uint32_t off32Data;
+    /** The offset where next data must be placed in the buffer. */
+    uint32_t off32Free;
+
+    /** The ring buffer for data. */
+    uint8_t  au8RingBuffer[VBVA_RING_BUFFER_SIZE];
+
+    /** The queue of record descriptions. */
+    VBVARECORD aRecords[VBVA_MAX_RECORDS];
+    uint32_t indexRecordFirst;
+    uint32_t indexRecordFree;
+
+    /** RDP orders supported by the client. The guest reports only them
+     * and falls back to DIRTY rects for not supported ones.
+     *
+     * (1 << VBVA_VRDP_*)
+     */
+    uint32_t fu32SupportedOrders;
+
+} VBVAMEMORY;
+AssertCompileSize(VBVAMEMORY, 12 + (_4M-_1K) + 4*64 + 12);
+
+
+/**
+ * The layout of VMMDEV RAM region that contains information for guest.
+ */
+typedef struct VMMDevMemory
+{
+    /** The size of this structure. */
+    uint32_t u32Size;
+    /** The structure version. (VMMDEV_MEMORY_VERSION) */
+    uint32_t u32Version;
+
+    union
+    {
+        struct
+        {
+            /** Flag telling that VMMDev set the IRQ and acknowlegment is required */
+            bool fHaveEvents;
+        } V1_04;
+
+        struct
+        {
+            /** Pending events flags, set by host. */
+            uint32_t u32HostEvents;
+            /** Mask of events the guest wants to see, set by guest. */
+            uint32_t u32GuestEventMask;
+        } V1_03;
+    } V;
+
+    VBVAMEMORY vbvaMemory;
+
+} VMMDevMemory;
+AssertCompileSize(VMMDevMemory, 8+8 + (12 + (_4M-_1K) + 4*64 + 12) );
+AssertCompileMemberOffset(VMMDevMemory, vbvaMemory, 16);
+
+/** Version of VMMDevMemory structure (VMMDevMemory::u32Version). */
+#define VMMDEV_MEMORY_VERSION   (1)
+
+/** @} */
+
+RT_C_DECLS_END
+#pragma pack()
+
+#endif
+
diff --git a/ubuntu/vbox/include/VBox/VMMDev2.h b/ubuntu/vbox/include/VBox/VMMDev2.h
new file mode 100644 (file)
index 0000000..0732d5a
--- /dev/null
@@ -0,0 +1,122 @@
+/** @file
+ * Virtual Device for Guest <-> VMM/Host communication, Mixed Up Mess. (ADD,DEV)
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBox_VMMDev2_h
+#define ___VBox_VMMDev2_h
+
+#include <iprt/assert.h>
+
+
+/** @addtogroup grp_vmmdev
+ * @{
+ */
+
+
+/**
+ * Seamless mode.
+ *
+ * Used by VbglR3SeamlessWaitEvent
+ *
+ * @ingroup grp_vmmdev_req
+ *
+ * @todo DARN! DARN! DARN! Who forgot to do the 32-bit hack here???
+ *       FIXME! XXX!
+ *
+ *       We will now have to carefully check how our compilers have treated this
+ *       flag. If any are compressing it into a byte type, we'll have to check
+ *       how the request memory is initialized. If we are 104% sure it's ok to
+ *       expand it, we'll expand it. If not, we must redefine the field to a
+ *       uint8_t and a 3 byte padding.
+ */
+typedef enum
+{
+    VMMDev_Seamless_Disabled         = 0,     /**< normal mode; entire guest desktop displayed. */
+    VMMDev_Seamless_Visible_Region   = 1,     /**< visible region mode; only top-level guest windows displayed. */
+    VMMDev_Seamless_Host_Window      = 2      /**< windowed mode; each top-level guest window is represented in a host window. */
+} VMMDevSeamlessMode;
+
+/**
+ * CPU event types.
+ *
+ * Used by VbglR3CpuHotplugWaitForEvent
+ *
+ * @ingroup grp_vmmdev_req
+ */
+typedef enum
+{
+    VMMDevCpuEventType_Invalid  = 0,
+    VMMDevCpuEventType_None     = 1,
+    VMMDevCpuEventType_Plug     = 2,
+    VMMDevCpuEventType_Unplug   = 3,
+    VMMDevCpuEventType_SizeHack = 0x7fffffff
+} VMMDevCpuEventType;
+
+/**
+ * HGCM service location types.
+ * @ingroup grp_vmmdev_req
+ */
+typedef enum
+{
+    VMMDevHGCMLoc_Invalid    = 0,
+    VMMDevHGCMLoc_LocalHost  = 1,
+    VMMDevHGCMLoc_LocalHost_Existing = 2,
+    VMMDevHGCMLoc_SizeHack   = 0x7fffffff
+} HGCMServiceLocationType;
+AssertCompileSize(HGCMServiceLocationType, 4);
+
+/**
+ * HGCM host service location.
+ * @ingroup grp_vmmdev_req
+ */
+typedef struct
+{
+    char achName[128]; /**< This is really szName. */
+} HGCMServiceLocationHost;
+AssertCompileSize(HGCMServiceLocationHost, 128);
+
+/**
+ * HGCM service location.
+ * @ingroup grp_vmmdev_req
+ */
+typedef struct HGCMSERVICELOCATION
+{
+    /** Type of the location. */
+    HGCMServiceLocationType type;
+
+    union
+    {
+        HGCMServiceLocationHost host;
+    } u;
+} HGCMServiceLocation;
+AssertCompileSize(HGCMServiceLocation, 128+4);
+
+/* forward declarations: */
+struct VMMDevReqMousePointer;
+struct VMMDevMemory;
+
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/VBox/cdefs.h b/ubuntu/vbox/include/VBox/cdefs.h
new file mode 100644 (file)
index 0000000..36a4a72
--- /dev/null
@@ -0,0 +1,461 @@
+/** @file
+ * VirtualBox - Common C and C++ definition.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBox_cdefs_h
+#define ___VBox_cdefs_h
+
+#include <iprt/cdefs.h>
+
+
+/** @defgroup VBox Common Defintions and Macros
+ * @{
+ */
+
+/** @def VBOX_WITH_STATISTICS
+ * When defined all statistics will be included in the build.
+ * This is enabled by default in all debug builds.
+ */
+#ifndef VBOX_WITH_STATISTICS
+# ifdef DEBUG
+#  define VBOX_WITH_STATISTICS
+# endif
+#endif
+
+/** @def VBOX_STRICT
+ * Alias for RT_STRICT.
+ */
+#ifdef RT_STRICT
+# ifndef VBOX_STRICT
+#  define VBOX_STRICT
+# endif
+#endif
+
+
+/*
+ * Shut up DOXYGEN warnings and guide it properly thru the code.
+ */
+#ifdef DOXYGEN_RUNNING
+#define VBOX_WITH_STATISTICS
+#define VBOX_STRICT
+#define IN_DBG
+#define IN_DIS
+#define IN_INTNET_R0
+#define IN_INTNET_R3
+#define IN_PCIRAW_R0
+#define IN_PCIRAW_R3
+#define IN_REM_R3
+#define IN_SUP_R0
+#define IN_SUP_R3
+#define IN_SUP_RC
+#define IN_SUP_STATIC
+#define IN_USBLIB
+#define IN_VBOXDDU
+#define IN_VMM_RC
+#define IN_VMM_R0
+#define IN_VMM_R3
+#define IN_VMM_STATIC
+#endif
+
+
+
+
+/** @def VBOXCALL
+ * The standard calling convention for VBOX interfaces.
+ */
+#define VBOXCALL   RTCALL
+
+
+
+/** @def IN_DIS
+ * Used to indicate whether we're inside the same link module as the
+ * disassembler.
+ */
+/** @def DISDECL(type)
+ * Disassembly export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#if defined(IN_DIS)
+# ifdef IN_DIS_STATIC
+#  define DISDECL(type)     DECLHIDDEN(type) VBOXCALL
+# else
+#  define DISDECL(type)     DECLEXPORT(type) VBOXCALL
+# endif
+#else
+# define DISDECL(type)      DECLIMPORT(type) VBOXCALL
+#endif
+
+
+
+/** @def IN_DBG
+ * Used to indicate whether we're inside the same link module as the debugger
+ * console, gui, and related things (ring-3).
+ */
+/** @def DBGDECL(type)
+ * Debugger module export or import declaration.
+ * Functions declared using this exists only in R3 since the
+ * debugger modules is R3 only.
+ * @param   type    The return type of the function declaration.
+ */
+#if defined(IN_DBG_R3) || defined(IN_DBG)
+# define DBGDECL(type)      DECLEXPORT(type) VBOXCALL
+#else
+# define DBGDECL(type)      DECLIMPORT(type) VBOXCALL
+#endif
+
+
+
+/** @def IN_INTNET_R3
+ * Used to indicate whether we're inside the same link module as the Ring-3
+ * Internal Networking Service.
+ */
+/** @def INTNETR3DECL(type)
+ * Internal Networking Service export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_INTNET_R3
+# define INTNETR3DECL(type) DECLEXPORT(type) VBOXCALL
+#else
+# define INTNETR3DECL(type) DECLIMPORT(type) VBOXCALL
+#endif
+
+/** @def IN_INTNET_R0
+ * Used to indicate whether we're inside the same link module as the R0
+ * Internal Network Service.
+ */
+/** @def INTNETR0DECL(type)
+ * Internal Networking Service export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_INTNET_R0
+# define INTNETR0DECL(type) DECLEXPORT(type) VBOXCALL
+#else
+# define INTNETR0DECL(type) DECLIMPORT(type) VBOXCALL
+#endif
+
+
+
+/** @def IN_PCIRAW_R3
+ * Used to indicate whether we're inside the same link module as the Ring-3
+ * PCI passthrough support.
+ */
+/** @def PCIRAWR3DECL(type)
+ * PCI passthrough export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_PCIRAW_R3
+# define PCIRAWR3DECL(type) DECLEXPORT(type) VBOXCALL
+#else
+# define PCIRAWR3DECL(type) DECLIMPORT(type) VBOXCALL
+#endif
+
+/** @def IN_PCIRAW_R0
+ * Used to indicate whether we're inside the same link module as the R0
+ * PCI passthrough support.
+ */
+/** @def PCIRAWR0DECL(type)
+ * PCI passthroug export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_PCIRAW_R0
+# define PCIRAWR0DECL(type) DECLEXPORT(type) VBOXCALL
+#else
+# define PCIRAWR0DECL(type) DECLIMPORT(type) VBOXCALL
+#endif
+
+
+
+/** @def IN_REM_R3
+ * Used to indicate whether we're inside the same link module as
+ * the HC Ring-3 Recompiled Execution Manager.
+ */
+/** @def REMR3DECL(type)
+ * Recompiled Execution Manager HC Ring-3 export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_REM_R3
+# define REMR3DECL(type)    DECLEXPORT(type) VBOXCALL
+#else
+# define REMR3DECL(type)    DECLIMPORT(type) VBOXCALL
+#endif
+
+
+
+/** @def IN_SUP_R3
+ * Used to indicate whether we're inside the same link module as the Ring-3
+ * Support Library or not.
+ */
+/** @def SUPR3DECL(type)
+ * Support library export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_SUP_R3
+# ifdef IN_SUP_STATIC
+#  define SUPR3DECL(type)   DECLHIDDEN(type) VBOXCALL
+# else
+#  define SUPR3DECL(type)   DECLEXPORT(type) VBOXCALL
+# endif
+#else
+# ifdef IN_SUP_STATIC
+#  define SUPR3DECL(type)   DECLHIDDEN(type) VBOXCALL
+# else
+#  define SUPR3DECL(type)   DECLIMPORT(type) VBOXCALL
+# endif
+#endif
+
+/** @def IN_SUP_R0
+ * Used to indicate whether we're inside the same link module as the Ring-0
+ * Support Library or not.
+ */
+/** @def IN_SUP_STATIC
+ * Used to indicate that the Support Library is built or used as a static
+ * library.
+ */
+/** @def SUPR0DECL(type)
+ * Support library export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_SUP_R0
+# ifdef IN_SUP_STATIC
+#  define SUPR0DECL(type)   DECLHIDDEN(type) VBOXCALL
+# else
+#  define SUPR0DECL(type)   DECLEXPORT(type) VBOXCALL
+# endif
+#else
+# ifdef IN_SUP_STATIC
+#  define SUPR0DECL(type)   DECLHIDDEN(type) VBOXCALL
+# else
+#  define SUPR0DECL(type)   DECLIMPORT(type) VBOXCALL
+# endif
+#endif
+
+/** @def IN_SUP_RC
+ * Used to indicate whether we're inside the same link module as the RC Support
+ * Library or not.
+ */
+/** @def SUPRCDECL(type)
+ * Support library export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_SUP_RC
+# define SUPRCDECL(type)    DECLEXPORT(type) VBOXCALL
+#else
+# define SUPRCDECL(type)    DECLIMPORT(type) VBOXCALL
+#endif
+
+/** @def IN_SUP_R0
+ * Used to indicate whether we're inside the same link module as the Ring-0
+ * Support Library or not.
+ */
+/** @def SUPR0DECL(type)
+ * Support library export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#if defined(IN_SUP_R0) || defined(IN_SUP_R3) || defined(IN_SUP_RC)
+# define SUPDECL(type)      DECLEXPORT(type) VBOXCALL
+#else
+# define SUPDECL(type)      DECLIMPORT(type) VBOXCALL
+#endif
+
+
+
+/** @def IN_USBLIB
+ * Used to indicate whether we're inside the same link module as the USBLib.
+ */
+/** @def USBLIB_DECL
+ * USBLIB export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_RING0
+# define USBLIB_DECL(type)   type VBOXCALL
+#elif defined(IN_USBLIB)
+# define USBLIB_DECL(type)   DECLEXPORT(type) VBOXCALL
+#else
+# define USBLIB_DECL(type)   DECLIMPORT(type) VBOXCALL
+#endif
+
+
+
+/** @def IN_VMM_STATIC
+ * Used to indicate that the virtual machine monitor is built or used as a
+ * static library.
+ */
+/** @def IN_VMM_R3
+ * Used to indicate whether we're inside the same link module as the ring 3 part of the
+ * virtual machine monitor or not.
+ */
+/** @def VMMR3DECL
+ * Ring-3 VMM export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_VMM_R3
+# ifdef IN_VMM_STATIC
+#  define VMMR3DECL(type)           DECLHIDDEN(type) VBOXCALL
+# else
+#  define VMMR3DECL(type)           DECLEXPORT(type) VBOXCALL
+# endif
+#elif defined(IN_RING3)
+# ifdef IN_VMM_STATIC
+#  define VMMR3DECL(type)           DECLHIDDEN(type) VBOXCALL
+# else
+#  define VMMR3DECL(type)           DECLIMPORT(type) VBOXCALL
+# endif
+#else
+# define VMMR3DECL(type)            DECL_INVALID(type)
+#endif
+
+/** @def IN_VMM_R0
+ * Used to indicate whether we're inside the same link module as the ring-0 part
+ * of the virtual machine monitor or not.
+ */
+/** @def VMMR0DECL
+ * Ring-0 VMM export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_VMM_R0
+# define VMMR0DECL(type)            DECLEXPORT(type) VBOXCALL
+#elif defined(IN_RING0)
+# define VMMR0DECL(type)            DECLIMPORT(type) VBOXCALL
+#else
+# define VMMR0DECL(type)            DECL_INVALID(type)
+#endif
+
+/** @def IN_VMM_RC
+ * Used to indicate whether we're inside the same link module as the raw-mode
+ * context part of the virtual machine monitor or not.
+ */
+/** @def VMMRCDECL
+ * Raw-mode context VMM export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_VMM_RC
+# define VMMRCDECL(type)            DECLEXPORT(type) VBOXCALL
+#elif defined(IN_RC)
+# define VMMRCDECL(type)            DECLIMPORT(type) VBOXCALL
+#else
+# define VMMRCDECL(type)            DECL_INVALID(type)
+#endif
+
+/** @def VMMRZDECL
+ * Ring-0 and Raw-mode context VMM export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#if defined(IN_VMM_R0) || defined(IN_VMM_RC)
+# define VMMRZDECL(type)            DECLEXPORT(type) VBOXCALL
+#elif defined(IN_RING0) || defined(IN_RZ)
+# define VMMRZDECL(type)            DECLIMPORT(type) VBOXCALL
+#else
+# define VMMRZDECL(type)            DECL_INVALID(type)
+#endif
+
+/** @def VMMDECL
+ * VMM export or import declaration.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_VMM_STATIC
+# define VMMDECL(type)              DECLHIDDEN(type) VBOXCALL
+#elif defined(IN_VMM_R3) || defined(IN_VMM_R0) || defined(IN_VMM_RC)
+# define VMMDECL(type)              DECLEXPORT(type) VBOXCALL
+#else
+# define VMMDECL(type)              DECLIMPORT(type) VBOXCALL
+#endif
+
+/** @def VMM_INT_DECL
+ * VMM internal function.
+ * @param   type    The return type of the function declaration.
+ */
+#if defined(IN_VMM_R3) || defined(IN_VMM_R0) || defined(IN_VMM_RC)
+# define VMM_INT_DECL(type)         DECLHIDDEN(type) VBOXCALL
+#else
+# define VMM_INT_DECL(type)         DECL_INVALID(type)
+#endif
+
+/** @def VMMR3_INT_DECL
+ * VMM internal function, ring-3.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_VMM_R3
+# define VMMR3_INT_DECL(type)       DECLHIDDEN(type) VBOXCALL
+#else
+# define VMMR3_INT_DECL(type)       DECL_INVALID(type)
+#endif
+
+/** @def VMMR0_INT_DECL
+ * VMM internal function, ring-0.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_VMM_R0
+# define VMMR0_INT_DECL(type)       DECLHIDDEN(type) VBOXCALL
+#else
+# define VMMR0_INT_DECL(type)       DECL_INVALID(type)
+#endif
+
+/** @def VMMRC_INT_DECL
+ * VMM internal function, raw-mode context.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_VMM_RC
+# define VMMRC_INT_DECL(type)       DECLHIDDEN(type) VBOXCALL
+#else
+# define VMMRC_INT_DECL(type)       DECL_INVALID(type)
+#endif
+
+/** @def VMMRZ_INT_DECL
+ * VMM internal function, ring-0 + raw-mode context.
+ * @param   type    The return type of the function declaration.
+ */
+#if defined(IN_VMM_RC) || defined(IN_VMM_R0)
+# define VMMRZ_INT_DECL(type)       DECLHIDDEN(type) VBOXCALL
+#else
+# define VMMRZ_INT_DECL(type)       DECL_INVALID(type)
+#endif
+
+
+
+/** @def IN_VBOXDDU
+ * Used to indicate whether we're inside the VBoxDDU shared object.
+ */
+/** @def VBOXDDU_DECL(type)
+ * VBoxDDU export or import (ring-3).
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef IN_VBOXDDU
+# ifdef IN_VBOXDDU_STATIC
+#  define VBOXDDU_DECL(type) type
+# else
+#  define VBOXDDU_DECL(type) DECLEXPORT(type) VBOXCALL
+# endif
+#else
+# define VBOXDDU_DECL(type) DECLIMPORT(type) VBOXCALL
+#endif
+
+/** @} */
+
+
+/** @defgroup grp_devdrv    Device Emulations and Drivers
+ * @{ */
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/VBox/err.h b/ubuntu/vbox/include/VBox/err.h
new file mode 100644 (file)
index 0000000..48e86c4
--- /dev/null
@@ -0,0 +1,2801 @@
+/** @file
+ * VirtualBox Status Codes.
+ */
+
+/*
+ * Copyright (C) 2006-2017 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.
+ */
+
+#ifndef ___VBox_err_h
+#define ___VBox_err_h
+
+#include <VBox/cdefs.h>
+#include <iprt/err.h>
+
+
+/** @defgroup grp_err       VBox Error Codes
+ * @{
+ */
+
+/* SED-START */
+
+/** @name Misc. Status Codes
+ * @{
+ */
+/** Failed to allocate VM memory. */
+#define VERR_NO_VM_MEMORY                   (-1000)
+/** RC is toasted and the VMM should be terminated at once, but no need to
+ * panic about it :-) */
+#define VERR_DONT_PANIC                     (-1001)
+/** Unsupported CPU. */
+#define VERR_UNSUPPORTED_CPU                (-1002)
+/** Unsupported CPU mode. */
+#define VERR_UNSUPPORTED_CPU_MODE           (-1003)
+/** Page not present. */
+#define VERR_PAGE_NOT_PRESENT               (-1004)
+/** Invalid/Corrupted configuration file. */
+#define VERR_CFG_INVALID_FORMAT             (-1005)
+/** No configuration value exists. */
+#define VERR_CFG_NO_VALUE                   (-1006)
+/** Selector not present. */
+#define VERR_SELECTOR_NOT_PRESENT           (-1007)
+/** Not code selector. */
+#define VERR_NOT_CODE_SELECTOR              (-1008)
+/** Not data selector. */
+#define VERR_NOT_DATA_SELECTOR              (-1009)
+/** Out of selector bounds. */
+#define VERR_OUT_OF_SELECTOR_BOUNDS         (-1010)
+/** Invalid selector. Usually beyond table limits. */
+#define VERR_INVALID_SELECTOR               (-1011)
+/** Invalid requested privilege level. */
+#define VERR_INVALID_RPL                    (-1012)
+/** PML4 entry not present. */
+#define VERR_PAGE_MAP_LEVEL4_NOT_PRESENT    (-1013)
+/** Page directory pointer not present. */
+#define VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT (-1014)
+/** Raw mode doesn't support SMP. */
+#define VERR_RAW_MODE_INVALID_SMP           (-1015)
+/** Invalid VM handle. */
+#define VERR_INVALID_VM_HANDLE              (-1016)
+/** Invalid VM handle. */
+#define VERR_INVALID_VMCPU_HANDLE           (-1017)
+/** Invalid Virtual CPU ID. */
+#define VERR_INVALID_CPU_ID                 (-1018)
+/** Too many VCPUs. */
+#define VERR_TOO_MANY_CPUS                  (-1019)
+/** The service was disabled on the host.
+ * Returned by pfnInit in VBoxService to indicated a non-fatal error that
+ * should results in the particular service being disabled. */
+#define VERR_SERVICE_DISABLED               (-1020)
+/** The requested feature is not supported in raw-mode. */
+#define VERR_NOT_SUP_IN_RAW_MODE            (-1021)
+/** Invalid CPU index. */
+#define VERR_INVALID_CPU_INDEX              (-1022)
+/** This VirtualBox build does not support raw-mode. */
+#define VERR_RAW_MODE_NOT_SUPPORTED         (-1023)
+/** @} */
+
+
+/** @name Execution Monitor/Manager (EM) Status Codes
+ *
+ * The order of the status codes between VINF_EM_FIRST and VINF_EM_LAST
+ * are of vital importance. The lower the number the higher importance
+ * as a scheduling instruction.
+ * @{
+ */
+/** First scheduling related status code. */
+#define VINF_EM_FIRST                       1100
+/** Indicating that the VM is being terminated and that the execution
+ * shall stop. */
+#define VINF_EM_TERMINATE                   1100
+/** Hypervisor code was stepped.
+ * EM will first send this to the debugger, and if the issue isn't
+ * resolved there it will enter guru meditation. */
+#define VINF_EM_DBG_HYPER_STEPPED           1101
+/** Hit a breakpoint in the hypervisor code,
+ * EM will first send this to the debugger, and if the issue isn't
+ * resolved there it will enter guru meditation. */
+#define VINF_EM_DBG_HYPER_BREAKPOINT        1102
+/** Hit a possible assertion in the hypervisor code,
+ * EM will first send this to the debugger, and if the issue isn't
+ * resolved there it will enter guru meditation. */
+#define VINF_EM_DBG_HYPER_ASSERTION         1103
+/** Generic debug event, suspend the VM for debugging. */
+#define VINF_EM_DBG_EVENT                   1104
+/** Indicating that the VM should be suspended for debugging because
+ * the developer wants to inspect the VM state. */
+#define VINF_EM_DBG_STOP                    1105
+/** Indicating success single stepping and that EM should report that
+ * event to the debugger. */
+#define VINF_EM_DBG_STEPPED                 1106
+/** Indicating that a breakpoint was hit and that EM should notify the debugger
+ * and in the event there is no debugger fail fatally. */
+#define VINF_EM_DBG_BREAKPOINT              1107
+/** Indicating that EM should single step an instruction.
+ * The instruction is stepped in the current execution mode (RAW/REM). */
+#define VINF_EM_DBG_STEP                    1108
+/** Indicating that the VM is being turned off and that the EM should
+ * exit to the VM awaiting the destruction request. */
+#define VINF_EM_OFF                         1109
+/** Indicating that the VM has been suspended and that the thread
+ * should wait for request telling it what to do next. */
+#define VINF_EM_SUSPEND                     1110
+/** Indicating that the VM has been reset and that scheduling goes
+ * back to startup defaults. */
+#define VINF_EM_RESET                       1111
+/** Indicating that the VM has executed a halt instruction and that
+ * the emulation thread should wait for an interrupt before resuming
+ * execution. */
+#define VINF_EM_HALT                        1112
+/** Indicating that the VM has been resumed and that the thread should
+ * start executing. */
+#define VINF_EM_RESUME                      1113
+/** Indicating that we've got an out-of-memory condition and that we need
+ * to take the appropriate actions to deal with this.
+ * @remarks It might seem odd at first that this has lower priority than VINF_EM_HALT,
+ *          VINF_EM_SUSPEND, and VINF_EM_RESUME. The reason is that these events are
+ *          vital to correctly operating the VM. Also, they can't normally occur together
+ *          with an out-of-memory condition, and even if that should happen the condition
+ *          will be rediscovered before executing any more code. */
+#define VINF_EM_NO_MEMORY                   1114
+/** The fatal variant of VINF_EM_NO_MEMORY. */
+#define VERR_EM_NO_MEMORY                   (-1114)
+/** Indicating that a rescheduling to recompiled execution.
+ * Typically caused by raw-mode executing code which is difficult/slow
+ * to virtualize rawly.
+ * @remarks Important to have a higher priority (lower number) than the other rescheduling status codes. */
+#define VINF_EM_RESCHEDULE_REM              1115
+/** Indicating that a rescheduling to vmx-mode execution.
+ * Typically caused by REM detecting that hardware-accelerated raw-mode execution is possible. */
+#define VINF_EM_RESCHEDULE_HM            1116
+/** Indicating that a rescheduling to raw-mode execution.
+ * Typically caused by REM detecting that raw-mode execution is possible.
+ * @remarks Important to have a higher priority (lower number) than VINF_EM_RESCHEDULE. */
+#define VINF_EM_RESCHEDULE_RAW              1117
+/** Indicating that a rescheduling now is required. Typically caused by
+ * interrupts having changed the EIP. */
+#define VINF_EM_RESCHEDULE                  1118
+/** PARAV call */
+#define VINF_EM_RESCHEDULE_PARAV            1119
+/** Go back into wait for SIPI mode */
+#define VINF_EM_WAIT_SIPI                   1120
+/** Last scheduling related status code. (inclusive) */
+#define VINF_EM_LAST                        1120
+
+/** Reason for leaving RC: Guest trap which couldn't be handled in RC.
+ * The trap is generally forwarded to the REM and executed there. */
+#define VINF_EM_RAW_GUEST_TRAP              1121
+/** Reason for leaving RC: Interrupted by external interrupt.
+ * The interrupt needed to be handled by the host OS. */
+#define VINF_EM_RAW_INTERRUPT               1122
+/** Reason for leaving RC: Interrupted by external interrupt while in hypervisor
+ * code. The interrupt needed to be handled by the host OS and hypervisor
+ * execution must be resumed. VM state is not complete at this point. */
+#define VINF_EM_RAW_INTERRUPT_HYPER         1123
+/** Reason for leaving RC: A Ring switch was attempted.
+ * Normal cause of action is to execute this in REM. */
+#define VINF_EM_RAW_RING_SWITCH             1124
+/** Reason for leaving RC: A Ring switch was attempted using software interrupt.
+ * Normal cause of action is to execute this in REM. */
+#define VINF_EM_RAW_RING_SWITCH_INT         1125
+/** Reason for leaving RC: A privileged instruction was attempted executed.
+ * Normal cause of action is to execute this in REM. */
+#define VINF_EM_RAW_EXCEPTION_PRIVILEGED    1126
+
+/** Reason for leaving RZ: Emulate instruction. */
+#define VINF_EM_RAW_EMULATE_INSTR           1127
+/** Reason for leaving RC: Unhandled TSS write.
+ * Recompiler gets control. */
+#define VINF_EM_RAW_EMULATE_INSTR_TSS_FAULT 1128
+/** Reason for leaving RC: Unhandled LDT write.
+ * Recompiler gets control. */
+#define VINF_EM_RAW_EMULATE_INSTR_LDT_FAULT 1129
+/** Reason for leaving RC: Unhandled IDT write.
+ * Recompiler gets control. */
+#define VINF_EM_RAW_EMULATE_INSTR_IDT_FAULT 1130
+/** Reason for leaving RC: Partly handled GDT write.
+ * Recompiler gets control. */
+#define VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT 1131
+/** Reason for leaving RC: jump inside generated patch jump.
+ * Fatal error. */
+#define VERR_EM_RAW_PATCH_CONFLICT          (-1133)
+/** Reason for leaving RZ: Ring-3 operation pending. */
+#define VINF_EM_RAW_TO_R3                   1135
+/** Reason for leaving RZ: Timer pending. */
+#define VINF_EM_RAW_TIMER_PENDING           1136
+/** Reason for leaving RC: Interrupt pending (guest). */
+#define VINF_EM_RAW_INTERRUPT_PENDING       1137
+/** Reason for leaving RC: Encountered a stale selector. */
+#define VINF_EM_RAW_STALE_SELECTOR          1138
+/** Reason for leaving RC: The IRET resuming guest code trapped. */
+#define VINF_EM_RAW_IRET_TRAP               1139
+/** Reason for leaving RC: Emulate (MM)IO intensive code in the recompiler. */
+#define VINF_EM_RAW_EMULATE_IO_BLOCK        1140
+/** The interpreter was unable to deal with the instruction at hand. */
+#define VERR_EM_INTERPRETER                 (-1148)
+/** Internal EM error caused by an unknown warning or informational status code. */
+#define VERR_EM_INTERNAL_ERROR              (-1149)
+/** Pending VM request packet. */
+#define VINF_EM_PENDING_REQUEST             1150
+/** Start instruction stepping (debug only). */
+#define VINF_EM_RAW_EMULATE_DBG_STEP        1151
+/** Patch TPR access instruction. */
+#define VINF_EM_HM_PATCH_TPR_INSTR          1152
+/** Unexpected guest mapping conflict detected. */
+#define VERR_EM_UNEXPECTED_MAPPING_CONFLICT (-1154)
+/** Reason for leaving RC: A triple-fault condition. Currently, causes
+ *  a guru meditation. */
+#define VINF_EM_TRIPLE_FAULT                1155
+/** The specified execution engine cannot execute guest code in the current
+ *  state. */
+#define VERR_EM_CANNOT_EXEC_GUEST           (-1156)
+/** Reason for leaving RC: Inject a TRPM event. */
+#define VINF_EM_RAW_INJECT_TRPM_EVENT       1157
+/** Guest tried to trigger a CPU hang.  The guest is probably up to no good. */
+#define VERR_EM_GUEST_CPU_HANG              (-1158)
+/** @} */
+
+
+/** @name Debugging Facility (DBGF) DBGF Status Codes
+ * @{
+ */
+/** The function called requires the caller to be attached as a
+ * debugger to the VM. */
+#define VERR_DBGF_NOT_ATTACHED              (-1200)
+/** Someone (including the caller) was already attached as
+ * debugger to the VM. */
+#define VERR_DBGF_ALREADY_ATTACHED          (-1201)
+/** Tried to halt a debugger which was already halted.
+ * (This is a warning and not an error.) */
+#define VWRN_DBGF_ALREADY_HALTED            1202
+/** The DBGF has no more free breakpoint slots. */
+#define VERR_DBGF_NO_MORE_BP_SLOTS          (-1203)
+/** The DBGF couldn't find the specified breakpoint. */
+#define VERR_DBGF_BP_NOT_FOUND              (-1204)
+/** Attempted to enabled a breakpoint which was already enabled. */
+#define VINF_DBGF_BP_ALREADY_ENABLED        1205
+/** Attempted to disabled a breakpoint which was already disabled. */
+#define VINF_DBGF_BP_ALREADY_DISABLED       1206
+/** The breakpoint already exists. */
+#define VINF_DBGF_BP_ALREADY_EXIST          1207
+/** The byte string was not found. */
+#define VERR_DBGF_MEM_NOT_FOUND             (-1208)
+/** The OS was not detected. */
+#define VERR_DBGF_OS_NOT_DETCTED            (-1209)
+/** The OS was not detected. */
+#define VINF_DBGF_OS_NOT_DETCTED            1209
+/** The specified register was not found. */
+#define VERR_DBGF_REGISTER_NOT_FOUND        (-1210)
+/** The value was truncated to fit.
+ * For queries this means that the register is wider than the queried value.
+ * For setters this means that the value is wider than the register. */
+#define VINF_DBGF_TRUNCATED_REGISTER        1211
+/** The value was zero extended to fit.
+ * For queries this means that the register is narrower than the queried value.
+ * For setters this means that the value is narrower than the register. */
+#define VINF_DBGF_ZERO_EXTENDED_REGISTER    1212
+/** The requested type conversion was not supported. */
+#define VERR_DBGF_UNSUPPORTED_CAST          (-1213)
+/** The register is read-only and cannot be modified. */
+#define VERR_DBGF_READ_ONLY_REGISTER        (-1214)
+/** Internal processing error \#1 in the DBGF register code. */
+#define VERR_DBGF_REG_IPE_1                 (-1215)
+/** Internal processing error \#2 in the DBGF register code. */
+#define VERR_DBGF_REG_IPE_2                 (-1216)
+/** Unhandled \#DB in hypervisor code. */
+#define VERR_DBGF_HYPER_DB_XCPT             (-1217)
+/** Internal processing error \#1 in the DBGF stack code. */
+#define VERR_DBGF_STACK_IPE_1               (-1218)
+/** Internal processing error \#2 in the DBGF stack code. */
+#define VERR_DBGF_STACK_IPE_2               (-1219)
+/** No trace buffer available, please change the VM config. */
+#define VERR_DBGF_NO_TRACE_BUFFER           (-1220)
+/** @} */
+
+
+/** @name Patch Manager (PATM) Status Codes
+ * @{
+ */
+/** Non fatal Patch Manager analysis phase warning */
+#define VWRN_CONTINUE_ANALYSIS              1400
+/** Non fatal Patch Manager recompile phase warning (mapped to VWRN_CONTINUE_ANALYSIS). */
+#define VWRN_CONTINUE_RECOMPILE             VWRN_CONTINUE_ANALYSIS
+/** Continue search (mapped to VWRN_CONTINUE_ANALYSIS). */
+#define VWRN_PATM_CONTINUE_SEARCH           VWRN_CONTINUE_ANALYSIS
+/** Patch installation refused (patch too complex or unsupported instructions ) */
+#define VERR_PATCHING_REFUSED               (-1401)
+/** Unable to find patch */
+#define VERR_PATCH_NOT_FOUND                (-1402)
+/** Patch disabled */
+#define VERR_PATCH_DISABLED                 (-1403)
+/** Patch enabled */
+#define VWRN_PATCH_ENABLED                  1404
+/** Patch was already disabled */
+#define VERR_PATCH_ALREADY_DISABLED         (-1405)
+/** Patch was already enabled */
+#define VERR_PATCH_ALREADY_ENABLED          (-1406)
+/** Patch was removed. */
+#define VWRN_PATCH_REMOVED                  1407
+
+/** Reason for leaving RC: \#GP with EIP pointing to patch code. */
+#define VINF_PATM_PATCH_TRAP_GP             1408
+/** First leave RC code. */
+#define VINF_PATM_LEAVE_RC_FIRST             VINF_PATM_PATCH_TRAP_GP
+/** Reason for leaving RC: \#PF with EIP pointing to patch code. */
+#define VINF_PATM_PATCH_TRAP_PF             1409
+/** Reason for leaving RC: int3 with EIP pointing to patch code. */
+#define VINF_PATM_PATCH_INT3                1410
+/** Reason for leaving RC: \#PF for monitored patch page. */
+#define VINF_PATM_CHECK_PATCH_PAGE          1411
+/** Reason for leaving RC: duplicate instruction called at current eip. */
+#define VINF_PATM_DUPLICATE_FUNCTION        1412
+/** Execute one instruction with the recompiler */
+#define VINF_PATCH_EMULATE_INSTR            1413
+/** Reason for leaving RC: attempt to patch MMIO write. */
+#define VINF_PATM_HC_MMIO_PATCH_WRITE       1414
+/** Reason for leaving RC: attempt to patch MMIO read. */
+#define VINF_PATM_HC_MMIO_PATCH_READ        1415
+/** Reason for leaving RC: pending irq after iret that sets IF. */
+#define VINF_PATM_PENDING_IRQ_AFTER_IRET    1416
+/** Last leave RC code. */
+#define VINF_PATM_LEAVE_RC_LAST              VINF_PATM_PENDING_IRQ_AFTER_IRET
+
+/** No conflicts to resolve */
+#define VERR_PATCH_NO_CONFLICT              (-1425)
+/** Detected unsafe code for patching */
+#define VERR_PATM_UNSAFE_CODE               (-1426)
+/** Terminate search branch */
+#define VWRN_PATCH_END_BRANCH                1427
+/** Already patched */
+#define VERR_PATM_ALREADY_PATCHED           (-1428)
+/** Spinlock detection failed. */
+#define VINF_PATM_SPINLOCK_FAILED           (1429)
+/** Continue execution after patch trap. */
+#define VINF_PATCH_CONTINUE                 (1430)
+/** The patch manager is not used because we're using HM and VT-x/AMD-V. */
+#define VERR_PATM_HM_IPE                    (-1431)
+/** Unexpected trap in patch code. */
+#define VERR_PATM_IPE_TRAP_IN_PATCH_CODE    (-1432)
+
+/** @} */
+
+
+/** @name Code Scanning and Analysis Manager (CSAM) Status Codes
+ * @{
+ */
+/** Trap not handled */
+#define VWRN_CSAM_TRAP_NOT_HANDLED          1500
+/** Patch installed */
+#define VWRN_CSAM_INSTRUCTION_PATCHED       1501
+/** Page record not found */
+#define VWRN_CSAM_PAGE_NOT_FOUND            1502
+/** Reason for leaving RC: CSAM wants perform a task in ring-3. */
+#define VINF_CSAM_PENDING_ACTION            1503
+/** The CSAM is not used because we're using HM and VT-x/AMD-V. */
+#define VERR_CSAM_HM_IPE                    (-1504)
+/** @} */
+
+
+/** @name Page Monitor/Manager (PGM) Status Codes
+ * @{
+ */
+/** Attempt to create a GC mapping which conflicts with an existing mapping. */
+#define VERR_PGM_MAPPING_CONFLICT           (-1600)
+/** The physical handler range has no corresponding RAM range.
+ * If this is MMIO, see todo above the return. If not MMIO, then it's
+ * someone else's fault... */
+#define VERR_PGM_HANDLER_PHYSICAL_NO_RAM_RANGE (-1601)
+/** Attempt to register an access handler for a virtual range of which a part
+ * was already handled. */
+#define VERR_PGM_HANDLER_VIRTUAL_CONFLICT   (-1602)
+/** Attempt to register an access handler for a physical range of which a part
+ * was already handled. */
+#define VERR_PGM_HANDLER_PHYSICAL_CONFLICT  (-1603)
+/** Invalid page directory specified to PGM. */
+#define VERR_PGM_INVALID_PAGE_DIRECTORY     (-1604)
+/** Invalid GC physical address. */
+#define VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS (-1605)
+/** Invalid GC physical range. Usually used when a specified range crosses
+ * a RAM region boundary. */
+#define VERR_PGM_INVALID_GC_PHYSICAL_RANGE  (-1606)
+/** Specified access handler was not found. */
+#define VERR_PGM_HANDLER_NOT_FOUND          (-1607)
+/** Attempt to register a RAM range of which parts are already
+ * covered by existing RAM ranges. */
+#define VERR_PGM_RAM_CONFLICT               (-1608)
+/** Failed to add new mappings because the current mappings are fixed
+ * in guest os memory. */
+#define VERR_PGM_MAPPINGS_FIXED             (-1609)
+/** Failed to fix mappings because of a conflict with the intermediate code. */
+#define VERR_PGM_MAPPINGS_FIX_CONFLICT      (-1610)
+/** Failed to fix mappings because a mapping rejected the address. */
+#define VERR_PGM_MAPPINGS_FIX_REJECTED      (-1611)
+/** Failed to fix mappings because the proposed memory area was to small. */
+#define VERR_PGM_MAPPINGS_FIX_TOO_SMALL     (-1612)
+/** Reason for leaving RZ: The urge to syncing CR3. */
+#define VINF_PGM_SYNC_CR3                   1613
+/** Page not marked for dirty bit tracking */
+#define VINF_PGM_NO_DIRTY_BIT_TRACKING      1614
+/** Page fault caused by dirty bit tracking; corrected */
+#define VINF_PGM_HANDLED_DIRTY_BIT_FAULT    1615
+/** Go ahead with the default Read/Write operation.
+ * This is returned by a R3 physical or virtual handler when it wants the
+ * PGMPhys[Read|Write] routine do the reading/writing. */
+#define VINF_PGM_HANDLER_DO_DEFAULT         1616
+/** The paging mode of the host is not supported yet. */
+#define VERR_PGM_UNSUPPORTED_HOST_PAGING_MODE (-1617)
+/** The physical guest page is a reserved/MMIO page and does not have any HC
+ *  address. */
+#define VERR_PGM_PHYS_PAGE_RESERVED         (-1618)
+/** No page directory available for the hypervisor. */
+#define VERR_PGM_NO_HYPERVISOR_ADDRESS      (-1619)
+/** The shadow page pool was flushed.
+ * This means that a global CR3 sync was flagged. Anyone receiving this kind of status
+ * will have to get down to a SyncCR3 ASAP. See also VINF_PGM_SYNC_CR3. */
+#define VERR_PGM_POOL_FLUSHED               (-1620)
+/** The shadow page pool was cleared.
+ * This is a error code internal to the shadow page pool, it will be
+ * converted to a VERR_PGM_POOL_FLUSHED before leaving the pool code. */
+#define VERR_PGM_POOL_CLEARED               (-1621)
+/** The returned shadow page is cached. */
+#define VINF_PGM_CACHED_PAGE                1622
+/** Returned by handler registration, modification and deregistration
+ * when the shadow PTs could be updated because the guest page
+ * aliased or/and mapped by multiple PTs. */
+#define VINF_PGM_GCPHYS_ALIASED             1623
+/** Reason for leaving RC: Paging mode changed.
+ * PGMChangeMode() uses this to force a switch to R3 so it can safely deal with
+ * a mode switch. */
+#define VINF_PGM_CHANGE_MODE                1624
+/** SyncPage modified the PDE.
+ * This is an internal status code used to communicate back to the \#PF handler
+ * that the PDE was (probably) marked not-present and it should restart the instruction. */
+#define VINF_PGM_SYNCPAGE_MODIFIED_PDE      1625
+/** Physical range crosses dynamic ram chunk boundary; translation to HC ptr not safe. */
+#define VERR_PGM_GCPHYS_RANGE_CROSSES_BOUNDARY  (-1626)
+/** Conflict between the core memory and the intermediate paging context, try again.
+ * There are some very special conditions applying to the intermediate paging context
+ * (used during the world switches), and some times we continuously run into these
+ * when asking the host kernel for memory during VM init. Let us know if you run into
+ * this and we'll adjust the code so it tries harder to avoid it.
+ */
+#define VERR_PGM_INTERMEDIATE_PAGING_CONFLICT   (-1627)
+/** The shadow paging mode is not supported yet. */
+#define VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE (-1628)
+/** The dynamic mapping cache for physical memory failed. */
+#define VERR_PGM_DYNMAP_FAILED                  (-1629)
+/** The auto usage cache for the dynamic mapping set is full. */
+#define VERR_PGM_DYNMAP_FULL_SET                (-1630)
+/** The initialization of the dynamic mapping cache failed. */
+#define VERR_PGM_DYNMAP_SETUP_ERROR             (-1631)
+/** The expanding of the dynamic mapping cache failed. */
+#define VERR_PGM_DYNMAP_EXPAND_ERROR            (-1632)
+/** The page is unassigned (akin to VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS). */
+#define VERR_PGM_PHYS_TLB_UNASSIGNED            (-1633)
+/** Catch any access and route it thru PGM. */
+#define VERR_PGM_PHYS_TLB_CATCH_ALL             (-1634)
+/** Catch write access and route it thru PGM. */
+#define VINF_PGM_PHYS_TLB_CATCH_WRITE           1635
+/** Catch write access and route it thru PGM. */
+#define VERR_PGM_PHYS_TLB_CATCH_WRITE           (-1635)
+/** No CR3 root shadow page table. */
+#define VERR_PGM_NO_CR3_SHADOW_ROOT             (-1636)
+/** Trying to free a page with an invalid Page ID. */
+#define VERR_PGM_PHYS_INVALID_PAGE_ID           (-1637)
+/** PGMPhysWrite/Read hit a handler in Ring-0 or raw-mode context. */
+#define VERR_PGM_PHYS_WR_HIT_HANDLER            (-1638)
+/** Trying to free a page that isn't RAM. */
+#define VERR_PGM_PHYS_NOT_RAM                   (-1639)
+/** Not ROM page. */
+#define VERR_PGM_PHYS_NOT_ROM                   (-1640)
+/** Not MMIO page. */
+#define VERR_PGM_PHYS_NOT_MMIO                  (-1641)
+/** Not MMIO2 page. */
+#define VERR_PGM_PHYS_NOT_MMIO2                 (-1642)
+/** Already aliased to a different page. */
+#define VERR_PGM_HANDLER_ALREADY_ALIASED        (-1643)
+/** Already aliased to the same page. */
+#define VINF_PGM_HANDLER_ALREADY_ALIASED        (1643)
+/** PGM pool flush pending - return to ring 3. */
+#define VINF_PGM_POOL_FLUSH_PENDING             (1644)
+/** Unable to use the range for a large page. */
+#define VERR_PGM_INVALID_LARGE_PAGE_RANGE       (-1645)
+/** Don't mess around with ballooned pages. */
+#define VERR_PGM_PHYS_PAGE_BALLOONED            (-1646)
+/** Internal processing error \#1 in page access handler code. */
+#define VERR_PGM_HANDLER_IPE_1                  (-1647)
+
+
+/** pgmPhysPageMapCommon encountered PGMPAGETYPE_MMIO2_ALIAS_MMIO. */
+#define VERR_PGM_MAP_MMIO2_ALIAS_MMIO           (-1651)
+/** Guest mappings are disabled. */
+#define VERR_PGM_MAPPINGS_DISABLED              (-1652)
+/** No guest mappings when SMP is enabled. */
+#define VERR_PGM_MAPPINGS_SMP                   (-1653)
+/** Invalid saved page state. */
+#define VERR_PGM_INVALID_SAVED_PAGE_STATE       (-1654)
+/** Encountered an unexpected page type in the saved state. */
+#define VERR_PGM_LOAD_UNEXPECTED_PAGE_TYPE      (-1655)
+/** Encountered an unexpected page state in the saved state. */
+#define VERR_PGM_UNEXPECTED_PAGE_STATE          (-1656)
+/** Couldn't find MMIO2 range from saved state. */
+#define VERR_PGM_SAVED_MMIO2_RANGE_NOT_FOUND    (-1657)
+/** Couldn't find MMIO2 page from saved state. */
+#define VERR_PGM_SAVED_MMIO2_PAGE_NOT_FOUND     (-1658)
+/** Couldn't find ROM range from saved state. */
+#define VERR_PGM_SAVED_ROM_RANGE_NOT_FOUND      (-1659)
+/** Couldn't find ROM page from saved state. */
+#define VERR_PGM_SAVED_ROM_PAGE_NOT_FOUND       (-1660)
+/** ROM page mismatch between saved state and the VM. */
+#define VERR_PGM_SAVED_ROM_PAGE_PROT            (-1661)
+/** Unknown saved state record. */
+#define VERR_PGM_SAVED_REC_TYPE                 (-1662)
+/** Internal processing error in the PGM dynmap (r0/rc). */
+#define VERR_PGM_DYNMAP_IPE                     (-1663)
+/** Internal processing error in the PGM handy page allocator. */
+#define VERR_PGM_HANDY_PAGE_IPE                 (-1664)
+/** Failed to map the guest PML4. */
+#define VERR_PGM_PML4_MAPPING                   (-1665)
+/** Failed to obtain a pool page.  */
+#define VERR_PGM_POOL_GET_PAGE_FAILED           (-1666)
+/** A PGM function was called in a mode where it isn't supposed to be used. */
+#define VERR_PGM_NOT_USED_IN_MODE               (-1667)
+/** The CR3 address specified memory we don't know about. */
+#define VERR_PGM_INVALID_CR3_ADDR               (-1668)
+/** One or the PDPEs specified memory we don't know about. */
+#define VERR_PGM_INVALID_PDPE_ADDR              (-1669)
+/** Internal processing error in the PGM physical handler code. */
+#define VERR_PGM_PHYS_HANDLER_IPE               (-1670)
+/** Internal processing error \#1 in the PGM physial page mapping code. */
+#define VERR_PGM_PHYS_PAGE_MAP_IPE_1            (-1671)
+/** Internal processing error \#2 in the PGM physial page mapping code. */
+#define VERR_PGM_PHYS_PAGE_MAP_IPE_2            (-1672)
+/** Internal processing error \#3 in the PGM physial page mapping code. */
+#define VERR_PGM_PHYS_PAGE_MAP_IPE_3            (-1673)
+/** Internal processing error \#4 in the PGM physial page mapping code. */
+#define VERR_PGM_PHYS_PAGE_MAP_IPE_4            (-1674)
+/** Too many loops looking for a page to reuse. */
+#define VERR_PGM_POOL_TOO_MANY_LOOPS            (-1675)
+/** Internal processing error related to guest mappings. */
+#define VERR_PGM_MAPPING_IPE                    (-1676)
+/** An attempt was made to grow an already maxed out page pool. */
+#define VERR_PGM_POOL_MAXED_OUT_ALREADY         (-1677)
+/** Internal processing error in the page pool code. */
+#define VERR_PGM_POOL_IPE                       (-1678)
+/** The write monitor is already engaged. */
+#define VERR_PGM_WRITE_MONITOR_ENGAGED          (-1679)
+/** Failed to get a guest page which is expected to be present.  */
+#define VERR_PGM_PHYS_PAGE_GET_IPE              (-1680)
+/** We were given a NULL pPage parameter. */
+#define VERR_PGM_PHYS_NULL_PAGE_PARAM           (-1681)
+/** PCI passthru is not supported by this build. */
+#define VERR_PGM_PCI_PASSTHRU_MISCONFIG         (-1682)
+/** Too many MMIO2 ranges. */
+#define VERR_PGM_TOO_MANY_MMIO2_RANGES          (-1683)
+/** Internal processing error in the PGM physical page mapping code dealing
+ * with MMIO2 pages. */
+#define VERR_PGM_PHYS_PAGE_MAP_MMIO2_IPE        (-1684)
+/** Internal processing error in the PGM physcal page handling code related to
+ *  MMIO/MMIO2. */
+#define VERR_PGM_PHYS_MMIO_EX_IPE               (-1685)
+/** @} */
+
+
+/** @name Memory Monitor (MM) Status Codes
+ * @{
+ */
+/** Attempt to register a RAM range of which parts are already
+ * covered by existing RAM ranges. */
+#define VERR_MM_RAM_CONFLICT                    (-1700)
+/** Hypervisor memory allocation failed. */
+#define VERR_MM_HYPER_NO_MEMORY                 (-1701)
+/** A bad trap type ended up in mmGCRamTrap0eHandler. */
+#define VERR_MM_BAD_TRAP_TYPE_IPE               (-1702)
+/** @} */
+
+
+/** @name CPU Monitor (CPUM) Status Codes
+ * @{
+ */
+/** The caller shall raise an \#GP(0) exception. */
+#define VERR_CPUM_RAISE_GP_0                    (-1750)
+/** Incompatible CPUM configuration. */
+#define VERR_CPUM_INCOMPATIBLE_CONFIG           (-1751)
+/** CPUMR3DisasmInstrCPU unexpectedly failed to determine the hidden
+ * parts of the CS register. */
+#define VERR_CPUM_HIDDEN_CS_LOAD_ERROR          (-1752)
+/** Couldn't find the end of CPUID sub-leaves. */
+#define VERR_CPUM_TOO_MANY_CPUID_SUBLEAVES      (-1753)
+/** CPUM internal processing error \#1. */
+#define VERR_CPUM_IPE_1                         (-1754)
+/** CPUM internal processing error \#2. */
+#define VERR_CPUM_IPE_2                         (-1755)
+/** The specified CPU cannot be found in the CPU database. */
+#define VERR_CPUM_DB_CPU_NOT_FOUND              (-1756)
+/** Invalid CPUMCPU offset in MSR range. */
+#define VERR_CPUM_MSR_BAD_CPUMCPU_OFFSET        (-1757)
+/** Return to ring-3 to read the MSR there. */
+#define VINF_CPUM_R3_MSR_READ                   (1758)
+/** Return to ring-3 to write the MSR there. */
+#define VINF_CPUM_R3_MSR_WRITE                  (1759)
+/** Too many CPUID leaves. */
+#define VERR_TOO_MANY_CPUID_LEAVES              (-1760)
+/** Invalid config value. */
+#define VERR_CPUM_INVALID_CONFIG_VALUE          (-1761)
+/** The loaded XSAVE component mask is not compatible with the host CPU
+ * or/and VM config. */
+#define VERR_CPUM_INCOMPATIBLE_XSAVE_COMP_MASK  (-1762)
+/** The loaded XSAVE component mask is not valid. */
+#define VERR_CPUM_INVALID_XSAVE_COMP_MASK       (-1763)
+/** The loaded XSAVE header is not valid. */
+#define VERR_CPUM_INVALID_XSAVE_HDR             (-1764)
+/** The loaded XCR0 register value is not valid. */
+#define VERR_CPUM_INVALID_XCR0                  (-1765)
+/** Indicates that we modified the host CR0 (FPU related). */
+#define VINF_CPUM_HOST_CR0_MODIFIED             (1766)
+/** @} */
+
+
+/** @name Save State Manager (SSM) Status Codes
+ * @{
+ */
+/** The specified data unit already exist. */
+#define VERR_SSM_UNIT_EXISTS                    (-1800)
+/** The specified data unit wasn't found. */
+#define VERR_SSM_UNIT_NOT_FOUND                 (-1801)
+/** The specified data unit wasn't owned by caller. */
+#define VERR_SSM_UNIT_NOT_OWNER                 (-1802)
+
+/** General saved state file integrity error. */
+#define VERR_SSM_INTEGRITY                      (-1810)
+/** The saved state file magic was not recognized. */
+#define VERR_SSM_INTEGRITY_MAGIC                (-1811)
+/** The saved state file version is not supported. */
+#define VERR_SSM_INTEGRITY_VERSION              (-1812)
+/** The saved state file size didn't match the one in the header. */
+#define VERR_SSM_INTEGRITY_SIZE                 (-1813)
+/** The CRC of the saved state file did not match. */
+#define VERR_SSM_INTEGRITY_CRC                  (-1814)
+/** The machine uuid field wasn't null. */
+#define VERR_SMM_INTEGRITY_MACHINE              (-1815)
+/** Saved state header integrity error. */
+#define VERR_SSM_INTEGRITY_HEADER               (-1816)
+/** Unit header integrity error. */
+#define VERR_SSM_INTEGRITY_UNIT                 (-1817)
+/** Invalid unit magic (internal data tag). */
+#define VERR_SSM_INTEGRITY_UNIT_MAGIC           (-1818)
+/** The file contained a data unit which no-one wants. */
+#define VERR_SSM_INTEGRITY_UNIT_NOT_FOUND       (-1819)
+/** Incorrect version numbers in the header. */
+#define VERR_SSM_INTEGRITY_VBOX_VERSION         (-1820)
+/** Footer integrity error. */
+#define VERR_SSM_INTEGRITY_FOOTER               (-1821)
+/** Record header integrity error. */
+#define VERR_SSM_INTEGRITY_REC_HDR              (-1822)
+/** Termination record integrity error. */
+#define VERR_SSM_INTEGRITY_REC_TERM             (-1823)
+/** Termination record CRC mismatch. */
+#define VERR_SSM_INTEGRITY_REC_TERM_CRC         (-1824)
+/** Decompression integrity error.  */
+#define VERR_SSM_INTEGRITY_DECOMPRESSION        (-1825)
+/** Saved state directory wintertides error.  */
+#define VERR_SSM_INTEGRITY_DIR                  (-1826)
+/** The saved state directory magic is wrong. */
+#define VERR_SSM_INTEGRITY_DIR_MAGIC            (-1827)
+
+/** A data unit in the saved state file was defined but didn't any
+ * routine for processing it. */
+#define VERR_SSM_NO_LOAD_EXEC                   (-1830)
+/** A restore routine attempted to load more data then the unit contained. */
+#define VERR_SSM_LOADED_TOO_MUCH                (-1831)
+/** Not in the correct state for the attempted operation. */
+#define VERR_SSM_INVALID_STATE                  (-1832)
+/** Not in the correct state for the attempted operation. */
+#define VERR_SSM_LOADED_TOO_LITTLE              (-1833)
+
+/** Unsupported data unit version.
+ * A SSM user returns this if it doesn't know the u32Version. */
+#define VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION  (-1840)
+/** The format of a data unit has changed.
+ * A SSM user returns this if it's not able to read the format for
+ * other reasons than u32Version. */
+#define VERR_SSM_DATA_UNIT_FORMAT_CHANGED       (-1841)
+/** The CPUID instruction returns different information when loading than when saved.
+ * Normally caused by hardware changes on the host, but could also be caused by
+ * changes in the BIOS setup. */
+#define VERR_SSM_LOAD_CPUID_MISMATCH            (-1842)
+/** The RAM size differs between the saved state and the VM config. */
+#define VERR_SSM_LOAD_MEMORY_SIZE_MISMATCH      (-1843)
+/** The state doesn't match the VM configuration in one or another way.
+ * (There are certain PCI reconfiguration which the OS could potentially
+ * do which can cause this problem. Check this out when it happens.) */
+#define VERR_SSM_LOAD_CONFIG_MISMATCH           (-1844)
+/** The virtual clock frequency differs too much.
+ * The clock source for the virtual time isn't reliable or the code have changed. */
+#define VERR_SSM_VIRTUAL_CLOCK_HZ               (-1845)
+/** A timeout occurred while waiting for async IDE operations to finish. */
+#define VERR_SSM_IDE_ASYNC_TIMEOUT              (-1846)
+/** One of the structure magics was wrong. */
+#define VERR_SSM_STRUCTURE_MAGIC                (-1847)
+/** The data in the saved state doesn't conform to expectations. */
+#define VERR_SSM_UNEXPECTED_DATA                (-1848)
+/** Trying to read a 64-bit guest physical address into a 32-bit variable. */
+#define VERR_SSM_GCPHYS_OVERFLOW                (-1849)
+/** Trying to read a 64-bit guest virtual address into a 32-bit variable. */
+#define VERR_SSM_GCPTR_OVERFLOW                 (-1850)
+/** Vote for another pass.  */
+#define VINF_SSM_VOTE_FOR_ANOTHER_PASS          1851
+/** Vote for done tell SSM not to call again until the final pass. */
+#define VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN      1852
+/** Vote for giving up.  */
+#define VERR_SSM_VOTE_FOR_GIVING_UP             (-1853)
+/** Don't call again until the final pass. */
+#define VINF_SSM_DONT_CALL_AGAIN                1854
+/** Giving up a live snapshot/teleportation attempt because of too many
+ * passes. */
+#define VERR_SSM_TOO_MANY_PASSES                (-1855)
+/** Giving up a live snapshot/teleportation attempt because the state grew to
+ * big. */
+#define VERR_SSM_STATE_GREW_TOO_BIG             (-1856)
+/** Giving up a live snapshot attempt because we're low on disk space.  */
+#define VERR_SSM_LOW_ON_DISK_SPACE              (-1857)
+/** The operation was cancelled. */
+#define VERR_SSM_CANCELLED                      (-1858)
+/** Nothing that can be cancelled.  */
+#define VERR_SSM_NO_PENDING_OPERATION           (-1859)
+/** The operation has already been cancelled. */
+#define VERR_SSM_ALREADY_CANCELLED              (-1860)
+/** The machine was powered off while saving. */
+#define VERR_SSM_LIVE_POWERED_OFF               (-1861)
+/** The live snapshot/teleportation operation was aborted because of a guru
+ *  meditation. */
+#define VERR_SSM_LIVE_GURU_MEDITATION           (-1862)
+/** The live snapshot/teleportation operation was aborted because of a fatal
+ *  runtime error. */
+#define VERR_SSM_LIVE_FATAL_ERROR               (-1863)
+/** The VM was suspended before or while saving, don't resume execution. */
+#define VINF_SSM_LIVE_SUSPENDED                  1864
+/** Complex SSM field fed to SSMR3PutStruct or SSMR3GetStruct.  Use the
+ * extended API. */
+#define VERR_SSM_FIELD_COMPLEX                  (-1864)
+/** Invalid size of a SSM field with the specified transformation. */
+#define VERR_SSM_FIELD_INVALID_SIZE             (-1865)
+/** The specified field is outside the structure.  */
+#define VERR_SSM_FIELD_OUT_OF_BOUNDS            (-1866)
+/** The field does not follow immediately the previous one. */
+#define VERR_SSM_FIELD_NOT_CONSECUTIVE          (-1867)
+/** The field contains an invalid callback or transformation index. */
+#define VERR_SSM_FIELD_INVALID_CALLBACK         (-1868)
+/** The field contains an invalid padding size. */
+#define VERR_SSM_FIELD_INVALID_PADDING_SIZE     (-1869)
+/** The field contains a value that is out of range. */
+#define VERR_SSM_FIELD_INVALID_VALUE            (-1870)
+/** Generic stream error. */
+#define VERR_SSM_STREAM_ERROR                   (-1871)
+/** SSM did a callback for a pass we didn't expect. */
+#define VERR_SSM_UNEXPECTED_PASS                (-1872)
+/** Someone is trying to skip backwards in the stream... */
+#define VERR_SSM_SKIP_BACKWARDS                 (-1873)
+/** Someone is trying to write a memory block which is too big to encode. */
+#define VERR_SSM_MEM_TOO_BIG                    (-1874)
+/** Encountered an bad (/unknown) record type. */
+#define VERR_SSM_BAD_REC_TYPE                   (-1875)
+/** Internal processing error \#1 in SSM code.  */
+#define VERR_SSM_IPE_1                          (-1876)
+/** Internal processing error \#2 in SSM code.  */
+#define VERR_SSM_IPE_2                          (-1877)
+/** Internal processing error \#3 in SSM code.  */
+#define VERR_SSM_IPE_3                          (-1878)
+/** A field contained an transformation that should only be used when loading
+ * old states. */
+#define VERR_SSM_FIELD_LOAD_ONLY_TRANSFORMATION (-1879)
+/** @} */
+
+
+/** @name Virtual Machine (VM) Status Codes
+ * @{
+ */
+/** The specified at reset handler wasn't found. */
+#define VERR_VM_ATRESET_NOT_FOUND               (-1900)
+/** Invalid VM request type.
+ * For the VMR3ReqAlloc() case, the caller just specified an illegal enmType. For
+ * all the other occurrences it means indicates corruption, broken logic, or stupid
+ * interface user. */
+#define VERR_VM_REQUEST_INVALID_TYPE            (-1901)
+/** Invalid VM request state.
+ * The state of the request packet was not the expected and accepted one(s). Either
+ * the interface user screwed up, or we've got corruption/broken logic. */
+#define VERR_VM_REQUEST_STATE                   (-1902)
+/** Invalid VM request packet.
+ * One or more of the VM controlled packet members didn't contain the correct
+ * values. Some thing's broken. */
+#define VERR_VM_REQUEST_INVALID_PACKAGE         (-1903)
+/** The status field has not been updated yet as the request is still
+ * pending completion. Someone queried the iStatus field before the request
+ * has been fully processed. */
+#define VERR_VM_REQUEST_STATUS_STILL_PENDING    (-1904)
+/** The request has been freed, don't read the status now.
+ * Someone is reading the iStatus field of a freed request packet. */
+#define VERR_VM_REQUEST_STATUS_FREED            (-1905)
+/** A VM api requiring EMT was called from another thread.
+ * Use the VMR3ReqCall() apis to call it! */
+#define VERR_VM_THREAD_NOT_EMT                  (-1906)
+/** The VM state was invalid for the requested operation.
+ * Go check the 'VM Statechart Diagram.gif'. */
+#define VERR_VM_INVALID_VM_STATE                (-1907)
+/** The support driver is not installed.
+ * On linux, open returned ENOENT. */
+#define VERR_VM_DRIVER_NOT_INSTALLED            (-1908)
+/** The support driver is not accessible.
+ * On linux, open returned EPERM. */
+#define VERR_VM_DRIVER_NOT_ACCESSIBLE           (-1909)
+/** Was not able to load the support driver.
+ * On linux, open returned ENODEV. */
+#define VERR_VM_DRIVER_LOAD_ERROR               (-1910)
+/** Was not able to open the support driver.
+ * Generic open error used when none of the other ones fit. */
+#define VERR_VM_DRIVER_OPEN_ERROR               (-1911)
+/** The installed support driver doesn't match the version of the user. */
+#define VERR_VM_DRIVER_VERSION_MISMATCH         (-1912)
+/** Saving the VM state is temporarily not allowed. Try again later. */
+#define VERR_VM_SAVE_STATE_NOT_ALLOWED          (-1913)
+/** An EMT called an API which cannot be called on such a thread. */
+#define VERR_VM_THREAD_IS_EMT                   (-1914)
+/** Encountered an unexpected VM state.  */
+#define VERR_VM_UNEXPECTED_VM_STATE             (-1915)
+/** Unexpected unstable VM state. */
+#define VERR_VM_UNEXPECTED_UNSTABLE_STATE       (-1916)
+/** Too many arguments passed to a VM request / request corruption.  */
+#define VERR_VM_REQUEST_TOO_MANY_ARGS_IPE       (-1917)
+/** Fatal EMT wait error. */
+#define VERR_VM_FATAL_WAIT_ERROR                (-1918)
+/** The VM request was killed at VM termination. */
+#define VERR_VM_REQUEST_KILLED                  (-1919)
+/** @} */
+
+
+/** @name VBox Remote Desktop Protocol (VRDP) Status Codes
+ * @{
+ */
+/** Successful completion of operation (mapped to generic iprt status code). */
+#define VINF_VRDP_SUCCESS                   VINF_SUCCESS
+/** VRDP transport operation timed out (mapped to generic iprt status code). */
+#define VERR_VRDP_TIMEOUT                   VERR_TIMEOUT
+
+/** Unsupported ISO protocol feature */
+#define VERR_VRDP_ISO_UNSUPPORTED           (-2000)
+/** Security (en/decryption) engine error */
+#define VERR_VRDP_SEC_ENGINE_FAIL           (-2001)
+/** VRDP protocol violation */
+#define VERR_VRDP_PROTOCOL_ERROR            (-2002)
+/** Unsupported VRDP protocol feature */
+#define VERR_VRDP_NOT_SUPPORTED             (-2003)
+/** VRDP protocol violation, client sends less data than expected */
+#define VERR_VRDP_INSUFFICIENT_DATA         (-2004)
+/** Internal error, VRDP packet is in wrong operation mode */
+#define VERR_VRDP_INVALID_MODE              (-2005)
+/** Memory allocation failed */
+#define VERR_VRDP_NO_MEMORY                 (-2006)
+/** Client has been rejected */
+#define VERR_VRDP_ACCESS_DENIED             (-2007)
+/** VRPD receives a packet that is not supported */
+#define VWRN_VRDP_PDU_NOT_SUPPORTED         2008
+/** VRDP script allowed the packet to be processed further */
+#define VINF_VRDP_PROCESS_PDU               2009
+/** VRDP script has completed its task */
+#define VINF_VRDP_OPERATION_COMPLETED       2010
+/** VRDP thread has started OK and will run */
+#define VINF_VRDP_THREAD_STARTED            2011
+/** Framebuffer is resized, terminate send bitmap procedure */
+#define VINF_VRDP_RESIZE_REQUESTED          2012
+/** Output can be enabled for the client. */
+#define VINF_VRDP_OUTPUT_ENABLE             2013
+/** @} */
+
+
+/** @name Configuration Manager (CFGM) Status Codes
+ * @{
+ */
+/** The integer value was too big for the requested representation. */
+#define VERR_CFGM_INTEGER_TOO_BIG           (-2100)
+/** Child node was not found. */
+#define VERR_CFGM_CHILD_NOT_FOUND           (-2101)
+/** Path to child node was invalid (i.e. empty). */
+#define VERR_CFGM_INVALID_CHILD_PATH        (-2102)
+/** Value not found. */
+#define VERR_CFGM_VALUE_NOT_FOUND           (-2103)
+/** No parent node specified. */
+#define VERR_CFGM_NO_PARENT                 (-2104)
+/** No node was specified. */
+#define VERR_CFGM_NO_NODE                   (-2105)
+/** The value is not an integer. */
+#define VERR_CFGM_NOT_INTEGER               (-2106)
+/** The value is not a zero terminated character string. */
+#define VERR_CFGM_NOT_STRING                (-2107)
+/** The value is not a byte string. */
+#define VERR_CFGM_NOT_BYTES                 (-2108)
+/** The specified string / bytes buffer was to small. Specify a larger one and retry. */
+#define VERR_CFGM_NOT_ENOUGH_SPACE          (-2109)
+/** The path of a new node contained slashes or was empty. */
+#define VERR_CFGM_INVALID_NODE_PATH         (-2160)
+/** A new node couldn't be inserted because one with the same name exists. */
+#define VERR_CFGM_NODE_EXISTS               (-2161)
+/** A new leaf couldn't be inserted because one with the same name exists. */
+#define VERR_CFGM_LEAF_EXISTS               (-2162)
+/** An unknown config value was encountered. */
+#define VERR_CFGM_CONFIG_UNKNOWN_VALUE      (-2163)
+/** An unknown config node (key) was encountered. */
+#define VERR_CFGM_CONFIG_UNKNOWN_NODE       (-2164)
+/** Internal processing error \#1 in CFGM. */
+#define VERR_CFGM_IPE_1                     (-2165)
+/** @} */
+
+
+/** @name Time Manager (TM) Status Codes
+ * @{
+ */
+/** The loaded timer state was incorrect. */
+#define VERR_TM_LOAD_STATE                  (-2200)
+/** The timer was not in the correct state for the request operation. */
+#define VERR_TM_INVALID_STATE               (-2201)
+/** The timer was in a unknown state. Corruption or stupid coding error. */
+#define VERR_TM_UNKNOWN_STATE               (-2202)
+/** The timer was stuck in an unstable state until we grew impatient and returned. */
+#define VERR_TM_UNSTABLE_STATE              (-2203)
+/** TM requires GIP. */
+#define VERR_TM_GIP_REQUIRED                (-2204)
+/** TM does not support the GIP version. */
+#define VERR_TM_GIP_VERSION                 (-2205)
+/** The GIP update interval is too large. */
+#define VERR_TM_GIP_UPDATE_INTERVAL_TOO_BIG (-2206)
+/** The timer has a bad clock enum value, probably corruption. */
+#define VERR_TM_TIMER_BAD_CLOCK             (-2207)
+/** The timer failed to reach a stable state. */
+#define VERR_TM_TIMER_UNSTABLE_STATE        (-2208)
+/** Attempt to resume a running TSC. */
+#define VERR_TM_TSC_ALREADY_TICKING         (-2209)
+/** Attempt to pause a paused TSC. */
+#define VERR_TM_TSC_ALREADY_PAUSED          (-2210)
+/** Invalid value for cVirtualTicking.  */
+#define VERR_TM_VIRTUAL_TICKING_IPE         (-2211)
+/** @} */
+
+
+/** @name Recompiled Execution Manager (REM) Status Codes
+ * @{
+ */
+/** Fatal error in virtual hardware. */
+#define VERR_REM_VIRTUAL_HARDWARE_ERROR     (-2300)
+/** Fatal error in the recompiler cpu. */
+#define VERR_REM_VIRTUAL_CPU_ERROR          (-2301)
+/** Recompiler execution was interrupted by forced action. */
+#define VINF_REM_INTERRUPED_FF              2302
+/** Too many similar traps. This is a very useful debug only
+ * check (we don't do double/triple faults in REM). */
+#define VERR_REM_TOO_MANY_TRAPS             (-2304)
+/** The REM is out of breakpoint slots. */
+#define VERR_REM_NO_MORE_BP_SLOTS           (-2305)
+/** The REM could not find any breakpoint on the specified address. */
+#define VERR_REM_BP_NOT_FOUND               (-2306)
+/** @} */
+
+
+/** @name Trap Manager / Monitor (TRPM) Status Codes
+ * @{
+ */
+/** No active trap. Cannot query or reset a non-existing trap. */
+#define VERR_TRPM_NO_ACTIVE_TRAP            (-2400)
+/** Active trap. Cannot assert a new trap when one is already active. */
+#define VERR_TRPM_ACTIVE_TRAP               (-2401)
+/** Reason for leaving RC: Guest tried to write to our IDT - fatal.
+ * The VM will be terminated assuming the worst, i.e. that the
+ * guest has read the idtr register. */
+#define VERR_TRPM_SHADOW_IDT_WRITE          (-2402)
+/** Reason for leaving RC: Fatal trap in hypervisor. */
+#define VERR_TRPM_DONT_PANIC                (-2403)
+/** Reason for leaving RC: Double Fault. */
+#define VERR_TRPM_PANIC                     (-2404)
+/** The exception was dispatched for raw-mode execution. */
+#define VINF_TRPM_XCPT_DISPATCHED           2405
+/** Bad TRPM_TRAP_IN_OP. */
+#define VERR_TRPM_BAD_TRAP_IN_OP            (-2406)
+/** Internal processing error \#1 in TRPM. */
+#define VERR_TRPM_IPE_1                     (-2407)
+/** Internal processing error \#2 in TRPM. */
+#define VERR_TRPM_IPE_2                     (-2408)
+/** Internal processing error \#3 in TRPM. */
+#define VERR_TRPM_IPE_3                     (-2409)
+/** Got into a part of TRPM that is not used when HM (VT-x/AMD-V) is enabled. */
+#define VERR_TRPM_HM_IPE                    (-2410)
+/** @} */
+
+
+/** @name Selector Manager / Monitor (SELM) Status Code
+ * @{
+ */
+/** Reason for leaving RC: Guest tried to write to our GDT - fatal.
+ * The VM will be terminated assuming the worst, i.e. that the
+ * guest has read the gdtr register. */
+#define VERR_SELM_SHADOW_GDT_WRITE          (-2500)
+/** Reason for leaving RC: Guest tried to write to our LDT - fatal.
+ * The VM will be terminated assuming the worst, i.e. that the
+ * guest has read the ldtr register. */
+#define VERR_SELM_SHADOW_LDT_WRITE          (-2501)
+/** Reason for leaving RC: Guest tried to write to our TSS - fatal.
+ * The VM will be terminated assuming the worst, i.e. that the
+ * guest has read the ltr register. */
+#define VERR_SELM_SHADOW_TSS_WRITE          (-2502)
+/** Reason for leaving RC: Sync the GDT table to solve a conflict. */
+#define VINF_SELM_SYNC_GDT                  2503
+/** No valid TSS present. */
+#define VERR_SELM_NO_TSS                    (-2504)
+/** Invalid guest LDT selector. */
+#define VERR_SELM_INVALID_LDT               (-2505)
+/** The guest LDT selector is out of bounds. */
+#define VERR_SELM_LDT_OUT_OF_BOUNDS         (-2506)
+/** Unknown error while reading the guest GDT during shadow table updating. */
+#define VERR_SELM_GDT_READ_ERROR            (-2507)
+/** The guest GDT so full that we cannot find free space for our own
+ * selectors. */
+#define VERR_SELM_GDT_TOO_FULL              (-2508)
+/** Got into a part of SELM that is not used when HM (VT-x/AMD-V) is enabled. */
+#define VERR_SELM_HM_IPE                    (-2509)
+/** @} */
+
+
+/** @name I/O Manager / Monitor (IOM) Status Code
+ * @{
+ */
+/** The specified I/O port range was invalid.
+ * It was either empty or it was out of bounds. */
+#define VERR_IOM_INVALID_IOPORT_RANGE       (-2600)
+/** The specified R0 or RC I/O port range didn't have a corresponding R3 range.
+ * IOMR3IOPortRegisterR3() must be called first. */
+#define VERR_IOM_NO_R3_IOPORT_RANGE         (-2601)
+/** The specified I/O port range intruded on an existing range. There is
+ * a I/O port conflict between two device, or a device tried to register
+ * the same range twice. */
+#define VERR_IOM_IOPORT_RANGE_CONFLICT      (-2602)
+/** The I/O port range specified for removal wasn't found or it wasn't contiguous. */
+#define VERR_IOM_IOPORT_RANGE_NOT_FOUND     (-2603)
+/** The specified I/O port range was owned by some other device(s). Both registration
+ * and deregistration, but in the first case only RC and R0 ranges. */
+#define VERR_IOM_NOT_IOPORT_RANGE_OWNER     (-2604)
+
+/** The specified MMIO range was invalid.
+ * It was either empty or it was out of bounds. */
+#define VERR_IOM_INVALID_MMIO_RANGE         (-2605)
+/** The specified R0 or RC MMIO range didn't have a corresponding R3 range.
+ * IOMR3MMIORegisterR3() must be called first. */
+#define VERR_IOM_NO_R3_MMIO_RANGE           (-2606)
+/** The specified MMIO range was owned by some other device(s). Both registration
+ * and deregistration, but in the first case only RC and R0 ranges. */
+#define VERR_IOM_NOT_MMIO_RANGE_OWNER       (-2607)
+/** The specified MMIO range intruded on an existing range. There is
+ * a MMIO conflict between two device, or a device tried to register
+ * the same range twice. */
+#define VERR_IOM_MMIO_RANGE_CONFLICT        (-2608)
+/** The MMIO range specified for removal was not found. */
+#define VERR_IOM_MMIO_RANGE_NOT_FOUND       (-2609)
+/** The MMIO range specified for removal was invalid. The range didn't match
+ * quite match a set of existing ranges. It's not possible to remove parts of
+ * a MMIO range, only one or more full ranges. */
+#define VERR_IOM_INCOMPLETE_MMIO_RANGE      (-2610)
+/** An invalid I/O port size was specified for a read or write operation. */
+#define VERR_IOM_INVALID_IOPORT_SIZE        (-2611)
+/** The MMIO handler was called for a bogus address! Internal error! */
+#define VERR_IOM_MMIO_HANDLER_BOGUS_CALL    (-2612)
+/** The MMIO handler experienced a problem with the disassembler. */
+#define VERR_IOM_MMIO_HANDLER_DISASM_ERROR  (-2613)
+/** The port being read was not present(/unused) and IOM shall return ~0 according to size. */
+#define VERR_IOM_IOPORT_UNUSED              (-2614)
+/** Unused MMIO register read, fill with 00. */
+#define VINF_IOM_MMIO_UNUSED_00             2615
+/** Unused MMIO register read, fill with FF. */
+#define VINF_IOM_MMIO_UNUSED_FF             2616
+
+/** Reason for leaving RZ: I/O port read. */
+#define VINF_IOM_R3_IOPORT_READ             2620
+/** Reason for leaving RZ: I/O port write. */
+#define VINF_IOM_R3_IOPORT_WRITE            2621
+/** Reason for leaving RZ: Pending I/O port write.  Since there is also
+ * VMCPU_FF_IOM for this condition, it's ok to drop this status code for
+ * some other VINF_EM_XXX statuses. */
+#define VINF_IOM_R3_IOPORT_COMMIT_WRITE     2622
+/** Reason for leaving RZ: MMIO read. */
+#define VINF_IOM_R3_MMIO_READ               2623
+/** Reason for leaving RZ: MMIO write. */
+#define VINF_IOM_R3_MMIO_WRITE              2624
+/** Reason for leaving RZ: MMIO read/write. */
+#define VINF_IOM_R3_MMIO_READ_WRITE         2625
+/** Reason for leaving RZ: Pending MMIO write.   Since there is also
+ * VMCPU_FF_IOM for this condition, it's ok to drop this status code for
+ * some other VINF_EM_XXX statuses. */
+#define VINF_IOM_R3_MMIO_COMMIT_WRITE       2626
+
+/** IOMGCIOPortHandler was given an unexpected opcode. */
+#define VERR_IOM_IOPORT_UNKNOWN_OPCODE      (-2630)
+/** Internal processing error \#1 in the I/O port code. */
+#define VERR_IOM_IOPORT_IPE_1               (-2631)
+/** Internal processing error \#2 in the I/O port code. */
+#define VERR_IOM_IOPORT_IPE_2               (-2632)
+/** Internal processing error \#3 in the I/O port code. */
+#define VERR_IOM_IOPORT_IPE_3               (-2633)
+/** Internal processing error \#1 in the MMIO code. */
+#define VERR_IOM_MMIO_IPE_1                 (-2634)
+/** Internal processing error \#2 in the MMIO code. */
+#define VERR_IOM_MMIO_IPE_2                 (-2635)
+/** Internal processing error \#3 in the MMIO code. */
+#define VERR_IOM_MMIO_IPE_3                 (-2636)
+/** Got into a part of IOM that is not used when HM (VT-x/AMD-V) is enabled. */
+#define VERR_IOM_HM_IPE                     (-2637)
+/** Internal processing error while merging status codes. */
+#define VERR_IOM_FF_STATUS_IPE              (-2638)
+/** @} */
+
+
+/** @name Virtual Machine Monitor (VMM) Status Codes
+ * @{
+ */
+/** Reason for leaving RZ: Calling host function. */
+#define VINF_VMM_CALL_HOST                  2700
+/** Reason for leaving R0: Hit a ring-0 assertion on EMT. */
+#define VERR_VMM_RING0_ASSERTION            (-2701)
+/** The hyper CR3 differs between PGM and CPUM. */
+#define VERR_VMM_HYPER_CR3_MISMATCH         (-2702)
+/** Reason for leaving RZ: Illegal call to ring-3. */
+#define VERR_VMM_RING3_CALL_DISABLED        (-2703)
+/** The VMMR0.r0 module version does not match VBoxVMM.dll/so/dylib.
+ * If you just upgraded VirtualBox, please terminate all VMs and make sure
+ * that neither VBoxNetDHCP nor VBoxNetNAT is running.  Then try again.
+ * If this error persists, try re-installing VirtualBox. */
+#define VERR_VMM_R0_VERSION_MISMATCH        (-2704)
+/** The VMMRC.rc module version does not match VBoxVMM.dll/so/dylib.
+ * Re-install if you are a user.  Developers should make sure the build is
+ * complete or try with a clean build. */
+#define VERR_VMM_RC_VERSION_MISMATCH        (-2705)
+/** VMM set jump error. */
+#define VERR_VMM_SET_JMP_ERROR              (-2706)
+/** VMM set jump stack overflow error. */
+#define VERR_VMM_SET_JMP_STACK_OVERFLOW     (-2707)
+/** VMM set jump resume error. */
+#define VERR_VMM_SET_JMP_ABORTED_RESUME     (-2708)
+/** VMM long jump error. */
+#define VERR_VMM_LONG_JMP_ERROR             (-2709)
+/** Unknown ring-3 call attempted. */
+#define VERR_VMM_UNKNOWN_RING3_CALL         (-2710)
+/** The ring-3 call didn't set an RC. */
+#define VERR_VMM_RING3_CALL_NO_RC           (-2711)
+/** Reason for leaving RC: Caller the tracer in ring-0. */
+#define VINF_VMM_CALL_TRACER                (2712)
+/** Internal processing error \#1 in the switcher code. */
+#define VERR_VMM_SWITCHER_IPE_1             (-2713)
+/** Reason for leaving RZ: Unknown call to ring-3. */
+#define VINF_VMM_UNKNOWN_RING3_CALL         (2714)
+/** Attempted to use stub switcher. */
+#define VERR_VMM_SWITCHER_STUB              (-2715)
+/** HM returned in the wrong state. */
+#define VERR_VMM_WRONG_HM_VMCPU_STATE       (-2716)
+/** SMAP enabled, but the AC flag was found to be clear - check the kernel
+ * log for details. */
+#define VERR_VMM_SMAP_BUT_AC_CLEAR          (-2717)
+/** @} */
+
+
+/** @name Pluggable Device and Driver Manager (PDM) Status Codes
+ * @{
+ */
+/** An invalid LUN specification was given. */
+#define VERR_PDM_NO_SUCH_LUN                        (-2800)
+/** A device encountered an unknown configuration value.
+ * This means that the device is potentially misconfigured and the device
+ * construction or unit attachment failed because of this. */
+#define VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES          (-2801)
+/** The above driver doesn't export a interface required by a driver being
+ * attached to it. Typical misconfiguration problem. */
+#define VERR_PDM_MISSING_INTERFACE_ABOVE            (-2802)
+/** The below driver doesn't export a interface required by the drive
+ * having attached it. Typical misconfiguration problem. */
+#define VERR_PDM_MISSING_INTERFACE_BELOW            (-2803)
+/** A device didn't find a required interface with an attached driver.
+ * Typical misconfiguration problem. */
+#define VERR_PDM_MISSING_INTERFACE                  (-2804)
+/** A driver encountered an unknown configuration value.
+ * This means that the driver is potentially misconfigured and the driver
+ * construction failed because of this. */
+#define VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES          (-2805)
+/** The PCI bus assigned to a device didn't have room for it.
+ * Either too many devices are configured on the same PCI bus, or there are
+ * some internal problem where PDM/PCI doesn't free up slots when unplugging devices. */
+#define VERR_PDM_TOO_PCI_MANY_DEVICES               (-2806)
+/** A queue is out of free items, the queueing operation failed. */
+#define VERR_PDM_NO_QUEUE_ITEMS                     (-2807)
+/** Not possible to attach further drivers to the driver.
+ * A driver which doesn't support attachments (below of course) will
+ * return this status code if it found that further drivers were configured
+ * to be attached to it. */
+#define VERR_PDM_DRVINS_NO_ATTACH                   (-2808)
+/** Not possible to attach drivers to the device.
+ * A device which doesn't support attachments (below of course) will
+ * return this status code if it found that drivers were configured
+ * to be attached to it. */
+#define VERR_PDM_DEVINS_NO_ATTACH                   (-2809)
+/** No attached driver.
+ * The PDMDRVHLP::pfnAttach and PDMDEVHLP::pfnDriverAttach will return
+ * this error when no driver was configured to be attached. */
+#define VERR_PDM_NO_ATTACHED_DRIVER                 (-2810)
+/** The media geometry hasn't been set yet, so it cannot be obtained.
+ * The caller should then calculate the geometry from the media size. */
+#define VERR_PDM_GEOMETRY_NOT_SET                   (-2811)
+/** The media translation hasn't been set yet, so it cannot be obtained.
+ * The caller should then guess the translation. */
+#define VERR_PDM_TRANSLATION_NOT_SET                (-2812)
+/** The media is not mounted, operation requires a mounted media. */
+#define VERR_PDM_MEDIA_NOT_MOUNTED                  (-2813)
+/** Mount failed because a media was already mounted. Unmount the media
+ * and retry the mount. */
+#define VERR_PDM_MEDIA_MOUNTED                      (-2814)
+/** The media is locked and cannot be unmounted. */
+#define VERR_PDM_MEDIA_LOCKED                       (-2815)
+/** No 'Type' attribute in the DrvBlock configuration.
+ * Misconfiguration. */
+#define VERR_PDM_BLOCK_NO_TYPE                      (-2816)
+/** The 'Type' attribute in the DrvBlock configuration had an unknown value.
+ * Misconfiguration. */
+#define VERR_PDM_BLOCK_UNKNOWN_TYPE                 (-2817)
+/** The 'Translation' attribute in the DrvBlock configuration had an unknown value.
+ * Misconfiguration. */
+#define VERR_PDM_BLOCK_UNKNOWN_TRANSLATION          (-2818)
+/** The block driver type wasn't supported.
+ * Misconfiguration of the kind you get when attaching a floppy to an IDE controller. */
+#define VERR_PDM_UNSUPPORTED_BLOCK_TYPE             (-2819)
+/** A attach or prepare mount call failed because the driver already
+ * had a driver attached. */
+#define VERR_PDM_DRIVER_ALREADY_ATTACHED            (-2820)
+/** An attempt on detaching a driver without anyone actually being attached, or
+ * performing any other operation on an attached driver. */
+#define VERR_PDM_NO_DRIVER_ATTACHED                 (-2821)
+/** The attached driver configuration is missing the 'Driver' attribute. */
+#define VERR_PDM_CFG_MISSING_DRIVER_NAME            (-2822)
+/** The configured driver wasn't found.
+ * Either the necessary driver modules wasn't loaded, the name was
+ * misspelled, or it was a misconfiguration. */
+#define VERR_PDM_DRIVER_NOT_FOUND                   (-2823)
+/** The Ring-3 module was already loaded. */
+#define VINF_PDM_ALREADY_LOADED                     (2824)
+/** The name of the module clashed with an existing module. */
+#define VERR_PDM_MODULE_NAME_CLASH                  (-2825)
+/** Couldn't find any export for registration of drivers/devices. */
+#define VERR_PDM_NO_REGISTRATION_EXPORT             (-2826)
+/** A module name is too long. */
+#define VERR_PDM_MODULE_NAME_TOO_LONG               (-2827)
+/** Driver name clash. Another driver with the same name as the
+ * one being registered exists. */
+#define VERR_PDM_DRIVER_NAME_CLASH                  (-2828)
+/** The version of the driver registration structure is unknown
+ * to this VBox version. Either mixing incompatible versions or
+ * the structure isn't correctly initialized. */
+#define VERR_PDM_UNKNOWN_DRVREG_VERSION             (-2829)
+/** Invalid entry in the driver registration structure. */
+#define VERR_PDM_INVALID_DRIVER_REGISTRATION        (-2830)
+/** Invalid host bit mask. */
+#define VERR_PDM_INVALID_DRIVER_HOST_BITS           (-2831)
+/** Not possible to detach a driver because the above driver/device
+ * doesn't support it. The above entity doesn't implement the pfnDetach call. */
+#define VERR_PDM_DRIVER_DETACH_NOT_POSSIBLE         (-2832)
+/** No PCI Bus is available to register the device with. This is usually a
+ * misconfiguration or in rare cases a buggy pci device. */
+#define VERR_PDM_NO_PCI_BUS                         (-2833)
+/** The device is not a registered PCI device and thus cannot
+ * perform any PCI operations. The device forgot to register it self. */
+#define VERR_PDM_NOT_PCI_DEVICE                     (-2834)
+
+/** The version of the device registration structure is unknown
+ * to this VBox version. Either mixing incompatible versions or
+ * the structure isn't correctly initialized. */
+#define VERR_PDM_UNKNOWN_DEVREG_VERSION             (-2835)
+/** Invalid entry in the device registration structure. */
+#define VERR_PDM_INVALID_DEVICE_REGISTRATION        (-2836)
+/** Invalid host bit mask. */
+#define VERR_PDM_INVALID_DEVICE_GUEST_BITS          (-2837)
+/** The guest bit mask didn't match the guest being loaded. */
+#define VERR_PDM_INVALID_DEVICE_HOST_BITS           (-2838)
+/** Device name clash. Another device with the same name as the
+ * one being registered exists. */
+#define VERR_PDM_DEVICE_NAME_CLASH                  (-2839)
+/** The device wasn't found. There was no registered device
+ * by that name. */
+#define VERR_PDM_DEVICE_NOT_FOUND                   (-2840)
+/** The device instance was not found. */
+#define VERR_PDM_DEVICE_INSTANCE_NOT_FOUND          (-2841)
+/** The device instance have no base interface. */
+#define VERR_PDM_DEVICE_INSTANCE_NO_IBASE           (-2842)
+/** The device instance have no such logical unit. */
+#define VERR_PDM_DEVICE_INSTANCE_LUN_NOT_FOUND      (-2843)
+/** The driver instance could not be found. */
+#define VERR_PDM_DRIVER_INSTANCE_NOT_FOUND          (-2844)
+/** Logical Unit was not found. */
+#define VERR_PDM_LUN_NOT_FOUND                      (-2845)
+/** The Logical Unit was found, but it had no driver attached to it. */
+#define VERR_PDM_NO_DRIVER_ATTACHED_TO_LUN          (-2846)
+/** The Logical Unit was found, but it had no driver attached to it. */
+#define VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN          2846
+/** No PIC device instance is registered with the current VM and thus
+ * the PIC operation cannot be performed. */
+#define VERR_PDM_NO_PIC_INSTANCE                    (-2847)
+/** No APIC device instance is registered with the current VM and thus
+ * the APIC operation cannot be performed. */
+#define VERR_PDM_NO_APIC_INSTANCE                   (-2848)
+/** No DMAC device instance is registered with the current VM and thus
+ * the DMA operation cannot be performed. */
+#define VERR_PDM_NO_DMAC_INSTANCE                   (-2849)
+/** No RTC device instance is registered with the current VM and thus
+ * the RTC or CMOS operation cannot be performed. */
+#define VERR_PDM_NO_RTC_INSTANCE                    (-2850)
+/** Unable to open the host interface due to a sharing violation . */
+#define VERR_PDM_HIF_SHARING_VIOLATION              (-2851)
+/** Unable to open the host interface. */
+#define VERR_PDM_HIF_OPEN_FAILED                    (-2852)
+/** The device doesn't support runtime driver attaching.
+ * The PDMDEVREG::pfnAttach callback function is NULL. */
+#define VERR_PDM_DEVICE_NO_RT_ATTACH                (-2853)
+/** The driver doesn't support runtime driver attaching.
+ * The PDMDRVREG::pfnAttach callback function is NULL. */
+#define VERR_PDM_DRIVER_NO_RT_ATTACH                (-2854)
+/** Invalid host interface version. */
+#define VERR_PDM_HIF_INVALID_VERSION                (-2855)
+
+/** The version of the USB device registration structure is unknown
+ * to this VBox version. Either mixing incompatible versions or
+ * the structure isn't correctly initialized. */
+#define VERR_PDM_UNKNOWN_USBREG_VERSION             (-2856)
+/** Invalid entry in the device registration structure. */
+#define VERR_PDM_INVALID_USB_REGISTRATION           (-2857)
+/** Driver name clash. Another driver with the same name as the
+ * one being registered exists. */
+#define VERR_PDM_USB_NAME_CLASH                     (-2858)
+/** The USB hub is already registered. */
+#define VERR_PDM_USB_HUB_EXISTS                     (-2859)
+/** Couldn't find any USB hubs to attach the device to. */
+#define VERR_PDM_NO_USB_HUBS                        (-2860)
+/** Couldn't find any free USB ports to attach the device to. */
+#define VERR_PDM_NO_USB_PORTS                       (-2861)
+/** Couldn't find the USB Proxy device. Using OSE? */
+#define VERR_PDM_NO_USBPROXY                        (-2862)
+/** The async completion template is still used. */
+#define VERR_PDM_ASYNC_TEMPLATE_BUSY                (-2863)
+/** The async completion task is already suspended. */
+#define VERR_PDM_ASYNC_COMPLETION_ALREADY_SUSPENDED (-2864)
+/** The async completion task is not suspended. */
+#define VERR_PDM_ASYNC_COMPLETION_NOT_SUSPENDED     (-2865)
+/** The driver properties were invalid, and as a consequence construction
+ * failed. Caused my unusable media or similar problems. */
+#define VERR_PDM_DRIVER_INVALID_PROPERTIES          (-2866)
+/** Too many instances of a device. */
+#define VERR_PDM_TOO_MANY_DEVICE_INSTANCES          (-2867)
+/** Too many instances of a driver. */
+#define VERR_PDM_TOO_MANY_DRIVER_INSTANCES          (-2868)
+/** Too many instances of a usb device. */
+#define VERR_PDM_TOO_MANY_USB_DEVICE_INSTANCES      (-2869)
+/** The device instance structure version has changed.
+ *
+ * If you have upgraded VirtualBox recently, please make sure you have
+ * terminated all VMs and upgraded any extension packs.  If this error
+ * persists, try re-installing VirtualBox. */
+#define VERR_PDM_DEVINS_VERSION_MISMATCH            (-2870)
+/** The device helper structure version has changed.
+ *
+ * If you have upgraded VirtualBox recently, please make sure you have
+ * terminated all VMs and upgraded any extension packs.  If this error
+ * persists, try re-installing VirtualBox. */
+#define VERR_PDM_DEVHLPR3_VERSION_MISMATCH          (-2871)
+/** The USB device instance structure version has changed.
+ *
+ * If you have upgraded VirtualBox recently, please make sure you have
+ * terminated all VMs and upgraded any extension packs.  If this error
+ * persists, try re-installing VirtualBox. */
+#define VERR_PDM_USBINS_VERSION_MISMATCH            (-2872)
+/** The USB device helper structure version has changed.
+ *
+ * If you have upgraded VirtualBox recently, please make sure you have
+ * terminated all VMs and upgraded any extension packs.  If this error
+ * persists, try re-installing VirtualBox. */
+#define VERR_PDM_USBHLPR3_VERSION_MISMATCH          (-2873)
+/** The driver instance structure version has changed.
+ *
+ * If you have upgraded VirtualBox recently, please make sure you have
+ * terminated all VMs and upgraded any extension packs.  If this error
+ * persists, try re-installing VirtualBox. */
+#define VERR_PDM_DRVINS_VERSION_MISMATCH            (-2874)
+/** The driver helper structure version has changed.
+ *
+ * If you have upgraded VirtualBox recently, please make sure you have
+ * terminated all VMs and upgraded any extension packs.  If this error
+ * persists, try re-installing VirtualBox. */
+#define VERR_PDM_DRVHLPR3_VERSION_MISMATCH          (-2875)
+/** Generic device structure version mismatch.
+ *
+ * If you have upgraded VirtualBox recently, please make sure you have
+ * terminated all VMs and upgraded any extension packs.  If this error
+ * persists, try re-installing VirtualBox. */
+#define VERR_PDM_DEVICE_VERSION_MISMATCH            (-2876)
+/** Generic USB device structure version mismatch.
+ *
+ * If you have upgraded VirtualBox recently, please make sure you have
+ * terminated all VMs and upgraded any extension packs.  If this error
+ * persists, try re-installing VirtualBox. */
+#define VERR_PDM_USBDEV_VERSION_MISMATCH            (-2877)
+/** Generic driver structure version mismatch.
+ *
+ * If you have upgraded VirtualBox recently, please make sure you have
+ * terminated all VMs and upgraded any extension packs.  If this error
+ * persists, try re-installing VirtualBox. */
+#define VERR_PDM_DRIVER_VERSION_MISMATCH            (-2878)
+/** PDMVMMDevHeapR3ToGCPhys failure. */
+#define VERR_PDM_DEV_HEAP_R3_TO_GCPHYS              (-2879)
+/** A legacy device isn't implementing the HPET notification interface. */
+#define VERR_PDM_HPET_LEGACY_NOTIFY_MISSING         (-2880)
+/** Internal processing error in the critical section code. */
+#define VERR_PDM_CRITSECT_IPE                       (-2881)
+/** The critical section being deleted was not found. */
+#define VERR_PDM_CRITSECT_NOT_FOUND                 (-2882)
+/** A PDMThread API was called by the wrong thread. */
+#define VERR_PDM_THREAD_INVALID_CALLER              (-2883)
+/** Internal processing error \#1 in the PDM Thread code. */
+#define VERR_PDM_THREAD_IPE_1                       (-2884)
+/** Internal processing error \#2 in the PDM Thread code. */
+#define VERR_PDM_THREAD_IPE_2                       (-2885)
+/** Only one PCI function is supported per PDM device. */
+#define VERR_PDM_ONE_PCI_FUNCTION_PER_DEVICE        (-2886)
+/** Bad PCI configuration. */
+#define VERR_PDM_BAD_PCI_CONFIG                     (-2887)
+/** Internal processing error # in the PDM device code. */
+#define VERR_PDM_DEV_IPE_1                          (-2888)
+/** Misconfigured driver chain transformation. */
+#define VERR_PDM_MISCONFIGURED_DRV_TRANSFORMATION   (-2889)
+/** The driver is already removed, not more transformations possible (at
+ *  present). */
+#define VERR_PDM_CANNOT_TRANSFORM_REMOVED_DRIVER    (-2890)
+/** The PCI device isn't configured as a busmaster, physical memory access
+ * rejected. */
+#define VERR_PDM_NOT_PCI_BUS_MASTER                 (-2891)
+/** Got into a part of PDM that is not used when HM (VT-x/AMD-V) is enabled. */
+#define VERR_PDM_HM_IPE                             (-2892)
+/** The I/O request was canceled. */
+#define VERR_PDM_MEDIAEX_IOREQ_CANCELED             (-2893)
+/** There is not enough room to store the data. */
+#define VERR_PDM_MEDIAEX_IOBUF_OVERFLOW             (-2894)
+/** There is not enough data to satisfy the request. */
+#define VERR_PDM_MEDIAEX_IOBUF_UNDERRUN             (-2895)
+/** The I/O request ID is already existing. */
+#define VERR_PDM_MEDIAEX_IOREQID_CONFLICT           (-2896)
+/** The I/O request ID was not found. */
+#define VERR_PDM_MEDIAEX_IOREQID_NOT_FOUND          (-2897)
+/** The I/O request is in progress. */
+#define VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS          2898
+/** The I/O request is in an invalid state for this operation. */
+#define VERR_PDM_MEDIAEX_IOREQ_INVALID_STATE        (-2899)
+/** @} */
+
+
+/** @name Host-Guest Communication Manager (HGCM) Status Codes
+ * @{
+ */
+/** Requested service does not exist. */
+#define VERR_HGCM_SERVICE_NOT_FOUND                 (-2900)
+/** Service rejected client connection */
+#define VINF_HGCM_CLIENT_REJECTED                   2901
+/** Command address is invalid. */
+#define VERR_HGCM_INVALID_CMD_ADDRESS               (-2902)
+/** Service will execute the command in background. */
+#define VINF_HGCM_ASYNC_EXECUTE                     2903
+/** HGCM could not perform requested operation because of an internal error. */
+#define VERR_HGCM_INTERNAL                          (-2904)
+/** Invalid HGCM client id. */
+#define VERR_HGCM_INVALID_CLIENT_ID                 (-2905)
+/** The HGCM is saving state. */
+#define VINF_HGCM_SAVE_STATE                        (2906)
+/** Requested service already exists. */
+#define VERR_HGCM_SERVICE_EXISTS                    (-2907)
+
+/** @} */
+
+
+/** @name Network Address Translation Driver (DrvNAT) Status Codes
+ * @{
+ */
+/** Failed to find the DNS configured for this machine. */
+#define VINF_NAT_DNS                                3000
+/** Failed to convert the specified Guest IP to a binary IP address.
+ * Malformed input. */
+#define VERR_NAT_REDIR_GUEST_IP                     (-3001)
+/** Failed while setting up a redirector rule.
+ * There probably is a conflict between the rule and some existing
+ * service on the computer. */
+#define VERR_NAT_REDIR_SETUP                        (-3002)
+/** @} */
+
+
+/** @name HostIF Driver (DrvTUN) Status Codes
+ * @{
+ */
+/** The Host Interface Networking init program failed. */
+#define VERR_HOSTIF_INIT_FAILED                     (-3100)
+/** The Host Interface Networking device name is too long. */
+#define VERR_HOSTIF_DEVICE_NAME_TOO_LONG            (-3101)
+/** The Host Interface Networking name config IOCTL call failed. */
+#define VERR_HOSTIF_IOCTL                           (-3102)
+/** Failed to make the Host Interface Networking handle non-blocking. */
+#define VERR_HOSTIF_BLOCKING                        (-3103)
+/** If a Host Interface Networking filehandle was specified it's not allowed to
+ * have any init or term programs. */
+#define VERR_HOSTIF_FD_AND_INIT_TERM                (-3104)
+/** The Host Interface Networking terminate program failed. */
+#define VERR_HOSTIF_TERM_FAILED                     (-3105)
+/** @} */
+
+
+/** @name VBox HDD Container (VD) Status Codes
+ * @{
+ */
+/** Invalid image type. */
+#define VERR_VD_INVALID_TYPE                        (-3200)
+/** Operation can't be done in current HDD container state. */
+#define VERR_VD_INVALID_STATE                       (-3201)
+/** Configuration value not found. */
+#define VERR_VD_VALUE_NOT_FOUND                     (-3202)
+/** Virtual HDD is not opened. */
+#define VERR_VD_NOT_OPENED                          (-3203)
+/** Requested image is not opened. */
+#define VERR_VD_IMAGE_NOT_FOUND                     (-3204)
+/** Image is read-only. */
+#define VERR_VD_IMAGE_READ_ONLY                     (-3205)
+/** Geometry hasn't been set. */
+#define VERR_VD_GEOMETRY_NOT_SET                    (-3206)
+/** No data for this block in image. */
+#define VERR_VD_BLOCK_FREE                          (-3207)
+/** Differencing and parent images can't be used together due to UUID. */
+#define VERR_VD_UUID_MISMATCH                       (-3208)
+/** Asynchronous I/O request finished. */
+#define VINF_VD_ASYNC_IO_FINISHED                   3209
+/** Asynchronous I/O is not finished yet. */
+#define VERR_VD_ASYNC_IO_IN_PROGRESS                (-3210)
+/** The image is too small or too large for this format. */
+#define VERR_VD_INVALID_SIZE                        (-3211)
+/** Configuration value is unknown. This indicates misconfiguration. */
+#define VERR_VD_UNKNOWN_CFG_VALUES                  (-3212)
+/** Interface is unknown. This indicates misconfiguration. */
+#define VERR_VD_UNKNOWN_INTERFACE                   (-3213)
+/** The DEK for disk encryption is missing. */
+#define VERR_VD_DEK_MISSING                         (-3214)
+/** The provided password to decrypt the DEK was incorrect. */
+#define VERR_VD_PASSWORD_INCORRECT                  (-3215)
+/** Generic: Invalid image file header. Use this for plugins. */
+#define VERR_VD_GEN_INVALID_HEADER                  (-3220)
+/** VDI: Invalid image file header. */
+#define VERR_VD_VDI_INVALID_HEADER                  (-3230)
+/** VDI: Invalid image file header: invalid signature. */
+#define VERR_VD_VDI_INVALID_SIGNATURE               (-3231)
+/** VDI: Invalid image file header: invalid version. */
+#define VERR_VD_VDI_UNSUPPORTED_VERSION             (-3232)
+/** Comment string is too long. */
+#define VERR_VD_VDI_COMMENT_TOO_LONG                (-3233)
+/** VMDK: Invalid image file header. */
+#define VERR_VD_VMDK_INVALID_HEADER                 (-3240)
+/** VMDK: Invalid image file header: invalid version. */
+#define VERR_VD_VMDK_UNSUPPORTED_VERSION            (-3241)
+/** VMDK: Image property not found. */
+#define VERR_VD_VMDK_VALUE_NOT_FOUND                (-3242)
+/** VMDK: Operation can't be done in current image state. */
+#define VERR_VD_VMDK_INVALID_STATE                  (-3243)
+/** VMDK: Format is invalid/inconsistent. */
+#define VERR_VD_VMDK_INVALID_FORMAT                 (-3244)
+/** VMDK: Invalid write position. */
+#define VERR_VD_VMDK_INVALID_WRITE                  (-3245)
+/** iSCSI: Invalid header, i.e. dummy for validity check. */
+#define VERR_VD_ISCSI_INVALID_HEADER                (-3250)
+/** iSCSI: Operation can't be done in current image state. */
+#define VERR_VD_ISCSI_INVALID_STATE                 (-3251)
+/** iSCSI: Invalid device type (not a disk). */
+#define VERR_VD_ISCSI_INVALID_TYPE                  (-3252)
+/** iSCSI: Initiator secret not decrypted */
+#define VERR_VD_ISCSI_SECRET_ENCRYPTED              (-3253)
+/** VHD: Invalid image file header. */
+#define VERR_VD_VHD_INVALID_HEADER                  (-3260)
+/** Parallels HDD: Invalid image file header. */
+#define VERR_VD_PARALLELS_INVALID_HEADER            (-3265)
+/** DMG: Invalid image file header. */
+#define VERR_VD_DMG_INVALID_HEADER                  (-3267)
+/** Raw: Invalid image file header. */
+#define VERR_VD_RAW_INVALID_HEADER                  (-3270)
+/** Raw: Invalid image file type. */
+#define VERR_VD_RAW_INVALID_TYPE                    (-3271)
+/** The backend needs more metadata before it can continue. */
+#define VERR_VD_NOT_ENOUGH_METADATA                 (-3272)
+/** Halt the current I/O context until further notification from the backend. */
+#define VERR_VD_IOCTX_HALT                          (-3273)
+/** The disk has a cache attached already. */
+#define VERR_VD_CACHE_ALREADY_EXISTS                (-3274)
+/** There is no cache attached to the disk. */
+#define VERR_VD_CACHE_NOT_FOUND                     (-3275)
+/** The cache is not up to date with the image. */
+#define VERR_VD_CACHE_NOT_UP_TO_DATE                (-3276)
+/** The given range does not meet the required alignment. */
+#define VERR_VD_DISCARD_ALIGNMENT_NOT_MET           (-3277)
+/** The discard operation is not supported for this image. */
+#define VERR_VD_DISCARD_NOT_SUPPORTED               (-3278)
+/** The image is the correct format but is corrupted. */
+#define VERR_VD_IMAGE_CORRUPTED                     (-3279)
+/** Repairing the image is not supported. */
+#define VERR_VD_IMAGE_REPAIR_NOT_SUPPORTED          (-3280)
+/** Repairing the image is not possible because the corruption is to severe. */
+#define VERR_VD_IMAGE_REPAIR_IMPOSSIBLE             (-3281)
+/** Reading from the image was not possible because the offset is out of the image range.
+ * This usually indicates that there is a minor corruption in the image meta data. */
+#define VERR_VD_READ_OUT_OF_RANGE                   (-3282)
+/** Block read was marked as free in the image and returned as a zero block. */
+#define VINF_VD_NEW_ZEROED_BLOCK                    3283
+/** Unable to parse the XML in DMG file. */
+#define VERR_VD_DMG_XML_PARSE_ERROR                 (-3284)
+/** Unable to locate a usable DMG file within the XAR archive. */
+#define VERR_VD_DMG_NOT_FOUND_INSIDE_XAR            (-3285)
+/** The size of the raw image is not dividable by 512 */
+#define VERR_VD_RAW_SIZE_MODULO_512                 (-3286)
+/** The size of the raw image is not dividable by 2048 */
+#define VERR_VD_RAW_SIZE_MODULO_2048                (-3287)
+/** The size of the raw optical image is too small (<= 32K) */
+#define VERR_VD_RAW_SIZE_OPTICAL_TOO_SMALL          (-3288)
+/** The size of the raw floppy image is too big (>2.88MB) */
+#define VERR_VD_RAW_SIZE_FLOPPY_TOO_BIG             (-3289)
+
+/** @} */
+
+
+/** @name VBox Guest Library (VBGL) Status Codes
+ * @{
+ */
+/** Library was not initialized. */
+#define VERR_VBGL_NOT_INITIALIZED                   (-3300)
+/** Virtual address was not allocated by the library. */
+#define VERR_VBGL_INVALID_ADDR                      (-3301)
+/** IOCtl to VBoxGuest driver failed. */
+#define VERR_VBGL_IOCTL_FAILED                      (-3302)
+/** @} */
+
+
+/** @name VBox USB (VUSB) Status Codes
+ * @{
+ */
+/** No available ports on the hub.
+ * This error is returned when a device is attempted created and/or attached
+ * to a hub which is out of ports. */
+#define VERR_VUSB_NO_PORTS                          (-3400)
+/** The requested operation cannot be performed on a detached USB device. */
+#define VERR_VUSB_DEVICE_NOT_ATTACHED               (-3401)
+/** Failed to allocate memory for a URB. */
+#define VERR_VUSB_NO_URB_MEMORY                     (-3402)
+/** General failure during URB queuing.
+ * This will go away when the queueing gets proper status code handling. */
+#define VERR_VUSB_FAILED_TO_QUEUE_URB               (-3403)
+/** Device creation failed because the USB device name was not found. */
+#define VERR_VUSB_DEVICE_NAME_NOT_FOUND             (-3404)
+/** Not permitted to open the USB device.
+ * The user doesn't have access to the device in the usbfs, check the mount options. */
+#define VERR_VUSB_USBFS_PERMISSION                  (-3405)
+/** The requested operation cannot be performed because the device
+ * is currently being reset. */
+#define VERR_VUSB_DEVICE_IS_RESETTING               (-3406)
+/** The requested operation cannot be performed because the device
+ * is currently suspended. */
+#define VERR_VUSB_DEVICE_IS_SUSPENDED               (-3407)
+/** Not permitted to open the USB device.
+ * The user doesn't have access to the device node, check group memberships. */
+#define VERR_VUSB_USB_DEVICE_PERMISSION             (-3408)
+/** @} */
+
+
+/** @name VBox VGA Status Codes
+ * @{
+ */
+/** One of the custom modes was incorrect.
+ * The format or bit count of the custom mode value is invalid. */
+#define VERR_VGA_INVALID_CUSTOM_MODE                (-3500)
+/** The display connector is resizing. */
+#define VINF_VGA_RESIZE_IN_PROGRESS                 (3501)
+/** @} */
+
+
+/** @name Internal Networking Status Codes
+ * @{
+ */
+/** The networking interface to filter was not found. */
+#define VERR_INTNET_FLT_IF_NOT_FOUND                (-3600)
+/** The networking interface to filter was busy (used by someone). */
+#define VERR_INTNET_FLT_IF_BUSY                     (-3601)
+/** Failed to create or connect to a networking interface filter. */
+#define VERR_INTNET_FLT_IF_FAILED                   (-3602)
+/** The network already exists with a different trunk configuration. */
+#define VERR_INTNET_INCOMPATIBLE_TRUNK              (-3603)
+/** The network already exists with a different security profile (restricted / public). */
+#define VERR_INTNET_INCOMPATIBLE_FLAGS              (-3604)
+/** Failed to create a virtual network interface instance. */
+#define VERR_INTNET_FLT_VNIC_CREATE_FAILED          (-3605)
+/** Failed to retrieve a virtual network interface link ID. */
+#define VERR_INTNET_FLT_VNIC_LINK_ID_NOT_FOUND      (-3606)
+/** Failed to initialize a virtual network interface instance. */
+#define VERR_INTNET_FLT_VNIC_INIT_FAILED            (-3607)
+/** Failed to open a virtual network interface instance. */
+#define VERR_INTNET_FLT_VNIC_OPEN_FAILED            (-3608)
+/** Failed to retrieve underlying (lower mac) link. */
+#define VERR_INTNET_FLT_LOWER_LINK_INFO_NOT_FOUND   (-3609)
+/** Failed to open underlying link instance. */
+#define VERR_INTNET_FLT_LOWER_LINK_OPEN_FAILED      (-3610)
+/** Failed to get underlying link ID. */
+#define VERR_INTNET_FLT_LOWER_LINK_ID_NOT_FOUND     (-3611)
+/** @} */
+
+
+/** @name Support Driver Status Codes
+ * @{
+ */
+/** The component factory was not found. */
+#define VERR_SUPDRV_COMPONENT_NOT_FOUND             (-3700)
+/** The component factories do not support the requested interface. */
+#define VERR_SUPDRV_INTERFACE_NOT_SUPPORTED         (-3701)
+/** The service module was not found. */
+#define VERR_SUPDRV_SERVICE_NOT_FOUND               (-3702)
+/** The host kernel is too old. */
+#define VERR_SUPDRV_KERNEL_TOO_OLD_FOR_VTX          (-3703)
+/** Bad VTG magic value.  */
+#define VERR_SUPDRV_VTG_MAGIC                       (-3704)
+/** Bad VTG bit count value.  */
+#define VERR_SUPDRV_VTG_BITS                        (-3705)
+/** Bad VTG header - misc.  */
+#define VERR_SUPDRV_VTG_BAD_HDR_MISC                (-3706)
+/** Bad VTG header - offset.  */
+#define VERR_SUPDRV_VTG_BAD_HDR_OFF                 (-3707)
+/** Bad VTG header - offset.  */
+#define VERR_SUPDRV_VTG_BAD_HDR_PTR                 (-3708)
+/** Bad VTG header - to low value.  */
+#define VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW             (-3709)
+/** Bad VTG header - to high value.  */
+#define VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH            (-3710)
+/** Bad VTG header - size value is not a multiple of the structure size. */
+#define VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE        (-3711)
+/** Bad VTG string table offset. */
+#define VERR_SUPDRV_VTG_STRTAB_OFF                  (-3712)
+/** Bad VTG string. */
+#define VERR_SUPDRV_VTG_BAD_STRING                  (-3713)
+/** VTG string is too long. */
+#define VERR_SUPDRV_VTG_STRING_TOO_LONG             (-3714)
+/** Bad VTG attribute value. */
+#define VERR_SUPDRV_VTG_BAD_ATTR                    (-3715)
+/** Bad VTG provider descriptor. */
+#define VERR_SUPDRV_VTG_BAD_PROVIDER                (-3716)
+/** Bad VTG probe descriptor. */
+#define VERR_SUPDRV_VTG_BAD_PROBE                   (-3717)
+/** Bad VTG argument list descriptor. */
+#define VERR_SUPDRV_VTG_BAD_ARGLIST                 (-3718)
+/** Bad VTG probe enabled data. */
+#define VERR_SUPDRV_VTG_BAD_PROBE_ENABLED           (-3719)
+/** Bad VTG probe location record. */
+#define VERR_SUPDRV_VTG_BAD_PROBE_LOC               (-3720)
+/** The VTG object for the session or image has already been registered. */
+#define VERR_SUPDRV_VTG_ALREADY_REGISTERED          (-3721)
+/** A driver may only register one VTG object per session. */
+#define VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION       (-3722)
+/** A tracer has already been registered. */
+#define VERR_SUPDRV_TRACER_ALREADY_REGISTERED       (-3723)
+/** The session has no tracer associated with it. */
+#define VERR_SUPDRV_TRACER_NOT_REGISTERED           (-3724)
+/** The tracer has already been opened in this sesssion. */
+#define VERR_SUPDRV_TRACER_ALREADY_OPENED           (-3725)
+/** The tracer has not been opened. */
+#define VERR_SUPDRV_TRACER_NOT_OPENED               (-3726)
+/** There is no tracer present. */
+#define VERR_SUPDRV_TRACER_NOT_PRESENT              (-3727)
+/** The tracer is unloading. */
+#define VERR_SUPDRV_TRACER_UNLOADING                (-3728)
+/** Another thread in the session is talking to the tracer.  */
+#define VERR_SUPDRV_TRACER_SESSION_BUSY             (-3729)
+/** The tracer cannot open it self in the same session. */
+#define VERR_SUPDRV_TRACER_CANNOT_OPEN_SELF         (-3730)
+/** Bad argument flags. */
+#define VERR_SUPDRV_TRACER_BAD_ARG_FLAGS            (-3731)
+/** The session has reached the max number of (user mode) providers. */
+#define VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS       (-3732)
+/** The tracepoint provider object is too large. */
+#define VERR_SUPDRV_TRACER_TOO_LARGE                (-3733)
+/** The probe location array isn't adjacent to the probe enable array. */
+#define VERR_SUPDRV_TRACER_UMOD_NOT_ADJACENT        (-3734)
+/** The user mode tracepoint provider has too many probe locations and
+ * probes. */
+#define VERR_SUPDRV_TRACER_UMOD_TOO_MANY_PROBES     (-3735)
+/** The user mode tracepoint provider string table is too large. */
+#define VERR_SUPDRV_TRACER_UMOD_STRTAB_TOO_BIG      (-3736)
+/** The user mode tracepoint provider string table offset is bad. */
+#define VERR_SUPDRV_TRACER_UMOD_STRTAB_OFF_BAD      (-3737)
+/** The VM process was denied access to vboxdrv because someone have managed to
+ * open the process or its main thread with too broad access rights. */
+#define VERR_SUPDRV_HARDENING_EVIL_HANDLE           (-3738)
+/** Error opening the ApiPort LPC object. */
+#define VERR_SUPDRV_APIPORT_OPEN_ERROR              (-3739)
+/** Error enumerating all processes in the session. */
+#define VERR_SUPDRV_SESSION_PROCESS_ENUM_ERROR      (-3740)
+/** The CSRSS instance associated with the client process could not be
+ * located. */
+#define VERR_SUPDRV_CSRSS_NOT_FOUND                 (-3741)
+/** Type error opening the ApiPort LPC object. */
+#define VERR_SUPDRV_APIPORT_OPEN_ERROR_TYPE         (-3742)
+/** Failed to measure the TSC delta between two CPUs. */
+#define VERR_SUPDRV_TSC_DELTA_MEASUREMENT_FAILED    (-3743)
+/** Failed to calculate the TSC frequency. */
+#define VERR_SUPDRV_TSC_FREQ_MEASUREMENT_FAILED     (-3744)
+/** Failed to get the delta-adjusted TSC value. */
+#define VERR_SUPDRV_TSC_READ_FAILED                 (-3745)
+/** Failed to measure the TSC delta between two CPUs, continue without any
+ *  TSC-delta. */
+#define VWRN_SUPDRV_TSC_DELTA_MEASUREMENT_FAILED     3746
+/** A TSC-delta measurement request is currently being serviced. */
+#define VERR_SUPDRV_TSC_DELTA_MEASUREMENT_BUSY      (-3747)
+/** The process trying to open VBoxDrv is not a budding VM process (1). */
+#define VERR_SUPDRV_NOT_BUDDING_VM_PROCESS_1        (-3748)
+/** The process trying to open VBoxDrv is not a budding VM process (2). */
+#define VERR_SUPDRV_NOT_BUDDING_VM_PROCESS_2        (-3749)
+/** @} */
+
+
+/** @name Support Library Status Codes
+ * @{
+ */
+/** The specified path was not absolute (hardening). */
+#define VERR_SUPLIB_PATH_NOT_ABSOLUTE               (-3750)
+/** The specified path was not clean (hardening). */
+#define VERR_SUPLIB_PATH_NOT_CLEAN                  (-3751)
+/** The specified path is too long (hardening). */
+#define VERR_SUPLIB_PATH_TOO_LONG                   (-3752)
+/** The specified path is too short (hardening). */
+#define VERR_SUPLIB_PATH_TOO_SHORT                  (-3753)
+/** The specified path has too many components (hardening). */
+#define VERR_SUPLIB_PATH_TOO_MANY_COMPONENTS        (-3754)
+/** The specified path is a root path (hardening). */
+#define VERR_SUPLIB_PATH_IS_ROOT                    (-3755)
+/** Failed to enumerate directory (hardening). */
+#define VERR_SUPLIB_DIR_ENUM_FAILED                 (-3756)
+/** Failed to stat a file/dir during enumeration (hardening). */
+#define VERR_SUPLIB_STAT_ENUM_FAILED                (-3757)
+/** Failed to stat a file/dir (hardening). */
+#define VERR_SUPLIB_STAT_FAILED                     (-3758)
+/** Failed to fstat a native handle (hardening). */
+#define VERR_SUPLIB_FSTAT_FAILED                    (-3759)
+/** Found an illegal symbolic link (hardening). */
+#define VERR_SUPLIB_SYMLINKS_ARE_NOT_PERMITTED      (-3760)
+/** Found something which isn't a file nor a directory (hardening). */
+#define VERR_SUPLIB_NOT_DIR_NOT_FILE                (-3761)
+/** The specified path is a directory and not a file (hardening). */
+#define VERR_SUPLIB_IS_DIRECTORY                    (-3762)
+/** The specified path is a file and not a directory (hardening). */
+#define VERR_SUPLIB_IS_FILE                         (-3763)
+/** The path is not the same object as the native handle (hardening). */
+#define VERR_SUPLIB_NOT_SAME_OBJECT                 (-3764)
+/** The owner is not root (hardening). */
+#define VERR_SUPLIB_OWNER_NOT_ROOT                  (-3765)
+/** The group is a non-system group and it has write access (hardening). */
+#define VERR_SUPLIB_WRITE_NON_SYS_GROUP             (-3766)
+/** The file or directory is world writable (hardening). */
+#define VERR_SUPLIB_WORLD_WRITABLE                  (-3767)
+/** The argv[0] of an internal application does not match the executable image
+ * path (hardening). */
+#define VERR_SUPLIB_INVALID_ARGV0_INTERNAL          (-3768)
+/** The internal application does not reside in the correct place (hardening). */
+#define VERR_SUPLIB_INVALID_INTERNAL_APP_DIR        (-3769)
+/** Unable to establish trusted of VM process (0). */
+#define VERR_SUPLIB_NT_PROCESS_UNTRUSTED_0          (-3770)
+/** Unable to establish trusted of VM process (1). */
+#define VERR_SUPLIB_NT_PROCESS_UNTRUSTED_1          (-3771)
+/** Unable to establish trusted of VM process (2). */
+#define VERR_SUPLIB_NT_PROCESS_UNTRUSTED_2          (-3772)
+/** Unable to establish trusted of VM process (3). */
+#define VERR_SUPLIB_NT_PROCESS_UNTRUSTED_3          (-3773)
+/** Unable to establish trusted of VM process (4). */
+#define VERR_SUPLIB_NT_PROCESS_UNTRUSTED_4          (-3774)
+/** Unable to establish trusted of VM process (5). */
+#define VERR_SUPLIB_NT_PROCESS_UNTRUSTED_5          (-3775)
+/** Unable to make text memory writeable (hardening). */
+#define VERR_SUPLIB_TEXT_NOT_WRITEABLE              (-3776)
+/** Unable to seal text memory again to protect against write access (hardening). */
+#define VERR_SUPLIB_TEXT_NOT_SEALED                 (-3777)
+/** Unexpected instruction encountered for which there is no patch strategy
+ * implemented (hardening). */
+#define VERR_SUPLIB_UNEXPECTED_INSTRUCTION          (-3778)
+/** @} */
+
+
+/** @name VBox GMM Status Codes
+ * @{
+ */
+/** The GMM is out of pages and needs to be give another chunk of user memory that
+ * it can lock down and borrow pages from. */
+#define VERR_GMM_SEED_ME                            (-3800)
+/** Unable to allocate more pages from the host system. */
+#define VERR_GMM_OUT_OF_MEMORY                      (-3801)
+/** Hit the global allocation limit.
+ * If you know there is still sufficient memory available, try raising the limit. */
+#define VERR_GMM_HIT_GLOBAL_LIMIT                   (-3802)
+/** Hit the a VM account limit. */
+#define VERR_GMM_HIT_VM_ACCOUNT_LIMIT               (-3803)
+/** Attempt to free more memory than what was previously allocated. */
+#define VERR_GMM_ATTEMPT_TO_FREE_TOO_MUCH           (-3804)
+/** Attempted to report too many pages as deflated.  */
+#define VERR_GMM_ATTEMPT_TO_DEFLATE_TOO_MUCH        (-3805)
+/** The page to be freed or updated was not found. */
+#define VERR_GMM_PAGE_NOT_FOUND                     (-3806)
+/** The specified shared page was not actually private. */
+#define VERR_GMM_PAGE_NOT_PRIVATE                   (-3807)
+/** The specified shared page was not actually shared. */
+#define VERR_GMM_PAGE_NOT_SHARED                    (-3808)
+/** The page to be freed was already freed. */
+#define VERR_GMM_PAGE_ALREADY_FREE                  (-3809)
+/** The page to be updated or freed was noted owned by the caller. */
+#define VERR_GMM_NOT_PAGE_OWNER                     (-3810)
+/** The specified chunk was not found. */
+#define VERR_GMM_CHUNK_NOT_FOUND                    (-3811)
+/** The chunk has already been mapped into the process. */
+#define VERR_GMM_CHUNK_ALREADY_MAPPED               (-3812)
+/** The chunk to be unmapped isn't actually mapped into the process. */
+#define VERR_GMM_CHUNK_NOT_MAPPED                   (-3813)
+/** The chunk has been mapped too many times already (impossible). */
+#define VERR_GMM_TOO_MANY_CHUNK_MAPPINGS            (-3814)
+/** The reservation or reservation update was declined - too many VMs, too
+ * little memory, and/or too low GMM configuration. */
+#define VERR_GMM_MEMORY_RESERVATION_DECLINED        (-3815)
+/** A GMM sanity check failed. */
+#define VERR_GMM_IS_NOT_SANE                        (-3816)
+/** Inserting a new chunk failed. */
+#define VERR_GMM_CHUNK_INSERT                       (-3817)
+/** Failed to obtain the GMM instance. */
+#define VERR_GMM_INSTANCE                           (-3818)
+/** Bad mutex semaphore flags. */
+#define VERR_GMM_MTX_FLAGS                          (-3819)
+/** Internal processing error in the page allocator. */
+#define VERR_GMM_ALLOC_PAGES_IPE                    (-3820)
+/** Invalid page count given to GMMR3FreePagesPerform.  */
+#define VERR_GMM_ACTUAL_PAGES_IPE                   (-3821)
+/** The shared module name is too long. */
+#define VERR_GMM_MODULE_NAME_TOO_LONG               (-3822)
+/** The shared module version string is too long. */
+#define VERR_GMM_MODULE_VERSION_TOO_LONG            (-3823)
+/** The shared module has too many regions. */
+#define VERR_GMM_TOO_MANY_REGIONS                   (-3824)
+/** The guest has reported too many modules. */
+#define VERR_GMM_TOO_MANY_PER_VM_MODULES            (-3825)
+/** The guest has reported too many modules. */
+#define VERR_GMM_TOO_MANY_GLOBAL_MODULES            (-3826)
+/** The shared module is already registered. */
+#define VINF_GMM_SHARED_MODULE_ALREADY_REGISTERED   (3827)
+/** The shared module clashed address wise with a previously registered
+ * module. */
+#define VERR_GMM_SHARED_MODULE_ADDRESS_CLASH        (-3828)
+/** The shared module was not found. */
+#define VERR_GMM_SHARED_MODULE_NOT_FOUND            (-3829)
+/** The size of the shared module was out of range. */
+#define VERR_GMM_BAD_SHARED_MODULE_SIZE             (-3830)
+/** The size of the one or more regions in the shared module was out of
+ * range. */
+#define VERR_GMM_SHARED_MODULE_BAD_REGIONS_SIZE     (-3831)
+/** @} */
+
+
+/** @name VBox GVM Status Codes
+ * @{
+ */
+/** The GVM is out of VM handle space. */
+#define VERR_GVM_TOO_MANY_VMS                       (-3900)
+/** The EMT was not blocked at the time of the call.  */
+#define VINF_GVM_NOT_BLOCKED                        3901
+/** The EMT was not busy running guest code at the time of the call. */
+#define VINF_GVM_NOT_BUSY_IN_GC                     3902
+/** RTThreadYield was called during a GVMMR0SchedPoll call. */
+#define VINF_GVM_YIELDED                            3903
+/** @} */
+
+
+/** @name VBox VMX Status Codes
+ * @{
+ */
+/** VMXON failed; possibly because it was already run before. */
+#define VERR_VMX_VMXON_FAILED                       (-4000)
+/** Invalid VMCS pointer.
+ * (Can be OR'ed with VERR_VMX_INVALID_VMCS_FIELD.) */
+#define VERR_VMX_INVALID_VMCS_PTR                   (-4001)
+/** Invalid VMCS index or write to read-only element. */
+#define VERR_VMX_INVALID_VMCS_FIELD                 (-4002)
+/** Reserved for future status code that we wish to OR with
+ *  VERR_VMX_INVALID_VMCS_PTR and VERR_VMX_INVALID_VMCS_FIELD. */
+#define VERR_VMX_RESERVED                           (-4003)
+/** Invalid VMXON pointer. */
+#define VERR_VMX_INVALID_VMXON_PTR                  (-4004)
+/** Unable to start VM execution. */
+#define VERR_VMX_UNABLE_TO_START_VM                 (-4005)
+/** Unable to switch due to invalid host state. */
+#define VERR_VMX_INVALID_HOST_STATE                 (-4006)
+/** IA32_FEATURE_CONTROL MSR not setup correcty (turn on VMX in the host system BIOS) */
+#define VERR_VMX_ILLEGAL_FEATURE_CONTROL_MSR        (-4007)
+/** Invalid CPU mode for VMX execution. */
+#define VERR_VMX_UNSUPPORTED_MODE                   (-4008)
+/** VMX CPU extension not available */
+#define VERR_VMX_NO_VMX                             (-4009)
+/** CPU was incorrectly left in VMX root mode; incompatible with VirtualBox */
+#define VERR_VMX_IN_VMX_ROOT_MODE                   (-4011)
+/** Somebody cleared X86_CR4_VMXE in the CR4 register. */
+#define VERR_VMX_X86_CR4_VMXE_CLEARED               (-4012)
+/** Failed to enable and lock VT-x features. */
+#define VERR_VMX_MSR_LOCKING_FAILED                 (-4013)
+/** Unable to switch due to invalid guest state. */
+#define VERR_VMX_INVALID_GUEST_STATE                (-4014)
+/** Unexpected VM exit. */
+#define VERR_VMX_UNEXPECTED_EXIT                    (-4015)
+/** Unexpected VM exception. */
+#define VERR_VMX_UNEXPECTED_EXCEPTION               (-4016)
+/** Unexpected interruption exit type. */
+#define VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE  (-4017)
+/** CPU is not in VMX root mode; unexpected when leaving VMX root mode. */
+#define VERR_VMX_NOT_IN_VMX_ROOT_MODE               (-4018)
+/** Undefined VM exit code. */
+#define VERR_VMX_UNDEFINED_EXIT_CODE                (-4019)
+/** VMPTRLD failed; possibly because of invalid VMCS launch-state. */
+#define VERR_VMX_VMPTRLD_FAILED                     (-4021)
+/** Invalid VMCS pointer passed to VMLAUNCH/VMRESUME. */
+#define VERR_VMX_INVALID_VMCS_PTR_TO_START_VM       (-4022)
+/** Internal VMX processing error no 1. */
+#define VERR_VMX_IPE_1                              (-4023)
+/** Internal VMX processing error no 2. */
+#define VERR_VMX_IPE_2                              (-4024)
+/** Internal VMX processing error no 3. */
+#define VERR_VMX_IPE_3                              (-4025)
+/** Internal VMX processing error no 4. */
+#define VERR_VMX_IPE_4                              (-4026)
+/** Internal VMX processing error no 5. */
+#define VERR_VMX_IPE_5                              (-4027)
+/** VT-x features for all modes (SMX and non-SMX) disabled by the BIOS. */
+#define VERR_VMX_MSR_ALL_VMX_DISABLED               (-4028)
+/** VT-x features disabled by the BIOS. */
+#define VERR_VMX_MSR_VMX_DISABLED                   (-4029)
+/** VM-Entry Controls internal cache invalid. */
+#define VERR_VMX_ENTRY_CTLS_CACHE_INVALID           (-4030)
+/** VM-Exit Controls internal cache invalid. */
+#define VERR_VMX_EXIT_CTLS_CACHE_INVALID            (-4031)
+/** VM-Execution Pin-based Controls internal cache invalid. */
+#define VERR_VMX_PIN_EXEC_CTLS_CACHE_INVALID        (-4032)
+/** VM-Execution Primary Processor-based Controls internal cache
+ *  invalid. */
+#define VERR_VMX_PROC_EXEC_CTLS_CACHE_INVALID       (-4033)
+/** VM-Execution Secondary Processor-based Controls internal
+ *  cache invalid. */
+#define VERR_VMX_PROC_EXEC2_CTLS_CACHE_INVALID      (-4034)
+/** Failed to set VMXON enable bit while enabling VT-x through the MSR. */
+#define VERR_VMX_MSR_VMX_ENABLE_FAILED              (-4035)
+/** Failed to enable VMXON-in-SMX bit while enabling VT-x through the MSR. */
+#define VERR_VMX_MSR_SMX_VMX_ENABLE_FAILED          (-4036)
+/** @} */
+
+
+/** @name VBox SVM Status Codes
+ * @{
+ */
+/** Unable to start VM execution. */
+#define VERR_SVM_UNABLE_TO_START_VM                 (-4050)
+/** AMD-V bit not set in K6_EFER MSR */
+#define VERR_SVM_ILLEGAL_EFER_MSR                   (-4051)
+/** AMD-V CPU extension not available. */
+#define VERR_SVM_NO_SVM                             (-4052)
+/** AMD-V CPU extension disabled (by BIOS). */
+#define VERR_SVM_DISABLED                           (-4053)
+/** AMD-V CPU extension in-use. */
+#define VERR_SVM_IN_USE                             (-4054)
+/** Invalid pVMCB. */
+#define VERR_SVM_INVALID_PVMCB                      (-4055)
+/** Unexpected SVM exit. */
+#define VERR_SVM_UNEXPECTED_EXIT                    (-4056)
+/** Unexpected SVM exception exit. */
+#define VERR_SVM_UNEXPECTED_XCPT_EXIT               (-4057)
+/** Unexpected SVM patch type. */
+#define VERR_SVM_UNEXPECTED_PATCH_TYPE              (-4058)
+/** Unable to start VM execution due to an invalid guest state. */
+#define VERR_SVM_INVALID_GUEST_STATE                (-4059)
+/** Unknown or unrecognized SVM exit.  */
+#define VERR_SVM_UNKNOWN_EXIT                       (-4060)
+/** Internal SVM processing error no 1. */
+#define VERR_SVM_IPE_1                              (-4061)
+/** Internal SVM processing error no 2. */
+#define VERR_SVM_IPE_2                              (-4062)
+/** Internal SVM processing error no 3. */
+#define VERR_SVM_IPE_3                              (-4063)
+/** Internal SVM processing error no 4. */
+#define VERR_SVM_IPE_4                              (-4064)
+/** Internal SVM processing error no 5. */
+#define VERR_SVM_IPE_5                              (-4065)
+/** The nested-guest \#VMEXIT processing failed, initiate shutdown. */
+#define VERR_SVM_VMEXIT_FAILED                      (-4066)
+/** An operation caused a nested-guest SVM \#VMEXIT. */
+#define VINF_SVM_VMEXIT                              4067
+/** @} */
+
+
+/** @name VBox HM Status Codes
+ * @{
+ */
+/** Unable to start VM execution. */
+#define VERR_HM_UNKNOWN_CPU                         (-4100)
+/** No CPUID support. */
+#define VERR_HM_NO_CPUID                            (-4101)
+/** Host is about to go into suspend mode. */
+#define VERR_HM_SUSPEND_PENDING                     (-4102)
+/** Conflicting CFGM values. */
+#define VERR_HM_CONFIG_MISMATCH                     (-4103)
+/** Internal processing error in the HM init code. */
+#define VERR_HM_ALREADY_ENABLED_IPE                 (-4104)
+/** Unexpected MSR in the auto-load/store area.  */
+#define VERR_HM_UNEXPECTED_LD_ST_MSR                (-4105)
+/** No 32-bit to 64-bit switcher in place. */
+#define VERR_HM_NO_32_TO_64_SWITCHER                (-4106)
+/** HMR0Leave was called on the wrong CPU. */
+#define VERR_HM_WRONG_CPU                           (-4107)
+/** Internal processing error \#1 in the HM code.  */
+#define VERR_HM_IPE_1                               (-4108)
+/** Internal processing error \#2 in the HM code.  */
+#define VERR_HM_IPE_2                               (-4109)
+/** Wrong 32/64-bit switcher. */
+#define VERR_HM_WRONG_SWITCHER                      (-4110)
+/** Unknown I/O instruction. */
+#define VERR_HM_UNKNOWN_IO_INSTRUCTION              (-4111)
+/** Unsupported CPU feature combination. */
+#define VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO       (-4112)
+/** Internal processing error \#3 in the HM code.  */
+#define VERR_HM_IPE_3                               (-4113)
+/** Internal processing error \#4 in the HM code.  */
+#define VERR_HM_IPE_4                               (-4114)
+/** Internal processing error \#5 in the HM code.  */
+#define VERR_HM_IPE_5                               (-4115)
+/** Invalid HM64ON32OP value.  */
+#define VERR_HM_INVALID_HM64ON32OP                  (-4116)
+/** Resume guest execution after injecting a double-fault. */
+#define VINF_HM_DOUBLE_FAULT                        4117
+/** The requested nested-guest VM-exit intercept is not active or not in
+ *  nested-guest execution mode. */
+#define VINF_HM_INTERCEPT_NOT_ACTIVE                4118
+/** @} */
+
+
+/** @name VBox Disassembler Status Codes
+ * @{
+ */
+/** Invalid opcode byte(s) */
+#define VERR_DIS_INVALID_OPCODE                     (-4200)
+/** Generic failure during disassembly. */
+#define VERR_DIS_GEN_FAILURE                        (-4201)
+/** No read callback. */
+#define VERR_DIS_NO_READ_CALLBACK                   (-4202)
+/** Invalid Mod/RM. */
+#define VERR_DIS_INVALID_MODRM                      (-4203)
+/** Invalid parameter index. */
+#define VERR_DIS_INVALID_PARAMETER                  (-4204)
+/** The instruction is too long. */
+#define VERR_DIS_TOO_LONG_INSTR                     (-4206)
+/** @} */
+
+
+/** @name VBox Webservice Status Codes
+ * @{
+ */
+/** Authentication failed (ISessionManager::logon()) */
+#define VERR_WEB_NOT_AUTHENTICATED                  (-4300)
+/** Invalid format of managed object reference */
+#define VERR_WEB_INVALID_MANAGED_OBJECT_REFERENCE   (-4301)
+/** Invalid session ID in managed object reference */
+#define VERR_WEB_INVALID_SESSION_ID                 (-4302)
+/** Invalid object ID in managed object reference */
+#define VERR_WEB_INVALID_OBJECT_ID                  (-4303)
+/** Unsupported interface for managed object reference */
+#define VERR_WEB_UNSUPPORTED_INTERFACE              (-4304)
+/** @} */
+
+
+/** @name VBox PARAV Status Codes
+ * @{
+ */
+/** Switch back to host */
+#define VINF_PARAV_SWITCH_TO_HOST                   4400
+
+/** @} */
+
+/** @name VBox Video HW Acceleration command status
+ * @{
+ */
+/** command processing is pending, a completion handler will be called */
+#define VINF_VHWA_CMD_PENDING                       4500
+
+/** @} */
+
+
+/** @name VBox COM error codes
+ *
+ * @remarks Global::vboxStatusCodeToCOM and Global::vboxStatusCodeFromCOM uses
+ *          these for conversion that is lossless with respect to important COM
+ *          status codes.  These methods should be moved to the glue library.
+ * @{  */
+/** Unexpected turn of events. */
+#define VERR_COM_UNEXPECTED                         (-4600)
+/** The base of the VirtualBox COM status codes (the lower value)
+ * corresponding 1:1 to VBOX_E_XXX.  This is the lowest value. */
+#define VERR_COM_VBOX_LOWEST                        (-4699)
+/** Object corresponding to the supplied arguments does not exist. */
+#define VERR_COM_OBJECT_NOT_FOUND                   (VERR_COM_VBOX_LOWEST + 1)
+/** Current virtual machine state prevents the operation. */
+#define VERR_COM_INVALID_VM_STATE                   (VERR_COM_VBOX_LOWEST + 2)
+/** Virtual machine error occurred attempting the operation. */
+#define VERR_COM_VM_ERROR                           (VERR_COM_VBOX_LOWEST + 3)
+/** File not accessible or erroneous file contents. */
+#define VERR_COM_FILE_ERROR                         (VERR_COM_VBOX_LOWEST + 4)
+/** IPRT error. */
+#define VERR_COM_IPRT_ERROR                         (VERR_COM_VBOX_LOWEST + 5)
+/** Pluggable Device Manager error. */
+#define VERR_COM_PDM_ERROR                          (VERR_COM_VBOX_LOWEST + 6)
+/** Current object state prohibits operation. */
+#define VERR_COM_INVALID_OBJECT_STATE               (VERR_COM_VBOX_LOWEST + 7)
+/** Host operating system related error. */
+#define VERR_COM_HOST_ERROR                         (VERR_COM_VBOX_LOWEST + 8)
+/** Requested operation is not supported. */
+#define VERR_COM_NOT_SUPPORTED                      (VERR_COM_VBOX_LOWEST + 9)
+/** Invalid XML found. */
+#define VERR_COM_XML_ERROR                          (VERR_COM_VBOX_LOWEST + 10)
+/** Current session state prohibits operation. */
+#define VERR_COM_INVALID_SESSION_STATE              (VERR_COM_VBOX_LOWEST + 11)
+/** Object being in use prohibits operation. */
+#define VERR_COM_OBJECT_IN_USE                      (VERR_COM_VBOX_LOWEST + 12)
+/** Returned by callback methods which does not need to be called
+ * again because the client does not actually make use of them. */
+#define VERR_COM_DONT_CALL_AGAIN                    (VERR_COM_VBOX_LOWEST + 13)
+/** @} */
+
+/** @name VBox VMMDev Status codes
+ * @{
+ */
+/** CPU hotplug events from VMMDev are not monitored by the guest. */
+#define VERR_VMMDEV_CPU_HOTPLUG_NOT_MONITORED_BY_GUEST      (-4700)
+/** @} */
+
+/** @name VBox async I/O manager Status Codes
+ * @{
+ */
+/** Async I/O task is pending, a completion handler will be called. */
+#define VINF_AIO_TASK_PENDING                       4800
+/** @} */
+
+/** @name VBox Virtual SCSI Status Codes
+ * @{
+ */
+/** LUN type is not supported. */
+#define VERR_VSCSI_LUN_TYPE_NOT_SUPPORTED           (-4900)
+/** LUN is already/still attached to a device. */
+#define VERR_VSCSI_LUN_ATTACHED_TO_DEVICE           (-4901)
+/** The specified LUN is invalid. */
+#define VERR_VSCSI_LUN_INVALID                      (-4902)
+/** The LUN is not attached to the device. */
+#define VERR_VSCSI_LUN_NOT_ATTACHED                 (-4903)
+/** The LUN is still busy. */
+#define VERR_VSCSI_LUN_BUSY                         (-4904)
+/** @} */
+
+/** @name VBox FAM Status Codes
+ * @{
+ */
+/** FAM failed to open a connection. */
+#define VERR_FAM_OPEN_FAILED                        (-5000)
+/** FAM failed to add a file to the list to be monitored. */
+#define VERR_FAM_MONITOR_FILE_FAILED                (-5001)
+/** FAM failed to add a directory to the list to be monitored. */
+#define VERR_FAM_MONITOR_DIRECTORY_FAILED           (-5002)
+/** The connection to the FAM daemon was lost. */
+#define VERR_FAM_CONNECTION_LOST                    (-5003)
+/** @} */
+
+
+/** @name PCI Passtrhough Status Codes
+ * @{
+ */
+/** RamPreAlloc not set.
+ * RAM pre-allocation is currently a requirement for PCI passthrough. */
+#define VERR_PCI_PASSTHROUGH_NO_RAM_PREALLOC        (-5100)
+/** VT-x/AMD-V not active.
+ * PCI passthrough currently works only if VT-x/AMD-V is active. */
+#define VERR_PCI_PASSTHROUGH_NO_HM              (-5101)
+/** Nested paging not active.
+ * PCI passthrough currently works only if nested paging is active. */
+#define VERR_PCI_PASSTHROUGH_NO_NESTED_PAGING       (-5102)
+/** @} */
+
+
+/** @name GVMM Status Codes
+ * @{
+ */
+/** Internal error obtaining the GVMM instance. */
+#define VERR_GVMM_INSTANCE                          (-5200)
+/** GVMM does not support the range of CPUs present/possible on the host. */
+#define VERR_GVMM_HOST_CPU_RANGE                    (-5201)
+/** GVMM ran into some broken IPRT code. */
+#define VERR_GVMM_BROKEN_IPRT                       (-5202)
+/** Internal processing error \#1 in the GVMM code. */
+#define VERR_GVMM_IPE_1                             (-5203)
+/** Internal processing error \#2 in the GVMM code. */
+#define VERR_GVMM_IPE_2                             (-5204)
+/** @} */
+
+
+/** @name IEM Status Codes
+ * @{ */
+/** The instruction is not yet implemented by IEM. */
+#define VERR_IEM_INSTR_NOT_IMPLEMENTED              (-5300)
+/** Invalid operand size passed to an IEM function. */
+#define VERR_IEM_INVALID_OPERAND_SIZE               (-5301)
+/** Invalid address mode passed to an IEM function. */
+#define VERR_IEM_INVALID_ADDRESS_MODE               (-5302)
+/** Invalid effective segment register number passed to an IEM function. */
+#define VERR_IEM_INVALID_EFF_SEG                    (-5303)
+/** Invalid instruction length passed to an IEM function. */
+#define VERR_IEM_INVALID_INSTR_LENGTH               (-5304)
+/** Internal status code for indicating that a selector isn't valid (LAR, LSL,
+ *  VERR, VERW).  This is not used outside the instruction implementations. */
+#define VINF_IEM_SELECTOR_NOT_OK                    (5305)
+/** Restart the current instruction. For testing only. */
+#define VERR_IEM_RESTART_INSTRUCTION                (-5389)
+/** This particular aspect of the instruction is not yet implemented by IEM. */
+#define VERR_IEM_ASPECT_NOT_IMPLEMENTED             (-5390)
+/** Internal processing error \#1 in the IEM code. */
+#define VERR_IEM_IPE_1                              (-5391)
+/** Internal processing error \#2 in the IEM code. */
+#define VERR_IEM_IPE_2                              (-5392)
+/** Internal processing error \#3 in the IEM code. */
+#define VERR_IEM_IPE_3                              (-5393)
+/** Internal processing error \#4 in the IEM code. */
+#define VERR_IEM_IPE_4                              (-5394)
+/** Internal processing error \#5 in the IEM code. */
+#define VERR_IEM_IPE_5                              (-5395)
+/** Internal processing error \#6 in the IEM code. */
+#define VERR_IEM_IPE_6                              (-5396)
+/** Internal processing error \#7 in the IEM code. */
+#define VERR_IEM_IPE_7                              (-5397)
+/** Internal processing error \#8 in the IEM code. */
+#define VERR_IEM_IPE_8                              (-5398)
+/** Internal processing error \#9 in the IEM code. */
+#define VERR_IEM_IPE_9                              (-5399)
+/** @} */
+
+
+/** @name DBGC Status Codes
+ *  @{ */
+/** Status that causes DBGC to quit. */
+#define VERR_DBGC_QUIT                              (-5400)
+/** Async command pending. */
+#define VWRN_DBGC_CMD_PENDING                       5401
+/** The command has already been registered. */
+#define VWRN_DBGC_ALREADY_REGISTERED                5402
+/** The command cannot be deregistered because has not been registered.  */
+#define VERR_DBGC_COMMANDS_NOT_REGISTERED           (-5403)
+/** Unknown breakpoint.  */
+#define VERR_DBGC_BP_NOT_FOUND                      (-5404)
+/** The breakpoint already exists. */
+#define VERR_DBGC_BP_EXISTS                         (-5405)
+/** The breakpoint has no command. */
+#define VINF_DBGC_BP_NO_COMMAND                     5406
+/** Generic debugger command failure. */
+#define VERR_DBGC_COMMAND_FAILED                    (-5407)
+/** Logic bug in the DBGC code. */
+#define VERR_DBGC_IPE                               (-5408)
+
+/** The lowest parse status code.   */
+#define VERR_DBGC_PARSE_LOWEST                      (-5499)
+/** Syntax error - too few arguments. */
+#define VERR_DBGC_PARSE_TOO_FEW_ARGUMENTS           (VERR_DBGC_PARSE_LOWEST + 0)
+/** Syntax error - too many arguments. */
+#define VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS          (VERR_DBGC_PARSE_LOWEST + 1)
+/** Syntax error - too many arguments for static storage. */
+#define VERR_DBGC_PARSE_ARGUMENT_OVERFLOW           (VERR_DBGC_PARSE_LOWEST + 2)
+/** Syntax error - expected binary operator. */
+#define VERR_DBGC_PARSE_EXPECTED_BINARY_OP          (VERR_DBGC_PARSE_LOWEST + 3)
+
+/** Syntax error - the argument does not allow a range to be specified. */
+#define VERR_DBGC_PARSE_NO_RANGE_ALLOWED            (VERR_DBGC_PARSE_LOWEST + 5)
+/** Syntax error - unbalanced quotes. */
+#define VERR_DBGC_PARSE_UNBALANCED_QUOTE            (VERR_DBGC_PARSE_LOWEST + 6)
+/** Syntax error - unbalanced parenthesis. */
+#define VERR_DBGC_PARSE_UNBALANCED_PARENTHESIS      (VERR_DBGC_PARSE_LOWEST + 7)
+/** Syntax error - an argument or subargument contains nothing useful. */
+#define VERR_DBGC_PARSE_EMPTY_ARGUMENT              (VERR_DBGC_PARSE_LOWEST + 8)
+/** Syntax error - invalid operator usage. */
+#define VERR_DBGC_PARSE_UNEXPECTED_OPERATOR         (VERR_DBGC_PARSE_LOWEST + 9)
+/** Syntax error - invalid numeric value. */
+#define VERR_DBGC_PARSE_INVALID_NUMBER              (VERR_DBGC_PARSE_LOWEST + 10)
+/** Syntax error - numeric overflow. */
+#define VERR_DBGC_PARSE_NUMBER_TOO_BIG              (VERR_DBGC_PARSE_LOWEST + 11)
+/** Syntax error - invalid operation attempted. */
+#define VERR_DBGC_PARSE_INVALID_OPERATION           (VERR_DBGC_PARSE_LOWEST + 12)
+/** Syntax error - function not found. */
+#define VERR_DBGC_PARSE_FUNCTION_NOT_FOUND          (VERR_DBGC_PARSE_LOWEST + 13)
+/** Syntax error - the specified function is not a function. */
+#define VERR_DBGC_PARSE_NOT_A_FUNCTION              (VERR_DBGC_PARSE_LOWEST + 14)
+/** Syntax error - out of scratch memory. */
+#define VERR_DBGC_PARSE_NO_SCRATCH                  (VERR_DBGC_PARSE_LOWEST + 15)
+/** Syntax error - out of regular heap memory. */
+#define VERR_DBGC_PARSE_NO_MEMORY                   (VERR_DBGC_PARSE_LOWEST + 16)
+/** Syntax error - incorrect argument type. */
+#define VERR_DBGC_PARSE_INCORRECT_ARG_TYPE          (VERR_DBGC_PARSE_LOWEST + 17)
+/** Syntax error - an undefined variable was referenced. */
+#define VERR_DBGC_PARSE_VARIABLE_NOT_FOUND          (VERR_DBGC_PARSE_LOWEST + 18)
+/** Syntax error - a type conversion failed. */
+#define VERR_DBGC_PARSE_CONVERSION_FAILED           (VERR_DBGC_PARSE_LOWEST + 19)
+/** Syntax error - you hit a debugger feature which isn't implemented yet.
+ * (Feel free to help implement it.) */
+#define VERR_DBGC_PARSE_NOT_IMPLEMENTED             (VERR_DBGC_PARSE_LOWEST + 20)
+/** Syntax error - Couldn't satisfy a request for a specific result type. */
+#define VERR_DBGC_PARSE_BAD_RESULT_TYPE             (VERR_DBGC_PARSE_LOWEST + 21)
+/** Syntax error - Cannot read symbol value, it is a set-only symbol. */
+#define VERR_DBGC_PARSE_WRITEONLY_SYMBOL            (VERR_DBGC_PARSE_LOWEST + 22)
+/** Syntax error - Invalid command name. */
+#define VERR_DBGC_PARSE_INVALD_COMMAND_NAME         (VERR_DBGC_PARSE_LOWEST + 23)
+/** Syntax error - Command not found. */
+#define VERR_DBGC_PARSE_COMMAND_NOT_FOUND           (VERR_DBGC_PARSE_LOWEST + 24)
+/** Syntax error - buggy parser. */
+#define VERR_DBGC_PARSE_BUG                         (VERR_DBGC_PARSE_LOWEST + 25)
+/** @} */
+
+
+/** @name Support driver/library shared verification status codes.
+ * @{  */
+/** Process Verification Failure: The memory content does not match the image
+ *  file. */
+#define VERR_SUP_VP_MEMORY_VS_FILE_MISMATCH          (-5600)
+/** Process Verification Failure: The memory protection of a image file section
+ *  does not match what the section header prescribes. */
+#define VERR_SUP_VP_SECTION_PROTECTION_MISMATCH      (-5601)
+/** Process Verification Failure: One of the section in the image file is not
+ *  mapped into memory. */
+#define VERR_SUP_VP_SECTION_NOT_MAPPED               (-5602)
+/** Process Verification Failure: One of the section in the image file is not
+ *  fully mapped into memory. */
+#define VERR_SUP_VP_SECTION_NOT_FULLY_MAPPED         (-5603)
+/** Process Verification Failure: Bad file alignment value in image header. */
+#define VERR_SUP_VP_BAD_FILE_ALIGNMENT_VALUE         (-5604)
+/** Process Verification Failure: Bad image base in header. */
+#define VERR_SUP_VP_BAD_IMAGE_BASE                   (-5605)
+/** Process Verification Failure: Bad image signature. */
+#define VERR_SUP_VP_BAD_IMAGE_SIGNATURE              (-5606)
+/** Process Verification Failure: Bad image size. */
+#define VERR_SUP_VP_BAD_IMAGE_SIZE                   (-5607)
+/** Process Verification Failure: Bad new-header offset in the MZ header. */
+#define VERR_SUP_VP_BAD_MZ_OFFSET                    (-5608)
+/** Process Verification Failure: Bad optional header field. */
+#define VERR_SUP_VP_BAD_OPTIONAL_HEADER              (-5609)
+/** Process Verification Failure: Bad section alignment value in image
+ *  header. */
+#define VERR_SUP_VP_BAD_SECTION_ALIGNMENT_VALUE      (-5610)
+/** Process Verification Failure: Bad section raw data size. */
+#define VERR_SUP_VP_BAD_SECTION_FILE_SIZE            (-5611)
+/** Process Verification Failure: Bad virtual section address. */
+#define VERR_SUP_VP_BAD_SECTION_RVA                  (-5612)
+/** Process Verification Failure: Bad virtual section size. */
+#define VERR_SUP_VP_BAD_SECTION_VIRTUAL_SIZE         (-5613)
+/** Process Verification Failure: Bad size of image header. */
+#define VERR_SUP_VP_BAD_SIZE_OF_HEADERS              (-5614)
+/** Process Verification Failure: The process is being debugged. */
+#define VERR_SUP_VP_DEBUGGED                         (-5615)
+/** Process Verification Failure: A DLL was found more than once. */
+#define VERR_SUP_VP_DUPLICATE_DLL_MAPPING            (-5616)
+/** Process Verification Failure: Image section region is too large. */
+#define VERR_SUP_VP_EMPTY_REGION_TOO_LARGE           (-5617)
+/** Process Verification Failure: Executable file name and process image name
+ *  does not match up. */
+#define VERR_SUP_VP_EXE_VS_PROC_NAME_MISMATCH        (-5618)
+/** Process Verification Failure: Found executable memory allocated in the
+ *  process.  There is only supposed be executable memory associated with
+ *  image file mappings (DLLs & EXE). */
+#define VERR_SUP_VP_FOUND_EXEC_MEMORY                (-5619)
+/** Process Verification Failure: There is more than one known executable mapped
+ *  into the process. */
+#define VERR_SUP_VP_FOUND_MORE_THAN_ONE_EXE_MAPPING  (-5620)
+/** Process Verification Failure: Error closing image file handle. */
+#define VERR_SUP_VP_IMAGE_FILE_CLOSE_ERROR           (-5621)
+/** Process Verification Failure: Error opening image file. */
+#define VERR_SUP_VP_IMAGE_FILE_OPEN_ERROR            (-5622)
+/** Process Verification Failure: Error reading image file header. */
+#define VERR_SUP_VP_IMAGE_HDR_READ_ERROR             (-5623)
+/** Process Verification Failure: Image mapping is bogus as the first region
+ *  has different AllocationBase and BaseAddress values, indicating that a
+ *  section was unmapped or otherwise tampered with. */
+#define VERR_SUP_VP_IMAGE_MAPPING_BASE_ERROR         (-5624)
+/** Process Verification Failure: Error reading process memory for comparing
+ *  with disk data. */
+#define VERR_SUP_VP_MEMORY_READ_ERROR                (-5625)
+/** Process Verification Failure: Found no executable mapped into the process
+ *  address space. */
+#define VERR_SUP_VP_NO_FOUND_NO_EXE_MAPPING          (-5626)
+/** Process Verification Failure: An image mapping failed to report a name. */
+#define VERR_SUP_VP_NO_IMAGE_MAPPING_NAME            (-5627)
+/** Process Verification Failure: No KERNE32.DLL mapping found.  This is
+ *  impossible. */
+#define VERR_SUP_VP_NO_KERNEL32_MAPPING              (-5628)
+/** Process Verification Failure: Error allocating memory. */
+#define VERR_SUP_VP_NO_MEMORY                        (-5629)
+/** Process Verification Failure: Error allocating state memory or querying
+ *  the system32 path. */
+#define VERR_SUP_VP_NO_MEMORY_STATE                  (-5630)
+/** Process Verification Failure: No NTDLL.DLL mapping found.  This is
+ *  impossible. */
+#define VERR_SUP_VP_NO_NTDLL_MAPPING                 (-5631)
+/** Process Verification Failure: A DLL residing outside System32 was found
+ *  in the process. */
+#define VERR_SUP_VP_NON_SYSTEM32_DLL                 (-5632)
+/** Process Verification Failure: An unknown and unwanted DLL was found loaded
+ *  into the process. */
+#define VERR_SUP_VP_NOT_KNOWN_DLL_OR_EXE             (-5633)
+/** Process Verification Failure: The name of an image file changes between
+ *  mapping regions. */
+#define VERR_SUP_VP_NT_MAPPING_NAME_CHANGED          (-5634)
+/** Process Verification Failure: Error querying process name. */
+#define VERR_SUP_VP_NT_QI_PROCESS_NM_ERROR           (-5635)
+/** Process Verification Failure: Error querying thread information. */
+#define VERR_SUP_VP_NT_QI_THREAD_ERROR               (-5636)
+/** Process Verification Failure: Error query virtual memory information. */
+#define VERR_SUP_VP_NT_QI_VIRTUAL_MEMORY_ERROR       (-5637)
+/** Process Verification Failure: Error query virtual memory mapping name. */
+#define VERR_SUP_VP_NT_QI_VIRTUAL_MEMORY_NM_ERROR    (-5638)
+/** Process Verification Failure: Error determining the full path of
+ *  System32. */
+#define VERR_SUP_VP_SYSTEM32_PATH                    (-5639)
+/** Process Verification Failure: The process has more than one thread. */
+#define VERR_SUP_VP_THREAD_NOT_ALONE                 (-5640)
+/** Process Verification Failure: The image mapping is too large (>= 2GB). */
+#define VERR_SUP_VP_TOO_HIGH_REGION_RVA              (-5641)
+/** Process Verification Failure: The memory region is too large (>= 2GB). */
+#define VERR_SUP_VP_TOO_LARGE_REGION                 (-5642)
+/** Process Verification Failure: There are too many DLLs loaded. */
+#define VERR_SUP_VP_TOO_MANY_DLLS_LOADED             (-5643)
+/** Process Verification Failure: An image has too many regions. */
+#define VERR_SUP_VP_TOO_MANY_IMAGE_REGIONS           (-5644)
+/** Process Verification Failure: The process has too many virtual memory
+ *  regions. */
+#define VERR_SUP_VP_TOO_MANY_MEMORY_REGIONS          (-5645)
+/** Process Verification Failure: An image has too many sections. */
+#define VERR_SUP_VP_TOO_MANY_SECTIONS                (-5646)
+/** Process Verification Failure: An image is targeting an unexpected
+ *  machine/CPU. */
+#define VERR_SUP_VP_UNEXPECTED_IMAGE_MACHINE         (-5647)
+/** Process Verification Failure: Unexpected section protection flag
+ *  combination. */
+#define VERR_SUP_VP_UNEXPECTED_SECTION_FLAGS         (-5648)
+/** Process Verification Failure: Expected the process and exe to have forced
+ * integrity checking enabled (verifying signatures). */
+#define VERR_SUP_VP_EXE_MISSING_FORCE_INTEGRITY     (-5649)
+/** Process Verification Failure: Expected the process and exe to have dynamic
+ * base enabled. */
+#define VERR_SUP_VP_EXE_MISSING_DYNAMIC_BASE        (-5650)
+/** Process Verification Failure: Expected the process and exe to advertise
+ * NX compatibility. */
+#define VERR_SUP_VP_EXE_MISSING_NX_COMPAT           (-5651)
+/** Process Verification Failure: The DllCharacteristics of the process
+ * does not match the value in the optional header in the exe file. */
+#define VERR_SUP_VP_DLL_CHARECTERISTICS_MISMATCH    (-5652)
+/** Process Verification Failure: The ImageCharacteristics of the process
+ * does not match the value in the file header in the exe file. */
+#define VERR_SUP_VP_IMAGE_CHARECTERISTICS_MISMATCH  (-5653)
+/** Process Verification Failure: Error querying image information. */
+#define VERR_SUP_VP_NT_QI_PROCESS_IMG_INFO_ERROR    (-5654)
+/** Process Verification Failure: Error querying debug port. */
+#define VERR_SUP_VP_NT_QI_PROCESS_DBG_PORT_ERROR    (-5655)
+/** WinVerifyTrust failed with an unexpected status code when using the
+ * catalog-file approach. */
+#define VERR_SUP_VP_WINTRUST_CAT_FAILURE            (-5656)
+/** The image is required to be signed with the same certificate as the rest
+ * of VirtualBox. */
+#define VERR_SUP_VP_NOT_SIGNED_WITH_BUILD_CERT      (-5657)
+/** Internal processing error: Not build certificate. */
+#define VERR_SUP_VP_NOT_BUILD_CERT_IPE              (-5658)
+/** The image requires to be signed using the kernel-code signing process. */
+#define VERR_SUP_VP_NOT_VALID_KERNEL_CODE_SIGNATURE (-5659)
+/** Unexpected number of valid paths. */
+#define VERR_SUP_VP_UNEXPECTED_VALID_PATH_COUNT     (-5660)
+/** The image is required to force integrity checks. */
+#define VERR_SUP_VP_SIGNATURE_CHECKS_NOT_ENFORCED   (-5661)
+/** Process Verification Failure: Symantec Endpoint Protection must be
+ * disabled for the VirtualBox VM processes.
+ * http://www.symantec.com/connect/articles/creating-application-control-exclusions-symantec-endpoint-protection-121 */
+#define VERR_SUP_VP_SYSFER_DLL                      (-5662)
+/** Process Purification Failure: KERNE32.DLL already mapped into the initial
+ *  process (suspended). */
+#define VERR_SUP_VP_KERNEL32_ALREADY_MAPPED         (-5663)
+/** Process Purification Failure: NtFreeVirtualMemory failed on a chunk of
+ *  executable memory which shouldn't be present in the process. */
+#define VERR_SUP_VP_FREE_VIRTUAL_MEMORY_FAILED      (-5664)
+/** Process Purification Failure: Both NtUnmapViewOfSetion and
+ *  NtProtectVirtualMemory failed to get rid of or passify an non-image
+ *  executable mapping. */
+#define VERR_SUP_VP_UNMAP_AND_PROTECT_FAILED        (-5665)
+/** Process Purification Failure: Unknown memory type of executable memory.   */
+#define VERR_SUP_VP_UNKOWN_MEM_TYPE                 (-5666)
+/** The image file is not owned by TrustedInstaller is it should be. */
+#define VERR_SUP_VP_NOT_OWNED_BY_TRUSTED_INSTALLER  (-5667)
+/** The image is outside the expected range. */
+#define VERR_SUP_VP_IMAGE_TOO_BIG                   (-5668)
+/** Stub process not found so it cannot be revalidated when vboxdrv is opened
+ * by the VM process. */
+#define VERR_SUP_VP_STUB_NOT_FOUND                  (-5669)
+/** Error opening the stub process for revalidation when vboxdrv is opened by
+ *  the VM process. */
+#define VERR_SUP_VP_STUB_OPEN_ERROR                 (-5670)
+/** Stub process thread not found during revalidation upon vboxdrv opening by
+ * the VM process. */
+#define VERR_SUP_VP_STUB_THREAD_NOT_FOUND           (-5671)
+/** Error opening the stub process thread for revalidation when vboxdrv is
+ * opened by the VM process. */
+#define VERR_SUP_VP_STUB_THREAD_OPEN_ERROR          (-5672)
+/** Process Purification Failure: NtAllocateVirtualMemory failed to get us
+ * suitable replacement memory for a chunk of executable memory that
+ * shouldn't be present in our process.  (You will only see this message if you
+ * got potentially fatally buggy anti-virus software installed.) */
+#define VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED   (-5673)
+/** Error getting the file mode. */
+#define VERR_SUP_VP_FILE_MODE_ERROR                 (-5674)
+/** Error creating an event semaphore for used with asynchronous reads. */
+#define VERR_SUP_VP_CREATE_READ_EVT_SEM_FAILED      (-5675)
+/** Undesirable module. */
+#define VERR_SUP_VP_UNDESIRABLE_MODULE              (-5676)
+
+/** @} */
+
+/** @name VBox Extension Pack Status Codes
+ * @{
+ */
+/** The host is not supported. Uninstall the extension pack.
+ * Returned by the VBOXEXTPACKREG::pfnInstalled. */
+#define VERR_EXTPACK_UNSUPPORTED_HOST_UNINSTALL     (-6000)
+/** The VirtualBox version is not supported by one of the extension packs.
+ *
+ * You have probably upgraded VirtualBox recently.  Please upgrade the
+ * extension packs to versions compatible with this VirtualBox release.
+ */
+#define VERR_EXTPACK_VBOX_VERSION_MISMATCH          (-6001)
+/** @} */
+
+
+/** @name VBox Guest Control Status Codes
+ * @{
+ */
+/** Guest side reported an error. */
+#define VERR_GSTCTL_GUEST_ERROR                     (-6200)
+/** A guest control object has changed its overall status. */
+#define VWRN_GSTCTL_OBJECTSTATE_CHANGED             6220
+/** Guest process is in a wrong state. */
+#define VERR_GSTCTL_PROCESS_WRONG_STATE             (-6221)
+/** Started guest process terminated with an exit code <> 0. */
+#define VWRN_GSTCTL_PROCESS_EXIT_CODE               6221
+/** @} */
+
+
+/** @name GIM Status Codes
+ * @{
+ */
+/** No GIM provider is configured for this VM. */
+#define VERR_GIM_NOT_ENABLED                        (-6300)
+/** GIM internal processing error \#1. */
+#define VERR_GIM_IPE_1                              (-6301)
+/** GIM internal processing error \#2. */
+#define VERR_GIM_IPE_2                              (-6302)
+/** GIM internal processing error \#3. */
+#define VERR_GIM_IPE_3                              (-6303)
+/** The GIM provider does not support any paravirtualized TSC. */
+#define VERR_GIM_PVTSC_NOT_AVAILABLE                (-6304)
+/** The guest has not setup use of the paravirtualized TSC. */
+#define VERR_GIM_PVTSC_NOT_ENABLED                  (-6305)
+/** Unknown or invalid GIM provider. */
+#define VERR_GIM_INVALID_PROVIDER                   (-6306)
+/** GIM generic operation failed. */
+#define VERR_GIM_OPERATION_FAILED                   (-6307)
+/** The GIM provider does not support any hypercalls. */
+#define VERR_GIM_HYPERCALLS_NOT_AVAILABLE           (-6308)
+/** The guest has not setup use of the hypercalls. */
+#define VERR_GIM_HYPERCALLS_NOT_ENABLED             (-6309)
+/** The GIM device is not registered with GIM when it ought to be. */
+#define VERR_GIM_DEVICE_NOT_REGISTERED              (-6310)
+/** Hypercall cannot be enabled/performed due to access/permissions/CPL. */
+#define VERR_GIM_HYPERCALL_ACCESS_DENIED            (-6311)
+/** Failed to read to a memory region while performing a hypercall. */
+#define VERR_GIM_HYPERCALL_MEMORY_READ_FAILED       (-6312)
+/** Failed to write to a memory region while performing a hypercall. */
+#define VERR_GIM_HYPERCALL_MEMORY_WRITE_FAILED      (-6313)
+/** Generic hypercall operation failure. */
+#define VERR_GIM_HYPERCALL_FAILED                   (-6314)
+/** No debug connection configured. */
+#define VERR_GIM_NO_DEBUG_CONNECTION                (-6315)
+/** Return to ring-3 to perform the hypercall there. */
+#define VINF_GIM_R3_HYPERCALL                       6316
+/** Continuing hypercall at the same RIP, continue guest execution. */
+#define VINF_GIM_HYPERCALL_CONTINUING               6317
+/** Instruction that triggers the hypercall is invalid/unrecognized. */
+#define VERR_GIM_INVALID_HYPERCALL_INSTR            (-6318)
+/** @} */
+
+
+/** @name Main API Status Codes
+ * @{
+ */
+/** The configuration constructor in main failed due to a COM error.  Check
+ * the release log of the VM for further details. */
+#define VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR      (-6400)
+/** The configuration constructor in main failed due to an internal consistency
+ *  error. Consult the release log of the VM for further details. */
+#define VERR_MAIN_CONFIG_CONSTRUCTOR_IPE            (-6401)
+/** @} */
+
+
+/** @name VBox Drag and Drop Status Codes
+ * @{
+ */
+/** Guest side reported an error. */
+#define VERR_GSTDND_GUEST_ERROR                     (-6500)
+/** @} */
+
+
+/** @name Audio Status Codes
+ * @{
+ */
+/** Host backend couldn't be initialized.  Happen if the audio server is not
+ *  reachable, audio hardware is not available or similar.  We should use the
+ *  NULL audio driver. */
+#define VERR_AUDIO_BACKEND_INIT_FAILED              (-6600)
+/** No free input streams.  */
+#define VERR_AUDIO_NO_FREE_INPUT_STREAMS            (-6601)
+/** No free output streams.  */
+#define VERR_AUDIO_NO_FREE_OUTPUT_STREAMS           (-6602)
+/** Pending stream disable operation in progress.  */
+#define VERR_AUDIO_STREAM_PENDING_DISABLE           (-6603)
+/** There is more data available.
+ *  This can happen due to a buffer wraparound of a buffer read/write operation. */
+#define VINF_AUDIO_MORE_DATA_AVAILABLE              (6604)
+/** @} */
+
+
+/** @name APIC Status Codes
+ * @{
+ */
+/** No pending interrupt. */
+#define VERR_APIC_INTR_NOT_PENDING                  (-6700)
+/** Pending interrupt is masked by TPR. */
+#define VERR_APIC_INTR_MASKED_BY_TPR                (-6701)
+/** APIC did not accept the interrupt. */
+#define VERR_APIC_INTR_DISCARDED                    (-6702)
+/** @} */
+
+/* SED-END */
+
+/** @} */
+
+
+#endif
+
diff --git a/ubuntu/vbox/include/VBox/hgcmsvc.h b/ubuntu/vbox/include/VBox/hgcmsvc.h
new file mode 100644 (file)
index 0000000..fcd9561
--- /dev/null
@@ -0,0 +1,423 @@
+/** @file
+ * Host-Guest Communication Manager (HGCM) - Service library 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.
+ */
+
+#ifndef ___VBox_hgcm_h
+#define ___VBox_hgcm_h
+
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <VBox/err.h>
+#ifdef VBOX_TEST_HGCM_PARMS
+# include <iprt/test.h>
+#endif
+
+/** @todo proper comments. */
+
+/**
+ * Service interface version.
+ *
+ * Includes layout of both VBOXHGCMSVCFNTABLE and VBOXHGCMSVCHELPERS.
+ *
+ * A service can work with these structures if major version
+ * is equal and minor version of service is <= version of the
+ * structures.
+ *
+ * For example when a new helper is added at the end of helpers
+ * structure, then the minor version will be increased. All older
+ * services still can work because they have their old helpers
+ * unchanged.
+ *
+ * Revision history.
+ * 1.1->2.1 Because the pfnConnect now also has the pvClient parameter.
+ * 2.1->2.2 Because pfnSaveState and pfnLoadState were added
+ * 2.2->3.1 Because pfnHostCall is now synchronous, returns rc, and parameters were changed
+ * 3.1->3.2 Because pfnRegisterExtension was added
+ * 3.2->3.3 Because pfnDisconnectClient helper was added
+ * 3.3->4.1 Because the pvService entry and parameter was added
+ * 4.1->4.2 Because the VBOX_HGCM_SVC_PARM_CALLBACK parameter type was added
+ * 4.2->5.1 Removed the VBOX_HGCM_SVC_PARM_CALLBACK parameter type, as
+ *          this problem is already solved by service extension callbacks
+ */
+#define VBOX_HGCM_SVC_VERSION_MAJOR (0x0005)
+#define VBOX_HGCM_SVC_VERSION_MINOR (0x0001)
+#define VBOX_HGCM_SVC_VERSION ((VBOX_HGCM_SVC_VERSION_MAJOR << 16) + VBOX_HGCM_SVC_VERSION_MINOR)
+
+
+/** Typed pointer to distinguish a call to service. */
+struct VBOXHGCMCALLHANDLE_TYPEDEF;
+typedef struct VBOXHGCMCALLHANDLE_TYPEDEF *VBOXHGCMCALLHANDLE;
+
+/** Service helpers pointers table. */
+typedef struct VBOXHGCMSVCHELPERS
+{
+    /** The service has processed the Call request. */
+    DECLR3CALLBACKMEMBER(void, pfnCallComplete, (VBOXHGCMCALLHANDLE callHandle, int32_t rc));
+
+    void *pvInstance;
+
+    /** The service disconnects the client. */
+    DECLR3CALLBACKMEMBER(void, pfnDisconnectClient, (void *pvInstance, uint32_t u32ClientID));
+} VBOXHGCMSVCHELPERS;
+
+typedef VBOXHGCMSVCHELPERS *PVBOXHGCMSVCHELPERS;
+
+
+#define VBOX_HGCM_SVC_PARM_INVALID (0U)
+#define VBOX_HGCM_SVC_PARM_32BIT (1U)
+#define VBOX_HGCM_SVC_PARM_64BIT (2U)
+#define VBOX_HGCM_SVC_PARM_PTR   (3U)
+
+typedef struct VBOXHGCMSVCPARM
+{
+    /** VBOX_HGCM_SVC_PARM_* values. */
+    uint32_t type;
+
+    union
+    {
+        uint32_t uint32;
+        uint64_t uint64;
+        struct
+        {
+            uint32_t size;
+            void *addr;
+        } pointer;
+    } u;
+#ifdef __cplusplus
+    /** Extract an uint32_t value from an HGCM parameter structure */
+    int getUInt32(uint32_t *u32)
+    {
+        AssertPtrReturn(u32, VERR_INVALID_POINTER);
+        int rc = VINF_SUCCESS;
+        if (type != VBOX_HGCM_SVC_PARM_32BIT)
+            rc = VERR_INVALID_PARAMETER;
+        if (RT_SUCCESS(rc))
+            *u32 = u.uint32;
+        return rc;
+    }
+
+    /** Extract a uint64_t value from an HGCM parameter structure */
+    int getUInt64(uint64_t *u64)
+    {
+        AssertPtrReturn(u64, VERR_INVALID_POINTER);
+        int rc = VINF_SUCCESS;
+        if (type != VBOX_HGCM_SVC_PARM_64BIT)
+            rc = VERR_INVALID_PARAMETER;
+        if (RT_SUCCESS(rc))
+            *u64 = u.uint64;
+        return rc;
+    }
+
+    /** Extract a pointer value from an HGCM parameter structure */
+    int getPointer(void **ppv, uint32_t *pcb)
+    {
+        AssertPtrReturn(ppv, VERR_INVALID_POINTER);
+        AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+        if (type == VBOX_HGCM_SVC_PARM_PTR)
+        {
+            *ppv = u.pointer.addr;
+            *pcb = u.pointer.size;
+            return VINF_SUCCESS;
+        }
+
+        return VERR_INVALID_PARAMETER;
+    }
+
+    /** Extract a constant pointer value from an HGCM parameter structure */
+    int getPointer(const void **ppcv, uint32_t *pcb)
+    {
+        AssertPtrReturn(ppcv, VERR_INVALID_POINTER);
+        AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+        void *pv;
+        int rc = getPointer(&pv, pcb);
+        *ppcv = pv;
+        return rc;
+    }
+
+    /** Extract a pointer value to a non-empty buffer from an HGCM parameter
+     * structure */
+    int getBuffer(void **ppv, uint32_t *pcb)
+    {
+        AssertPtrReturn(ppv, VERR_INVALID_POINTER);
+        AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+        void *pv = NULL;
+        uint32_t cb = 0;
+        int rc = getPointer(&pv, &cb);
+        if (   RT_SUCCESS(rc)
+            && VALID_PTR(pv)
+            && cb > 0)
+        {
+            *ppv = pv;
+            *pcb = cb;
+            return VINF_SUCCESS;
+        }
+
+        return VERR_INVALID_PARAMETER;
+    }
+
+    /** Extract a pointer value to a non-empty constant buffer from an HGCM
+     * parameter structure */
+    int getBuffer(const void **ppcv, uint32_t *pcb)
+    {
+        AssertPtrReturn(ppcv, VERR_INVALID_POINTER);
+        AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+        void *pcv = NULL;
+        int rc = getBuffer(&pcv, pcb);
+        *ppcv = pcv;
+        return rc;
+    }
+
+    /** Extract a string value from an HGCM parameter structure */
+    int getString(char **ppch, uint32_t *pcb)
+    {
+        uint32_t cb = 0;
+        char *pch = NULL;
+        int rc = getBuffer((void **)&pch, &cb);
+        if (RT_FAILURE(rc))
+        {
+            *ppch = NULL;
+            *pcb = 0;
+            return rc;
+        }
+        rc = RTStrValidateEncodingEx(pch, cb,
+                                     RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
+        *ppch = pch;
+        *pcb = cb;
+        return rc;
+    }
+
+    /** Extract a constant string value from an HGCM parameter structure */
+    int getString(const char **ppch, uint32_t *pcb)
+    {
+        char *pch = NULL;
+        int rc = getString(&pch, pcb);
+        *ppch = pch;
+        return rc;
+    }
+
+    /** Set a uint32_t value to an HGCM parameter structure */
+    void setUInt32(uint32_t u32)
+    {
+        type = VBOX_HGCM_SVC_PARM_32BIT;
+        u.uint32 = u32;
+    }
+
+    /** Set a uint64_t value to an HGCM parameter structure */
+    void setUInt64(uint64_t u64)
+    {
+        type = VBOX_HGCM_SVC_PARM_64BIT;
+        u.uint64 = u64;
+    }
+
+    /** Set a pointer value to an HGCM parameter structure */
+    void setPointer(void *pv, uint32_t cb)
+    {
+        type = VBOX_HGCM_SVC_PARM_PTR;
+        u.pointer.addr = pv;
+        u.pointer.size = cb;
+    }
+
+    /** Set a const string value to an HGCM parameter structure */
+    void setString(const char *psz)
+    {
+        type = VBOX_HGCM_SVC_PARM_PTR;
+        u.pointer.addr = (void *)psz;
+        u.pointer.size = (uint32_t)strlen(psz) + 1;
+    }
+
+#ifdef ___iprt_cpp_ministring_h
+    /** Set a const string value to an HGCM parameter structure */
+    void setCppString(const RTCString &rString)
+    {
+        type = VBOX_HGCM_SVC_PARM_PTR;
+        u.pointer.addr = (void *)rString.c_str();
+        u.pointer.size = (uint32_t)rString.length() + 1;
+    }
+#endif
+
+#ifdef VBOX_TEST_HGCM_PARMS
+    /** Test the getString member function.  Indirectly tests the getPointer
+     * and getBuffer APIs.
+     * @param  hTest  an running IPRT test
+     * @param  aType  the type that the parameter should be set to before
+     *                calling getString
+     * @param  apcc   the value that the parameter should be set to before
+     *                calling getString, and also the address (!) which we
+     *                expect getString to return.  Stricter than needed of
+     *                course, but I was feeling lazy.
+     * @param  acb    the size that the parameter should be set to before
+     *                calling getString, and also the size which we expect
+     *                getString to return.
+     * @param  rcExp  the expected return value of the call to getString.
+     */
+    void doTestGetString(RTTEST hTest, uint32_t aType, const char *apcc,
+                         uint32_t acb, int rcExp)
+    {
+        /* An RTTest API like this, which would print out an additional line
+         * of context if a test failed, would be nice.  This is because the
+         * line number alone doesn't help much here, given that this is a
+         * subroutine called many times. */
+        /*
+        RTTestContextF(hTest,
+                       ("doTestGetString, aType=%u, apcc=%p, acp=%u, rcExp=%Rrc",
+                        aType, apcc, acp, rcExp));
+         */
+        setPointer((void *)apcc, acb);
+        type = aType;  /* in case we don't want VBOX_HGCM_SVC_PARM_PTR */
+        const char *pcc = NULL;
+        uint32_t cb = 0;
+        int rc = getString(&pcc, &cb);
+        RTTEST_CHECK_RC(hTest, rc, rcExp);
+        if (RT_SUCCESS(rcExp))
+        {
+            RTTEST_CHECK_MSG_RETV(hTest, (pcc == apcc),
+                                  (hTest, "expected %p, got %p", apcc, pcc));
+            RTTEST_CHECK_MSG_RETV(hTest, (cb == acb),
+                                  (hTest, "expected %u, got %u", acb, cb));
+        }
+    }
+
+    /** Run some unit tests on the getString method and indirectly test
+     * getPointer and getBuffer as well. */
+    void testGetString(RTTEST hTest)
+    {
+        RTTestSub(hTest, "HGCM string parameter handling");
+        doTestGetString(hTest, VBOX_HGCM_SVC_PARM_32BIT, "test", 3,
+                        VERR_INVALID_PARAMETER);
+        doTestGetString(hTest, VBOX_HGCM_SVC_PARM_PTR, "test", 5,
+                        VINF_SUCCESS);
+        doTestGetString(hTest, VBOX_HGCM_SVC_PARM_PTR, "test", 3,
+                        VERR_BUFFER_OVERFLOW);
+        doTestGetString(hTest, VBOX_HGCM_SVC_PARM_PTR, "test\xf0", 6,
+                        VERR_INVALID_UTF8_ENCODING);
+        doTestGetString(hTest, VBOX_HGCM_SVC_PARM_PTR, "test", 0,
+                        VERR_INVALID_PARAMETER);
+        doTestGetString(hTest, VBOX_HGCM_SVC_PARM_PTR, (const char *)0x1, 5,
+                        VERR_INVALID_PARAMETER);
+        RTTestSubDone(hTest);
+    }
+#endif
+
+    VBOXHGCMSVCPARM() : type(VBOX_HGCM_SVC_PARM_INVALID) {}
+#endif
+} VBOXHGCMSVCPARM;
+
+typedef VBOXHGCMSVCPARM *PVBOXHGCMSVCPARM;
+
+#ifdef VBOX_WITH_CRHGSMI
+typedef void * HGCMCVSHANDLE;
+
+typedef DECLCALLBACK(void) HGCMHOSTFASTCALLCB (int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext);
+typedef HGCMHOSTFASTCALLCB *PHGCMHOSTFASTCALLCB;
+#endif
+
+
+/** Service specific extension callback.
+ *  This callback is called by the service to perform service specific operation.
+ *
+ * @param pvExtension The extension pointer.
+ * @param u32Function What the callback is supposed to do.
+ * @param pvParm      The function parameters.
+ * @param cbParm      The size of the function parameters.
+ */
+typedef DECLCALLBACK(int) FNHGCMSVCEXT(void *pvExtension, uint32_t u32Function, void *pvParm, uint32_t cbParms);
+typedef FNHGCMSVCEXT *PFNHGCMSVCEXT;
+
+/** The Service DLL entry points.
+ *
+ *  HGCM will call the DLL "VBoxHGCMSvcLoad"
+ *  function and the DLL must fill in the VBOXHGCMSVCFNTABLE
+ *  with function pointers.
+ */
+
+/* The structure is used in separately compiled binaries so an explicit packing is required. */
+#pragma pack(1) /** @todo r=bird: The pragma pack(1) is not at all required!! */
+typedef struct VBOXHGCMSVCFNTABLE
+{
+    /** @name Filled by HGCM
+     * @{ */
+
+    /** Size of the structure. */
+    uint32_t                 cbSize;
+
+    /** Version of the structure, including the helpers. */
+    uint32_t                 u32Version;
+
+    PVBOXHGCMSVCHELPERS      pHelpers;
+    /** @} */
+
+    /** @name Filled in by the service.
+     * @{ */
+
+    /** Size of client information the service want to have. */
+    uint32_t                 cbClient;
+#if ARCH_BITS == 64
+    /** Ensure that the following pointers are properly aligned on 64-bit system. */
+    uint32_t                 u32Alignment0;
+#endif
+
+    /** Uninitialize service */
+    DECLR3CALLBACKMEMBER(int, pfnUnload, (void *pvService));
+
+    /** Inform the service about a client connection. */
+    DECLR3CALLBACKMEMBER(int, pfnConnect, (void *pvService, uint32_t u32ClientID, void *pvClient));
+
+    /** Inform the service that the client wants to disconnect. */
+    DECLR3CALLBACKMEMBER(int, pfnDisconnect, (void *pvService, uint32_t u32ClientID, void *pvClient));
+
+    /** Service entry point.
+     *  Return code is passed to pfnCallComplete callback.
+     */
+    DECLR3CALLBACKMEMBER(void, pfnCall, (void *pvService, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]));
+
+    /** Host Service entry point meant for privileged features invisible to the guest.
+     *  Return code is passed to pfnCallComplete callback.
+     */
+    DECLR3CALLBACKMEMBER(int, pfnHostCall, (void *pvService, uint32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]));
+
+    /** Inform the service about a VM save operation. */
+    DECLR3CALLBACKMEMBER(int, pfnSaveState, (void *pvService, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM));
+
+    /** Inform the service about a VM load operation. */
+    DECLR3CALLBACKMEMBER(int, pfnLoadState, (void *pvService, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM));
+
+    /** Register a service extension callback. */
+    DECLR3CALLBACKMEMBER(int, pfnRegisterExtension, (void *pvService, PFNHGCMSVCEXT pfnExtension, void *pvExtension));
+
+    /** User/instance data pointer for the service. */
+    void *pvService;
+
+    /** @} */
+} VBOXHGCMSVCFNTABLE;
+#pragma pack()
+
+
+/** Service initialization entry point. */
+typedef DECLCALLBACK(int) VBOXHGCMSVCLOAD(VBOXHGCMSVCFNTABLE *ptable);
+typedef VBOXHGCMSVCLOAD *PFNVBOXHGCMSVCLOAD;
+#define VBOX_HGCM_SVCLOAD_NAME "VBoxHGCMSvcLoad"
+
+#endif
diff --git a/ubuntu/vbox/include/VBox/log.h b/ubuntu/vbox/include/VBox/log.h
new file mode 100644 (file)
index 0000000..059929c
--- /dev/null
@@ -0,0 +1,1178 @@
+/** @file
+ * VirtualBox - Logging.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBox_log_h
+#define ___VBox_log_h
+
+/*
+ * Set the default loggroup.
+ */
+#ifndef LOG_GROUP
+# define LOG_GROUP LOG_GROUP_DEFAULT
+#endif
+
+#include <iprt/log.h>
+
+
+/** @defgroup grp_rt_vbox_log    VBox Logging
+ * @ingroup grp_rt_vbox
+ * @{
+ */
+
+/** PC port for debug output */
+#define RTLOG_DEBUG_PORT 0x504
+
+/**
+ * VirtualBox Logging Groups.
+ * (Remember to update LOGGROUP_NAMES!)
+ *
+ * @remark It should be pretty obvious, but just to have
+ *         mentioned it, the values are sorted alphabetically (using the
+ *         english alphabet) except for _DEFAULT which is always first.
+ *
+ *         If anyone might be wondering what the alphabet looks like:
+ *              A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _
+ */
+typedef enum LOGGROUP
+{
+    /** The default VBox group. */
+    LOG_GROUP_DEFAULT = RTLOGGROUP_FIRST_USER,
+    /** Audio mixer group. */
+    LOG_GROUP_AUDIO_MIXER,
+    /** Audio mixer buffer group. */
+    LOG_GROUP_AUDIO_MIXER_BUFFER,
+    /** Auto-logon group. */
+    LOG_GROUP_AUTOLOGON,
+    /** CFGM group. */
+    LOG_GROUP_CFGM,
+    /** CPUM group. */
+    LOG_GROUP_CPUM,
+    /** CSAM group. */
+    LOG_GROUP_CSAM,
+    /** Debug Console group. */
+    LOG_GROUP_DBGC,
+    /** DBGF group. */
+    LOG_GROUP_DBGF,
+    /** DBGF info group. */
+    LOG_GROUP_DBGF_INFO,
+    /** The debugger gui. */
+    LOG_GROUP_DBGG,
+    /** Generic Device group. */
+    LOG_GROUP_DEV,
+    /** AC97 Device group. */
+    LOG_GROUP_DEV_AC97,
+    /** ACPI Device group. */
+    LOG_GROUP_DEV_ACPI,
+    /** AHCI Device group. */
+    LOG_GROUP_DEV_AHCI,
+    /** APIC Device group. */
+    LOG_GROUP_DEV_APIC,
+    /** BusLogic SCSI host adapter group. */
+    LOG_GROUP_DEV_BUSLOGIC,
+    /** DMA Controller group. */
+    LOG_GROUP_DEV_DMA,
+    /** Gigabit Ethernet Device group. */
+    LOG_GROUP_DEV_E1000,
+    /** Extensible Firmware Interface Device group. */
+    LOG_GROUP_DEV_EFI,
+    /** USB EHCI Device group. */
+    LOG_GROUP_DEV_EHCI,
+    /** Floppy Controller Device group. */
+    LOG_GROUP_DEV_FDC,
+    /** Guest Interface Manager Device group. */
+    LOG_GROUP_DEV_GIM,
+    /** HDA Device group. */
+    LOG_GROUP_DEV_HDA,
+    /** HDA Codec Device group. */
+    LOG_GROUP_DEV_HDA_CODEC,
+    /** High Precision Event Timer Device group. */
+    LOG_GROUP_DEV_HPET,
+    /** IDE Device group. */
+    LOG_GROUP_DEV_IDE,
+    /** I/O APIC Device group. */
+    LOG_GROUP_DEV_IOAPIC,
+    /** The internal networking IP stack Device group. */
+    LOG_GROUP_DEV_INIP,
+    /** KeyBoard Controller Device group. */
+    LOG_GROUP_DEV_KBD,
+    /** Low Pin Count Device group. */
+    LOG_GROUP_DEV_LPC,
+    /** LsiLogic SCSI controller Device group. */
+    LOG_GROUP_DEV_LSILOGICSCSI,
+    /** NVMe Device group. */
+    LOG_GROUP_DEV_NVME,
+    /** USB OHCI Device group. */
+    LOG_GROUP_DEV_OHCI,
+    /** Parallel Device group */
+    LOG_GROUP_DEV_PARALLEL,
+    /** PC Device group. */
+    LOG_GROUP_DEV_PC,
+    /** PC Architecture Device group. */
+    LOG_GROUP_DEV_PC_ARCH,
+    /** PC BIOS Device group. */
+    LOG_GROUP_DEV_PC_BIOS,
+    /** PCI Device group. */
+    LOG_GROUP_DEV_PCI,
+    /** PCI Raw Device group. */
+    LOG_GROUP_DEV_PCI_RAW,
+    /** PCNet Device group. */
+    LOG_GROUP_DEV_PCNET,
+    /** PIC Device group. */
+    LOG_GROUP_DEV_PIC,
+    /** PIT Device group. */
+    LOG_GROUP_DEV_PIT,
+    /** RTC Device group. */
+    LOG_GROUP_DEV_RTC,
+    /** SB16 Device group. */
+    LOG_GROUP_DEV_SB16,
+    /** Serial Device group */
+    LOG_GROUP_DEV_SERIAL,
+    /** System Management Controller Device group. */
+    LOG_GROUP_DEV_SMC,
+    /** VGA Device group. */
+    LOG_GROUP_DEV_VGA,
+    /** Virtio PCI Device group. */
+    LOG_GROUP_DEV_VIRTIO,
+    /** Virtio Network Device group. */
+    LOG_GROUP_DEV_VIRTIO_NET,
+    /** VMM Device group. */
+    LOG_GROUP_DEV_VMM,
+    /** VMM Device group for backdoor logging. */
+    LOG_GROUP_DEV_VMM_BACKDOOR,
+    /** VMM Device group for logging guest backdoor logging to stderr. */
+    LOG_GROUP_DEV_VMM_STDERR,
+    /** VMSVGA Device group. */
+    LOG_GROUP_DEV_VMSVGA,
+    /** USB xHCI Device group. */
+    LOG_GROUP_DEV_XHCI,
+    /** Disassembler group. */
+    LOG_GROUP_DIS,
+    /** Generic driver group. */
+    LOG_GROUP_DRV,
+    /** ACPI driver group */
+    LOG_GROUP_DRV_ACPI,
+    /** Audio driver group */
+    LOG_GROUP_DRV_AUDIO,
+    /** Block driver group. */
+    LOG_GROUP_DRV_BLOCK,
+    /** Char driver group. */
+    LOG_GROUP_DRV_CHAR,
+    /** Disk integrity driver group. */
+    LOG_GROUP_DRV_DISK_INTEGRITY,
+    /** Video Display driver group. */
+    LOG_GROUP_DRV_DISPLAY,
+    /** Floppy media driver group. */
+    LOG_GROUP_DRV_FLOPPY,
+    /** Host Audio driver group. */
+    LOG_GROUP_DRV_HOST_AUDIO,
+    /** Host Base block driver group. */
+    LOG_GROUP_DRV_HOST_BASE,
+    /** Host DVD block driver group. */
+    LOG_GROUP_DRV_HOST_DVD,
+    /** Host floppy block driver group. */
+    LOG_GROUP_DRV_HOST_FLOPPY,
+    /** Host Parallel Driver group */
+    LOG_GROUP_DRV_HOST_PARALLEL,
+    /** Host Serial Driver Group */
+    LOG_GROUP_DRV_HOST_SERIAL,
+    /** The internal networking transport driver group. */
+    LOG_GROUP_DRV_INTNET,
+    /** ISO (CD/DVD) media driver group. */
+    LOG_GROUP_DRV_ISO,
+    /** Keyboard Queue driver group. */
+    LOG_GROUP_DRV_KBD_QUEUE,
+    /** lwIP IP stack driver group. */
+    LOG_GROUP_DRV_LWIP,
+    /** Video Miniport driver group. */
+    LOG_GROUP_DRV_MINIPORT,
+    /** Mouse driver group. */
+    LOG_GROUP_DRV_MOUSE,
+    /** Mouse Queue driver group. */
+    LOG_GROUP_DRV_MOUSE_QUEUE,
+    /** Named Pipe stream driver group. */
+    LOG_GROUP_DRV_NAMEDPIPE,
+    /** NAT network transport driver group */
+    LOG_GROUP_DRV_NAT,
+    /** Raw image driver group */
+    LOG_GROUP_DRV_RAW_IMAGE,
+    /** SCSI driver group. */
+    LOG_GROUP_DRV_SCSI,
+    /** Host SCSI driver group. */
+    LOG_GROUP_DRV_SCSIHOST,
+    /** TCP socket stream driver group. */
+    LOG_GROUP_DRV_TCP,
+    /** Async transport driver group */
+    LOG_GROUP_DRV_TRANSPORT_ASYNC,
+    /** TUN network transport driver group */
+    LOG_GROUP_DRV_TUN,
+    /** UDP socket stream driver group. */
+    LOG_GROUP_DRV_UDP,
+    /** UDP tunnet network transport driver group. */
+    LOG_GROUP_DRV_UDPTUNNEL,
+    /** USB Proxy driver group. */
+    LOG_GROUP_DRV_USBPROXY,
+    /** VBoxHDD media driver group. */
+    LOG_GROUP_DRV_VBOXHDD,
+    /** VBox HDD container media driver group. */
+    LOG_GROUP_DRV_VD,
+    /** VRDE audio driver group. */
+    LOG_GROUP_DRV_VRDE_AUDIO,
+    /** Virtual Switch transport driver group */
+    LOG_GROUP_DRV_VSWITCH,
+    /** VUSB driver group */
+    LOG_GROUP_DRV_VUSB,
+    /** EM group. */
+    LOG_GROUP_EM,
+    /** FTM group. */
+    LOG_GROUP_FTM,
+    /** GIM group. */
+    LOG_GROUP_GIM,
+    /** GMM group. */
+    LOG_GROUP_GMM,
+    /** Guest control. */
+    LOG_GROUP_GUEST_CONTROL,
+    /** Guest drag'n drop. */
+    LOG_GROUP_GUEST_DND,
+    /** GUI group. */
+    LOG_GROUP_GUI,
+    /** GVMM group. */
+    LOG_GROUP_GVMM,
+    /** HGCM group */
+    LOG_GROUP_HGCM,
+    /** HGSMI group */
+    LOG_GROUP_HGSMI,
+    /** HM group. */
+    LOG_GROUP_HM,
+    /** IEM group. */
+    LOG_GROUP_IEM,
+    /** IOM group. */
+    LOG_GROUP_IOM,
+    /** XPCOM IPC group. */
+    LOG_GROUP_IPC,
+    /** lwIP group. */
+    LOG_GROUP_LWIP,
+    /** lwIP group, api_lib.c API_LIB_DEBUG */
+    LOG_GROUP_LWIP_API_LIB,
+    /** lwIP group, api_msg.c API_MSG_DEBUG */
+    LOG_GROUP_LWIP_API_MSG,
+    /** lwIP group, etharp.c ETHARP_DEBUG */
+    LOG_GROUP_LWIP_ETHARP,
+    /** lwIP group, icmp.c ICMP_DEBUG */
+    LOG_GROUP_LWIP_ICMP,
+    /** lwIP group, igmp.c IGMP_DEBUG */
+    LOG_GROUP_LWIP_IGMP,
+    /** lwIP group, inet.c INET_DEBUG */
+    LOG_GROUP_LWIP_INET,
+    /** lwIP group, IP_DEBUG (sic!) */
+    LOG_GROUP_LWIP_IP4,
+    /** lwIP group, ip_frag.c IP_REASS_DEBUG (sic!) */
+    LOG_GROUP_LWIP_IP4_REASS,
+    /** lwIP group, IP6_DEBUG */
+    LOG_GROUP_LWIP_IP6,
+    /** lwIP group, mem.c MEM_DEBUG */
+    LOG_GROUP_LWIP_MEM,
+    /** lwIP group, memp.c MEMP_DEBUG */
+    LOG_GROUP_LWIP_MEMP,
+    /** lwIP group, netif.c NETIF_DEBUG */
+    LOG_GROUP_LWIP_NETIF,
+    /** lwIP group, pbuf.c PBUF_DEBUG */
+    LOG_GROUP_LWIP_PBUF,
+    /** lwIP group, raw.c RAW_DEBUG */
+    LOG_GROUP_LWIP_RAW,
+    /** lwIP group, sockets.c SOCKETS_DEBUG */
+    LOG_GROUP_LWIP_SOCKETS,
+    /** lwIP group, SYS_DEBUG */
+    LOG_GROUP_LWIP_SYS,
+    /** lwIP group, TCP_DEBUG */
+    LOG_GROUP_LWIP_TCP,
+    /** lwIP group, tcpip.c TCPIP_DEBUG */
+    LOG_GROUP_LWIP_TCPIP,
+    /** lwIP group, TCP_CWND_DEBUG (congestion window) */
+    LOG_GROUP_LWIP_TCP_CWND,
+    /** lwIP group, tcp_in.c TCP_FR_DEBUG (fast retransmit) */
+    LOG_GROUP_LWIP_TCP_FR,
+    /** lwIP group, tcp_in.c TCP_INPUT_DEBUG */
+    LOG_GROUP_LWIP_TCP_INPUT,
+    /** lwIP group, tcp_out.c TCP_OUTPUT_DEBUG */
+    LOG_GROUP_LWIP_TCP_OUTPUT,
+    /** lwIP group, TCP_QLEN_DEBUG */
+    LOG_GROUP_LWIP_TCP_QLEN,
+    /** lwIP group, TCP_RST_DEBUG */
+    LOG_GROUP_LWIP_TCP_RST,
+    /** lwIP group, TCP_RTO_DEBUG (retransmit) */
+    LOG_GROUP_LWIP_TCP_RTO,
+    /** lwIP group, tcp_in.c TCP_WND_DEBUG (window updates) */
+    LOG_GROUP_LWIP_TCP_WND,
+    /** lwIP group, timers.c TIMERS_DEBUG */
+    LOG_GROUP_LWIP_TIMERS,
+    /** lwIP group, udp.c UDP_DEBUG */
+    LOG_GROUP_LWIP_UDP,
+    /** Main group. */
+    LOG_GROUP_MAIN,
+    /** Main group, IAdditionsFacility. */
+    LOG_GROUP_MAIN_ADDITIONSFACILITY,
+    /** Main group, IAdditionsStateChangedEvent. */
+    LOG_GROUP_MAIN_ADDITIONSSTATECHANGEDEVENT,
+    /** Main group, IAppliance. */
+    LOG_GROUP_MAIN_APPLIANCE,
+    /** Main group, IAudioAdapter. */
+    LOG_GROUP_MAIN_AUDIOADAPTER,
+    /** Main group, IBandwidthControl. */
+    LOG_GROUP_MAIN_BANDWIDTHCONTROL,
+    /** Main group, IBandwidthGroup. */
+    LOG_GROUP_MAIN_BANDWIDTHGROUP,
+    /** Main group, IBandwidthGroupChangedEvent. */
+    LOG_GROUP_MAIN_BANDWIDTHGROUPCHANGEDEVENT,
+    /** Main group, IBIOSSettings. */
+    LOG_GROUP_MAIN_BIOSSETTINGS,
+    /** Main group, ICanShowWindowEvent. */
+    LOG_GROUP_MAIN_CANSHOWWINDOWEVENT,
+    /** Main group, ICertificate. */
+    LOG_GROUP_MAIN_CERTIFICATE,
+    /** Main group, IClipboardModeChangedEvent. */
+    LOG_GROUP_MAIN_CLIPBOARDMODECHANGEDEVENT,
+    /** Main group, IConsole. */
+    LOG_GROUP_MAIN_CONSOLE,
+    /** Main group, ICPUChangedEvent. */
+    LOG_GROUP_MAIN_CPUCHANGEDEVENT,
+    /** Main group, ICPUExecutionCapChangedEvent. */
+    LOG_GROUP_MAIN_CPUEXECUTIONCAPCHANGEDEVENT,
+    /** Main group, IDHCPServer. */
+    LOG_GROUP_MAIN_DHCPSERVER,
+    /** Main group, IDirectory. */
+    LOG_GROUP_MAIN_DIRECTORY,
+    /** Main group, IDisplay. */
+    LOG_GROUP_MAIN_DISPLAY,
+    /** Main group, IDisplaySourceBitmap. */
+    LOG_GROUP_MAIN_DISPLAYSOURCEBITMAP,
+    /** Main group, IDnDBase. */
+    LOG_GROUP_MAIN_DNDBASE,
+    /** Main group, IDnDModeChangedEvent. */
+    LOG_GROUP_MAIN_DNDMODECHANGEDEVENT,
+    /** Main group, IDnDSource. */
+    LOG_GROUP_MAIN_DNDSOURCE,
+    /** Main group, IDnDTarget. */
+    LOG_GROUP_MAIN_DNDTARGET,
+    /** Main group, IEmulatedUSB. */
+    LOG_GROUP_MAIN_EMULATEDUSB,
+    /** Main group, IEvent. */
+    LOG_GROUP_MAIN_EVENT,
+    /** Main group, IEventListener. */
+    LOG_GROUP_MAIN_EVENTLISTENER,
+    /** Main group, IEventSource. */
+    LOG_GROUP_MAIN_EVENTSOURCE,
+    /** Main group, IEventSourceChangedEvent. */
+    LOG_GROUP_MAIN_EVENTSOURCECHANGEDEVENT,
+    /** Main group, IExtPack. */
+    LOG_GROUP_MAIN_EXTPACK,
+    /** Main group, IExtPackBase. */
+    LOG_GROUP_MAIN_EXTPACKBASE,
+    /** Main group, IExtPackFile. */
+    LOG_GROUP_MAIN_EXTPACKFILE,
+    /** Main group, IExtPackManager. */
+    LOG_GROUP_MAIN_EXTPACKMANAGER,
+    /** Main group, IExtPackPlugIn. */
+    LOG_GROUP_MAIN_EXTPACKPLUGIN,
+    /** Main group, IExtraDataCanChangeEvent. */
+    LOG_GROUP_MAIN_EXTRADATACANCHANGEEVENT,
+    /** Main group, IExtraDataChangedEvent. */
+    LOG_GROUP_MAIN_EXTRADATACHANGEDEVENT,
+    /** Main group, IFile. */
+    LOG_GROUP_MAIN_FILE,
+    /** Main group, IFramebuffer. */
+    LOG_GROUP_MAIN_FRAMEBUFFER,
+    /** Main group, IFramebufferOverlay. */
+    LOG_GROUP_MAIN_FRAMEBUFFEROVERLAY,
+    /** Main group, IFsObjInfo. */
+    LOG_GROUP_MAIN_FSOBJINFO,
+    /** Main group, IGuest. */
+    LOG_GROUP_MAIN_GUEST,
+    /** Main group, IGuestDirectory. */
+    LOG_GROUP_MAIN_GUESTDIRECTORY,
+    /** Main group, IGuestDnDSource. */
+    LOG_GROUP_MAIN_GUESTDNDSOURCE,
+    /** Main group, IGuestDnDTarget. */
+    LOG_GROUP_MAIN_GUESTDNDTARGET,
+    /** Main group, IGuestErrorInfo. */
+    LOG_GROUP_MAIN_GUESTERRORINFO,
+    /** Main group, IGuestFile. */
+    LOG_GROUP_MAIN_GUESTFILE,
+    /** Main group, IGuestFileEvent. */
+    LOG_GROUP_MAIN_GUESTFILEEVENT,
+    /** Main group, IGuestFileIOEvent. */
+    LOG_GROUP_MAIN_GUESTFILEIOEVENT,
+    /** Main group, IGuestFileOffsetChangedEvent. */
+    LOG_GROUP_MAIN_GUESTFILEOFFSETCHANGEDEVENT,
+    /** Main group, IGuestFileReadEvent. */
+    LOG_GROUP_MAIN_GUESTFILEREADEVENT,
+    /** Main group, IGuestFileRegisteredEvent. */
+    LOG_GROUP_MAIN_GUESTFILEREGISTEREDEVENT,
+    /** Main group, IGuestFileStateChangedEvent. */
+    LOG_GROUP_MAIN_GUESTFILESTATECHANGEDEVENT,
+    /** Main group, IGuestFileWriteEvent. */
+    LOG_GROUP_MAIN_GUESTFILEWRITEEVENT,
+    /** Main group, IGuestFsObjInfo. */
+    LOG_GROUP_MAIN_GUESTFSOBJINFO,
+    /** Main group, IGuestKeyboardEvent. */
+    LOG_GROUP_MAIN_GUESTKEYBOARDEVENT,
+    /** Main group, IGuestMonitorChangedEvent. */
+    LOG_GROUP_MAIN_GUESTMONITORCHANGEDEVENT,
+    /** Main group, IGuestMouseEvent. */
+    LOG_GROUP_MAIN_GUESTMOUSEEVENT,
+    /** Main group, IGuestMultiTouchEvent. */
+    LOG_GROUP_MAIN_GUESTMULTITOUCHEVENT,
+    /** Main group, IGuestOSType. */
+    LOG_GROUP_MAIN_GUESTOSTYPE,
+    /** Main group, IGuestProcess. */
+    LOG_GROUP_MAIN_GUESTPROCESS,
+    /** Main group, IGuestProcessEvent. */
+    LOG_GROUP_MAIN_GUESTPROCESSEVENT,
+    /** Main group, IGuestProcessInputNotifyEvent. */
+    LOG_GROUP_MAIN_GUESTPROCESSINPUTNOTIFYEVENT,
+    /** Main group, IGuestProcessIOEvent. */
+    LOG_GROUP_MAIN_GUESTPROCESSIOEVENT,
+    /** Main group, IGuestProcessOutputEvent. */
+    LOG_GROUP_MAIN_GUESTPROCESSOUTPUTEVENT,
+    /** Main group, IGuestProcessRegisteredEvent. */
+    LOG_GROUP_MAIN_GUESTPROCESSREGISTEREDEVENT,
+    /** Main group, IGuestProcessStateChangedEvent. */
+    LOG_GROUP_MAIN_GUESTPROCESSSTATECHANGEDEVENT,
+    /** Main group, IGuestPropertyChangedEvent. */
+    LOG_GROUP_MAIN_GUESTPROPERTYCHANGEDEVENT,
+    /** Main group, IGuestScreenInfo. */
+    LOG_GROUP_MAIN_GUESTSCREENINFO,
+    /** Main group, IGuestSession. */
+    LOG_GROUP_MAIN_GUESTSESSION,
+    /** Main group, IGuestSessionEvent. */
+    LOG_GROUP_MAIN_GUESTSESSIONEVENT,
+    /** Main group, IGuestSessionRegisteredEvent. */
+    LOG_GROUP_MAIN_GUESTSESSIONREGISTEREDEVENT,
+    /** Main group, IGuestSessionStateChangedEvent. */
+    LOG_GROUP_MAIN_GUESTSESSIONSTATECHANGEDEVENT,
+    /** Main group, IGuestUserStateChangedEvent. */
+    LOG_GROUP_MAIN_GUESTUSERSTATECHANGEDEVENT,
+    /** Main group, IHost. */
+    LOG_GROUP_MAIN_HOST,
+    /** Main group, IHostNameResolutionConfigurationChangeEvent. */
+    LOG_GROUP_MAIN_HOSTNAMERESOLUTIONCONFIGURATIONCHANGEEVENT,
+    /** Main group, IHostNetworkInterface. */
+    LOG_GROUP_MAIN_HOSTNETWORKINTERFACE,
+    /** Main group, IHostPCIDevicePlugEvent. */
+    LOG_GROUP_MAIN_HOSTPCIDEVICEPLUGEVENT,
+    /** Main group, IHostUSBDevice. */
+    LOG_GROUP_MAIN_HOSTUSBDEVICE,
+    /** Main group, IHostUSBDeviceFilter. */
+    LOG_GROUP_MAIN_HOSTUSBDEVICEFILTER,
+    /** Main group, IHostVideoInputDevice. */
+    LOG_GROUP_MAIN_HOSTVIDEOINPUTDEVICE,
+    /** Main group, IInternalMachineControl. */
+    LOG_GROUP_MAIN_INTERNALMACHINECONTROL,
+    /** Main group, IInternalSessionControl. */
+    LOG_GROUP_MAIN_INTERNALSESSIONCONTROL,
+    /** Main group, IKeyboard. */
+    LOG_GROUP_MAIN_KEYBOARD,
+    /** Main group, IKeyboardLedsChangedEvent. */
+    LOG_GROUP_MAIN_KEYBOARDLEDSCHANGEDEVENT,
+    /** Main group, IMachine. */
+    LOG_GROUP_MAIN_MACHINE,
+    /** Main group, IMachineDataChangedEvent. */
+    LOG_GROUP_MAIN_MACHINEDATACHANGEDEVENT,
+    /** Main group, IMachineDebugger. */
+    LOG_GROUP_MAIN_MACHINEDEBUGGER,
+    /** Main group, IMachineEvent. */
+    LOG_GROUP_MAIN_MACHINEEVENT,
+    /** Main group, IMachineRegisteredEvent. */
+    LOG_GROUP_MAIN_MACHINEREGISTEREDEVENT,
+    /** Main group, IMachineStateChangedEvent. */
+    LOG_GROUP_MAIN_MACHINESTATECHANGEDEVENT,
+    /** Main group, IMedium. */
+    LOG_GROUP_MAIN_MEDIUM,
+    /** Main group, IMediumAttachment. */
+    LOG_GROUP_MAIN_MEDIUMATTACHMENT,
+    /** Main group, IMediumChangedEvent. */
+    LOG_GROUP_MAIN_MEDIUMCHANGEDEVENT,
+    /** Main group, IMediumConfigChangedEvent. */
+    LOG_GROUP_MAIN_MEDIUMCONFIGCHANGEDEVENT,
+    /** Main group, IMediumFormat. */
+    LOG_GROUP_MAIN_MEDIUMFORMAT,
+    /** Main group, IMediumRegisteredEvent. */
+    LOG_GROUP_MAIN_MEDIUMREGISTEREDEVENT,
+    /** Main group, IMouse. */
+    LOG_GROUP_MAIN_MOUSE,
+    /** Main group, IMouseCapabilityChangedEvent. */
+    LOG_GROUP_MAIN_MOUSECAPABILITYCHANGEDEVENT,
+    /** Main group, IMousePointerShape. */
+    LOG_GROUP_MAIN_MOUSEPOINTERSHAPE,
+    /** Main group, IMousePointerShapeChangedEvent. */
+    LOG_GROUP_MAIN_MOUSEPOINTERSHAPECHANGEDEVENT,
+    /** Main group, INATEngine. */
+    LOG_GROUP_MAIN_NATENGINE,
+    /** Main group, INATNetwork. */
+    LOG_GROUP_MAIN_NATNETWORK,
+    /** Main group, INATNetworkAlterEvent. */
+    LOG_GROUP_MAIN_NATNETWORKALTEREVENT,
+    /** Main group, INATNetworkChangedEvent. */
+    LOG_GROUP_MAIN_NATNETWORKCHANGEDEVENT,
+    /** Main group, INATNetworkCreationDeletionEvent. */
+    LOG_GROUP_MAIN_NATNETWORKCREATIONDELETIONEVENT,
+    /** Main group, INATNetworkPortForwardEvent. */
+    LOG_GROUP_MAIN_NATNETWORKPORTFORWARDEVENT,
+    /** Main group, INATNetworkSettingEvent. */
+    LOG_GROUP_MAIN_NATNETWORKSETTINGEVENT,
+    /** Main group, INATNetworkStartStopEvent. */
+    LOG_GROUP_MAIN_NATNETWORKSTARTSTOPEVENT,
+    /** Main group, INATRedirectEvent. */
+    LOG_GROUP_MAIN_NATREDIRECTEVENT,
+    /** Main group, INetworkAdapter. */
+    LOG_GROUP_MAIN_NETWORKADAPTER,
+    /** Main group, INetworkAdapterChangedEvent. */
+    LOG_GROUP_MAIN_NETWORKADAPTERCHANGEDEVENT,
+    /** Main group, IParallelPort. */
+    LOG_GROUP_MAIN_PARALLELPORT,
+    /** Main group, IParallelPortChangedEvent. */
+    LOG_GROUP_MAIN_PARALLELPORTCHANGEDEVENT,
+    /** Main group, IPCIAddress. */
+    LOG_GROUP_MAIN_PCIADDRESS,
+    /** Main group, IPCIDeviceAttachment. */
+    LOG_GROUP_MAIN_PCIDEVICEATTACHMENT,
+    /** Main group, IPerformanceCollector. */
+    LOG_GROUP_MAIN_PERFORMANCECOLLECTOR,
+    /** Main group, IPerformanceMetric. */
+    LOG_GROUP_MAIN_PERFORMANCEMETRIC,
+    /** Main group, IProcess. */
+    LOG_GROUP_MAIN_PROCESS,
+    /** Main group, IProgress. */
+    LOG_GROUP_MAIN_PROGRESS,
+    /** Main group, IReusableEvent. */
+    LOG_GROUP_MAIN_REUSABLEEVENT,
+    /** Main group, IRuntimeErrorEvent. */
+    LOG_GROUP_MAIN_RUNTIMEERROREVENT,
+    /** Main group, ISerialPort. */
+    LOG_GROUP_MAIN_SERIALPORT,
+    /** Main group, ISerialPortChangedEvent. */
+    LOG_GROUP_MAIN_SERIALPORTCHANGEDEVENT,
+    /** Main group, ISession. */
+    LOG_GROUP_MAIN_SESSION,
+    /** Main group, ISessionStateChangedEvent. */
+    LOG_GROUP_MAIN_SESSIONSTATECHANGEDEVENT,
+    /** Main group, ISharedFolder. */
+    LOG_GROUP_MAIN_SHAREDFOLDER,
+    /** Main group, ISharedFolderChangedEvent. */
+    LOG_GROUP_MAIN_SHAREDFOLDERCHANGEDEVENT,
+    /** Main group, IShowWindowEvent. */
+    LOG_GROUP_MAIN_SHOWWINDOWEVENT,
+    /** Main group, ISnapshot. */
+    LOG_GROUP_MAIN_SNAPSHOT,
+    /** Main group, ISnapshotChangedEvent. */
+    LOG_GROUP_MAIN_SNAPSHOTCHANGEDEVENT,
+    /** Main group, ISnapshotDeletedEvent. */
+    LOG_GROUP_MAIN_SNAPSHOTDELETEDEVENT,
+    /** Main group, ISnapshotEvent. */
+    LOG_GROUP_MAIN_SNAPSHOTEVENT,
+    /** Main group, ISnapshotTakenEvent. */
+    LOG_GROUP_MAIN_SNAPSHOTRESTOREDEVENT,
+    /** Main group, ISnapshotRestoredEvent. */
+    LOG_GROUP_MAIN_SNAPSHOTTAKENEVENT,
+    /** Main group, IStateChangedEvent. */
+    LOG_GROUP_MAIN_STATECHANGEDEVENT,
+    /** Main group, IStorageController. */
+    LOG_GROUP_MAIN_STORAGECONTROLLER,
+    /** Main group, IStorageControllerChangedEvent. */
+    LOG_GROUP_MAIN_STORAGECONTROLLERCHANGEDEVENT,
+    /** Main group, IStorageDeviceChangedEvent. */
+    LOG_GROUP_MAIN_STORAGEDEVICECHANGEDEVENT,
+    /** Main group, ISystemProperties. */
+    LOG_GROUP_MAIN_SYSTEMPROPERTIES,
+    /** Main group, IToken. */
+    LOG_GROUP_MAIN_TOKEN,
+    /** Main group, IUSBController. */
+    LOG_GROUP_MAIN_USBCONTROLLER,
+    /** Main group, IUSBControllerChangedEvent. */
+    LOG_GROUP_MAIN_USBCONTROLLERCHANGEDEVENT,
+    /** Main group, IUSBDevice. */
+    LOG_GROUP_MAIN_USBDEVICE,
+    /** Main group, IUSBDeviceFilter. */
+    LOG_GROUP_MAIN_USBDEVICEFILTER,
+    /** Main group, IUSBDeviceFilters. */
+    LOG_GROUP_MAIN_USBDEVICEFILTERS,
+    /** Main group, IUSBDeviceStateChangedEvent. */
+    LOG_GROUP_MAIN_USBDEVICESTATECHANGEDEVENT,
+    /** Main group, IUSBProxyBackend. */
+    LOG_GROUP_MAIN_USBPROXYBACKEND,
+    /** Main group, IVBoxSVCAvailabilityChangedEvent. */
+    LOG_GROUP_MAIN_VBOXSVCAVAILABILITYCHANGEDEVENT,
+    /** Main group, IVetoEvent. */
+    LOG_GROUP_MAIN_VETOEVENT,
+    /** Main group, IVFSExplorer. */
+    LOG_GROUP_MAIN_VFSEXPLORER,
+    /** Main group, IVideoCaptureChangedEvent. */
+    LOG_GROUP_MAIN_VIDEOCAPTURECHANGEDEVENT,
+    /** Main group, IVirtualBox. */
+    LOG_GROUP_MAIN_VIRTUALBOX,
+    /** Main group, IVirtualBoxClient. */
+    LOG_GROUP_MAIN_VIRTUALBOXCLIENT,
+    /** Main group, IVirtualSystemDescription. */
+    LOG_GROUP_MAIN_VIRTUALSYSTEMDESCRIPTION,
+    /** Main group, IVRDEServer. */
+    LOG_GROUP_MAIN_VRDESERVER,
+    /** Main group, IVRDEServerChangedEvent. */
+    LOG_GROUP_MAIN_VRDESERVERCHANGEDEVENT,
+    /** Main group, IVRDEServerInfo. */
+    LOG_GROUP_MAIN_VRDESERVERINFO,
+    /** Main group, IVRDEServerInfoChangedEvent. */
+    LOG_GROUP_MAIN_VRDESERVERINFOCHANGEDEVENT,
+    /** Misc. group intended for external use only. */
+    LOG_GROUP_MISC,
+    /** MM group. */
+    LOG_GROUP_MM,
+    /** MM group. */
+    LOG_GROUP_MM_HEAP,
+    /** MM group. */
+    LOG_GROUP_MM_HYPER,
+    /** MM Hypervisor Heap group. */
+    LOG_GROUP_MM_HYPER_HEAP,
+    /** MM Physical/Ram group. */
+    LOG_GROUP_MM_PHYS,
+    /** MM Page pool group. */
+    LOG_GROUP_MM_POOL,
+    /** The NAT service group */
+    LOG_GROUP_NAT_SERVICE,
+    /** The network adaptor driver group. */
+    LOG_GROUP_NET_ADP_DRV,
+    /** The network filter driver group. */
+    LOG_GROUP_NET_FLT_DRV,
+    /** The common network service group */
+    LOG_GROUP_NET_SERVICE,
+    /** Network traffic shaper driver group. */
+    LOG_GROUP_NET_SHAPER,
+    /** PATM group. */
+    LOG_GROUP_PATM,
+    /** PDM group. */
+    LOG_GROUP_PDM,
+    /** PDM Async completion group. */
+    LOG_GROUP_PDM_ASYNC_COMPLETION,
+    /** PDM Block cache group. */
+    LOG_GROUP_PDM_BLK_CACHE,
+    /** PDM Device group. */
+    LOG_GROUP_PDM_DEVICE,
+    /** PDM Driver group. */
+    LOG_GROUP_PDM_DRIVER,
+    /** PDM Loader group. */
+    LOG_GROUP_PDM_LDR,
+    /** PDM Loader group. */
+    LOG_GROUP_PDM_QUEUE,
+    /** PGM group. */
+    LOG_GROUP_PGM,
+    /** PGM dynamic mapping group. */
+    LOG_GROUP_PGM_DYNMAP,
+    /** PGM physical group. */
+    LOG_GROUP_PGM_PHYS,
+    /** PGM physical access group. */
+    LOG_GROUP_PGM_PHYS_ACCESS,
+    /** PGM shadow page pool group. */
+    LOG_GROUP_PGM_POOL,
+    /** PGM shared paging group. */
+    LOG_GROUP_PGM_SHARED,
+    /** REM group. */
+    LOG_GROUP_REM,
+    /** REM disassembly handler group. */
+    LOG_GROUP_REM_DISAS,
+    /** REM access handler group. */
+    LOG_GROUP_REM_HANDLER,
+    /** REM I/O port access group. */
+    LOG_GROUP_REM_IOPORT,
+    /** REM MMIO access group. */
+    LOG_GROUP_REM_MMIO,
+    /** REM Printf. */
+    LOG_GROUP_REM_PRINTF,
+    /** REM running group. */
+    LOG_GROUP_REM_RUN,
+    /** SELM group. */
+    LOG_GROUP_SELM,
+    /** Shared clipboard host service group. */
+    LOG_GROUP_SHARED_CLIPBOARD,
+    /** Chromium OpenGL host service group. */
+    LOG_GROUP_SHARED_CROPENGL,
+    /** Shared folders host service group. */
+    LOG_GROUP_SHARED_FOLDERS,
+    /** OpenGL host service group. */
+    LOG_GROUP_SHARED_OPENGL,
+    /** The internal networking service group. */
+    LOG_GROUP_SRV_INTNET,
+    /** SSM group. */
+    LOG_GROUP_SSM,
+    /** STAM group. */
+    LOG_GROUP_STAM,
+    /** SUP group. */
+    LOG_GROUP_SUP,
+    /** SUPport driver group. */
+    LOG_GROUP_SUP_DRV,
+    /** TM group. */
+    LOG_GROUP_TM,
+    /** TRPM group. */
+    LOG_GROUP_TRPM,
+    /** USB cardreader group. */
+    LOG_GROUP_USB_CARDREADER,
+    /** USB driver group. */
+    LOG_GROUP_USB_DRV,
+    /** USBFilter group. */
+    LOG_GROUP_USB_FILTER,
+    /** USB keyboard device group. */
+    LOG_GROUP_USB_KBD,
+    /** USB mouse/tablet device group. */
+    LOG_GROUP_USB_MOUSE,
+    /** MSD USB device group. */
+    LOG_GROUP_USB_MSD,
+    /** USB remote support. */
+    LOG_GROUP_USB_REMOTE,
+    /** USB webcam. */
+    LOG_GROUP_USB_WEBCAM,
+    /** VBox Guest Additions Driver (VBoxGuest). */
+    LOG_GROUP_VGDRV,
+    /** VBox Guest Additions Library. */
+    LOG_GROUP_VBGL,
+    /** Generic virtual disk layer. */
+    LOG_GROUP_VD,
+    /** DMG virtual disk backend. */
+    LOG_GROUP_VD_DMG,
+    /** iSCSI virtual disk backend. */
+    LOG_GROUP_VD_ISCSI,
+    /** Parallels HDD virtual disk backend. */
+    LOG_GROUP_VD_PARALLELS,
+    /** QCOW virtual disk backend. */
+    LOG_GROUP_VD_QCOW,
+    /** QED virtual disk backend. */
+    LOG_GROUP_VD_QED,
+    /** Raw virtual disk backend. */
+    LOG_GROUP_VD_RAW,
+    /** VDI virtual disk backend. */
+    LOG_GROUP_VD_VDI,
+    /** VHD virtual disk backend. */
+    LOG_GROUP_VD_VHD,
+    /** VHDX virtual disk backend. */
+    LOG_GROUP_VD_VHDX,
+    /** VMDK virtual disk backend. */
+    LOG_GROUP_VD_VMDK,
+    /** VM group. */
+    LOG_GROUP_VM,
+    /** VMM group. */
+    LOG_GROUP_VMM,
+    /** VRDE group */
+    LOG_GROUP_VRDE,
+    /** VRDP group */
+    LOG_GROUP_VRDP,
+    /** VSCSI group */
+    LOG_GROUP_VSCSI,
+    /** Webservice group. */
+    LOG_GROUP_WEBSERVICE
+    /* !!!ALPHABETICALLY!!! */
+} VBOX_LOGGROUP;
+
+
+/** @def VBOX_LOGGROUP_NAMES
+ * VirtualBox Logging group names.
+ *
+ * Must correspond 100% to LOGGROUP!
+ * Don't forget commas!
+ *
+ * @remark It should be pretty obvious, but just to have
+ *         mentioned it, the values are sorted alphabetically (using the
+ *         english alphabet) except for _DEFAULT which is always first.
+ *
+ *         If anyone might be wondering what the alphabet looks like:
+ *              a b c d e f g h i j k l m n o p q r s t u v w x y z
+ */
+#define VBOX_LOGGROUP_NAMES \
+{                   \
+    RT_LOGGROUP_NAMES, \
+    "DEFAULT",      \
+    "AUDIO_MIXER",  \
+    "AUDIO_MIXER_BUFFER", \
+    "AUTOLOGON",    \
+    "CFGM",         \
+    "CPUM",         \
+    "CSAM",         \
+    "DBGC",         \
+    "DBGF",         \
+    "DBGF_INFO",    \
+    "DBGG",         \
+    "DEV",          \
+    "DEV_AC97",     \
+    "DEV_ACPI",     \
+    "DEV_AHCI",     \
+    "DEV_APIC",     \
+    "DEV_BUSLOGIC", \
+    "DEV_DMA",      \
+    "DEV_E1000",    \
+    "DEV_EFI",      \
+    "DEV_EHCI",     \
+    "DEV_FDC",      \
+    "DEV_GIM",      \
+    "DEV_HDA",      \
+    "DEV_HDA_CODEC", \
+    "DEV_HPET",     \
+    "DEV_IDE",      \
+    "DEV_IOAPIC",   \
+    "DEV_INIP",     \
+    "DEV_KBD",      \
+    "DEV_LPC",      \
+    "DEV_LSILOGICSCSI", \
+    "DEV_NVME",     \
+    "DEV_OHCI",     \
+    "DEV_PARALLEL", \
+    "DEV_PC",       \
+    "DEV_PC_ARCH",  \
+    "DEV_PC_BIOS",  \
+    "DEV_PCI",      \
+    "DEV_PCI_RAW",  \
+    "DEV_PCNET",    \
+    "DEV_PIC",      \
+    "DEV_PIT",      \
+    "DEV_RTC",      \
+    "DEV_SB16",     \
+    "DEV_SERIAL",   \
+    "DEV_SMC",      \
+    "DEV_VGA",      \
+    "DEV_VIRTIO",   \
+    "DEV_VIRTIO_NET", \
+    "DEV_VMM",      \
+    "DEV_VMM_BACKDOOR", \
+    "DEV_VMM_STDERR", \
+    "DEV_VMSVGA",   \
+    "DEV_XHCI",     \
+    "DIS",          \
+    "DRV",          \
+    "DRV_ACPI",     \
+    "DRV_AUDIO",    \
+    "DRV_BLOCK",    \
+    "DRV_CHAR",     \
+    "DRV_DISK_INTEGRITY", \
+    "DRV_DISPLAY",  \
+    "DRV_FLOPPY",   \
+    "DRV_HOST_AUDIO", \
+    "DRV_HOST_BASE", \
+    "DRV_HOST_DVD", \
+    "DRV_HOST_FLOPPY", \
+    "DRV_HOST_PARALLEL", \
+    "DRV_HOST_SERIAL", \
+    "DRV_INTNET",   \
+    "DRV_ISO",      \
+    "DRV_KBD_QUEUE", \
+    "DRV_LWIP",     \
+    "DRV_MINIPORT", \
+    "DRV_MOUSE",    \
+    "DRV_MOUSE_QUEUE", \
+    "DRV_NAMEDPIPE", \
+    "DRV_NAT",      \
+    "DRV_RAW_IMAGE", \
+    "DRV_SCSI",     \
+    "DRV_SCSIHOST", \
+    "DRV_TCP", \
+    "DRV_TRANSPORT_ASYNC", \
+    "DRV_TUN",      \
+    "DRV_UDP", \
+    "DRV_UDPTUNNEL", \
+    "DRV_USBPROXY", \
+    "DRV_VBOXHDD",  \
+    "DRV_VD",       \
+    "DRV_VRDE_AUDIO", \
+    "DRV_VSWITCH",  \
+    "DRV_VUSB",     \
+    "EM",           \
+    "FTM",          \
+    "GIM",          \
+    "GMM",          \
+    "GUEST_CONTROL", \
+    "GUEST_DND",    \
+    "GUI",          \
+    "GVMM",         \
+    "HGCM",         \
+    "HGSMI",        \
+    "HM",           \
+    "IEM",          \
+    "IOM",          \
+    "IPC",          \
+    "LWIP",            \
+    "LWIP_API_LIB",    \
+    "LWIP_API_MSG",    \
+    "LWIP_ETHARP",     \
+    "LWIP_ICMP",       \
+    "LWIP_IGMP",       \
+    "LWIP_INET",       \
+    "LWIP_IP4",        \
+    "LWIP_IP4_REASS",  \
+    "LWIP_IP6",        \
+    "LWIP_MEM",        \
+    "LWIP_MEMP",       \
+    "LWIP_NETIF",      \
+    "LWIP_PBUF",       \
+    "LWIP_RAW",        \
+    "LWIP_SOCKETS",    \
+    "LWIP_SYS",        \
+    "LWIP_TCP",        \
+    "LWIP_TCPIP",      \
+    "LWIP_TCP_CWND",   \
+    "LWIP_TCP_FR",     \
+    "LWIP_TCP_INPUT",  \
+    "LWIP_TCP_OUTPUT", \
+    "LWIP_TCP_QLEN",   \
+    "LWIP_TCP_RST",    \
+    "LWIP_TCP_RTO",    \
+    "LWIP_TCP_WND",    \
+    "LWIP_TIMERS",     \
+    "LWIP_UDP",        \
+    "MAIN",         \
+    "MAIN_ADDITIONSFACILITY", \
+    "MAIN_ADDITIONSSTATECHANGEDEVENT", \
+    "MAIN_APPLIANCE", \
+    "MAIN_AUDIOADAPTER", \
+    "MAIN_BANDWIDTHCONTROL", \
+    "MAIN_BANDWIDTHGROUP", \
+    "MAIN_BANDWIDTHGROUPCHANGEDEVENT", \
+    "MAIN_BIOSSETTINGS", \
+    "MAIN_CANSHOWWINDOWEVENT", \
+    "MAIN_CERTIFICATE", \
+    "MAIN_CLIPBOARDMODECHANGEDEVENT", \
+    "MAIN_CONSOLE", \
+    "MAIN_CPUCHANGEDEVENT", \
+    "MAIN_CPUEXECUTIONCAPCHANGEDEVENT", \
+    "MAIN_DHCPSERVER", \
+    "MAIN_DIRECTORY", \
+    "MAIN_DISPLAY", \
+    "MAIN_DISPLAYSOURCEBITMAP", \
+    "MAIN_DNDBASE", \
+    "MAIN_DNDMODECHANGEDEVENT", \
+    "MAIN_DNDSOURCE", \
+    "MAIN_DNDTARGET", \
+    "MAIN_EMULATEDUSB",   \
+    "MAIN_EVENT",   \
+    "MAIN_EVENTLISTENER", \
+    "MAIN_EVENTSOURCE", \
+    "MAIN_EVENTSOURCECHANGEDEVENT", \
+    "MAIN_EXTPACK", \
+    "MAIN_EXTPACKBASE", \
+    "MAIN_EXTPACKFILE", \
+    "MAIN_EXTPACKMANAGER", \
+    "MAIN_EXTPACKPLUGIN", \
+    "MAIN_EXTRADATACANCHANGEEVENT", \
+    "MAIN_EXTRADATACHANGEDEVENT", \
+    "MAIN_FILE",    \
+    "MAIN_FRAMEBUFFER", \
+    "MAIN_FRAMEBUFFEROVERLAY", \
+    "MAIN_FSOBJINFO", \
+    "MAIN_GUEST",   \
+    "MAIN_GUESTDIRECTORY", \
+    "MAIN_GUESTDNDSOURCE", \
+    "MAIN_GUESTDNDTARGET", \
+    "MAIN_GUESTERRORINFO", \
+    "MAIN_GUESTFILE", \
+    "MAIN_GUESTFILEEVENT", \
+    "MAIN_GUESTFILEIOEVENT", \
+    "MAIN_GUESTFILEOFFSETCHANGEDEVENT", \
+    "MAIN_GUESTFILEREADEVENT", \
+    "MAIN_GUESTFILEREGISTEREDEVENT", \
+    "MAIN_GUESTFILESTATECHANGEDEVENT", \
+    "MAIN_GUESTFILEWRITEEVENT", \
+    "MAIN_GUESTFSOBJINFO", \
+    "MAIN_GUESTKEYBOARDEVENT", \
+    "MAIN_GUESTMONITORCHANGEDEVENT", \
+    "MAIN_GUESTMOUSEEVENT", \
+    "MAIN_GUESTMULTITOUCHEVENT", \
+    "MAIN_GUESTOSTYPE", \
+    "MAIN_GUESTPROCESS", \
+    "MAIN_GUESTPROCESSEVENT", \
+    "MAIN_GUESTPROCESSINPUTNOTIFYEVENT", \
+    "MAIN_GUESTPROCESSIOEVENT", \
+    "MAIN_GUESTPROCESSOUTPUTEVENT", \
+    "MAIN_GUESTPROCESSREGISTEREDEVENT", \
+    "MAIN_GUESTPROCESSSTATECHANGEDEVENT", \
+    "MAIN_GUESTPROPERTYCHANGEDEVENT", \
+    "MAIN_GUESTSCREENINFO", \
+    "MAIN_GUESTSESSION", \
+    "MAIN_GUESTSESSIONEVENT", \
+    "MAIN_GUESTSESSIONREGISTEREDEVENT", \
+    "MAIN_GUESTSESSIONSTATECHANGEDEVENT", \
+    "MAIN_GUESTUSERSTATECHANGEDEVENT", \
+    "MAIN_HOST", \
+    "MAIN_HOSTNAMERESOLUTIONCONFIGURATIONCHANGEEVENT", \
+    "MAIN_HOSTNETWORKINTERFACE", \
+    "MAIN_HOSTPCIDEVICEPLUGEVENT", \
+    "MAIN_HOSTUSBDEVICE", \
+    "MAIN_HOSTUSBDEVICEFILTER", \
+    "MAIN_HOSTVIDEOINPUTDEVICE", \
+    "MAIN_INTERNALMACHINECONTROL", \
+    "MAIN_INTERNALSESSIONCONTROL", \
+    "MAIN_KEYBOARD", \
+    "MAIN_KEYBOARDLEDSCHANGEDEVENT", \
+    "MAIN_MACHINE", \
+    "MAIN_MACHINEDATACHANGEDEVENT", \
+    "MAIN_MACHINEDEBUGGER", \
+    "MAIN_MACHINEEVENT", \
+    "MAIN_MACHINEREGISTEREDEVENT", \
+    "MAIN_MACHINESTATECHANGEDEVENT", \
+    "MAIN_MEDIUM",  \
+    "MAIN_MEDIUMATTACHMENT", \
+    "MAIN_MEDIUMCHANGEDEVENT", \
+    "MAIN_MEDIUMCONFIGCHANGEDEVENT", \
+    "MAIN_MEDIUMFORMAT", \
+    "MAIN_MEDIUMREGISTEREDEVENT", \
+    "MAIN_MOUSE",   \
+    "MAIN_MOUSECAPABILITYCHANGEDEVENT", \
+    "MAIN_MOUSEPOINTERSHAPE", \
+    "MAIN_MOUSEPOINTERSHAPECHANGEDEVENT", \
+    "MAIN_NATENGINE", \
+    "MAIN_NATNETWORK", \
+    "MAIN_NATNETWORKALTEREVENT", \
+    "MAIN_NATNETWORKCHANGEDEVENT", \
+    "MAIN_NATNETWORKCREATIONDELETIONEVENT", \
+    "MAIN_NATNETWORKPORTFORWARDEVENT", \
+    "MAIN_NATNETWORKSETTINGEVENT", \
+    "MAIN_NATNETWORKSTARTSTOPEVENT", \
+    "MAIN_NATREDIRECTEVENT", \
+    "MAIN_NETWORKADAPTER", \
+    "MAIN_NETWORKADAPTERCHANGEDEVENT", \
+    "MAIN_PARALLELPORT", \
+    "MAIN_PARALLELPORTCHANGEDEVENT", \
+    "MAIN_PCIADDRESS", \
+    "MAIN_PCIDEVICEATTACHMENT", \
+    "MAIN_PERFORMANCECOLLECTOR", \
+    "MAIN_PERFORMANCEMETRIC", \
+    "MAIN_PROCESS", \
+    "MAIN_PROGRESS", \
+    "MAIN_REUSABLEEVENT", \
+    "MAIN_RUNTIMEERROREVENT", \
+    "MAIN_SERIALPORT", \
+    "MAIN_SERIALPORTCHANGEDEVENT", \
+    "MAIN_SESSION", \
+    "MAIN_SESSIONSTATECHANGEDEVENT", \
+    "MAIN_SHAREDFOLDER", \
+    "MAIN_SHAREDFOLDERCHANGEDEVENT", \
+    "MAIN_SHOWWINDOWEVENT", \
+    "MAIN_SNAPSHOT", \
+    "MAIN_SNAPSHOTCHANGEDEVENT", \
+    "MAIN_SNAPSHOTDELETEDEVENT", \
+    "MAIN_SNAPSHOTEVENT", \
+    "MAIN_SNAPSHOTRESTOREDEVENT", \
+    "MAIN_SNAPSHOTTAKENEVENT", \
+    "MAIN_STATECHANGEDEVENT", \
+    "MAIN_STORAGECONTROLLER", \
+    "MAIN_STORAGECONTROLLERCHANGEDEVENT", \
+    "MAIN_STORAGEDEVICECHANGEDEVENT", \
+    "MAIN_SYSTEMPROPERTIES", \
+    "MAIN_TOKEN", \
+    "MAIN_USBCONTROLLER", \
+    "MAIN_USBCONTROLLERCHANGEDEVENT", \
+    "MAIN_USBDEVICE", \
+    "MAIN_USBDEVICEFILTER", \
+    "MAIN_USBDEVICEFILTERS", \
+    "MAIN_USBDEVICESTATECHANGEDEVENT", \
+    "MAIN_USBPROXYBACKEND", \
+    "MAIN_VBOXSVCAVAILABILITYCHANGEDEVENT", \
+    "MAIN_VETOEVENT", \
+    "MAIN_VFSEXPLORER", \
+    "MAIN_VIDEOCAPTURECHANGEDEVENT", \
+    "MAIN_VIRTUALBOX", \
+    "MAIN_VIRTUALBOXCLIENT", \
+    "MAIN_VIRTUALSYSTEMDESCRIPTION", \
+    "MAIN_VRDESERVER", \
+    "MAIN_VRDESERVERCHANGEDEVENT", \
+    "MAIN_VRDESERVERINFO", \
+    "MAIN_VRDESERVERINFOCHANGEDEVENT", \
+    "MISC",         \
+    "MM",           \
+    "MM_HEAP",      \
+    "MM_HYPER",     \
+    "MM_HYPER_HEAP",\
+    "MM_PHYS",      \
+    "MM_POOL",      \
+    "NAT_SERVICE",  \
+    "NET_ADP_DRV",  \
+    "NET_FLT_DRV",  \
+    "NET_SERVICE",  \
+    "NET_SHAPER",   \
+    "PATM",         \
+    "PDM",          \
+    "PDM_ASYNC_COMPLETION", \
+    "PDM_BLK_CACHE", \
+    "PDM_DEVICE",   \
+    "PDM_DRIVER",   \
+    "PDM_LDR",      \
+    "PDM_QUEUE",    \
+    "PGM",          \
+    "PGM_DYNMAP",   \
+    "PGM_PHYS",     \
+    "PGM_PHYS_ACCESS",\
+    "PGM_POOL",     \
+    "PGM_SHARED",   \
+    "REM",          \
+    "REM_DISAS",    \
+    "REM_HANDLER",  \
+    "REM_IOPORT",   \
+    "REM_MMIO",     \
+    "REM_PRINTF",   \
+    "REM_RUN",      \
+    "SELM",         \
+    "SHARED_CLIPBOARD",\
+    "SHARED_CROPENGL",\
+    "SHARED_FOLDERS",\
+    "SHARED_OPENGL",\
+    "SRV_INTNET",   \
+    "SSM",          \
+    "STAM",         \
+    "SUP",          \
+    "SUP_DRV",      \
+    "TM",           \
+    "TRPM",         \
+    "USB_CARDREADER",\
+    "USB_DRV",      \
+    "USB_FILTER",   \
+    "USB_KBD",      \
+    "USB_MOUSE",    \
+    "USB_MSD",      \
+    "USB_REMOTE",   \
+    "USB_WEBCAM",   \
+    "VGDRV",        \
+    "VBGL",         \
+    "VD",           \
+    "VD_DMG",       \
+    "VD_ISCSI",     \
+    "VD_PARALLELS", \
+    "VD_QCOW",      \
+    "VD_QED",       \
+    "VD_RAW",       \
+    "VD_VDI",       \
+    "VD_VHD",       \
+    "VD_VHDX",      \
+    "VD_VMDK",      \
+    "VM",           \
+    "VMM",          \
+    "VRDE",         \
+    "VRDP",         \
+    "VSCSI",        \
+    "WEBSERVICE",   \
+}
+
+/** @} */
+#endif
diff --git a/ubuntu/vbox/include/VBox/ostypes.h b/ubuntu/vbox/include/VBox/ostypes.h
new file mode 100644 (file)
index 0000000..8f7d492
--- /dev/null
@@ -0,0 +1,170 @@
+/** @file
+ * VirtualBox - Global Guest Operating System definition.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBox_ostypes_h
+#define ___VBox_ostypes_h
+
+#include <iprt/cdefs.h>
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Global list of guest operating system types.
+ *
+ * They are grouped into families. A family identifer is always has
+ * mod 0x10000 == 0. New entries can be added, however other components
+ * depend on the values (e.g. the Qt GUI and guest additions) so the
+ * existing values MUST stay the same.
+ *
+ * Note: distinguish between 32 & 64 bits guest OSes by checking bit 8 (mod 0x100)
+ */
+typedef enum VBOXOSTYPE
+{
+    VBOXOSTYPE_Unknown          = 0,
+    VBOXOSTYPE_Unknown_x64      = 0x00100,
+    VBOXOSTYPE_DOS              = 0x10000,
+    VBOXOSTYPE_Win31            = 0x15000,
+    VBOXOSTYPE_Win9x            = 0x20000,
+    VBOXOSTYPE_Win95            = 0x21000,
+    VBOXOSTYPE_Win98            = 0x22000,
+    VBOXOSTYPE_WinMe            = 0x23000,
+    VBOXOSTYPE_WinNT            = 0x30000,
+    VBOXOSTYPE_WinNT_x64        = 0x30100,
+    VBOXOSTYPE_WinNT4           = 0x31000,
+    VBOXOSTYPE_Win2k            = 0x32000,
+    VBOXOSTYPE_WinXP            = 0x33000,
+    VBOXOSTYPE_WinXP_x64        = 0x33100,
+    VBOXOSTYPE_Win2k3           = 0x34000,
+    VBOXOSTYPE_Win2k3_x64       = 0x34100,
+    VBOXOSTYPE_WinVista         = 0x35000,
+    VBOXOSTYPE_WinVista_x64     = 0x35100,
+    VBOXOSTYPE_Win2k8           = 0x36000,
+    VBOXOSTYPE_Win2k8_x64       = 0x36100,
+    VBOXOSTYPE_Win7             = 0x37000,
+    VBOXOSTYPE_Win7_x64         = 0x37100,
+    VBOXOSTYPE_Win8             = 0x38000,
+    VBOXOSTYPE_Win8_x64         = 0x38100,
+    VBOXOSTYPE_Win2k12_x64      = 0x39100,
+    VBOXOSTYPE_Win81            = 0x3A000,
+    VBOXOSTYPE_Win81_x64        = 0x3A100,
+    VBOXOSTYPE_Win10            = 0x3B000,
+    VBOXOSTYPE_Win10_x64        = 0x3B100,
+    VBOXOSTYPE_Win2k16_x64      = 0x3C100,
+    VBOXOSTYPE_OS2              = 0x40000,
+    VBOXOSTYPE_OS2Warp3         = 0x41000,
+    VBOXOSTYPE_OS2Warp4         = 0x42000,
+    VBOXOSTYPE_OS2Warp45        = 0x43000,
+    VBOXOSTYPE_ECS              = 0x44000,
+    VBOXOSTYPE_OS21x            = 0x48000,
+    VBOXOSTYPE_Linux            = 0x50000,
+    VBOXOSTYPE_Linux_x64        = 0x50100,
+    VBOXOSTYPE_Linux22          = 0x51000,
+    VBOXOSTYPE_Linux24          = 0x52000,
+    VBOXOSTYPE_Linux24_x64      = 0x52100,
+    VBOXOSTYPE_Linux26          = 0x53000,
+    VBOXOSTYPE_Linux26_x64      = 0x53100,
+    VBOXOSTYPE_ArchLinux        = 0x54000,
+    VBOXOSTYPE_ArchLinux_x64    = 0x54100,
+    VBOXOSTYPE_Debian           = 0x55000,
+    VBOXOSTYPE_Debian_x64       = 0x55100,
+    VBOXOSTYPE_OpenSUSE         = 0x56000,
+    VBOXOSTYPE_OpenSUSE_x64     = 0x56100,
+    VBOXOSTYPE_FedoraCore       = 0x57000,
+    VBOXOSTYPE_FedoraCore_x64   = 0x57100,
+    VBOXOSTYPE_Gentoo           = 0x58000,
+    VBOXOSTYPE_Gentoo_x64       = 0x58100,
+    VBOXOSTYPE_Mandriva         = 0x59000,
+    VBOXOSTYPE_Mandriva_x64     = 0x59100,
+    VBOXOSTYPE_RedHat           = 0x5A000,
+    VBOXOSTYPE_RedHat_x64       = 0x5A100,
+    VBOXOSTYPE_Turbolinux       = 0x5B000,
+    VBOXOSTYPE_Turbolinux_x64   = 0x5B100,
+    VBOXOSTYPE_Ubuntu           = 0x5C000,
+    VBOXOSTYPE_Ubuntu_x64       = 0x5C100,
+    VBOXOSTYPE_Xandros          = 0x5D000,
+    VBOXOSTYPE_Xandros_x64      = 0x5D100,
+    VBOXOSTYPE_Oracle           = 0x5E000,
+    VBOXOSTYPE_Oracle_x64       = 0x5E100,
+    VBOXOSTYPE_FreeBSD          = 0x60000,
+    VBOXOSTYPE_FreeBSD_x64      = 0x60100,
+    VBOXOSTYPE_OpenBSD          = 0x61000,
+    VBOXOSTYPE_OpenBSD_x64      = 0x61100,
+    VBOXOSTYPE_NetBSD           = 0x62000,
+    VBOXOSTYPE_NetBSD_x64       = 0x62100,
+    VBOXOSTYPE_Netware          = 0x70000,
+    VBOXOSTYPE_Solaris          = 0x80000,
+    VBOXOSTYPE_Solaris_x64      = 0x80100,
+    VBOXOSTYPE_OpenSolaris      = 0x81000,
+    VBOXOSTYPE_OpenSolaris_x64  = 0x81100,
+    VBOXOSTYPE_Solaris11_x64    = 0x82100,
+    VBOXOSTYPE_L4               = 0x90000,
+    VBOXOSTYPE_QNX              = 0xA0000,
+    VBOXOSTYPE_MacOS            = 0xB0000,
+    VBOXOSTYPE_MacOS_x64        = 0xB0100,
+    VBOXOSTYPE_MacOS106         = 0xB2000,
+    VBOXOSTYPE_MacOS106_x64     = 0xB2100,
+    VBOXOSTYPE_MacOS107_x64     = 0xB3100,
+    VBOXOSTYPE_MacOS108_x64     = 0xB4100,
+    VBOXOSTYPE_MacOS109_x64     = 0xB5100,
+    VBOXOSTYPE_MacOS1010_x64    = 0xB6100,
+    VBOXOSTYPE_MacOS1011_x64    = 0xB7100,
+    VBOXOSTYPE_MacOS1012_x64    = 0xB8100,
+    VBOXOSTYPE_MacOS1013_x64    = 0xB9100,
+    VBOXOSTYPE_JRockitVE        = 0xC0000,
+    VBOXOSTYPE_Haiku            = 0xD0000,
+    VBOXOSTYPE_Haiku_x64        = 0xD0100,
+    VBOXOSTYPE_VBoxBS_x64       = 0xE0100,
+/** The bit number which indicates 64-bit or 32-bit. */
+#define VBOXOSTYPE_x64_BIT       8
+    /** The mask which indicates 64-bit. */
+    VBOXOSTYPE_x64            = 1 << VBOXOSTYPE_x64_BIT,
+    /** The usual 32-bit hack. */
+    VBOXOSTYPE_32BIT_HACK = 0x7fffffff
+} VBOXOSTYPE;
+
+
+/**
+ * Global list of guest OS families.
+ */
+typedef enum VBOXOSFAMILY
+{
+    VBOXOSFAMILY_Unknown          = 0,
+    VBOXOSFAMILY_Windows32        = 1,
+    VBOXOSFAMILY_Windows64        = 2,
+    VBOXOSFAMILY_Linux32          = 3,
+    VBOXOSFAMILY_Linux64          = 4,
+    VBOXOSFAMILY_FreeBSD32        = 5,
+    VBOXOSFAMILY_FreeBSD64        = 6,
+    VBOXOSFAMILY_Solaris32        = 7,
+    VBOXOSFAMILY_Solaris64        = 8,
+    VBOXOSFAMILY_MacOSX32         = 9,
+    VBOXOSFAMILY_MacOSX64         = 10,
+    /** The usual 32-bit hack. */
+    VBOXOSFAMILY_32BIT_HACK = 0x7fffffff
+} VBOXOSFAMILY;
+
+RT_C_DECLS_END
+
+#endif
diff --git a/ubuntu/vbox/include/VBox/param.h b/ubuntu/vbox/include/VBox/param.h
new file mode 100644 (file)
index 0000000..f3c0001
--- /dev/null
@@ -0,0 +1,190 @@
+/** @file
+ * VirtualBox Parameter Definitions. (VMM,+)
+ *
+ * param.mac is generated from this file by running 'kmk incs' in the root.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBox_param_h
+#define ___VBox_param_h
+
+#include <iprt/param.h>
+#include <iprt/cdefs.h>
+
+
+/** @defgroup   grp_vbox_param  VBox Parameter Definition
+ * @{
+ */
+
+/** The maximum number of pages that can be allocated and mapped
+ * by various MM, PGM and SUP APIs. */
+#if ARCH_BITS == 64
+# define VBOX_MAX_ALLOC_PAGE_COUNT   (_512M / PAGE_SIZE)
+#else
+# define VBOX_MAX_ALLOC_PAGE_COUNT   (_256M / PAGE_SIZE)
+#endif
+
+/** @def VBOX_WITH_PAGE_SHARING
+ * Enables the page sharing code.
+ * @remarks This must match GMMR0Init; currently we only support page fusion on
+ *          all 64-bit hosts except Mac OS X */
+#if (   HC_ARCH_BITS == 64          /* ASM-NOINC */ \
+     && (defined(RT_OS_FREEBSD) || defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS)) ) /* ASM-NOINC */ \
+ || defined(DOXYGEN_RUNNING)        /* ASM-NOINC */
+# define VBOX_WITH_PAGE_SHARING     /* ASM-NOINC */
+#endif                              /* ASM-NOINC */
+
+
+/** @defgroup   grp_vbox_param_mm  Memory Monitor Parameters
+ * @{
+ */
+/** Initial address of Hypervisor Memory Area.
+ * MUST BE PAGE TABLE ALIGNED! */
+#define MM_HYPER_AREA_ADDRESS       UINT32_C(0xa0000000)
+
+/** The max size of the hypervisor memory area. */
+#define MM_HYPER_AREA_MAX_SIZE      (40U * _1M) /**< @todo Readjust when floating RAMRANGEs have been implemented. Used to be 20 * _1MB */
+
+/** Maximum number of bytes we can dynamically map into the hypervisor region.
+ * This must be a power of 2 number of pages!
+ */
+#define MM_HYPER_DYNAMIC_SIZE       (16U * PAGE_SIZE)
+
+/** The minimum guest RAM size in bytes. */
+#define MM_RAM_MIN                  UINT32_C(0x00400000)
+/** The maximum guest RAM size in bytes. */
+#if HC_ARCH_BITS == 64
+# define MM_RAM_MAX                 UINT64_C(0x20000000000)
+#else
+# define MM_RAM_MAX                 UINT64_C(0x000E0000000)
+#endif
+/** The minimum guest RAM size in MBs. */
+#define MM_RAM_MIN_IN_MB            UINT32_C(4)
+/** The maximum guest RAM size in MBs. */
+#if HC_ARCH_BITS == 64
+# define MM_RAM_MAX_IN_MB           UINT32_C(2097152)
+#else
+# define MM_RAM_MAX_IN_MB           UINT32_C(3584)
+#endif
+/** The default size of the below 4GB RAM hole. */
+#define MM_RAM_HOLE_SIZE_DEFAULT    (512U * _1M)
+/** The maximum 64-bit MMIO BAR size.
+ * @remarks There isn't really any limit here other than the size of the
+ *          tracking structures we need (around 1/256 of the size). */
+#if HC_ARCH_BITS == 64
+# define MM_MMIO_64_MAX             _1T
+#else
+# define MM_MMIO_64_MAX             (_1G64 * 16)
+#endif
+/** The maximum 32-bit MMIO BAR size. */
+#define MM_MMIO_32_MAX              _2G
+
+/** @} */
+
+
+/** @defgroup   grp_vbox_param_pgm  Page Manager Parameters
+ * @{
+ */
+/** The number of handy pages.
+ * This should be a power of two. */
+#define PGM_HANDY_PAGES             128
+/** The threshold at which allocation of more handy pages is flagged. */
+#define PGM_HANDY_PAGES_SET_FF      32
+/** The threshold at which we will allocate more when in ring-3.
+ * This is must be smaller than both PGM_HANDY_PAGES_SET_FF and
+ * PGM_HANDY_PAGES_MIN. */
+#define PGM_HANDY_PAGES_R3_ALLOC    8
+/** The threshold at which we will allocate more when in ring-0 or raw mode.
+ * The idea is that we should never go below this threshold while in ring-0 or
+ * raw mode because of PGM_HANDY_PAGES_RZ_TO_R3. However, should this happen and
+ * we are actually out of memory, we will have 8 page to get out of whatever
+ * code we're executing.
+ *
+ * This is must be smaller than both PGM_HANDY_PAGES_SET_FF and
+ * PGM_HANDY_PAGES_MIN. */
+#define PGM_HANDY_PAGES_RZ_ALLOC    8
+/** The threshold at which we force return to R3 ASAP.
+ * The idea is that this should be large enough to get out of any code and up to
+ * the main EM loop when we are out of memory.
+ * This must be less or equal to PGM_HANDY_PAGES_MIN. */
+#define PGM_HANDY_PAGES_RZ_TO_R3    24
+/** The minimum number of handy pages (after allocation).
+ * This must be greater or equal to PGM_HANDY_PAGES_SET_FF.
+ * Another name would be PGM_HANDY_PAGES_EXTRA_RESERVATION or _PARANOIA. :-) */
+#define PGM_HANDY_PAGES_MIN         32
+/** @} */
+
+
+/** @defgroup   grp_vbox_param_vmm  VMM Parameters
+ * @{
+ */
+/** VMM stack size. */
+#ifdef RT_OS_DARWIN
+# define VMM_STACK_SIZE             16384U
+#else
+# define VMM_STACK_SIZE             8192U
+#endif
+/** Min number of Virtual CPUs. */
+#define VMM_MIN_CPU_COUNT           1
+/** Max number of Virtual CPUs. */
+#define VMM_MAX_CPU_COUNT           64
+
+/** @} */
+
+
+/** @defgroup   grp_vbox_pci        PCI Identifiers
+ * @{ */
+/** VirtualBox PCI vendor ID. */
+#define VBOX_PCI_VENDORID           (0x80ee)
+
+/** @name VirtualBox graphics card identifiers
+ * @{ */
+#define VBOX_VENDORID               VBOX_PCI_VENDORID   /**< @todo wonderful choice of name! Please squeeze a _VGA_ or something in there, please. */
+#define VBOX_DEVICEID               (0xbeef)            /**< @todo ditto. */
+#define VBOX_VESA_VENDORID          VBOX_PCI_VENDORID
+#define VBOX_VESA_DEVICEID          (0xbeef)
+/** @} */
+
+/** @name VMMDev PCI card identifiers
+ * @{ */
+#define VMMDEV_VENDORID             VBOX_PCI_VENDORID
+#define VMMDEV_DEVICEID             (0xcafe)
+/** @} */
+
+/** @} */
+
+
+/** @defgroup grp_vbox_param_misc  Misc
+ * @{ */
+
+/** The maximum size of a generic segment offload (GSO) frame.  This limit is
+ *  imposed by the 16-bit frame size in internal networking header. */
+#define VBOX_MAX_GSO_SIZE           0xfff0
+
+/** @} */
+
+
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/VBox/shflsvc.h b/ubuntu/vbox/include/VBox/shflsvc.h
new file mode 100644 (file)
index 0000000..0a0f513
--- /dev/null
@@ -0,0 +1,1423 @@
+/** @file
+ * Shared Folders: Common header for host service and guest clients.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBox_shflsvc_h
+#define ___VBox_shflsvc_h
+
+#include <VBox/types.h>
+#include <VBox/VBoxGuest2.h>
+#include <VBox/VMMDev.h>
+#include <VBox/hgcmsvc.h>
+#include <iprt/fs.h>
+
+
+/** @name Some bit flag manipulation macros.
+ * @{  */
+#ifndef BIT_FLAG
+#define BIT_FLAG(__Field,__Flag)       ((__Field) & (__Flag))
+#endif
+
+#ifndef BIT_FLAG_SET
+#define BIT_FLAG_SET(__Field,__Flag)   ((__Field) |= (__Flag))
+#endif
+
+#ifndef BIT_FLAG_CLEAR
+#define BIT_FLAG_CLEAR(__Field,__Flag) ((__Field) &= ~(__Flag))
+#endif
+/** @} */
+
+
+/**
+ * Structures shared between guest and the service
+ * can be relocated and use offsets to point to variable
+ * length parts.
+ */
+
+/**
+ * Shared folders protocol works with handles.
+ * Before doing any action on a file system object,
+ * one have to obtain the object handle via a SHFL_FN_CREATE
+ * request. A handle must be closed with SHFL_FN_CLOSE.
+ */
+
+/** Shared Folders service functions. (guest)
+ *  @{
+ */
+
+/** Query mappings changes. */
+#define SHFL_FN_QUERY_MAPPINGS      (1)
+/** Query mappings changes. */
+#define SHFL_FN_QUERY_MAP_NAME      (2)
+/** Open/create object. */
+#define SHFL_FN_CREATE              (3)
+/** Close object handle. */
+#define SHFL_FN_CLOSE               (4)
+/** Read object content. */
+#define SHFL_FN_READ                (5)
+/** Write new object content. */
+#define SHFL_FN_WRITE               (6)
+/** Lock/unlock a range in the object. */
+#define SHFL_FN_LOCK                (7)
+/** List object content. */
+#define SHFL_FN_LIST                (8)
+/** Query/set object information. */
+#define SHFL_FN_INFORMATION         (9)
+/** Remove object */
+#define SHFL_FN_REMOVE              (11)
+/** Map folder (legacy) */
+#define SHFL_FN_MAP_FOLDER_OLD      (12)
+/** Unmap folder */
+#define SHFL_FN_UNMAP_FOLDER        (13)
+/** Rename object (possibly moving it to another directory) */
+#define SHFL_FN_RENAME              (14)
+/** Flush file */
+#define SHFL_FN_FLUSH               (15)
+/** @todo macl, a description, please. */
+#define SHFL_FN_SET_UTF8            (16)
+/** Map folder */
+#define SHFL_FN_MAP_FOLDER          (17)
+/** Read symlink destination (as of VBox 4.0) */
+#define SHFL_FN_READLINK            (18)
+/** Create symlink (as of VBox 4.0) */
+#define SHFL_FN_SYMLINK             (19)
+/** Ask host to show symlinks (as of VBox 4.0) */
+#define SHFL_FN_SET_SYMLINKS        (20)
+
+/** @} */
+
+/** Shared Folders service functions. (host)
+ *  @{
+ */
+
+/** Add shared folder mapping. */
+#define SHFL_FN_ADD_MAPPING         (1)
+/** Remove shared folder mapping. */
+#define SHFL_FN_REMOVE_MAPPING      (2)
+/** Set the led status light address. */
+#define SHFL_FN_SET_STATUS_LED      (3)
+/** Allow the guest to create symbolic links (as of VBox 4.0) */
+#define SHFL_FN_ALLOW_SYMLINKS_CREATE (4)
+/** @} */
+
+/** Root handle for a mapping. Root handles are unique.
+ *  @note
+ *  Function parameters structures consider
+ *  the root handle as 32 bit value. If the typedef
+ *  will be changed, then function parameters must be
+ *  changed accordingly. All those parameters are marked
+ *  with SHFLROOT in comments.
+ */
+typedef uint32_t SHFLROOT;
+
+#define SHFL_ROOT_NIL ((SHFLROOT)~0)
+
+
+/** A shared folders handle for an opened object. */
+typedef uint64_t SHFLHANDLE;
+
+#define SHFL_HANDLE_NIL  ((SHFLHANDLE)~0LL)
+#define SHFL_HANDLE_ROOT ((SHFLHANDLE)0LL)
+
+/** Hardcoded maximum length (in chars) of a shared folder name. */
+#define SHFL_MAX_LEN         (256)
+/** Hardcoded maximum number of shared folder mapping available to the guest. */
+#define SHFL_MAX_MAPPINGS    (64)
+
+/** @name Shared Folders strings. They can be either UTF-8 or UTF-16.
+ * @{
+ */
+
+/**
+ * Shared folder string buffer structure.
+ */
+#pragma pack(1)
+typedef struct _SHFLSTRING
+{
+    /** Allocated size of the String member in bytes. */
+    uint16_t u16Size;
+
+    /** Length of string without trailing nul in bytes. */
+    uint16_t u16Length;
+
+    /** UTF-8 or UTF-16 string. Nul terminated. */
+    union
+    {
+        uint8_t  utf8[1];
+        uint16_t ucs2[1];
+    } String;
+} SHFLSTRING;
+#pragma pack()
+
+#define SHFLSTRING_HEADER_SIZE RT_UOFFSETOF(SHFLSTRING, String)
+
+/** Pointer to a shared folder string buffer. */
+typedef SHFLSTRING *PSHFLSTRING;
+/** Pointer to a const shared folder string buffer. */
+typedef const SHFLSTRING *PCSHFLSTRING;
+
+/** Calculate size of the string. */
+DECLINLINE(uint32_t) ShflStringSizeOfBuffer(PCSHFLSTRING pString)
+{
+    return pString ? (uint32_t)(sizeof(SHFLSTRING) - sizeof(pString->String) + pString->u16Size) : 0;
+}
+
+DECLINLINE(uint32_t) ShflStringLength(PCSHFLSTRING pString)
+{
+    return pString ? pString->u16Length : 0;
+}
+
+DECLINLINE(PSHFLSTRING) ShflStringInitBuffer(void *pvBuffer, uint32_t u32Size)
+{
+    PSHFLSTRING pString = NULL;
+    const uint32_t u32HeaderSize = SHFLSTRING_HEADER_SIZE;
+
+    /*
+     * Check that the buffer size is big enough to hold a zero sized string
+     * and is not too big to fit into 16 bit variables.
+     */
+    if (u32Size >= u32HeaderSize && u32Size - u32HeaderSize <= 0xFFFF)
+    {
+        pString = (PSHFLSTRING)pvBuffer;
+        pString->u16Size = (uint16_t)(u32Size - u32HeaderSize);
+        pString->u16Length = 0;
+        if (pString->u16Size >= sizeof(pString->String.ucs2[0]))
+            pString->String.ucs2[0] = 0;
+        else if (pString->u16Size >= sizeof(pString->String.utf8[0]))
+            pString->String.utf8[0] = 0;
+    }
+
+    return pString;
+}
+
+/**
+ * Validates a HGCM string output parameter.
+ *
+ * @returns true if valid, false if not.
+ *
+ * @param   pString     The string buffer pointer.
+ * @param   cbBuf       The buffer size from the parameter.
+ */
+DECLINLINE(bool) ShflStringIsValidOut(PCSHFLSTRING pString, uint32_t cbBuf)
+{
+    if (RT_LIKELY(cbBuf > RT_UOFFSETOF(SHFLSTRING, String)))
+        if (RT_LIKELY((uint32_t)pString->u16Size + RT_UOFFSETOF(SHFLSTRING, String) <= cbBuf))
+            if (RT_LIKELY(pString->u16Length < pString->u16Size))
+                return true;
+    return false;
+}
+
+/**
+ * Validates a HGCM string input parameter.
+ *
+ * @returns true if valid, false if not.
+ *
+ * @param   pString     The string buffer pointer.
+ * @param   cbBuf       The buffer size from the parameter.
+ * @param   fUtf8Not16  Set if UTF-8 encoding, clear if UTF-16 encoding.
+ */
+DECLINLINE(bool) ShflStringIsValidIn(PCSHFLSTRING pString, uint32_t cbBuf, bool fUtf8Not16)
+{
+    int rc;
+    if (RT_LIKELY(cbBuf > RT_UOFFSETOF(SHFLSTRING, String)))
+    {
+        if (RT_LIKELY((uint32_t)pString->u16Size + RT_UOFFSETOF(SHFLSTRING, String) <= cbBuf))
+        {
+            if (fUtf8Not16)
+            {
+                /* UTF-8: */
+                if (RT_LIKELY(pString->u16Length < pString->u16Size))
+                {
+                    rc = RTStrValidateEncodingEx((const char *)&pString->String.utf8[0], pString->u16Length + 1,
+                                                 RTSTR_VALIDATE_ENCODING_EXACT_LENGTH | RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
+                    if (RT_SUCCESS(rc))
+                        return true;
+                }
+            }
+            else
+            {
+                /* UTF-16: */
+                if (RT_LIKELY(!(pString->u16Length & 1)))
+                {
+                    if (RT_LIKELY((uint32_t)sizeof(RTUTF16) + pString->u16Length <= pString->u16Size))
+                    {
+                        rc = RTUtf16ValidateEncodingEx(&pString->String.ucs2[0], pString->u16Length / 2 + 1,
+                                                       RTSTR_VALIDATE_ENCODING_EXACT_LENGTH
+                                                       | RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
+                        if (RT_SUCCESS(rc))
+                            return true;
+                    }
+                }
+            }
+        }
+    }
+    return false;
+}
+
+/**
+ * Validates an optional HGCM string input parameter.
+ *
+ * @returns true if valid, false if not.
+ *
+ * @param   pString     The string buffer pointer. Can be NULL.
+ * @param   cbBuf       The buffer size from the parameter.
+ * @param   fUtf8Not16  Set if UTF-8 encoding, clear if UTF-16 encoding.
+ */
+DECLINLINE(bool) ShflStringIsValidOrNullIn(PCSHFLSTRING pString, uint32_t cbBuf, bool fUtf8Not16)
+{
+    if (pString)
+        return ShflStringIsValidIn(pString, cbBuf, fUtf8Not16);
+    if (RT_LIKELY(cbBuf == 0))
+        return true;
+    return false;
+}
+
+/** @} */
+
+
+/**
+ * The available additional information in a SHFLFSOBJATTR object.
+ */
+typedef enum SHFLFSOBJATTRADD
+{
+    /** No additional information is available / requested. */
+    SHFLFSOBJATTRADD_NOTHING = 1,
+    /** The additional unix attributes (SHFLFSOBJATTR::u::Unix) are
+     *  available / requested. */
+    SHFLFSOBJATTRADD_UNIX,
+    /** The additional extended attribute size (SHFLFSOBJATTR::u::EASize) is
+     *  available / requested. */
+    SHFLFSOBJATTRADD_EASIZE,
+    /** The last valid item (inclusive).
+     * The valid range is SHFLFSOBJATTRADD_NOTHING thru
+     * SHFLFSOBJATTRADD_LAST. */
+    SHFLFSOBJATTRADD_LAST = SHFLFSOBJATTRADD_EASIZE,
+
+    /** The usual 32-bit hack. */
+    SHFLFSOBJATTRADD_32BIT_SIZE_HACK = 0x7fffffff
+} SHFLFSOBJATTRADD;
+
+
+/* Assert sizes of the IRPT types we're using below. */
+AssertCompileSize(RTFMODE,      4);
+AssertCompileSize(RTFOFF,       8);
+AssertCompileSize(RTINODE,      8);
+AssertCompileSize(RTTIMESPEC,   8);
+AssertCompileSize(RTDEV,        4);
+AssertCompileSize(RTUID,        4);
+
+/**
+ * Shared folder filesystem object attributes.
+ */
+#pragma pack(1)
+typedef struct SHFLFSOBJATTR
+{
+    /** Mode flags (st_mode). RTFS_UNIX_*, RTFS_TYPE_*, and RTFS_DOS_*.
+     * @remarks We depend on a number of RTFS_ defines to remain unchanged.
+     *          Fortuntately, these are depending on windows, dos and unix
+     *          standard values, so this shouldn't be much of a pain. */
+    RTFMODE         fMode;
+
+    /** The additional attributes available. */
+    SHFLFSOBJATTRADD  enmAdditional;
+
+    /**
+     * Additional attributes.
+     *
+     * Unless explicitly specified to an API, the API can provide additional
+     * data as it is provided by the underlying OS.
+     */
+    union SHFLFSOBJATTRUNION
+    {
+        /** Additional Unix Attributes
+         * These are available when SHFLFSOBJATTRADD is set in fUnix.
+         */
+         struct SHFLFSOBJATTRUNIX
+         {
+            /** The user owning the filesystem object (st_uid).
+             * This field is ~0U if not supported. */
+            RTUID           uid;
+
+            /** The group the filesystem object is assigned (st_gid).
+             * This field is ~0U if not supported. */
+            RTGID           gid;
+
+            /** Number of hard links to this filesystem object (st_nlink).
+             * This field is 1 if the filesystem doesn't support hardlinking or
+             * the information isn't available.
+             */
+            uint32_t        cHardlinks;
+
+            /** The device number of the device which this filesystem object resides on (st_dev).
+             * This field is 0 if this information is not available. */
+            RTDEV           INodeIdDevice;
+
+            /** The unique identifier (within the filesystem) of this filesystem object (st_ino).
+             * Together with INodeIdDevice, this field can be used as a OS wide unique id
+             * when both their values are not 0.
+             * This field is 0 if the information is not available. */
+            RTINODE         INodeId;
+
+            /** User flags (st_flags).
+             * This field is 0 if this information is not available. */
+            uint32_t        fFlags;
+
+            /** The current generation number (st_gen).
+             * This field is 0 if this information is not available. */
+            uint32_t        GenerationId;
+
+            /** The device number of a character or block device type object (st_rdev).
+             * This field is 0 if the file isn't of a character or block device type and
+             * when the OS doesn't subscribe to the major+minor device idenfication scheme. */
+            RTDEV           Device;
+        } Unix;
+
+        /**
+         * Extended attribute size.
+         */
+        struct SHFLFSOBJATTREASIZE
+        {
+            /** Size of EAs. */
+            RTFOFF          cb;
+        } EASize;
+    } u;
+} SHFLFSOBJATTR;
+#pragma pack()
+AssertCompileSize(SHFLFSOBJATTR, 44);
+/** Pointer to a shared folder filesystem object attributes structure. */
+typedef SHFLFSOBJATTR *PSHFLFSOBJATTR;
+/** Pointer to a const shared folder filesystem object attributes structure. */
+typedef const SHFLFSOBJATTR *PCSHFLFSOBJATTR;
+
+
+/**
+ * Filesystem object information structure.
+ */
+#pragma pack(1)
+typedef struct SHFLFSOBJINFO
+{
+   /** Logical size (st_size).
+    * For normal files this is the size of the file.
+    * For symbolic links, this is the length of the path name contained
+    * in the symbolic link.
+    * For other objects this fields needs to be specified.
+    */
+   RTFOFF       cbObject;
+
+   /** Disk allocation size (st_blocks * DEV_BSIZE). */
+   RTFOFF       cbAllocated;
+
+   /** Time of last access (st_atime).
+    * @remarks  Here (and other places) we depend on the IPRT timespec to
+    *           remain unchanged. */
+   RTTIMESPEC   AccessTime;
+
+   /** Time of last data modification (st_mtime). */
+   RTTIMESPEC   ModificationTime;
+
+   /** Time of last status change (st_ctime).
+    * If not available this is set to ModificationTime.
+    */
+   RTTIMESPEC   ChangeTime;
+
+   /** Time of file birth (st_birthtime).
+    * If not available this is set to ChangeTime.
+    */
+   RTTIMESPEC   BirthTime;
+
+   /** Attributes. */
+   SHFLFSOBJATTR Attr;
+
+} SHFLFSOBJINFO;
+#pragma pack()
+AssertCompileSize(SHFLFSOBJINFO, 92);
+/** Pointer to a shared folder filesystem object information structure. */
+typedef SHFLFSOBJINFO *PSHFLFSOBJINFO;
+/** Pointer to a const shared folder filesystem object information
+ *  structure. */
+typedef const SHFLFSOBJINFO *PCSHFLFSOBJINFO;
+
+
+/**
+ * Copy file system objinfo from IPRT to shared folder format.
+ *
+ * @param   pDst                The shared folder structure.
+ * @param   pSrc                The IPRT structure.
+ */
+DECLINLINE(void) vbfsCopyFsObjInfoFromIprt(PSHFLFSOBJINFO pDst, PCRTFSOBJINFO pSrc)
+{
+    pDst->cbObject          = pSrc->cbObject;
+    pDst->cbAllocated       = pSrc->cbAllocated;
+    pDst->AccessTime        = pSrc->AccessTime;
+    pDst->ModificationTime  = pSrc->ModificationTime;
+    pDst->ChangeTime        = pSrc->ChangeTime;
+    pDst->BirthTime         = pSrc->BirthTime;
+    pDst->Attr.fMode        = pSrc->Attr.fMode;
+    RT_ZERO(pDst->Attr.u);
+    switch (pSrc->Attr.enmAdditional)
+    {
+        default:
+        case RTFSOBJATTRADD_NOTHING:
+            pDst->Attr.enmAdditional        = SHFLFSOBJATTRADD_NOTHING;
+            break;
+
+        case RTFSOBJATTRADD_UNIX:
+            pDst->Attr.enmAdditional        = SHFLFSOBJATTRADD_UNIX;
+            pDst->Attr.u.Unix.uid           = pSrc->Attr.u.Unix.uid;
+            pDst->Attr.u.Unix.gid           = pSrc->Attr.u.Unix.gid;
+            pDst->Attr.u.Unix.cHardlinks    = pSrc->Attr.u.Unix.cHardlinks;
+            pDst->Attr.u.Unix.INodeIdDevice = pSrc->Attr.u.Unix.INodeIdDevice;
+            pDst->Attr.u.Unix.INodeId       = pSrc->Attr.u.Unix.INodeId;
+            pDst->Attr.u.Unix.fFlags        = pSrc->Attr.u.Unix.fFlags;
+            pDst->Attr.u.Unix.GenerationId  = pSrc->Attr.u.Unix.GenerationId;
+            pDst->Attr.u.Unix.Device        = pSrc->Attr.u.Unix.Device;
+            break;
+
+        case RTFSOBJATTRADD_EASIZE:
+            pDst->Attr.enmAdditional        = SHFLFSOBJATTRADD_EASIZE;
+            pDst->Attr.u.EASize.cb          = pSrc->Attr.u.EASize.cb;
+            break;
+    }
+}
+
+
+/** Result of an open/create request.
+ *  Along with handle value the result code
+ *  identifies what has happened while
+ *  trying to open the object.
+ */
+typedef enum _SHFLCREATERESULT
+{
+    SHFL_NO_RESULT,
+    /** Specified path does not exist. */
+    SHFL_PATH_NOT_FOUND,
+    /** Path to file exists, but the last component does not. */
+    SHFL_FILE_NOT_FOUND,
+    /** File already exists and either has been opened or not. */
+    SHFL_FILE_EXISTS,
+    /** New file was created. */
+    SHFL_FILE_CREATED,
+    /** Existing file was replaced or overwritten. */
+    SHFL_FILE_REPLACED
+} SHFLCREATERESULT;
+
+
+/** Open/create flags.
+ *  @{
+ */
+
+/** No flags. Initialization value. */
+#define SHFL_CF_NONE                  (0x00000000)
+
+/** Lookup only the object, do not return a handle. All other flags are ignored. */
+#define SHFL_CF_LOOKUP                (0x00000001)
+
+/** Open parent directory of specified object.
+ *  Useful for the corresponding Windows FSD flag
+ *  and for opening paths like \\dir\\*.* to search the 'dir'.
+ *  @todo possibly not needed???
+ */
+#define SHFL_CF_OPEN_TARGET_DIRECTORY (0x00000002)
+
+/** Create/open a directory. */
+#define SHFL_CF_DIRECTORY             (0x00000004)
+
+/** Open/create action to do if object exists
+ *  and if the object does not exists.
+ *  REPLACE file means atomically DELETE and CREATE.
+ *  OVERWRITE file means truncating the file to 0 and
+ *  setting new size.
+ *  When opening an existing directory REPLACE and OVERWRITE
+ *  actions are considered invalid, and cause returning
+ *  FILE_EXISTS with NIL handle.
+ */
+#define SHFL_CF_ACT_MASK_IF_EXISTS      (0x000000F0)
+#define SHFL_CF_ACT_MASK_IF_NEW         (0x00000F00)
+
+/** What to do if object exists. */
+#define SHFL_CF_ACT_OPEN_IF_EXISTS      (0x00000000)
+#define SHFL_CF_ACT_FAIL_IF_EXISTS      (0x00000010)
+#define SHFL_CF_ACT_REPLACE_IF_EXISTS   (0x00000020)
+#define SHFL_CF_ACT_OVERWRITE_IF_EXISTS (0x00000030)
+
+/** What to do if object does not exist. */
+#define SHFL_CF_ACT_CREATE_IF_NEW       (0x00000000)
+#define SHFL_CF_ACT_FAIL_IF_NEW         (0x00000100)
+
+/** Read/write requested access for the object. */
+#define SHFL_CF_ACCESS_MASK_RW          (0x00003000)
+
+/** No access requested. */
+#define SHFL_CF_ACCESS_NONE             (0x00000000)
+/** Read access requested. */
+#define SHFL_CF_ACCESS_READ             (0x00001000)
+/** Write access requested. */
+#define SHFL_CF_ACCESS_WRITE            (0x00002000)
+/** Read/Write access requested. */
+#define SHFL_CF_ACCESS_READWRITE        (SHFL_CF_ACCESS_READ | SHFL_CF_ACCESS_WRITE)
+
+/** Requested share access for the object. */
+#define SHFL_CF_ACCESS_MASK_DENY        (0x0000C000)
+
+/** Allow any access. */
+#define SHFL_CF_ACCESS_DENYNONE         (0x00000000)
+/** Do not allow read. */
+#define SHFL_CF_ACCESS_DENYREAD         (0x00004000)
+/** Do not allow write. */
+#define SHFL_CF_ACCESS_DENYWRITE        (0x00008000)
+/** Do not allow access. */
+#define SHFL_CF_ACCESS_DENYALL          (SHFL_CF_ACCESS_DENYREAD | SHFL_CF_ACCESS_DENYWRITE)
+
+/** Requested access to attributes of the object. */
+#define SHFL_CF_ACCESS_MASK_ATTR        (0x00030000)
+
+/** No access requested. */
+#define SHFL_CF_ACCESS_ATTR_NONE        (0x00000000)
+/** Read access requested. */
+#define SHFL_CF_ACCESS_ATTR_READ        (0x00010000)
+/** Write access requested. */
+#define SHFL_CF_ACCESS_ATTR_WRITE       (0x00020000)
+/** Read/Write access requested. */
+#define SHFL_CF_ACCESS_ATTR_READWRITE   (SHFL_CF_ACCESS_ATTR_READ | SHFL_CF_ACCESS_ATTR_WRITE)
+
+/** The file is opened in append mode. Ignored if SHFL_CF_ACCESS_WRITE is not set. */
+#define SHFL_CF_ACCESS_APPEND           (0x00040000)
+
+/** @} */
+
+#pragma pack(1)
+typedef struct _SHFLCREATEPARMS
+{
+    /* Returned handle of opened object. */
+    SHFLHANDLE Handle;
+
+    /* Returned result of the operation */
+    SHFLCREATERESULT Result;
+
+    /* SHFL_CF_* */
+    uint32_t CreateFlags;
+
+    /* Attributes of object to create and
+     * returned actual attributes of opened/created object.
+     */
+    SHFLFSOBJINFO Info;
+
+} SHFLCREATEPARMS;
+#pragma pack()
+
+typedef SHFLCREATEPARMS *PSHFLCREATEPARMS;
+
+
+/** Shared Folders mappings.
+ *  @{
+ */
+
+/** The mapping has been added since last query. */
+#define SHFL_MS_NEW        (1)
+/** The mapping has been deleted since last query. */
+#define SHFL_MS_DELETED    (2)
+
+typedef struct _SHFLMAPPING
+{
+    /** Mapping status. */
+    uint32_t u32Status;
+    /** Root handle. */
+    SHFLROOT root;
+} SHFLMAPPING;
+/** Pointer to a SHFLMAPPING structure. */
+typedef SHFLMAPPING *PSHFLMAPPING;
+
+/** @} */
+
+/** Shared Folder directory information
+ *  @{
+ */
+
+typedef struct _SHFLDIRINFO
+{
+    /** Full information about the object. */
+    SHFLFSOBJINFO   Info;
+    /** The length of the short field (number of RTUTF16 chars).
+     * It is 16-bit for reasons of alignment. */
+    uint16_t        cucShortName;
+    /** The short name for 8.3 compatibility.
+     * Empty string if not available.
+     */
+    RTUTF16         uszShortName[14];
+    /** @todo malc, a description, please. */
+    SHFLSTRING      name;
+} SHFLDIRINFO, *PSHFLDIRINFO;
+
+
+/**
+ * Shared folder filesystem properties.
+ */
+typedef struct SHFLFSPROPERTIES
+{
+    /** The maximum size of a filesystem object name.
+     * This does not include the '\\0'. */
+    uint32_t cbMaxComponent;
+
+    /** True if the filesystem is remote.
+     * False if the filesystem is local. */
+    bool    fRemote;
+
+    /** True if the filesystem is case sensitive.
+     * False if the filesystem is case insensitive. */
+    bool    fCaseSensitive;
+
+    /** True if the filesystem is mounted read only.
+     * False if the filesystem is mounted read write. */
+    bool    fReadOnly;
+
+    /** True if the filesystem can encode unicode object names.
+     * False if it can't. */
+    bool    fSupportsUnicode;
+
+    /** True if the filesystem is compresses.
+     * False if it isn't or we don't know. */
+    bool    fCompressed;
+
+    /** True if the filesystem compresses of individual files.
+     * False if it doesn't or we don't know. */
+    bool    fFileCompression;
+
+    /** @todo more? */
+} SHFLFSPROPERTIES;
+AssertCompileSize(SHFLFSPROPERTIES, 12);
+/** Pointer to a shared folder filesystem properties structure. */
+typedef SHFLFSPROPERTIES *PSHFLFSPROPERTIES;
+/** Pointer to a const shared folder filesystem properties structure. */
+typedef SHFLFSPROPERTIES const *PCSHFLFSPROPERTIES;
+
+
+/**
+ * Copy file system properties from IPRT to shared folder format.
+ *
+ * @param   pDst                The shared folder structure.
+ * @param   pSrc                The IPRT structure.
+ */
+DECLINLINE(void) vbfsCopyFsPropertiesFromIprt(PSHFLFSPROPERTIES pDst, PCRTFSPROPERTIES pSrc)
+{
+    RT_ZERO(*pDst);                     /* zap the implicit padding. */
+    pDst->cbMaxComponent   = pSrc->cbMaxComponent;
+    pDst->fRemote          = pSrc->fRemote;
+    pDst->fCaseSensitive   = pSrc->fCaseSensitive;
+    pDst->fReadOnly        = pSrc->fReadOnly;
+    pDst->fSupportsUnicode = pSrc->fSupportsUnicode;
+    pDst->fCompressed      = pSrc->fCompressed;
+    pDst->fFileCompression = pSrc->fFileCompression;
+}
+
+
+typedef struct _SHFLVOLINFO
+{
+    RTFOFF         ullTotalAllocationBytes;
+    RTFOFF         ullAvailableAllocationBytes;
+    uint32_t       ulBytesPerAllocationUnit;
+    uint32_t       ulBytesPerSector;
+    uint32_t       ulSerial;
+    SHFLFSPROPERTIES fsProperties;
+} SHFLVOLINFO, *PSHFLVOLINFO;
+
+/** @} */
+
+/** Function parameter structures.
+ *  @{
+ */
+
+/**
+ * SHFL_FN_QUERY_MAPPINGS
+ */
+/** Validation mask.  Needs to be adjusted
+  * whenever a new SHFL_MF_ flag is added. */
+#define SHFL_MF_MASK       (0x00000011)
+/** UC2 enconded strings. */
+#define SHFL_MF_UCS2       (0x00000000)
+/** Guest uses UTF8 strings, if not set then the strings are unicode (UCS2). */
+#define SHFL_MF_UTF8       (0x00000001)
+/** Just handle the auto-mounted folders. */
+#define SHFL_MF_AUTOMOUNT  (0x00000010)
+
+/** Type of guest system. For future system dependent features. */
+#define SHFL_MF_SYSTEM_MASK    (0x0000FF00)
+#define SHFL_MF_SYSTEM_NONE    (0x00000000)
+#define SHFL_MF_SYSTEM_WINDOWS (0x00000100)
+#define SHFL_MF_SYSTEM_LINUX   (0x00000200)
+
+/** Parameters structure. */
+typedef struct _VBoxSFQueryMappings
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** 32bit, in:
+     * Flags describing various client needs.
+     */
+    HGCMFunctionParameter flags;
+
+    /** 32bit, in/out:
+     * Number of mappings the client expects.
+     * This is the number of elements in the
+     * mappings array.
+     */
+    HGCMFunctionParameter numberOfMappings;
+
+    /** pointer, in/out:
+     * Points to array of SHFLMAPPING structures.
+     */
+    HGCMFunctionParameter mappings;
+
+} VBoxSFQueryMappings;
+
+/** Number of parameters */
+#define SHFL_CPARMS_QUERY_MAPPINGS (3)
+
+
+
+/**
+ * SHFL_FN_QUERY_MAP_NAME
+ */
+
+/** Parameters structure. */
+typedef struct _VBoxSFQueryMapName
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** 32bit, in: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+    /** pointer, in/out:
+     * Points to SHFLSTRING buffer.
+     */
+    HGCMFunctionParameter name;
+
+} VBoxSFQueryMapName;
+
+/** Number of parameters */
+#define SHFL_CPARMS_QUERY_MAP_NAME (2)
+
+/**
+ * SHFL_FN_MAP_FOLDER_OLD
+ */
+
+/** Parameters structure. */
+typedef struct _VBoxSFMapFolder_Old
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** pointer, in:
+     * Points to SHFLSTRING buffer.
+     */
+    HGCMFunctionParameter path;
+
+    /** pointer, out: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+    /** pointer, in: RTUTF16
+     * Path delimiter
+     */
+    HGCMFunctionParameter delimiter;
+
+} VBoxSFMapFolder_Old;
+
+/** Number of parameters */
+#define SHFL_CPARMS_MAP_FOLDER_OLD (3)
+
+/**
+ * SHFL_FN_MAP_FOLDER
+ */
+
+/** Parameters structure. */
+typedef struct _VBoxSFMapFolder
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** pointer, in:
+     * Points to SHFLSTRING buffer.
+     */
+    HGCMFunctionParameter path;
+
+    /** pointer, out: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+    /** pointer, in: RTUTF16
+     * Path delimiter
+     */
+    HGCMFunctionParameter delimiter;
+
+    /** pointer, in: SHFLROOT
+     * Case senstive flag
+     */
+    HGCMFunctionParameter fCaseSensitive;
+
+} VBoxSFMapFolder;
+
+/** Number of parameters */
+#define SHFL_CPARMS_MAP_FOLDER (4)
+
+/**
+ * SHFL_FN_UNMAP_FOLDER
+ */
+
+/** Parameters structure. */
+typedef struct _VBoxSFUnmapFolder
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** pointer, in: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+} VBoxSFUnmapFolder;
+
+/** Number of parameters */
+#define SHFL_CPARMS_UNMAP_FOLDER (1)
+
+
+/**
+ * SHFL_FN_CREATE
+ */
+
+/** Parameters structure. */
+typedef struct _VBoxSFCreate
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** pointer, in: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+    /** pointer, in:
+     * Points to SHFLSTRING buffer.
+     */
+    HGCMFunctionParameter path;
+
+    /** pointer, in/out:
+     * Points to SHFLCREATEPARMS buffer.
+     */
+    HGCMFunctionParameter parms;
+
+} VBoxSFCreate;
+
+/** Number of parameters */
+#define SHFL_CPARMS_CREATE (3)
+
+
+/**
+ * SHFL_FN_CLOSE
+ */
+
+/** Parameters structure. */
+typedef struct _VBoxSFClose
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** pointer, in: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+
+    /** value64, in:
+     * SHFLHANDLE of object to close.
+     */
+    HGCMFunctionParameter handle;
+
+} VBoxSFClose;
+
+/** Number of parameters */
+#define SHFL_CPARMS_CLOSE (2)
+
+
+/**
+ * SHFL_FN_READ
+ */
+
+/** Parameters structure. */
+typedef struct _VBoxSFRead
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** pointer, in: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+    /** value64, in:
+     * SHFLHANDLE of object to read from.
+     */
+    HGCMFunctionParameter handle;
+
+    /** value64, in:
+     * Offset to read from.
+     */
+    HGCMFunctionParameter offset;
+
+    /** value64, in/out:
+     * Bytes to read/How many were read.
+     */
+    HGCMFunctionParameter cb;
+
+    /** pointer, out:
+     * Buffer to place data to.
+     */
+    HGCMFunctionParameter buffer;
+
+} VBoxSFRead;
+
+/** Number of parameters */
+#define SHFL_CPARMS_READ (5)
+
+
+
+/**
+ * SHFL_FN_WRITE
+ */
+
+/** Parameters structure. */
+typedef struct _VBoxSFWrite
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** pointer, in: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+    /** value64, in:
+     * SHFLHANDLE of object to write to.
+     */
+    HGCMFunctionParameter handle;
+
+    /** value64, in:
+     * Offset to write to.
+     */
+    HGCMFunctionParameter offset;
+
+    /** value64, in/out:
+     * Bytes to write/How many were written.
+     */
+    HGCMFunctionParameter cb;
+
+    /** pointer, in:
+     * Data to write.
+     */
+    HGCMFunctionParameter buffer;
+
+} VBoxSFWrite;
+
+/** Number of parameters */
+#define SHFL_CPARMS_WRITE (5)
+
+
+
+/**
+ * SHFL_FN_LOCK
+ */
+
+/** Lock owner is the HGCM client. */
+
+/** Lock mode bit mask. */
+#define SHFL_LOCK_MODE_MASK  (0x3)
+/** Cancel lock on the given range. */
+#define SHFL_LOCK_CANCEL     (0x0)
+/** Acquire read only lock. Prevent write to the range. */
+#define SHFL_LOCK_SHARED     (0x1)
+/** Acquire write lock. Prevent both write and read to the range. */
+#define SHFL_LOCK_EXCLUSIVE  (0x2)
+
+/** Do not wait for lock if it can not be acquired at the time. */
+#define SHFL_LOCK_NOWAIT     (0x0)
+/** Wait and acquire lock. */
+#define SHFL_LOCK_WAIT       (0x4)
+
+/** Lock the specified range. */
+#define SHFL_LOCK_PARTIAL    (0x0)
+/** Lock entire object. */
+#define SHFL_LOCK_ENTIRE     (0x8)
+
+/** Parameters structure. */
+typedef struct _VBoxSFLock
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** pointer, in: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+    /** value64, in:
+     * SHFLHANDLE of object to be locked.
+     */
+    HGCMFunctionParameter handle;
+
+    /** value64, in:
+     * Starting offset of lock range.
+     */
+    HGCMFunctionParameter offset;
+
+    /** value64, in:
+     * Length of range.
+     */
+    HGCMFunctionParameter length;
+
+    /** value32, in:
+     * Lock flags SHFL_LOCK_*.
+     */
+    HGCMFunctionParameter flags;
+
+} VBoxSFLock;
+
+/** Number of parameters */
+#define SHFL_CPARMS_LOCK (5)
+
+
+
+/**
+ * SHFL_FN_FLUSH
+ */
+
+/** Parameters structure. */
+typedef struct _VBoxSFFlush
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** pointer, in: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+    /** value64, in:
+     * SHFLHANDLE of object to be locked.
+     */
+    HGCMFunctionParameter handle;
+
+} VBoxSFFlush;
+
+/** Number of parameters */
+#define SHFL_CPARMS_FLUSH (2)
+
+/**
+ * SHFL_FN_LIST
+ */
+
+/** Listing information includes variable length RTDIRENTRY[EX] structures. */
+
+/** @todo might be necessary for future. */
+#define SHFL_LIST_NONE          0
+#define SHFL_LIST_RETURN_ONE        1
+
+/** Parameters structure. */
+typedef struct _VBoxSFList
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** pointer, in: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+    /** value64, in:
+     * SHFLHANDLE of object to be listed.
+     */
+    HGCMFunctionParameter handle;
+
+    /** value32, in:
+     * List flags SHFL_LIST_*.
+     */
+    HGCMFunctionParameter flags;
+
+    /** value32, in/out:
+     * Bytes to be used for listing information/How many bytes were used.
+     */
+    HGCMFunctionParameter cb;
+
+    /** pointer, in/optional
+     * Points to SHFLSTRING buffer that specifies a search path.
+     */
+    HGCMFunctionParameter path;
+
+    /** pointer, out:
+     * Buffer to place listing information to. (SHFLDIRINFO)
+     */
+    HGCMFunctionParameter buffer;
+
+    /** value32, in/out:
+     * Indicates a key where the listing must be resumed.
+     * in: 0 means start from begin of object.
+     * out: 0 means listing completed.
+     */
+    HGCMFunctionParameter resumePoint;
+
+    /** pointer, out:
+     * Number of files returned
+     */
+    HGCMFunctionParameter cFiles;
+
+} VBoxSFList;
+
+/** Number of parameters */
+#define SHFL_CPARMS_LIST (8)
+
+
+
+/**
+ * SHFL_FN_READLINK
+ */
+
+/** Parameters structure. */
+typedef struct _VBoxSFReadLink
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** pointer, in: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+    /** pointer, in:
+     * Points to SHFLSTRING buffer.
+     */
+    HGCMFunctionParameter path;
+
+    /** pointer, out:
+     * Buffer to place data to.
+     */
+    HGCMFunctionParameter buffer;
+
+} VBoxSFReadLink;
+
+/** Number of parameters */
+#define SHFL_CPARMS_READLINK (3)
+
+
+
+/**
+ * SHFL_FN_INFORMATION
+ */
+
+/** Mask of Set/Get bit. */
+#define SHFL_INFO_MODE_MASK    (0x1)
+/** Get information */
+#define SHFL_INFO_GET          (0x0)
+/** Set information */
+#define SHFL_INFO_SET          (0x1)
+
+/** Get name of the object. */
+#define SHFL_INFO_NAME         (0x2)
+/** Set size of object (extend/trucate); only applies to file objects */
+#define SHFL_INFO_SIZE         (0x4)
+/** Get/Set file object info. */
+#define SHFL_INFO_FILE         (0x8)
+/** Get volume information. */
+#define SHFL_INFO_VOLUME       (0x10)
+
+/** @todo different file info structures */
+
+
+/** Parameters structure. */
+typedef struct _VBoxSFInformation
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** pointer, in: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+    /** value64, in:
+     * SHFLHANDLE of object to be listed.
+     */
+    HGCMFunctionParameter handle;
+
+    /** value32, in:
+     * SHFL_INFO_*
+     */
+    HGCMFunctionParameter flags;
+
+    /** value32, in/out:
+     * Bytes to be used for information/How many bytes were used.
+     */
+    HGCMFunctionParameter cb;
+
+    /** pointer, in/out:
+     * Information to be set/get (SHFLFSOBJINFO or SHFLSTRING). Do not forget
+     * to set the SHFLFSOBJINFO::Attr::enmAdditional for Get operation as well.
+     */
+    HGCMFunctionParameter info;
+
+} VBoxSFInformation;
+
+/** Number of parameters */
+#define SHFL_CPARMS_INFORMATION (5)
+
+
+/**
+ * SHFL_FN_REMOVE
+ */
+
+#define SHFL_REMOVE_FILE        (0x1)
+#define SHFL_REMOVE_DIR         (0x2)
+#define SHFL_REMOVE_SYMLINK     (0x4)
+
+/** Parameters structure. */
+typedef struct _VBoxSFRemove
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** pointer, in: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+    /** pointer, in:
+     * Points to SHFLSTRING buffer.
+     */
+    HGCMFunctionParameter path;
+
+    /** value32, in:
+     * remove flags (file/directory)
+     */
+    HGCMFunctionParameter flags;
+
+} VBoxSFRemove;
+
+#define SHFL_CPARMS_REMOVE  (3)
+
+
+/**
+ * SHFL_FN_RENAME
+ */
+
+#define SHFL_RENAME_FILE                (0x1)
+#define SHFL_RENAME_DIR                 (0x2)
+#define SHFL_RENAME_REPLACE_IF_EXISTS   (0x4)
+
+/** Parameters structure. */
+typedef struct _VBoxSFRename
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** pointer, in: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+    /** pointer, in:
+     * Points to SHFLSTRING src.
+     */
+    HGCMFunctionParameter src;
+
+    /** pointer, in:
+     * Points to SHFLSTRING dest.
+     */
+    HGCMFunctionParameter dest;
+
+    /** value32, in:
+     * rename flags (file/directory)
+     */
+    HGCMFunctionParameter flags;
+
+} VBoxSFRename;
+
+#define SHFL_CPARMS_RENAME  (4)
+
+
+/**
+ * SHFL_FN_SYMLINK
+ */
+
+/** Parameters structure. */
+typedef struct _VBoxSFSymlink
+{
+    VBoxGuestHGCMCallInfo callInfo;
+
+    /** pointer, in: SHFLROOT
+     * Root handle of the mapping which name is queried.
+     */
+    HGCMFunctionParameter root;
+
+    /** pointer, in:
+     * Points to SHFLSTRING of path for the new symlink.
+     */
+    HGCMFunctionParameter newPath;
+
+    /** pointer, in:
+     * Points to SHFLSTRING of destination for symlink.
+     */
+    HGCMFunctionParameter oldPath;
+
+    /** pointer, out:
+     * Information about created symlink.
+     */
+    HGCMFunctionParameter info;
+
+} VBoxSFSymlink;
+
+#define SHFL_CPARMS_SYMLINK  (4)
+
+
+
+/**
+ * SHFL_FN_ADD_MAPPING
+ * Host call, no guest structure is used.
+ */
+
+/** mapping is writable */
+#define SHFL_ADD_MAPPING_F_WRITABLE         (RT_BIT_32(0))
+/** mapping is automounted by the guest */
+#define SHFL_ADD_MAPPING_F_AUTOMOUNT        (RT_BIT_32(1))
+/** allow the guest to create symlinks */
+#define SHFL_ADD_MAPPING_F_CREATE_SYMLINKS  (RT_BIT_32(2))
+/** mapping is actually missing on the host */
+#define SHFL_ADD_MAPPING_F_MISSING          (RT_BIT_32(3))
+
+#define SHFL_CPARMS_ADD_MAPPING  (3)
+
+/**
+ * SHFL_FN_REMOVE_MAPPING
+ * Host call, no guest structure is used.
+ */
+
+#define SHFL_CPARMS_REMOVE_MAPPING (1)
+
+
+/**
+ * SHFL_FN_SET_STATUS_LED
+ * Host call, no guest structure is used.
+ */
+
+#define SHFL_CPARMS_SET_STATUS_LED (1)
+
+/** @} */
+
+#endif
diff --git a/ubuntu/vbox/include/VBox/types.h b/ubuntu/vbox/include/VBox/types.h
new file mode 100644 (file)
index 0000000..81640ac
--- /dev/null
@@ -0,0 +1,1082 @@
+/** @file
+ * VirtualBox - Types.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBox_types_h
+#define ___VBox_types_h
+
+#include <VBox/cdefs.h>
+#include <iprt/types.h>
+
+
+/** @defgroup grp_types     VBox Basic Types
+ * @{
+ */
+
+
+/** @defgroup grp_types_both  Common Guest and Host Context Basic Types
+ * @{
+ */
+
+
+/** @defgroup grp_types_hc  Host Context Basic Types
+ * @{
+ */
+
+/** @} */
+
+
+/** @defgroup grp_types_gc  Guest Context Basic Types
+ * @{
+ */
+
+/** @} */
+
+
+/** Pointer to per support driver session data.
+ * (The data is a R0 entity and private to the the R0 SUP part. All
+ * other should consider this a sort of handle.) */
+typedef R0PTRTYPE(struct SUPDRVSESSION *)           PSUPDRVSESSION;
+
+/** Event semaphore handle. Ring-0 / ring-3. */
+typedef R0PTRTYPE(struct SUPSEMEVENTHANDLE *)       SUPSEMEVENT;
+/** Pointer to an event semaphore handle. */
+typedef SUPSEMEVENT                                *PSUPSEMEVENT;
+/** Nil event semaphore handle. */
+#define NIL_SUPSEMEVENT                             ((SUPSEMEVENT)0)
+
+/** Multiple release event semaphore handle. Ring-0 / ring-3. */
+typedef R0PTRTYPE(struct SUPSEMEVENTMULTIHANDLE *)  SUPSEMEVENTMULTI;
+/** Pointer to an multiple release event semaphore handle. */
+typedef SUPSEMEVENTMULTI                           *PSUPSEMEVENTMULTI;
+/** Nil multiple release event semaphore handle. */
+#define NIL_SUPSEMEVENTMULTI                        ((SUPSEMEVENTMULTI)0)
+
+
+/** Pointer to a VM. */
+typedef struct VM                  *PVM;
+/** Pointer to a VM - Ring-0 Ptr. */
+typedef R0PTRTYPE(struct VM *)      PVMR0;
+/** Pointer to a VM - Ring-3 Ptr. */
+typedef R3PTRTYPE(struct VM *)      PVMR3;
+/** Pointer to a VM - RC Ptr. */
+typedef RCPTRTYPE(struct VM *)      PVMRC;
+
+/** Pointer to a virtual CPU structure. */
+typedef struct VMCPU *              PVMCPU;
+/** Pointer to a const virtual CPU structure. */
+typedef const struct VMCPU *        PCVMCPU;
+/** Pointer to a virtual CPU structure - Ring-3 Ptr. */
+typedef R3PTRTYPE(struct VMCPU *)   PVMCPUR3;
+/** Pointer to a virtual CPU structure - Ring-0 Ptr. */
+typedef R0PTRTYPE(struct VMCPU *)   PVMCPUR0;
+/** Pointer to a virtual CPU structure - RC Ptr. */
+typedef RCPTRTYPE(struct VMCPU *)   PVMCPURC;
+
+/** Pointer to a ring-0 (global) VM structure. */
+typedef R0PTRTYPE(struct GVM *)     PGVM;
+
+/** Pointer to a ring-3 (user mode) VM structure. */
+typedef R3PTRTYPE(struct UVM *)     PUVM;
+
+/** Pointer to a ring-3 (user mode) VMCPU structure. */
+typedef R3PTRTYPE(struct UVMCPU *)  PUVMCPU;
+
+/** Virtual CPU ID. */
+typedef uint32_t                    VMCPUID;
+/** Pointer to a virtual CPU ID. */
+typedef VMCPUID                    *PVMCPUID;
+/** @name Special CPU ID values.
+ * Most of these are for request scheduling.
+ *
+ * @{ */
+/** All virtual CPUs. */
+#define VMCPUID_ALL         UINT32_C(0xfffffff2)
+/** All virtual CPUs, descending order. */
+#define VMCPUID_ALL_REVERSE UINT32_C(0xfffffff3)
+/** Any virtual CPU.
+ * Intended for scheduling a VM request or some other task. */
+#define VMCPUID_ANY         UINT32_C(0xfffffff4)
+/** Any virtual CPU; always queue for future execution.
+ * Intended for scheduling a VM request or some other task. */
+#define VMCPUID_ANY_QUEUE   UINT32_C(0xfffffff5)
+/** The NIL value. */
+#define NIL_VMCPUID         UINT32_C(0xfffffffd)
+/** @} */
+
+/**
+ * Virtual CPU set.
+ */
+typedef struct VMCPUSET
+{
+    /** The bitmap data.  */
+    uint32_t    au32Bitmap[8 /*256/32*/];
+} VMCPUSET;
+/** Pointer to a Virtual CPU set. */
+typedef VMCPUSET *PVMCPUSET;
+/** Pointer to a const Virtual CPU set. */
+typedef VMCPUSET const *PCVMCPUSET;
+
+
+/**
+ * VM State
+ */
+typedef enum VMSTATE
+{
+    /** The VM is being created. */
+    VMSTATE_CREATING = 0,
+    /** The VM is created. */
+    VMSTATE_CREATED,
+    /** The VM state is being loaded from file. */
+    VMSTATE_LOADING,
+    /** The VM is being powered on */
+    VMSTATE_POWERING_ON,
+    /** The VM is being resumed. */
+    VMSTATE_RESUMING,
+    /** The VM is runnning. */
+    VMSTATE_RUNNING,
+    /** Live save: The VM is running and the state is being saved. */
+    VMSTATE_RUNNING_LS,
+    /** Fault Tolerance: The VM is running and the state is being synced. */
+    VMSTATE_RUNNING_FT,
+    /** The VM is being reset. */
+    VMSTATE_RESETTING,
+    /** Live save: The VM is being reset and immediately suspended. */
+    VMSTATE_RESETTING_LS,
+    /** The VM is being soft/warm reset. */
+    VMSTATE_SOFT_RESETTING,
+    /** Live save: The VM is being soft/warm reset (not suspended afterwards). */
+    VMSTATE_SOFT_RESETTING_LS,
+    /** The VM is being suspended. */
+    VMSTATE_SUSPENDING,
+    /** Live save: The VM is being suspended during a live save operation, either as
+     * part of the normal flow or VMR3Reset. */
+    VMSTATE_SUSPENDING_LS,
+    /** Live save: The VM is being suspended by VMR3Suspend during live save. */
+    VMSTATE_SUSPENDING_EXT_LS,
+    /** The VM is suspended. */
+    VMSTATE_SUSPENDED,
+    /** Live save: The VM has been suspended and is waiting for the live save
+     * operation to move on. */
+    VMSTATE_SUSPENDED_LS,
+    /** Live save: The VM has been suspended by VMR3Suspend during a live save. */
+    VMSTATE_SUSPENDED_EXT_LS,
+    /** The VM is suspended and its state is being saved by EMT(0). (See SSM) */
+    VMSTATE_SAVING,
+    /** The VM is being debugged. (See DBGF.) */
+    VMSTATE_DEBUGGING,
+    /** Live save: The VM is being debugged while the live phase is going on. */
+    VMSTATE_DEBUGGING_LS,
+    /** The VM is being powered off. */
+    VMSTATE_POWERING_OFF,
+    /** Live save: The VM is being powered off and the save cancelled. */
+    VMSTATE_POWERING_OFF_LS,
+    /** The VM is switched off, awaiting destruction. */
+    VMSTATE_OFF,
+    /** Live save: Waiting for cancellation and transition to VMSTATE_OFF. */
+    VMSTATE_OFF_LS,
+    /** The VM is powered off because of a fatal error. */
+    VMSTATE_FATAL_ERROR,
+    /** Live save: Waiting for cancellation and transition to FatalError. */
+    VMSTATE_FATAL_ERROR_LS,
+    /** The VM is in guru meditation over a fatal failure. */
+    VMSTATE_GURU_MEDITATION,
+    /** Live save: Waiting for cancellation and transition to GuruMeditation. */
+    VMSTATE_GURU_MEDITATION_LS,
+    /** The VM is screwed because of a failed state loading. */
+    VMSTATE_LOAD_FAILURE,
+    /** The VM is being destroyed. */
+    VMSTATE_DESTROYING,
+    /** Terminated. */
+    VMSTATE_TERMINATED,
+    /** hack forcing the size of the enum to 32-bits. */
+    VMSTATE_MAKE_32BIT_HACK = 0x7fffffff
+} VMSTATE;
+
+/** @def VBOXSTRICTRC_STRICT_ENABLED
+ * Indicates that VBOXSTRICTRC is in strict mode.
+ */
+#if defined(__cplusplus) \
+ && ARCH_BITS == 64    /* cdecl requires classes and structs as hidden params. */ \
+ && !defined(_MSC_VER) /* trouble similar to 32-bit gcc. */ \
+ &&  (   defined(RT_STRICT) \
+      || defined(VBOX_STRICT) \
+      || defined(DEBUG) \
+      || defined(DOXYGEN_RUNNING) )
+# define VBOXSTRICTRC_STRICT_ENABLED 1
+#endif
+
+/** We need RTERR_STRICT_RC.  */
+#if defined(VBOXSTRICTRC_STRICT_ENABLED) && !defined(RTERR_STRICT_RC)
+# define RTERR_STRICT_RC 1
+#endif
+
+/**
+ * Strict VirtualBox status code.
+ *
+ * This is normally an 32-bit integer and the only purpose of the type is to
+ * highlight the special handling that is required.  But in strict build it is a
+ * class that causes compilation and runtime errors for some of the incorrect
+ * handling.
+ */
+#ifdef VBOXSTRICTRC_STRICT_ENABLED
+struct VBOXSTRICTRC
+{
+protected:
+    /** The status code. */
+    int32_t m_rc;
+
+public:
+    /** Default constructor setting the status to VERR_IPE_UNINITIALIZED_STATUS. */
+    VBOXSTRICTRC()
+#ifdef VERR_IPE_UNINITIALIZED_STATUS
+        : m_rc(VERR_IPE_UNINITIALIZED_STATUS)
+#else
+        : m_rc(-233 /*VERR_IPE_UNINITIALIZED_STATUS*/)
+#endif
+    {
+    }
+
+    /** Constructor for normal integer status codes. */
+    VBOXSTRICTRC(int32_t const rc)
+        : m_rc(rc)
+    {
+    }
+
+    /** Getter that VBOXSTRICTRC_VAL can use. */
+    int32_t getValue() const                        { return m_rc; }
+
+    /** @name Comparison operators
+     * @{ */
+    bool operator==(int32_t rc) const               { return m_rc == rc; }
+    bool operator!=(int32_t rc) const               { return m_rc != rc; }
+    bool operator<=(int32_t rc) const               { return m_rc <= rc; }
+    bool operator>=(int32_t rc) const               { return m_rc >= rc; }
+    bool operator<(int32_t rc) const                { return m_rc <  rc; }
+    bool operator>(int32_t rc) const                { return m_rc >  rc; }
+
+    bool operator==(const VBOXSTRICTRC &rRc) const  { return m_rc == rRc.m_rc; }
+    bool operator!=(const VBOXSTRICTRC &rRc) const  { return m_rc != rRc.m_rc; }
+    bool operator<=(const VBOXSTRICTRC &rRc) const  { return m_rc <= rRc.m_rc; }
+    bool operator>=(const VBOXSTRICTRC &rRc) const  { return m_rc >= rRc.m_rc; }
+    bool operator<(const VBOXSTRICTRC &rRc) const   { return m_rc <  rRc.m_rc; }
+    bool operator>(const VBOXSTRICTRC &rRc) const   { return m_rc >  rRc.m_rc; }
+    /** @} */
+
+    /** Special automatic cast for RT_SUCCESS_NP. */
+    operator RTErrStrictType2() const               { return RTErrStrictType2(m_rc); }
+
+private:
+    /** @name Constructors that will prevent some of the bad types.
+     * @{ */
+    VBOXSTRICTRC(uint8_t  rc) : m_rc(-999)          { NOREF(rc); }
+    VBOXSTRICTRC(uint16_t rc) : m_rc(-999)          { NOREF(rc); }
+    VBOXSTRICTRC(uint32_t rc) : m_rc(-999)          { NOREF(rc); }
+    VBOXSTRICTRC(uint64_t rc) : m_rc(-999)          { NOREF(rc); }
+
+    VBOXSTRICTRC(int8_t rc)   : m_rc(-999)          { NOREF(rc); }
+    VBOXSTRICTRC(int16_t rc)  : m_rc(-999)          { NOREF(rc); }
+    VBOXSTRICTRC(int64_t rc)  : m_rc(-999)          { NOREF(rc); }
+    /** @} */
+};
+# ifdef _MSC_VER
+#  pragma warning(disable:4190)
+# endif
+#else
+typedef int32_t VBOXSTRICTRC;
+#endif
+
+/** @def VBOXSTRICTRC_VAL
+ * Explicit getter.
+ * @param rcStrict  The strict VirtualBox status code.
+ */
+#ifdef VBOXSTRICTRC_STRICT_ENABLED
+# define VBOXSTRICTRC_VAL(rcStrict) ( (rcStrict).getValue() )
+#else
+# define VBOXSTRICTRC_VAL(rcStrict) (rcStrict)
+#endif
+
+/** @def VBOXSTRICTRC_TODO
+ * Returns that needs dealing with.
+ * @param rcStrict  The strict VirtualBox status code.
+ */
+#define VBOXSTRICTRC_TODO(rcStrict) VBOXSTRICTRC_VAL(rcStrict)
+
+
+/** Pointer to a PDM Base Interface. */
+typedef struct PDMIBASE *PPDMIBASE;
+/** Pointer to a pointer to a PDM Base Interface. */
+typedef PPDMIBASE *PPPDMIBASE;
+
+/** Pointer to a PDM Device Instance. */
+typedef struct PDMDEVINS *PPDMDEVINS;
+/** Pointer to a pointer to a PDM Device Instance. */
+typedef PPDMDEVINS *PPPDMDEVINS;
+/** R3 pointer to a PDM Device Instance. */
+typedef R3PTRTYPE(PPDMDEVINS) PPDMDEVINSR3;
+/** R0 pointer to a PDM Device Instance. */
+typedef R0PTRTYPE(PPDMDEVINS) PPDMDEVINSR0;
+/** RC pointer to a PDM Device Instance. */
+typedef RCPTRTYPE(PPDMDEVINS) PPDMDEVINSRC;
+
+/** Pointer to a PDM PCI device structure. */
+typedef struct PDMPCIDEV *PPDMPCIDEV;
+
+/** Pointer to a PDM USB Device Instance. */
+typedef struct PDMUSBINS *PPDMUSBINS;
+/** Pointer to a pointer to a PDM USB Device Instance. */
+typedef PPDMUSBINS *PPPDMUSBINS;
+
+/** Pointer to a PDM Driver Instance. */
+typedef struct PDMDRVINS *PPDMDRVINS;
+/** Pointer to a pointer to a PDM Driver Instance. */
+typedef PPDMDRVINS *PPPDMDRVINS;
+/** R3 pointer to a PDM Driver Instance. */
+typedef R3PTRTYPE(PPDMDRVINS) PPDMDRVINSR3;
+/** R0 pointer to a PDM Driver Instance. */
+typedef R0PTRTYPE(PPDMDRVINS) PPDMDRVINSR0;
+/** RC pointer to a PDM Driver Instance. */
+typedef RCPTRTYPE(PPDMDRVINS) PPDMDRVINSRC;
+
+/** Pointer to a PDM Service Instance. */
+typedef struct PDMSRVINS *PPDMSRVINS;
+/** Pointer to a pointer to a PDM Service Instance. */
+typedef PPDMSRVINS *PPPDMSRVINS;
+
+/** Pointer to a PDM critical section. */
+typedef union PDMCRITSECT *PPDMCRITSECT;
+/** Pointer to a const PDM critical section. */
+typedef const union PDMCRITSECT *PCPDMCRITSECT;
+
+/** Pointer to a PDM read/write critical section. */
+typedef union PDMCRITSECTRW *PPDMCRITSECTRW;
+/** Pointer to a const PDM read/write critical section. */
+typedef union PDMCRITSECTRW const *PCPDMCRITSECTRW;
+
+/** R3 pointer to a timer. */
+typedef R3PTRTYPE(struct TMTIMER *) PTMTIMERR3;
+/** Pointer to a R3 pointer to a timer. */
+typedef PTMTIMERR3 *PPTMTIMERR3;
+
+/** R0 pointer to a timer. */
+typedef R0PTRTYPE(struct TMTIMER *) PTMTIMERR0;
+/** Pointer to a R3 pointer to a timer. */
+typedef PTMTIMERR0 *PPTMTIMERR0;
+
+/** RC pointer to a timer. */
+typedef RCPTRTYPE(struct TMTIMER *) PTMTIMERRC;
+/** Pointer to a RC pointer to a timer. */
+typedef PTMTIMERRC *PPTMTIMERRC;
+
+/** Pointer to a timer. */
+typedef CTX_SUFF(PTMTIMER)     PTMTIMER;
+/** Pointer to a pointer to a timer. */
+typedef PTMTIMER              *PPTMTIMER;
+
+/** SSM Operation handle. */
+typedef struct SSMHANDLE *PSSMHANDLE;
+/** Pointer to a const SSM stream method table. */
+typedef struct SSMSTRMOPS const *PCSSMSTRMOPS;
+
+/** Pointer to a CPUMCTX. */
+typedef struct CPUMCTX *PCPUMCTX;
+/** Pointer to a const CPUMCTX. */
+typedef const struct CPUMCTX *PCCPUMCTX;
+
+/** Pointer to a CPU context core. */
+typedef struct CPUMCTXCORE *PCPUMCTXCORE;
+/** Pointer to a const CPU context core. */
+typedef const struct CPUMCTXCORE *PCCPUMCTXCORE;
+
+/** Pointer to a selector register. */
+typedef struct CPUMSELREG *PCPUMSELREG;
+/** Pointer to a const selector register. */
+typedef const struct CPUMSELREG *PCCPUMSELREG;
+
+/** Pointer to selector hidden registers.
+ * @deprecated Replaced by PCPUMSELREG  */
+typedef struct CPUMSELREG *PCPUMSELREGHID;
+/** Pointer to const selector hidden registers.
+ * @deprecated Replaced by PCCPUMSELREG  */
+typedef const struct CPUMSELREG *PCCPUMSELREGHID;
+
+/** @} */
+
+
+/** @defgroup grp_types_idt     Interrupt Descriptor Table Entry.
+ * @todo This all belongs in x86.h!
+ * @{ */
+
+/** @todo VBOXIDT -> VBOXDESCIDT, skip the complex variations. We'll never use them. */
+
+/** IDT Entry, Task Gate view. */
+#pragma pack(1)                         /* paranoia */
+typedef struct VBOXIDTE_TASKGATE
+{
+    /** Reserved. */
+    unsigned    u16Reserved1 : 16;
+    /** Task Segment Selector. */
+    unsigned    u16TSS : 16;
+    /** More reserved. */
+    unsigned    u8Reserved2 : 8;
+    /** Fixed value bit 0 - Set to 1. */
+    unsigned    u1Fixed0 : 1;
+    /** Busy bit. */
+    unsigned    u1Busy : 1;
+    /** Fixed value bit 2 - Set to 1. */
+    unsigned    u1Fixed1 : 1;
+    /** Fixed value bit 3 - Set to 0. */
+    unsigned    u1Fixed2 : 1;
+    /** Fixed value bit 4 - Set to 0. */
+    unsigned    u1Fixed3 : 1;
+    /** Descriptor Privilege level. */
+    unsigned    u2DPL : 2;
+    /** Present flag. */
+    unsigned    u1Present : 1;
+    /** Reserved. */
+    unsigned    u16Reserved3 : 16;
+} VBOXIDTE_TASKGATE;
+#pragma pack()
+/** Pointer to IDT Entry, Task gate view. */
+typedef VBOXIDTE_TASKGATE *PVBOXIDTE_TASKGATE;
+
+
+/** IDT Entry, Intertupt gate view. */
+#pragma pack(1)                         /* paranoia */
+typedef struct VBOXIDTE_INTERRUPTGATE
+{
+    /** Low offset word. */
+    unsigned    u16OffsetLow : 16;
+    /** Segment Selector. */
+    unsigned    u16SegSel : 16;
+    /** Reserved. */
+    unsigned    u5Reserved2 : 5;
+    /** Fixed value bit 0 - Set to 0. */
+    unsigned    u1Fixed0 : 1;
+    /** Fixed value bit 1 - Set to 0. */
+    unsigned    u1Fixed1 : 1;
+    /** Fixed value bit 2 - Set to 0. */
+    unsigned    u1Fixed2 : 1;
+    /** Fixed value bit 3 - Set to 0. */
+    unsigned    u1Fixed3 : 1;
+    /** Fixed value bit 4 - Set to 1. */
+    unsigned    u1Fixed4 : 1;
+    /** Fixed value bit 5 - Set to 1. */
+    unsigned    u1Fixed5 : 1;
+    /** Gate size, 1 = 32 bits, 0 = 16 bits. */
+    unsigned    u132BitGate : 1;
+    /** Fixed value bit 5 - Set to 0. */
+    unsigned    u1Fixed6 : 1;
+    /** Descriptor Privilege level. */
+    unsigned    u2DPL : 2;
+    /** Present flag. */
+    unsigned    u1Present : 1;
+    /** High offset word. */
+    unsigned    u16OffsetHigh : 16;
+} VBOXIDTE_INTERRUPTGATE;
+#pragma pack()
+/** Pointer to IDT Entry, Interrupt gate view. */
+typedef  VBOXIDTE_INTERRUPTGATE *PVBOXIDTE_INTERRUPTGATE;
+
+/** IDT Entry, Trap Gate view. */
+#pragma pack(1)                         /* paranoia */
+typedef struct VBOXIDTE_TRAPGATE
+{
+    /** Low offset word. */
+    unsigned    u16OffsetLow : 16;
+    /** Segment Selector. */
+    unsigned    u16SegSel : 16;
+    /** Reserved. */
+    unsigned    u5Reserved2 : 5;
+    /** Fixed value bit 0 - Set to 0. */
+    unsigned    u1Fixed0 : 1;
+    /** Fixed value bit 1 - Set to 0. */
+    unsigned    u1Fixed1 : 1;
+    /** Fixed value bit 2 - Set to 0. */
+    unsigned    u1Fixed2 : 1;
+    /** Fixed value bit 3 - Set to 1. */
+    unsigned    u1Fixed3 : 1;
+    /** Fixed value bit 4 - Set to 1. */
+    unsigned    u1Fixed4 : 1;
+    /** Fixed value bit 5 - Set to 1. */
+    unsigned    u1Fixed5 : 1;
+    /** Gate size, 1 = 32 bits, 0 = 16 bits. */
+    unsigned    u132BitGate : 1;
+    /** Fixed value bit 5 - Set to 0. */
+    unsigned    u1Fixed6 : 1;
+    /** Descriptor Privilege level. */
+    unsigned    u2DPL : 2;
+    /** Present flag. */
+    unsigned    u1Present : 1;
+    /** High offset word. */
+    unsigned    u16OffsetHigh : 16;
+} VBOXIDTE_TRAPGATE;
+#pragma pack()
+/** Pointer to IDT Entry, Trap Gate view. */
+typedef VBOXIDTE_TRAPGATE *PVBOXIDTE_TRAPGATE;
+
+/** IDT Entry Generic view. */
+#pragma pack(1)                         /* paranoia */
+typedef struct VBOXIDTE_GENERIC
+{
+    /** Low offset word. */
+    unsigned    u16OffsetLow : 16;
+    /** Segment Selector. */
+    unsigned    u16SegSel : 16;
+    /** Reserved. */
+    unsigned    u5Reserved : 5;
+    /** IDT Type part one (not used for task gate). */
+    unsigned    u3Type1 : 3;
+    /** IDT Type part two. */
+    unsigned    u5Type2 : 5;
+    /** Descriptor Privilege level. */
+    unsigned    u2DPL : 2;
+    /** Present flag. */
+    unsigned    u1Present : 1;
+    /** High offset word. */
+    unsigned    u16OffsetHigh : 16;
+} VBOXIDTE_GENERIC;
+#pragma pack()
+/** Pointer to IDT Entry Generic view. */
+typedef VBOXIDTE_GENERIC *PVBOXIDTE_GENERIC;
+
+/** IDT Type1 value. (Reserved for task gate!) */
+#define VBOX_IDTE_TYPE1             0
+/** IDT Type2 value - Task gate. */
+#define VBOX_IDTE_TYPE2_TASK        0x5
+/** IDT Type2 value - 16 bit interrupt gate. */
+#define VBOX_IDTE_TYPE2_INT_16      0x6
+/** IDT Type2 value - 32 bit interrupt gate. */
+#define VBOX_IDTE_TYPE2_INT_32      0xe
+/** IDT Type2 value - 16 bit trap gate. */
+#define VBOX_IDTE_TYPE2_TRAP_16     0x7
+/** IDT Type2 value - 32 bit trap gate. */
+#define VBOX_IDTE_TYPE2_TRAP_32     0xf
+
+/** IDT Entry. */
+#pragma pack(1)                         /* paranoia */
+typedef union VBOXIDTE
+{
+    /** Task gate view. */
+    VBOXIDTE_TASKGATE       Task;
+    /** Trap gate view. */
+    VBOXIDTE_TRAPGATE       Trap;
+    /** Interrupt gate view. */
+    VBOXIDTE_INTERRUPTGATE  Int;
+    /** Generic IDT view. */
+    VBOXIDTE_GENERIC        Gen;
+
+    /** 8 bit unsigned integer view. */
+    uint8_t     au8[8];
+    /** 16 bit unsigned integer view. */
+    uint16_t    au16[4];
+    /** 32 bit unsigned integer view. */
+    uint32_t    au32[2];
+    /** 64 bit unsigned integer view. */
+    uint64_t    au64;
+} VBOXIDTE;
+#pragma pack()
+/** Pointer to IDT Entry. */
+typedef VBOXIDTE *PVBOXIDTE;
+/** Pointer to IDT Entry. */
+typedef VBOXIDTE const *PCVBOXIDTE;
+
+/** IDT Entry, 64-bit mode, Intertupt gate view. */
+#pragma pack(1)                         /* paranoia */
+typedef struct VBOXIDTE64_INTERRUPTGATE
+{
+    /** Low offset word. */
+    unsigned    u16OffsetLow : 16;
+    /** Segment Selector. */
+    unsigned    u16SegSel : 16;
+    /** Interrupt Stack Table Index. */
+    unsigned    u3Ist : 3;
+    /** Fixed value bit 0 - Set to 0. */
+    unsigned    u1Fixed0 : 1;
+    /** Fixed value bit 1 - Set to 0. */
+    unsigned    u1Fixed1 : 1;
+    /** Fixed value bit 2 - Set to 0. */
+    unsigned    u1Fixed2 : 1;
+    /** Fixed value bit 3 - Set to 0. */
+    unsigned    u1Fixed3 : 1;
+    /** Fixed value bit 4 - Set to 0. */
+    unsigned    u1Fixed4 : 1;
+    /** Fixed value bit 5 - Set to 0. */
+    unsigned    u1Fixed5 : 1;
+    /** Fixed value bit 6 - Set to 1. */
+    unsigned    u1Fixed6 : 1;
+    /** Fixed value bit 7 - Set to 1. */
+    unsigned    u1Fixed7 : 1;
+    /** Gate size, 1 = 32 bits, 0 = 16 bits. */
+    unsigned    u132BitGate : 1;
+    /** Fixed value bit 5 - Set to 0. */
+    unsigned    u1Fixed8 : 1;
+    /** Descriptor Privilege level. */
+    unsigned    u2DPL : 2;
+    /** Present flag. */
+    unsigned    u1Present : 1;
+    /** High offset word. */
+    unsigned    u16OffsetHigh : 16;
+    /** Offset bits 32..63. */
+    unsigned    u32OffsetHigh64;
+    /** Reserved. */
+    unsigned    u32Reserved;
+} VBOXIDTE64_INTERRUPTGATE;
+#pragma pack()
+/** Pointer to IDT Entry, 64-bit mode, Interrupt gate view. */
+typedef  VBOXIDTE64_INTERRUPTGATE *PVBOXIDTE64_INTERRUPTGATE;
+
+/** IDT Entry, 64-bit mode, Trap gate view. */
+#pragma pack(1)                         /* paranoia */
+typedef struct VBOXIDTE64_TRAPGATE
+{
+    /** Low offset word. */
+    unsigned    u16OffsetLow : 16;
+    /** Segment Selector. */
+    unsigned    u16SegSel : 16;
+    /** Interrupt Stack Table Index. */
+    unsigned    u3Ist : 3;
+    /** Fixed value bit 0 - Set to 0. */
+    unsigned    u1Fixed0 : 1;
+    /** Fixed value bit 1 - Set to 0. */
+    unsigned    u1Fixed1 : 1;
+    /** Fixed value bit 2 - Set to 0. */
+    unsigned    u1Fixed2 : 1;
+    /** Fixed value bit 3 - Set to 0. */
+    unsigned    u1Fixed3 : 1;
+    /** Fixed value bit 4 - Set to 0. */
+    unsigned    u1Fixed4 : 1;
+    /** Fixed value bit 5 - Set to 1. */
+    unsigned    u1Fixed5 : 1;
+    /** Fixed value bit 6 - Set to 1. */
+    unsigned    u1Fixed6 : 1;
+    /** Fixed value bit 7 - Set to 1. */
+    unsigned    u1Fixed7 : 1;
+    /** Gate size, 1 = 32 bits, 0 = 16 bits. */
+    unsigned    u132BitGate : 1;
+    /** Fixed value bit 5 - Set to 0. */
+    unsigned    u1Fixed8 : 1;
+    /** Descriptor Privilege level. */
+    unsigned    u2DPL : 2;
+    /** Present flag. */
+    unsigned    u1Present : 1;
+    /** High offset word. */
+    unsigned    u16OffsetHigh : 16;
+    /** Offset bits 32..63. */
+    unsigned    u32OffsetHigh64;
+    /** Reserved. */
+    unsigned    u32Reserved;
+} VBOXIDTE64_TRAPGATE;
+#pragma pack()
+/** Pointer to IDT Entry, 64-bit mode, Trap gate view. */
+typedef  VBOXIDTE64_TRAPGATE *PVBOXIDTE64_TRAPGATE;
+
+/** IDT Entry, 64-bit mode, Generic view. */
+#pragma pack(1)                         /* paranoia */
+typedef struct VBOXIDTE64_GENERIC
+{
+    /** Low offset word. */
+    unsigned    u16OffsetLow : 16;
+    /** Segment Selector. */
+    unsigned    u16SegSel : 16;
+    /** Reserved. */
+    unsigned    u3Ist : 3;
+    /** Fixed value bit 0 - Set to 0. */
+    unsigned    u1Fixed0 : 1;
+    /** Fixed value bit 1 - Set to 0. */
+    unsigned    u1Fixed1 : 1;
+    /** IDT Type part one (not used for task gate). */
+    unsigned    u3Type1 : 3;
+    /** IDT Type part two. */
+    unsigned    u5Type2 : 5;
+    /** Descriptor Privilege level. */
+    unsigned    u2DPL : 2;
+    /** Present flag. */
+    unsigned    u1Present : 1;
+    /** High offset word. */
+    unsigned    u16OffsetHigh : 16;
+    /** Offset bits 32..63. */
+    unsigned    u32OffsetHigh64;
+    /** Reserved. */
+    unsigned    u32Reserved;
+} VBOXIDTE64_GENERIC;
+#pragma pack()
+/** Pointer to IDT Entry, 64-bit mode, Generic view. */
+typedef VBOXIDTE64_GENERIC *PVBOXIDTE64_GENERIC;
+
+/** IDT Entry, 64-bit mode. */
+#pragma pack(1)                         /* paranoia */
+typedef union VBOXIDTE64
+{
+    /** Trap gate view. */
+    VBOXIDTE64_TRAPGATE       Trap;
+    /** Interrupt gate view. */
+    VBOXIDTE64_INTERRUPTGATE  Int;
+    /** Generic IDT view. */
+    VBOXIDTE64_GENERIC        Gen;
+
+    /** 8 bit unsigned integer view. */
+    uint8_t     au8[16];
+    /** 16 bit unsigned integer view. */
+    uint16_t    au16[8];
+    /** 32 bit unsigned integer view. */
+    uint32_t    au32[4];
+    /** 64 bit unsigned integer view. */
+    uint64_t    au64[2];
+} VBOXIDTE64;
+#pragma pack()
+/** Pointer to IDT Entry. */
+typedef VBOXIDTE64 *PVBOXIDTE64;
+/** Pointer to IDT Entry. */
+typedef VBOXIDTE64 const *PCVBOXIDTE64;
+
+#pragma pack(1)
+/** IDTR */
+typedef struct VBOXIDTR
+{
+    /** Size of the IDT. */
+    uint16_t    cbIdt;
+    /** Address of the IDT. */
+    uint64_t     pIdt;
+} VBOXIDTR, *PVBOXIDTR;
+#pragma pack()
+
+/** @} */
+
+
+/** @def VBOXIDTE_OFFSET
+ * Return the offset of an IDT entry.
+ */
+#define VBOXIDTE_OFFSET(desc) \
+        (  ((uint32_t)((desc).Gen.u16OffsetHigh) << 16) \
+         | (           (desc).Gen.u16OffsetLow        ) )
+
+/** @def VBOXIDTE64_OFFSET
+ * Return the offset of an IDT entry.
+ */
+#define VBOXIDTE64_OFFSET(desc) \
+        (  ((uint64_t)((desc).Gen.u32OffsetHigh64) << 32) \
+         | ((uint32_t)((desc).Gen.u16OffsetHigh)   << 16) \
+         | (           (desc).Gen.u16OffsetLow          ) )
+
+#pragma pack(1)
+/** GDTR */
+typedef struct VBOXGDTR
+{
+    /** Size of the GDT. */
+    uint16_t    cbGdt;
+    /** Address of the GDT. */
+    uint64_t    pGdt;
+} VBOXGDTR;
+#pragma pack()
+/** Pointer to GDTR. */
+typedef VBOXGDTR *PVBOXGDTR;
+
+/** @} */
+
+
+/**
+ * 32-bit Task Segment used in raw mode.
+ * @todo Move this to SELM! Use X86TSS32 instead.
+ */
+#pragma pack(1)
+typedef struct VBOXTSS
+{
+    /** 0x00 - Back link to previous task. (static) */
+    RTSEL       selPrev;
+    uint16_t    padding1;
+    /** 0x04 - Ring-0 stack pointer. (static) */
+    uint32_t    esp0;
+    /** 0x08 - Ring-0 stack segment. (static) */
+    RTSEL       ss0;
+    uint16_t    padding_ss0;
+    /** 0x0c - Ring-1 stack pointer. (static) */
+    uint32_t    esp1;
+    /** 0x10 - Ring-1 stack segment. (static) */
+    RTSEL       ss1;
+    uint16_t    padding_ss1;
+    /** 0x14 - Ring-2 stack pointer. (static) */
+    uint32_t    esp2;
+    /** 0x18 - Ring-2 stack segment. (static) */
+    RTSEL       ss2;
+    uint16_t    padding_ss2;
+    /** 0x1c - Page directory for the task. (static) */
+    uint32_t    cr3;
+    /** 0x20 - EIP before task switch. */
+    uint32_t    eip;
+    /** 0x24 - EFLAGS before task switch. */
+    uint32_t    eflags;
+    /** 0x28 - EAX before task switch. */
+    uint32_t    eax;
+    /** 0x2c - ECX before task switch. */
+    uint32_t    ecx;
+    /** 0x30 - EDX before task switch. */
+    uint32_t    edx;
+    /** 0x34 - EBX before task switch. */
+    uint32_t    ebx;
+    /** 0x38 - ESP before task switch. */
+    uint32_t    esp;
+    /** 0x3c - EBP before task switch. */
+    uint32_t    ebp;
+    /** 0x40 - ESI before task switch. */
+    uint32_t    esi;
+    /** 0x44 - EDI before task switch. */
+    uint32_t    edi;
+    /** 0x48 - ES before task switch. */
+    RTSEL       es;
+    uint16_t    padding_es;
+    /** 0x4c - CS before task switch. */
+    RTSEL       cs;
+    uint16_t    padding_cs;
+    /** 0x50 - SS before task switch. */
+    RTSEL       ss;
+    uint16_t    padding_ss;
+    /** 0x54 - DS before task switch. */
+    RTSEL       ds;
+    uint16_t    padding_ds;
+    /** 0x58 - FS before task switch. */
+    RTSEL       fs;
+    uint16_t    padding_fs;
+    /** 0x5c - GS before task switch. */
+    RTSEL       gs;
+    uint16_t    padding_gs;
+    /** 0x60 - LDTR before task switch. */
+    RTSEL       selLdt;
+    uint16_t    padding_ldt;
+    /** 0x64 - Debug trap flag */
+    uint16_t    fDebugTrap;
+    /** 0x66 -  Offset relative to the TSS of the start of the I/O Bitmap
+     * and the end of the interrupt redirection bitmap. */
+    uint16_t    offIoBitmap;
+    /** 0x68 -  32 bytes for the virtual interrupt redirection bitmap. (VME) */
+    uint8_t     IntRedirBitmap[32];
+} VBOXTSS;
+#pragma pack()
+/** Pointer to task segment. */
+typedef VBOXTSS *PVBOXTSS;
+/** Pointer to const task segment. */
+typedef const VBOXTSS *PCVBOXTSS;
+
+
+/** Pointer to a callback method table provided by the VM API user. */
+typedef struct VMM2USERMETHODS const *PCVMM2USERMETHODS;
+
+
+/**
+ * Data transport buffer (scatter/gather)
+ */
+typedef struct PDMDATASEG
+{
+    /** Length of buffer in entry. */
+    size_t  cbSeg;
+    /** Pointer to the start of the buffer. */
+    void   *pvSeg;
+} PDMDATASEG;
+/** Pointer to a data transport segment. */
+typedef PDMDATASEG *PPDMDATASEG;
+/** Pointer to a const data transport segment. */
+typedef PDMDATASEG const *PCPDMDATASEG;
+
+
+/**
+ * Forms of generic segment offloading.
+ */
+typedef enum PDMNETWORKGSOTYPE
+{
+    /** Invalid zero value. */
+    PDMNETWORKGSOTYPE_INVALID = 0,
+    /** TCP/IPv4 - no CWR/ECE encoding. */
+    PDMNETWORKGSOTYPE_IPV4_TCP,
+    /** TCP/IPv6 - no CWR/ECE encoding. */
+    PDMNETWORKGSOTYPE_IPV6_TCP,
+    /** UDP/IPv4. */
+    PDMNETWORKGSOTYPE_IPV4_UDP,
+    /** UDP/IPv6. */
+    PDMNETWORKGSOTYPE_IPV6_UDP,
+    /** TCP/IPv6 over IPv4 tunneling - no CWR/ECE encoding.
+     * The header offsets and sizes relates to IPv4 and TCP, the IPv6 header is
+     * figured out as needed.
+     * @todo Needs checking against facts, this is just an outline of the idea. */
+    PDMNETWORKGSOTYPE_IPV4_IPV6_TCP,
+    /** UDP/IPv6 over IPv4 tunneling.
+     * The header offsets and sizes relates to IPv4 and UDP, the IPv6 header is
+     * figured out as needed.
+     * @todo Needs checking against facts, this is just an outline of the idea. */
+    PDMNETWORKGSOTYPE_IPV4_IPV6_UDP,
+    /** The end of valid GSO types. */
+    PDMNETWORKGSOTYPE_END
+} PDMNETWORKGSOTYPE;
+
+
+/**
+ * Generic segment offloading context.
+ *
+ * We generally follow the E1000 specs wrt to which header fields we change.
+ * However the GSO type implies where the checksum fields are and that they are
+ * always updated from scratch (no half done pseudo checksums).
+ *
+ * @remarks This is part of the internal network GSO packets.  Take great care
+ *          when making changes.  The size is expected to be exactly 8 bytes.
+ */
+typedef struct PDMNETWORKGSO
+{
+    /** The type of segmentation offloading we're performing (PDMNETWORKGSOTYPE). */
+    uint8_t             u8Type;
+    /** The total header size. */
+    uint8_t             cbHdrsTotal;
+    /** The max segment size (MSS) to apply. */
+    uint16_t            cbMaxSeg;
+
+    /** Offset of the first header (IPv4 / IPv6).  0 if not not needed. */
+    uint8_t             offHdr1;
+    /** Offset of the second header (TCP / UDP).  0 if not not needed. */
+    uint8_t             offHdr2;
+    /** The header size used for segmentation (equal to offHdr2 in UFO). */
+    uint8_t             cbHdrsSeg;
+    /** Unused. */
+    uint8_t             u8Unused;
+} PDMNETWORKGSO;
+/** Pointer to a GSO context. */
+typedef PDMNETWORKGSO *PPDMNETWORKGSO;
+/** Pointer to a const GSO context. */
+typedef PDMNETWORKGSO const *PCPDMNETWORKGSO;
+
+
+/**
+ * The current ROM page protection.
+ *
+ * @remarks This is part of the saved state.
+ */
+typedef enum PGMROMPROT
+{
+    /** The customary invalid value. */
+    PGMROMPROT_INVALID = 0,
+    /** Read from the virgin ROM page, ignore writes.
+     * Map the virgin page, use write access handler to ignore writes. */
+    PGMROMPROT_READ_ROM_WRITE_IGNORE,
+    /** Read from the virgin ROM page, write to the shadow RAM.
+     * Map the virgin page, use write access handler to change the shadow RAM. */
+    PGMROMPROT_READ_ROM_WRITE_RAM,
+    /** Read from the shadow ROM page, ignore writes.
+     * Map the shadow page read-only, use write access handler to ignore writes. */
+    PGMROMPROT_READ_RAM_WRITE_IGNORE,
+    /** Read from the shadow ROM page, ignore writes.
+     * Map the shadow page read-write, disabled write access handler. */
+    PGMROMPROT_READ_RAM_WRITE_RAM,
+    /** The end of valid values. */
+    PGMROMPROT_END,
+    /** The usual 32-bit type size hack. */
+    PGMROMPROT_32BIT_HACK = 0x7fffffff
+} PGMROMPROT;
+
+
+/**
+ * Page mapping lock.
+ */
+typedef struct PGMPAGEMAPLOCK
+{
+#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
+    /** The locked page. */
+    void       *pvPage;
+    /** Pointer to the CPU that made the mapping.
+     * In ring-0 and raw-mode context we don't intend to ever allow long term
+     * locking and this is a way of making sure we're still on the same CPU. */
+    PVMCPU      pVCpu;
+#else
+    /** Pointer to the PGMPAGE and lock type.
+     * bit-0 abuse: set=write, clear=read. */
+    uintptr_t   uPageAndType;
+/** Read lock type value. */
+# define PGMPAGEMAPLOCK_TYPE_READ    ((uintptr_t)0)
+/** Write lock type value. */
+# define PGMPAGEMAPLOCK_TYPE_WRITE   ((uintptr_t)1)
+/** Lock type mask. */
+# define PGMPAGEMAPLOCK_TYPE_MASK    ((uintptr_t)1)
+    /** Pointer to the PGMCHUNKR3MAP. */
+    void       *pvMap;
+#endif
+} PGMPAGEMAPLOCK;
+/** Pointer to a page mapping lock. */
+typedef PGMPAGEMAPLOCK *PPGMPAGEMAPLOCK;
+
+
+/** Pointer to a info helper callback structure. */
+typedef struct DBGFINFOHLP *PDBGFINFOHLP;
+/** Pointer to a const info helper callback structure. */
+typedef const struct DBGFINFOHLP *PCDBGFINFOHLP;
+
+/** Pointer to a const register descriptor. */
+typedef struct DBGFREGDESC const *PCDBGFREGDESC;
+
+
+/** Configuration manager tree node - A key. */
+typedef struct CFGMNODE *PCFGMNODE;
+
+/** Configuration manager tree leaf - A value. */
+typedef struct CFGMLEAF *PCFGMLEAF;
+
+
+/**
+ * CPU modes.
+ */
+typedef enum CPUMMODE
+{
+    /** The usual invalid zero entry. */
+    CPUMMODE_INVALID = 0,
+    /** Real mode. */
+    CPUMMODE_REAL,
+    /** Protected mode (32-bit). */
+    CPUMMODE_PROTECTED,
+    /** Long mode (64-bit). */
+    CPUMMODE_LONG
+} CPUMMODE;
+
+
+/**
+ * CPU mode flags (DISSTATE::mode).
+ */
+typedef enum DISCPUMODE
+{
+    DISCPUMODE_INVALID = 0,
+    DISCPUMODE_16BIT,
+    DISCPUMODE_32BIT,
+    DISCPUMODE_64BIT,
+    /** hack forcing the size of the enum to 32-bits. */
+    DISCPUMODE_MAKE_32BIT_HACK = 0x7fffffff
+} DISCPUMODE;
+
+/** Pointer to the disassembler state. */
+typedef struct DISSTATE *PDISSTATE;
+/** Pointer to a const disassembler state. */
+typedef struct DISSTATE const *PCDISSTATE;
+
+/** @deprecated  PDISSTATE and change pCpu and pDisState to pDis. */
+typedef PDISSTATE PDISCPUSTATE;
+/** @deprecated  PCDISSTATE and change pCpu and pDisState to pDis. */
+typedef PCDISSTATE PCDISCPUSTATE;
+
+
+/** @} */
+
+#endif
diff --git a/ubuntu/vbox/include/VBox/version.h b/ubuntu/vbox/include/VBox/version.h
new file mode 100644 (file)
index 0000000..c3c665a
--- /dev/null
@@ -0,0 +1,153 @@
+/** @file
+ * VBox Version Management.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBox_version_h
+#define ___VBox_version_h
+
+/* Product info. */
+#include <product-generated.h>
+#include <version-generated.h>
+
+#ifdef RC_INVOKED
+/* Some versions of RC has trouble with cdefs.h, so we duplicate these two here. */
+# define RT_STR(str)             #str
+# define RT_XSTR(str)            RT_STR(str)
+#else  /* !RC_INVOKED */
+
+/** Combined version number. */
+# define VBOX_VERSION                    (VBOX_VERSION_MAJOR << 16 | VBOX_VERSION_MINOR)
+/** Get minor version from combined version. */
+# define VBOX_GET_VERSION_MINOR(uVer)    ((uVer) & 0xffff)
+/** Get major version from combined version. */
+# define VBOX_GET_VERSION_MAJOR(uVer)    ((uVer) >> 16)
+
+/**
+ * Make a full version number.
+ *
+ * The returned number can be used in normal integer comparsions and will yield
+ * the expected results.
+ *
+ * @param   uMajor      The major version number.
+ * @param   uMinor      The minor version number.
+ * @param   uBuild      The build number.
+ * @returns Full version number.
+ */
+# define VBOX_FULL_VERSION_MAKE(uMajor, uMinor, uBuild) \
+    (  (uint32_t)((uMajor) &   0xff) << 24 \
+     | (uint32_t)((uMinor) &   0xff) << 16 \
+     | (uint32_t)((uBuild) & 0xffff)       \
+    )
+
+/** Combined version number. */
+# define VBOX_FULL_VERSION              \
+    VBOX_FULL_VERSION_MAKE(VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD)
+/** Get the major version number from a VBOX_FULL_VERSION style number. */
+# define VBOX_FULL_VERSION_GET_MAJOR(uFullVer)  ( ((uFullVer) >> 24) &   0xffU )
+/** Get the minor version number from a VBOX_FULL_VERSION style number. */
+# define VBOX_FULL_VERSION_GET_MINOR(uFullVer)  ( ((uFullVer) >> 16) &   0xffU )
+/** Get the build version number from a VBOX_FULL_VERSION style number. */
+# define VBOX_FULL_VERSION_GET_BUILD(uFullVer)  ( ((uFullVer)      ) & 0xffffU )
+
+/**
+ * Make a short version number for use in 16 bit version fields.
+ *
+ * The returned number can be used in normal integer comparsions and will yield
+ * the expected results.
+ *
+ * @param   uMajor      The major version number.
+ * @param   uMinor      The minor version number.
+ * @returns Short version number.
+ */
+# define VBOX_SHORT_VERSION_MAKE(uMajor, uMinor) \
+    (  (uint16_t)((uMajor) &   0xff) << 8 \
+     | (uint16_t)((uMinor) &   0xff)      \
+    )
+
+/** Combined short version number. */
+# define VBOX_SHORT_VERSION               \
+    VBOX_SHORT_VERSION_MAKE(VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR)
+/** Get the major version number from a VBOX_SHORT_VERSION style number. */
+# define VBOX_SHORT_VERSION_GET_MAJOR(uShortVer)  ( ((uShortVer) >> 8) &   0xffU )
+/** Get the minor version number from a VBOX_SHORT_VERSION style number. */
+# define VBOX_SHORT_VERSION_GET_MINOR(uShortVer)  ( (uShortVer) &   0xffU )
+
+#endif /* !RC_INVOKED */
+
+/** @name Prefined strings for Windows resource files
+ * @{ */
+#define VBOX_RC_COMPANY_NAME            VBOX_VENDOR
+#define VBOX_RC_LEGAL_COPYRIGHT         "Copyright (C) 2009-" VBOX_C_YEAR " Oracle Corporation\0"
+#define VBOX_RC_PRODUCT_NAME                    VBOX_PRODUCT
+#define VBOX_RC_PRODUCT_NAME_GA                 VBOX_PRODUCT " Guest Additions"
+#define VBOX_RC_PRODUCT_NAME_PUEL_EXTPACK       VBOX_PRODUCT " Extension Pack"
+#define VBOX_RC_PRODUCT_NAME_DTRACE_EXTPACK     VBOX_PRODUCT " VBoxDTrace Extension Pack"
+#define VBOX_RC_PRODUCT_NAME_STR                VBOX_RC_PRODUCT_NAME "\0"
+#define VBOX_RC_PRODUCT_NAME_GA_STR             VBOX_RC_PRODUCT_NAME_GA "\0"
+#define VBOX_RC_PRODUCT_NAME_PUEL_EXTPACK_STR   VBOX_RC_PRODUCT_NAME_PUEL_EXTPACK "\0"
+#define VBOX_RC_PRODUCT_NAME_DTRACE_EXTPACK_STR VBOX_RC_PRODUCT_NAME_DTRACE_EXTPACK "\0"
+#define VBOX_RC_PRODUCT_VERSION         VBOX_VERSION_MAJOR , VBOX_VERSION_MINOR , VBOX_VERSION_BUILD , VBOX_SVN_REV_MOD_5K
+#define VBOX_RC_FILE_VERSION            VBOX_VERSION_MAJOR , VBOX_VERSION_MINOR , VBOX_VERSION_BUILD , VBOX_SVN_REV_MOD_5K
+#ifndef VBOX_VERSION_PRERELEASE
+# define VBOX_RC_PRODUCT_VERSION_STR    RT_XSTR(VBOX_VERSION_MAJOR) "." RT_XSTR(VBOX_VERSION_MINOR) "." RT_XSTR(VBOX_VERSION_BUILD) "." RT_XSTR(VBOX_SVN_REV) "\0"
+# define VBOX_RC_FILE_VERSION_STR       RT_XSTR(VBOX_VERSION_MAJOR) "." RT_XSTR(VBOX_VERSION_MINOR) "." RT_XSTR(VBOX_VERSION_BUILD) "." RT_XSTR(VBOX_SVN_REV) "\0"
+#else
+# define VBOX_RC_PRODUCT_VERSION_STR    RT_XSTR(VBOX_VERSION_MAJOR) "." RT_XSTR(VBOX_VERSION_MINOR) "." RT_XSTR(VBOX_VERSION_BUILD) "." RT_XSTR(VBOX_SVN_REV) " (" VBOX_VERSION_PRERELEASE ")\0"
+# define VBOX_RC_FILE_VERSION_STR       RT_XSTR(VBOX_VERSION_MAJOR) "." RT_XSTR(VBOX_VERSION_MINOR) "." RT_XSTR(VBOX_VERSION_BUILD) "." RT_XSTR(VBOX_SVN_REV) " (" VBOX_VERSION_PRERELEASE ")\0"
+#endif
+#define VBOX_RC_FILE_OS                 VOS_NT_WINDOWS32
+#define VBOX_RC_TYPE_DLL                VFT_DLL
+#define VBOX_RC_TYPE_APP                VFT_APP
+#define VBOX_RC_TYPE_DRV                VFT_DRV
+/* Flags and extra strings depending on the build type and who's building. */
+#if defined(DEBUG) || defined(LOG_ENABLED) || defined(RT_STRICT) || defined(VBOX_STRICT) || defined(VBOX_WITH_STATISTICS)
+# define VBOX_RC_FILE_FLAGS_DEBUG       VS_FF_DEBUG
+#else
+# define VBOX_RC_FILE_FLAGS_DEBUG       0
+#endif
+#if VBOX_VERSION_MINOR >= 51 || defined(VBOX_VERSION_PRERELEASE)
+# define VBOX_RC_FILE_FLAGS_PRERELEASE  VS_FF_PRERELEASE
+#else
+# define VBOX_RC_FILE_FLAGS_PRERELEASE  0
+#endif
+#if defined(VBOX_BUILD_SERVER_BUILD) && (VBOX_VERSION_MINOR & 1) == 0
+# define VBOX_RC_FILE_FLAGS_BUILD       0
+# define VBOX_RC_MORE_STRINGS
+#elif defined(VBOX_BUILD_SERVER_BUILD)
+# define VBOX_RC_FILE_FLAGS_BUILD       VS_FF_SPECIALBUILD
+# define VBOX_RC_MORE_STRINGS           VALUE "SpecialBuild", "r" RT_XSTR(VBOX_SVN_REV) "\0"
+#else
+# define VBOX_RC_FILE_FLAGS_BUILD       VS_FF_PRIVATEBUILD
+# ifdef VBOX_PRIVATE_BUILD_DESC
+#  define VBOX_RC_MORE_STRINGS          VALUE "PrivateBuild", VBOX_PRIVATE_BUILD_DESC "\0"
+# else
+#  define VBOX_RC_MORE_STRINGS          VALUE "PrivateBuild", "r" RT_XSTR(VBOX_SVN_REV) "\0"
+# error
+# endif
+#endif
+#define VBOX_RC_FILE_FLAGS              (VBOX_RC_FILE_FLAGS_DEBUG | VBOX_RC_FILE_FLAGS_PRERELEASE | VBOX_RC_FILE_FLAGS_BUILD)
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/internal/assert.h b/ubuntu/vbox/include/internal/assert.h
new file mode 100644 (file)
index 0000000..78e4e43
--- /dev/null
@@ -0,0 +1,63 @@
+/* $Id: assert.h $ */
+/** @file
+ * IPRT - Internal RTAssert header
+ */
+
+/*
+ * Copyright (C) 2009-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.
+ */
+
+#ifndef ___internal_assert_h
+#define ___internal_assert_h
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+#ifdef IN_RING0
+
+/**
+ * Print the 1st part of an assert message to whatever native facility is best
+ * fitting.
+ *
+ * @param   pszExpr     Expression. Can be NULL.
+ * @param   uLine       Location line number.
+ * @param   pszFile     Location file name.
+ * @param   pszFunction Location function name.
+ */
+DECLHIDDEN(void) rtR0AssertNativeMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction);
+
+/**
+ * Print the 2nd (optional) part of an assert message to whatever native
+ * facility is best fitting.
+ *
+ * @param   fInitial    Whether it's the initial (true) or an additional (false)
+ *                      message.
+ * @param   pszFormat   Printf like format string.
+ * @param   va          Arguments to that string.
+ */
+DECLHIDDEN(void) rtR0AssertNativeMsg2V(bool fInitial, const char *pszFormat, va_list va);
+
+#endif
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/internal/initterm.h b/ubuntu/vbox/include/internal/initterm.h
new file mode 100644 (file)
index 0000000..4f6495f
--- /dev/null
@@ -0,0 +1,53 @@
+/* $Id: initterm.h $ */
+/** @file
+ * IPRT - Initialization & Termination.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___internal_initterm_h
+#define ___internal_initterm_h
+
+#include <iprt/cdefs.h>
+
+RT_C_DECLS_BEGIN
+
+#ifdef IN_RING0
+
+/**
+ * Platform specific initialization.
+ *
+ * @returns IPRT status code.
+ */
+DECLHIDDEN(int)  rtR0InitNative(void);
+
+/**
+ * Platform specific termination.
+ */
+DECLHIDDEN(void) rtR0TermNative(void);
+
+#endif /* IN_RING0 */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/internal/iprt.h b/ubuntu/vbox/include/internal/iprt.h
new file mode 100644 (file)
index 0000000..de86779
--- /dev/null
@@ -0,0 +1,204 @@
+/* $Id: iprt.h $ */
+/** @file
+ * IPRT - Internal header for miscellaneous global defs and types.
+ */
+
+/*
+ * Copyright (C) 2009-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.
+ */
+
+#ifndef ___internal_iprt_h
+#define ___internal_iprt_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+/** @def RT_EXPORT_SYMBOL
+ * This define is really here just for the linux kernel.
+ * @param   Name        The symbol name.
+ */
+#if defined(RT_OS_LINUX) \
+ && defined(IN_RING0) \
+ && defined(MODULE) \
+ && !defined(RT_NO_EXPORT_SYMBOL)
+# define bool linux_bool /* see r0drv/linux/the-linux-kernel.h */
+# include <linux/version.h>
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+#  include <generated/autoconf.h>
+# else
+#  ifndef AUTOCONF_INCLUDED
+#   include <linux/autoconf.h>
+#  endif
+# endif
+# if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#  define MODVERSIONS
+#  if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 71)
+#   include <linux/modversions.h>
+#  endif
+# endif
+# include <linux/module.h>
+# undef bool
+# define RT_EXPORT_SYMBOL(Name) EXPORT_SYMBOL(Name)
+#else
+# define RT_EXPORT_SYMBOL(Name) extern int g_rtExportSymbolDummyVariable
+#endif
+
+
+/** @def RT_MORE_STRICT
+ * Enables more assertions in IPRT. */
+#if !defined(RT_MORE_STRICT) && (defined(DEBUG) || defined(RT_STRICT) || defined(DOXYGEN_RUNNING)) && !defined(RT_OS_WINDOWS) /** @todo enable on windows after testing */
+# define RT_MORE_STRICT
+#endif
+
+/** @def RT_ASSERT_PREEMPT_CPUID_VAR
+ * Partner to RT_ASSERT_PREEMPT_CPUID_VAR. Declares and initializes a variable
+ * idAssertCpu to NIL_RTCPUID if preemption is enabled and to RTMpCpuId if
+ * disabled.  When RT_MORE_STRICT isn't defined it declares an uninitialized
+ * dummy variable.
+ *
+ * Requires iprt/mp.h and iprt/asm.h.
+ */
+/** @def RT_ASSERT_PREEMPT_CPUID
+ * Asserts that we didn't change CPU since RT_ASSERT_PREEMPT_CPUID_VAR if
+ * preemption is disabled.  Will also detect changes in preemption
+ * disable/enable status.  This is a noop when RT_MORE_STRICT isn't defined. */
+#ifdef RT_MORE_STRICT
+# define RT_ASSERT_PREEMPT_CPUID_VAR() \
+    RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
+# define RT_ASSERT_PREEMPT_CPUID() \
+   do \
+   { \
+        RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
+        AssertMsg(idAssertCpu == idAssertCpuNow,  ("%#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
+   } while (0)
+
+#else
+# define RT_ASSERT_PREEMPT_CPUID_VAR()  RTCPUID idAssertCpuDummy
+# define RT_ASSERT_PREEMPT_CPUID()      NOREF(idAssertCpuDummy)
+#endif
+
+/** @def RT_ASSERT_PREEMPT_CPUID_SPIN_ACQUIRED
+ * Extended version of RT_ASSERT_PREEMPT_CPUID for use before
+ * RTSpinlockAcquired* returns.  This macro works the idCpuOwner and idAssertCpu
+ * members of the spinlock instance data. */
+#ifdef RT_MORE_STRICT
+# define RT_ASSERT_PREEMPT_CPUID_SPIN_ACQUIRED(pThis) \
+    do \
+    { \
+        RTCPUID const idAssertCpuNow = RTMpCpuId(); \
+        AssertMsg(idAssertCpu == idAssertCpuNow || idAssertCpu == NIL_RTCPUID,  ("%#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
+        (pThis)->idAssertCpu = idAssertCpu; \
+        (pThis)->idCpuOwner  = idAssertCpuNow; \
+    } while (0)
+#else
+# define RT_ASSERT_PREEMPT_CPUID_SPIN_ACQUIRED(pThis)   NOREF(idAssertCpuDummy)
+#endif
+
+/** @def RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE_VARS
+ * Extended version of RT_ASSERT_PREEMPT_CPUID_VAR for use with
+ * RTSpinlockRelease* returns. */
+#ifdef RT_MORE_STRICT
+# define RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE_VARS()    RTCPUID idAssertCpu
+#else
+# define RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE_VARS()    RTCPUID idAssertCpuDummy
+#endif
+
+/** @def RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE
+ * Extended version of RT_ASSERT_PREEMPT_CPUID for use in RTSpinlockRelease*
+ * before calling the native API for releasing the spinlock.  It must be
+ * teamed up with RT_ASSERT_PREEMPT_CPUID_SPIN_ACQUIRED. */
+#ifdef RT_MORE_STRICT
+# define RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE(pThis) \
+    do \
+    { \
+        RTCPUID const idCpuOwner     = (pThis)->idCpuOwner; \
+        RTCPUID const idAssertCpuNow = RTMpCpuId(); \
+        AssertMsg(idCpuOwner == idAssertCpuNow,  ("%#x, %#x\n", idCpuOwner, idAssertCpuNow)); \
+        (pThis)->idCpuOwner  = NIL_RTCPUID; \
+        idAssertCpu = (pThis)->idAssertCpu; \
+        (pThis)->idAssertCpu = NIL_RTCPUID; \
+    } while (0)
+#else
+# define RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE(pThis)    NOREF(idAssertCpuDummy)
+#endif
+
+/** @def RT_ASSERT_PREEMPT_CPUID_DISABLE
+ * For use in RTThreadPreemptDisable implementations after having disabled
+ * preemption.  Requires iprt/mp.h. */
+#ifdef RT_MORE_STRICT
+# define RT_ASSERT_PREEMPT_CPUID_DISABLE(pStat) \
+    do \
+    { \
+        Assert((pStat)->idCpu == NIL_RTCPUID); \
+        (pStat)->idCpu = RTMpCpuId(); \
+    } while (0)
+#else
+# define RT_ASSERT_PREEMPT_CPUID_DISABLE(pStat) \
+    Assert((pStat)->idCpu == NIL_RTCPUID)
+#endif
+
+/** @def RT_ASSERT_PREEMPT_CPUID_RESTORE
+ * For use in RTThreadPreemptRestore implementations before restoring
+ * preemption.  Requires iprt/mp.h. */
+#ifdef RT_MORE_STRICT
+# define RT_ASSERT_PREEMPT_CPUID_RESTORE(pStat) \
+    do \
+    { \
+        RTCPUID const idAssertCpuNow = RTMpCpuId(); \
+        AssertMsg((pStat)->idCpu == idAssertCpuNow,  ("%#x, %#x\n", (pStat)->idCpu, idAssertCpuNow)); \
+        (pStat)->idCpu = NIL_RTCPUID; \
+    } while (0)
+#else
+# define RT_ASSERT_PREEMPT_CPUID_RESTORE(pStat)         do { } while (0)
+#endif
+
+
+/** @def RT_ASSERT_INTS_ON
+ * Asserts that interrupts are disabled when RT_MORE_STRICT is defined. */
+#ifdef RT_MORE_STRICT
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+#  define RT_ASSERT_INTS_ON()           Assert(ASMIntAreEnabled())
+# else /* PORTME: Add architecture/platform specific test. */
+#  define RT_ASSERT_INTS_ON()           Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD))
+# endif
+#else
+# define RT_ASSERT_INTS_ON()            do { } while (0)
+#endif
+
+/** @def RT_ASSERT_PREEMPTIBLE
+ * Asserts that preemption hasn't been disabled (using
+ * RTThreadPreemptDisable) when RT_MORE_STRICT is defined. */
+#ifdef RT_MORE_STRICT
+# define RT_ASSERT_PREEMPTIBLE()        Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD))
+#else
+# define RT_ASSERT_PREEMPTIBLE()        do { } while (0)
+#endif
+
+
+RT_C_DECLS_BEGIN
+
+#ifdef RT_OS_OS2
+uint32_t rtR0SemWaitOs2ConvertTimeout(uint32_t fFlags, uint64_t uTimeout);
+#endif
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/internal/lockvalidator.h b/ubuntu/vbox/include/internal/lockvalidator.h
new file mode 100644 (file)
index 0000000..342402d
--- /dev/null
@@ -0,0 +1,116 @@
+/* $Id: lockvalidator.h $ */
+/** @file
+ * IPRT - Internal RTLockValidator header.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_internal_lockvalidator_h
+#define ___iprt_internal_lockvalidator_h
+
+#include <iprt/types.h>
+#include <iprt/lockvalidator.h>
+
+RT_C_DECLS_BEGIN
+
+
+/**
+ * Record used only on the lock stack for recording the stack and source
+ * position of a recursive lock acquisition.
+ */
+typedef struct RTLOCKVALRECNEST
+{
+    RTLOCKVALRECCORE                Core;
+    /** The recursion level at this point in the stack. */
+    uint32_t                        cRecursion;
+    /** Pointer to the next record on the stack. */
+    PRTLOCKVALRECUNION volatile     pDown;
+    /** Pointer to the first recursion. */
+    PRTLOCKVALRECUNION volatile     pRec;
+    /** Pointer to the next free record when in the
+     *  RTLOCKVALPERTHREAD::pFreeNestRecs list. */
+    struct RTLOCKVALRECNEST        *pNextFree;
+    /** The source position. */
+    RTLOCKVALSRCPOS                 SrcPos;
+} RTLOCKVALRECNEST;
+/** Pointer to a recursion record. */
+typedef RTLOCKVALRECNEST *PRTLOCKVALRECNEST;
+
+
+/**
+ * Record union for simplifying internal processing.
+ */
+typedef union RTLOCKVALRECUNION
+{
+    RTLOCKVALRECCORE                Core;
+    RTLOCKVALRECEXCL                Excl;
+    RTLOCKVALRECSHRD                Shared;
+    RTLOCKVALRECSHRDOWN             ShrdOwner;
+    RTLOCKVALRECNEST                Nest;
+} RTLOCKVALRECUNION;
+
+
+/**
+ * Per thread data for the lock validator.
+ *
+ * This is part of the RTTHREADINT structure.
+ */
+typedef struct RTLOCKVALPERTHREAD
+{
+    /** Where we are blocking. */
+    RTLOCKVALSRCPOS                 SrcPos;
+    /** Top of the lock stack. */
+    PRTLOCKVALRECUNION volatile     pStackTop;
+    /** List of free recursion (nesting) record. */
+    PRTLOCKVALRECNEST               pFreeNestRecs;
+    /** What we're blocking on.
+     * The lock validator sets this, RTThreadUnblock clears it. */
+    PRTLOCKVALRECUNION volatile     pRec;
+    /** The state in which pRec that goes with pRec.
+     * RTThreadUnblocking uses this to figure out when to clear pRec. */
+    RTTHREADSTATE volatile          enmRecState;
+    /** The thread is running inside the lock validator. */
+    bool volatile                   fInValidator;
+    /** Reserved for alignment purposes. */
+    bool                            afReserved[3];
+    /** Number of registered write locks, mutexes and critsects that this thread owns. */
+    int32_t volatile                cWriteLocks;
+    /** Number of registered read locks that this thread owns, nesting included. */
+    int32_t volatile                cReadLocks;
+    /** Bitmap indicating which entires are free (set) and allocated (clear). */
+    uint32_t volatile               bmFreeShrdOwners;
+    /** Reserved for alignment purposes. */
+    uint32_t                        u32Reserved;
+    /** Statically allocated shared owner records */
+    RTLOCKVALRECSHRDOWN             aShrdOwners[32];
+} RTLOCKVALPERTHREAD;
+
+
+DECLHIDDEN(void)    rtLockValidatorInitPerThread(RTLOCKVALPERTHREAD *pPerThread);
+DECLHIDDEN(void)    rtLockValidatorDeletePerThread(RTLOCKVALPERTHREAD *pPerThread);
+DECLHIDDEN(void)    rtLockValidatorSerializeDestructEnter(void);
+DECLHIDDEN(void)    rtLockValidatorSerializeDestructLeave(void);
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/internal/magics.h b/ubuntu/vbox/include/internal/magics.h
new file mode 100644 (file)
index 0000000..ff23f47
--- /dev/null
@@ -0,0 +1,241 @@
+/* $Id: magics.h $ */
+/** @file
+ * IPRT - Internal header defining The Magic Numbers.
+ */
+
+/*
+ * Copyright (C) 2007-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.
+ */
+
+#ifndef ___internal_magics_h
+#define ___internal_magics_h
+
+/** @name Magic Numbers.
+ * @{ */
+
+/** Magic number for RTAIOMGRINT::u32Magic. (Emil Erich Kaestner) */
+#define RTAIOMGR_MAGIC                  UINT32_C(0x18990223)
+/** Magic number for RTAIOMGRINTFILE::u32Magic. (Ephraim Kishon) */
+#define RTAIOMGRFILE_MAGIC              UINT32_C(0x19240823)
+/** Magic number for RTDBGMODINT::u32Magic. (Charles Lloyd) */
+#define RTDBGAS_MAGIC                   UINT32_C(0x19380315)
+/** Magic number for RTDBGCFGINT::u32Magic. (McCoy Tyner) */
+#define RTDBGCFG_MAGIC                  UINT32_C(0x19381211)
+/** Magic number for RTDBGMODINT::u32Magic. (Keith Jarrett) */
+#define RTDBGMOD_MAGIC                  UINT32_C(0x19450508)
+/** Magic number for RTDBGMODVTIMG::u32Magic. (Jack DeJohnette) */
+#define RTDBGMODVTDBG_MAGIC             UINT32_C(0x19420809)
+/** Magic number for RTDBGMODVTIMG::u32Magic. (Cecil McBee) */
+#define RTDBGMODVTIMG_MAGIC             UINT32_C(0x19350419)
+/** Magic value for RTDBGKRNLINFOINT::u32Magic. (John Carmack) */
+#define RTDBGKRNLINFO_MAGIC             UINT32_C(0x19700820)
+/** The value of RTDIR::u32Magic. (Michael Ende) */
+#define RTDIR_MAGIC                     UINT32_C(0x19291112)
+/** The value of RTDIR::u32Magic after RTDirClose().  */
+#define RTDIR_MAGIC_DEAD                UINT32_C(0x19950829)
+/** The value of RTDVMINTERNAL::u32Magic. (Dan Brown) */
+#define RTDVM_MAGIC                     UINT32_C(0x19640622)
+/** The value of RTDVMINTERNAL::u32Magic after close. */
+#define RTDVM_MAGIC_DEAD                (~RTDVM_MAGIC)
+/** The value of RTDVMVOLUMEINTERNAL::u32Magic. (Daniel Defoe) */
+#define RTDVMVOLUME_MAGIC               UINT32_C(0x16591961)
+/** The value of RTDVMVOLUMEINTERNAL::u32Magic after close. */
+#define RTDVMVOLUME_MAGIC_DEAD          UINT32_C(0x17310424)
+/** The value of RTFILEAIOCTXINT::u32Magic. (Howard Phillips Lovecraft) */
+#define RTFILEAIOCTX_MAGIC              UINT32_C(0x18900820)
+/** The value of RTFILEAIOCTXINT::u32Magic after RTFileAioCtxDestroy(). */
+#define RTFILEAIOCTX_MAGIC_DEAD         UINT32_C(0x19370315)
+/** The value of RTFILEAIOREQINT::u32Magic. (Stephen Edwin King)  */
+#define RTFILEAIOREQ_MAGIC              UINT32_C(0x19470921)
+/** The value of RTENVINTERNAL::u32Magic. (Rumiko Takahashi) */
+#define RTENV_MAGIC                     UINT32_C(0x19571010)
+/** The value of RTERRVARS::ai32Vars[0]. (Ryuichi Sakamoto) */
+#define RTERRVARS_MAGIC                 UINT32_C(0x19520117)
+/** Magic number for RTHANDLETABLEINT::u32Magic. (Hitomi Kanehara) */
+#define RTHANDLETABLE_MAGIC             UINT32_C(0x19830808)
+/** Magic number for RTHEAPOFFSETINTERNAL::u32Magic. (Neal Town Stephenson) */
+#define RTHEAPOFFSET_MAGIC              UINT32_C(0x19591031)
+/** Magic number for RTHEAPSIMPLEINTERNAL::uMagic. (Kyoichi Katayama) */
+#define RTHEAPSIMPLE_MAGIC              UINT32_C(0x19590105)
+/** The magic value for RTHTTPINTERNAL::u32Magic. (Karl May) */
+#define RTHTTP_MAGIC                    UINT32_C(0x18420225)
+/** The value of RTHTTPINTERNAL::u32Magic after close. */
+#define RTHTTP_MAGIC_DEAD               UINT32_C(0x19120330)
+/** The magic value for RTLDRMODINTERNAL::u32Magic. (Alan Moore) */
+#define RTLDRMOD_MAGIC                  UINT32_C(0x19531118)
+/** The magic value for RTLOCALIPCSERVER::u32Magic. (Naoki Yamamoto) */
+#define RTLOCALIPCSERVER_MAGIC          UINT32_C(0x19600201)
+/** The magic value for RTLOCALIPCSERVER::u32Magic. (Katsuhiro Otomo) */
+#define RTLOCALIPCSESSION_MAGIC         UINT32_C(0x19530414)
+/** The magic value for RTLOCKVALCLASSINT::u32Magic. (Thomas Mann) */
+#define RTLOCKVALCLASS_MAGIC            UINT32_C(0x18750605)
+/** The magic value for RTLOCKVALCLASSINT::u32Magic after destruction. */
+#define RTLOCKVALCLASS_MAGIC_DEAD       UINT32_C(0x19550812)
+/** The magic value for RTLOCKVALRECEXCL::u32Magic. (Vladimir Vladimirovich Nabokov) */
+#define RTLOCKVALRECEXCL_MAGIC          UINT32_C(0x18990422)
+/** The dead magic value for RTLOCKVALRECEXCL::u32Magic. */
+#define RTLOCKVALRECEXCL_MAGIC_DEAD     UINT32_C(0x19770702)
+/** The magic value for RTLOCKVALRECSHRD::u32Magic. (Agnar Mykle) */
+#define RTLOCKVALRECSHRD_MAGIC          UINT32_C(0x19150808)
+/** The magic value for RTLOCKVALRECSHRD::u32Magic after deletion. */
+#define RTLOCKVALRECSHRD_MAGIC_DEAD     UINT32_C(0x19940115)
+/** The magic value for RTLOCKVALRECSHRDOWN::u32Magic. (Jens Ingvald Bjoerneboe) */
+#define RTLOCKVALRECSHRDOWN_MAGIC       UINT32_C(0x19201009)
+/** The magic value for RTLOCKVALRECSHRDOWN::u32Magic after deletion. */
+#define RTLOCKVALRECSHRDOWN_MAGIC_DEAD  UINT32_C(0x19760509)
+/** The magic value for RTLOCKVALRECNEST::u32Magic. (Anne Desclos) */
+#define RTLOCKVALRECNEST_MAGIC          UINT32_C(0x19071123)
+/** The magic value for RTLOCKVALRECNEST::u32Magic after deletion. */
+#define RTLOCKVALRECNEST_MAGIC_DEAD     UINT32_C(0x19980427)
+/** Magic number for RTMEMCACHEINT::u32Magic. (Joseph Weizenbaum) */
+#define RTMEMCACHE_MAGIC                UINT32_C(0x19230108)
+/** Dead magic number for RTMEMCACHEINT::u32Magic. */
+#define RTMEMCACHE_MAGIC_DEAD           UINT32_C(0x20080305)
+/** The magic value for RTMEMPOOL::u32Magic. (Jane Austin) */
+#define RTMEMPOOL_MAGIC                 UINT32_C(0x17751216)
+/** The magic value for RTMEMPOOL::u32Magic after RTMemPoolDestroy. */
+#define RTMEMPOOL_MAGIC_DEAD            UINT32_C(0x18170718)
+/** The magic value for heap blocks. (Edgar Allan Poe) */
+#define RTMEMHDR_MAGIC                  UINT32_C(0x18090119)
+/** The magic value for heap blocks after freeing. */
+#define RTMEMHDR_MAGIC_DEAD             UINT32_C(0x18491007)
+/** The value of RTPIPEINTERNAL::u32Magic. (Frank Schaetzing) */
+#define RTPIPE_MAGIC                    UINT32_C(0x19570528)
+/** The value of RTPOLLSETINTERNAL::u32Magic. (Ai Yazawa) */
+#define RTPOLLSET_MAGIC                 UINT32_C(0x19670307)
+/** RTR0MEMOBJ::u32Magic. (Masakazu Katsura) */
+#define RTR0MEMOBJ_MAGIC                UINT32_C(0x19611210)
+/** RTRANDINT::u32Magic. (Alan Moore) */
+#define RTRANDINT_MAGIC                 UINT32_C(0x19531118)
+/** The value of RTREQ::u32Magic. */
+#define RTREQ_MAGIC                     UINT32_C(0xfeed0001) /**< @todo find a value */
+/** The value of RTREQ::u32Magic of a freed request. */
+#define RTREQ_MAGIC_DEAD                (~RTREQ_MAGIC)
+/** The value of RTREQPOOLINT::u32Magic. */
+#define RTREQPOOL_MAGIC                 UINT32_C(0xfeed0002)/**< @todo find a value */
+/** The value of RTREQPOOLINT::u32Magic after destruction. */
+#define RTREQPOOL_MAGIC_DEAD           (~RTREQPOOL_MAGIC)
+/** The value of RTREQQUEUEINT::u32Magic. */
+#define RTREQQUEUE_MAGIC                UINT32_C(0xfeed0003)/**< @todo find a value */
+/** The value of RTREQQUEUEINT::u32Magic after destruction. */
+#define RTREQQUEUE_MAGIC_DEAD           (~RTREQQUEUE_MAGIC)
+/** The value of RTS3::u32Magic. (Edgar Wallace) */
+#define RTS3_MAGIC                      UINT32_C(0x18750401)
+/** The value of RTS3::u32Magic after RTS3Destroy().  */
+#define RTS3_MAGIC_DEAD                 UINT32_C(0x19320210)
+/** Magic for the event semaphore structure. (Neil Gaiman) */
+#define RTSEMEVENT_MAGIC                UINT32_C(0x19601110)
+/** Magic for the multiple release event semaphore structure. (Isaac Asimov) */
+#define RTSEMEVENTMULTI_MAGIC           UINT32_C(0x19200102)
+/** Dead magic value for multiple release event semaphore structures. */
+#define RTSEMEVENTMULTI_MAGIC_DEAD      UINT32_C(0x19920406)
+/** Magic value for RTSEMFASTMUTEXINTERNAL::u32Magic. (John Ronald Reuel Tolkien) */
+#define RTSEMFASTMUTEX_MAGIC            UINT32_C(0x18920103)
+/** Dead magic value for RTSEMFASTMUTEXINTERNAL::u32Magic. */
+#define RTSEMFASTMUTEX_MAGIC_DEAD       UINT32_C(0x19730902)
+/** Magic for the mutex semaphore structure. (Douglas Adams) */
+#define RTSEMMUTEX_MAGIC                UINT32_C(0x19520311)
+/** Dead magic for the mutex semaphore structure. */
+#define RTSEMMUTEX_MAGIC_DEAD           UINT32_C(0x20010511)
+/** Magic for the spinning mutex semaphore structure. (Natsume Soseki) */
+#define RTSEMSPINMUTEX_MAGIC            UINT32_C(0x18670209)
+/** Dead magic value for RTSEMSPINMUTEXINTERNAL::u32Magic. */
+#define RTSEMSPINMUTEX_MAGIC_DEAD       UINT32_C(0x19161209)
+/** RTSEMRWINTERNAL::u32Magic value. (Kosuke Fujishima) */
+#define RTSEMRW_MAGIC                   UINT32_C(0x19640707)
+/** RTSEMXROADSINTERNAL::u32Magic value. (Kenneth Elton "Ken" Kesey) */
+#define RTSEMXROADS_MAGIC               UINT32_C(0x19350917)
+/** RTSEMXROADSINTERNAL::u32Magic value after RTSemXRoadsDestroy. */
+#define RTSEMXROADS_MAGIC_DEAD          UINT32_C(0x20011110)
+/** The magic value for RTSOCKETINT::u32Magic. (Stanislaw Lem) */
+#define RTSOCKET_MAGIC                  UINT32_C(0x19210912)
+/** The magic value for RTSOCKETINT::u32Magic after destruction. */
+#define RTSOCKET_MAGIC_DEAD             UINT32_C(0x20060326)
+/** Magic value for RTSPINLOCKINTERNAL::u32Magic. (Terry Pratchett) */
+#define RTSPINLOCK_MAGIC                UINT32_C(0x19480428)
+/** Magic value for generic RTSPINLOCKINTERNAL::u32Magic (Georges Prosper Remi). */
+#define RTSPINLOCK_GEN_MAGIC            UINT32_C(0x10970522)
+/** Magic value for RTSTRCACHE::u32Magic. (Sir Arthur Charles Clarke) */
+#define RTSTRCACHE_MAGIC                UINT32_C(0x19171216)
+/** Magic value for RTSTRCACHE::u32Magic after RTStrCacheDestroy. */
+#define RTSTRCACHE_MAGIC_DEAD           UINT32_C(0x20080319)
+/** The value of RTSTREAM::u32Magic for a valid stream. */
+#define RTSTREAM_MAGIC                  UINT32_C(0xe44e44ee)
+/** Magic value for RTTCPSERVER::u32Magic. (Jan Garbarek) */
+#define RTTCPSERVER_MAGIC               UINT32_C(0x19470304)
+/** Magic value for RTTCPSERVER::u32Magic. (Harlan Ellison) */
+#define RTUDPSERVER_MAGIC               UINT32_C(0x19340527)
+/** The value of RTTAR::u32Magic. (Donald Ervin Knuth) */
+#define RTTAR_MAGIC                     UINT32_C(0x19380110)
+/** The value of RTTAR::u32Magic after RTTarClose(). */
+#define RTTAR_MAGIC_DEAD                ~RTTAR_MAGIC
+/** The value of RTTARFILE::u32Magic. (Abraham Stoker) */
+#define RTTARFILE_MAGIC                 UINT32_C(0x18471108)
+/** The value of RTTARFILE::u32Magic after RTTarFileClose(). */
+#define RTTARFILE_MAGIC_DEAD            UINT32_C(0x19120420)
+/** RTTESTINT::u32Magic value. (Daniel Kehlmann) */
+#define RTTESTINT_MAGIC                 UINT32_C(0x19750113)
+/** RTTHREADCTXHOOKINT::u32Magic value. (Dennis MacAlistair Ritchie) */
+#define RTTHREADCTXHOOKINT_MAGIC        UINT32_C(0x19410909)
+/** RTTHREADINT::u32Magic value. (Gilbert Keith Chesterton) */
+#define RTTHREADINT_MAGIC               UINT32_C(0x18740529)
+/** RTTHREADINT::u32Magic value for a dead thread. */
+#define RTTHREADINT_MAGIC_DEAD          UINT32_C(0x19360614)
+/** Magic number for timer handles. (Jared Mason Diamond) */
+#define RTTIMER_MAGIC                   UINT32_C(0x19370910)
+/** Magic number for timer low resolution handles. (Saki Hiwatari) */
+#define RTTIMERLR_MAGIC                 UINT32_C(0x19610715)
+/** Magic value of RTTRACEBUFINT::u32Magic. (George Orwell) */
+#define RTTRACEBUF_MAGIC                UINT32_C(0x19030625)
+/** Magic value of RTTRACEBUFINT::u32Magic after the final release. */
+#define RTTRACEBUF_MAGIC_DEAD           UINT32_C(0x19500121)
+/** The value of RTVFSOBJINTERNAL::u32Magic. (Yasunari Kawabata) */
+#define RTVFSOBJ_MAGIC                  UINT32_C(0x18990614)
+/** The value of RTVFSOBJINTERNAL::u32Magic arter close. */
+#define RTVFSOBJ_MAGIC_DEAD             UINT32_C(0x19720416)
+/** The value of RTVFSINTERNAL::u32Magic. (Sir Kingsley William Amis) */
+#define RTVFS_MAGIC                     UINT32_C(0x19220416)
+/** The value of RTVFSINTERNAL::u32Magic after close.  */
+#define RTVFS_MAGIC_DEAD                UINT32_C(0x19951022)
+/** The value of RTVFSFSSTREAMINTERNAL::u32Magic. (William McGuire "Bill" Bryson) */
+#define RTVFSFSSTREAM_MAGIC             UINT32_C(0x19511208)
+/** The value of RTVFSFSSTREAMINTERNAL::u32Magic after close */
+#define RTVFSFSSTREAM_MAGIC_DEAD        (~RTVFSFSSTREAM_MAGIC)
+/** The value of RTVFSDIRINTERNAL::u32Magic. (Franklin Patrick Herbert, Jr.) */
+#define RTVFSDIR_MAGIC                  UINT32_C(0x19201008)
+/** The value of RTVFSDIRINTERNAL::u32Magic after close. */
+#define RTVFSDIR_MAGIC_DEAD             UINT32_C(0x19860211)
+/** The value of RTVFSFILEINTERNAL::u32Magic. (Charles John Huffam Dickens) */
+#define RTVFSFILE_MAGIC                 UINT32_C(0x18120207)
+/** The value of RTVFSFILEINTERNAL::u32Magic after close. */
+#define RTVFSFILE_MAGIC_DEAD            UINT32_C(0x18700609)
+/** The value of RTVFSIOSTREAMINTERNAL::u32Magic. (Ernest Miller Hemingway) */
+#define RTVFSIOSTREAM_MAGIC             UINT32_C(0x18990721)
+/** The value of RTVFSIOSTREAMINTERNAL::u32Magic after close. */
+#define RTVFSIOSTREAM_MAGIC_DEAD        UINT32_C(0x19610702)
+/** The value of RTVFSSYMLINKINTERNAL::u32Magic. (Francis Scott Key Fitzgerald) */
+#define RTVFSSYMLINK_MAGIC              UINT32_C(0x18960924)
+/** The value of RTVFSSYMLINKINTERNAL::u32Magic after close. */
+#define RTVFSSYMLINK_MAGIC_DEAD         UINT32_C(0x19401221)
+
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/internal/mem.h b/ubuntu/vbox/include/internal/mem.h
new file mode 100644 (file)
index 0000000..4fb1835
--- /dev/null
@@ -0,0 +1,74 @@
+/* $Id: mem.h $ */
+/** @file
+ * IPRT - Memory Management.
+ */
+
+/*
+ * Copyright (C) 2010-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.
+ */
+
+#ifndef ___internal_mem_h
+#define ___internal_mem_h
+
+#include <iprt/cdefs.h>
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Special allocation method that does not have any IPRT dependencies.
+ *
+ * This is suitable for allocating memory for IPRT heaps, pools, caches, memory
+ * trackers, semaphores and similar that end up in bootstrap depencency hell
+ * otherwise.
+ *
+ * @returns Pointer to the allocated memory, NULL on failure.  Must be freed by
+ *          calling rtMemBaseFree().
+ * @param   cb          The number of bytes to allocate.
+ */
+DECLHIDDEN(void *)  rtMemBaseAlloc(size_t cb);
+
+/**
+ * Frees memory allocated by rtInitAlloc().
+ *
+ * @param   pv          What rtInitAlloc() returned.
+ */
+DECLHIDDEN(void)    rtMemBaseFree(void *pv);
+
+
+#ifdef IN_RING0
+/** @def RTR0MEM_WITH_EF_APIS
+ * Enables the electrict fence APIs.
+ *
+ * Requires working rtR0MemObjNativeProtect implementation, thus the current
+ * OS restrictions.
+ */
+# if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) || defined(DOXYGEN_RUNNING)
+#  define RTR0MEM_WITH_EF_APIS
+# endif
+# ifdef RTR0MEM_WITH_EF_APIS
+DECLHIDDEN(void)    rtR0MemEfInit(void);
+DECLHIDDEN(void)    rtR0MemEfTerm(void);
+# endif
+#endif
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/internal/memobj.h b/ubuntu/vbox/include/internal/memobj.h
new file mode 100644 (file)
index 0000000..919c0f6
--- /dev/null
@@ -0,0 +1,483 @@
+/* $Id: memobj.h $ */
+/** @file
+ * IPRT - Ring-0 Memory Objects.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___internal_memobj_h
+#define ___internal_memobj_h
+
+#include <iprt/memobj.h>
+#include <iprt/assert.h>
+#include "internal/magics.h"
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_memobj_int Internals.
+ * @ingroup grp_rt_memobj
+ * @internal
+ * @{
+ */
+
+/**
+ * Ring-0 memory object type.
+ */
+typedef enum RTR0MEMOBJTYPE
+{
+    /** The traditional invalid value. */
+    RTR0MEMOBJTYPE_INVALID = 0,
+
+    /** @name Primary types (parents)
+     * @{ */
+    /** RTR0MemObjAllocPage.
+     * This memory is page aligned and fixed. */
+    RTR0MEMOBJTYPE_PAGE,
+    /** RTR0MemObjAllocLow.
+     * This memory is page aligned, fixed and is backed by physical memory below 4GB. */
+    RTR0MEMOBJTYPE_LOW,
+    /** RTR0MemObjAllocCont.
+     * This memory is page aligned, fixed and is backed by contiguous physical memory below 4GB. */
+    RTR0MEMOBJTYPE_CONT,
+    /** RTR0MemObjLockKernel, RTR0MemObjLockUser.
+     * This memory is page aligned and fixed. It was locked/pinned/wired down by the API call. */
+    RTR0MEMOBJTYPE_LOCK,
+    /** RTR0MemObjAllocPhys, RTR0MemObjEnterPhys.
+     * This memory is physical memory, page aligned, contiguous and doesn't need to have a mapping. */
+    RTR0MEMOBJTYPE_PHYS,
+    /** RTR0MemObjAllocPhysNC.
+     * This memory is physical memory, page aligned and doesn't need to have a mapping. */
+    RTR0MEMOBJTYPE_PHYS_NC,
+    /** RTR0MemObjReserveKernel, RTR0MemObjReserveUser.
+     * This memory is page aligned and has no backing. */
+    RTR0MEMOBJTYPE_RES_VIRT,
+    /** @} */
+
+    /** @name Secondary types (children)
+     * @{
+     */
+    /** RTR0MemObjMapUser, RTR0MemObjMapKernel.
+     * This is a user or kernel context mapping of another ring-0 memory object. */
+    RTR0MEMOBJTYPE_MAPPING,
+    /** @} */
+
+    /** The end of the valid types. Used for sanity checking. */
+    RTR0MEMOBJTYPE_END
+} RTR0MEMOBJTYPE;
+
+
+/** @name RTR0MEMOBJINTERNAL::fFlags
+ * @{ */
+/** Page level protection was changed. */
+#define RTR0MEMOBJ_FLAGS_PROT_CHANGED       RT_BIT_32(0)
+/** @} */
+
+
+typedef struct RTR0MEMOBJINTERNAL *PRTR0MEMOBJINTERNAL;
+typedef struct RTR0MEMOBJINTERNAL **PPRTR0MEMOBJINTERNAL;
+
+/**
+ * Ring-0 memory object.
+ *
+ * When using the PRTR0MEMOBJINTERNAL and PPRTR0MEMOBJINTERNAL types
+ * we get pMem and ppMem variable names.
+ *
+ * When using the RTR0MEMOBJ and PRTR0MEMOBJ types we get MemObj and
+ * pMemObj variable names. We never dereference variables of the RTR0MEMOBJ
+ * type, we always convert it to a PRTR0MEMOBJECTINTERNAL variable first.
+ */
+typedef struct RTR0MEMOBJINTERNAL
+{
+    /** Magic number (RTR0MEMOBJ_MAGIC). */
+    uint32_t        u32Magic;
+    /** The size of this structure. */
+    uint32_t        cbSelf;
+    /** The type of allocation. */
+    RTR0MEMOBJTYPE  enmType;
+    /** Flags, RTR0MEMOBJ_FLAGS_*. */
+    uint32_t        fFlags;
+    /** The size of the memory allocated, pinned down, or mapped. */
+    size_t          cb;
+    /** The memory address.
+     * What this really is varies with the type.
+     * For PAGE, CONT, LOW, RES_VIRT/R0, LOCK/R0 and MAP/R0 it's the ring-0 mapping.
+     * For LOCK/R3, RES_VIRT/R3 and MAP/R3 it is the ring-3 mapping.
+     * For PHYS this might actually be NULL if there isn't any mapping.
+     */
+    void           *pv;
+
+    /** Object relations. */
+    union
+    {
+        /** This is for tracking child memory handles mapping the
+         * memory described by the primary handle. */
+        struct
+        {
+            /** Number of mappings. */
+            uint32_t                cMappingsAllocated;
+            /** Number of mappings in the array. */
+            uint32_t                cMappings;
+            /** Pointers to child handles mapping this memory. */
+            PPRTR0MEMOBJINTERNAL    papMappings;
+        } Parent;
+
+        /** Pointer to the primary handle. */
+        struct
+        {
+            /** Pointer to the parent. */
+            PRTR0MEMOBJINTERNAL     pParent;
+        } Child;
+    } uRel;
+
+    /** Type specific data for the memory types that requires that. */
+    union
+    {
+        /** RTR0MEMTYPE_PAGE. */
+        struct
+        {
+            unsigned iDummy;
+        } Page;
+
+        /** RTR0MEMTYPE_LOW. */
+        struct
+        {
+            unsigned iDummy;
+        } Low;
+
+        /** RTR0MEMTYPE_CONT. */
+        struct
+        {
+            /** The physical address of the first page. */
+            RTHCPHYS    Phys;
+        } Cont;
+
+        /** RTR0MEMTYPE_LOCK_USER. */
+        struct
+        {
+            /** The process that owns the locked memory.
+             * This is NIL_RTR0PROCESS if it's kernel memory. */
+            RTR0PROCESS R0Process;
+        } Lock;
+
+        /** RTR0MEMTYPE_PHYS. */
+        struct
+        {
+            /** The base address of the physical memory. */
+            RTHCPHYS    PhysBase;
+            /** If set this object was created by RTR0MemPhysAlloc, otherwise it was
+             * created by RTR0MemPhysEnter. */
+            bool        fAllocated;
+            /** See RTMEM_CACHE_POLICY_XXX constants */
+            uint32_t    uCachePolicy;
+        } Phys;
+
+        /** RTR0MEMTYPE_PHYS_NC. */
+        struct
+        {
+            unsigned iDummy;
+        } PhysNC;
+
+        /** RTR0MEMOBJTYPE_RES_VIRT */
+        struct
+        {
+            /** The process that owns the reserved memory.
+             * This is NIL_RTR0PROCESS if it's kernel memory. */
+            RTR0PROCESS R0Process;
+        } ResVirt;
+
+        /** RTR0MEMOBJTYPE_MAPPING */
+        struct
+        {
+            /** The process that owns the reserved memory.
+             * This is NIL_RTR0PROCESS if it's kernel memory. */
+            RTR0PROCESS R0Process;
+        } Mapping;
+    } u;
+
+} RTR0MEMOBJINTERNAL;
+
+
+/**
+ * Checks if this is mapping or not.
+ *
+ * @returns true if it's a mapping, otherwise false.
+ * @param   pMem        The ring-0 memory object handle.
+ * @see RTR0MemObjIsMapping
+ */
+DECLINLINE(bool) rtR0MemObjIsMapping(PRTR0MEMOBJINTERNAL pMem)
+{
+    switch (pMem->enmType)
+    {
+        case RTR0MEMOBJTYPE_MAPPING:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+
+/**
+ * Checks page level protection can be changed on this object.
+ *
+ * @returns true / false.
+ * @param   pMem        The ring-0 memory object handle.
+ */
+DECLINLINE(bool) rtR0MemObjIsProtectable(PRTR0MEMOBJINTERNAL pMem)
+{
+    switch (pMem->enmType)
+    {
+        case RTR0MEMOBJTYPE_MAPPING:
+        case RTR0MEMOBJTYPE_PAGE:
+        case RTR0MEMOBJTYPE_LOW:
+        case RTR0MEMOBJTYPE_CONT:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+
+/**
+ * Checks if RTR0MEMOBJ::pv is a ring-3 pointer or not.
+ *
+ * @returns true if it's a object with a ring-3 address, otherwise false.
+ * @param   pMem        The ring-0 memory object handle.
+ */
+DECLINLINE(bool) rtR0MemObjIsRing3(PRTR0MEMOBJINTERNAL pMem)
+{
+    switch (pMem->enmType)
+    {
+        case RTR0MEMOBJTYPE_RES_VIRT:
+            return pMem->u.ResVirt.R0Process != NIL_RTR0PROCESS;
+        case RTR0MEMOBJTYPE_LOCK:
+            return pMem->u.Lock.R0Process    != NIL_RTR0PROCESS;
+        case RTR0MEMOBJTYPE_MAPPING:
+            return pMem->u.Mapping.R0Process != NIL_RTR0PROCESS;
+        default:
+            return false;
+    }
+}
+
+
+/**
+ * Frees the memory object (but not the handle).
+ * Any OS specific handle resources will be freed by this call.
+ *
+ * @returns IPRT status code. On failure it is assumed that the object remains valid.
+ * @param   pMem        The ring-0 memory object handle to the memory which should be freed.
+ */
+DECLHIDDEN(int) rtR0MemObjNativeFree(PRTR0MEMOBJINTERNAL pMem);
+
+/**
+ * Allocates page aligned virtual kernel memory.
+ *
+ * The memory is taken from a non paged (= fixed physical memory backing) pool.
+ *
+ * @returns IPRT status code.
+ * @param   ppMem           Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate, page aligned.
+ * @param   fExecutable     Flag indicating whether it should be permitted to executed code in the memory object.
+ */
+DECLHIDDEN(int) rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable);
+
+/**
+ * Allocates page aligned virtual kernel memory with physical backing below 4GB.
+ *
+ * The physical memory backing the allocation is fixed.
+ *
+ * @returns IPRT status code.
+ * @param   ppMem           Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate, page aligned.
+ * @param   fExecutable     Flag indicating whether it should be permitted to executed code in the memory object.
+ */
+DECLHIDDEN(int) rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable);
+
+/**
+ * Allocates page aligned virtual kernel memory with contiguous physical backing below 4GB.
+ *
+ * The physical memory backing the allocation is fixed.
+ *
+ * @returns IPRT status code.
+ * @param   ppMem           Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate, page aligned.
+ * @param   fExecutable     Flag indicating whether it should be permitted to executed code in the memory object.
+ */
+DECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable);
+
+/**
+ * Locks a range of user virtual memory.
+ *
+ * @returns IPRT status code.
+ * @param   ppMem           Where to store the ring-0 memory object handle.
+ * @param   R3Ptr           User virtual address, page aligned.
+ * @param   cb              Number of bytes to lock, page aligned.
+ * @param   fAccess         The desired access, a combination of RTMEM_PROT_READ
+ *                          and RTMEM_PROT_WRITE.
+ * @param   R0Process       The process to lock pages in.
+ */
+DECLHIDDEN(int) rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process);
+
+/**
+ * Locks a range of kernel virtual memory.
+ *
+ * @returns IPRT status code.
+ * @param   ppMem           Where to store the ring-0 memory object handle.
+ * @param   pv              Kernel virtual address, page aligned.
+ * @param   cb              Number of bytes to lock, page aligned.
+ * @param   fAccess         The desired access, a combination of RTMEM_PROT_READ
+ *                          and RTMEM_PROT_WRITE.
+ */
+DECLHIDDEN(int) rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess);
+
+/**
+ * Allocates contiguous page aligned physical memory without (necessarily) any
+ * kernel mapping.
+ *
+ * @returns IPRT status code.
+ * @param   ppMem           Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate, page aligned.
+ * @param   PhysHighest     The highest permitable address (inclusive).
+ *                          NIL_RTHCPHYS if any address is acceptable.
+ * @param   uAlignment      The alignment of the reserved memory.
+ *                          Supported values are PAGE_SIZE, _2M, _4M and _1G.
+ */
+DECLHIDDEN(int) rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment);
+
+/**
+ * Allocates non-contiguous page aligned physical memory without (necessarily) any kernel mapping.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NOT_SUPPORTED if it's not possible to allocated unmapped
+ *          physical memory on this platform.
+ * @param   ppMem           Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate, page aligned.
+ * @param   PhysHighest     The highest permitable address (inclusive).
+ *                          NIL_RTHCPHYS if any address is acceptable.
+ */
+DECLHIDDEN(int) rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest);
+
+/**
+ * Creates a page aligned, contiguous, physical memory object.
+ *
+ * @returns IPRT status code.
+ * @param   ppMem           Where to store the ring-0 memory object handle.
+ * @param   Phys            The physical address to start at, page aligned.
+ * @param   cb              The size of the object in bytes, page aligned.
+ * @param   uCachePolicy    One of the RTMEM_CACHE_XXX modes.
+ */
+DECLHIDDEN(int) rtR0MemObjNativeEnterPhys(PPRTR0MEMOBJINTERNAL ppMem, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy);
+
+/**
+ * Reserves kernel virtual address space.
+ *
+ * @returns IPRT status code.
+ *          Return VERR_NOT_SUPPORTED to indicate that the user should employ fallback strategies.
+ * @param   ppMem           Where to store the ring-0 memory object handle.
+ * @param   pvFixed         Requested address. (void *)-1 means any address. This matches uAlignment if specified.
+ * @param   cb              The number of bytes to reserve, page aligned.
+ * @param   uAlignment      The alignment of the reserved memory; PAGE_SIZE, _2M or _4M.
+ */
+DECLHIDDEN(int) rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment);
+
+/**
+ * Reserves user virtual address space in the current process.
+ *
+ * @returns IPRT status code.
+ * @param   ppMem           Where to store the ring-0 memory object handle.
+ * @param   R3PtrFixed      Requested address. (RTR3PTR)-1 means any address. This matches uAlignment if specified.
+ * @param   cb              The number of bytes to reserve, page aligned.
+ * @param   uAlignment      The alignment of the reserved memory; PAGE_SIZE, _2M or _4M.
+ * @param   R0Process       The process to reserve the memory in.
+ */
+DECLHIDDEN(int) rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process);
+
+/**
+ * Maps a memory object into user virtual address space in the current process.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NOT_SUPPORTED see RTR0MemObjMapKernelEx.
+ *
+ * @param   ppMem           Where to store the ring-0 memory object handle of the mapping object.
+ * @param   pMemToMap       The object to be map.
+ * @param   pvFixed         Requested address. (void *)-1 means any address. This matches uAlignment if specified.
+ * @param   uAlignment      The alignment of the reserved memory; PAGE_SIZE, _2M or _4M.
+ * @param   fProt           Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE).
+ * @param   offSub          Where in the object to start mapping. If non-zero
+ *                          the value must be page aligned and cbSub must be
+ *                          non-zero as well.
+ * @param   cbSub           The size of the part of the object to be mapped. If
+ *                          zero the entire object is mapped. The value must be
+ *                          page aligned.
+ */
+DECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment,
+                                          unsigned fProt, size_t offSub, size_t cbSub);
+
+/**
+ * Maps a memory object into user virtual address space in the current process.
+ *
+ * @returns IPRT status code.
+ * @param   ppMem           Where to store the ring-0 memory object handle of the mapping object.
+ * @param   pMemToMap       The object to be map.
+ * @param   R3PtrFixed      Requested address. (RTR3PTR)-1 means any address. This matches uAlignment if specified.
+ * @param   uAlignment      The alignment of the reserved memory; PAGE_SIZE, _2M or _4M.
+ * @param   fProt           Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE).
+ * @param   R0Process       The process to map the memory into.
+ */
+DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, PRTR0MEMOBJINTERNAL pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process);
+
+/**
+ * Change the page level protection of one or more pages in a memory object.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NOT_SUPPORTED see RTR0MemObjProtect.
+ *
+ * @param   pMem            The memory object.
+ * @param   offSub          Offset into the memory object. Page aligned.
+ * @param   cbSub           Number of bytes to change the protection of. Page
+ *                          aligned.
+ * @param   fProt           Combination of RTMEM_PROT_* flags.
+ */
+DECLHIDDEN(int) rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt);
+
+/**
+ * Get the physical address of an page in the memory object.
+ *
+ * @returns The physical address.
+ * @returns NIL_RTHCPHYS if the object doesn't contain fixed physical pages.
+ * @returns NIL_RTHCPHYS if the iPage is out of range.
+ * @returns NIL_RTHCPHYS if the object handle isn't valid.
+ * @param   pMem            The ring-0 memory object handle.
+ * @param   iPage           The page number within the object (valid).
+ */
+DECLHIDDEN(RTHCPHYS) rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, size_t iPage);
+
+DECLHIDDEN(PRTR0MEMOBJINTERNAL) rtR0MemObjNew(size_t cbSelf, RTR0MEMOBJTYPE enmType, void *pv, size_t cb);
+DECLHIDDEN(void) rtR0MemObjDelete(PRTR0MEMOBJINTERNAL pMem);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/internal/process.h b/ubuntu/vbox/include/internal/process.h
new file mode 100644 (file)
index 0000000..abe4b5c
--- /dev/null
@@ -0,0 +1,69 @@
+/* $Id: process.h $ */
+/** @file
+ * IPRT - Internal RTProc header.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___internal_process_h
+#define ___internal_process_h
+
+#include <iprt/process.h>
+#include <iprt/param.h>
+
+RT_C_DECLS_BEGIN
+
+extern DECLHIDDEN(RTPROCESS)        g_ProcessSelf;
+extern DECLHIDDEN(RTPROCPRIORITY)   g_enmProcessPriority;
+extern DECLHIDDEN(char)             g_szrtProcExePath[RTPATH_MAX];
+extern DECLHIDDEN(size_t)           g_cchrtProcExePath;
+extern DECLHIDDEN(size_t)           g_cchrtProcDir;
+extern DECLHIDDEN(size_t)           g_offrtProcName;
+extern DECLHIDDEN(bool volatile)    g_frtAtExitCalled;
+
+/**
+ * Validates and sets the process priority.
+ * This will check that all rtThreadNativeSetPriority() will success for all the
+ * thread types when applied to the current thread.
+ *
+ * @returns iprt status code.
+ * @param   enmPriority     The priority to validate and set.
+ * @remark  Located in sched.
+ */
+DECLHIDDEN(int) rtProcNativeSetPriority(RTPROCPRIORITY enmPriority);
+
+/**
+ * Determines the full path to the executable image.
+ *
+ * This is called by rtR3Init.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   pszPath     Pointer to the g_szrtProcExePath buffer.
+ * @param   cchPath     The size of the buffer.
+ */
+DECLHIDDEN(int) rtProcInitExePath(char *pszPath, size_t cchPath);
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/internal/sched.h b/ubuntu/vbox/include/internal/sched.h
new file mode 100644 (file)
index 0000000..5191605
--- /dev/null
@@ -0,0 +1,47 @@
+/* $Id: sched.h $ */
+/** @file
+ * IPRT - Internal RTSched header.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___internal_sched_h
+#define ___internal_sched_h
+
+#include <iprt/thread.h>
+#include "internal/process.h"
+#include "internal/thread.h"
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Calculate the scheduling properties for all the threads in the default
+ * process priority, assuming the current thread have the type enmType.
+ *
+ * @returns iprt status code.
+ * @param   enmType     The thread type to be assumed for the current thread.
+ */
+DECLHIDDEN(int) rtSchedNativeCalcDefaultPriority(RTTHREADTYPE enmType);
+
+RT_C_DECLS_END
+
+#endif
diff --git a/ubuntu/vbox/include/internal/string.h b/ubuntu/vbox/include/internal/string.h
new file mode 100644 (file)
index 0000000..933a5d4
--- /dev/null
@@ -0,0 +1,102 @@
+/* $Id: string.h $ */
+/** @file
+ * IPRT - Internal RTStr header.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___internal_string_h
+#define ___internal_string_h
+
+#include <iprt/string.h>
+
+RT_C_DECLS_BEGIN
+
+/** @def RTSTR_STRICT
+ * Enables strict assertions on bad string encodings.
+ */
+#ifdef DOXYGEN_RUNNING
+# define RTSTR_STRICT
+#endif
+/*#define RTSTR_STRICT*/
+
+#ifdef RTSTR_STRICT
+# define RTStrAssertMsgFailed(msg)              AssertMsgFailed(msg)
+# define RTStrAssertMsgReturn(expr, msg, rc)    AssertMsgReturn(expr, msg, rc)
+#else
+# define RTStrAssertMsgFailed(msg)              do { } while (0)
+# define RTStrAssertMsgReturn(expr, msg, rc)    do { if (!(expr)) return rc; } while (0)
+#endif
+
+DECLHIDDEN(size_t) rtstrFormatRt(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, const char **ppszFormat, va_list *pArgs,
+                                 int cchWidth, int cchPrecision, unsigned fFlags, char chArgSize);
+DECLHIDDEN(size_t) rtstrFormatType(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, const char **ppszFormat, va_list *pArgs,
+                                   int cchWidth, int cchPrecision, unsigned fFlags, char chArgSize);
+
+/**
+ * Format kernel address into @a pszBuf.
+ *
+ * @returns Number of bytes returned.
+ * @param   pszBuf          The return buffer.
+ * @param   cbBuf           The buffer size.
+ * @param   uPtr            The ring-0 pointer value.
+ * @param   cchWidth        The specified width, -1 if not given.
+ * @param   cchPrecision    The specified precision.
+ * @param   fFlags          Format flags, RTSTR_F_XXX.
+ */
+DECLHIDDEN(size_t) rtStrFormatKernelAddress(char *pszBuf, size_t cbBuf, RTR0INTPTR uPtr, signed int cchWidth,
+                                            signed int cchPrecision, unsigned int fFlags);
+
+#ifdef RT_WITH_ICONV_CACHE
+DECLHIDDEN(void) rtStrIconvCacheInit(struct RTTHREADINT *pThread);
+DECLHIDDEN(void) rtStrIconvCacheDestroy(struct RTTHREADINT *pThread);
+#endif
+
+/**
+ * Indexes into RTTHREADINT::ahIconvs
+ */
+typedef enum RTSTRICONV
+{
+    /** UTF-8 to the locale codeset (LC_CTYPE). */
+    RTSTRICONV_UTF8_TO_LOCALE = 0,
+    /** The locale codeset (LC_CTYPE) to UTF-8. */
+    RTSTRICONV_LOCALE_TO_UTF8,
+    /** UTF-8 to the filesystem codeset - if different from the locale codeset. */
+    RTSTRICONV_UTF8_TO_FS,
+    /** The filesystem codeset to UTF-8. */
+    RTSTRICONV_FS_TO_UTF8,
+    /** The end of the valid indexes. */
+    RTSTRICONV_END
+} RTSTRICONV;
+
+DECLHIDDEN(int) rtStrConvert(const char *pchInput, size_t cchInput, const char *pszInputCS,
+                             char **ppszOutput, size_t cbOutput, const char *pszOutputCS,
+                             unsigned cFactor, RTSTRICONV enmCacheIdx);
+DECLHIDDEN(const char *) rtStrGetLocaleCodeset(void);
+DECLHIDDEN(int) rtUtf8Length(const char *psz, size_t cch, size_t *pcuc, size_t *pcchActual);
+
+DECLHIDDEN(int) rtStrToIpAddr6Str(const char *psz, char *pszAddrOut, size_t addrOutSize, char *pszPortOut, size_t portOutSize, bool followRfc);
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/internal/thread.h b/ubuntu/vbox/include/internal/thread.h
new file mode 100644 (file)
index 0000000..54dc78a
--- /dev/null
@@ -0,0 +1,275 @@
+/* $Id: thread.h $ */
+/** @file
+ * IPRT - Internal RTThread header.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___thread_h
+#define ___thread_h
+
+#include <iprt/types.h>
+#include <iprt/thread.h>
+#include <iprt/avl.h>
+#ifdef IN_RING3
+# include <iprt/process.h>
+# include <iprt/critsect.h>
+#endif
+#include "internal/lockvalidator.h"
+#include "internal/magics.h"
+#ifdef RT_WITH_ICONV_CACHE
+# include "internal/string.h"
+#endif
+
+RT_C_DECLS_BEGIN
+
+
+/** Max thread name length. */
+#define RTTHREAD_NAME_LEN       16
+#ifdef IPRT_WITH_GENERIC_TLS
+/** The number of TLS entries for the generic implementation. */
+# define RTTHREAD_TLS_ENTRIES   64
+#endif
+
+/**
+ * Internal representation of a thread.
+ */
+typedef struct RTTHREADINT
+{
+    /** Avl node core - the key is the native thread id. */
+    AVLPVNODECORE           Core;
+    /** Magic value (RTTHREADINT_MAGIC). */
+    uint32_t                u32Magic;
+    /** Reference counter. */
+    uint32_t volatile       cRefs;
+    /** The current thread state. */
+    RTTHREADSTATE volatile  enmState;
+    /** Set when really sleeping. */
+    bool volatile           fReallySleeping;
+#if defined(RT_OS_WINDOWS) && defined(IN_RING3)
+    /** The thread handle
+     * This is not valid until the create function has returned! */
+    uintptr_t               hThread;
+#endif
+#if defined(RT_OS_LINUX) && defined(IN_RING3)
+    /** The thread ID.
+     * This is not valid before rtThreadMain has been called by the new thread.  */
+    pid_t                   tid;
+#endif
+#if defined(RT_OS_SOLARIS) && defined(IN_RING0)
+    /** Debug thread ID needed for thread_join. */
+    uint64_t                tid;
+#endif
+    /** The user event semaphore. */
+    RTSEMEVENTMULTI         EventUser;
+    /** The terminated event semaphore. */
+    RTSEMEVENTMULTI         EventTerminated;
+    /** The thread type. */
+    RTTHREADTYPE            enmType;
+    /** The thread creation flags. (RTTHREADFLAGS) */
+    unsigned                fFlags;
+    /** Internal flags. (RTTHREADINT_FLAGS_ *) */
+    uint32_t                fIntFlags;
+    /** The result code. */
+    int                     rc;
+    /** Thread function. */
+    PFNRTTHREAD             pfnThread;
+    /** Thread function argument. */
+    void                   *pvUser;
+    /** Actual stack size. */
+    size_t                  cbStack;
+#ifdef IN_RING3
+    /** The lock validator data. */
+    RTLOCKVALPERTHREAD      LockValidator;
+#endif /* IN_RING3 */
+#ifdef RT_WITH_ICONV_CACHE
+    /** Handle cache for iconv.
+     * @remarks ASSUMES sizeof(void *) >= sizeof(iconv_t). */
+    void *ahIconvs[RTSTRICONV_END];
+#endif
+#ifdef IPRT_WITH_GENERIC_TLS
+    /** The TLS entries for this thread. */
+    void                   *apvTlsEntries[RTTHREAD_TLS_ENTRIES];
+#endif
+    /** Thread name. */
+    char                    szName[RTTHREAD_NAME_LEN];
+} RTTHREADINT;
+/** Pointer to the internal representation of a thread. */
+typedef RTTHREADINT *PRTTHREADINT;
+
+
+/** @name RTTHREADINT::fIntFlags Masks and Bits.
+ * @{ */
+/** Set if the thread is an alien thread.
+ * Clear if the thread was created by IPRT. */
+#define RTTHREADINT_FLAGS_ALIEN      RT_BIT(0)
+/** Set if the thread has terminated.
+ * Clear if the thread is running. */
+#define RTTHREADINT_FLAGS_TERMINATED RT_BIT(1)
+/** This bit is set if the thread is in the AVL tree. */
+#define RTTHREADINT_FLAG_IN_TREE_BIT 2
+/** @copydoc RTTHREADINT_FLAG_IN_TREE_BIT */
+#define RTTHREADINT_FLAG_IN_TREE     RT_BIT(RTTHREADINT_FLAG_IN_TREE_BIT)
+/** Set if it's the main thread. */
+#define RTTHREADINT_FLAGS_MAIN       RT_BIT(3)
+/** @} */
+
+
+/**
+ * Initialize the native part of the thread management.
+ *
+ * Generally a TLS entry will be allocated at this point (Ring-3).
+ *
+ * @returns iprt status code.
+ */
+DECLHIDDEN(int) rtThreadNativeInit(void);
+
+#ifdef IN_RING3
+/**
+ * Called when IPRT was first initialized in unobtrusive mode and later changed
+ * to obtrustive.
+ *
+ * This is only applicable in ring-3.
+ */
+DECLHIDDEN(void) rtThreadNativeReInitObtrusive(void);
+#endif
+
+/**
+ * Create a native thread.
+ * This creates the thread as described in pThreadInt and stores the thread id in *pThread.
+ *
+ * @returns iprt status code.
+ * @param   pThreadInt      The thread data structure for the thread.
+ * @param   pNativeThread   Where to store the native thread identifier.
+ */
+DECLHIDDEN(int) rtThreadNativeCreate(PRTTHREADINT pThreadInt, PRTNATIVETHREAD pNativeThread);
+
+/**
+ * Adopts a thread, this is called immediately after allocating the
+ * thread structure.
+ *
+ * @param   pThread     Pointer to the thread structure.
+ */
+DECLHIDDEN(int) rtThreadNativeAdopt(PRTTHREADINT pThread);
+
+/**
+ * Called from rtThreadDestroy so that the TLS entry and any native data in the
+ * thread structure can be cleared.
+ *
+ * @param   pThread         The thread structure.
+ */
+DECLHIDDEN(void) rtThreadNativeDestroy(PRTTHREADINT pThread);
+
+#ifdef IN_RING0
+/**
+ * Called from rtThreadWait when the last thread has completed in order to make
+ * sure it's all the way out of IPRT before RTR0Term is called.
+ *
+ * @param   pThread     The thread structure.
+ */
+DECLHIDDEN(void) rtThreadNativeWaitKludge(PRTTHREADINT pThread);
+#endif
+
+
+/**
+ * Sets the priority of the thread according to the thread type
+ * and current process priority.
+ *
+ * The RTTHREADINT::enmType member has not yet been updated and will be updated by
+ * the caller on a successful return.
+ *
+ * @returns iprt status code.
+ * @param   pThread     The thread in question.
+ * @param   enmType     The thread type.
+ * @remark  Located in sched.
+ */
+DECLHIDDEN(int) rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType);
+
+#ifdef IN_RING3
+# ifdef RT_OS_WINDOWS
+/**
+ * Callback for when a native thread is detaching.
+ *
+ * It give the Win32/64 backend a chance to terminate alien
+ * threads properly.
+ */
+DECLHIDDEN(void) rtThreadNativeDetach(void);
+
+/**
+ * Internal function for informing the debugger about a thread.
+ * @param   pThread     The thread. May differ from the calling thread.
+ */
+DECLHIDDEN(void) rtThreadNativeInformDebugger(PRTTHREADINT pThread);
+# endif
+#endif /* IN_RING3 */
+
+
+/* thread.cpp */
+DECLCALLBACK(DECLHIDDEN(int)) rtThreadMain(PRTTHREADINT pThread, RTNATIVETHREAD NativeThread, const char *pszThreadName);
+DECLHIDDEN(uint32_t)     rtThreadRelease(PRTTHREADINT pThread);
+DECLHIDDEN(void)         rtThreadTerminate(PRTTHREADINT pThread, int rc);
+DECLHIDDEN(PRTTHREADINT) rtThreadGetByNative(RTNATIVETHREAD NativeThread);
+DECLHIDDEN(PRTTHREADINT) rtThreadGet(RTTHREAD Thread);
+DECLHIDDEN(int)          rtThreadInit(void);
+#ifdef IN_RING3
+DECLHIDDEN(void)         rtThreadReInitObtrusive(void);
+#endif
+DECLHIDDEN(void)         rtThreadTerm(void);
+DECLHIDDEN(void)         rtThreadInsert(PRTTHREADINT pThread, RTNATIVETHREAD NativeThread);
+#ifdef IN_RING3
+DECLHIDDEN(int)          rtThreadDoSetProcPriority(RTPROCPRIORITY enmPriority);
+#endif /* !IN_RING0 */
+#ifdef IPRT_WITH_GENERIC_TLS
+DECLHIDDEN(void)         rtThreadClearTlsEntry(RTTLS iTls);
+DECLHIDDEN(void)         rtThreadTlsDestruction(PRTTHREADINT pThread); /* in tls-generic.cpp */
+#endif
+
+#ifdef ___iprt_asm_h
+
+/**
+ * Gets the thread state.
+ *
+ * @returns The thread state.
+ * @param   pThread             The thread.
+ */
+DECLINLINE(RTTHREADSTATE) rtThreadGetState(PRTTHREADINT pThread)
+{
+    return pThread->enmState;
+}
+
+/**
+ * Sets the thread state.
+ *
+ * @param   pThread             The thread.
+ * @param   enmNewState         The new thread state.
+ */
+DECLINLINE(void) rtThreadSetState(PRTTHREADINT pThread, RTTHREADSTATE enmNewState)
+{
+    AssertCompile(sizeof(pThread->enmState) == sizeof(uint32_t));
+    ASMAtomicWriteU32((uint32_t volatile *)&pThread->enmState, enmNewState);
+}
+
+#endif
+
+RT_C_DECLS_END
+
+#endif
diff --git a/ubuntu/vbox/include/internal/time.h b/ubuntu/vbox/include/internal/time.h
new file mode 100644 (file)
index 0000000..3f59825
--- /dev/null
@@ -0,0 +1,44 @@
+/* $Id: time.h $ */
+/** @file
+ * IPRT - Internal RTTime header
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___internal_time_h
+#define ___internal_time_h
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+#if defined(IN_RING3) || defined(IN_RC)
+
+extern DECLHIDDEN(uint64_t) g_u64ProgramStartNanoTS;
+extern DECLHIDDEN(uint64_t) g_u64ProgramStartMicroTS;
+extern DECLHIDDEN(uint64_t) g_u64ProgramStartMilliTS;
+
+#endif
+
+RT_C_DECLS_END
+
+#endif
diff --git a/ubuntu/vbox/include/iprt/alloc.h b/ubuntu/vbox/include/iprt/alloc.h
new file mode 100644 (file)
index 0000000..022f71e
--- /dev/null
@@ -0,0 +1,33 @@
+/** @file
+ * IPRT - Memory Allocation.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_alloc_h
+#define ___iprt_alloc_h
+
+/* Forwarding to the canonical header. */
+#include <iprt/mem.h>
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/alloca.h b/ubuntu/vbox/include/iprt/alloca.h
new file mode 100644 (file)
index 0000000..5d46326
--- /dev/null
@@ -0,0 +1,60 @@
+/** @file
+ * IPRT - alloca().
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_alloca_h
+#define ___iprt_alloca_h
+
+#if defined(IN_RC) || defined(IN_RING0_AGNOSTIC)
+# error "No alloca() in raw-mode and agnostic ring-0 context as it may have external dependencies like libgcc."
+#endif
+
+/*
+ * If there are more difficult platforms out there, we'll do OS
+ * specific #ifdefs. But for now we'll just include the headers
+ * which normally contains the alloca() prototype.
+ * When we're in kernel territory it starts getting a bit more
+ * interesting of course...
+ */
+#if defined(IN_RING0) \
+ && (   defined(RT_OS_DARWIN) \
+     || defined(RT_OS_FREEBSD) \
+     || defined(RT_OS_LINUX) \
+     || defined(RT_OS_NETBSD) \
+     || defined(RT_OS_SOLARIS))
+/* ASSUMES GNU C */
+# define alloca(cb) __builtin_alloca(cb)
+
+#else
+# include <stdlib.h>
+# if !defined(RT_OS_DARWIN) && !defined(RT_OS_FREEBSD) && !defined(RT_OS_NETBSD)
+#  include <malloc.h>
+# endif
+# if defined(RT_OS_SOLARIS) || defined(RT_OS_LINUX)
+#  include <alloca.h>
+# endif
+#endif
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/asm-amd64-x86.h b/ubuntu/vbox/include/iprt/asm-amd64-x86.h
new file mode 100644 (file)
index 0000000..452a3e3
--- /dev/null
@@ -0,0 +1,3362 @@
+/** @file
+ * IPRT - AMD64 and x86 Specific Assembly Functions.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_asm_amd64_x86_h
+#define ___iprt_asm_amd64_x86_h
+
+#include <iprt/types.h>
+#include <iprt/assert.h>
+#if !defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86)
+# error "Not on AMD64 or x86"
+#endif
+
+#if defined(_MSC_VER) && RT_INLINE_ASM_USES_INTRIN
+# pragma warning(push)
+# pragma warning(disable:4668) /* Several incorrect __cplusplus uses. */
+# pragma warning(disable:4255) /* Incorrect __slwpcb prototype. */
+# include <intrin.h>
+# pragma warning(pop)
+   /* Emit the intrinsics at all optimization levels. */
+# pragma intrinsic(_ReadWriteBarrier)
+# pragma intrinsic(__cpuid)
+# pragma intrinsic(_enable)
+# pragma intrinsic(_disable)
+# pragma intrinsic(__rdtsc)
+# pragma intrinsic(__readmsr)
+# pragma intrinsic(__writemsr)
+# pragma intrinsic(__outbyte)
+# pragma intrinsic(__outbytestring)
+# pragma intrinsic(__outword)
+# pragma intrinsic(__outwordstring)
+# pragma intrinsic(__outdword)
+# pragma intrinsic(__outdwordstring)
+# pragma intrinsic(__inbyte)
+# pragma intrinsic(__inbytestring)
+# pragma intrinsic(__inword)
+# pragma intrinsic(__inwordstring)
+# pragma intrinsic(__indword)
+# pragma intrinsic(__indwordstring)
+# pragma intrinsic(__invlpg)
+# pragma intrinsic(__wbinvd)
+# pragma intrinsic(__readcr0)
+# pragma intrinsic(__readcr2)
+# pragma intrinsic(__readcr3)
+# pragma intrinsic(__readcr4)
+# pragma intrinsic(__writecr0)
+# pragma intrinsic(__writecr3)
+# pragma intrinsic(__writecr4)
+# pragma intrinsic(__readdr)
+# pragma intrinsic(__writedr)
+# ifdef RT_ARCH_AMD64
+#  pragma intrinsic(__readcr8)
+#  pragma intrinsic(__writecr8)
+# endif
+# if RT_INLINE_ASM_USES_INTRIN >= 14
+#  pragma intrinsic(__halt)
+# endif
+# if RT_INLINE_ASM_USES_INTRIN >= 15
+#  pragma intrinsic(__readeflags)
+#  pragma intrinsic(__writeeflags)
+#  pragma intrinsic(__rdtscp)
+# endif
+#endif
+
+
+/*
+ * Include #pragma aux definitions for Watcom C/C++.
+ */
+#if defined(__WATCOMC__) && ARCH_BITS == 16
+# include "asm-amd64-x86-watcom-16.h"
+#elif defined(__WATCOMC__) && ARCH_BITS == 32
+# include "asm-amd64-x86-watcom-32.h"
+#endif
+
+
+/** @defgroup grp_rt_asm_amd64_x86  AMD64 and x86 Specific ASM Routines
+ * @ingroup grp_rt_asm
+ * @{
+ */
+
+/** @todo find a more proper place for these structures? */
+
+#pragma pack(1)
+/** IDTR */
+typedef struct RTIDTR
+{
+    /** Size of the IDT. */
+    uint16_t    cbIdt;
+    /** Address of the IDT. */
+#if ARCH_BITS != 64
+    uint32_t    pIdt;
+#else
+    uint64_t    pIdt;
+#endif
+} RTIDTR, *PRTIDTR;
+#pragma pack()
+
+#pragma pack(1)
+/** @internal */
+typedef struct RTIDTRALIGNEDINT
+{
+    /** Alignment padding.   */
+    uint16_t    au16Padding[ARCH_BITS == 64 ? 3 : 1];
+    /** The IDTR structure.  */
+    RTIDTR      Idtr;
+} RTIDTRALIGNEDINT;
+#pragma pack()
+
+/** Wrapped RTIDTR for preventing misalignment exceptions. */
+typedef union RTIDTRALIGNED
+{
+    /** Try make sure this structure has optimal alignment. */
+    uint64_t            auAlignmentHack[ARCH_BITS == 64 ? 2 : 1];
+    /** Aligned structure. */
+    RTIDTRALIGNEDINT    s;
+} RTIDTRALIGNED;
+AssertCompileSize(RTIDTRALIGNED, ((ARCH_BITS == 64) + 1) * 8);
+/** Pointer to a an RTIDTR alignment wrapper. */
+typedef RTIDTRALIGNED *PRIDTRALIGNED;
+
+
+#pragma pack(1)
+/** GDTR */
+typedef struct RTGDTR
+{
+    /** Size of the GDT. */
+    uint16_t    cbGdt;
+    /** Address of the GDT. */
+#if ARCH_BITS != 64
+    uint32_t    pGdt;
+#else
+    uint64_t    pGdt;
+#endif
+} RTGDTR, *PRTGDTR;
+#pragma pack()
+
+#pragma pack(1)
+/** @internal */
+typedef struct RTGDTRALIGNEDINT
+{
+    /** Alignment padding.   */
+    uint16_t    au16Padding[ARCH_BITS == 64 ? 3 : 1];
+    /** The GDTR structure.  */
+    RTGDTR      Gdtr;
+} RTGDTRALIGNEDINT;
+#pragma pack()
+
+/** Wrapped RTGDTR for preventing misalignment exceptions. */
+typedef union RTGDTRALIGNED
+{
+    /** Try make sure this structure has optimal alignment. */
+    uint64_t            auAlignmentHack[ARCH_BITS == 64 ? 2 : 1];
+    /** Aligned structure. */
+    RTGDTRALIGNEDINT    s;
+} RTGDTRALIGNED;
+AssertCompileSize(RTIDTRALIGNED, ((ARCH_BITS == 64) + 1) * 8);
+/** Pointer to a an RTGDTR alignment wrapper. */
+typedef RTGDTRALIGNED *PRGDTRALIGNED;
+
+
+/**
+ * Gets the content of the IDTR CPU register.
+ * @param   pIdtr   Where to store the IDTR contents.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMGetIDTR(PRTIDTR pIdtr);
+#else
+DECLINLINE(void) ASMGetIDTR(PRTIDTR pIdtr)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("sidt %0" : "=m" (*pIdtr));
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pIdtr]
+        sidt    [rax]
+#  else
+        mov     eax, [pIdtr]
+        sidt    [eax]
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Gets the content of the IDTR.LIMIT CPU register.
+ * @returns IDTR limit.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(uint16_t) ASMGetIdtrLimit(void);
+#else
+DECLINLINE(uint16_t) ASMGetIdtrLimit(void)
+{
+    RTIDTRALIGNED TmpIdtr;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("sidt %0" : "=m" (TmpIdtr.s.Idtr));
+# else
+    __asm
+    {
+        sidt    [TmpIdtr.s.Idtr]
+    }
+# endif
+    return TmpIdtr.s.Idtr.cbIdt;
+}
+#endif
+
+
+/**
+ * Sets the content of the IDTR CPU register.
+ * @param   pIdtr   Where to load the IDTR contents from
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMSetIDTR(const RTIDTR *pIdtr);
+#else
+DECLINLINE(void) ASMSetIDTR(const RTIDTR *pIdtr)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("lidt %0" : : "m" (*pIdtr));
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pIdtr]
+        lidt    [rax]
+#  else
+        mov     eax, [pIdtr]
+        lidt    [eax]
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Gets the content of the GDTR CPU register.
+ * @param   pGdtr   Where to store the GDTR contents.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMGetGDTR(PRTGDTR pGdtr);
+#else
+DECLINLINE(void) ASMGetGDTR(PRTGDTR pGdtr)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("sgdt %0" : "=m" (*pGdtr));
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pGdtr]
+        sgdt    [rax]
+#  else
+        mov     eax, [pGdtr]
+        sgdt    [eax]
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Sets the content of the GDTR CPU register.
+ * @param   pGdtr   Where to load the GDTR contents from
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMSetGDTR(const RTGDTR *pGdtr);
+#else
+DECLINLINE(void) ASMSetGDTR(const RTGDTR *pGdtr)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("lgdt %0" : : "m" (*pGdtr));
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pGdtr]
+        lgdt    [rax]
+#  else
+        mov     eax, [pGdtr]
+        lgdt    [eax]
+#  endif
+    }
+# endif
+}
+#endif
+
+
+
+/**
+ * Get the cs register.
+ * @returns cs.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(RTSEL) ASMGetCS(void);
+#else
+DECLINLINE(RTSEL) ASMGetCS(void)
+{
+    RTSEL SelCS;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("movw  %%cs, %0\n\t" : "=r" (SelCS));
+# else
+    __asm
+    {
+        mov     ax, cs
+        mov     [SelCS], ax
+    }
+# endif
+    return SelCS;
+}
+#endif
+
+
+/**
+ * Get the DS register.
+ * @returns DS.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(RTSEL) ASMGetDS(void);
+#else
+DECLINLINE(RTSEL) ASMGetDS(void)
+{
+    RTSEL SelDS;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("movw  %%ds, %0\n\t" : "=r" (SelDS));
+# else
+    __asm
+    {
+        mov     ax, ds
+        mov     [SelDS], ax
+    }
+# endif
+    return SelDS;
+}
+#endif
+
+
+/**
+ * Get the ES register.
+ * @returns ES.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(RTSEL) ASMGetES(void);
+#else
+DECLINLINE(RTSEL) ASMGetES(void)
+{
+    RTSEL SelES;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("movw  %%es, %0\n\t" : "=r" (SelES));
+# else
+    __asm
+    {
+        mov     ax, es
+        mov     [SelES], ax
+    }
+# endif
+    return SelES;
+}
+#endif
+
+
+/**
+ * Get the FS register.
+ * @returns FS.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(RTSEL) ASMGetFS(void);
+#else
+DECLINLINE(RTSEL) ASMGetFS(void)
+{
+    RTSEL SelFS;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("movw  %%fs, %0\n\t" : "=r" (SelFS));
+# else
+    __asm
+    {
+        mov     ax, fs
+        mov     [SelFS], ax
+    }
+# endif
+    return SelFS;
+}
+# endif
+
+
+/**
+ * Get the GS register.
+ * @returns GS.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(RTSEL) ASMGetGS(void);
+#else
+DECLINLINE(RTSEL) ASMGetGS(void)
+{
+    RTSEL SelGS;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("movw  %%gs, %0\n\t" : "=r" (SelGS));
+# else
+    __asm
+    {
+        mov     ax, gs
+        mov     [SelGS], ax
+    }
+# endif
+    return SelGS;
+}
+#endif
+
+
+/**
+ * Get the SS register.
+ * @returns SS.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(RTSEL) ASMGetSS(void);
+#else
+DECLINLINE(RTSEL) ASMGetSS(void)
+{
+    RTSEL SelSS;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("movw  %%ss, %0\n\t" : "=r" (SelSS));
+# else
+    __asm
+    {
+        mov     ax, ss
+        mov     [SelSS], ax
+    }
+# endif
+    return SelSS;
+}
+#endif
+
+
+/**
+ * Get the TR register.
+ * @returns TR.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(RTSEL) ASMGetTR(void);
+#else
+DECLINLINE(RTSEL) ASMGetTR(void)
+{
+    RTSEL SelTR;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("str %w0\n\t" : "=r" (SelTR));
+# else
+    __asm
+    {
+        str     ax
+        mov     [SelTR], ax
+    }
+# endif
+    return SelTR;
+}
+#endif
+
+
+/**
+ * Get the LDTR register.
+ * @returns LDTR.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(RTSEL) ASMGetLDTR(void);
+#else
+DECLINLINE(RTSEL) ASMGetLDTR(void)
+{
+    RTSEL SelLDTR;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("sldt %w0\n\t" : "=r" (SelLDTR));
+# else
+    __asm
+    {
+        sldt    ax
+        mov     [SelLDTR], ax
+    }
+# endif
+    return SelLDTR;
+}
+#endif
+
+
+/**
+ * Get the access rights for the segment selector.
+ *
+ * @returns The access rights on success or UINT32_MAX on failure.
+ * @param   uSel        The selector value.
+ *
+ * @remarks Using UINT32_MAX for failure is chosen because valid access rights
+ *          always have bits 0:7 as 0 (on both Intel & AMD).
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(uint32_t) ASMGetSegAttr(uint32_t uSel);
+#else
+DECLINLINE(uint32_t) ASMGetSegAttr(uint32_t uSel)
+{
+    uint32_t uAttr;
+    /* LAR only accesses 16-bit of the source operand, but eax for the
+       destination operand is required for getting the full 32-bit access rights. */
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("lar %1, %%eax\n\t"
+                         "jz done%=\n\t"
+                         "movl $0xffffffff, %%eax\n\t"
+                         "done%=:\n\t"
+                         "movl %%eax, %0\n\t"
+                         : "=r" (uAttr)
+                         : "r" (uSel)
+                         : "cc", "%eax");
+# else
+    __asm
+    {
+        lar     eax, [uSel]
+        jz      done
+        mov     eax, 0ffffffffh
+        done:
+        mov     [uAttr], eax
+    }
+# endif
+    return uAttr;
+}
+#endif
+
+
+/**
+ * Get the [RE]FLAGS register.
+ * @returns [RE]FLAGS.
+ */
+#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 15
+DECLASM(RTCCUINTREG) ASMGetFlags(void);
+#else
+DECLINLINE(RTCCUINTREG) ASMGetFlags(void)
+{
+    RTCCUINTREG uFlags;
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("pushfq\n\t"
+                         "popq  %0\n\t"
+                         : "=r" (uFlags));
+#  else
+    __asm__ __volatile__("pushfl\n\t"
+                         "popl  %0\n\t"
+                         : "=r" (uFlags));
+#  endif
+# elif RT_INLINE_ASM_USES_INTRIN >= 15
+    uFlags = __readeflags();
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        pushfq
+        pop  [uFlags]
+#  else
+        pushfd
+        pop  [uFlags]
+#  endif
+    }
+# endif
+    return uFlags;
+}
+#endif
+
+
+/**
+ * Set the [RE]FLAGS register.
+ * @param   uFlags      The new [RE]FLAGS value.
+ */
+#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 15
+DECLASM(void) ASMSetFlags(RTCCUINTREG uFlags);
+#else
+DECLINLINE(void) ASMSetFlags(RTCCUINTREG uFlags)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("pushq %0\n\t"
+                         "popfq\n\t"
+                         : : "g" (uFlags));
+#  else
+    __asm__ __volatile__("pushl %0\n\t"
+                         "popfl\n\t"
+                         : : "g" (uFlags));
+#  endif
+# elif RT_INLINE_ASM_USES_INTRIN >= 15
+    __writeeflags(uFlags);
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        push    [uFlags]
+        popfq
+#  else
+        push    [uFlags]
+        popfd
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Modifies the [RE]FLAGS register.
+ * @returns Original value.
+ * @param   fAndEfl     Flags to keep (applied first).
+ * @param   fOrEfl      Flags to be set.
+ */
+#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 15
+DECLASM(RTCCUINTREG) ASMChangeFlags(RTCCUINTREG fAndEfl, RTCCUINTREG fOrEfl);
+#else
+DECLINLINE(RTCCUINTREG) ASMChangeFlags(RTCCUINTREG fAndEfl, RTCCUINTREG fOrEfl)
+{
+    RTCCUINTREG fOldEfl;
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("pushfq\n\t"
+                         "movq  (%%rsp), %0\n\t"
+                         "andq  %0, %1\n\t"
+                         "orq   %3, %1\n\t"
+                         "mov   %1, (%%rsp)\n\t"
+                         "popfq\n\t"
+                         : "=&r" (fOldEfl),
+                           "=r" (fAndEfl)
+                         : "1" (fAndEfl),
+                           "rn" (fOrEfl) );
+#  else
+    __asm__ __volatile__("pushfl\n\t"
+                         "movl  (%%esp), %0\n\t"
+                         "andl  %1, (%%esp)\n\t"
+                         "orl   %2, (%%esp)\n\t"
+                         "popfl\n\t"
+                         : "=&r" (fOldEfl)
+                         : "rn" (fAndEfl),
+                           "rn" (fOrEfl) );
+#  endif
+# elif RT_INLINE_ASM_USES_INTRIN >= 15
+    fOldEfl = __readeflags();
+    __writeeflags((fOldEfl & fAndEfl) | fOrEfl);
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [fAndEfl]
+        mov     rcx, [fOrEfl]
+        pushfq
+        mov     rax, [rsp]
+        and     rdx, rax
+        or      rdx, rcx
+        mov     [rsp], rdx
+        popfq
+        mov     [fOldEfl], rax
+#  else
+        mov     edx, [fAndEfl]
+        mov     ecx, [fOrEfl]
+        pushfd
+        mov     eax, [esp]
+        and     edx, eax
+        or      edx, ecx
+        mov     [esp], edx
+        popfd
+        mov     [fOldEfl], eax
+#  endif
+    }
+# endif
+    return fOldEfl;
+}
+#endif
+
+
+/**
+ * Modifies the [RE]FLAGS register by ORing in one or more flags.
+ * @returns Original value.
+ * @param   fOrEfl      The flags to be set (ORed in).
+ */
+#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 15
+DECLASM(RTCCUINTREG) ASMAddFlags(RTCCUINTREG fOrEfl);
+#else
+DECLINLINE(RTCCUINTREG) ASMAddFlags(RTCCUINTREG fOrEfl)
+{
+    RTCCUINTREG fOldEfl;
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("pushfq\n\t"
+                         "movq  (%%rsp), %0\n\t"
+                         "orq   %1, (%%rsp)\n\t"
+                         "popfq\n\t"
+                         : "=&r" (fOldEfl)
+                         : "rn" (fOrEfl) );
+#  else
+    __asm__ __volatile__("pushfl\n\t"
+                         "movl  (%%esp), %0\n\t"
+                         "orl   %1, (%%esp)\n\t"
+                         "popfl\n\t"
+                         : "=&r" (fOldEfl)
+                         : "rn" (fOrEfl) );
+#  endif
+# elif RT_INLINE_ASM_USES_INTRIN >= 15
+    fOldEfl = __readeflags();
+    __writeeflags(fOldEfl | fOrEfl);
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rcx, [fOrEfl]
+        pushfq
+        mov     rdx, [rsp]
+        or      [rsp], rcx
+        popfq
+        mov     [fOldEfl], rax
+#  else
+        mov     ecx, [fOrEfl]
+        pushfd
+        mov     edx, [esp]
+        or      [esp], ecx
+        popfd
+        mov     [fOldEfl], eax
+#  endif
+    }
+# endif
+    return fOldEfl;
+}
+#endif
+
+
+/**
+ * Modifies the [RE]FLAGS register by AND'ing out one or more flags.
+ * @returns Original value.
+ * @param   fAndEfl      The flags to keep.
+ */
+#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 15
+DECLASM(RTCCUINTREG) ASMClearFlags(RTCCUINTREG fAndEfl);
+#else
+DECLINLINE(RTCCUINTREG) ASMClearFlags(RTCCUINTREG fAndEfl)
+{
+    RTCCUINTREG fOldEfl;
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("pushfq\n\t"
+                         "movq  (%%rsp), %0\n\t"
+                         "andq  %1, (%%rsp)\n\t"
+                         "popfq\n\t"
+                         : "=&r" (fOldEfl)
+                         : "rn" (fAndEfl) );
+#  else
+    __asm__ __volatile__("pushfl\n\t"
+                         "movl  (%%esp), %0\n\t"
+                         "andl  %1, (%%esp)\n\t"
+                         "popfl\n\t"
+                         : "=&r" (fOldEfl)
+                         : "rn" (fAndEfl) );
+#  endif
+# elif RT_INLINE_ASM_USES_INTRIN >= 15
+    fOldEfl = __readeflags();
+    __writeeflags(fOldEfl & fAndEfl);
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [fAndEfl]
+        pushfq
+        mov     rdx, [rsp]
+        and     [rsp], rdx
+        popfq
+        mov     [fOldEfl], rax
+#  else
+        mov     edx, [fAndEfl]
+        pushfd
+        mov     edx, [esp]
+        and     [esp], edx
+        popfd
+        mov     [fOldEfl], eax
+#  endif
+    }
+# endif
+    return fOldEfl;
+}
+#endif
+
+
+/**
+ * Gets the content of the CPU timestamp counter register.
+ *
+ * @returns TSC.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint64_t) ASMReadTSC(void);
+#else
+DECLINLINE(uint64_t) ASMReadTSC(void)
+{
+    RTUINT64U u;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("rdtsc\n\t" : "=a" (u.s.Lo), "=d" (u.s.Hi));
+# else
+#  if RT_INLINE_ASM_USES_INTRIN
+    u.u = __rdtsc();
+#  else
+    __asm
+    {
+        rdtsc
+        mov     [u.s.Lo], eax
+        mov     [u.s.Hi], edx
+    }
+#  endif
+# endif
+    return u.u;
+}
+#endif
+
+
+/**
+ * Gets the content of the CPU timestamp counter register and the
+ * assoicated AUX value.
+ *
+ * @returns TSC.
+ * @param   puAux   Where to store the AUX value.
+ */
+#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 15
+DECLASM(uint64_t) ASMReadTscWithAux(uint32_t *puAux);
+#else
+DECLINLINE(uint64_t) ASMReadTscWithAux(uint32_t *puAux)
+{
+    RTUINT64U u;
+# if RT_INLINE_ASM_GNU_STYLE
+    /* rdtscp is not supported by ancient linux build VM of course :-( */
+    /*__asm__ __volatile__("rdtscp\n\t" : "=a" (u.s.Lo), "=d" (u.s.Hi), "=c" (*puAux)); */
+    __asm__ __volatile__(".byte 0x0f,0x01,0xf9\n\t" : "=a" (u.s.Lo), "=d" (u.s.Hi), "=c" (*puAux));
+# else
+#  if RT_INLINE_ASM_USES_INTRIN >= 15
+    u.u = __rdtscp(puAux);
+#  else
+    __asm
+    {
+        rdtscp
+        mov     [u.s.Lo], eax
+        mov     [u.s.Hi], edx
+        mov     eax, [puAux]
+        mov     [eax], ecx
+    }
+#  endif
+# endif
+    return u.u;
+}
+#endif
+
+
+/**
+ * Performs the cpuid instruction returning all registers.
+ *
+ * @param   uOperator   CPUID operation (eax).
+ * @param   pvEAX       Where to store eax.
+ * @param   pvEBX       Where to store ebx.
+ * @param   pvECX       Where to store ecx.
+ * @param   pvEDX       Where to store edx.
+ * @remark  We're using void pointers to ease the use of special bitfield structures and such.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMCpuId(uint32_t uOperator, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX);
+#else
+DECLINLINE(void) ASMCpuId(uint32_t uOperator, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    RTCCUINTREG uRAX, uRBX, uRCX, uRDX;
+    __asm__ __volatile__ ("cpuid\n\t"
+                          : "=a" (uRAX),
+                            "=b" (uRBX),
+                            "=c" (uRCX),
+                            "=d" (uRDX)
+             : "0" (uOperator), "2" (0));
+    *(uint32_t *)pvEAX = (uint32_t)uRAX;
+    *(uint32_t *)pvEBX = (uint32_t)uRBX;
+    *(uint32_t *)pvECX = (uint32_t)uRCX;
+    *(uint32_t *)pvEDX = (uint32_t)uRDX;
+#  else
+    __asm__ __volatile__ ("xchgl %%ebx, %1\n\t"
+                          "cpuid\n\t"
+                          "xchgl %%ebx, %1\n\t"
+                         : "=a" (*(uint32_t *)pvEAX),
+                           "=r" (*(uint32_t *)pvEBX),
+                           "=c" (*(uint32_t *)pvECX),
+                           "=d" (*(uint32_t *)pvEDX)
+                         : "0" (uOperator), "2" (0));
+#  endif
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    int aInfo[4];
+    __cpuid(aInfo, uOperator);
+    *(uint32_t *)pvEAX = aInfo[0];
+    *(uint32_t *)pvEBX = aInfo[1];
+    *(uint32_t *)pvECX = aInfo[2];
+    *(uint32_t *)pvEDX = aInfo[3];
+
+# else
+    uint32_t    uEAX;
+    uint32_t    uEBX;
+    uint32_t    uECX;
+    uint32_t    uEDX;
+    __asm
+    {
+        push    ebx
+        mov     eax, [uOperator]
+        cpuid
+        mov     [uEAX], eax
+        mov     [uEBX], ebx
+        mov     [uECX], ecx
+        mov     [uEDX], edx
+        pop     ebx
+    }
+    *(uint32_t *)pvEAX = uEAX;
+    *(uint32_t *)pvEBX = uEBX;
+    *(uint32_t *)pvECX = uECX;
+    *(uint32_t *)pvEDX = uEDX;
+# endif
+}
+#endif
+
+
+/**
+ * Performs the CPUID instruction with EAX and ECX input returning ALL output
+ * registers.
+ *
+ * @param   uOperator   CPUID operation (eax).
+ * @param   uIdxECX     ecx index
+ * @param   pvEAX       Where to store eax.
+ * @param   pvEBX       Where to store ebx.
+ * @param   pvECX       Where to store ecx.
+ * @param   pvEDX       Where to store edx.
+ * @remark  We're using void pointers to ease the use of special bitfield structures and such.
+ */
+#if RT_INLINE_ASM_EXTERNAL || RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMCpuId_Idx_ECX(uint32_t uOperator, uint32_t uIdxECX, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX);
+#else
+DECLINLINE(void) ASMCpuId_Idx_ECX(uint32_t uOperator, uint32_t uIdxECX, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    RTCCUINTREG uRAX, uRBX, uRCX, uRDX;
+    __asm__ ("cpuid\n\t"
+             : "=a" (uRAX),
+               "=b" (uRBX),
+               "=c" (uRCX),
+               "=d" (uRDX)
+             : "0" (uOperator),
+               "2" (uIdxECX));
+    *(uint32_t *)pvEAX = (uint32_t)uRAX;
+    *(uint32_t *)pvEBX = (uint32_t)uRBX;
+    *(uint32_t *)pvECX = (uint32_t)uRCX;
+    *(uint32_t *)pvEDX = (uint32_t)uRDX;
+#  else
+    __asm__ ("xchgl %%ebx, %1\n\t"
+             "cpuid\n\t"
+             "xchgl %%ebx, %1\n\t"
+             : "=a" (*(uint32_t *)pvEAX),
+               "=r" (*(uint32_t *)pvEBX),
+               "=c" (*(uint32_t *)pvECX),
+               "=d" (*(uint32_t *)pvEDX)
+             : "0" (uOperator),
+               "2" (uIdxECX));
+#  endif
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    int aInfo[4];
+    __cpuidex(aInfo, uOperator, uIdxECX);
+    *(uint32_t *)pvEAX = aInfo[0];
+    *(uint32_t *)pvEBX = aInfo[1];
+    *(uint32_t *)pvECX = aInfo[2];
+    *(uint32_t *)pvEDX = aInfo[3];
+
+# else
+    uint32_t    uEAX;
+    uint32_t    uEBX;
+    uint32_t    uECX;
+    uint32_t    uEDX;
+    __asm
+    {
+        push    ebx
+        mov     eax, [uOperator]
+        mov     ecx, [uIdxECX]
+        cpuid
+        mov     [uEAX], eax
+        mov     [uEBX], ebx
+        mov     [uECX], ecx
+        mov     [uEDX], edx
+        pop     ebx
+    }
+    *(uint32_t *)pvEAX = uEAX;
+    *(uint32_t *)pvEBX = uEBX;
+    *(uint32_t *)pvECX = uECX;
+    *(uint32_t *)pvEDX = uEDX;
+# endif
+}
+#endif
+
+
+/**
+ * CPUID variant that initializes all 4 registers before the CPUID instruction.
+ *
+ * @returns The EAX result value.
+ * @param   uOperator   CPUID operation (eax).
+ * @param   uInitEBX    The value to assign EBX prior to the CPUID instruction.
+ * @param   uInitECX    The value to assign ECX prior to the CPUID instruction.
+ * @param   uInitEDX    The value to assign EDX prior to the CPUID instruction.
+ * @param   pvEAX       Where to store eax. Optional.
+ * @param   pvEBX       Where to store ebx. Optional.
+ * @param   pvECX       Where to store ecx. Optional.
+ * @param   pvEDX       Where to store edx. Optional.
+ */
+DECLASM(uint32_t) ASMCpuIdExSlow(uint32_t uOperator, uint32_t uInitEBX, uint32_t uInitECX, uint32_t uInitEDX,
+                                 void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX);
+
+
+/**
+ * Performs the cpuid instruction returning ecx and edx.
+ *
+ * @param   uOperator   CPUID operation (eax).
+ * @param   pvECX       Where to store ecx.
+ * @param   pvEDX       Where to store edx.
+ * @remark  We're using void pointers to ease the use of special bitfield structures and such.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMCpuId_ECX_EDX(uint32_t uOperator, void *pvECX, void *pvEDX);
+#else
+DECLINLINE(void) ASMCpuId_ECX_EDX(uint32_t uOperator, void *pvECX, void *pvEDX)
+{
+    uint32_t uEBX;
+    ASMCpuId(uOperator, &uOperator, &uEBX, pvECX, pvEDX);
+}
+#endif
+
+
+/**
+ * Performs the cpuid instruction returning eax.
+ *
+ * @param   uOperator   CPUID operation (eax).
+ * @returns EAX after cpuid operation.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint32_t) ASMCpuId_EAX(uint32_t uOperator);
+#else
+DECLINLINE(uint32_t) ASMCpuId_EAX(uint32_t uOperator)
+{
+    RTCCUINTREG xAX;
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ ("cpuid"
+             : "=a" (xAX)
+             : "0" (uOperator)
+             : "rbx", "rcx", "rdx");
+#  elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
+    __asm__ ("push  %%ebx\n\t"
+             "cpuid\n\t"
+             "pop   %%ebx\n\t"
+             : "=a" (xAX)
+             : "0" (uOperator)
+             : "ecx", "edx");
+#  else
+    __asm__ ("cpuid"
+             : "=a" (xAX)
+             : "0" (uOperator)
+             : "edx", "ecx", "ebx");
+#  endif
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    int aInfo[4];
+    __cpuid(aInfo, uOperator);
+    xAX = aInfo[0];
+
+# else
+    __asm
+    {
+        push    ebx
+        mov     eax, [uOperator]
+        cpuid
+        mov     [xAX], eax
+        pop     ebx
+    }
+# endif
+    return (uint32_t)xAX;
+}
+#endif
+
+
+/**
+ * Performs the cpuid instruction returning ebx.
+ *
+ * @param   uOperator   CPUID operation (eax).
+ * @returns EBX after cpuid operation.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint32_t) ASMCpuId_EBX(uint32_t uOperator);
+#else
+DECLINLINE(uint32_t) ASMCpuId_EBX(uint32_t uOperator)
+{
+    RTCCUINTREG xBX;
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    RTCCUINTREG uSpill;
+    __asm__ ("cpuid"
+             : "=a" (uSpill),
+               "=b" (xBX)
+             : "0" (uOperator)
+             : "rdx", "rcx");
+#  elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
+    __asm__ ("push  %%ebx\n\t"
+             "cpuid\n\t"
+             "mov   %%ebx, %%edx\n\t"
+             "pop   %%ebx\n\t"
+             : "=a" (uOperator),
+               "=d" (xBX)
+             : "0" (uOperator)
+             : "ecx");
+#  else
+    __asm__ ("cpuid"
+             : "=a" (uOperator),
+               "=b" (xBX)
+             : "0" (uOperator)
+             : "edx", "ecx");
+#  endif
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    int aInfo[4];
+    __cpuid(aInfo, uOperator);
+    xBX = aInfo[1];
+
+# else
+    __asm
+    {
+        push    ebx
+        mov     eax, [uOperator]
+        cpuid
+        mov     [xBX], ebx
+        pop     ebx
+    }
+# endif
+    return (uint32_t)xBX;
+}
+#endif
+
+
+/**
+ * Performs the cpuid instruction returning ecx.
+ *
+ * @param   uOperator   CPUID operation (eax).
+ * @returns ECX after cpuid operation.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint32_t) ASMCpuId_ECX(uint32_t uOperator);
+#else
+DECLINLINE(uint32_t) ASMCpuId_ECX(uint32_t uOperator)
+{
+    RTCCUINTREG xCX;
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    RTCCUINTREG uSpill;
+    __asm__ ("cpuid"
+             : "=a" (uSpill),
+               "=c" (xCX)
+             : "0" (uOperator)
+             : "rbx", "rdx");
+#  elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
+    __asm__ ("push  %%ebx\n\t"
+             "cpuid\n\t"
+             "pop   %%ebx\n\t"
+             : "=a" (uOperator),
+               "=c" (xCX)
+             : "0" (uOperator)
+             : "edx");
+#  else
+    __asm__ ("cpuid"
+             : "=a" (uOperator),
+               "=c" (xCX)
+             : "0" (uOperator)
+             : "ebx", "edx");
+
+#  endif
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    int aInfo[4];
+    __cpuid(aInfo, uOperator);
+    xCX = aInfo[2];
+
+# else
+    __asm
+    {
+        push    ebx
+        mov     eax, [uOperator]
+        cpuid
+        mov     [xCX], ecx
+        pop     ebx
+    }
+# endif
+    return (uint32_t)xCX;
+}
+#endif
+
+
+/**
+ * Performs the cpuid instruction returning edx.
+ *
+ * @param   uOperator   CPUID operation (eax).
+ * @returns EDX after cpuid operation.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint32_t) ASMCpuId_EDX(uint32_t uOperator);
+#else
+DECLINLINE(uint32_t) ASMCpuId_EDX(uint32_t uOperator)
+{
+    RTCCUINTREG xDX;
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    RTCCUINTREG uSpill;
+    __asm__ ("cpuid"
+             : "=a" (uSpill),
+               "=d" (xDX)
+             : "0" (uOperator)
+             : "rbx", "rcx");
+#  elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
+    __asm__ ("push  %%ebx\n\t"
+             "cpuid\n\t"
+             "pop   %%ebx\n\t"
+             : "=a" (uOperator),
+               "=d" (xDX)
+             : "0" (uOperator)
+             : "ecx");
+#  else
+    __asm__ ("cpuid"
+             : "=a" (uOperator),
+               "=d" (xDX)
+             : "0" (uOperator)
+             : "ebx", "ecx");
+#  endif
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    int aInfo[4];
+    __cpuid(aInfo, uOperator);
+    xDX = aInfo[3];
+
+# else
+    __asm
+    {
+        push    ebx
+        mov     eax, [uOperator]
+        cpuid
+        mov     [xDX], edx
+        pop     ebx
+    }
+# endif
+    return (uint32_t)xDX;
+}
+#endif
+
+
+/**
+ * Checks if the current CPU supports CPUID.
+ *
+ * @returns true if CPUID is supported.
+ */
+#ifdef __WATCOMC__
+DECLASM(bool) ASMHasCpuId(void);
+#else
+DECLINLINE(bool) ASMHasCpuId(void)
+{
+# ifdef RT_ARCH_AMD64
+    return true; /* ASSUME that all amd64 compatible CPUs have cpuid. */
+# else /* !RT_ARCH_AMD64 */
+    bool        fRet = false;
+#  if RT_INLINE_ASM_GNU_STYLE
+    uint32_t    u1;
+    uint32_t    u2;
+    __asm__ ("pushf\n\t"
+             "pop   %1\n\t"
+             "mov   %1, %2\n\t"
+             "xorl  $0x200000, %1\n\t"
+             "push  %1\n\t"
+             "popf\n\t"
+             "pushf\n\t"
+             "pop   %1\n\t"
+             "cmpl  %1, %2\n\t"
+             "setne %0\n\t"
+             "push  %2\n\t"
+             "popf\n\t"
+             : "=m" (fRet), "=r" (u1), "=r" (u2));
+#  else
+    __asm
+    {
+        pushfd
+        pop     eax
+        mov     ebx, eax
+        xor     eax, 0200000h
+        push    eax
+        popfd
+        pushfd
+        pop     eax
+        cmp     eax, ebx
+        setne   fRet
+        push    ebx
+        popfd
+    }
+#  endif
+    return fRet;
+# endif /* !RT_ARCH_AMD64 */
+}
+#endif
+
+
+/**
+ * Gets the APIC ID of the current CPU.
+ *
+ * @returns the APIC ID.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint8_t) ASMGetApicId(void);
+#else
+DECLINLINE(uint8_t) ASMGetApicId(void)
+{
+    RTCCUINTREG xBX;
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    RTCCUINTREG uSpill;
+    __asm__ __volatile__ ("cpuid"
+                          : "=a" (uSpill),
+                            "=b" (xBX)
+                          : "0" (1)
+                          : "rcx", "rdx");
+#  elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
+    RTCCUINTREG uSpill;
+    __asm__ __volatile__ ("mov   %%ebx,%1\n\t"
+                          "cpuid\n\t"
+                          "xchgl %%ebx,%1\n\t"
+                          : "=a" (uSpill),
+                            "=rm" (xBX)
+                          : "0" (1)
+                          : "ecx", "edx");
+#  else
+    RTCCUINTREG uSpill;
+    __asm__ __volatile__ ("cpuid"
+                          : "=a" (uSpill),
+                            "=b" (xBX)
+                          : "0" (1)
+                          : "ecx", "edx");
+#  endif
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    int aInfo[4];
+    __cpuid(aInfo, 1);
+    xBX = aInfo[1];
+
+# else
+    __asm
+    {
+        push    ebx
+        mov     eax, 1
+        cpuid
+        mov     [xBX], ebx
+        pop     ebx
+    }
+# endif
+    return (uint8_t)(xBX >> 24);
+}
+#endif
+
+
+/**
+ * Tests if it a genuine Intel CPU based on the ASMCpuId(0) output.
+ *
+ * @returns true/false.
+ * @param   uEBX    EBX return from ASMCpuId(0)
+ * @param   uECX    ECX return from ASMCpuId(0)
+ * @param   uEDX    EDX return from ASMCpuId(0)
+ */
+DECLINLINE(bool) ASMIsIntelCpuEx(uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
+{
+    return uEBX == UINT32_C(0x756e6547)
+        && uECX == UINT32_C(0x6c65746e)
+        && uEDX == UINT32_C(0x49656e69);
+}
+
+
+/**
+ * Tests if this is a genuine Intel CPU.
+ *
+ * @returns true/false.
+ * @remarks ASSUMES that cpuid is supported by the CPU.
+ */
+DECLINLINE(bool) ASMIsIntelCpu(void)
+{
+    uint32_t uEAX, uEBX, uECX, uEDX;
+    ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
+    return ASMIsIntelCpuEx(uEBX, uECX, uEDX);
+}
+
+
+/**
+ * Tests if it an authentic AMD CPU based on the ASMCpuId(0) output.
+ *
+ * @returns true/false.
+ * @param   uEBX    EBX return from ASMCpuId(0)
+ * @param   uECX    ECX return from ASMCpuId(0)
+ * @param   uEDX    EDX return from ASMCpuId(0)
+ */
+DECLINLINE(bool) ASMIsAmdCpuEx(uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
+{
+    return uEBX == UINT32_C(0x68747541)
+        && uECX == UINT32_C(0x444d4163)
+        && uEDX == UINT32_C(0x69746e65);
+}
+
+
+/**
+ * Tests if this is an authentic AMD CPU.
+ *
+ * @returns true/false.
+ * @remarks ASSUMES that cpuid is supported by the CPU.
+ */
+DECLINLINE(bool) ASMIsAmdCpu(void)
+{
+    uint32_t uEAX, uEBX, uECX, uEDX;
+    ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
+    return ASMIsAmdCpuEx(uEBX, uECX, uEDX);
+}
+
+
+/**
+ * Tests if it a centaur hauling VIA CPU based on the ASMCpuId(0) output.
+ *
+ * @returns true/false.
+ * @param   uEBX    EBX return from ASMCpuId(0).
+ * @param   uECX    ECX return from ASMCpuId(0).
+ * @param   uEDX    EDX return from ASMCpuId(0).
+ */
+DECLINLINE(bool) ASMIsViaCentaurCpuEx(uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
+{
+    return uEBX == UINT32_C(0x746e6543)
+        && uECX == UINT32_C(0x736c7561)
+        && uEDX == UINT32_C(0x48727561);
+}
+
+
+/**
+ * Tests if this is a centaur hauling VIA CPU.
+ *
+ * @returns true/false.
+ * @remarks ASSUMES that cpuid is supported by the CPU.
+ */
+DECLINLINE(bool) ASMIsViaCentaurCpu(void)
+{
+    uint32_t uEAX, uEBX, uECX, uEDX;
+    ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
+    return ASMIsViaCentaurCpuEx(uEBX, uECX, uEDX);
+}
+
+
+/**
+ * Checks whether ASMCpuId_EAX(0x00000000) indicates a valid range.
+ *
+ *
+ * @returns true/false.
+ * @param   uEAX    The EAX value of CPUID leaf 0x00000000.
+ *
+ * @note    This only succeeds if there are at least two leaves in the range.
+ * @remarks The upper range limit is just some half reasonable value we've
+ *          picked out of thin air.
+ */
+DECLINLINE(bool) ASMIsValidStdRange(uint32_t uEAX)
+{
+    return uEAX >= UINT32_C(0x00000001) && uEAX <= UINT32_C(0x000fffff);
+}
+
+
+/**
+ * Checks whether ASMCpuId_EAX(0x80000000) indicates a valid range.
+ *
+ * This only succeeds if there are at least two leaves in the range.
+ *
+ * @returns true/false.
+ * @param   uEAX    The EAX value of CPUID leaf 0x80000000.
+ *
+ * @note    This only succeeds if there are at least two leaves in the range.
+ * @remarks The upper range limit is just some half reasonable value we've
+ *          picked out of thin air.
+ */
+DECLINLINE(bool) ASMIsValidExtRange(uint32_t uEAX)
+{
+    return uEAX >= UINT32_C(0x80000001) && uEAX <= UINT32_C(0x800fffff);
+}
+
+
+/**
+ * Extracts the CPU family from ASMCpuId(1) or ASMCpuId(0x80000001)
+ *
+ * @returns Family.
+ * @param   uEAX    EAX return from ASMCpuId(1) or ASMCpuId(0x80000001).
+ */
+DECLINLINE(uint32_t) ASMGetCpuFamily(uint32_t uEAX)
+{
+    return ((uEAX >> 8) & 0xf) == 0xf
+         ? ((uEAX >> 20) & 0x7f) + 0xf
+         : ((uEAX >> 8) & 0xf);
+}
+
+
+/**
+ * Extracts the CPU model from ASMCpuId(1) or ASMCpuId(0x80000001), Intel variant.
+ *
+ * @returns Model.
+ * @param   uEAX    EAX from ASMCpuId(1) or ASMCpuId(0x80000001).
+ */
+DECLINLINE(uint32_t) ASMGetCpuModelIntel(uint32_t uEAX)
+{
+    return ((uEAX >> 8) & 0xf) == 0xf || (((uEAX >> 8) & 0xf) == 0x6) /* family! */
+         ? ((uEAX >> 4) & 0xf) | ((uEAX >> 12) & 0xf0)
+         : ((uEAX >> 4) & 0xf);
+}
+
+
+/**
+ * Extracts the CPU model from ASMCpuId(1) or ASMCpuId(0x80000001), AMD variant.
+ *
+ * @returns Model.
+ * @param   uEAX    EAX from ASMCpuId(1) or ASMCpuId(0x80000001).
+ */
+DECLINLINE(uint32_t) ASMGetCpuModelAMD(uint32_t uEAX)
+{
+    return ((uEAX >> 8) & 0xf) == 0xf
+         ? ((uEAX >> 4) & 0xf) | ((uEAX >> 12) & 0xf0)
+         : ((uEAX >> 4) & 0xf);
+}
+
+
+/**
+ * Extracts the CPU model from ASMCpuId(1) or ASMCpuId(0x80000001)
+ *
+ * @returns Model.
+ * @param   uEAX    EAX from ASMCpuId(1) or ASMCpuId(0x80000001).
+ * @param   fIntel  Whether it's an intel CPU. Use ASMIsIntelCpuEx() or ASMIsIntelCpu().
+ */
+DECLINLINE(uint32_t) ASMGetCpuModel(uint32_t uEAX, bool fIntel)
+{
+    return ((uEAX >> 8) & 0xf) == 0xf || (((uEAX >> 8) & 0xf) == 0x6 && fIntel) /* family! */
+         ? ((uEAX >> 4) & 0xf) | ((uEAX >> 12) & 0xf0)
+         : ((uEAX >> 4) & 0xf);
+}
+
+
+/**
+ * Extracts the CPU stepping from ASMCpuId(1) or ASMCpuId(0x80000001)
+ *
+ * @returns Model.
+ * @param   uEAX    EAX from ASMCpuId(1) or ASMCpuId(0x80000001).
+ */
+DECLINLINE(uint32_t) ASMGetCpuStepping(uint32_t uEAX)
+{
+    return uEAX & 0xf;
+}
+
+
+/**
+ * Get cr0.
+ * @returns cr0.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(RTCCUINTXREG) ASMGetCR0(void);
+#else
+DECLINLINE(RTCCUINTXREG) ASMGetCR0(void)
+{
+    RTCCUINTXREG uCR0;
+# if RT_INLINE_ASM_USES_INTRIN
+    uCR0 = __readcr0();
+
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq  %%cr0, %0\t\n" : "=r" (uCR0));
+#  else
+    __asm__ __volatile__("movl  %%cr0, %0\t\n" : "=r" (uCR0));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, cr0
+        mov     [uCR0], rax
+#  else
+        mov     eax, cr0
+        mov     [uCR0], eax
+#  endif
+    }
+# endif
+    return uCR0;
+}
+#endif
+
+
+/**
+ * Sets the CR0 register.
+ * @param   uCR0 The new CR0 value.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMSetCR0(RTCCUINTXREG uCR0);
+#else
+DECLINLINE(void) ASMSetCR0(RTCCUINTXREG uCR0)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    __writecr0(uCR0);
+
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq %0, %%cr0\n\t" :: "r" (uCR0));
+#  else
+    __asm__ __volatile__("movl %0, %%cr0\n\t" :: "r" (uCR0));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [uCR0]
+        mov     cr0, rax
+#  else
+        mov     eax, [uCR0]
+        mov     cr0, eax
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Get cr2.
+ * @returns cr2.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(RTCCUINTXREG) ASMGetCR2(void);
+#else
+DECLINLINE(RTCCUINTXREG) ASMGetCR2(void)
+{
+    RTCCUINTXREG uCR2;
+# if RT_INLINE_ASM_USES_INTRIN
+    uCR2 = __readcr2();
+
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq  %%cr2, %0\t\n" : "=r" (uCR2));
+#  else
+    __asm__ __volatile__("movl  %%cr2, %0\t\n" : "=r" (uCR2));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, cr2
+        mov     [uCR2], rax
+#  else
+        mov     eax, cr2
+        mov     [uCR2], eax
+#  endif
+    }
+# endif
+    return uCR2;
+}
+#endif
+
+
+/**
+ * Sets the CR2 register.
+ * @param   uCR2 The new CR0 value.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMSetCR2(RTCCUINTXREG uCR2);
+#else
+DECLINLINE(void) ASMSetCR2(RTCCUINTXREG uCR2)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq %0, %%cr2\n\t" :: "r" (uCR2));
+#  else
+    __asm__ __volatile__("movl %0, %%cr2\n\t" :: "r" (uCR2));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [uCR2]
+        mov     cr2, rax
+#  else
+        mov     eax, [uCR2]
+        mov     cr2, eax
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Get cr3.
+ * @returns cr3.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(RTCCUINTXREG) ASMGetCR3(void);
+#else
+DECLINLINE(RTCCUINTXREG) ASMGetCR3(void)
+{
+    RTCCUINTXREG uCR3;
+# if RT_INLINE_ASM_USES_INTRIN
+    uCR3 = __readcr3();
+
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq  %%cr3, %0\t\n" : "=r" (uCR3));
+#  else
+    __asm__ __volatile__("movl  %%cr3, %0\t\n" : "=r" (uCR3));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, cr3
+        mov     [uCR3], rax
+#  else
+        mov     eax, cr3
+        mov     [uCR3], eax
+#  endif
+    }
+# endif
+    return uCR3;
+}
+#endif
+
+
+/**
+ * Sets the CR3 register.
+ *
+ * @param   uCR3    New CR3 value.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMSetCR3(RTCCUINTXREG uCR3);
+#else
+DECLINLINE(void) ASMSetCR3(RTCCUINTXREG uCR3)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    __writecr3(uCR3);
+
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq %0, %%cr3\n\t" : : "r" (uCR3));
+#  else
+    __asm__ __volatile__("movl %0, %%cr3\n\t" : : "r" (uCR3));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [uCR3]
+        mov     cr3, rax
+#  else
+        mov     eax, [uCR3]
+        mov     cr3, eax
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Reloads the CR3 register.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMReloadCR3(void);
+#else
+DECLINLINE(void) ASMReloadCR3(void)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    __writecr3(__readcr3());
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    RTCCUINTXREG u;
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq %%cr3, %0\n\t"
+                         "movq %0, %%cr3\n\t"
+                         : "=r" (u));
+#  else
+    __asm__ __volatile__("movl %%cr3, %0\n\t"
+                         "movl %0, %%cr3\n\t"
+                         : "=r" (u));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, cr3
+        mov     cr3, rax
+#  else
+        mov     eax, cr3
+        mov     cr3, eax
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Get cr4.
+ * @returns cr4.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(RTCCUINTXREG) ASMGetCR4(void);
+#else
+DECLINLINE(RTCCUINTXREG) ASMGetCR4(void)
+{
+    RTCCUINTXREG uCR4;
+# if RT_INLINE_ASM_USES_INTRIN
+    uCR4 = __readcr4();
+
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq  %%cr4, %0\t\n" : "=r" (uCR4));
+#  else
+    __asm__ __volatile__("movl  %%cr4, %0\t\n" : "=r" (uCR4));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, cr4
+        mov     [uCR4], rax
+#  else
+        push    eax /* just in case */
+        /*mov     eax, cr4*/
+        _emit   0x0f
+        _emit   0x20
+        _emit   0xe0
+        mov     [uCR4], eax
+        pop     eax
+#  endif
+    }
+# endif
+    return uCR4;
+}
+#endif
+
+
+/**
+ * Sets the CR4 register.
+ *
+ * @param   uCR4    New CR4 value.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMSetCR4(RTCCUINTXREG uCR4);
+#else
+DECLINLINE(void) ASMSetCR4(RTCCUINTXREG uCR4)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    __writecr4(uCR4);
+
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq %0, %%cr4\n\t" : : "r" (uCR4));
+#  else
+    __asm__ __volatile__("movl %0, %%cr4\n\t" : : "r" (uCR4));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [uCR4]
+        mov     cr4, rax
+#  else
+        mov     eax, [uCR4]
+        _emit   0x0F
+        _emit   0x22
+        _emit   0xE0        /* mov     cr4, eax */
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Get cr8.
+ * @returns cr8.
+ * @remark  The lock prefix hack for access from non-64-bit modes is NOT used and 0 is returned.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(RTCCUINTXREG) ASMGetCR8(void);
+#else
+DECLINLINE(RTCCUINTXREG) ASMGetCR8(void)
+{
+# ifdef RT_ARCH_AMD64
+    RTCCUINTXREG uCR8;
+#  if RT_INLINE_ASM_USES_INTRIN
+    uCR8 = __readcr8();
+
+#  elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("movq  %%cr8, %0\t\n" : "=r" (uCR8));
+#  else
+    __asm
+    {
+        mov     rax, cr8
+        mov     [uCR8], rax
+    }
+#  endif
+    return uCR8;
+# else /* !RT_ARCH_AMD64 */
+    return 0;
+# endif /* !RT_ARCH_AMD64 */
+}
+#endif
+
+
+/**
+ * Get XCR0 (eXtended feature Control Register 0).
+ * @returns xcr0.
+ */
+DECLASM(uint64_t) ASMGetXcr0(void);
+
+/**
+ * Sets the XCR0 register.
+ * @param   uXcr0   The new XCR0 value.
+ */
+DECLASM(void) ASMSetXcr0(uint64_t uXcr0);
+
+struct X86XSAVEAREA;
+/**
+ * Save extended CPU state.
+ * @param   pXStateArea     Where to save the state.
+ * @param   fComponents     Which state components to save.
+ */
+DECLASM(void) ASMXSave(struct X86XSAVEAREA *pXStateArea, uint64_t fComponents);
+
+/**
+ * Loads extended CPU state.
+ * @param   pXStateArea     Where to load the state from.
+ * @param   fComponents     Which state components to load.
+ */
+DECLASM(void) ASMXRstor(struct X86XSAVEAREA const *pXStateArea, uint64_t fComponents);
+
+
+struct X86FXSTATE;
+/**
+ * Save FPU and SSE CPU state.
+ * @param   pXStateArea     Where to save the state.
+ */
+DECLASM(void) ASMFxSave(struct X86FXSTATE *pXStateArea);
+
+/**
+ * Load FPU and SSE CPU state.
+ * @param   pXStateArea     Where to load the state from.
+ */
+DECLASM(void) ASMFxRstor(struct X86FXSTATE const *pXStateArea);
+
+
+/**
+ * Enables interrupts (EFLAGS.IF).
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMIntEnable(void);
+#else
+DECLINLINE(void) ASMIntEnable(void)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm("sti\n");
+# elif RT_INLINE_ASM_USES_INTRIN
+    _enable();
+# else
+    __asm sti
+# endif
+}
+#endif
+
+
+/**
+ * Disables interrupts (!EFLAGS.IF).
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMIntDisable(void);
+#else
+DECLINLINE(void) ASMIntDisable(void)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm("cli\n");
+# elif RT_INLINE_ASM_USES_INTRIN
+    _disable();
+# else
+    __asm cli
+# endif
+}
+#endif
+
+
+/**
+ * Disables interrupts and returns previous xFLAGS.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(RTCCUINTREG) ASMIntDisableFlags(void);
+#else
+DECLINLINE(RTCCUINTREG) ASMIntDisableFlags(void)
+{
+    RTCCUINTREG xFlags;
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("pushfq\n\t"
+                         "cli\n\t"
+                         "popq  %0\n\t"
+                         : "=r" (xFlags));
+#  else
+    __asm__ __volatile__("pushfl\n\t"
+                         "cli\n\t"
+                         "popl  %0\n\t"
+                         : "=r" (xFlags));
+#  endif
+# elif RT_INLINE_ASM_USES_INTRIN && !defined(RT_ARCH_X86)
+    xFlags = ASMGetFlags();
+    _disable();
+# else
+    __asm {
+        pushfd
+        cli
+        pop  [xFlags]
+    }
+# endif
+    return xFlags;
+}
+#endif
+
+
+/**
+ * Are interrupts enabled?
+ *
+ * @returns true / false.
+ */
+DECLINLINE(bool) ASMIntAreEnabled(void)
+{
+    RTCCUINTREG uFlags = ASMGetFlags();
+    return uFlags & 0x200 /* X86_EFL_IF */ ? true : false;
+}
+
+
+/**
+ * Halts the CPU until interrupted.
+ */
+#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 14
+DECLASM(void) ASMHalt(void);
+#else
+DECLINLINE(void) ASMHalt(void)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("hlt\n\t");
+# elif RT_INLINE_ASM_USES_INTRIN
+    __halt();
+# else
+    __asm {
+        hlt
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Reads a machine specific register.
+ *
+ * @returns Register content.
+ * @param   uRegister   Register to read.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint64_t) ASMRdMsr(uint32_t uRegister);
+#else
+DECLINLINE(uint64_t) ASMRdMsr(uint32_t uRegister)
+{
+    RTUINT64U u;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("rdmsr\n\t"
+                         : "=a" (u.s.Lo),
+                           "=d" (u.s.Hi)
+                         : "c" (uRegister));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    u.u = __readmsr(uRegister);
+
+# else
+    __asm
+    {
+        mov     ecx, [uRegister]
+        rdmsr
+        mov     [u.s.Lo], eax
+        mov     [u.s.Hi], edx
+    }
+# endif
+
+    return u.u;
+}
+#endif
+
+
+/**
+ * Writes a machine specific register.
+ *
+ * @returns Register content.
+ * @param   uRegister   Register to write to.
+ * @param   u64Val      Value to write.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMWrMsr(uint32_t uRegister, uint64_t u64Val);
+#else
+DECLINLINE(void) ASMWrMsr(uint32_t uRegister, uint64_t u64Val)
+{
+    RTUINT64U u;
+
+    u.u = u64Val;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("wrmsr\n\t"
+                         ::"a" (u.s.Lo),
+                           "d" (u.s.Hi),
+                           "c" (uRegister));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    __writemsr(uRegister, u.u);
+
+# else
+    __asm
+    {
+        mov     ecx, [uRegister]
+        mov     edx, [u.s.Hi]
+        mov     eax, [u.s.Lo]
+        wrmsr
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Reads a machine specific register, extended version (for AMD).
+ *
+ * @returns Register content.
+ * @param   uRegister   Register to read.
+ * @param   uXDI        RDI/EDI value.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(uint64_t) ASMRdMsrEx(uint32_t uRegister, RTCCUINTXREG uXDI);
+#else
+DECLINLINE(uint64_t) ASMRdMsrEx(uint32_t uRegister, RTCCUINTXREG uXDI)
+{
+    RTUINT64U u;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("rdmsr\n\t"
+                         : "=a" (u.s.Lo),
+                           "=d" (u.s.Hi)
+                         : "c" (uRegister),
+                           "D" (uXDI));
+
+# else
+    __asm
+    {
+        mov     ecx, [uRegister]
+        xchg    edi, [uXDI]
+        rdmsr
+        mov     [u.s.Lo], eax
+        mov     [u.s.Hi], edx
+        xchg    edi, [uXDI]
+    }
+# endif
+
+    return u.u;
+}
+#endif
+
+
+/**
+ * Writes a machine specific register, extended version (for AMD).
+ *
+ * @returns Register content.
+ * @param   uRegister   Register to write to.
+ * @param   uXDI        RDI/EDI value.
+ * @param   u64Val      Value to write.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMWrMsrEx(uint32_t uRegister, RTCCUINTXREG uXDI, uint64_t u64Val);
+#else
+DECLINLINE(void) ASMWrMsrEx(uint32_t uRegister, RTCCUINTXREG uXDI, uint64_t u64Val)
+{
+    RTUINT64U u;
+
+    u.u = u64Val;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("wrmsr\n\t"
+                         ::"a" (u.s.Lo),
+                           "d" (u.s.Hi),
+                           "c" (uRegister),
+                           "D" (uXDI));
+
+# else
+    __asm
+    {
+        mov     ecx, [uRegister]
+        xchg    edi, [uXDI]
+        mov     edx, [u.s.Hi]
+        mov     eax, [u.s.Lo]
+        wrmsr
+        xchg    edi, [uXDI]
+    }
+# endif
+}
+#endif
+
+
+
+/**
+ * Reads low part of a machine specific register.
+ *
+ * @returns Register content.
+ * @param   uRegister   Register to read.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint32_t) ASMRdMsr_Low(uint32_t uRegister);
+#else
+DECLINLINE(uint32_t) ASMRdMsr_Low(uint32_t uRegister)
+{
+    uint32_t u32;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("rdmsr\n\t"
+                         : "=a" (u32)
+                         : "c" (uRegister)
+                         : "edx");
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    u32 = (uint32_t)__readmsr(uRegister);
+
+#else
+    __asm
+    {
+        mov     ecx, [uRegister]
+        rdmsr
+        mov     [u32], eax
+    }
+# endif
+
+    return u32;
+}
+#endif
+
+
+/**
+ * Reads high part of a machine specific register.
+ *
+ * @returns Register content.
+ * @param   uRegister   Register to read.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint32_t) ASMRdMsr_High(uint32_t uRegister);
+#else
+DECLINLINE(uint32_t) ASMRdMsr_High(uint32_t uRegister)
+{
+    uint32_t    u32;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("rdmsr\n\t"
+                         : "=d" (u32)
+                         : "c" (uRegister)
+                         : "eax");
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    u32 = (uint32_t)(__readmsr(uRegister) >> 32);
+
+# else
+    __asm
+    {
+        mov     ecx, [uRegister]
+        rdmsr
+        mov     [u32], edx
+    }
+# endif
+
+    return u32;
+}
+#endif
+
+
+/**
+ * Gets dr0.
+ *
+ * @returns dr0.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(RTCCUINTXREG) ASMGetDR0(void);
+#else
+DECLINLINE(RTCCUINTXREG) ASMGetDR0(void)
+{
+    RTCCUINTXREG uDR0;
+# if RT_INLINE_ASM_USES_INTRIN
+    uDR0 = __readdr(0);
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq   %%dr0, %0\n\t" : "=r" (uDR0));
+#  else
+    __asm__ __volatile__("movl   %%dr0, %0\n\t" : "=r" (uDR0));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, dr0
+        mov     [uDR0], rax
+#  else
+        mov     eax, dr0
+        mov     [uDR0], eax
+#  endif
+    }
+# endif
+    return uDR0;
+}
+#endif
+
+
+/**
+ * Gets dr1.
+ *
+ * @returns dr1.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(RTCCUINTXREG) ASMGetDR1(void);
+#else
+DECLINLINE(RTCCUINTXREG) ASMGetDR1(void)
+{
+    RTCCUINTXREG uDR1;
+# if RT_INLINE_ASM_USES_INTRIN
+    uDR1 = __readdr(1);
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq   %%dr1, %0\n\t" : "=r" (uDR1));
+#  else
+    __asm__ __volatile__("movl   %%dr1, %0\n\t" : "=r" (uDR1));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, dr1
+        mov     [uDR1], rax
+#  else
+        mov     eax, dr1
+        mov     [uDR1], eax
+#  endif
+    }
+# endif
+    return uDR1;
+}
+#endif
+
+
+/**
+ * Gets dr2.
+ *
+ * @returns dr2.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(RTCCUINTXREG) ASMGetDR2(void);
+#else
+DECLINLINE(RTCCUINTXREG) ASMGetDR2(void)
+{
+    RTCCUINTXREG uDR2;
+# if RT_INLINE_ASM_USES_INTRIN
+    uDR2 = __readdr(2);
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq   %%dr2, %0\n\t" : "=r" (uDR2));
+#  else
+    __asm__ __volatile__("movl   %%dr2, %0\n\t" : "=r" (uDR2));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, dr2
+        mov     [uDR2], rax
+#  else
+        mov     eax, dr2
+        mov     [uDR2], eax
+#  endif
+    }
+# endif
+    return uDR2;
+}
+#endif
+
+
+/**
+ * Gets dr3.
+ *
+ * @returns dr3.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(RTCCUINTXREG) ASMGetDR3(void);
+#else
+DECLINLINE(RTCCUINTXREG) ASMGetDR3(void)
+{
+    RTCCUINTXREG uDR3;
+# if RT_INLINE_ASM_USES_INTRIN
+    uDR3 = __readdr(3);
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq   %%dr3, %0\n\t" : "=r" (uDR3));
+#  else
+    __asm__ __volatile__("movl   %%dr3, %0\n\t" : "=r" (uDR3));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, dr3
+        mov     [uDR3], rax
+#  else
+        mov     eax, dr3
+        mov     [uDR3], eax
+#  endif
+    }
+# endif
+    return uDR3;
+}
+#endif
+
+
+/**
+ * Gets dr6.
+ *
+ * @returns dr6.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(RTCCUINTXREG) ASMGetDR6(void);
+#else
+DECLINLINE(RTCCUINTXREG) ASMGetDR6(void)
+{
+    RTCCUINTXREG uDR6;
+# if RT_INLINE_ASM_USES_INTRIN
+    uDR6 = __readdr(6);
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq   %%dr6, %0\n\t" : "=r" (uDR6));
+#  else
+    __asm__ __volatile__("movl   %%dr6, %0\n\t" : "=r" (uDR6));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, dr6
+        mov     [uDR6], rax
+#  else
+        mov     eax, dr6
+        mov     [uDR6], eax
+#  endif
+    }
+# endif
+    return uDR6;
+}
+#endif
+
+
+/**
+ * Reads and clears DR6.
+ *
+ * @returns DR6.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(RTCCUINTXREG) ASMGetAndClearDR6(void);
+#else
+DECLINLINE(RTCCUINTXREG) ASMGetAndClearDR6(void)
+{
+    RTCCUINTXREG uDR6;
+# if RT_INLINE_ASM_USES_INTRIN
+    uDR6 = __readdr(6);
+    __writedr(6, 0xffff0ff0U);          /* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */
+# elif RT_INLINE_ASM_GNU_STYLE
+    RTCCUINTXREG uNewValue = 0xffff0ff0U;/* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq   %%dr6, %0\n\t"
+                         "movq   %1, %%dr6\n\t"
+                         : "=r" (uDR6)
+                         : "r" (uNewValue));
+#  else
+    __asm__ __volatile__("movl   %%dr6, %0\n\t"
+                         "movl   %1, %%dr6\n\t"
+                         : "=r" (uDR6)
+                         : "r" (uNewValue));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, dr6
+        mov     [uDR6], rax
+        mov     rcx, rax
+        mov     ecx, 0ffff0ff0h;        /* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */
+        mov     dr6, rcx
+#  else
+        mov     eax, dr6
+        mov     [uDR6], eax
+        mov     ecx, 0ffff0ff0h;        /* 31-16 and 4-11 are 1's, 12 is zero. */
+        mov     dr6, ecx
+#  endif
+    }
+# endif
+    return uDR6;
+}
+#endif
+
+
+/**
+ * Gets dr7.
+ *
+ * @returns dr7.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(RTCCUINTXREG) ASMGetDR7(void);
+#else
+DECLINLINE(RTCCUINTXREG) ASMGetDR7(void)
+{
+    RTCCUINTXREG uDR7;
+# if RT_INLINE_ASM_USES_INTRIN
+    uDR7 = __readdr(7);
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq   %%dr7, %0\n\t" : "=r" (uDR7));
+#  else
+    __asm__ __volatile__("movl   %%dr7, %0\n\t" : "=r" (uDR7));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, dr7
+        mov     [uDR7], rax
+#  else
+        mov     eax, dr7
+        mov     [uDR7], eax
+#  endif
+    }
+# endif
+    return uDR7;
+}
+#endif
+
+
+/**
+ * Sets dr0.
+ *
+ * @param   uDRVal   Debug register value to write
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMSetDR0(RTCCUINTXREG uDRVal);
+#else
+DECLINLINE(void) ASMSetDR0(RTCCUINTXREG uDRVal)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    __writedr(0, uDRVal);
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq   %0, %%dr0\n\t" : : "r" (uDRVal));
+#  else
+    __asm__ __volatile__("movl   %0, %%dr0\n\t" : : "r" (uDRVal));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [uDRVal]
+        mov     dr0, rax
+#  else
+        mov     eax, [uDRVal]
+        mov     dr0, eax
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Sets dr1.
+ *
+ * @param   uDRVal   Debug register value to write
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMSetDR1(RTCCUINTXREG uDRVal);
+#else
+DECLINLINE(void) ASMSetDR1(RTCCUINTXREG uDRVal)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    __writedr(1, uDRVal);
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq   %0, %%dr1\n\t" : : "r" (uDRVal));
+#  else
+    __asm__ __volatile__("movl   %0, %%dr1\n\t" : : "r" (uDRVal));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [uDRVal]
+        mov     dr1, rax
+#  else
+        mov     eax, [uDRVal]
+        mov     dr1, eax
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Sets dr2.
+ *
+ * @param   uDRVal   Debug register value to write
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMSetDR2(RTCCUINTXREG uDRVal);
+#else
+DECLINLINE(void) ASMSetDR2(RTCCUINTXREG uDRVal)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    __writedr(2, uDRVal);
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq   %0, %%dr2\n\t" : : "r" (uDRVal));
+#  else
+    __asm__ __volatile__("movl   %0, %%dr2\n\t" : : "r" (uDRVal));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [uDRVal]
+        mov     dr2, rax
+#  else
+        mov     eax, [uDRVal]
+        mov     dr2, eax
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Sets dr3.
+ *
+ * @param   uDRVal   Debug register value to write
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMSetDR3(RTCCUINTXREG uDRVal);
+#else
+DECLINLINE(void) ASMSetDR3(RTCCUINTXREG uDRVal)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    __writedr(3, uDRVal);
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq   %0, %%dr3\n\t" : : "r" (uDRVal));
+#  else
+    __asm__ __volatile__("movl   %0, %%dr3\n\t" : : "r" (uDRVal));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [uDRVal]
+        mov     dr3, rax
+#  else
+        mov     eax, [uDRVal]
+        mov     dr3, eax
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Sets dr6.
+ *
+ * @param   uDRVal   Debug register value to write
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMSetDR6(RTCCUINTXREG uDRVal);
+#else
+DECLINLINE(void) ASMSetDR6(RTCCUINTXREG uDRVal)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    __writedr(6, uDRVal);
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq   %0, %%dr6\n\t" : : "r" (uDRVal));
+#  else
+    __asm__ __volatile__("movl   %0, %%dr6\n\t" : : "r" (uDRVal));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [uDRVal]
+        mov     dr6, rax
+#  else
+        mov     eax, [uDRVal]
+        mov     dr6, eax
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Sets dr7.
+ *
+ * @param   uDRVal   Debug register value to write
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMSetDR7(RTCCUINTXREG uDRVal);
+#else
+DECLINLINE(void) ASMSetDR7(RTCCUINTXREG uDRVal)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    __writedr(7, uDRVal);
+# elif RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("movq   %0, %%dr7\n\t" : : "r" (uDRVal));
+#  else
+    __asm__ __volatile__("movl   %0, %%dr7\n\t" : : "r" (uDRVal));
+#  endif
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [uDRVal]
+        mov     dr7, rax
+#  else
+        mov     eax, [uDRVal]
+        mov     dr7, eax
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Writes a 8-bit unsigned integer to an I/O port, ordered.
+ *
+ * @param   Port    I/O port to write to.
+ * @param   u8      8-bit integer to write.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMOutU8(RTIOPORT Port, uint8_t u8);
+#else
+DECLINLINE(void) ASMOutU8(RTIOPORT Port, uint8_t u8)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("outb %b1, %w0\n\t"
+                         :: "Nd" (Port),
+                            "a" (u8));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    __outbyte(Port, u8);
+
+# else
+    __asm
+    {
+        mov     dx, [Port]
+        mov     al, [u8]
+        out     dx, al
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Reads a 8-bit unsigned integer from an I/O port, ordered.
+ *
+ * @returns 8-bit integer.
+ * @param   Port    I/O port to read from.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint8_t) ASMInU8(RTIOPORT Port);
+#else
+DECLINLINE(uint8_t) ASMInU8(RTIOPORT Port)
+{
+    uint8_t u8;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("inb %w1, %b0\n\t"
+                         : "=a" (u8)
+                         : "Nd" (Port));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    u8 = __inbyte(Port);
+
+# else
+    __asm
+    {
+        mov     dx, [Port]
+        in      al, dx
+        mov     [u8], al
+    }
+# endif
+    return u8;
+}
+#endif
+
+
+/**
+ * Writes a 16-bit unsigned integer to an I/O port, ordered.
+ *
+ * @param   Port    I/O port to write to.
+ * @param   u16     16-bit integer to write.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMOutU16(RTIOPORT Port, uint16_t u16);
+#else
+DECLINLINE(void) ASMOutU16(RTIOPORT Port, uint16_t u16)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("outw %w1, %w0\n\t"
+                         :: "Nd" (Port),
+                            "a" (u16));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    __outword(Port, u16);
+
+# else
+    __asm
+    {
+        mov     dx, [Port]
+        mov     ax, [u16]
+        out     dx, ax
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Reads a 16-bit unsigned integer from an I/O port, ordered.
+ *
+ * @returns 16-bit integer.
+ * @param   Port    I/O port to read from.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint16_t) ASMInU16(RTIOPORT Port);
+#else
+DECLINLINE(uint16_t) ASMInU16(RTIOPORT Port)
+{
+    uint16_t u16;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("inw %w1, %w0\n\t"
+                         : "=a" (u16)
+                         : "Nd" (Port));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    u16 = __inword(Port);
+
+# else
+    __asm
+    {
+        mov     dx, [Port]
+        in      ax, dx
+        mov     [u16], ax
+    }
+# endif
+    return u16;
+}
+#endif
+
+
+/**
+ * Writes a 32-bit unsigned integer to an I/O port, ordered.
+ *
+ * @param   Port    I/O port to write to.
+ * @param   u32     32-bit integer to write.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMOutU32(RTIOPORT Port, uint32_t u32);
+#else
+DECLINLINE(void) ASMOutU32(RTIOPORT Port, uint32_t u32)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("outl %1, %w0\n\t"
+                         :: "Nd" (Port),
+                            "a" (u32));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    __outdword(Port, u32);
+
+# else
+    __asm
+    {
+        mov     dx, [Port]
+        mov     eax, [u32]
+        out     dx, eax
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Reads a 32-bit unsigned integer from an I/O port, ordered.
+ *
+ * @returns 32-bit integer.
+ * @param   Port    I/O port to read from.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint32_t) ASMInU32(RTIOPORT Port);
+#else
+DECLINLINE(uint32_t) ASMInU32(RTIOPORT Port)
+{
+    uint32_t u32;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("inl %w1, %0\n\t"
+                         : "=a" (u32)
+                         : "Nd" (Port));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    u32 = __indword(Port);
+
+# else
+    __asm
+    {
+        mov     dx, [Port]
+        in      eax, dx
+        mov     [u32], eax
+    }
+# endif
+    return u32;
+}
+#endif
+
+
+/**
+ * Writes a string of 8-bit unsigned integer items to an I/O port, ordered.
+ *
+ * @param   Port    I/O port to write to.
+ * @param   pau8    Pointer to the string buffer.
+ * @param   c       The number of items to write.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMOutStrU8(RTIOPORT Port, uint8_t const *pau8, size_t c);
+#else
+DECLINLINE(void) ASMOutStrU8(RTIOPORT Port, uint8_t const *pau8, size_t c)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("rep; outsb\n\t"
+                         : "+S" (pau8),
+                           "+c" (c)
+                         : "d" (Port));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    __outbytestring(Port, (unsigned char *)pau8, (unsigned long)c);
+
+# else
+    __asm
+    {
+        mov     dx, [Port]
+        mov     ecx, [c]
+        mov     eax, [pau8]
+        xchg    esi, eax
+        rep outsb
+        xchg    esi, eax
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Reads a string of 8-bit unsigned integer items from an I/O port, ordered.
+ *
+ * @param   Port    I/O port to read from.
+ * @param   pau8    Pointer to the string buffer (output).
+ * @param   c       The number of items to read.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMInStrU8(RTIOPORT Port, uint8_t *pau8, size_t c);
+#else
+DECLINLINE(void) ASMInStrU8(RTIOPORT Port, uint8_t *pau8, size_t c)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("rep; insb\n\t"
+                         : "+D" (pau8),
+                           "+c" (c)
+                         : "d" (Port));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    __inbytestring(Port, pau8, (unsigned long)c);
+
+# else
+    __asm
+    {
+        mov     dx, [Port]
+        mov     ecx, [c]
+        mov     eax, [pau8]
+        xchg    edi, eax
+        rep insb
+        xchg    edi, eax
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Writes a string of 16-bit unsigned integer items to an I/O port, ordered.
+ *
+ * @param   Port    I/O port to write to.
+ * @param   pau16   Pointer to the string buffer.
+ * @param   c       The number of items to write.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMOutStrU16(RTIOPORT Port, uint16_t const *pau16, size_t c);
+#else
+DECLINLINE(void) ASMOutStrU16(RTIOPORT Port, uint16_t const *pau16, size_t c)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("rep; outsw\n\t"
+                         : "+S" (pau16),
+                           "+c" (c)
+                         : "d" (Port));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    __outwordstring(Port, (unsigned short *)pau16, (unsigned long)c);
+
+# else
+    __asm
+    {
+        mov     dx, [Port]
+        mov     ecx, [c]
+        mov     eax, [pau16]
+        xchg    esi, eax
+        rep outsw
+        xchg    esi, eax
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Reads a string of 16-bit unsigned integer items from an I/O port, ordered.
+ *
+ * @param   Port    I/O port to read from.
+ * @param   pau16   Pointer to the string buffer (output).
+ * @param   c       The number of items to read.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMInStrU16(RTIOPORT Port, uint16_t *pau16, size_t c);
+#else
+DECLINLINE(void) ASMInStrU16(RTIOPORT Port, uint16_t *pau16, size_t c)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("rep; insw\n\t"
+                         : "+D" (pau16),
+                           "+c" (c)
+                         : "d" (Port));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    __inwordstring(Port, pau16, (unsigned long)c);
+
+# else
+    __asm
+    {
+        mov     dx, [Port]
+        mov     ecx, [c]
+        mov     eax, [pau16]
+        xchg    edi, eax
+        rep insw
+        xchg    edi, eax
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Writes a string of 32-bit unsigned integer items to an I/O port, ordered.
+ *
+ * @param   Port    I/O port to write to.
+ * @param   pau32   Pointer to the string buffer.
+ * @param   c       The number of items to write.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMOutStrU32(RTIOPORT Port, uint32_t const *pau32, size_t c);
+#else
+DECLINLINE(void) ASMOutStrU32(RTIOPORT Port, uint32_t const *pau32, size_t c)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("rep; outsl\n\t"
+                         : "+S" (pau32),
+                           "+c" (c)
+                         : "d" (Port));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    __outdwordstring(Port, (unsigned long *)pau32, (unsigned long)c);
+
+# else
+    __asm
+    {
+        mov     dx, [Port]
+        mov     ecx, [c]
+        mov     eax, [pau32]
+        xchg    esi, eax
+        rep outsd
+        xchg    esi, eax
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Reads a string of 32-bit unsigned integer items from an I/O port, ordered.
+ *
+ * @param   Port    I/O port to read from.
+ * @param   pau32   Pointer to the string buffer (output).
+ * @param   c       The number of items to read.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMInStrU32(RTIOPORT Port, uint32_t *pau32, size_t c);
+#else
+DECLINLINE(void) ASMInStrU32(RTIOPORT Port, uint32_t *pau32, size_t c)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("rep; insl\n\t"
+                         : "+D" (pau32),
+                           "+c" (c)
+                         : "d" (Port));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    __indwordstring(Port, (unsigned long *)pau32, (unsigned long)c);
+
+# else
+    __asm
+    {
+        mov     dx, [Port]
+        mov     ecx, [c]
+        mov     eax, [pau32]
+        xchg    edi, eax
+        rep insd
+        xchg    edi, eax
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Invalidate page.
+ *
+ * @param   uPtr    Address of the page to invalidate.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMInvalidatePage(RTCCUINTXREG uPtr);
+#else
+DECLINLINE(void) ASMInvalidatePage(RTCCUINTXREG uPtr)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    __invlpg((void *)uPtr);
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("invlpg %0\n\t"
+                         : : "m" (*(uint8_t *)(uintptr_t)uPtr));
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [uPtr]
+        invlpg  [rax]
+#  else
+        mov     eax, [uPtr]
+        invlpg  [eax]
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Write back the internal caches and invalidate them.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMWriteBackAndInvalidateCaches(void);
+#else
+DECLINLINE(void) ASMWriteBackAndInvalidateCaches(void)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    __wbinvd();
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("wbinvd");
+# else
+    __asm
+    {
+        wbinvd
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Invalidate internal and (perhaps) external caches without first
+ * flushing dirty cache lines. Use with extreme care.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMInvalidateInternalCaches(void);
+#else
+DECLINLINE(void) ASMInvalidateInternalCaches(void)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("invd");
+# else
+    __asm
+    {
+        invd
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Memory load/store fence, waits for any pending writes and reads to complete.
+ * Requires the X86_CPUID_FEATURE_EDX_SSE2 CPUID bit set.
+ */
+DECLINLINE(void) ASMMemoryFenceSSE2(void)
+{
+#if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__ (".byte 0x0f,0xae,0xf0\n\t");
+#elif RT_INLINE_ASM_USES_INTRIN
+    _mm_mfence();
+#else
+    __asm
+    {
+        _emit   0x0f
+        _emit   0xae
+        _emit   0xf0
+    }
+#endif
+}
+
+
+/**
+ * Memory store fence, waits for any writes to complete.
+ * Requires the X86_CPUID_FEATURE_EDX_SSE CPUID bit set.
+ */
+DECLINLINE(void) ASMWriteFenceSSE(void)
+{
+#if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__ (".byte 0x0f,0xae,0xf8\n\t");
+#elif RT_INLINE_ASM_USES_INTRIN
+    _mm_sfence();
+#else
+    __asm
+    {
+        _emit   0x0f
+        _emit   0xae
+        _emit   0xf8
+    }
+#endif
+}
+
+
+/**
+ * Memory load fence, waits for any pending reads to complete.
+ * Requires the X86_CPUID_FEATURE_EDX_SSE2 CPUID bit set.
+ */
+DECLINLINE(void) ASMReadFenceSSE2(void)
+{
+#if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__ (".byte 0x0f,0xae,0xe8\n\t");
+#elif RT_INLINE_ASM_USES_INTRIN
+    _mm_lfence();
+#else
+    __asm
+    {
+        _emit   0x0f
+        _emit   0xae
+        _emit   0xe8
+    }
+#endif
+}
+
+#if !defined(_MSC_VER) || !defined(RT_ARCH_AMD64)
+
+/*
+ * Clear the AC bit in the EFLAGS register.
+ * Requires the X86_CPUID_STEXT_FEATURE_EBX_SMAP CPUID bit set.
+ * Requires to be executed in R0.
+ */
+DECLINLINE(void) ASMClearAC(void)
+{
+#if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__ (".byte 0x0f,0x01,0xca\n\t");
+#else
+    __asm
+    {
+        _emit   0x0f
+        _emit   0x01
+        _emit   0xca
+    }
+#endif
+}
+
+
+/*
+ * Set the AC bit in the EFLAGS register.
+ * Requires the X86_CPUID_STEXT_FEATURE_EBX_SMAP CPUID bit set.
+ * Requires to be executed in R0.
+ */
+DECLINLINE(void) ASMSetAC(void)
+{
+#if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__ (".byte 0x0f,0x01,0xcb\n\t");
+#else
+    __asm
+    {
+        _emit   0x0f
+        _emit   0x01
+        _emit   0xcb
+    }
+#endif
+}
+
+#endif /* !_MSC_VER) || !RT_ARCH_AMD64 */
+
+/** @} */
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/asm-math.h b/ubuntu/vbox/include/iprt/asm-math.h
new file mode 100644 (file)
index 0000000..bda7934
--- /dev/null
@@ -0,0 +1,438 @@
+/** @file
+ * IPRT - Assembly Routines for Optimizing some Integers Math Operations.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_asm_math_h
+#define ___iprt_asm_math_h
+
+#include <iprt/types.h>
+
+#if defined(_MSC_VER) && RT_INLINE_ASM_USES_INTRIN
+# pragma warning(push)
+# pragma warning(disable:4668) /* Several incorrect __cplusplus uses. */
+# pragma warning(disable:4255) /* Incorrect __slwpcb prototype. */
+# include <intrin.h>
+# pragma warning(pop)
+  /* Emit the intrinsics at all optimization levels. */
+# pragma intrinsic(__emul)
+# pragma intrinsic(__emulu)
+# ifdef RT_ARCH_AMD64
+#  pragma intrinsic(_mul128)
+#  pragma intrinsic(_umul128)
+# endif
+#endif
+
+
+/** @defgroup grp_rt_asm_math   Interger Math Optimizations
+ * @ingroup grp_rt_asm
+ * @{ */
+
+/**
+ * Multiplies two unsigned 32-bit values returning an unsigned 64-bit result.
+ *
+ * @returns u32F1 * u32F2.
+ */
+
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_X86)
+DECLASM(uint64_t) ASMMult2xU32RetU64(uint32_t u32F1, uint32_t u32F2);
+#else
+DECLINLINE(uint64_t) ASMMult2xU32RetU64(uint32_t u32F1, uint32_t u32F2)
+{
+# ifdef RT_ARCH_X86
+    uint64_t u64;
+#  if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("mull %%edx"
+                         : "=A" (u64)
+                         : "a" (u32F2), "d" (u32F1));
+#  elif RT_INLINE_ASM_USES_INTRIN
+    u64 = __emulu(u32F1, u32F2);
+#  else
+    __asm
+    {
+        mov     edx, [u32F1]
+        mov     eax, [u32F2]
+        mul     edx
+        mov     dword ptr [u64], eax
+        mov     dword ptr [u64 + 4], edx
+    }
+#  endif
+    return u64;
+# else  /* generic: */
+    return (uint64_t)u32F1 * u32F2;
+# endif
+}
+#endif
+
+
+/**
+ * Multiplies two signed 32-bit values returning a signed 64-bit result.
+ *
+ * @returns u32F1 * u32F2.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_X86)
+DECLASM(int64_t) ASMMult2xS32RetS64(int32_t i32F1, int32_t i32F2);
+#else
+DECLINLINE(int64_t) ASMMult2xS32RetS64(int32_t i32F1, int32_t i32F2)
+{
+# ifdef RT_ARCH_X86
+    int64_t i64;
+#  if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("imull %%edx"
+                         : "=A" (i64)
+                         : "a" (i32F2), "d" (i32F1));
+#  elif RT_INLINE_ASM_USES_INTRIN
+    i64 = __emul(i32F1, i32F2);
+#  else
+    __asm
+    {
+        mov     edx, [i32F1]
+        mov     eax, [i32F2]
+        imul    edx
+        mov     dword ptr [i64], eax
+        mov     dword ptr [i64 + 4], edx
+    }
+#  endif
+    return i64;
+# else  /* generic: */
+    return (int64_t)i32F1 * i32F2;
+# endif
+}
+#endif
+
+
+#if ARCH_BITS == 64
+DECLINLINE(uint64_t) ASMMult2xU64Ret2xU64(uint64_t u64F1, uint64_t u64F2, uint64_t *pu64ProdHi)
+{
+# if defined(RT_ARCH_AMD64) && (RT_INLINE_ASM_GNU_STYLE || RT_INLINE_ASM_USES_INTRIN)
+#  if RT_INLINE_ASM_GNU_STYLE
+    uint64_t u64Low, u64High;
+    __asm__ __volatile__("mulq %%rdx"
+                         : "=a" (u64Low), "=d" (u64High)
+                         : "0" (u64F1), "1" (u64F2));
+    *pu64ProdHi = u64High;
+    return u64Low;
+#  elif RT_INLINE_ASM_USES_INTRIN
+    return _umul128(u64F1, u64F2, pu64ProdHi);
+#  else
+#   error "hmm"
+#  endif
+# else  /* generic: */
+    /*
+     *   F1 * F2 = Prod
+     *   --   --
+     *   ab * cd =  b*d + a*d*10  +  b*c*10 + a*c*100
+     *
+     * Where a, b, c and d are 'digits', and 10 is max digit + 1.
+     *
+     * Our digits are 32-bit wide, so instead of 10 we multiply by 4G.
+     *  Prod = F1.s.Lo*F2.s.Lo    + F1.s.Hi*F2.s.Lo*4G
+     *       + F1.s.Lo*F2.s.Hi*4G + F1.s.Hi*F2.s.Hi*4G*4G
+     */
+    RTUINT128U Prod;
+    RTUINT64U  Tmp1;
+    uint64_t   u64Tmp;
+    RTUINT64U  F1, F2;
+    F1.u = u64F1;
+    F2.u = u64F2;
+
+    Prod.s.Lo = ASMMult2xU32RetU64(F1.s.Lo, F2.s.Lo);
+
+    Tmp1.u = ASMMult2xU32RetU64(F1.s.Hi, F2.s.Lo);
+    u64Tmp = (uint64_t)Prod.DWords.dw1 + Tmp1.s.Lo;
+    Prod.DWords.dw1 = (uint32_t)u64Tmp;
+    Prod.s.Hi = Tmp1.s.Hi;
+    Prod.s.Hi += u64Tmp >> 32; /* carry */
+
+    Tmp1.u = ASMMult2xU32RetU64(F1.s.Lo, F2.s.Hi);
+    u64Tmp = (uint64_t)Prod.DWords.dw1 + Tmp1.s.Lo;
+    Prod.DWords.dw1 = (uint32_t)u64Tmp;
+    u64Tmp >>= 32;      /* carry */
+    u64Tmp += Prod.DWords.dw2;
+    u64Tmp += Tmp1.s.Hi;
+    Prod.DWords.dw2 = (uint32_t)u64Tmp;
+    Prod.DWords.dw3 += u64Tmp >> 32; /* carry */
+
+    Prod.s.Hi += ASMMult2xU32RetU64(F1.s.Hi, F2.s.Hi);
+    *pu64ProdHi  = Prod.s.Hi;
+    return Prod.s.Lo;
+# endif
+}
+#endif
+
+
+
+/**
+ * Divides a 64-bit unsigned by a 32-bit unsigned returning an unsigned 32-bit result.
+ *
+ * @returns u64 / u32.
+ */
+#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86)
+DECLASM(uint32_t) ASMDivU64ByU32RetU32(uint64_t u64, uint32_t u32);
+#else
+DECLINLINE(uint32_t) ASMDivU64ByU32RetU32(uint64_t u64, uint32_t u32)
+{
+# ifdef RT_ARCH_X86
+#  if RT_INLINE_ASM_GNU_STYLE
+    RTCCUINTREG uDummy;
+    __asm__ __volatile__("divl %3"
+                         : "=a" (u32), "=d"(uDummy)
+                         : "A" (u64), "r" (u32));
+#  else
+    __asm
+    {
+        mov     eax, dword ptr [u64]
+        mov     edx, dword ptr [u64 + 4]
+        mov     ecx, [u32]
+        div     ecx
+        mov     [u32], eax
+    }
+#  endif
+    return u32;
+# else   /* generic: */
+    return (uint32_t)(u64 / u32);
+# endif
+}
+#endif
+
+
+/**
+ * Divides a 64-bit signed by a 32-bit signed returning a signed 32-bit result.
+ *
+ * @returns u64 / u32.
+ */
+#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86)
+DECLASM(int32_t) ASMDivS64ByS32RetS32(int64_t i64, int32_t i32);
+#else
+DECLINLINE(int32_t) ASMDivS64ByS32RetS32(int64_t i64, int32_t i32)
+{
+# ifdef RT_ARCH_X86
+#  if RT_INLINE_ASM_GNU_STYLE
+    RTCCUINTREG iDummy;
+    __asm__ __volatile__("idivl %3"
+                         : "=a" (i32), "=d"(iDummy)
+                         : "A" (i64), "r" (i32));
+#  else
+    __asm
+    {
+        mov     eax, dword ptr [i64]
+        mov     edx, dword ptr [i64 + 4]
+        mov     ecx, [i32]
+        idiv    ecx
+        mov     [i32], eax
+    }
+#  endif
+    return i32;
+# else  /* generic: */
+    return (int32_t)(i64 / i32);
+# endif
+}
+#endif
+
+
+/**
+ * Performs 64-bit unsigned by a 32-bit unsigned division with a 32-bit unsigned result,
+ * returning the rest.
+ *
+ * @returns u64 % u32.
+ *
+ * @remarks It is important that the result is <= UINT32_MAX or we'll overflow and crash.
+ */
+#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86)
+DECLASM(uint32_t) ASMModU64ByU32RetU32(uint64_t u64, uint32_t u32);
+#else
+DECLINLINE(uint32_t) ASMModU64ByU32RetU32(uint64_t u64, uint32_t u32)
+{
+# ifdef RT_ARCH_X86
+#  if RT_INLINE_ASM_GNU_STYLE
+    RTCCUINTREG uDummy;
+    __asm__ __volatile__("divl %3"
+                         : "=a" (uDummy), "=d"(u32)
+                         : "A" (u64), "r" (u32));
+#  else
+    __asm
+    {
+        mov     eax, dword ptr [u64]
+        mov     edx, dword ptr [u64 + 4]
+        mov     ecx, [u32]
+        div     ecx
+        mov     [u32], edx
+    }
+#  endif
+    return u32;
+# else  /* generic: */
+    return (uint32_t)(u64 % u32);
+# endif
+}
+#endif
+
+
+/**
+ * Performs 64-bit signed by a 32-bit signed division with a 32-bit signed result,
+ * returning the rest.
+ *
+ * @returns u64 % u32.
+ *
+ * @remarks It is important that the result is <= UINT32_MAX or we'll overflow and crash.
+ */
+#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86)
+DECLASM(int32_t) ASMModS64ByS32RetS32(int64_t i64, int32_t i32);
+#else
+DECLINLINE(int32_t) ASMModS64ByS32RetS32(int64_t i64, int32_t i32)
+{
+# ifdef RT_ARCH_X86
+#  if RT_INLINE_ASM_GNU_STYLE
+    RTCCUINTREG iDummy;
+    __asm__ __volatile__("idivl %3"
+                         : "=a" (iDummy), "=d"(i32)
+                         : "A" (i64), "r" (i32));
+#  else
+    __asm
+    {
+        mov     eax, dword ptr [i64]
+        mov     edx, dword ptr [i64 + 4]
+        mov     ecx, [i32]
+        idiv    ecx
+        mov     [i32], edx
+    }
+#  endif
+    return i32;
+# else  /* generic: */
+    return (int32_t)(i64 % i32);
+# endif
+}
+#endif
+
+
+/**
+ * Multiple a 32-bit by a 32-bit integer and divide the result by a 32-bit integer
+ * using a 64 bit intermediate result.
+ *
+ * @returns (u32A * u32B) / u32C.
+ * @param   u32A    The 32-bit value (A).
+ * @param   u32B    The 32-bit value to multiple by A.
+ * @param   u32C    The 32-bit value to divide A*B by.
+ *
+ * @remarks Architecture specific.
+ * @remarks Make sure the result won't ever exceed 32-bit, because hardware
+ *          exception may be raised if it does.
+ * @remarks On x86 this may be used to avoid dragging in 64-bit builtin
+ *          arithmetics functions.
+ */
+#if RT_INLINE_ASM_EXTERNAL && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
+DECLASM(uint32_t) ASMMultU32ByU32DivByU32(uint32_t u32A, uint32_t u32B, uint32_t u32C);
+#else
+DECLINLINE(uint32_t) ASMMultU32ByU32DivByU32(uint32_t u32A, uint32_t u32B, uint32_t u32C)
+{
+# if RT_INLINE_ASM_GNU_STYLE && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
+    uint32_t u32Result, u32Spill;
+    __asm__ __volatile__("mull %2\n\t"
+                         "divl %3\n\t"
+                         : "=&a" (u32Result),
+                           "=&d" (u32Spill)
+                         : "r" (u32B),
+                           "r" (u32C),
+                           "0" (u32A));
+    return u32Result;
+# else
+    return (uint32_t)(((uint64_t)u32A * u32B) / u32C);
+# endif
+}
+#endif
+
+
+/**
+ * Multiple a 64-bit by a 32-bit integer and divide the result by a 32-bit integer
+ * using a 96 bit intermediate result.
+ *
+ * @returns (u64A * u32B) / u32C.
+ * @param   u64A    The 64-bit value.
+ * @param   u32B    The 32-bit value to multiple by A.
+ * @param   u32C    The 32-bit value to divide A*B by.
+ *
+ * @remarks Architecture specific.
+ * @remarks Make sure the result won't ever exceed 64-bit, because hardware
+ *          exception may be raised if it does.
+ * @remarks On x86 this may be used to avoid dragging in 64-bit builtin
+ *          arithmetics function.
+ */
+#if RT_INLINE_ASM_EXTERNAL || !defined(__GNUC__) || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86))
+DECLASM(uint64_t) ASMMultU64ByU32DivByU32(uint64_t u64A, uint32_t u32B, uint32_t u32C);
+#else
+DECLINLINE(uint64_t) ASMMultU64ByU32DivByU32(uint64_t u64A, uint32_t u32B, uint32_t u32C)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    uint64_t u64Result, u64Spill;
+    __asm__ __volatile__("mulq %2\n\t"
+                         "divq %3\n\t"
+                         : "=&a" (u64Result),
+                           "=&d" (u64Spill)
+                         : "r" ((uint64_t)u32B),
+                           "r" ((uint64_t)u32C),
+                           "0" (u64A));
+    return u64Result;
+#  else
+    uint32_t u32Dummy;
+    uint64_t u64Result;
+    __asm__ __volatile__("mull %%ecx       \n\t" /* eax = u64Lo.lo = (u64A.lo * u32B).lo
+                                                    edx = u64Lo.hi = (u64A.lo * u32B).hi */
+                         "xchg %%eax,%%esi \n\t" /* esi = u64Lo.lo
+                                                    eax = u64A.hi */
+                         "xchg %%edx,%%edi \n\t" /* edi = u64Low.hi
+                                                    edx = u32C */
+                         "xchg %%edx,%%ecx \n\t" /* ecx = u32C
+                                                    edx = u32B */
+                         "mull %%edx       \n\t" /* eax = u64Hi.lo = (u64A.hi * u32B).lo
+                                                    edx = u64Hi.hi = (u64A.hi * u32B).hi */
+                         "addl %%edi,%%eax \n\t" /* u64Hi.lo += u64Lo.hi */
+                         "adcl $0,%%edx    \n\t" /* u64Hi.hi += carry */
+                         "divl %%ecx       \n\t" /* eax = u64Hi / u32C
+                                                    edx = u64Hi % u32C */
+                         "movl %%eax,%%edi \n\t" /* edi = u64Result.hi = u64Hi / u32C */
+                         "movl %%esi,%%eax \n\t" /* eax = u64Lo.lo */
+                         "divl %%ecx       \n\t" /* u64Result.lo */
+                         "movl %%edi,%%edx \n\t" /* u64Result.hi */
+                         : "=A"(u64Result), "=c"(u32Dummy),
+                           "=S"(u32Dummy), "=D"(u32Dummy)
+                         : "a"((uint32_t)u64A),
+                           "S"((uint32_t)(u64A >> 32)),
+                           "c"(u32B),
+                           "D"(u32C));
+    return u64Result;
+#  endif
+# else
+    RTUINT64U   u;
+    uint64_t    u64Lo = (uint64_t)(u64A & 0xffffffff) * u32B;
+    uint64_t    u64Hi = (uint64_t)(u64A >> 32)        * u32B;
+    u64Hi  += (u64Lo >> 32);
+    u.s.Hi = (uint32_t)(u64Hi / u32C);
+    u.s.Lo = (uint32_t)((((u64Hi % u32C) << 32) + (u64Lo & 0xffffffff)) / u32C);
+    return u.u;
+# endif
+}
+#endif
+
+/** @} */
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/asm.h b/ubuntu/vbox/include/iprt/asm.h
new file mode 100644 (file)
index 0000000..75f24b9
--- /dev/null
@@ -0,0 +1,5598 @@
+/** @file
+ * IPRT - Assembly Functions.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_asm_h
+#define ___iprt_asm_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/assert.h>
+/** @def RT_INLINE_ASM_USES_INTRIN
+ * Defined as 1 if we're using a _MSC_VER 1400.
+ * Otherwise defined as 0.
+ */
+
+/* Solaris 10 header ugliness */
+#ifdef u
+# undef u
+#endif
+
+#if defined(_MSC_VER) && RT_INLINE_ASM_USES_INTRIN
+# pragma warning(push)
+# pragma warning(disable:4668) /* Several incorrect __cplusplus uses. */
+# pragma warning(disable:4255) /* Incorrect __slwpcb prototype. */
+# include <intrin.h>
+# pragma warning(pop)
+  /* Emit the intrinsics at all optimization levels. */
+# pragma intrinsic(_ReadWriteBarrier)
+# pragma intrinsic(__cpuid)
+# pragma intrinsic(__stosd)
+# pragma intrinsic(__stosw)
+# pragma intrinsic(__stosb)
+# pragma intrinsic(_BitScanForward)
+# pragma intrinsic(_BitScanReverse)
+# pragma intrinsic(_bittest)
+# pragma intrinsic(_bittestandset)
+# pragma intrinsic(_bittestandreset)
+# pragma intrinsic(_bittestandcomplement)
+# pragma intrinsic(_byteswap_ushort)
+# pragma intrinsic(_byteswap_ulong)
+# pragma intrinsic(_interlockedbittestandset)
+# pragma intrinsic(_interlockedbittestandreset)
+# pragma intrinsic(_InterlockedAnd)
+# pragma intrinsic(_InterlockedOr)
+# pragma intrinsic(_InterlockedIncrement)
+# pragma intrinsic(_InterlockedDecrement)
+# pragma intrinsic(_InterlockedExchange)
+# pragma intrinsic(_InterlockedExchangeAdd)
+# pragma intrinsic(_InterlockedCompareExchange)
+# pragma intrinsic(_InterlockedCompareExchange64)
+# pragma intrinsic(_rotl)
+# pragma intrinsic(_rotr)
+# pragma intrinsic(_rotl64)
+# pragma intrinsic(_rotr64)
+# ifdef RT_ARCH_AMD64
+#  pragma intrinsic(__stosq)
+#  pragma intrinsic(_byteswap_uint64)
+#  pragma intrinsic(_InterlockedExchange64)
+#  pragma intrinsic(_InterlockedExchangeAdd64)
+#  pragma intrinsic(_InterlockedAnd64)
+#  pragma intrinsic(_InterlockedOr64)
+#  pragma intrinsic(_InterlockedIncrement64)
+#  pragma intrinsic(_InterlockedDecrement64)
+# endif
+#endif
+
+/*
+ * Include #pragma aux definitions for Watcom C/C++.
+ */
+#if defined(__WATCOMC__) && ARCH_BITS == 16 && defined(RT_ARCH_X86)
+# include "asm-watcom-x86-16.h"
+#elif defined(__WATCOMC__) && ARCH_BITS == 32 && defined(RT_ARCH_X86)
+# include "asm-watcom-x86-32.h"
+#endif
+
+
+
+/** @defgroup grp_rt_asm    ASM - Assembly Routines
+ * @ingroup grp_rt
+ *
+ * @remarks The difference between ordered and unordered atomic operations are that
+ *          the former will complete outstanding reads and writes before continuing
+ *          while the latter doesn't make any promises about the order. Ordered
+ *          operations doesn't, it seems, make any 100% promise wrt to whether
+ *          the operation will complete before any subsequent memory access.
+ *          (please, correct if wrong.)
+ *
+ *          ASMAtomicSomething operations are all ordered, while ASMAtomicUoSomething
+ *          are unordered (note the Uo).
+ *
+ * @remarks Some remarks about __volatile__: Without this keyword gcc is allowed to reorder
+ *          or even optimize assembler instructions away. For instance, in the following code
+ *          the second rdmsr instruction is optimized away because gcc treats that instruction
+ *          as deterministic:
+ *
+ *            @code
+ *            static inline uint64_t rdmsr_low(int idx)
+ *            {
+ *              uint32_t low;
+ *              __asm__ ("rdmsr" : "=a"(low) : "c"(idx) : "edx");
+ *            }
+ *            ...
+ *            uint32_t msr1 = rdmsr_low(1);
+ *            foo(msr1);
+ *            msr1 = rdmsr_low(1);
+ *            bar(msr1);
+ *            @endcode
+ *
+ *          The input parameter of rdmsr_low is the same for both calls and therefore gcc will
+ *          use the result of the first call as input parameter for bar() as well. For rdmsr this
+ *          is not acceptable as this instruction is _not_ deterministic. This applies to reading
+ *          machine status information in general.
+ *
+ * @{
+ */
+
+
+/** @def RT_INLINE_ASM_GCC_4_3_X_X86
+ * Used to work around some 4.3.x register allocation issues in this version of
+ * the compiler. So far this workaround is still required for 4.4 and 4.5 but
+ * definitely not for 5.x */
+#if (RT_GNUC_PREREQ(4, 3) && !RT_GNUC_PREREQ(5, 0) && defined(__i386__))
+# define RT_INLINE_ASM_GCC_4_3_X_X86 1
+#else
+# define RT_INLINE_ASM_GCC_4_3_X_X86 0
+#endif
+
+/** @def RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC
+ * i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5493) screws up
+ * RTSemRWRequestWrite semsemrw-lockless-generic.cpp in release builds. PIC
+ * mode, x86.
+ *
+ * Some gcc 4.3.x versions may have register allocation issues with cmpxchg8b
+ * when in PIC mode on x86.
+ */
+#ifndef RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC
+# if defined(DOXYGEN_RUNNING) || defined(__WATCOMC__) /* Watcom has trouble with the expression below */
+#  define RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC 1
+# elif defined(_MSC_VER) /* Visual C++ has trouble too, but it'll only tell us when C4688 is enabled. */
+#  define RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC 0
+# elif (   (defined(PIC) || defined(__PIC__)) \
+        && defined(RT_ARCH_X86) \
+        && (   RT_INLINE_ASM_GCC_4_3_X_X86 \
+            || defined(RT_OS_DARWIN)) )
+#  define RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC 1
+# else
+#  define RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC 0
+# endif
+#endif
+
+
+/** @def ASMReturnAddress
+ * Gets the return address of the current (or calling if you like) function or method.
+ */
+#ifdef _MSC_VER
+# ifdef __cplusplus
+extern "C"
+# endif
+void * _ReturnAddress(void);
+# pragma intrinsic(_ReturnAddress)
+# define ASMReturnAddress() _ReturnAddress()
+#elif defined(__GNUC__) || defined(DOXYGEN_RUNNING)
+# define ASMReturnAddress() __builtin_return_address(0)
+#elif defined(__WATCOMC__)
+# define ASMReturnAddress() Watcom_does_not_appear_to_have_intrinsic_return_address_function()
+#else
+# error "Unsupported compiler."
+#endif
+
+
+/**
+ * Compiler memory barrier.
+ *
+ * Ensure that the compiler does not use any cached (register/tmp stack) memory
+ * values or any outstanding writes when returning from this function.
+ *
+ * This function must be used if non-volatile data is modified by a
+ * device or the VMM. Typical cases are port access, MMIO access,
+ * trapping instruction, etc.
+ */
+#if RT_INLINE_ASM_GNU_STYLE
+# define ASMCompilerBarrier()   do { __asm__ __volatile__("" : : : "memory"); } while (0)
+#elif RT_INLINE_ASM_USES_INTRIN
+# define ASMCompilerBarrier()   do { _ReadWriteBarrier(); } while (0)
+#elif defined(__WATCOMC__)
+void ASMCompilerBarrier(void);
+#else /* 2003 should have _ReadWriteBarrier() but I guess we're at 2002 level then... */
+DECLINLINE(void) ASMCompilerBarrier(void)
+{
+    __asm
+    {
+    }
+}
+#endif
+
+
+/** @def ASMBreakpoint
+ * Debugger Breakpoint.
+ * @deprecated Use RT_BREAKPOINT instead.
+ * @internal
+ */
+#define ASMBreakpoint() RT_BREAKPOINT()
+
+
+/**
+ * Spinloop hint for platforms that have these, empty function on the other
+ * platforms.
+ *
+ * x86 & AMD64: The PAUSE variant of NOP for helping hyperthreaded CPUs detecting
+ * spin locks.
+ */
+#if RT_INLINE_ASM_EXTERNAL && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
+DECLASM(void) ASMNopPause(void);
+#else
+DECLINLINE(void) ASMNopPause(void)
+{
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+#  if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__(".byte 0xf3,0x90\n\t");
+#  else
+    __asm {
+        _emit 0f3h
+        _emit 090h
+    }
+#  endif
+# else
+    /* dummy */
+# endif
+}
+#endif
+
+
+/**
+ * Atomically Exchange an unsigned 8-bit value, ordered.
+ *
+ * @returns Current *pu8 value
+ * @param   pu8    Pointer to the 8-bit variable to update.
+ * @param   u8     The 8-bit value to assign to *pu8.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(uint8_t) ASMAtomicXchgU8(volatile uint8_t *pu8, uint8_t u8);
+#else
+DECLINLINE(uint8_t) ASMAtomicXchgU8(volatile uint8_t *pu8, uint8_t u8)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("xchgb %0, %1\n\t"
+                         : "=m" (*pu8),
+                           "=q" (u8) /* =r - busted on g++ (GCC) 3.4.4 20050721 (Red Hat 3.4.4-2) */
+                         : "1" (u8),
+                           "m" (*pu8));
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [pu8]
+        mov     al, [u8]
+        xchg    [rdx], al
+        mov     [u8], al
+#  else
+        mov     edx, [pu8]
+        mov     al, [u8]
+        xchg    [edx], al
+        mov     [u8], al
+#  endif
+    }
+# endif
+    return u8;
+}
+#endif
+
+
+/**
+ * Atomically Exchange a signed 8-bit value, ordered.
+ *
+ * @returns Current *pu8 value
+ * @param   pi8     Pointer to the 8-bit variable to update.
+ * @param   i8      The 8-bit value to assign to *pi8.
+ */
+DECLINLINE(int8_t) ASMAtomicXchgS8(volatile int8_t *pi8, int8_t i8)
+{
+    return (int8_t)ASMAtomicXchgU8((volatile uint8_t *)pi8, (uint8_t)i8);
+}
+
+
+/**
+ * Atomically Exchange a bool value, ordered.
+ *
+ * @returns Current *pf value
+ * @param   pf      Pointer to the 8-bit variable to update.
+ * @param   f       The 8-bit value to assign to *pi8.
+ */
+DECLINLINE(bool) ASMAtomicXchgBool(volatile bool *pf, bool f)
+{
+#ifdef _MSC_VER
+    return !!ASMAtomicXchgU8((volatile uint8_t *)pf, (uint8_t)f);
+#else
+    return (bool)ASMAtomicXchgU8((volatile uint8_t *)pf, (uint8_t)f);
+#endif
+}
+
+
+/**
+ * Atomically Exchange an unsigned 16-bit value, ordered.
+ *
+ * @returns Current *pu16 value
+ * @param   pu16    Pointer to the 16-bit variable to update.
+ * @param   u16     The 16-bit value to assign to *pu16.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(uint16_t) ASMAtomicXchgU16(volatile uint16_t *pu16, uint16_t u16);
+#else
+DECLINLINE(uint16_t) ASMAtomicXchgU16(volatile uint16_t *pu16, uint16_t u16)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("xchgw %0, %1\n\t"
+                         : "=m" (*pu16),
+                           "=r" (u16)
+                         : "1" (u16),
+                           "m" (*pu16));
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [pu16]
+        mov     ax, [u16]
+        xchg    [rdx], ax
+        mov     [u16], ax
+#  else
+        mov     edx, [pu16]
+        mov     ax, [u16]
+        xchg    [edx], ax
+        mov     [u16], ax
+#  endif
+    }
+# endif
+    return u16;
+}
+#endif
+
+
+/**
+ * Atomically Exchange a signed 16-bit value, ordered.
+ *
+ * @returns Current *pu16 value
+ * @param   pi16    Pointer to the 16-bit variable to update.
+ * @param   i16     The 16-bit value to assign to *pi16.
+ */
+DECLINLINE(int16_t) ASMAtomicXchgS16(volatile int16_t *pi16, int16_t i16)
+{
+    return (int16_t)ASMAtomicXchgU16((volatile uint16_t *)pi16, (uint16_t)i16);
+}
+
+
+/**
+ * Atomically Exchange an unsigned 32-bit value, ordered.
+ *
+ * @returns Current *pu32 value
+ * @param   pu32    Pointer to the 32-bit variable to update.
+ * @param   u32     The 32-bit value to assign to *pu32.
+ *
+ * @remarks Does not work on 286 and earlier.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint32_t) ASMAtomicXchgU32(volatile uint32_t *pu32, uint32_t u32);
+#else
+DECLINLINE(uint32_t) ASMAtomicXchgU32(volatile uint32_t *pu32, uint32_t u32)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("xchgl %0, %1\n\t"
+                         : "=m" (*pu32),
+                           "=r" (u32)
+                         : "1" (u32),
+                           "m" (*pu32));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+   u32 = _InterlockedExchange((long *)pu32, u32);
+
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [pu32]
+        mov     eax, u32
+        xchg    [rdx], eax
+        mov     [u32], eax
+#  else
+        mov     edx, [pu32]
+        mov     eax, u32
+        xchg    [edx], eax
+        mov     [u32], eax
+#  endif
+    }
+# endif
+    return u32;
+}
+#endif
+
+
+/**
+ * Atomically Exchange a signed 32-bit value, ordered.
+ *
+ * @returns Current *pu32 value
+ * @param   pi32    Pointer to the 32-bit variable to update.
+ * @param   i32     The 32-bit value to assign to *pi32.
+ */
+DECLINLINE(int32_t) ASMAtomicXchgS32(volatile int32_t *pi32, int32_t i32)
+{
+    return (int32_t)ASMAtomicXchgU32((volatile uint32_t *)pi32, (uint32_t)i32);
+}
+
+
+/**
+ * Atomically Exchange an unsigned 64-bit value, ordered.
+ *
+ * @returns Current *pu64 value
+ * @param   pu64    Pointer to the 64-bit variable to update.
+ * @param   u64     The 64-bit value to assign to *pu64.
+ *
+ * @remarks Works on 32-bit x86 CPUs starting with Pentium.
+ */
+#if (RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN) \
+ || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC
+DECLASM(uint64_t) ASMAtomicXchgU64(volatile uint64_t *pu64, uint64_t u64);
+#else
+DECLINLINE(uint64_t) ASMAtomicXchgU64(volatile uint64_t *pu64, uint64_t u64)
+{
+# if defined(RT_ARCH_AMD64)
+#  if RT_INLINE_ASM_USES_INTRIN
+   u64 = _InterlockedExchange64((__int64 *)pu64, u64);
+
+#  elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("xchgq %0, %1\n\t"
+                         : "=m" (*pu64),
+                           "=r" (u64)
+                         : "1" (u64),
+                           "m" (*pu64));
+#  else
+    __asm
+    {
+        mov     rdx, [pu64]
+        mov     rax, [u64]
+        xchg    [rdx], rax
+        mov     [u64], rax
+    }
+#  endif
+# else /* !RT_ARCH_AMD64 */
+#  if RT_INLINE_ASM_GNU_STYLE
+#   if defined(PIC) || defined(__PIC__)
+    uint32_t u32EBX = (uint32_t)u64;
+    __asm__ __volatile__(/*"xchgl %%esi, %5\n\t"*/
+                         "xchgl %%ebx, %3\n\t"
+                         "1:\n\t"
+                         "lock; cmpxchg8b (%5)\n\t"
+                         "jnz 1b\n\t"
+                         "movl %3, %%ebx\n\t"
+                         /*"xchgl %%esi, %5\n\t"*/
+                         : "=A" (u64),
+                           "=m" (*pu64)
+                         : "0" (*pu64),
+                           "m" ( u32EBX ),
+                           "c" ( (uint32_t)(u64 >> 32) ),
+                           "S" (pu64));
+#   else /* !PIC */
+    __asm__ __volatile__("1:\n\t"
+                         "lock; cmpxchg8b %1\n\t"
+                         "jnz 1b\n\t"
+                         : "=A" (u64),
+                           "=m" (*pu64)
+                         : "0" (*pu64),
+                           "b" ( (uint32_t)u64 ),
+                           "c" ( (uint32_t)(u64 >> 32) ));
+#   endif
+#  else
+    __asm
+    {
+        mov     ebx, dword ptr [u64]
+        mov     ecx, dword ptr [u64 + 4]
+        mov     edi, pu64
+        mov     eax, dword ptr [edi]
+        mov     edx, dword ptr [edi + 4]
+    retry:
+        lock cmpxchg8b [edi]
+        jnz retry
+        mov     dword ptr [u64], eax
+        mov     dword ptr [u64 + 4], edx
+    }
+#  endif
+# endif /* !RT_ARCH_AMD64 */
+    return u64;
+}
+#endif
+
+
+/**
+ * Atomically Exchange an signed 64-bit value, ordered.
+ *
+ * @returns Current *pi64 value
+ * @param   pi64    Pointer to the 64-bit variable to update.
+ * @param   i64     The 64-bit value to assign to *pi64.
+ */
+DECLINLINE(int64_t) ASMAtomicXchgS64(volatile int64_t *pi64, int64_t i64)
+{
+    return (int64_t)ASMAtomicXchgU64((volatile uint64_t *)pi64, (uint64_t)i64);
+}
+
+
+/**
+ * Atomically Exchange a pointer value, ordered.
+ *
+ * @returns Current *ppv value
+ * @param   ppv    Pointer to the pointer variable to update.
+ * @param   pv     The pointer value to assign to *ppv.
+ */
+DECLINLINE(void *) ASMAtomicXchgPtr(void * volatile *ppv, const void *pv)
+{
+#if ARCH_BITS == 32 || (ARCH_BITS == 16 && RT_FAR_DATA)
+    return (void *)ASMAtomicXchgU32((volatile uint32_t *)(void *)ppv, (uint32_t)pv);
+#elif ARCH_BITS == 64
+    return (void *)ASMAtomicXchgU64((volatile uint64_t *)(void *)ppv, (uint64_t)pv);
+#else
+# error "ARCH_BITS is bogus"
+#endif
+}
+
+
+/**
+ * Convenience macro for avoiding the annoying casting with ASMAtomicXchgPtr.
+ *
+ * @returns Current *pv value
+ * @param   ppv     Pointer to the pointer variable to update.
+ * @param   pv      The pointer value to assign to *ppv.
+ * @param   Type    The type of *ppv, sans volatile.
+ */
+#ifdef __GNUC__
+# define ASMAtomicXchgPtrT(ppv, pv, Type) \
+    __extension__ \
+    ({\
+        __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \
+        Type                          const pvTypeChecked  = (pv); \
+        Type pvTypeCheckedRet = (__typeof__(*(ppv))) ASMAtomicXchgPtr((void * volatile *)ppvTypeChecked, (void *)pvTypeChecked); \
+        pvTypeCheckedRet; \
+     })
+#else
+# define ASMAtomicXchgPtrT(ppv, pv, Type) \
+    (Type)ASMAtomicXchgPtr((void * volatile *)(ppv), (void *)(pv))
+#endif
+
+
+/**
+ * Atomically Exchange a raw-mode context pointer value, ordered.
+ *
+ * @returns Current *ppv value
+ * @param   ppvRC   Pointer to the pointer variable to update.
+ * @param   pvRC    The pointer value to assign to *ppv.
+ */
+DECLINLINE(RTRCPTR) ASMAtomicXchgRCPtr(RTRCPTR volatile *ppvRC, RTRCPTR pvRC)
+{
+    return (RTRCPTR)ASMAtomicXchgU32((uint32_t volatile *)(void *)ppvRC, (uint32_t)pvRC);
+}
+
+
+/**
+ * Atomically Exchange a ring-0 pointer value, ordered.
+ *
+ * @returns Current *ppv value
+ * @param   ppvR0  Pointer to the pointer variable to update.
+ * @param   pvR0   The pointer value to assign to *ppv.
+ */
+DECLINLINE(RTR0PTR) ASMAtomicXchgR0Ptr(RTR0PTR volatile *ppvR0, RTR0PTR pvR0)
+{
+#if R0_ARCH_BITS == 32 || (ARCH_BITS == 16 && RT_FAR_DATA)
+    return (RTR0PTR)ASMAtomicXchgU32((volatile uint32_t *)(void *)ppvR0, (uint32_t)pvR0);
+#elif R0_ARCH_BITS == 64
+    return (RTR0PTR)ASMAtomicXchgU64((volatile uint64_t *)(void *)ppvR0, (uint64_t)pvR0);
+#else
+# error "R0_ARCH_BITS is bogus"
+#endif
+}
+
+
+/**
+ * Atomically Exchange a ring-3 pointer value, ordered.
+ *
+ * @returns Current *ppv value
+ * @param   ppvR3  Pointer to the pointer variable to update.
+ * @param   pvR3   The pointer value to assign to *ppv.
+ */
+DECLINLINE(RTR3PTR) ASMAtomicXchgR3Ptr(RTR3PTR volatile *ppvR3, RTR3PTR pvR3)
+{
+#if R3_ARCH_BITS == 32 || (ARCH_BITS == 16 && RT_FAR_DATA)
+    return (RTR3PTR)ASMAtomicXchgU32((volatile uint32_t *)(void *)ppvR3, (uint32_t)pvR3);
+#elif R3_ARCH_BITS == 64
+    return (RTR3PTR)ASMAtomicXchgU64((volatile uint64_t *)(void *)ppvR3, (uint64_t)pvR3);
+#else
+# error "R3_ARCH_BITS is bogus"
+#endif
+}
+
+
+/** @def ASMAtomicXchgHandle
+ * Atomically Exchange a typical IPRT handle value, ordered.
+ *
+ * @param   ph          Pointer to the value to update.
+ * @param   hNew        The new value to assigned to *pu.
+ * @param   phRes       Where to store the current *ph value.
+ *
+ * @remarks This doesn't currently work for all handles (like RTFILE).
+ */
+#if HC_ARCH_BITS == 32 || (ARCH_BITS == 16 && RT_FAR_DATA)
+# define ASMAtomicXchgHandle(ph, hNew, phRes) \
+   do { \
+       AssertCompile(sizeof(*(ph))    == sizeof(uint32_t)); \
+       AssertCompile(sizeof(*(phRes)) == sizeof(uint32_t)); \
+       *(uint32_t *)(phRes) = ASMAtomicXchgU32((uint32_t volatile *)(ph), (const uint32_t)(hNew)); \
+   } while (0)
+#elif HC_ARCH_BITS == 64
+# define ASMAtomicXchgHandle(ph, hNew, phRes) \
+   do { \
+       AssertCompile(sizeof(*(ph))    == sizeof(uint64_t)); \
+       AssertCompile(sizeof(*(phRes)) == sizeof(uint64_t)); \
+       *(uint64_t *)(phRes) = ASMAtomicXchgU64((uint64_t volatile *)(ph), (const uint64_t)(hNew)); \
+   } while (0)
+#else
+# error HC_ARCH_BITS
+#endif
+
+
+/**
+ * Atomically Exchange a value which size might differ
+ * between platforms or compilers, ordered.
+ *
+ * @param   pu      Pointer to the variable to update.
+ * @param   uNew    The value to assign to *pu.
+ * @todo This is busted as its missing the result argument.
+ */
+#define ASMAtomicXchgSize(pu, uNew) \
+    do { \
+        switch (sizeof(*(pu))) { \
+            case 1: ASMAtomicXchgU8((volatile uint8_t *)(void *)(pu), (uint8_t)(uNew)); break; \
+            case 2: ASMAtomicXchgU16((volatile uint16_t *)(void *)(pu), (uint16_t)(uNew)); break; \
+            case 4: ASMAtomicXchgU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew)); break; \
+            case 8: ASMAtomicXchgU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew)); break; \
+            default: AssertMsgFailed(("ASMAtomicXchgSize: size %d is not supported\n", sizeof(*(pu)))); \
+        } \
+    } while (0)
+
+/**
+ * Atomically Exchange a value which size might differ
+ * between platforms or compilers, ordered.
+ *
+ * @param   pu      Pointer to the variable to update.
+ * @param   uNew    The value to assign to *pu.
+ * @param   puRes   Where to store the current *pu value.
+ */
+#define ASMAtomicXchgSizeCorrect(pu, uNew, puRes) \
+    do { \
+        switch (sizeof(*(pu))) { \
+            case 1: *(uint8_t  *)(puRes) = ASMAtomicXchgU8((volatile uint8_t *)(void *)(pu), (uint8_t)(uNew)); break; \
+            case 2: *(uint16_t *)(puRes) = ASMAtomicXchgU16((volatile uint16_t *)(void *)(pu), (uint16_t)(uNew)); break; \
+            case 4: *(uint32_t *)(puRes) = ASMAtomicXchgU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew)); break; \
+            case 8: *(uint64_t *)(puRes) = ASMAtomicXchgU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew)); break; \
+            default: AssertMsgFailed(("ASMAtomicXchgSize: size %d is not supported\n", sizeof(*(pu)))); \
+        } \
+    } while (0)
+
+
+
+/**
+ * Atomically Compare and Exchange an unsigned 8-bit value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param   pu8         Pointer to the value to update.
+ * @param   u8New       The new value to assigned to *pu8.
+ * @param   u8Old       The old value to *pu8 compare with.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL || !RT_INLINE_ASM_GNU_STYLE
+DECLASM(bool) ASMAtomicCmpXchgU8(volatile uint8_t *pu8, const uint8_t u8New, const uint8_t u8Old);
+#else
+DECLINLINE(bool) ASMAtomicCmpXchgU8(volatile uint8_t *pu8, const uint8_t u8New, uint8_t u8Old)
+{
+    uint8_t u8Ret;
+    __asm__ __volatile__("lock; cmpxchgb %3, %0\n\t"
+                         "setz  %1\n\t"
+                         : "=m" (*pu8),
+                           "=qm" (u8Ret),
+                           "=a" (u8Old)
+                         : "q" (u8New),
+                           "2" (u8Old),
+                           "m" (*pu8));
+    return (bool)u8Ret;
+}
+#endif
+
+
+/**
+ * Atomically Compare and Exchange a signed 8-bit value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param   pi8         Pointer to the value to update.
+ * @param   i8New       The new value to assigned to *pi8.
+ * @param   i8Old       The old value to *pi8 compare with.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgS8(volatile int8_t *pi8, const int8_t i8New, const int8_t i8Old)
+{
+    return ASMAtomicCmpXchgU8((volatile uint8_t *)pi8, (const uint8_t)i8New, (const uint8_t)i8Old);
+}
+
+
+/**
+ * Atomically Compare and Exchange a bool value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param   pf          Pointer to the value to update.
+ * @param   fNew        The new value to assigned to *pf.
+ * @param   fOld        The old value to *pf compare with.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgBool(volatile bool *pf, const bool fNew, const bool fOld)
+{
+    return ASMAtomicCmpXchgU8((volatile uint8_t *)pf, (const uint8_t)fNew, (const uint8_t)fOld);
+}
+
+
+/**
+ * Atomically Compare and Exchange an unsigned 32-bit value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param   pu32        Pointer to the value to update.
+ * @param   u32New      The new value to assigned to *pu32.
+ * @param   u32Old      The old value to *pu32 compare with.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(bool) ASMAtomicCmpXchgU32(volatile uint32_t *pu32, const uint32_t u32New, const uint32_t u32Old);
+#else
+DECLINLINE(bool) ASMAtomicCmpXchgU32(volatile uint32_t *pu32, const uint32_t u32New, uint32_t u32Old)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    uint8_t u8Ret;
+    __asm__ __volatile__("lock; cmpxchgl %3, %0\n\t"
+                         "setz  %1\n\t"
+                         : "=m" (*pu32),
+                           "=qm" (u8Ret),
+                           "=a" (u32Old)
+                         : "r" (u32New),
+                           "2" (u32Old),
+                           "m" (*pu32));
+    return (bool)u8Ret;
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    return (uint32_t)_InterlockedCompareExchange((long *)pu32, u32New, u32Old) == u32Old;
+
+# else
+    uint32_t u32Ret;
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [pu32]
+#  else
+        mov     edx, [pu32]
+#  endif
+        mov     eax, [u32Old]
+        mov     ecx, [u32New]
+#  ifdef RT_ARCH_AMD64
+        lock cmpxchg [rdx], ecx
+#  else
+        lock cmpxchg [edx], ecx
+#  endif
+        setz    al
+        movzx   eax, al
+        mov     [u32Ret], eax
+    }
+    return !!u32Ret;
+# endif
+}
+#endif
+
+
+/**
+ * Atomically Compare and Exchange a signed 32-bit value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param   pi32        Pointer to the value to update.
+ * @param   i32New      The new value to assigned to *pi32.
+ * @param   i32Old      The old value to *pi32 compare with.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgS32(volatile int32_t *pi32, const int32_t i32New, const int32_t i32Old)
+{
+    return ASMAtomicCmpXchgU32((volatile uint32_t *)pi32, (uint32_t)i32New, (uint32_t)i32Old);
+}
+
+
+/**
+ * Atomically Compare and exchange an unsigned 64-bit value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param   pu64    Pointer to the 64-bit variable to update.
+ * @param   u64New  The 64-bit value to assign to *pu64.
+ * @param   u64Old  The value to compare with.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+#if (RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN) \
+ || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC
+DECLASM(bool) ASMAtomicCmpXchgU64(volatile uint64_t *pu64, const uint64_t u64New, const uint64_t u64Old);
+#else
+DECLINLINE(bool) ASMAtomicCmpXchgU64(volatile uint64_t *pu64, uint64_t u64New, uint64_t u64Old)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+   return (uint64_t)_InterlockedCompareExchange64((__int64 *)pu64, u64New, u64Old) == u64Old;
+
+# elif defined(RT_ARCH_AMD64)
+#  if RT_INLINE_ASM_GNU_STYLE
+    uint8_t u8Ret;
+    __asm__ __volatile__("lock; cmpxchgq %3, %0\n\t"
+                         "setz  %1\n\t"
+                         : "=m" (*pu64),
+                           "=qm" (u8Ret),
+                           "=a" (u64Old)
+                         : "r" (u64New),
+                           "2" (u64Old),
+                           "m" (*pu64));
+    return (bool)u8Ret;
+#  else
+    bool fRet;
+    __asm
+    {
+        mov     rdx, [pu32]
+        mov     rax, [u64Old]
+        mov     rcx, [u64New]
+        lock cmpxchg [rdx], rcx
+        setz    al
+        mov     [fRet], al
+    }
+    return fRet;
+#  endif
+# else /* !RT_ARCH_AMD64 */
+    uint32_t u32Ret;
+#  if RT_INLINE_ASM_GNU_STYLE
+#   if defined(PIC) || defined(__PIC__)
+    uint32_t u32EBX = (uint32_t)u64New;
+    uint32_t u32Spill;
+    __asm__ __volatile__("xchgl %%ebx, %4\n\t"
+                         "lock; cmpxchg8b (%6)\n\t"
+                         "setz  %%al\n\t"
+                         "movl  %4, %%ebx\n\t"
+                         "movzbl %%al, %%eax\n\t"
+                         : "=a" (u32Ret),
+                           "=d" (u32Spill),
+#    if RT_GNUC_PREREQ(4, 3)
+                           "+m" (*pu64)
+#    else
+                           "=m" (*pu64)
+#    endif
+                         : "A" (u64Old),
+                           "m" ( u32EBX ),
+                           "c" ( (uint32_t)(u64New >> 32) ),
+                           "S" (pu64));
+#   else /* !PIC */
+    uint32_t u32Spill;
+    __asm__ __volatile__("lock; cmpxchg8b %2\n\t"
+                         "setz  %%al\n\t"
+                         "movzbl %%al, %%eax\n\t"
+                         : "=a" (u32Ret),
+                           "=d" (u32Spill),
+                           "+m" (*pu64)
+                         : "A" (u64Old),
+                           "b" ( (uint32_t)u64New ),
+                           "c" ( (uint32_t)(u64New >> 32) ));
+#   endif
+    return (bool)u32Ret;
+#  else
+    __asm
+    {
+        mov     ebx, dword ptr [u64New]
+        mov     ecx, dword ptr [u64New + 4]
+        mov     edi, [pu64]
+        mov     eax, dword ptr [u64Old]
+        mov     edx, dword ptr [u64Old + 4]
+        lock cmpxchg8b [edi]
+        setz    al
+        movzx   eax, al
+        mov     dword ptr [u32Ret], eax
+    }
+    return !!u32Ret;
+#  endif
+# endif /* !RT_ARCH_AMD64 */
+}
+#endif
+
+
+/**
+ * Atomically Compare and exchange a signed 64-bit value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param   pi64    Pointer to the 64-bit variable to update.
+ * @param   i64     The 64-bit value to assign to *pu64.
+ * @param   i64Old  The value to compare with.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgS64(volatile int64_t *pi64, const int64_t i64, const int64_t i64Old)
+{
+    return ASMAtomicCmpXchgU64((volatile uint64_t *)pi64, (uint64_t)i64, (uint64_t)i64Old);
+}
+
+
+/**
+ * Atomically Compare and Exchange a pointer value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param   ppv         Pointer to the value to update.
+ * @param   pvNew       The new value to assigned to *ppv.
+ * @param   pvOld       The old value to *ppv compare with.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgPtrVoid(void * volatile *ppv, const void *pvNew, const void *pvOld)
+{
+#if ARCH_BITS == 32 || (ARCH_BITS == 16 && RT_FAR_DATA)
+    return ASMAtomicCmpXchgU32((volatile uint32_t *)(void *)ppv, (uint32_t)pvNew, (uint32_t)pvOld);
+#elif ARCH_BITS == 64
+    return ASMAtomicCmpXchgU64((volatile uint64_t *)(void *)ppv, (uint64_t)pvNew, (uint64_t)pvOld);
+#else
+# error "ARCH_BITS is bogus"
+#endif
+}
+
+
+/**
+ * Atomically Compare and Exchange a pointer value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param   ppv         Pointer to the value to update.
+ * @param   pvNew       The new value to assigned to *ppv.
+ * @param   pvOld       The old value to *ppv compare with.
+ *
+ * @remarks This is relatively type safe on GCC platforms.
+ * @remarks x86: Requires a 486 or later.
+ */
+#ifdef __GNUC__
+# define ASMAtomicCmpXchgPtr(ppv, pvNew, pvOld) \
+    __extension__ \
+    ({\
+        __typeof__(*(ppv)) volatile * const ppvTypeChecked   = (ppv); \
+        __typeof__(*(ppv))            const pvNewTypeChecked = (pvNew); \
+        __typeof__(*(ppv))            const pvOldTypeChecked = (pvOld); \
+        bool fMacroRet = ASMAtomicCmpXchgPtrVoid((void * volatile *)ppvTypeChecked, \
+                                                 (void *)pvNewTypeChecked, (void *)pvOldTypeChecked); \
+        fMacroRet; \
+     })
+#else
+# define ASMAtomicCmpXchgPtr(ppv, pvNew, pvOld) \
+    ASMAtomicCmpXchgPtrVoid((void * volatile *)(ppv), (void *)(pvNew), (void *)(pvOld))
+#endif
+
+
+/** @def ASMAtomicCmpXchgHandle
+ * Atomically Compare and Exchange a typical IPRT handle value, ordered.
+ *
+ * @param   ph          Pointer to the value to update.
+ * @param   hNew        The new value to assigned to *pu.
+ * @param   hOld        The old value to *pu compare with.
+ * @param   fRc         Where to store the result.
+ *
+ * @remarks This doesn't currently work for all handles (like RTFILE).
+ * @remarks x86: Requires a 486 or later.
+ */
+#if HC_ARCH_BITS == 32 || (ARCH_BITS == 16 && RT_FAR_DATA)
+# define ASMAtomicCmpXchgHandle(ph, hNew, hOld, fRc) \
+   do { \
+       AssertCompile(sizeof(*(ph)) == sizeof(uint32_t)); \
+       (fRc) = ASMAtomicCmpXchgU32((uint32_t volatile *)(ph), (const uint32_t)(hNew), (const uint32_t)(hOld)); \
+   } while (0)
+#elif HC_ARCH_BITS == 64
+# define ASMAtomicCmpXchgHandle(ph, hNew, hOld, fRc) \
+   do { \
+       AssertCompile(sizeof(*(ph)) == sizeof(uint64_t)); \
+       (fRc) = ASMAtomicCmpXchgU64((uint64_t volatile *)(ph), (const uint64_t)(hNew), (const uint64_t)(hOld)); \
+   } while (0)
+#else
+# error HC_ARCH_BITS
+#endif
+
+
+/** @def ASMAtomicCmpXchgSize
+ * Atomically Compare and Exchange a value which size might differ
+ * between platforms or compilers, ordered.
+ *
+ * @param   pu          Pointer to the value to update.
+ * @param   uNew        The new value to assigned to *pu.
+ * @param   uOld        The old value to *pu compare with.
+ * @param   fRc         Where to store the result.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+#define ASMAtomicCmpXchgSize(pu, uNew, uOld, fRc) \
+    do { \
+        switch (sizeof(*(pu))) { \
+            case 4: (fRc) = ASMAtomicCmpXchgU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew), (uint32_t)(uOld)); \
+                break; \
+            case 8: (fRc) = ASMAtomicCmpXchgU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew), (uint64_t)(uOld)); \
+                break; \
+            default: AssertMsgFailed(("ASMAtomicCmpXchgSize: size %d is not supported\n", sizeof(*(pu)))); \
+                (fRc) = false; \
+                break; \
+        } \
+    } while (0)
+
+
+/**
+ * Atomically Compare and Exchange an unsigned 32-bit value, additionally
+ * passes back old value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param   pu32        Pointer to the value to update.
+ * @param   u32New      The new value to assigned to *pu32.
+ * @param   u32Old      The old value to *pu32 compare with.
+ * @param   pu32Old     Pointer store the old value at.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(bool) ASMAtomicCmpXchgExU32(volatile uint32_t *pu32, const uint32_t u32New, const uint32_t u32Old, uint32_t *pu32Old);
+#else
+DECLINLINE(bool) ASMAtomicCmpXchgExU32(volatile uint32_t *pu32, const uint32_t u32New, const uint32_t u32Old, uint32_t *pu32Old)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    uint8_t u8Ret;
+    __asm__ __volatile__("lock; cmpxchgl %3, %0\n\t"
+                         "setz  %1\n\t"
+                         : "=m" (*pu32),
+                           "=qm" (u8Ret),
+                           "=a" (*pu32Old)
+                         : "r" (u32New),
+                           "a" (u32Old),
+                           "m" (*pu32));
+    return (bool)u8Ret;
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    return (*pu32Old =_InterlockedCompareExchange((long *)pu32, u32New, u32Old)) == u32Old;
+
+# else
+    uint32_t u32Ret;
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [pu32]
+#  else
+        mov     edx, [pu32]
+#  endif
+        mov     eax, [u32Old]
+        mov     ecx, [u32New]
+#  ifdef RT_ARCH_AMD64
+        lock cmpxchg [rdx], ecx
+        mov     rdx, [pu32Old]
+        mov     [rdx], eax
+#  else
+        lock cmpxchg [edx], ecx
+        mov     edx, [pu32Old]
+        mov     [edx], eax
+#  endif
+        setz    al
+        movzx   eax, al
+        mov     [u32Ret], eax
+    }
+    return !!u32Ret;
+# endif
+}
+#endif
+
+
+/**
+ * Atomically Compare and Exchange a signed 32-bit value, additionally
+ * passes back old value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param   pi32        Pointer to the value to update.
+ * @param   i32New      The new value to assigned to *pi32.
+ * @param   i32Old      The old value to *pi32 compare with.
+ * @param   pi32Old     Pointer store the old value at.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgExS32(volatile int32_t *pi32, const int32_t i32New, const int32_t i32Old, int32_t *pi32Old)
+{
+    return ASMAtomicCmpXchgExU32((volatile uint32_t *)pi32, (uint32_t)i32New, (uint32_t)i32Old, (uint32_t *)pi32Old);
+}
+
+
+/**
+ * Atomically Compare and exchange an unsigned 64-bit value, additionally
+ * passing back old value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param   pu64    Pointer to the 64-bit variable to update.
+ * @param   u64New  The 64-bit value to assign to *pu64.
+ * @param   u64Old  The value to compare with.
+ * @param   pu64Old     Pointer store the old value at.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+#if (RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN) \
+ || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC
+DECLASM(bool) ASMAtomicCmpXchgExU64(volatile uint64_t *pu64, const uint64_t u64New, const uint64_t u64Old, uint64_t *pu64Old);
+#else
+DECLINLINE(bool) ASMAtomicCmpXchgExU64(volatile uint64_t *pu64, const uint64_t u64New, const uint64_t u64Old, uint64_t *pu64Old)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+   return (*pu64Old =_InterlockedCompareExchange64((__int64 *)pu64, u64New, u64Old)) == u64Old;
+
+# elif defined(RT_ARCH_AMD64)
+#  if RT_INLINE_ASM_GNU_STYLE
+    uint8_t u8Ret;
+    __asm__ __volatile__("lock; cmpxchgq %3, %0\n\t"
+                         "setz  %1\n\t"
+                         : "=m" (*pu64),
+                           "=qm" (u8Ret),
+                           "=a" (*pu64Old)
+                         : "r" (u64New),
+                           "a" (u64Old),
+                           "m" (*pu64));
+    return (bool)u8Ret;
+#  else
+    bool fRet;
+    __asm
+    {
+        mov     rdx, [pu32]
+        mov     rax, [u64Old]
+        mov     rcx, [u64New]
+        lock cmpxchg [rdx], rcx
+        mov     rdx, [pu64Old]
+        mov     [rdx], rax
+        setz    al
+        mov     [fRet], al
+    }
+    return fRet;
+#  endif
+# else /* !RT_ARCH_AMD64 */
+#  if RT_INLINE_ASM_GNU_STYLE
+    uint64_t u64Ret;
+#   if defined(PIC) || defined(__PIC__)
+    /* NB: this code uses a memory clobber description, because the clean
+     * solution with an output value for *pu64 makes gcc run out of registers.
+     * This will cause suboptimal code, and anyone with a better solution is
+     * welcome to improve this. */
+    __asm__ __volatile__("xchgl %%ebx, %1\n\t"
+                         "lock; cmpxchg8b %3\n\t"
+                         "xchgl %%ebx, %1\n\t"
+                         : "=A" (u64Ret)
+                         : "DS" ((uint32_t)u64New),
+                           "c" ((uint32_t)(u64New >> 32)),
+                           "m" (*pu64),
+                           "0" (u64Old)
+                         : "memory" );
+#   else /* !PIC */
+    __asm__ __volatile__("lock; cmpxchg8b %4\n\t"
+                         : "=A" (u64Ret),
+                           "=m" (*pu64)
+                         : "b" ((uint32_t)u64New),
+                           "c" ((uint32_t)(u64New >> 32)),
+                           "m" (*pu64),
+                           "0" (u64Old));
+#   endif
+    *pu64Old = u64Ret;
+    return u64Ret == u64Old;
+#  else
+    uint32_t u32Ret;
+    __asm
+    {
+        mov     ebx, dword ptr [u64New]
+        mov     ecx, dword ptr [u64New + 4]
+        mov     edi, [pu64]
+        mov     eax, dword ptr [u64Old]
+        mov     edx, dword ptr [u64Old + 4]
+        lock cmpxchg8b [edi]
+        mov     ebx, [pu64Old]
+        mov     [ebx], eax
+        setz    al
+        movzx   eax, al
+        add     ebx, 4
+        mov     [ebx], edx
+        mov     dword ptr [u32Ret], eax
+    }
+    return !!u32Ret;
+#  endif
+# endif /* !RT_ARCH_AMD64 */
+}
+#endif
+
+
+/**
+ * Atomically Compare and exchange a signed 64-bit value, additionally
+ * passing back old value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param   pi64    Pointer to the 64-bit variable to update.
+ * @param   i64     The 64-bit value to assign to *pu64.
+ * @param   i64Old  The value to compare with.
+ * @param   pi64Old Pointer store the old value at.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgExS64(volatile int64_t *pi64, const int64_t i64, const int64_t i64Old, int64_t *pi64Old)
+{
+    return ASMAtomicCmpXchgExU64((volatile uint64_t *)pi64, (uint64_t)i64, (uint64_t)i64Old, (uint64_t *)pi64Old);
+}
+
+/** @def ASMAtomicCmpXchgExHandle
+ * Atomically Compare and Exchange a typical IPRT handle value, ordered.
+ *
+ * @param   ph          Pointer to the value to update.
+ * @param   hNew        The new value to assigned to *pu.
+ * @param   hOld        The old value to *pu compare with.
+ * @param   fRc         Where to store the result.
+ * @param   phOldVal    Pointer to where to store the old value.
+ *
+ * @remarks This doesn't currently work for all handles (like RTFILE).
+ */
+#if HC_ARCH_BITS == 32 || (ARCH_BITS == 16 && RT_FAR_DATA)
+# define ASMAtomicCmpXchgExHandle(ph, hNew, hOld, fRc, phOldVal) \
+    do { \
+        AssertCompile(sizeof(*ph)       == sizeof(uint32_t)); \
+        AssertCompile(sizeof(*phOldVal) == sizeof(uint32_t)); \
+        (fRc) = ASMAtomicCmpXchgExU32((volatile uint32_t *)(pu), (uint32_t)(uNew), (uint32_t)(uOld), (uint32_t *)(puOldVal)); \
+    } while (0)
+#elif HC_ARCH_BITS == 64
+# define ASMAtomicCmpXchgExHandle(ph, hNew, hOld, fRc, phOldVal) \
+    do { \
+        AssertCompile(sizeof(*(ph))       == sizeof(uint64_t)); \
+        AssertCompile(sizeof(*(phOldVal)) == sizeof(uint64_t)); \
+        (fRc) = ASMAtomicCmpXchgExU64((volatile uint64_t *)(pu), (uint64_t)(uNew), (uint64_t)(uOld), (uint64_t *)(puOldVal)); \
+    } while (0)
+#else
+# error HC_ARCH_BITS
+#endif
+
+
+/** @def ASMAtomicCmpXchgExSize
+ * Atomically Compare and Exchange a value which size might differ
+ * between platforms or compilers. Additionally passes back old value.
+ *
+ * @param   pu          Pointer to the value to update.
+ * @param   uNew        The new value to assigned to *pu.
+ * @param   uOld        The old value to *pu compare with.
+ * @param   fRc         Where to store the result.
+ * @param   puOldVal    Pointer to where to store the old value.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+#define ASMAtomicCmpXchgExSize(pu, uNew, uOld, fRc, puOldVal) \
+    do { \
+        switch (sizeof(*(pu))) { \
+            case 4: (fRc) = ASMAtomicCmpXchgExU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew), (uint32_t)(uOld), (uint32_t *)(uOldVal)); \
+                break; \
+            case 8: (fRc) = ASMAtomicCmpXchgExU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew), (uint64_t)(uOld), (uint64_t *)(uOldVal)); \
+                break; \
+            default: AssertMsgFailed(("ASMAtomicCmpXchgSize: size %d is not supported\n", sizeof(*(pu)))); \
+                (fRc) = false; \
+                (uOldVal) = 0; \
+                break; \
+        } \
+    } while (0)
+
+
+/**
+ * Atomically Compare and Exchange a pointer value, additionally
+ * passing back old value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param   ppv         Pointer to the value to update.
+ * @param   pvNew       The new value to assigned to *ppv.
+ * @param   pvOld       The old value to *ppv compare with.
+ * @param   ppvOld      Pointer store the old value at.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgExPtrVoid(void * volatile *ppv, const void *pvNew, const void *pvOld, void **ppvOld)
+{
+#if ARCH_BITS == 32 || (ARCH_BITS == 16 && RT_FAR_DATA)
+    return ASMAtomicCmpXchgExU32((volatile uint32_t *)(void *)ppv, (uint32_t)pvNew, (uint32_t)pvOld, (uint32_t *)ppvOld);
+#elif ARCH_BITS == 64
+    return ASMAtomicCmpXchgExU64((volatile uint64_t *)(void *)ppv, (uint64_t)pvNew, (uint64_t)pvOld, (uint64_t *)ppvOld);
+#else
+# error "ARCH_BITS is bogus"
+#endif
+}
+
+
+/**
+ * Atomically Compare and Exchange a pointer value, additionally
+ * passing back old value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param   ppv         Pointer to the value to update.
+ * @param   pvNew       The new value to assigned to *ppv.
+ * @param   pvOld       The old value to *ppv compare with.
+ * @param   ppvOld      Pointer store the old value at.
+ *
+ * @remarks This is relatively type safe on GCC platforms.
+ * @remarks x86: Requires a 486 or later.
+ */
+#ifdef __GNUC__
+# define ASMAtomicCmpXchgExPtr(ppv, pvNew, pvOld, ppvOld) \
+    __extension__ \
+    ({\
+        __typeof__(*(ppv)) volatile * const ppvTypeChecked    = (ppv); \
+        __typeof__(*(ppv))            const pvNewTypeChecked  = (pvNew); \
+        __typeof__(*(ppv))            const pvOldTypeChecked  = (pvOld); \
+        __typeof__(*(ppv)) *          const ppvOldTypeChecked = (ppvOld); \
+        bool fMacroRet = ASMAtomicCmpXchgExPtrVoid((void * volatile *)ppvTypeChecked, \
+                                                   (void *)pvNewTypeChecked, (void *)pvOldTypeChecked, \
+                                                   (void **)ppvOldTypeChecked); \
+        fMacroRet; \
+     })
+#else
+# define ASMAtomicCmpXchgExPtr(ppv, pvNew, pvOld, ppvOld) \
+    ASMAtomicCmpXchgExPtrVoid((void * volatile *)(ppv), (void *)(pvNew), (void *)(pvOld), (void **)(ppvOld))
+#endif
+
+
+/**
+ * Virtualization unfriendly serializing instruction, always exits.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMSerializeInstructionCpuId(void);
+#else
+DECLINLINE(void) ASMSerializeInstructionCpuId(void)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    RTCCUINTREG xAX = 0;
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__ ("cpuid"
+                          : "=a" (xAX)
+                          : "0" (xAX)
+                          : "rbx", "rcx", "rdx", "memory");
+#  elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
+    __asm__ __volatile__ ("push  %%ebx\n\t"
+                          "cpuid\n\t"
+                          "pop   %%ebx\n\t"
+                          : "=a" (xAX)
+                          : "0" (xAX)
+                          : "ecx", "edx", "memory");
+#  else
+    __asm__ __volatile__ ("cpuid"
+                          : "=a" (xAX)
+                          : "0" (xAX)
+                          : "ebx", "ecx", "edx", "memory");
+#  endif
+
+# elif RT_INLINE_ASM_USES_INTRIN
+    int aInfo[4];
+    _ReadWriteBarrier();
+    __cpuid(aInfo, 0);
+
+# else
+    __asm
+    {
+        push    ebx
+        xor     eax, eax
+        cpuid
+        pop     ebx
+    }
+# endif
+}
+#endif
+
+/**
+ * Virtualization friendly serializing instruction, though more expensive.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMSerializeInstructionIRet(void);
+#else
+DECLINLINE(void) ASMSerializeInstructionIRet(void)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+#  ifdef RT_ARCH_AMD64
+    __asm__ __volatile__ ("movq  %%rsp,%%r10\n\t"
+                          "subq  $128, %%rsp\n\t" /*redzone*/
+                          "mov   %%ss, %%eax\n\t"
+                          "pushq %%rax\n\t"
+                          "pushq %%r10\n\t"
+                          "pushfq\n\t"
+                          "movl  %%cs, %%eax\n\t"
+                          "pushq %%rax\n\t"
+                          "leaq  1f(%%rip), %%rax\n\t"
+                          "pushq %%rax\n\t"
+                          "iretq\n\t"
+                          "1:\n\t"
+                          ::: "rax", "r10", "memory");
+#  else
+    __asm__ __volatile__ ("pushfl\n\t"
+                          "pushl %%cs\n\t"
+                          "pushl $1f\n\t"
+                          "iretl\n\t"
+                          "1:\n\t"
+                          ::: "memory");
+#  endif
+
+# else
+    __asm
+    {
+        pushfd
+        push    cs
+        push    la_ret
+        iretd
+    la_ret:
+    }
+# endif
+}
+#endif
+
+/**
+ * Virtualization friendlier serializing instruction, may still cause exits.
+ */
+#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 15
+DECLASM(void) ASMSerializeInstructionRdTscp(void);
+#else
+DECLINLINE(void) ASMSerializeInstructionRdTscp(void)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    /* rdtscp is not supported by ancient linux build VM of course :-( */
+#  ifdef RT_ARCH_AMD64
+    /*__asm__ __volatile__("rdtscp\n\t" ::: "rax", "rdx, "rcx"); */
+    __asm__ __volatile__(".byte 0x0f,0x01,0xf9\n\t" ::: "rax", "rdx", "rcx", "memory");
+#  else
+    /*__asm__ __volatile__("rdtscp\n\t" ::: "eax", "edx, "ecx"); */
+    __asm__ __volatile__(".byte 0x0f,0x01,0xf9\n\t" ::: "eax", "edx", "ecx", "memory");
+#  endif
+# else
+#  if RT_INLINE_ASM_USES_INTRIN >= 15
+    uint32_t uIgnore;
+    _ReadWriteBarrier();
+    (void)__rdtscp(&uIgnore);
+    (void)uIgnore;
+#  else
+    __asm
+    {
+        rdtscp
+    }
+#  endif
+# endif
+}
+#endif
+
+
+/**
+ * Serialize Instruction.
+ */
+#if (defined(RT_ARCH_X86) && ARCH_BITS == 16) || defined(IN_GUEST)
+# define ASMSerializeInstruction() ASMSerializeInstructionIRet()
+#else
+# define ASMSerializeInstruction() ASMSerializeInstructionCpuId()
+#endif
+
+
+/**
+ * Memory fence, waits for any pending writes and reads to complete.
+ */
+DECLINLINE(void) ASMMemoryFence(void)
+{
+    /** @todo use mfence? check if all cpus we care for support it. */
+#if ARCH_BITS == 16
+    uint16_t volatile u16;
+    ASMAtomicXchgU16(&u16, 0);
+#else
+    uint32_t volatile u32;
+    ASMAtomicXchgU32(&u32, 0);
+#endif
+}
+
+
+/**
+ * Write fence, waits for any pending writes to complete.
+ */
+DECLINLINE(void) ASMWriteFence(void)
+{
+    /** @todo use sfence? check if all cpus we care for support it. */
+    ASMMemoryFence();
+}
+
+
+/**
+ * Read fence, waits for any pending reads to complete.
+ */
+DECLINLINE(void) ASMReadFence(void)
+{
+    /** @todo use lfence? check if all cpus we care for support it. */
+    ASMMemoryFence();
+}
+
+
+/**
+ * Atomically reads an unsigned 8-bit value, ordered.
+ *
+ * @returns Current *pu8 value
+ * @param   pu8    Pointer to the 8-bit variable to read.
+ */
+DECLINLINE(uint8_t) ASMAtomicReadU8(volatile uint8_t *pu8)
+{
+    ASMMemoryFence();
+    return *pu8;    /* byte reads are atomic on x86 */
+}
+
+
+/**
+ * Atomically reads an unsigned 8-bit value, unordered.
+ *
+ * @returns Current *pu8 value
+ * @param   pu8    Pointer to the 8-bit variable to read.
+ */
+DECLINLINE(uint8_t) ASMAtomicUoReadU8(volatile uint8_t *pu8)
+{
+    return *pu8;    /* byte reads are atomic on x86 */
+}
+
+
+/**
+ * Atomically reads a signed 8-bit value, ordered.
+ *
+ * @returns Current *pi8 value
+ * @param   pi8    Pointer to the 8-bit variable to read.
+ */
+DECLINLINE(int8_t) ASMAtomicReadS8(volatile int8_t *pi8)
+{
+    ASMMemoryFence();
+    return *pi8;    /* byte reads are atomic on x86 */
+}
+
+
+/**
+ * Atomically reads a signed 8-bit value, unordered.
+ *
+ * @returns Current *pi8 value
+ * @param   pi8    Pointer to the 8-bit variable to read.
+ */
+DECLINLINE(int8_t) ASMAtomicUoReadS8(volatile int8_t *pi8)
+{
+    return *pi8;    /* byte reads are atomic on x86 */
+}
+
+
+/**
+ * Atomically reads an unsigned 16-bit value, ordered.
+ *
+ * @returns Current *pu16 value
+ * @param   pu16    Pointer to the 16-bit variable to read.
+ */
+DECLINLINE(uint16_t) ASMAtomicReadU16(volatile uint16_t *pu16)
+{
+    ASMMemoryFence();
+    Assert(!((uintptr_t)pu16 & 1));
+    return *pu16;
+}
+
+
+/**
+ * Atomically reads an unsigned 16-bit value, unordered.
+ *
+ * @returns Current *pu16 value
+ * @param   pu16    Pointer to the 16-bit variable to read.
+ */
+DECLINLINE(uint16_t) ASMAtomicUoReadU16(volatile uint16_t *pu16)
+{
+    Assert(!((uintptr_t)pu16 & 1));
+    return *pu16;
+}
+
+
+/**
+ * Atomically reads a signed 16-bit value, ordered.
+ *
+ * @returns Current *pi16 value
+ * @param   pi16    Pointer to the 16-bit variable to read.
+ */
+DECLINLINE(int16_t) ASMAtomicReadS16(volatile int16_t *pi16)
+{
+    ASMMemoryFence();
+    Assert(!((uintptr_t)pi16 & 1));
+    return *pi16;
+}
+
+
+/**
+ * Atomically reads a signed 16-bit value, unordered.
+ *
+ * @returns Current *pi16 value
+ * @param   pi16    Pointer to the 16-bit variable to read.
+ */
+DECLINLINE(int16_t) ASMAtomicUoReadS16(volatile int16_t *pi16)
+{
+    Assert(!((uintptr_t)pi16 & 1));
+    return *pi16;
+}
+
+
+/**
+ * Atomically reads an unsigned 32-bit value, ordered.
+ *
+ * @returns Current *pu32 value
+ * @param   pu32    Pointer to the 32-bit variable to read.
+ */
+DECLINLINE(uint32_t) ASMAtomicReadU32(volatile uint32_t *pu32)
+{
+    ASMMemoryFence();
+    Assert(!((uintptr_t)pu32 & 3));
+#if ARCH_BITS == 16
+    AssertFailed();  /** @todo 16-bit */
+#endif
+    return *pu32;
+}
+
+
+/**
+ * Atomically reads an unsigned 32-bit value, unordered.
+ *
+ * @returns Current *pu32 value
+ * @param   pu32    Pointer to the 32-bit variable to read.
+ */
+DECLINLINE(uint32_t) ASMAtomicUoReadU32(volatile uint32_t *pu32)
+{
+    Assert(!((uintptr_t)pu32 & 3));
+#if ARCH_BITS == 16
+    AssertFailed();  /** @todo 16-bit */
+#endif
+    return *pu32;
+}
+
+
+/**
+ * Atomically reads a signed 32-bit value, ordered.
+ *
+ * @returns Current *pi32 value
+ * @param   pi32    Pointer to the 32-bit variable to read.
+ */
+DECLINLINE(int32_t) ASMAtomicReadS32(volatile int32_t *pi32)
+{
+    ASMMemoryFence();
+    Assert(!((uintptr_t)pi32 & 3));
+#if ARCH_BITS == 16
+    AssertFailed();  /** @todo 16-bit */
+#endif
+    return *pi32;
+}
+
+
+/**
+ * Atomically reads a signed 32-bit value, unordered.
+ *
+ * @returns Current *pi32 value
+ * @param   pi32    Pointer to the 32-bit variable to read.
+ */
+DECLINLINE(int32_t) ASMAtomicUoReadS32(volatile int32_t *pi32)
+{
+    Assert(!((uintptr_t)pi32 & 3));
+#if ARCH_BITS == 16
+    AssertFailed();  /** @todo 16-bit */
+#endif
+    return *pi32;
+}
+
+
+/**
+ * Atomically reads an unsigned 64-bit value, ordered.
+ *
+ * @returns Current *pu64 value
+ * @param   pu64    Pointer to the 64-bit variable to read.
+ *                  The memory pointed to must be writable.
+ *
+ * @remarks This may fault if the memory is read-only!
+ * @remarks x86: Requires a Pentium or later.
+ */
+#if (RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)) \
+ || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC
+DECLASM(uint64_t) ASMAtomicReadU64(volatile uint64_t *pu64);
+#else
+DECLINLINE(uint64_t) ASMAtomicReadU64(volatile uint64_t *pu64)
+{
+    uint64_t u64;
+# ifdef RT_ARCH_AMD64
+    Assert(!((uintptr_t)pu64 & 7));
+/*#  if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__(  "mfence\n\t"
+                           "movq %1, %0\n\t"
+                         : "=r" (u64)
+                         : "m" (*pu64));
+#  else
+    __asm
+    {
+        mfence
+        mov     rdx, [pu64]
+        mov     rax, [rdx]
+        mov     [u64], rax
+    }
+#  endif*/
+    ASMMemoryFence();
+    u64 = *pu64;
+# else /* !RT_ARCH_AMD64 */
+#  if RT_INLINE_ASM_GNU_STYLE
+#   if defined(PIC) || defined(__PIC__)
+    uint32_t u32EBX = 0;
+    Assert(!((uintptr_t)pu64 & 7));
+    __asm__ __volatile__("xchgl %%ebx, %3\n\t"
+                         "lock; cmpxchg8b (%5)\n\t"
+                         "movl %3, %%ebx\n\t"
+                         : "=A" (u64),
+#    if RT_GNUC_PREREQ(4, 3)
+                           "+m" (*pu64)
+#    else
+                           "=m" (*pu64)
+#    endif
+                         : "0" (0ULL),
+                           "m" (u32EBX),
+                           "c" (0),
+                           "S" (pu64));
+#   else /* !PIC */
+    __asm__ __volatile__("lock; cmpxchg8b %1\n\t"
+                         : "=A" (u64),
+                           "+m" (*pu64)
+                         : "0" (0ULL),
+                           "b" (0),
+                           "c" (0));
+#   endif
+#  else
+    Assert(!((uintptr_t)pu64 & 7));
+    __asm
+    {
+        xor     eax, eax
+        xor     edx, edx
+        mov     edi, pu64
+        xor     ecx, ecx
+        xor     ebx, ebx
+        lock cmpxchg8b [edi]
+        mov     dword ptr [u64], eax
+        mov     dword ptr [u64 + 4], edx
+    }
+#  endif
+# endif /* !RT_ARCH_AMD64 */
+    return u64;
+}
+#endif
+
+
+/**
+ * Atomically reads an unsigned 64-bit value, unordered.
+ *
+ * @returns Current *pu64 value
+ * @param   pu64    Pointer to the 64-bit variable to read.
+ *                  The memory pointed to must be writable.
+ *
+ * @remarks This may fault if the memory is read-only!
+ * @remarks x86: Requires a Pentium or later.
+ */
+#if !defined(RT_ARCH_AMD64) \
+  && (   (RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN) \
+      || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC)
+DECLASM(uint64_t) ASMAtomicUoReadU64(volatile uint64_t *pu64);
+#else
+DECLINLINE(uint64_t) ASMAtomicUoReadU64(volatile uint64_t *pu64)
+{
+    uint64_t u64;
+# ifdef RT_ARCH_AMD64
+    Assert(!((uintptr_t)pu64 & 7));
+/*#  if RT_INLINE_ASM_GNU_STYLE
+    Assert(!((uintptr_t)pu64 & 7));
+    __asm__ __volatile__("movq %1, %0\n\t"
+                         : "=r" (u64)
+                         : "m" (*pu64));
+#  else
+    __asm
+    {
+        mov     rdx, [pu64]
+        mov     rax, [rdx]
+        mov     [u64], rax
+    }
+#  endif */
+    u64 = *pu64;
+# else /* !RT_ARCH_AMD64 */
+#  if RT_INLINE_ASM_GNU_STYLE
+#   if defined(PIC) || defined(__PIC__)
+    uint32_t u32EBX = 0;
+    uint32_t u32Spill;
+    Assert(!((uintptr_t)pu64 & 7));
+    __asm__ __volatile__("xor   %%eax,%%eax\n\t"
+                         "xor   %%ecx,%%ecx\n\t"
+                         "xor   %%edx,%%edx\n\t"
+                         "xchgl %%ebx, %3\n\t"
+                         "lock; cmpxchg8b (%4)\n\t"
+                         "movl %3, %%ebx\n\t"
+                         : "=A" (u64),
+#    if RT_GNUC_PREREQ(4, 3)
+                           "+m" (*pu64),
+#    else
+                           "=m" (*pu64),
+#    endif
+                           "=c" (u32Spill)
+                         : "m" (u32EBX),
+                           "S" (pu64));
+#   else /* !PIC */
+    __asm__ __volatile__("lock; cmpxchg8b %1\n\t"
+                         : "=A" (u64),
+                           "+m" (*pu64)
+                         : "0" (0ULL),
+                           "b" (0),
+                           "c" (0));
+#   endif
+#  else
+    Assert(!((uintptr_t)pu64 & 7));
+    __asm
+    {
+        xor     eax, eax
+        xor     edx, edx
+        mov     edi, pu64
+        xor     ecx, ecx
+        xor     ebx, ebx
+        lock cmpxchg8b [edi]
+        mov     dword ptr [u64], eax
+        mov     dword ptr [u64 + 4], edx
+    }
+#  endif
+# endif /* !RT_ARCH_AMD64 */
+    return u64;
+}
+#endif
+
+
+/**
+ * Atomically reads a signed 64-bit value, ordered.
+ *
+ * @returns Current *pi64 value
+ * @param   pi64    Pointer to the 64-bit variable to read.
+ *                  The memory pointed to must be writable.
+ *
+ * @remarks This may fault if the memory is read-only!
+ * @remarks x86: Requires a Pentium or later.
+ */
+DECLINLINE(int64_t) ASMAtomicReadS64(volatile int64_t *pi64)
+{
+    return (int64_t)ASMAtomicReadU64((volatile uint64_t *)pi64);
+}
+
+
+/**
+ * Atomically reads a signed 64-bit value, unordered.
+ *
+ * @returns Current *pi64 value
+ * @param   pi64    Pointer to the 64-bit variable to read.
+ *                  The memory pointed to must be writable.
+ *
+ * @remarks This will fault if the memory is read-only!
+ * @remarks x86: Requires a Pentium or later.
+ */
+DECLINLINE(int64_t) ASMAtomicUoReadS64(volatile int64_t *pi64)
+{
+    return (int64_t)ASMAtomicUoReadU64((volatile uint64_t *)pi64);
+}
+
+
+/**
+ * Atomically reads a size_t value, ordered.
+ *
+ * @returns Current *pcb value
+ * @param   pcb     Pointer to the size_t variable to read.
+ */
+DECLINLINE(size_t) ASMAtomicReadZ(size_t volatile *pcb)
+{
+#if ARCH_BITS == 64
+    return ASMAtomicReadU64((uint64_t volatile *)pcb);
+#elif ARCH_BITS == 32
+    return ASMAtomicReadU32((uint32_t volatile *)pcb);
+#elif ARCH_BITS == 16
+    AssertCompileSize(size_t, 2);
+    return ASMAtomicReadU16((uint16_t volatile *)pcb);
+#else
+# error "Unsupported ARCH_BITS value"
+#endif
+}
+
+
+/**
+ * Atomically reads a size_t value, unordered.
+ *
+ * @returns Current *pcb value
+ * @param   pcb     Pointer to the size_t variable to read.
+ */
+DECLINLINE(size_t) ASMAtomicUoReadZ(size_t volatile *pcb)
+{
+#if ARCH_BITS == 64 || (ARCH_BITS == 16 && RT_FAR_DATA)
+    return ASMAtomicUoReadU64((uint64_t volatile *)pcb);
+#elif ARCH_BITS == 32
+    return ASMAtomicUoReadU32((uint32_t volatile *)pcb);
+#elif ARCH_BITS == 16
+    AssertCompileSize(size_t, 2);
+    return ASMAtomicUoReadU16((uint16_t volatile *)pcb);
+#else
+# error "Unsupported ARCH_BITS value"
+#endif
+}
+
+
+/**
+ * Atomically reads a pointer value, ordered.
+ *
+ * @returns Current *pv value
+ * @param   ppv     Pointer to the pointer variable to read.
+ *
+ * @remarks Please use ASMAtomicReadPtrT, it provides better type safety and
+ *          requires less typing (no casts).
+ */
+DECLINLINE(void *) ASMAtomicReadPtr(void * volatile *ppv)
+{
+#if ARCH_BITS == 32 || (ARCH_BITS == 16 && RT_FAR_DATA)
+    return (void *)ASMAtomicReadU32((volatile uint32_t *)(void *)ppv);
+#elif ARCH_BITS == 64
+    return (void *)ASMAtomicReadU64((volatile uint64_t *)(void *)ppv);
+#else
+# error "ARCH_BITS is bogus"
+#endif
+}
+
+/**
+ * Convenience macro for avoiding the annoying casting with ASMAtomicReadPtr.
+ *
+ * @returns Current *pv value
+ * @param   ppv     Pointer to the pointer variable to read.
+ * @param   Type    The type of *ppv, sans volatile.
+ */
+#ifdef __GNUC__
+# define ASMAtomicReadPtrT(ppv, Type) \
+    __extension__ \
+    ({\
+        __typeof__(*(ppv)) volatile *ppvTypeChecked = (ppv); \
+        Type pvTypeChecked = (__typeof__(*(ppv))) ASMAtomicReadPtr((void * volatile *)ppvTypeChecked); \
+        pvTypeChecked; \
+     })
+#else
+# define ASMAtomicReadPtrT(ppv, Type) \
+    (Type)ASMAtomicReadPtr((void * volatile *)(ppv))
+#endif
+
+
+/**
+ * Atomically reads a pointer value, unordered.
+ *
+ * @returns Current *pv value
+ * @param   ppv     Pointer to the pointer variable to read.
+ *
+ * @remarks Please use ASMAtomicUoReadPtrT, it provides better type safety and
+ *          requires less typing (no casts).
+ */
+DECLINLINE(void *) ASMAtomicUoReadPtr(void * volatile *ppv)
+{
+#if ARCH_BITS == 32 || (ARCH_BITS == 16 && RT_FAR_DATA)
+    return (void *)ASMAtomicUoReadU32((volatile uint32_t *)(void *)ppv);
+#elif ARCH_BITS == 64
+    return (void *)ASMAtomicUoReadU64((volatile uint64_t *)(void *)ppv);
+#else
+# error "ARCH_BITS is bogus"
+#endif
+}
+
+
+/**
+ * Convenience macro for avoiding the annoying casting with ASMAtomicUoReadPtr.
+ *
+ * @returns Current *pv value
+ * @param   ppv     Pointer to the pointer variable to read.
+ * @param   Type    The type of *ppv, sans volatile.
+ */
+#ifdef __GNUC__
+# define ASMAtomicUoReadPtrT(ppv, Type) \
+    __extension__ \
+    ({\
+        __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \
+        Type pvTypeChecked = (__typeof__(*(ppv))) ASMAtomicUoReadPtr((void * volatile *)ppvTypeChecked); \
+        pvTypeChecked; \
+     })
+#else
+# define ASMAtomicUoReadPtrT(ppv, Type) \
+    (Type)ASMAtomicUoReadPtr((void * volatile *)(ppv))
+#endif
+
+
+/**
+ * Atomically reads a boolean value, ordered.
+ *
+ * @returns Current *pf value
+ * @param   pf      Pointer to the boolean variable to read.
+ */
+DECLINLINE(bool) ASMAtomicReadBool(volatile bool *pf)
+{
+    ASMMemoryFence();
+    return *pf;     /* byte reads are atomic on x86 */
+}
+
+
+/**
+ * Atomically reads a boolean value, unordered.
+ *
+ * @returns Current *pf value
+ * @param   pf      Pointer to the boolean variable to read.
+ */
+DECLINLINE(bool) ASMAtomicUoReadBool(volatile bool *pf)
+{
+    return *pf;     /* byte reads are atomic on x86 */
+}
+
+
+/**
+ * Atomically read a typical IPRT handle value, ordered.
+ *
+ * @param   ph      Pointer to the handle variable to read.
+ * @param   phRes   Where to store the result.
+ *
+ * @remarks This doesn't currently work for all handles (like RTFILE).
+ */
+#if HC_ARCH_BITS == 32 || (ARCH_BITS == 16 && RT_FAR_DATA)
+# define ASMAtomicReadHandle(ph, phRes) \
+    do { \
+        AssertCompile(sizeof(*(ph))    == sizeof(uint32_t)); \
+        AssertCompile(sizeof(*(phRes)) == sizeof(uint32_t)); \
+        *(uint32_t *)(phRes) = ASMAtomicReadU32((uint32_t volatile *)(ph)); \
+    } while (0)
+#elif HC_ARCH_BITS == 64
+# define ASMAtomicReadHandle(ph, phRes) \
+    do { \
+        AssertCompile(sizeof(*(ph))    == sizeof(uint64_t)); \
+        AssertCompile(sizeof(*(phRes)) == sizeof(uint64_t)); \
+        *(uint64_t *)(phRes) = ASMAtomicReadU64((uint64_t volatile *)(ph)); \
+    } while (0)
+#else
+# error HC_ARCH_BITS
+#endif
+
+
+/**
+ * Atomically read a typical IPRT handle value, unordered.
+ *
+ * @param   ph      Pointer to the handle variable to read.
+ * @param   phRes   Where to store the result.
+ *
+ * @remarks This doesn't currently work for all handles (like RTFILE).
+ */
+#if HC_ARCH_BITS == 32 || (ARCH_BITS == 16 && RT_FAR_DATA)
+# define ASMAtomicUoReadHandle(ph, phRes) \
+    do { \
+        AssertCompile(sizeof(*(ph))    == sizeof(uint32_t)); \
+        AssertCompile(sizeof(*(phRes)) == sizeof(uint32_t)); \
+        *(uint32_t *)(phRes) = ASMAtomicUoReadU32((uint32_t volatile *)(ph)); \
+    } while (0)
+#elif HC_ARCH_BITS == 64
+# define ASMAtomicUoReadHandle(ph, phRes) \
+    do { \
+        AssertCompile(sizeof(*(ph))    == sizeof(uint64_t)); \
+        AssertCompile(sizeof(*(phRes)) == sizeof(uint64_t)); \
+        *(uint64_t *)(phRes) = ASMAtomicUoReadU64((uint64_t volatile *)(ph)); \
+    } while (0)
+#else
+# error HC_ARCH_BITS
+#endif
+
+
+/**
+ * Atomically read a value which size might differ
+ * between platforms or compilers, ordered.
+ *
+ * @param   pu      Pointer to the variable to read.
+ * @param   puRes   Where to store the result.
+ */
+#define ASMAtomicReadSize(pu, puRes) \
+    do { \
+        switch (sizeof(*(pu))) { \
+            case 1: *(uint8_t  *)(puRes) = ASMAtomicReadU8( (volatile uint8_t  *)(void *)(pu)); break; \
+            case 2: *(uint16_t *)(puRes) = ASMAtomicReadU16((volatile uint16_t *)(void *)(pu)); break; \
+            case 4: *(uint32_t *)(puRes) = ASMAtomicReadU32((volatile uint32_t *)(void *)(pu)); break; \
+            case 8: *(uint64_t *)(puRes) = ASMAtomicReadU64((volatile uint64_t *)(void *)(pu)); break; \
+            default: AssertMsgFailed(("ASMAtomicReadSize: size %d is not supported\n", sizeof(*(pu)))); \
+        } \
+    } while (0)
+
+
+/**
+ * Atomically read a value which size might differ
+ * between platforms or compilers, unordered.
+ *
+ * @param   pu      Pointer to the variable to read.
+ * @param   puRes   Where to store the result.
+ */
+#define ASMAtomicUoReadSize(pu, puRes) \
+    do { \
+        switch (sizeof(*(pu))) { \
+            case 1: *(uint8_t  *)(puRes) = ASMAtomicUoReadU8( (volatile uint8_t  *)(void *)(pu)); break; \
+            case 2: *(uint16_t *)(puRes) = ASMAtomicUoReadU16((volatile uint16_t *)(void *)(pu)); break; \
+            case 4: *(uint32_t *)(puRes) = ASMAtomicUoReadU32((volatile uint32_t *)(void *)(pu)); break; \
+            case 8: *(uint64_t *)(puRes) = ASMAtomicUoReadU64((volatile uint64_t *)(void *)(pu)); break; \
+            default: AssertMsgFailed(("ASMAtomicReadSize: size %d is not supported\n", sizeof(*(pu)))); \
+        } \
+    } while (0)
+
+
+/**
+ * Atomically writes an unsigned 8-bit value, ordered.
+ *
+ * @param   pu8     Pointer to the 8-bit variable.
+ * @param   u8      The 8-bit value to assign to *pu8.
+ */
+DECLINLINE(void) ASMAtomicWriteU8(volatile uint8_t *pu8, uint8_t u8)
+{
+    ASMAtomicXchgU8(pu8, u8);
+}
+
+
+/**
+ * Atomically writes an unsigned 8-bit value, unordered.
+ *
+ * @param   pu8     Pointer to the 8-bit variable.
+ * @param   u8      The 8-bit value to assign to *pu8.
+ */
+DECLINLINE(void) ASMAtomicUoWriteU8(volatile uint8_t *pu8, uint8_t u8)
+{
+    *pu8 = u8;      /* byte writes are atomic on x86 */
+}
+
+
+/**
+ * Atomically writes a signed 8-bit value, ordered.
+ *
+ * @param   pi8     Pointer to the 8-bit variable to read.
+ * @param   i8      The 8-bit value to assign to *pi8.
+ */
+DECLINLINE(void) ASMAtomicWriteS8(volatile int8_t *pi8, int8_t i8)
+{
+    ASMAtomicXchgS8(pi8, i8);
+}
+
+
+/**
+ * Atomically writes a signed 8-bit value, unordered.
+ *
+ * @param   pi8     Pointer to the 8-bit variable to write.
+ * @param   i8      The 8-bit value to assign to *pi8.
+ */
+DECLINLINE(void) ASMAtomicUoWriteS8(volatile int8_t *pi8, int8_t i8)
+{
+    *pi8 = i8;      /* byte writes are atomic on x86 */
+}
+
+
+/**
+ * Atomically writes an unsigned 16-bit value, ordered.
+ *
+ * @param   pu16    Pointer to the 16-bit variable to write.
+ * @param   u16     The 16-bit value to assign to *pu16.
+ */
+DECLINLINE(void) ASMAtomicWriteU16(volatile uint16_t *pu16, uint16_t u16)
+{
+    ASMAtomicXchgU16(pu16, u16);
+}
+
+
+/**
+ * Atomically writes an unsigned 16-bit value, unordered.
+ *
+ * @param   pu16    Pointer to the 16-bit variable to write.
+ * @param   u16     The 16-bit value to assign to *pu16.
+ */
+DECLINLINE(void) ASMAtomicUoWriteU16(volatile uint16_t *pu16, uint16_t u16)
+{
+    Assert(!((uintptr_t)pu16 & 1));
+    *pu16 = u16;
+}
+
+
+/**
+ * Atomically writes a signed 16-bit value, ordered.
+ *
+ * @param   pi16    Pointer to the 16-bit variable to write.
+ * @param   i16     The 16-bit value to assign to *pi16.
+ */
+DECLINLINE(void) ASMAtomicWriteS16(volatile int16_t *pi16, int16_t i16)
+{
+    ASMAtomicXchgS16(pi16, i16);
+}
+
+
+/**
+ * Atomically writes a signed 16-bit value, unordered.
+ *
+ * @param   pi16    Pointer to the 16-bit variable to write.
+ * @param   i16     The 16-bit value to assign to *pi16.
+ */
+DECLINLINE(void) ASMAtomicUoWriteS16(volatile int16_t *pi16, int16_t i16)
+{
+    Assert(!((uintptr_t)pi16 & 1));
+    *pi16 = i16;
+}
+
+
+/**
+ * Atomically writes an unsigned 32-bit value, ordered.
+ *
+ * @param   pu32    Pointer to the 32-bit variable to write.
+ * @param   u32     The 32-bit value to assign to *pu32.
+ */
+DECLINLINE(void) ASMAtomicWriteU32(volatile uint32_t *pu32, uint32_t u32)
+{
+    ASMAtomicXchgU32(pu32, u32);
+}
+
+
+/**
+ * Atomically writes an unsigned 32-bit value, unordered.
+ *
+ * @param   pu32    Pointer to the 32-bit variable to write.
+ * @param   u32     The 32-bit value to assign to *pu32.
+ */
+DECLINLINE(void) ASMAtomicUoWriteU32(volatile uint32_t *pu32, uint32_t u32)
+{
+    Assert(!((uintptr_t)pu32 & 3));
+#if ARCH_BITS >= 32
+    *pu32 = u32;
+#else
+    ASMAtomicXchgU32(pu32, u32);
+#endif
+}
+
+
+/**
+ * Atomically writes a signed 32-bit value, ordered.
+ *
+ * @param   pi32    Pointer to the 32-bit variable to write.
+ * @param   i32     The 32-bit value to assign to *pi32.
+ */
+DECLINLINE(void) ASMAtomicWriteS32(volatile int32_t *pi32, int32_t i32)
+{
+    ASMAtomicXchgS32(pi32, i32);
+}
+
+
+/**
+ * Atomically writes a signed 32-bit value, unordered.
+ *
+ * @param   pi32    Pointer to the 32-bit variable to write.
+ * @param   i32     The 32-bit value to assign to *pi32.
+ */
+DECLINLINE(void) ASMAtomicUoWriteS32(volatile int32_t *pi32, int32_t i32)
+{
+    Assert(!((uintptr_t)pi32 & 3));
+#if ARCH_BITS >= 32
+    *pi32 = i32;
+#else
+    ASMAtomicXchgS32(pi32, i32);
+#endif
+}
+
+
+/**
+ * Atomically writes an unsigned 64-bit value, ordered.
+ *
+ * @param   pu64    Pointer to the 64-bit variable to write.
+ * @param   u64     The 64-bit value to assign to *pu64.
+ */
+DECLINLINE(void) ASMAtomicWriteU64(volatile uint64_t *pu64, uint64_t u64)
+{
+    ASMAtomicXchgU64(pu64, u64);
+}
+
+
+/**
+ * Atomically writes an unsigned 64-bit value, unordered.
+ *
+ * @param   pu64    Pointer to the 64-bit variable to write.
+ * @param   u64     The 64-bit value to assign to *pu64.
+ */
+DECLINLINE(void) ASMAtomicUoWriteU64(volatile uint64_t *pu64, uint64_t u64)
+{
+    Assert(!((uintptr_t)pu64 & 7));
+#if ARCH_BITS == 64
+    *pu64 = u64;
+#else
+    ASMAtomicXchgU64(pu64, u64);
+#endif
+}
+
+
+/**
+ * Atomically writes a signed 64-bit value, ordered.
+ *
+ * @param   pi64    Pointer to the 64-bit variable to write.
+ * @param   i64     The 64-bit value to assign to *pi64.
+ */
+DECLINLINE(void) ASMAtomicWriteS64(volatile int64_t *pi64, int64_t i64)
+{
+    ASMAtomicXchgS64(pi64, i64);
+}
+
+
+/**
+ * Atomically writes a signed 64-bit value, unordered.
+ *
+ * @param   pi64    Pointer to the 64-bit variable to write.
+ * @param   i64     The 64-bit value to assign to *pi64.
+ */
+DECLINLINE(void) ASMAtomicUoWriteS64(volatile int64_t *pi64, int64_t i64)
+{
+    Assert(!((uintptr_t)pi64 & 7));
+#if ARCH_BITS == 64
+    *pi64 = i64;
+#else
+    ASMAtomicXchgS64(pi64, i64);
+#endif
+}
+
+
+/**
+ * Atomically writes a boolean value, unordered.
+ *
+ * @param   pf      Pointer to the boolean variable to write.
+ * @param   f       The boolean value to assign to *pf.
+ */
+DECLINLINE(void) ASMAtomicWriteBool(volatile bool *pf, bool f)
+{
+    ASMAtomicWriteU8((uint8_t volatile *)pf, f);
+}
+
+
+/**
+ * Atomically writes a boolean value, unordered.
+ *
+ * @param   pf      Pointer to the boolean variable to write.
+ * @param   f       The boolean value to assign to *pf.
+ */
+DECLINLINE(void) ASMAtomicUoWriteBool(volatile bool *pf, bool f)
+{
+    *pf = f;    /* byte writes are atomic on x86 */
+}
+
+
+/**
+ * Atomically writes a pointer value, ordered.
+ *
+ * @param   ppv     Pointer to the pointer variable to write.
+ * @param   pv      The pointer value to assign to *ppv.
+ */
+DECLINLINE(void) ASMAtomicWritePtrVoid(void * volatile *ppv, const void *pv)
+{
+#if ARCH_BITS == 32 || (ARCH_BITS == 16 && RT_FAR_DATA)
+    ASMAtomicWriteU32((volatile uint32_t *)(void *)ppv, (uint32_t)pv);
+#elif ARCH_BITS == 64
+    ASMAtomicWriteU64((volatile uint64_t *)(void *)ppv, (uint64_t)pv);
+#else
+# error "ARCH_BITS is bogus"
+#endif
+}
+
+
+/**
+ * Atomically writes a pointer value, ordered.
+ *
+ * @param   ppv     Pointer to the pointer variable to write.
+ * @param   pv      The pointer value to assign to *ppv. If NULL use
+ *                  ASMAtomicWriteNullPtr or you'll land in trouble.
+ *
+ * @remarks This is relatively type safe on GCC platforms when @a pv isn't
+ *          NULL.
+ */
+#ifdef __GNUC__
+# define ASMAtomicWritePtr(ppv, pv) \
+    do \
+    { \
+        __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \
+        __typeof__(*(ppv))            const pvTypeChecked  = (pv); \
+        \
+        AssertCompile(sizeof(*ppv) == sizeof(void *)); \
+        AssertCompile(sizeof(pv) == sizeof(void *)); \
+        Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
+        \
+        ASMAtomicWritePtrVoid((void * volatile *)(ppvTypeChecked), (void *)(pvTypeChecked)); \
+    } while (0)
+#else
+# define ASMAtomicWritePtr(ppv, pv) \
+    do \
+    { \
+        AssertCompile(sizeof(*ppv) == sizeof(void *)); \
+        AssertCompile(sizeof(pv) == sizeof(void *)); \
+        Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
+        \
+        ASMAtomicWritePtrVoid((void * volatile *)(ppv), (void *)(pv)); \
+    } while (0)
+#endif
+
+
+/**
+ * Atomically sets a pointer to NULL, ordered.
+ *
+ * @param   ppv     Pointer to the pointer variable that should be set to NULL.
+ *
+ * @remarks This is relatively type safe on GCC platforms.
+ */
+#ifdef __GNUC__
+# define ASMAtomicWriteNullPtr(ppv) \
+    do \
+    { \
+        __typeof__(*(ppv)) * const ppvTypeChecked = (ppv); \
+        AssertCompile(sizeof(*ppv) == sizeof(void *)); \
+        Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
+        ASMAtomicWritePtrVoid((void * volatile *)(ppvTypeChecked), NULL); \
+    } while (0)
+#else
+# define ASMAtomicWriteNullPtr(ppv) \
+    do \
+    { \
+        AssertCompile(sizeof(*ppv) == sizeof(void *)); \
+        Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
+        ASMAtomicWritePtrVoid((void * volatile *)(ppv), NULL); \
+    } while (0)
+#endif
+
+
+/**
+ * Atomically writes a pointer value, unordered.
+ *
+ * @returns Current *pv value
+ * @param   ppv     Pointer to the pointer variable.
+ * @param   pv      The pointer value to assign to *ppv. If NULL use
+ *                  ASMAtomicUoWriteNullPtr or you'll land in trouble.
+ *
+ * @remarks This is relatively type safe on GCC platforms when @a pv isn't
+ *          NULL.
+ */
+#ifdef __GNUC__
+# define ASMAtomicUoWritePtr(ppv, pv) \
+    do \
+    { \
+        __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \
+        __typeof__(*(ppv))            const pvTypeChecked  = (pv); \
+        \
+        AssertCompile(sizeof(*ppv) == sizeof(void *)); \
+        AssertCompile(sizeof(pv) == sizeof(void *)); \
+        Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
+        \
+        *(ppvTypeChecked) = pvTypeChecked; \
+    } while (0)
+#else
+# define ASMAtomicUoWritePtr(ppv, pv) \
+    do \
+    { \
+        AssertCompile(sizeof(*ppv) == sizeof(void *)); \
+        AssertCompile(sizeof(pv) == sizeof(void *)); \
+        Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
+        *(ppv) = pv; \
+    } while (0)
+#endif
+
+
+/**
+ * Atomically sets a pointer to NULL, unordered.
+ *
+ * @param   ppv     Pointer to the pointer variable that should be set to NULL.
+ *
+ * @remarks This is relatively type safe on GCC platforms.
+ */
+#ifdef __GNUC__
+# define ASMAtomicUoWriteNullPtr(ppv) \
+    do \
+    { \
+        __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \
+        AssertCompile(sizeof(*ppv) == sizeof(void *)); \
+        Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
+        *(ppvTypeChecked) = NULL; \
+    } while (0)
+#else
+# define ASMAtomicUoWriteNullPtr(ppv) \
+    do \
+    { \
+        AssertCompile(sizeof(*ppv) == sizeof(void *)); \
+        Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
+        *(ppv) = NULL; \
+    } while (0)
+#endif
+
+
+/**
+ * Atomically write a typical IPRT handle value, ordered.
+ *
+ * @param   ph      Pointer to the variable to update.
+ * @param   hNew    The value to assign to *ph.
+ *
+ * @remarks This doesn't currently work for all handles (like RTFILE).
+ */
+#if HC_ARCH_BITS == 32 || (ARCH_BITS == 16 && RT_FAR_DATA)
+# define ASMAtomicWriteHandle(ph, hNew) \
+    do { \
+        AssertCompile(sizeof(*(ph)) == sizeof(uint32_t)); \
+        ASMAtomicWriteU32((uint32_t volatile *)(ph), (const uint32_t)(hNew)); \
+    } while (0)
+#elif HC_ARCH_BITS == 64
+# define ASMAtomicWriteHandle(ph, hNew) \
+    do { \
+        AssertCompile(sizeof(*(ph)) == sizeof(uint64_t)); \
+        ASMAtomicWriteU64((uint64_t volatile *)(ph), (const uint64_t)(hNew)); \
+    } while (0)
+#else
+# error HC_ARCH_BITS
+#endif
+
+
+/**
+ * Atomically write a typical IPRT handle value, unordered.
+ *
+ * @param   ph      Pointer to the variable to update.
+ * @param   hNew    The value to assign to *ph.
+ *
+ * @remarks This doesn't currently work for all handles (like RTFILE).
+ */
+#if HC_ARCH_BITS == 32 || (ARCH_BITS == 16 && RT_FAR_DATA)
+# define ASMAtomicUoWriteHandle(ph, hNew) \
+    do { \
+        AssertCompile(sizeof(*(ph)) == sizeof(uint32_t)); \
+        ASMAtomicUoWriteU32((uint32_t volatile *)(ph), (const uint32_t)hNew); \
+    } while (0)
+#elif HC_ARCH_BITS == 64
+# define ASMAtomicUoWriteHandle(ph, hNew) \
+    do { \
+        AssertCompile(sizeof(*(ph)) == sizeof(uint64_t)); \
+        ASMAtomicUoWriteU64((uint64_t volatile *)(ph), (const uint64_t)hNew); \
+    } while (0)
+#else
+# error HC_ARCH_BITS
+#endif
+
+
+/**
+ * Atomically write a value which size might differ
+ * between platforms or compilers, ordered.
+ *
+ * @param   pu      Pointer to the variable to update.
+ * @param   uNew    The value to assign to *pu.
+ */
+#define ASMAtomicWriteSize(pu, uNew) \
+    do { \
+        switch (sizeof(*(pu))) { \
+            case 1: ASMAtomicWriteU8( (volatile uint8_t  *)(void *)(pu), (uint8_t )(uNew)); break; \
+            case 2: ASMAtomicWriteU16((volatile uint16_t *)(void *)(pu), (uint16_t)(uNew)); break; \
+            case 4: ASMAtomicWriteU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew)); break; \
+            case 8: ASMAtomicWriteU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew)); break; \
+            default: AssertMsgFailed(("ASMAtomicWriteSize: size %d is not supported\n", sizeof(*(pu)))); \
+        } \
+    } while (0)
+
+/**
+ * Atomically write a value which size might differ
+ * between platforms or compilers, unordered.
+ *
+ * @param   pu      Pointer to the variable to update.
+ * @param   uNew    The value to assign to *pu.
+ */
+#define ASMAtomicUoWriteSize(pu, uNew) \
+    do { \
+        switch (sizeof(*(pu))) { \
+            case 1: ASMAtomicUoWriteU8( (volatile uint8_t  *)(void *)(pu), (uint8_t )(uNew)); break; \
+            case 2: ASMAtomicUoWriteU16((volatile uint16_t *)(void *)(pu), (uint16_t)(uNew)); break; \
+            case 4: ASMAtomicUoWriteU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew)); break; \
+            case 8: ASMAtomicUoWriteU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew)); break; \
+            default: AssertMsgFailed(("ASMAtomicWriteSize: size %d is not supported\n", sizeof(*(pu)))); \
+        } \
+    } while (0)
+
+
+
+/**
+ * Atomically exchanges and adds to a 16-bit value, ordered.
+ *
+ * @returns The old value.
+ * @param   pu16        Pointer to the value.
+ * @param   u16         Number to add.
+ *
+ * @remarks Currently not implemented, just to make 16-bit code happy.
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLASM(uint16_t) ASMAtomicAddU16(uint16_t volatile *pu16, uint32_t u16);
+
+
+/**
+ * Atomically exchanges and adds to a 32-bit value, ordered.
+ *
+ * @returns The old value.
+ * @param   pu32        Pointer to the value.
+ * @param   u32         Number to add.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint32_t) ASMAtomicAddU32(uint32_t volatile *pu32, uint32_t u32);
+#else
+DECLINLINE(uint32_t) ASMAtomicAddU32(uint32_t volatile *pu32, uint32_t u32)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    u32 = _InterlockedExchangeAdd((long *)pu32, u32);
+    return u32;
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("lock; xaddl %0, %1\n\t"
+                         : "=r" (u32),
+                           "=m" (*pu32)
+                         : "0" (u32),
+                           "m" (*pu32)
+                         : "memory");
+    return u32;
+# else
+    __asm
+    {
+        mov     eax, [u32]
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [pu32]
+        lock xadd [rdx], eax
+#  else
+        mov     edx, [pu32]
+        lock xadd [edx], eax
+#  endif
+        mov     [u32], eax
+    }
+    return u32;
+# endif
+}
+#endif
+
+
+/**
+ * Atomically exchanges and adds to a signed 32-bit value, ordered.
+ *
+ * @returns The old value.
+ * @param   pi32        Pointer to the value.
+ * @param   i32         Number to add.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(int32_t) ASMAtomicAddS32(int32_t volatile *pi32, int32_t i32)
+{
+    return (int32_t)ASMAtomicAddU32((uint32_t volatile *)pi32, (uint32_t)i32);
+}
+
+
+/**
+ * Atomically exchanges and adds to a 64-bit value, ordered.
+ *
+ * @returns The old value.
+ * @param   pu64        Pointer to the value.
+ * @param   u64         Number to add.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint64_t) ASMAtomicAddU64(uint64_t volatile *pu64, uint64_t u64);
+#else
+DECLINLINE(uint64_t) ASMAtomicAddU64(uint64_t volatile *pu64, uint64_t u64)
+{
+# if RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_AMD64)
+    u64 = _InterlockedExchangeAdd64((__int64 *)pu64, u64);
+    return u64;
+
+# elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64)
+    __asm__ __volatile__("lock; xaddq %0, %1\n\t"
+                         : "=r" (u64),
+                           "=m" (*pu64)
+                         : "0" (u64),
+                           "m" (*pu64)
+                         : "memory");
+    return u64;
+# else
+    uint64_t u64Old;
+    for (;;)
+    {
+        uint64_t u64New;
+        u64Old = ASMAtomicUoReadU64(pu64);
+        u64New = u64Old + u64;
+        if (ASMAtomicCmpXchgU64(pu64, u64New, u64Old))
+            break;
+        ASMNopPause();
+    }
+    return u64Old;
+# endif
+}
+#endif
+
+
+/**
+ * Atomically exchanges and adds to a signed 64-bit value, ordered.
+ *
+ * @returns The old value.
+ * @param   pi64        Pointer to the value.
+ * @param   i64         Number to add.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+DECLINLINE(int64_t) ASMAtomicAddS64(int64_t volatile *pi64, int64_t i64)
+{
+    return (int64_t)ASMAtomicAddU64((uint64_t volatile *)pi64, (uint64_t)i64);
+}
+
+
+/**
+ * Atomically exchanges and adds to a size_t value, ordered.
+ *
+ * @returns The old value.
+ * @param   pcb         Pointer to the size_t value.
+ * @param   cb          Number to add.
+ */
+DECLINLINE(size_t) ASMAtomicAddZ(size_t volatile *pcb, size_t cb)
+{
+#if ARCH_BITS == 64
+    AssertCompileSize(size_t, 8);
+    return ASMAtomicAddU64((uint64_t volatile *)pcb, cb);
+#elif ARCH_BITS == 32
+    AssertCompileSize(size_t, 4);
+    return ASMAtomicAddU32((uint32_t volatile *)pcb, cb);
+#elif ARCH_BITS == 16
+    AssertCompileSize(size_t, 2);
+    return ASMAtomicAddU16((uint16_t volatile *)pcb, cb);
+#else
+# error "Unsupported ARCH_BITS value"
+#endif
+}
+
+
+/**
+ * Atomically exchanges and adds a value which size might differ between
+ * platforms or compilers, ordered.
+ *
+ * @param   pu      Pointer to the variable to update.
+ * @param   uNew    The value to add to *pu.
+ * @param   puOld   Where to store the old value.
+ */
+#define ASMAtomicAddSize(pu, uNew, puOld) \
+    do { \
+        switch (sizeof(*(pu))) { \
+            case 4: *(uint32_t  *)(puOld) = ASMAtomicAddU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew)); break; \
+            case 8: *(uint64_t  *)(puOld) = ASMAtomicAddU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew)); break; \
+            default: AssertMsgFailed(("ASMAtomicAddSize: size %d is not supported\n", sizeof(*(pu)))); \
+        } \
+    } while (0)
+
+
+
+/**
+ * Atomically exchanges and subtracts to an unsigned 16-bit value, ordered.
+ *
+ * @returns The old value.
+ * @param   pu16        Pointer to the value.
+ * @param   u16         Number to subtract.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(uint16_t) ASMAtomicSubU16(uint16_t volatile *pu16, uint32_t u16)
+{
+    return ASMAtomicAddU16(pu16, (uint16_t)-(int16_t)u16);
+}
+
+
+/**
+ * Atomically exchanges and subtracts to a signed 16-bit value, ordered.
+ *
+ * @returns The old value.
+ * @param   pi16        Pointer to the value.
+ * @param   i16         Number to subtract.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(int16_t) ASMAtomicSubS16(int16_t volatile *pi16, int16_t i16)
+{
+    return (int16_t)ASMAtomicAddU16((uint16_t volatile *)pi16, (uint16_t)-i16);
+}
+
+
+/**
+ * Atomically exchanges and subtracts to an unsigned 32-bit value, ordered.
+ *
+ * @returns The old value.
+ * @param   pu32        Pointer to the value.
+ * @param   u32         Number to subtract.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(uint32_t) ASMAtomicSubU32(uint32_t volatile *pu32, uint32_t u32)
+{
+    return ASMAtomicAddU32(pu32, (uint32_t)-(int32_t)u32);
+}
+
+
+/**
+ * Atomically exchanges and subtracts to a signed 32-bit value, ordered.
+ *
+ * @returns The old value.
+ * @param   pi32        Pointer to the value.
+ * @param   i32         Number to subtract.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(int32_t) ASMAtomicSubS32(int32_t volatile *pi32, int32_t i32)
+{
+    return (int32_t)ASMAtomicAddU32((uint32_t volatile *)pi32, (uint32_t)-i32);
+}
+
+
+/**
+ * Atomically exchanges and subtracts to an unsigned 64-bit value, ordered.
+ *
+ * @returns The old value.
+ * @param   pu64        Pointer to the value.
+ * @param   u64         Number to subtract.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+DECLINLINE(uint64_t) ASMAtomicSubU64(uint64_t volatile *pu64, uint64_t u64)
+{
+    return ASMAtomicAddU64(pu64, (uint64_t)-(int64_t)u64);
+}
+
+
+/**
+ * Atomically exchanges and subtracts to a signed 64-bit value, ordered.
+ *
+ * @returns The old value.
+ * @param   pi64        Pointer to the value.
+ * @param   i64         Number to subtract.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+DECLINLINE(int64_t) ASMAtomicSubS64(int64_t volatile *pi64, int64_t i64)
+{
+    return (int64_t)ASMAtomicAddU64((uint64_t volatile *)pi64, (uint64_t)-i64);
+}
+
+
+/**
+ * Atomically exchanges and subtracts to a size_t value, ordered.
+ *
+ * @returns The old value.
+ * @param   pcb         Pointer to the size_t value.
+ * @param   cb          Number to subtract.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(size_t) ASMAtomicSubZ(size_t volatile *pcb, size_t cb)
+{
+#if ARCH_BITS == 64
+    return ASMAtomicSubU64((uint64_t volatile *)pcb, cb);
+#elif ARCH_BITS == 32
+    return ASMAtomicSubU32((uint32_t volatile *)pcb, cb);
+#elif ARCH_BITS == 16
+    AssertCompileSize(size_t, 2);
+    return ASMAtomicSubU16((uint16_t volatile *)pcb, cb);
+#else
+# error "Unsupported ARCH_BITS value"
+#endif
+}
+
+
+/**
+ * Atomically exchanges and subtracts a value which size might differ between
+ * platforms or compilers, ordered.
+ *
+ * @param   pu      Pointer to the variable to update.
+ * @param   uNew    The value to subtract to *pu.
+ * @param   puOld   Where to store the old value.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+#define ASMAtomicSubSize(pu, uNew, puOld) \
+    do { \
+        switch (sizeof(*(pu))) { \
+            case 4: *(uint32_t  *)(puOld) = ASMAtomicSubU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew)); break; \
+            case 8: *(uint64_t  *)(puOld) = ASMAtomicSubU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew)); break; \
+            default: AssertMsgFailed(("ASMAtomicSubSize: size %d is not supported\n", sizeof(*(pu)))); \
+        } \
+    } while (0)
+
+
+
+/**
+ * Atomically increment a 16-bit value, ordered.
+ *
+ * @returns The new value.
+ * @param   pu16        Pointer to the value to increment.
+ * @remarks Not implemented. Just to make 16-bit code happy.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLASM(uint16_t) ASMAtomicIncU16(uint16_t volatile *pu16);
+
+
+/**
+ * Atomically increment a 32-bit value, ordered.
+ *
+ * @returns The new value.
+ * @param   pu32        Pointer to the value to increment.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint32_t) ASMAtomicIncU32(uint32_t volatile *pu32);
+#else
+DECLINLINE(uint32_t) ASMAtomicIncU32(uint32_t volatile *pu32)
+{
+    uint32_t u32;
+# if RT_INLINE_ASM_USES_INTRIN
+    u32 = _InterlockedIncrement((long *)pu32);
+    return u32;
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("lock; xaddl %0, %1\n\t"
+                         : "=r" (u32),
+                           "=m" (*pu32)
+                         : "0" (1),
+                           "m" (*pu32)
+                         : "memory");
+    return u32+1;
+# else
+    __asm
+    {
+        mov     eax, 1
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [pu32]
+        lock xadd [rdx], eax
+#  else
+        mov     edx, [pu32]
+        lock xadd [edx], eax
+#  endif
+        mov     u32, eax
+    }
+    return u32+1;
+# endif
+}
+#endif
+
+
+/**
+ * Atomically increment a signed 32-bit value, ordered.
+ *
+ * @returns The new value.
+ * @param   pi32        Pointer to the value to increment.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(int32_t) ASMAtomicIncS32(int32_t volatile *pi32)
+{
+    return (int32_t)ASMAtomicIncU32((uint32_t volatile *)pi32);
+}
+
+
+/**
+ * Atomically increment a 64-bit value, ordered.
+ *
+ * @returns The new value.
+ * @param   pu64        Pointer to the value to increment.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint64_t) ASMAtomicIncU64(uint64_t volatile *pu64);
+#else
+DECLINLINE(uint64_t) ASMAtomicIncU64(uint64_t volatile *pu64)
+{
+# if RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_AMD64)
+    uint64_t u64;
+    u64 = _InterlockedIncrement64((__int64 *)pu64);
+    return u64;
+
+# elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64)
+    uint64_t u64;
+    __asm__ __volatile__("lock; xaddq %0, %1\n\t"
+                         : "=r" (u64),
+                           "=m" (*pu64)
+                         : "0" (1),
+                           "m" (*pu64)
+                         : "memory");
+    return u64 + 1;
+# else
+    return ASMAtomicAddU64(pu64, 1) + 1;
+# endif
+}
+#endif
+
+
+/**
+ * Atomically increment a signed 64-bit value, ordered.
+ *
+ * @returns The new value.
+ * @param   pi64        Pointer to the value to increment.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+DECLINLINE(int64_t) ASMAtomicIncS64(int64_t volatile *pi64)
+{
+    return (int64_t)ASMAtomicIncU64((uint64_t volatile *)pi64);
+}
+
+
+/**
+ * Atomically increment a size_t value, ordered.
+ *
+ * @returns The new value.
+ * @param   pcb         Pointer to the value to increment.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(int64_t) ASMAtomicIncZ(size_t volatile *pcb)
+{
+#if ARCH_BITS == 64
+    return ASMAtomicIncU64((uint64_t volatile *)pcb);
+#elif ARCH_BITS == 32
+    return ASMAtomicIncU32((uint32_t volatile *)pcb);
+#elif ARCH_BITS == 16
+    return ASMAtomicIncU16((uint16_t volatile *)pcb);
+#else
+# error "Unsupported ARCH_BITS value"
+#endif
+}
+
+
+
+/**
+ * Atomically decrement an unsigned 32-bit value, ordered.
+ *
+ * @returns The new value.
+ * @param   pu16        Pointer to the value to decrement.
+ * @remarks Not implemented. Just to make 16-bit code happy.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLASM(uint32_t) ASMAtomicDecU16(uint16_t volatile *pu16);
+
+
+/**
+ * Atomically decrement an unsigned 32-bit value, ordered.
+ *
+ * @returns The new value.
+ * @param   pu32        Pointer to the value to decrement.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint32_t) ASMAtomicDecU32(uint32_t volatile *pu32);
+#else
+DECLINLINE(uint32_t) ASMAtomicDecU32(uint32_t volatile *pu32)
+{
+    uint32_t u32;
+# if RT_INLINE_ASM_USES_INTRIN
+    u32 = _InterlockedDecrement((long *)pu32);
+    return u32;
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("lock; xaddl %0, %1\n\t"
+                         : "=r" (u32),
+                           "=m" (*pu32)
+                         : "0" (-1),
+                           "m" (*pu32)
+                         : "memory");
+    return u32-1;
+# else
+    __asm
+    {
+        mov     eax, -1
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [pu32]
+        lock xadd [rdx], eax
+#  else
+        mov     edx, [pu32]
+        lock xadd [edx], eax
+#  endif
+        mov     u32, eax
+    }
+    return u32-1;
+# endif
+}
+#endif
+
+
+/**
+ * Atomically decrement a signed 32-bit value, ordered.
+ *
+ * @returns The new value.
+ * @param   pi32        Pointer to the value to decrement.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(int32_t) ASMAtomicDecS32(int32_t volatile *pi32)
+{
+    return (int32_t)ASMAtomicDecU32((uint32_t volatile *)pi32);
+}
+
+
+/**
+ * Atomically decrement an unsigned 64-bit value, ordered.
+ *
+ * @returns The new value.
+ * @param   pu64        Pointer to the value to decrement.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint64_t) ASMAtomicDecU64(uint64_t volatile *pu64);
+#else
+DECLINLINE(uint64_t) ASMAtomicDecU64(uint64_t volatile *pu64)
+{
+# if RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_AMD64)
+    uint64_t u64 = _InterlockedDecrement64((__int64 volatile *)pu64);
+    return u64;
+
+# elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64)
+    uint64_t u64;
+    __asm__ __volatile__("lock; xaddq %q0, %1\n\t"
+                         : "=r" (u64),
+                           "=m" (*pu64)
+                         : "0" (~(uint64_t)0),
+                           "m" (*pu64)
+                         : "memory");
+    return u64-1;
+# else
+    return ASMAtomicAddU64(pu64, UINT64_MAX) - 1;
+# endif
+}
+#endif
+
+
+/**
+ * Atomically decrement a signed 64-bit value, ordered.
+ *
+ * @returns The new value.
+ * @param   pi64        Pointer to the value to decrement.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+DECLINLINE(int64_t) ASMAtomicDecS64(int64_t volatile *pi64)
+{
+    return (int64_t)ASMAtomicDecU64((uint64_t volatile *)pi64);
+}
+
+
+/**
+ * Atomically decrement a size_t value, ordered.
+ *
+ * @returns The new value.
+ * @param   pcb         Pointer to the value to decrement.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(int64_t) ASMAtomicDecZ(size_t volatile *pcb)
+{
+#if ARCH_BITS == 64
+    return ASMAtomicDecU64((uint64_t volatile *)pcb);
+#elif ARCH_BITS == 32
+    return ASMAtomicDecU32((uint32_t volatile *)pcb);
+#elif ARCH_BITS == 16
+    return ASMAtomicDecU16((uint16_t volatile *)pcb);
+#else
+# error "Unsupported ARCH_BITS value"
+#endif
+}
+
+
+/**
+ * Atomically Or an unsigned 32-bit value, ordered.
+ *
+ * @param   pu32   Pointer to the pointer variable to OR u32 with.
+ * @param   u32    The value to OR *pu32 with.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMAtomicOrU32(uint32_t volatile *pu32, uint32_t u32);
+#else
+DECLINLINE(void) ASMAtomicOrU32(uint32_t volatile *pu32, uint32_t u32)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    _InterlockedOr((long volatile *)pu32, (long)u32);
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("lock; orl %1, %0\n\t"
+                         : "=m" (*pu32)
+                         : "ir" (u32),
+                           "m" (*pu32));
+# else
+    __asm
+    {
+        mov     eax, [u32]
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [pu32]
+        lock    or [rdx], eax
+#  else
+        mov     edx, [pu32]
+        lock    or [edx], eax
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Atomically Or a signed 32-bit value, ordered.
+ *
+ * @param   pi32   Pointer to the pointer variable to OR u32 with.
+ * @param   i32    The value to OR *pu32 with.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+DECLINLINE(void) ASMAtomicOrS32(int32_t volatile *pi32, int32_t i32)
+{
+    ASMAtomicOrU32((uint32_t volatile *)pi32, i32);
+}
+
+
+/**
+ * Atomically Or an unsigned 64-bit value, ordered.
+ *
+ * @param   pu64   Pointer to the pointer variable to OR u64 with.
+ * @param   u64    The value to OR *pu64 with.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMAtomicOrU64(uint64_t volatile *pu64, uint64_t u64);
+#else
+DECLINLINE(void) ASMAtomicOrU64(uint64_t volatile *pu64, uint64_t u64)
+{
+# if RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_AMD64)
+    _InterlockedOr64((__int64 volatile *)pu64, (__int64)u64);
+
+# elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64)
+    __asm__ __volatile__("lock; orq %1, %q0\n\t"
+                         : "=m" (*pu64)
+                         : "r" (u64),
+                           "m" (*pu64));
+# else
+    for (;;)
+    {
+        uint64_t u64Old = ASMAtomicUoReadU64(pu64);
+        uint64_t u64New = u64Old | u64;
+        if (ASMAtomicCmpXchgU64(pu64, u64New, u64Old))
+            break;
+        ASMNopPause();
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Atomically Or a signed 64-bit value, ordered.
+ *
+ * @param   pi64   Pointer to the pointer variable to OR u64 with.
+ * @param   i64    The value to OR *pu64 with.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+DECLINLINE(void) ASMAtomicOrS64(int64_t volatile *pi64, int64_t i64)
+{
+    ASMAtomicOrU64((uint64_t volatile *)pi64, i64);
+}
+
+
+/**
+ * Atomically And an unsigned 32-bit value, ordered.
+ *
+ * @param   pu32   Pointer to the pointer variable to AND u32 with.
+ * @param   u32    The value to AND *pu32 with.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMAtomicAndU32(uint32_t volatile *pu32, uint32_t u32);
+#else
+DECLINLINE(void) ASMAtomicAndU32(uint32_t volatile *pu32, uint32_t u32)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    _InterlockedAnd((long volatile *)pu32, u32);
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("lock; andl %1, %0\n\t"
+                         : "=m" (*pu32)
+                         : "ir" (u32),
+                           "m" (*pu32));
+# else
+    __asm
+    {
+        mov     eax, [u32]
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [pu32]
+        lock and [rdx], eax
+#  else
+        mov     edx, [pu32]
+        lock and [edx], eax
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Atomically And a signed 32-bit value, ordered.
+ *
+ * @param   pi32   Pointer to the pointer variable to AND i32 with.
+ * @param   i32    The value to AND *pi32 with.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+DECLINLINE(void) ASMAtomicAndS32(int32_t volatile *pi32, int32_t i32)
+{
+    ASMAtomicAndU32((uint32_t volatile *)pi32, (uint32_t)i32);
+}
+
+
+/**
+ * Atomically And an unsigned 64-bit value, ordered.
+ *
+ * @param   pu64   Pointer to the pointer variable to AND u64 with.
+ * @param   u64    The value to AND *pu64 with.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMAtomicAndU64(uint64_t volatile *pu64, uint64_t u64);
+#else
+DECLINLINE(void) ASMAtomicAndU64(uint64_t volatile *pu64, uint64_t u64)
+{
+# if RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_AMD64)
+    _InterlockedAnd64((__int64 volatile *)pu64, u64);
+
+# elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64)
+    __asm__ __volatile__("lock; andq %1, %0\n\t"
+                         : "=m" (*pu64)
+                         : "r" (u64),
+                           "m" (*pu64));
+# else
+    for (;;)
+    {
+        uint64_t u64Old = ASMAtomicUoReadU64(pu64);
+        uint64_t u64New = u64Old & u64;
+        if (ASMAtomicCmpXchgU64(pu64, u64New, u64Old))
+            break;
+        ASMNopPause();
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Atomically And a signed 64-bit value, ordered.
+ *
+ * @param   pi64   Pointer to the pointer variable to AND i64 with.
+ * @param   i64    The value to AND *pi64 with.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+DECLINLINE(void) ASMAtomicAndS64(int64_t volatile *pi64, int64_t i64)
+{
+    ASMAtomicAndU64((uint64_t volatile *)pi64, (uint64_t)i64);
+}
+
+
+/**
+ * Atomically OR an unsigned 32-bit value, unordered but interrupt safe.
+ *
+ * @param   pu32   Pointer to the pointer variable to OR u32 with.
+ * @param   u32    The value to OR *pu32 with.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMAtomicUoOrU32(uint32_t volatile *pu32, uint32_t u32);
+#else
+DECLINLINE(void) ASMAtomicUoOrU32(uint32_t volatile *pu32, uint32_t u32)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("orl %1, %0\n\t"
+                         : "=m" (*pu32)
+                         : "ir" (u32),
+                           "m" (*pu32));
+# else
+    __asm
+    {
+        mov     eax, [u32]
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [pu32]
+        or      [rdx], eax
+#  else
+        mov     edx, [pu32]
+        or      [edx], eax
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Atomically OR a signed 32-bit value, unordered.
+ *
+ * @param   pi32   Pointer to the pointer variable to OR u32 with.
+ * @param   i32    The value to OR *pu32 with.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+DECLINLINE(void) ASMAtomicUoOrS32(int32_t volatile *pi32, int32_t i32)
+{
+    ASMAtomicUoOrU32((uint32_t volatile *)pi32, i32);
+}
+
+
+/**
+ * Atomically OR an unsigned 64-bit value, unordered.
+ *
+ * @param   pu64   Pointer to the pointer variable to OR u64 with.
+ * @param   u64    The value to OR *pu64 with.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMAtomicUoOrU64(uint64_t volatile *pu64, uint64_t u64);
+#else
+DECLINLINE(void) ASMAtomicUoOrU64(uint64_t volatile *pu64, uint64_t u64)
+{
+# if RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64)
+    __asm__ __volatile__("orq %1, %q0\n\t"
+                         : "=m" (*pu64)
+                         : "r" (u64),
+                           "m" (*pu64));
+# else
+    for (;;)
+    {
+        uint64_t u64Old = ASMAtomicUoReadU64(pu64);
+        uint64_t u64New = u64Old | u64;
+        if (ASMAtomicCmpXchgU64(pu64, u64New, u64Old))
+            break;
+        ASMNopPause();
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Atomically Or a signed 64-bit value, unordered.
+ *
+ * @param   pi64   Pointer to the pointer variable to OR u64 with.
+ * @param   i64    The value to OR *pu64 with.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+DECLINLINE(void) ASMAtomicUoOrS64(int64_t volatile *pi64, int64_t i64)
+{
+    ASMAtomicUoOrU64((uint64_t volatile *)pi64, i64);
+}
+
+
+/**
+ * Atomically And an unsigned 32-bit value, unordered.
+ *
+ * @param   pu32   Pointer to the pointer variable to AND u32 with.
+ * @param   u32    The value to AND *pu32 with.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMAtomicUoAndU32(uint32_t volatile *pu32, uint32_t u32);
+#else
+DECLINLINE(void) ASMAtomicUoAndU32(uint32_t volatile *pu32, uint32_t u32)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("andl %1, %0\n\t"
+                         : "=m" (*pu32)
+                         : "ir" (u32),
+                           "m" (*pu32));
+# else
+    __asm
+    {
+        mov     eax, [u32]
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [pu32]
+        and     [rdx], eax
+#  else
+        mov     edx, [pu32]
+        and     [edx], eax
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Atomically And a signed 32-bit value, unordered.
+ *
+ * @param   pi32   Pointer to the pointer variable to AND i32 with.
+ * @param   i32    The value to AND *pi32 with.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+DECLINLINE(void) ASMAtomicUoAndS32(int32_t volatile *pi32, int32_t i32)
+{
+    ASMAtomicUoAndU32((uint32_t volatile *)pi32, (uint32_t)i32);
+}
+
+
+/**
+ * Atomically And an unsigned 64-bit value, unordered.
+ *
+ * @param   pu64   Pointer to the pointer variable to AND u64 with.
+ * @param   u64    The value to AND *pu64 with.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMAtomicUoAndU64(uint64_t volatile *pu64, uint64_t u64);
+#else
+DECLINLINE(void) ASMAtomicUoAndU64(uint64_t volatile *pu64, uint64_t u64)
+{
+# if RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64)
+    __asm__ __volatile__("andq %1, %0\n\t"
+                         : "=m" (*pu64)
+                         : "r" (u64),
+                           "m" (*pu64));
+# else
+    for (;;)
+    {
+        uint64_t u64Old = ASMAtomicUoReadU64(pu64);
+        uint64_t u64New = u64Old & u64;
+        if (ASMAtomicCmpXchgU64(pu64, u64New, u64Old))
+            break;
+        ASMNopPause();
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Atomically And a signed 64-bit value, unordered.
+ *
+ * @param   pi64   Pointer to the pointer variable to AND i64 with.
+ * @param   i64    The value to AND *pi64 with.
+ *
+ * @remarks x86: Requires a Pentium or later.
+ */
+DECLINLINE(void) ASMAtomicUoAndS64(int64_t volatile *pi64, int64_t i64)
+{
+    ASMAtomicUoAndU64((uint64_t volatile *)pi64, (uint64_t)i64);
+}
+
+
+/**
+ * Atomically increment an unsigned 32-bit value, unordered.
+ *
+ * @returns the new value.
+ * @param   pu32   Pointer to the variable to increment.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(uint32_t) ASMAtomicUoIncU32(uint32_t volatile *pu32);
+#else
+DECLINLINE(uint32_t) ASMAtomicUoIncU32(uint32_t volatile *pu32)
+{
+    uint32_t u32;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("xaddl %0, %1\n\t"
+                         : "=r" (u32),
+                           "=m" (*pu32)
+                         : "0" (1),
+                           "m" (*pu32)
+                         : "memory");
+    return u32 + 1;
+# else
+    __asm
+    {
+        mov     eax, 1
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [pu32]
+        xadd    [rdx], eax
+#  else
+        mov     edx, [pu32]
+        xadd    [edx], eax
+#  endif
+        mov     u32, eax
+    }
+    return u32 + 1;
+# endif
+}
+#endif
+
+
+/**
+ * Atomically decrement an unsigned 32-bit value, unordered.
+ *
+ * @returns the new value.
+ * @param   pu32   Pointer to the variable to decrement.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(uint32_t) ASMAtomicUoDecU32(uint32_t volatile *pu32);
+#else
+DECLINLINE(uint32_t) ASMAtomicUoDecU32(uint32_t volatile *pu32)
+{
+    uint32_t u32;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("lock; xaddl %0, %1\n\t"
+                         : "=r" (u32),
+                           "=m" (*pu32)
+                         : "0" (-1),
+                           "m" (*pu32)
+                         : "memory");
+    return u32 - 1;
+# else
+    __asm
+    {
+        mov     eax, -1
+#  ifdef RT_ARCH_AMD64
+        mov     rdx, [pu32]
+        xadd    [rdx], eax
+#  else
+        mov     edx, [pu32]
+        xadd    [edx], eax
+#  endif
+        mov     u32, eax
+    }
+    return u32 - 1;
+# endif
+}
+#endif
+
+
+/** @def RT_ASM_PAGE_SIZE
+ * We try avoid dragging in iprt/param.h here.
+ * @internal
+ */
+#if defined(RT_ARCH_SPARC64)
+# define RT_ASM_PAGE_SIZE   0x2000
+# if defined(PAGE_SIZE) && !defined(NT_INCLUDED)
+#  if PAGE_SIZE != 0x2000
+#   error "PAGE_SIZE is not 0x2000!"
+#  endif
+# endif
+#else
+# define RT_ASM_PAGE_SIZE   0x1000
+# if defined(PAGE_SIZE) && !defined(NT_INCLUDED)
+#  if PAGE_SIZE != 0x1000
+#   error "PAGE_SIZE is not 0x1000!"
+#  endif
+# endif
+#endif
+
+/**
+ * Zeros a 4K memory page.
+ *
+ * @param   pv  Pointer to the memory block. This must be page aligned.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMMemZeroPage(volatile void *pv);
+# else
+DECLINLINE(void) ASMMemZeroPage(volatile void *pv)
+{
+#  if RT_INLINE_ASM_USES_INTRIN
+#   ifdef RT_ARCH_AMD64
+    __stosq((unsigned __int64 *)pv, 0, RT_ASM_PAGE_SIZE / 8);
+#   else
+    __stosd((unsigned long *)pv, 0, RT_ASM_PAGE_SIZE / 4);
+#   endif
+
+#  elif RT_INLINE_ASM_GNU_STYLE
+    RTCCUINTREG uDummy;
+#   ifdef RT_ARCH_AMD64
+    __asm__ __volatile__("rep stosq"
+                         : "=D" (pv),
+                           "=c" (uDummy)
+                         : "0" (pv),
+                           "c" (RT_ASM_PAGE_SIZE >> 3),
+                           "a" (0)
+                         : "memory");
+#   else
+    __asm__ __volatile__("rep stosl"
+                         : "=D" (pv),
+                           "=c" (uDummy)
+                         : "0" (pv),
+                           "c" (RT_ASM_PAGE_SIZE >> 2),
+                           "a" (0)
+                         : "memory");
+#   endif
+#  else
+    __asm
+    {
+#   ifdef RT_ARCH_AMD64
+        xor     rax, rax
+        mov     ecx, 0200h
+        mov     rdi, [pv]
+        rep     stosq
+#   else
+        xor     eax, eax
+        mov     ecx, 0400h
+        mov     edi, [pv]
+        rep     stosd
+#   endif
+    }
+#  endif
+}
+# endif
+
+
+/**
+ * Zeros a memory block with a 32-bit aligned size.
+ *
+ * @param   pv  Pointer to the memory block.
+ * @param   cb  Number of bytes in the block. This MUST be aligned on 32-bit!
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMMemZero32(volatile void *pv, size_t cb);
+#else
+DECLINLINE(void) ASMMemZero32(volatile void *pv, size_t cb)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+#  ifdef RT_ARCH_AMD64
+    if (!(cb & 7))
+        __stosq((unsigned __int64 *)pv, 0, cb / 8);
+    else
+#  endif
+        __stosd((unsigned long *)pv, 0, cb / 4);
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("rep stosl"
+                         : "=D" (pv),
+                           "=c" (cb)
+                         : "0" (pv),
+                           "1" (cb >> 2),
+                           "a" (0)
+                         : "memory");
+# else
+    __asm
+    {
+        xor     eax, eax
+#  ifdef RT_ARCH_AMD64
+        mov     rcx, [cb]
+        shr     rcx, 2
+        mov     rdi, [pv]
+#  else
+        mov     ecx, [cb]
+        shr     ecx, 2
+        mov     edi, [pv]
+#  endif
+        rep stosd
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Fills a memory block with a 32-bit aligned size.
+ *
+ * @param   pv  Pointer to the memory block.
+ * @param   cb  Number of bytes in the block. This MUST be aligned on 32-bit!
+ * @param   u32 The value to fill with.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMMemFill32(volatile void *pv, size_t cb, uint32_t u32);
+#else
+DECLINLINE(void) ASMMemFill32(volatile void *pv, size_t cb, uint32_t u32)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+#  ifdef RT_ARCH_AMD64
+    if (!(cb & 7))
+        __stosq((unsigned __int64 *)pv, RT_MAKE_U64(u32, u32), cb / 8);
+    else
+#  endif
+        __stosd((unsigned long *)pv, u32, cb / 4);
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("rep stosl"
+                         : "=D" (pv),
+                           "=c" (cb)
+                         : "0" (pv),
+                           "1" (cb >> 2),
+                           "a" (u32)
+                         : "memory");
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rcx, [cb]
+        shr     rcx, 2
+        mov     rdi, [pv]
+#  else
+        mov     ecx, [cb]
+        shr     ecx, 2
+        mov     edi, [pv]
+#  endif
+        mov     eax, [u32]
+        rep stosd
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Checks if a memory block is all zeros.
+ *
+ * @returns Pointer to the first non-zero byte.
+ * @returns NULL if all zero.
+ *
+ * @param   pv      Pointer to the memory block.
+ * @param   cb      Number of bytes in the block.
+ *
+ * @todo Fix name, it is a predicate function but it's not returning boolean!
+ */
+#if !defined(RDESKTOP) && (!defined(RT_OS_LINUX) || !defined(__KERNEL__))
+DECLASM(void *) ASMMemFirstNonZero(void const *pv, size_t cb);
+#else
+DECLINLINE(void *) ASMMemFirstNonZero(void const *pv, size_t cb)
+{
+    uint8_t const *pb = (uint8_t const *)pv;
+    for (; cb; cb--, pb++)
+        if (RT_LIKELY(*pb == 0))
+        { /* likely */ }
+        else
+            return (void *)pb;
+    return NULL;
+}
+#endif
+
+
+/**
+ * Checks if a memory block is all zeros.
+ *
+ * @returns true if zero, false if not.
+ *
+ * @param   pv      Pointer to the memory block.
+ * @param   cb      Number of bytes in the block.
+ *
+ * @sa      ASMMemFirstNonZero
+ */
+DECLINLINE(bool) ASMMemIsZero(void const *pv, size_t cb)
+{
+    return ASMMemFirstNonZero(pv, cb) == NULL;
+}
+
+
+/**
+ * Checks if a memory page is all zeros.
+ *
+ * @returns true / false.
+ *
+ * @param   pvPage      Pointer to the page.  Must be aligned on 16 byte
+ *                      boundary
+ */
+DECLINLINE(bool) ASMMemIsZeroPage(void const *pvPage)
+{
+# if 0 /*RT_INLINE_ASM_GNU_STYLE - this is actually slower... */
+    union { RTCCUINTREG r; bool f; } uAX;
+    RTCCUINTREG xCX, xDI;
+   Assert(!((uintptr_t)pvPage & 15));
+    __asm__ __volatile__("repe; "
+#  ifdef RT_ARCH_AMD64
+                         "scasq\n\t"
+#  else
+                         "scasl\n\t"
+#  endif
+                         "setnc %%al\n\t"
+                         : "=&c" (xCX),
+                           "=&D" (xDI),
+                           "=&a" (uAX.r)
+                         : "mr" (pvPage),
+#  ifdef RT_ARCH_AMD64
+                         "0" (RT_ASM_PAGE_SIZE/8),
+#  else
+                         "0" (RT_ASM_PAGE_SIZE/4),
+#  endif
+                         "1" (pvPage),
+                         "2" (0));
+    return uAX.f;
+# else
+   uintptr_t const *puPtr = (uintptr_t const *)pvPage;
+   size_t           cLeft = RT_ASM_PAGE_SIZE / sizeof(uintptr_t) / 8;
+   Assert(!((uintptr_t)pvPage & 15));
+   for (;;)
+   {
+       if (puPtr[0])        return false;
+       if (puPtr[4])        return false;
+
+       if (puPtr[2])        return false;
+       if (puPtr[6])        return false;
+
+       if (puPtr[1])        return false;
+       if (puPtr[5])        return false;
+
+       if (puPtr[3])        return false;
+       if (puPtr[7])        return false;
+
+       if (!--cLeft)
+           return true;
+       puPtr += 8;
+   }
+# endif
+}
+
+
+/**
+ * Checks if a memory block is filled with the specified byte, returning the
+ * first mismatch.
+ *
+ * This is sort of an inverted memchr.
+ *
+ * @returns Pointer to the byte which doesn't equal u8.
+ * @returns NULL if all equal to u8.
+ *
+ * @param   pv      Pointer to the memory block.
+ * @param   cb      Number of bytes in the block.
+ * @param   u8      The value it's supposed to be filled with.
+ *
+ * @remarks No alignment requirements.
+ */
+#if    (!defined(RT_OS_LINUX) || !defined(__KERNEL__)) \
+    && (!defined(RT_OS_FREEBSD) || !defined(_KERNEL))
+DECLASM(void *) ASMMemFirstMismatchingU8(void const *pv, size_t cb, uint8_t u8);
+#else
+DECLINLINE(void *) ASMMemFirstMismatchingU8(void const *pv, size_t cb, uint8_t u8)
+{
+    uint8_t const *pb = (uint8_t const *)pv;
+    for (; cb; cb--, pb++)
+        if (RT_LIKELY(*pb == u8))
+        { /* likely */ }
+        else
+            return (void *)pb;
+    return NULL;
+}
+#endif
+
+
+/**
+ * Checks if a memory block is filled with the specified byte.
+ *
+ * @returns true if all matching, false if not.
+ *
+ * @param   pv      Pointer to the memory block.
+ * @param   cb      Number of bytes in the block.
+ * @param   u8      The value it's supposed to be filled with.
+ *
+ * @remarks No alignment requirements.
+ */
+DECLINLINE(bool) ASMMemIsAllU8(void const *pv, size_t cb, uint8_t u8)
+{
+    return ASMMemFirstMismatchingU8(pv, cb, u8) == NULL;
+}
+
+
+/**
+ * Checks if a memory block is filled with the specified 32-bit value.
+ *
+ * This is a sort of inverted memchr.
+ *
+ * @returns Pointer to the first value which doesn't equal u32.
+ * @returns NULL if all equal to u32.
+ *
+ * @param   pv      Pointer to the memory block.
+ * @param   cb      Number of bytes in the block. This MUST be aligned on 32-bit!
+ * @param   u32     The value it's supposed to be filled with.
+ */
+DECLINLINE(uint32_t *) ASMMemFirstMismatchingU32(void const *pv, size_t cb, uint32_t u32)
+{
+/** @todo rewrite this in inline assembly? */
+    uint32_t const *pu32 = (uint32_t const *)pv;
+    for (; cb; cb -= 4, pu32++)
+        if (RT_LIKELY(*pu32 == u32))
+        { /* likely */ }
+        else
+            return (uint32_t *)pu32;
+    return NULL;
+}
+
+
+/**
+ * Probes a byte pointer for read access.
+ *
+ * While the function will not fault if the byte is not read accessible,
+ * the idea is to do this in a safe place like before acquiring locks
+ * and such like.
+ *
+ * Also, this functions guarantees that an eager compiler is not going
+ * to optimize the probing away.
+ *
+ * @param   pvByte      Pointer to the byte.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(uint8_t) ASMProbeReadByte(const void *pvByte);
+#else
+DECLINLINE(uint8_t) ASMProbeReadByte(const void *pvByte)
+{
+    /** @todo verify that the compiler actually doesn't optimize this away. (intel & gcc) */
+    uint8_t u8;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("movb (%1), %0\n\t"
+                         : "=r" (u8)
+                         : "r" (pvByte));
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pvByte]
+        mov     al, [rax]
+#  else
+        mov     eax, [pvByte]
+        mov     al, [eax]
+#  endif
+        mov     [u8], al
+    }
+# endif
+    return u8;
+}
+#endif
+
+/**
+ * Probes a buffer for read access page by page.
+ *
+ * While the function will fault if the buffer is not fully read
+ * accessible, the idea is to do this in a safe place like before
+ * acquiring locks and such like.
+ *
+ * Also, this functions guarantees that an eager compiler is not going
+ * to optimize the probing away.
+ *
+ * @param   pvBuf       Pointer to the buffer.
+ * @param   cbBuf       The size of the buffer in bytes. Must be >= 1.
+ */
+DECLINLINE(void) ASMProbeReadBuffer(const void *pvBuf, size_t cbBuf)
+{
+    /** @todo verify that the compiler actually doesn't optimize this away. (intel & gcc) */
+    /* the first byte */
+    const uint8_t *pu8 = (const uint8_t *)pvBuf;
+    ASMProbeReadByte(pu8);
+
+    /* the pages in between pages. */
+    while (cbBuf > RT_ASM_PAGE_SIZE)
+    {
+        ASMProbeReadByte(pu8);
+        cbBuf -= RT_ASM_PAGE_SIZE;
+        pu8   += RT_ASM_PAGE_SIZE;
+    }
+
+    /* the last byte */
+    ASMProbeReadByte(pu8 + cbBuf - 1);
+}
+
+
+
+/** @defgroup grp_inline_bits   Bit Operations
+ * @{
+ */
+
+
+/**
+ * Sets a bit in a bitmap.
+ *
+ * @param   pvBitmap    Pointer to the bitmap. This should be 32-bit aligned.
+ * @param   iBit        The bit to set.
+ *
+ * @remarks The 32-bit aligning of pvBitmap is not a strict requirement.
+ *          However, doing so will yield better performance as well as avoiding
+ *          traps accessing the last bits in the bitmap.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMBitSet(volatile void *pvBitmap, int32_t iBit);
+#else
+DECLINLINE(void) ASMBitSet(volatile void *pvBitmap, int32_t iBit)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    _bittestandset((long *)pvBitmap, iBit);
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("btsl %1, %0"
+                         : "=m" (*(volatile long *)pvBitmap)
+                         : "Ir" (iBit),
+                           "m" (*(volatile long *)pvBitmap)
+                         : "memory");
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pvBitmap]
+        mov     edx, [iBit]
+        bts     [rax], edx
+#  else
+        mov     eax, [pvBitmap]
+        mov     edx, [iBit]
+        bts     [eax], edx
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Atomically sets a bit in a bitmap, ordered.
+ *
+ * @param   pvBitmap    Pointer to the bitmap. Must be 32-bit aligned, otherwise
+ *                      the memory access isn't atomic!
+ * @param   iBit        The bit to set.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMAtomicBitSet(volatile void *pvBitmap, int32_t iBit);
+#else
+DECLINLINE(void) ASMAtomicBitSet(volatile void *pvBitmap, int32_t iBit)
+{
+    AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap));
+# if RT_INLINE_ASM_USES_INTRIN
+    _interlockedbittestandset((long *)pvBitmap, iBit);
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("lock; btsl %1, %0"
+                         : "=m" (*(volatile long *)pvBitmap)
+                         : "Ir" (iBit),
+                           "m" (*(volatile long *)pvBitmap)
+                         : "memory");
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pvBitmap]
+        mov     edx, [iBit]
+        lock bts [rax], edx
+#  else
+        mov     eax, [pvBitmap]
+        mov     edx, [iBit]
+        lock bts [eax], edx
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Clears a bit in a bitmap.
+ *
+ * @param   pvBitmap    Pointer to the bitmap.
+ * @param   iBit        The bit to clear.
+ *
+ * @remarks The 32-bit aligning of pvBitmap is not a strict requirement.
+ *          However, doing so will yield better performance as well as avoiding
+ *          traps accessing the last bits in the bitmap.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMBitClear(volatile void *pvBitmap, int32_t iBit);
+#else
+DECLINLINE(void) ASMBitClear(volatile void *pvBitmap, int32_t iBit)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    _bittestandreset((long *)pvBitmap, iBit);
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("btrl %1, %0"
+                         : "=m" (*(volatile long *)pvBitmap)
+                         : "Ir" (iBit),
+                           "m" (*(volatile long *)pvBitmap)
+                         : "memory");
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pvBitmap]
+        mov     edx, [iBit]
+        btr     [rax], edx
+#  else
+        mov     eax, [pvBitmap]
+        mov     edx, [iBit]
+        btr     [eax], edx
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Atomically clears a bit in a bitmap, ordered.
+ *
+ * @param   pvBitmap    Pointer to the bitmap. Must be 32-bit aligned, otherwise
+ *                      the memory access isn't atomic!
+ * @param   iBit        The bit to toggle set.
+ *
+ * @remarks No memory barrier, take care on smp.
+ * @remarks x86: Requires a 386 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMAtomicBitClear(volatile void *pvBitmap, int32_t iBit);
+#else
+DECLINLINE(void) ASMAtomicBitClear(volatile void *pvBitmap, int32_t iBit)
+{
+    AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap));
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("lock; btrl %1, %0"
+                         : "=m" (*(volatile long *)pvBitmap)
+                         : "Ir" (iBit),
+                           "m" (*(volatile long *)pvBitmap)
+                         : "memory");
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pvBitmap]
+        mov     edx, [iBit]
+        lock btr [rax], edx
+#  else
+        mov     eax, [pvBitmap]
+        mov     edx, [iBit]
+        lock btr [eax], edx
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Toggles a bit in a bitmap.
+ *
+ * @param   pvBitmap    Pointer to the bitmap.
+ * @param   iBit        The bit to toggle.
+ *
+ * @remarks The 32-bit aligning of pvBitmap is not a strict requirement.
+ *          However, doing so will yield better performance as well as avoiding
+ *          traps accessing the last bits in the bitmap.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMBitToggle(volatile void *pvBitmap, int32_t iBit);
+#else
+DECLINLINE(void) ASMBitToggle(volatile void *pvBitmap, int32_t iBit)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    _bittestandcomplement((long *)pvBitmap, iBit);
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("btcl %1, %0"
+                         : "=m" (*(volatile long *)pvBitmap)
+                         : "Ir" (iBit),
+                           "m" (*(volatile long *)pvBitmap)
+                         : "memory");
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pvBitmap]
+        mov     edx, [iBit]
+        btc     [rax], edx
+#  else
+        mov     eax, [pvBitmap]
+        mov     edx, [iBit]
+        btc     [eax], edx
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Atomically toggles a bit in a bitmap, ordered.
+ *
+ * @param   pvBitmap    Pointer to the bitmap. Must be 32-bit aligned, otherwise
+ *                      the memory access isn't atomic!
+ * @param   iBit        The bit to test and set.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMAtomicBitToggle(volatile void *pvBitmap, int32_t iBit);
+#else
+DECLINLINE(void) ASMAtomicBitToggle(volatile void *pvBitmap, int32_t iBit)
+{
+    AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap));
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("lock; btcl %1, %0"
+                         : "=m" (*(volatile long *)pvBitmap)
+                         : "Ir" (iBit),
+                           "m" (*(volatile long *)pvBitmap)
+                         : "memory");
+# else
+    __asm
+    {
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pvBitmap]
+        mov     edx, [iBit]
+        lock btc [rax], edx
+#  else
+        mov     eax, [pvBitmap]
+        mov     edx, [iBit]
+        lock btc [eax], edx
+#  endif
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Tests and sets a bit in a bitmap.
+ *
+ * @returns true if the bit was set.
+ * @returns false if the bit was clear.
+ *
+ * @param   pvBitmap    Pointer to the bitmap.
+ * @param   iBit        The bit to test and set.
+ *
+ * @remarks The 32-bit aligning of pvBitmap is not a strict requirement.
+ *          However, doing so will yield better performance as well as avoiding
+ *          traps accessing the last bits in the bitmap.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(bool) ASMBitTestAndSet(volatile void *pvBitmap, int32_t iBit);
+#else
+DECLINLINE(bool) ASMBitTestAndSet(volatile void *pvBitmap, int32_t iBit)
+{
+    union { bool f; uint32_t u32; uint8_t u8; } rc;
+# if RT_INLINE_ASM_USES_INTRIN
+    rc.u8 = _bittestandset((long *)pvBitmap, iBit);
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("btsl %2, %1\n\t"
+                         "setc %b0\n\t"
+                         "andl $1, %0\n\t"
+                         : "=q" (rc.u32),
+                           "=m" (*(volatile long *)pvBitmap)
+                         : "Ir" (iBit),
+                           "m" (*(volatile long *)pvBitmap)
+                         : "memory");
+# else
+    __asm
+    {
+        mov     edx, [iBit]
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pvBitmap]
+        bts     [rax], edx
+#  else
+        mov     eax, [pvBitmap]
+        bts     [eax], edx
+#  endif
+        setc    al
+        and     eax, 1
+        mov     [rc.u32], eax
+    }
+# endif
+    return rc.f;
+}
+#endif
+
+
+/**
+ * Atomically tests and sets a bit in a bitmap, ordered.
+ *
+ * @returns true if the bit was set.
+ * @returns false if the bit was clear.
+ *
+ * @param   pvBitmap    Pointer to the bitmap. Must be 32-bit aligned, otherwise
+ *                      the memory access isn't atomic!
+ * @param   iBit        The bit to set.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(bool) ASMAtomicBitTestAndSet(volatile void *pvBitmap, int32_t iBit);
+#else
+DECLINLINE(bool) ASMAtomicBitTestAndSet(volatile void *pvBitmap, int32_t iBit)
+{
+    union { bool f; uint32_t u32; uint8_t u8; } rc;
+    AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap));
+# if RT_INLINE_ASM_USES_INTRIN
+    rc.u8 = _interlockedbittestandset((long *)pvBitmap, iBit);
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("lock; btsl %2, %1\n\t"
+                         "setc %b0\n\t"
+                         "andl $1, %0\n\t"
+                         : "=q" (rc.u32),
+                           "=m" (*(volatile long *)pvBitmap)
+                         : "Ir" (iBit),
+                           "m" (*(volatile long *)pvBitmap)
+                         : "memory");
+# else
+    __asm
+    {
+        mov     edx, [iBit]
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pvBitmap]
+        lock bts [rax], edx
+#  else
+        mov     eax, [pvBitmap]
+        lock bts [eax], edx
+#  endif
+        setc    al
+        and     eax, 1
+        mov     [rc.u32], eax
+    }
+# endif
+    return rc.f;
+}
+#endif
+
+
+/**
+ * Tests and clears a bit in a bitmap.
+ *
+ * @returns true if the bit was set.
+ * @returns false if the bit was clear.
+ *
+ * @param   pvBitmap    Pointer to the bitmap.
+ * @param   iBit        The bit to test and clear.
+ *
+ * @remarks The 32-bit aligning of pvBitmap is not a strict requirement.
+ *          However, doing so will yield better performance as well as avoiding
+ *          traps accessing the last bits in the bitmap.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(bool) ASMBitTestAndClear(volatile void *pvBitmap, int32_t iBit);
+#else
+DECLINLINE(bool) ASMBitTestAndClear(volatile void *pvBitmap, int32_t iBit)
+{
+    union { bool f; uint32_t u32; uint8_t u8; } rc;
+# if RT_INLINE_ASM_USES_INTRIN
+    rc.u8 = _bittestandreset((long *)pvBitmap, iBit);
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("btrl %2, %1\n\t"
+                         "setc %b0\n\t"
+                         "andl $1, %0\n\t"
+                         : "=q" (rc.u32),
+                           "=m" (*(volatile long *)pvBitmap)
+                         : "Ir" (iBit),
+                           "m" (*(volatile long *)pvBitmap)
+                         : "memory");
+# else
+    __asm
+    {
+        mov     edx, [iBit]
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pvBitmap]
+        btr     [rax], edx
+#  else
+        mov     eax, [pvBitmap]
+        btr     [eax], edx
+#  endif
+        setc    al
+        and     eax, 1
+        mov     [rc.u32], eax
+    }
+# endif
+    return rc.f;
+}
+#endif
+
+
+/**
+ * Atomically tests and clears a bit in a bitmap, ordered.
+ *
+ * @returns true if the bit was set.
+ * @returns false if the bit was clear.
+ *
+ * @param   pvBitmap    Pointer to the bitmap. Must be 32-bit aligned, otherwise
+ *                      the memory access isn't atomic!
+ * @param   iBit        The bit to test and clear.
+ *
+ * @remarks No memory barrier, take care on smp.
+ * @remarks x86: Requires a 386 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(bool) ASMAtomicBitTestAndClear(volatile void *pvBitmap, int32_t iBit);
+#else
+DECLINLINE(bool) ASMAtomicBitTestAndClear(volatile void *pvBitmap, int32_t iBit)
+{
+    union { bool f; uint32_t u32; uint8_t u8; } rc;
+    AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap));
+# if RT_INLINE_ASM_USES_INTRIN
+    rc.u8 = _interlockedbittestandreset((long *)pvBitmap, iBit);
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("lock; btrl %2, %1\n\t"
+                         "setc %b0\n\t"
+                         "andl $1, %0\n\t"
+                         : "=q" (rc.u32),
+                           "=m" (*(volatile long *)pvBitmap)
+                         : "Ir" (iBit),
+                           "m" (*(volatile long *)pvBitmap)
+                         : "memory");
+# else
+    __asm
+    {
+        mov     edx, [iBit]
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pvBitmap]
+        lock btr [rax], edx
+#  else
+        mov     eax, [pvBitmap]
+        lock btr [eax], edx
+#  endif
+        setc    al
+        and     eax, 1
+        mov     [rc.u32], eax
+    }
+# endif
+    return rc.f;
+}
+#endif
+
+
+/**
+ * Tests and toggles a bit in a bitmap.
+ *
+ * @returns true if the bit was set.
+ * @returns false if the bit was clear.
+ *
+ * @param   pvBitmap    Pointer to the bitmap.
+ * @param   iBit        The bit to test and toggle.
+ *
+ * @remarks The 32-bit aligning of pvBitmap is not a strict requirement.
+ *          However, doing so will yield better performance as well as avoiding
+ *          traps accessing the last bits in the bitmap.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(bool) ASMBitTestAndToggle(volatile void *pvBitmap, int32_t iBit);
+#else
+DECLINLINE(bool) ASMBitTestAndToggle(volatile void *pvBitmap, int32_t iBit)
+{
+    union { bool f; uint32_t u32; uint8_t u8; } rc;
+# if RT_INLINE_ASM_USES_INTRIN
+    rc.u8 = _bittestandcomplement((long *)pvBitmap, iBit);
+
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("btcl %2, %1\n\t"
+                         "setc %b0\n\t"
+                         "andl $1, %0\n\t"
+                         : "=q" (rc.u32),
+                           "=m" (*(volatile long *)pvBitmap)
+                         : "Ir" (iBit),
+                           "m" (*(volatile long *)pvBitmap)
+                         : "memory");
+# else
+    __asm
+    {
+        mov   edx, [iBit]
+#  ifdef RT_ARCH_AMD64
+        mov   rax, [pvBitmap]
+        btc   [rax], edx
+#  else
+        mov   eax, [pvBitmap]
+        btc   [eax], edx
+#  endif
+        setc  al
+        and   eax, 1
+        mov   [rc.u32], eax
+    }
+# endif
+    return rc.f;
+}
+#endif
+
+
+/**
+ * Atomically tests and toggles a bit in a bitmap, ordered.
+ *
+ * @returns true if the bit was set.
+ * @returns false if the bit was clear.
+ *
+ * @param   pvBitmap    Pointer to the bitmap. Must be 32-bit aligned, otherwise
+ *                      the memory access isn't atomic!
+ * @param   iBit        The bit to test and toggle.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(bool) ASMAtomicBitTestAndToggle(volatile void *pvBitmap, int32_t iBit);
+#else
+DECLINLINE(bool) ASMAtomicBitTestAndToggle(volatile void *pvBitmap, int32_t iBit)
+{
+    union { bool f; uint32_t u32; uint8_t u8; } rc;
+    AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap));
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("lock; btcl %2, %1\n\t"
+                         "setc %b0\n\t"
+                         "andl $1, %0\n\t"
+                         : "=q" (rc.u32),
+                           "=m" (*(volatile long *)pvBitmap)
+                         : "Ir" (iBit),
+                           "m" (*(volatile long *)pvBitmap)
+                         : "memory");
+# else
+    __asm
+    {
+        mov     edx, [iBit]
+#  ifdef RT_ARCH_AMD64
+        mov     rax, [pvBitmap]
+        lock btc [rax], edx
+#  else
+        mov     eax, [pvBitmap]
+        lock btc [eax], edx
+#  endif
+        setc    al
+        and     eax, 1
+        mov     [rc.u32], eax
+    }
+# endif
+    return rc.f;
+}
+#endif
+
+
+/**
+ * Tests if a bit in a bitmap is set.
+ *
+ * @returns true if the bit is set.
+ * @returns false if the bit is clear.
+ *
+ * @param   pvBitmap    Pointer to the bitmap.
+ * @param   iBit        The bit to test.
+ *
+ * @remarks The 32-bit aligning of pvBitmap is not a strict requirement.
+ *          However, doing so will yield better performance as well as avoiding
+ *          traps accessing the last bits in the bitmap.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(bool) ASMBitTest(const volatile void *pvBitmap, int32_t iBit);
+#else
+DECLINLINE(bool) ASMBitTest(const volatile void *pvBitmap, int32_t iBit)
+{
+    union { bool f; uint32_t u32; uint8_t u8; } rc;
+# if RT_INLINE_ASM_USES_INTRIN
+    rc.u32 = _bittest((long *)pvBitmap, iBit);
+# elif RT_INLINE_ASM_GNU_STYLE
+
+    __asm__ __volatile__("btl %2, %1\n\t"
+                         "setc %b0\n\t"
+                         "andl $1, %0\n\t"
+                         : "=q" (rc.u32)
+                         : "m" (*(const volatile long *)pvBitmap),
+                           "Ir" (iBit)
+                         : "memory");
+# else
+    __asm
+    {
+        mov   edx, [iBit]
+#  ifdef RT_ARCH_AMD64
+        mov   rax, [pvBitmap]
+        bt    [rax], edx
+#  else
+        mov   eax, [pvBitmap]
+        bt    [eax], edx
+#  endif
+        setc  al
+        and   eax, 1
+        mov   [rc.u32], eax
+    }
+# endif
+    return rc.f;
+}
+#endif
+
+
+/**
+ * Clears a bit range within a bitmap.
+ *
+ * @param   pvBitmap    Pointer to the bitmap.
+ * @param   iBitStart   The First bit to clear.
+ * @param   iBitEnd     The first bit not to clear.
+ */
+DECLINLINE(void) ASMBitClearRange(volatile void *pvBitmap, int32_t iBitStart, int32_t iBitEnd)
+{
+    if (iBitStart < iBitEnd)
+    {
+        volatile uint32_t *pu32 = (volatile uint32_t *)pvBitmap + (iBitStart >> 5);
+        int32_t iStart = iBitStart & ~31;
+        int32_t iEnd   = iBitEnd & ~31;
+        if (iStart == iEnd)
+            *pu32 &= ((UINT32_C(1) << (iBitStart & 31)) - 1) | ~((UINT32_C(1) << (iBitEnd & 31)) - 1);
+        else
+        {
+            /* bits in first dword. */
+            if (iBitStart & 31)
+            {
+                *pu32 &= (UINT32_C(1) << (iBitStart & 31)) - 1;
+                pu32++;
+                iBitStart = iStart + 32;
+            }
+
+            /* whole dword. */
+            if (iBitStart != iEnd)
+                ASMMemZero32(pu32, (iEnd - iBitStart) >> 3);
+
+            /* bits in last dword. */
+            if (iBitEnd & 31)
+            {
+                pu32 = (volatile uint32_t *)pvBitmap + (iBitEnd >> 5);
+                *pu32 &= ~((UINT32_C(1) << (iBitEnd & 31)) - 1);
+            }
+        }
+    }
+}
+
+
+/**
+ * Sets a bit range within a bitmap.
+ *
+ * @param   pvBitmap    Pointer to the bitmap.
+ * @param   iBitStart   The First bit to set.
+ * @param   iBitEnd     The first bit not to set.
+ */
+DECLINLINE(void) ASMBitSetRange(volatile void *pvBitmap, int32_t iBitStart, int32_t iBitEnd)
+{
+    if (iBitStart < iBitEnd)
+    {
+        volatile uint32_t *pu32 = (volatile uint32_t *)pvBitmap + (iBitStart >> 5);
+        int32_t iStart = iBitStart & ~31;
+        int32_t iEnd   = iBitEnd & ~31;
+        if (iStart == iEnd)
+            *pu32 |= ((UINT32_C(1) << (iBitEnd - iBitStart)) - 1) << (iBitStart & 31);
+        else
+        {
+            /* bits in first dword. */
+            if (iBitStart & 31)
+            {
+                *pu32 |= ~((UINT32_C(1) << (iBitStart & 31)) - 1);
+                pu32++;
+                iBitStart = iStart + 32;
+            }
+
+            /* whole dword. */
+            if (iBitStart != iEnd)
+                ASMMemFill32(pu32, (iEnd - iBitStart) >> 3, ~UINT32_C(0));
+
+            /* bits in last dword. */
+            if (iBitEnd & 31)
+            {
+                pu32 = (volatile uint32_t *)pvBitmap + (iBitEnd >> 5);
+                *pu32 |= (UINT32_C(1) << (iBitEnd & 31)) - 1;
+            }
+        }
+    }
+}
+
+
+/**
+ * Finds the first clear bit in a bitmap.
+ *
+ * @returns Index of the first zero bit.
+ * @returns -1 if no clear bit was found.
+ * @param   pvBitmap    Pointer to the bitmap.
+ * @param   cBits       The number of bits in the bitmap. Multiple of 32.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(int32_t) ASMBitFirstClear(const volatile void *pvBitmap, uint32_t cBits);
+#else
+DECLINLINE(int32_t) ASMBitFirstClear(const volatile void *pvBitmap, uint32_t cBits)
+{
+    if (cBits)
+    {
+        int32_t iBit;
+# if RT_INLINE_ASM_GNU_STYLE
+        RTCCUINTREG uEAX, uECX, uEDI;
+        cBits = RT_ALIGN_32(cBits, 32);
+        __asm__ __volatile__("repe; scasl\n\t"
+                             "je    1f\n\t"
+#  ifdef RT_ARCH_AMD64
+                             "lea   -4(%%rdi), %%rdi\n\t"
+                             "xorl  (%%rdi), %%eax\n\t"
+                             "subq  %5, %%rdi\n\t"
+#  else
+                             "lea   -4(%%edi), %%edi\n\t"
+                             "xorl  (%%edi), %%eax\n\t"
+                             "subl  %5, %%edi\n\t"
+#  endif
+                             "shll  $3, %%edi\n\t"
+                             "bsfl  %%eax, %%edx\n\t"
+                             "addl  %%edi, %%edx\n\t"
+                             "1:\t\n"
+                             : "=d" (iBit),
+                               "=&c" (uECX),
+                               "=&D" (uEDI),
+                               "=&a" (uEAX)
+                             : "0" (0xffffffff),
+                               "mr" (pvBitmap),
+                               "1" (cBits >> 5),
+                               "2" (pvBitmap),
+                               "3" (0xffffffff));
+# else
+        cBits = RT_ALIGN_32(cBits, 32);
+        __asm
+        {
+#  ifdef RT_ARCH_AMD64
+            mov     rdi, [pvBitmap]
+            mov     rbx, rdi
+#  else
+            mov     edi, [pvBitmap]
+            mov     ebx, edi
+#  endif
+            mov     edx, 0ffffffffh
+            mov     eax, edx
+            mov     ecx, [cBits]
+            shr     ecx, 5
+            repe    scasd
+            je      done
+
+#  ifdef RT_ARCH_AMD64
+            lea     rdi, [rdi - 4]
+            xor     eax, [rdi]
+            sub     rdi, rbx
+#  else
+            lea     edi, [edi - 4]
+            xor     eax, [edi]
+            sub     edi, ebx
+#  endif
+            shl     edi, 3
+            bsf     edx, eax
+            add     edx, edi
+        done:
+            mov     [iBit], edx
+        }
+# endif
+        return iBit;
+    }
+    return -1;
+}
+#endif
+
+
+/**
+ * Finds the next clear bit in a bitmap.
+ *
+ * @returns Index of the first zero bit.
+ * @returns -1 if no clear bit was found.
+ * @param   pvBitmap    Pointer to the bitmap.
+ * @param   cBits       The number of bits in the bitmap. Multiple of 32.
+ * @param   iBitPrev    The bit returned from the last search.
+ *                      The search will start at iBitPrev + 1.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(int) ASMBitNextClear(const volatile void *pvBitmap, uint32_t cBits, uint32_t iBitPrev);
+#else
+DECLINLINE(int) ASMBitNextClear(const volatile void *pvBitmap, uint32_t cBits, uint32_t iBitPrev)
+{
+    const volatile uint32_t *pau32Bitmap = (const volatile uint32_t *)pvBitmap;
+    int                      iBit = ++iBitPrev & 31;
+    if (iBit)
+    {
+        /*
+         * Inspect the 32-bit word containing the unaligned bit.
+         */
+        uint32_t  u32 = ~pau32Bitmap[iBitPrev / 32] >> iBit;
+
+# if RT_INLINE_ASM_USES_INTRIN
+        unsigned long ulBit = 0;
+        if (_BitScanForward(&ulBit, u32))
+            return ulBit + iBitPrev;
+# else
+#  if RT_INLINE_ASM_GNU_STYLE
+        __asm__ __volatile__("bsf %1, %0\n\t"
+                             "jnz 1f\n\t"
+                             "movl $-1, %0\n\t"
+                             "1:\n\t"
+                             : "=r" (iBit)
+                             : "r" (u32));
+#  else
+        __asm
+        {
+            mov     edx, [u32]
+            bsf     eax, edx
+            jnz     done
+            mov     eax, 0ffffffffh
+        done:
+            mov     [iBit], eax
+        }
+#  endif
+        if (iBit >= 0)
+            return iBit + iBitPrev;
+# endif
+
+        /*
+         * Skip ahead and see if there is anything left to search.
+         */
+        iBitPrev |= 31;
+        iBitPrev++;
+        if (cBits <= (uint32_t)iBitPrev)
+            return -1;
+    }
+
+    /*
+     * 32-bit aligned search, let ASMBitFirstClear do the dirty work.
+     */
+    iBit = ASMBitFirstClear(&pau32Bitmap[iBitPrev / 32], cBits - iBitPrev);
+    if (iBit >= 0)
+        iBit += iBitPrev;
+    return iBit;
+}
+#endif
+
+
+/**
+ * Finds the first set bit in a bitmap.
+ *
+ * @returns Index of the first set bit.
+ * @returns -1 if no clear bit was found.
+ * @param   pvBitmap    Pointer to the bitmap.
+ * @param   cBits       The number of bits in the bitmap. Multiple of 32.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(int32_t) ASMBitFirstSet(const volatile void *pvBitmap, uint32_t cBits);
+#else
+DECLINLINE(int32_t) ASMBitFirstSet(const volatile void *pvBitmap, uint32_t cBits)
+{
+    if (cBits)
+    {
+        int32_t iBit;
+# if RT_INLINE_ASM_GNU_STYLE
+        RTCCUINTREG uEAX, uECX, uEDI;
+        cBits = RT_ALIGN_32(cBits, 32);
+        __asm__ __volatile__("repe; scasl\n\t"
+                             "je    1f\n\t"
+#  ifdef RT_ARCH_AMD64
+                             "lea   -4(%%rdi), %%rdi\n\t"
+                             "movl  (%%rdi), %%eax\n\t"
+                             "subq  %5, %%rdi\n\t"
+#  else
+                             "lea   -4(%%edi), %%edi\n\t"
+                             "movl  (%%edi), %%eax\n\t"
+                             "subl  %5, %%edi\n\t"
+#  endif
+                             "shll  $3, %%edi\n\t"
+                             "bsfl  %%eax, %%edx\n\t"
+                             "addl  %%edi, %%edx\n\t"
+                             "1:\t\n"
+                             : "=d" (iBit),
+                               "=&c" (uECX),
+                               "=&D" (uEDI),
+                               "=&a" (uEAX)
+                             : "0" (0xffffffff),
+                               "mr" (pvBitmap),
+                               "1" (cBits >> 5),
+                               "2" (pvBitmap),
+                               "3" (0));
+# else
+        cBits = RT_ALIGN_32(cBits, 32);
+        __asm
+        {
+#  ifdef RT_ARCH_AMD64
+            mov     rdi, [pvBitmap]
+            mov     rbx, rdi
+#  else
+            mov     edi, [pvBitmap]
+            mov     ebx, edi
+#  endif
+            mov     edx, 0ffffffffh
+            xor     eax, eax
+            mov     ecx, [cBits]
+            shr     ecx, 5
+            repe    scasd
+            je      done
+#  ifdef RT_ARCH_AMD64
+            lea     rdi, [rdi - 4]
+            mov     eax, [rdi]
+            sub     rdi, rbx
+#  else
+            lea     edi, [edi - 4]
+            mov     eax, [edi]
+            sub     edi, ebx
+#  endif
+            shl     edi, 3
+            bsf     edx, eax
+            add     edx, edi
+        done:
+            mov   [iBit], edx
+        }
+# endif
+        return iBit;
+    }
+    return -1;
+}
+#endif
+
+
+/**
+ * Finds the next set bit in a bitmap.
+ *
+ * @returns Index of the next set bit.
+ * @returns -1 if no set bit was found.
+ * @param   pvBitmap    Pointer to the bitmap.
+ * @param   cBits       The number of bits in the bitmap. Multiple of 32.
+ * @param   iBitPrev    The bit returned from the last search.
+ *                      The search will start at iBitPrev + 1.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(int) ASMBitNextSet(const volatile void *pvBitmap, uint32_t cBits, uint32_t iBitPrev);
+#else
+DECLINLINE(int) ASMBitNextSet(const volatile void *pvBitmap, uint32_t cBits, uint32_t iBitPrev)
+{
+    const volatile uint32_t *pau32Bitmap = (const volatile uint32_t *)pvBitmap;
+    int                      iBit = ++iBitPrev & 31;
+    if (iBit)
+    {
+        /*
+         * Inspect the 32-bit word containing the unaligned bit.
+         */
+        uint32_t  u32 = pau32Bitmap[iBitPrev / 32] >> iBit;
+
+# if RT_INLINE_ASM_USES_INTRIN
+        unsigned long ulBit = 0;
+        if (_BitScanForward(&ulBit, u32))
+            return ulBit + iBitPrev;
+# else
+#  if RT_INLINE_ASM_GNU_STYLE
+        __asm__ __volatile__("bsf %1, %0\n\t"
+                             "jnz 1f\n\t"
+                             "movl $-1, %0\n\t"
+                             "1:\n\t"
+                             : "=r" (iBit)
+                             : "r" (u32));
+#  else
+        __asm
+        {
+            mov     edx, [u32]
+            bsf     eax, edx
+            jnz     done
+            mov     eax, 0ffffffffh
+        done:
+            mov     [iBit], eax
+        }
+#  endif
+        if (iBit >= 0)
+            return iBit + iBitPrev;
+# endif
+
+        /*
+         * Skip ahead and see if there is anything left to search.
+         */
+        iBitPrev |= 31;
+        iBitPrev++;
+        if (cBits <= (uint32_t)iBitPrev)
+            return -1;
+    }
+
+    /*
+     * 32-bit aligned search, let ASMBitFirstClear do the dirty work.
+     */
+    iBit = ASMBitFirstSet(&pau32Bitmap[iBitPrev / 32], cBits - iBitPrev);
+    if (iBit >= 0)
+        iBit += iBitPrev;
+    return iBit;
+}
+#endif
+
+
+/**
+ * Finds the first bit which is set in the given 32-bit integer.
+ * Bits are numbered from 1 (least significant) to 32.
+ *
+ * @returns index [1..32] of the first set bit.
+ * @returns 0 if all bits are cleared.
+ * @param   u32     Integer to search for set bits.
+ * @remarks Similar to ffs() in BSD.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(unsigned) ASMBitFirstSetU32(uint32_t u32);
+#else
+DECLINLINE(unsigned) ASMBitFirstSetU32(uint32_t u32)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    unsigned long iBit;
+    if (_BitScanForward(&iBit, u32))
+        iBit++;
+    else
+        iBit = 0;
+# elif RT_INLINE_ASM_GNU_STYLE
+    uint32_t iBit;
+    __asm__ __volatile__("bsf  %1, %0\n\t"
+                         "jnz  1f\n\t"
+                         "xorl %0, %0\n\t"
+                         "jmp  2f\n"
+                         "1:\n\t"
+                         "incl %0\n"
+                         "2:\n\t"
+                         : "=r" (iBit)
+                         : "rm" (u32));
+# else
+    uint32_t iBit;
+    _asm
+    {
+        bsf     eax, [u32]
+        jnz     found
+        xor     eax, eax
+        jmp     done
+    found:
+        inc     eax
+    done:
+        mov     [iBit], eax
+    }
+# endif
+    return iBit;
+}
+#endif
+
+
+/**
+ * Finds the first bit which is set in the given 32-bit integer.
+ * Bits are numbered from 1 (least significant) to 32.
+ *
+ * @returns index [1..32] of the first set bit.
+ * @returns 0 if all bits are cleared.
+ * @param   i32     Integer to search for set bits.
+ * @remark  Similar to ffs() in BSD.
+ */
+DECLINLINE(unsigned) ASMBitFirstSetS32(int32_t i32)
+{
+    return ASMBitFirstSetU32((uint32_t)i32);
+}
+
+
+/**
+ * Finds the first bit which is set in the given 64-bit integer.
+ *
+ * Bits are numbered from 1 (least significant) to 64.
+ *
+ * @returns index [1..64] of the first set bit.
+ * @returns 0 if all bits are cleared.
+ * @param   u64     Integer to search for set bits.
+ * @remarks Similar to ffs() in BSD.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(unsigned) ASMBitFirstSetU64(uint64_t u64);
+#else
+DECLINLINE(unsigned) ASMBitFirstSetU64(uint64_t u64)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    unsigned long iBit;
+#  if ARCH_BITS == 64
+    if (_BitScanForward64(&iBit, u64))
+        iBit++;
+    else
+        iBit = 0;
+#  else
+    if (_BitScanForward(&iBit, (uint32_t)u64))
+        iBit++;
+    else if (_BitScanForward(&iBit, (uint32_t)(u64 >> 32)))
+        iBit += 33;
+    else
+        iBit = 0;
+#  endif
+# elif RT_INLINE_ASM_GNU_STYLE && ARCH_BITS == 64
+    uint64_t iBit;
+    __asm__ __volatile__("bsfq %1, %0\n\t"
+                         "jnz  1f\n\t"
+                         "xorl %k0, %k0\n\t"
+                         "jmp  2f\n"
+                         "1:\n\t"
+                         "incl %k0\n"
+                         "2:\n\t"
+                         : "=r" (iBit)
+                         : "rm" (u64));
+# else
+    unsigned iBit = ASMBitFirstSetU32((uint32_t)u64);
+    if (!iBit)
+    {
+        iBit = ASMBitFirstSetU32((uint32_t)(u64 >> 32));
+        if (iBit)
+            iBit += 32;
+    }
+# endif
+    return (unsigned)iBit;
+}
+#endif
+
+
+/**
+ * Finds the first bit which is set in the given 16-bit integer.
+ *
+ * Bits are numbered from 1 (least significant) to 16.
+ *
+ * @returns index [1..16] of the first set bit.
+ * @returns 0 if all bits are cleared.
+ * @param   u16     Integer to search for set bits.
+ * @remarks For 16-bit bs3kit code.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(unsigned) ASMBitFirstSetU16(uint16_t u16);
+#else
+DECLINLINE(unsigned) ASMBitFirstSetU16(uint16_t u16)
+{
+    return ASMBitFirstSetU32((uint32_t)u16);
+}
+#endif
+
+
+/**
+ * Finds the last bit which is set in the given 32-bit integer.
+ * Bits are numbered from 1 (least significant) to 32.
+ *
+ * @returns index [1..32] of the last set bit.
+ * @returns 0 if all bits are cleared.
+ * @param   u32     Integer to search for set bits.
+ * @remark  Similar to fls() in BSD.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(unsigned) ASMBitLastSetU32(uint32_t u32);
+#else
+DECLINLINE(unsigned) ASMBitLastSetU32(uint32_t u32)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    unsigned long iBit;
+    if (_BitScanReverse(&iBit, u32))
+        iBit++;
+    else
+        iBit = 0;
+# elif RT_INLINE_ASM_GNU_STYLE
+    uint32_t iBit;
+    __asm__ __volatile__("bsrl %1, %0\n\t"
+                         "jnz   1f\n\t"
+                         "xorl %0, %0\n\t"
+                         "jmp  2f\n"
+                         "1:\n\t"
+                         "incl %0\n"
+                         "2:\n\t"
+                         : "=r" (iBit)
+                         : "rm" (u32));
+# else
+    uint32_t iBit;
+    _asm
+    {
+        bsr     eax, [u32]
+        jnz     found
+        xor     eax, eax
+        jmp     done
+    found:
+        inc     eax
+    done:
+        mov     [iBit], eax
+    }
+# endif
+    return iBit;
+}
+#endif
+
+
+/**
+ * Finds the last bit which is set in the given 32-bit integer.
+ * Bits are numbered from 1 (least significant) to 32.
+ *
+ * @returns index [1..32] of the last set bit.
+ * @returns 0 if all bits are cleared.
+ * @param   i32     Integer to search for set bits.
+ * @remark  Similar to fls() in BSD.
+ */
+DECLINLINE(unsigned) ASMBitLastSetS32(int32_t i32)
+{
+    return ASMBitLastSetU32((uint32_t)i32);
+}
+
+
+/**
+ * Finds the last bit which is set in the given 64-bit integer.
+ *
+ * Bits are numbered from 1 (least significant) to 64.
+ *
+ * @returns index [1..64] of the last set bit.
+ * @returns 0 if all bits are cleared.
+ * @param   u64     Integer to search for set bits.
+ * @remark  Similar to fls() in BSD.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(unsigned) ASMBitLastSetU64(uint64_t u64);
+#else
+DECLINLINE(unsigned) ASMBitLastSetU64(uint64_t u64)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    unsigned long iBit;
+#  if ARCH_BITS == 64
+    if (_BitScanReverse64(&iBit, u64))
+        iBit++;
+    else
+        iBit = 0;
+#  else
+    if (_BitScanReverse(&iBit, (uint32_t)(u64 >> 32)))
+        iBit += 33;
+    else if (_BitScanReverse(&iBit, (uint32_t)u64))
+        iBit++;
+    else
+        iBit = 0;
+#  endif
+# elif RT_INLINE_ASM_GNU_STYLE && ARCH_BITS == 64
+    uint64_t iBit;
+    __asm__ __volatile__("bsrq %1, %0\n\t"
+                         "jnz  1f\n\t"
+                         "xorl %k0, %k0\n\t"
+                         "jmp  2f\n"
+                         "1:\n\t"
+                         "incl %k0\n"
+                         "2:\n\t"
+                         : "=r" (iBit)
+                         : "rm" (u64));
+# else
+    unsigned iBit = ASMBitLastSetU32((uint32_t)(u64 >> 32));
+    if (iBit)
+        iBit += 32;
+    else
+        iBit = ASMBitLastSetU32((uint32_t)u64);
+#endif
+    return (unsigned)iBit;
+}
+#endif
+
+
+/**
+ * Finds the last bit which is set in the given 16-bit integer.
+ *
+ * Bits are numbered from 1 (least significant) to 16.
+ *
+ * @returns index [1..16] of the last set bit.
+ * @returns 0 if all bits are cleared.
+ * @param   u16     Integer to search for set bits.
+ * @remarks For 16-bit bs3kit code.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(unsigned) ASMBitLastSetU16(uint16_t u16);
+#else
+DECLINLINE(unsigned) ASMBitLastSetU16(uint16_t u16)
+{
+    return ASMBitLastSetU32((uint32_t)u16);
+}
+#endif
+
+
+/**
+ * Reverse the byte order of the given 16-bit integer.
+ *
+ * @returns Revert
+ * @param   u16     16-bit integer value.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint16_t) ASMByteSwapU16(uint16_t u16);
+#else
+DECLINLINE(uint16_t) ASMByteSwapU16(uint16_t u16)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    u16 = _byteswap_ushort(u16);
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ ("rorw $8, %0" : "=r" (u16) : "0" (u16));
+# else
+    _asm
+    {
+        mov     ax, [u16]
+        ror     ax, 8
+        mov     [u16], ax
+    }
+# endif
+    return u16;
+}
+#endif
+
+
+/**
+ * Reverse the byte order of the given 32-bit integer.
+ *
+ * @returns Revert
+ * @param   u32     32-bit integer value.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint32_t) ASMByteSwapU32(uint32_t u32);
+#else
+DECLINLINE(uint32_t) ASMByteSwapU32(uint32_t u32)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    u32 = _byteswap_ulong(u32);
+# elif RT_INLINE_ASM_GNU_STYLE
+    __asm__ ("bswapl %0" : "=r" (u32) : "0" (u32));
+# else
+    _asm
+    {
+        mov     eax, [u32]
+        bswap   eax
+        mov     [u32], eax
+    }
+# endif
+    return u32;
+}
+#endif
+
+
+/**
+ * Reverse the byte order of the given 64-bit integer.
+ *
+ * @returns Revert
+ * @param   u64     64-bit integer value.
+ */
+DECLINLINE(uint64_t) ASMByteSwapU64(uint64_t u64)
+{
+#if defined(RT_ARCH_AMD64) && RT_INLINE_ASM_USES_INTRIN
+    u64 = _byteswap_uint64(u64);
+#else
+    u64 = (uint64_t)ASMByteSwapU32((uint32_t)u64) << 32
+        | (uint64_t)ASMByteSwapU32((uint32_t)(u64 >> 32));
+#endif
+    return u64;
+}
+
+
+/**
+ * Rotate 32-bit unsigned value to the left by @a cShift.
+ *
+ * @returns Rotated value.
+ * @param   u32                 The value to rotate.
+ * @param   cShift              How many bits to rotate by.
+ */
+#ifdef __WATCOMC__
+DECLASM(uint32_t) ASMRotateLeftU32(uint32_t u32, unsigned cShift);
+#else
+DECLINLINE(uint32_t) ASMRotateLeftU32(uint32_t u32, uint32_t cShift)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    return _rotl(u32, cShift);
+# elif RT_INLINE_ASM_GNU_STYLE && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
+    __asm__ __volatile__("roll %b1, %0" : "=g" (u32) : "Ic" (cShift), "0" (u32));
+    return u32;
+# else
+    cShift &= 31;
+    return (u32 << cShift) | (u32 >> (32 - cShift));
+# endif
+}
+#endif
+
+
+/**
+ * Rotate 32-bit unsigned value to the right by @a cShift.
+ *
+ * @returns Rotated value.
+ * @param   u32                 The value to rotate.
+ * @param   cShift              How many bits to rotate by.
+ */
+#ifdef __WATCOMC__
+DECLASM(uint32_t) ASMRotateRightU32(uint32_t u32, unsigned cShift);
+#else
+DECLINLINE(uint32_t) ASMRotateRightU32(uint32_t u32, uint32_t cShift)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+    return _rotr(u32, cShift);
+# elif RT_INLINE_ASM_GNU_STYLE && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
+    __asm__ __volatile__("rorl %b1, %0" : "=g" (u32) : "Ic" (cShift), "0" (u32));
+    return u32;
+# else
+    cShift &= 31;
+    return (u32 >> cShift) | (u32 << (32 - cShift));
+# endif
+}
+#endif
+
+
+/**
+ * Rotate 64-bit unsigned value to the left by @a cShift.
+ *
+ * @returns Rotated value.
+ * @param   u64                 The value to rotate.
+ * @param   cShift              How many bits to rotate by.
+ */
+DECLINLINE(uint64_t) ASMRotateLeftU64(uint64_t u64, uint32_t cShift)
+{
+#if RT_INLINE_ASM_USES_INTRIN
+    return _rotl64(u64, cShift);
+#elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64)
+    __asm__ __volatile__("rolq %b1, %0" : "=g" (u64) : "Jc" (cShift), "0" (u64));
+    return u64;
+#elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_X86)
+    uint32_t uSpill;
+    __asm__ __volatile__("testb $0x20, %%cl\n\t"        /* if (cShift >= 0x20) { swap(u64.hi, u64lo); cShift -= 0x20; } */
+                         "jz    1f\n\t"
+                         "xchgl %%eax, %%edx\n\t"
+                         "1:\n\t"
+                         "andb  $0x1f, %%cl\n\t"        /* if (cShift & 0x1f) { */
+                         "jz    2f\n\t"
+                         "movl  %%edx, %2\n\t"          /*   save the hi value in %3. */
+                         "shldl %%cl,%%eax,%%edx\n\t"   /*   shift the hi value left, feeding MSBits from the low value. */
+                         "shldl %%cl,%2,%%eax\n\t"      /*   shift the lo value left, feeding MSBits from the saved hi value. */
+                         "2:\n\t"                       /* } */
+                         : "=A" (u64), "=c" (cShift), "=r" (uSpill)
+                         : "0" (u64),
+                           "1" (cShift));
+    return u64;
+#else
+    cShift &= 63;
+    return (u64 << cShift) | (u64 >> (64 - cShift));
+#endif
+}
+
+
+/**
+ * Rotate 64-bit unsigned value to the right by @a cShift.
+ *
+ * @returns Rotated value.
+ * @param   u64                 The value to rotate.
+ * @param   cShift              How many bits to rotate by.
+ */
+DECLINLINE(uint64_t) ASMRotateRightU64(uint64_t u64, uint32_t cShift)
+{
+#if RT_INLINE_ASM_USES_INTRIN
+    return _rotr64(u64, cShift);
+#elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64)
+    __asm__ __volatile__("rorq %b1, %0" : "=g" (u64) : "Jc" (cShift), "0" (u64));
+    return u64;
+#elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_X86)
+    uint32_t uSpill;
+    __asm__ __volatile__("testb $0x20, %%cl\n\t"        /* if (cShift >= 0x20) { swap(u64.hi, u64lo); cShift -= 0x20; } */
+                         "jz    1f\n\t"
+                         "xchgl %%eax, %%edx\n\t"
+                         "1:\n\t"
+                         "andb  $0x1f, %%cl\n\t"        /* if (cShift & 0x1f) { */
+                         "jz    2f\n\t"
+                         "movl  %%edx, %2\n\t"          /*   save the hi value in %3. */
+                         "shrdl %%cl,%%eax,%%edx\n\t"   /*   shift the hi value right, feeding LSBits from the low value. */
+                         "shrdl %%cl,%2,%%eax\n\t"      /*   shift the lo value right, feeding LSBits from the saved hi value. */
+                         "2:\n\t"                       /* } */
+                         : "=A" (u64), "=c" (cShift), "=r" (uSpill)
+                         : "0" (u64),
+                           "1" (cShift));
+    return u64;
+#else
+    cShift &= 63;
+    return (u64 >> cShift) | (u64 << (64 - cShift));
+#endif
+}
+
+/** @} */
+
+
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/assert.h b/ubuntu/vbox/include/iprt/assert.h
new file mode 100644 (file)
index 0000000..47afdd8
--- /dev/null
@@ -0,0 +1,2845 @@
+/** @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.
+ */
+
+#ifndef ___iprt_assert_h
+#define ___iprt_assert_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+
+/** @defgroup grp_rt_assert     Assert - Assertions
+ * @ingroup grp_rt
+ *
+ * Assertions are generally used to check preconditions and other
+ * assumptions. Sometimes it is also used to catch odd errors or errors
+ * that one would like to inspect in the debugger. They should not be
+ * used for errors that happen frequently.
+ *
+ * IPRT provides a host of assertion macros, so many that it can be a bit
+ * overwhelming at first. Don't despair, there is a system (surprise).
+ *
+ * First there are four families of assertions:
+ *      - Assert        - The normal strict build only assertions.
+ *      - AssertLogRel  - Calls LogRel() in non-strict builds, otherwise like Assert.
+ *      - AssertRelease - Triggers in all builds.
+ *      - AssertFatal   - Triggers in all builds and cannot be continued.
+ *
+ * Then there are variations wrt to argument list and behavior on failure:
+ *      - Msg           - Custom RTStrPrintf-like message with the assertion message.
+ *      - Return        - Return the specific rc on failure.
+ *      - ReturnVoid    - Return (void) on failure.
+ *      - Break         - Break (out of switch/loop) on failure.
+ *      - Stmt          - Execute the specified statement(s) on failure.
+ *      - RC            - Assert RT_SUCCESS.
+ *      - RCSuccess     - Assert VINF_SUCCESS.
+ *
+ * In addition there is a very special family AssertCompile that can be
+ * used for some limited compile-time checking, like structure sizes and member
+ * alignment. This family doesn't have the same variations.
+ *
+ *
+ * @remarks As you might have noticed, the macros don't follow the
+ * coding guidelines wrt to macros supposedly being all uppercase
+ * and underscored. For various  reasons they don't, and nobody
+ * has complained yet. Wonder why... :-)
+ *
+ * @remarks Each project has its own specific guidelines on how to use
+ * assertions, so the above is just trying to give you the general idea
+ * from the IPRT point of view.
+ *
+ * @{
+ */
+
+RT_C_DECLS_BEGIN
+
+/**
+ * The 1st part of an assert message.
+ *
+ * @param   pszExpr     Expression. Can be NULL.
+ * @param   uLine       Location line number.
+ * @param   pszFile     Location file name.
+ * @param   pszFunction Location function name.
+ */
+RTDECL(void)    RTAssertMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction);
+/**
+ * Weak version of RTAssertMsg1 that can be overridden locally in a module to
+ * modify, redirect or otherwise mess with the assertion output.
+ *
+ * @copydoc RTAssertMsg1
+ */
+RTDECL(void)    RTAssertMsg1Weak(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction);
+
+/**
+ * The 2nd (optional) part of an assert message.
+ *
+ * @param   pszFormat   Printf like format string.
+ * @param   ...         Arguments to that string.
+ */
+RTDECL(void)    RTAssertMsg2(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+/**
+ * Weak version of RTAssertMsg2 that forwards to RTAssertMsg2WeakV.
+ *
+ * There is not need to override this, check out RTAssertMsg2WeakV instead!
+ *
+ * @copydoc RTAssertMsg2
+ */
+RTDECL(void)    RTAssertMsg2Weak(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * The 2nd (optional) part of an assert message.
+ *
+ * @param   pszFormat   Printf like format string.
+ * @param   va          Arguments to that string.
+ */
+RTDECL(void)    RTAssertMsg2V(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+/**
+ * Weak version of RTAssertMsg2V that can be overridden locally in a module to
+ * modify, redirect or otherwise mess with the assertion output.
+ *
+ * @copydoc RTAssertMsg2V
+ */
+RTDECL(void)    RTAssertMsg2WeakV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Additional information which should be appended to the 2nd part of an
+ * assertion message.
+ *
+ * @param   pszFormat   Printf like format string.
+ * @param   ...         Arguments to that string.
+ */
+RTDECL(void)    RTAssertMsg2Add(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+/**
+ * Weak version of RTAssertMsg2Add that forwards to RTAssertMsg2AddWeakV.
+ *
+ * There is not need to override this, check out RTAssertMsg2AddWeakV instead!
+ *
+ * @copydoc RTAssertMsg2Add
+ */
+RTDECL(void)    RTAssertMsg2AddWeak(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Additional information which should be appended to the 2nd part of an
+ * assertion message.
+ *
+ * @param   pszFormat   Printf like format string.
+ * @param   va          Arguments to that string.
+ */
+RTDECL(void)    RTAssertMsg2AddV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+/**
+ * Weak version of RTAssertMsg2AddV that can be overridden locally in a module
+ * to modify, redirect or otherwise mess with the assertion output.
+ *
+ * @copydoc RTAssertMsg2AddV
+ */
+RTDECL(void)    RTAssertMsg2AddWeakV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+#ifdef IN_RING0
+/**
+ * Panics the system as the result of a fail assertion.
+ */
+RTR0DECL(void)  RTR0AssertPanicSystem(void);
+#endif /* IN_RING0 */
+
+/**
+ * Overridable function that decides whether assertions executes the panic
+ * (breakpoint) or not.
+ *
+ * The generic implementation will return true.
+ *
+ * @returns true if the breakpoint should be hit, false if it should be ignored.
+ *
+ * @remark  The RTDECL() makes this a bit difficult to override on Windows. So,
+ *          you'll have to use RTASSERT_HAVE_SHOULD_PANIC or
+ *          RTASSERT_HAVE_SHOULD_PANIC_PRIVATE there to control the kind of
+ *          prototype.
+ */
+#if !defined(RTASSERT_HAVE_SHOULD_PANIC) && !defined(RTASSERT_HAVE_SHOULD_PANIC_PRIVATE)
+RTDECL(bool)    RTAssertShouldPanic(void);
+#elif defined(RTASSERT_HAVE_SHOULD_PANIC_PRIVATE)
+bool            RTAssertShouldPanic(void);
+#else
+DECLEXPORT(bool) RTCALL RTAssertShouldPanic(void);
+#endif
+
+/**
+ * Controls whether the assertions should be quiet or noisy (default).
+ *
+ * @returns The old setting.
+ * @param   fQuiet              The new setting.
+ */
+RTDECL(bool)    RTAssertSetQuiet(bool fQuiet);
+
+/**
+ * Are assertions quiet or noisy?
+ *
+ * @returns True if they are quiet, false if noisy.
+ */
+RTDECL(bool)    RTAssertAreQuiet(void);
+
+/**
+ * Makes the assertions panic (default) or not.
+ *
+ * @returns The old setting.
+ * @param   fPanic              The new setting.
+ */
+RTDECL(bool)    RTAssertSetMayPanic(bool fPanic);
+
+/**
+ * Can assertion panic.
+ *
+ * @returns True if they can, false if not.
+ */
+RTDECL(bool)    RTAssertMayPanic(void);
+
+
+/** @name Globals for crash analysis
+ * @remarks     This is the full potential set, it
+ * @{
+ */
+/** The last assert message, 1st part. */
+extern RTDATADECL(char)                     g_szRTAssertMsg1[1024];
+/** The last assert message, 2nd part. */
+extern RTDATADECL(char)                     g_szRTAssertMsg2[4096];
+/** The last assert message, expression. */
+extern RTDATADECL(const char * volatile)    g_pszRTAssertExpr;
+/** The last assert message, file name. */
+extern RTDATADECL(const char * volatile)    g_pszRTAssertFile;
+/** The last assert message, line number. */
+extern RTDATADECL(uint32_t volatile)        g_u32RTAssertLine;
+/** The last assert message, function name. */
+extern RTDATADECL(const char * volatile)    g_pszRTAssertFunction;
+/** @} */
+
+RT_C_DECLS_END
+
+/** @def RTAssertDebugBreak()
+ * Debugger breakpoint instruction.
+ *
+ * @remarks This macro does not depend on RT_STRICT.
+ */
+#define RTAssertDebugBreak()    do { RT_BREAKPOINT(); } while (0)
+
+
+
+/** @name Compile time assertions.
+ *
+ * These assertions are used to check structure sizes, member/size alignments
+ * and similar compile time expressions.
+ *
+ * @{
+ */
+
+/**
+ * RTASSERTTYPE is the type the AssertCompile() macro redefines.
+ * It has no other function and shouldn't be used.
+ * Visual C++ uses this.
+ */
+typedef int RTASSERTTYPE[1];
+
+/**
+ * RTASSERTVAR is the type the AssertCompile() macro redefines.
+ * It has no other function and shouldn't be used.
+ * GCC uses this.
+ */
+#ifdef __GNUC__
+RT_C_DECLS_BEGIN
+#endif
+extern int RTASSERTVAR[1];
+#ifdef __GNUC__
+RT_C_DECLS_END
+#endif
+
+/** @def RTASSERT_HAVE_STATIC_ASSERT
+ * Indicates that the compiler implements static_assert(expr, msg).
+ */
+#ifdef _MSC_VER
+# if _MSC_VER >= 1600 && defined(__cplusplus)
+#  define RTASSERT_HAVE_STATIC_ASSERT
+# endif
+#endif
+#if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define RTASSERT_HAVE_STATIC_ASSERT
+#endif
+#if RT_CLANG_PREREQ(6, 0)
+# if __has_feature(cxx_static_assert) || __has_feature(c_static_assert)
+#  define RTASSERT_HAVE_STATIC_ASSERT
+# endif
+#endif
+#ifdef DOXYGEN_RUNNING
+# define RTASSERT_HAVE_STATIC_ASSERT
+#endif
+
+/** @def AssertCompileNS
+ * Asserts that a compile-time expression is true. If it's not break the build.
+ *
+ * This differs from AssertCompile in that it accepts some more expressions
+ * than what C++0x allows - NS = Non-standard.
+ *
+ * @param   expr    Expression which should be true.
+ */
+#ifdef __GNUC__
+# define AssertCompileNS(expr)  extern int RTASSERTVAR[1] __attribute__((__unused__)), RTASSERTVAR[(expr) ? 1 : 0] __attribute__((__unused__))
+#elif defined(__IBMC__) || defined(__IBMCPP__)
+# define AssertCompileNS(expr)  extern int RTASSERTVAR[(expr) ? 1 : 0]
+#else
+# define AssertCompileNS(expr)  typedef int RTASSERTTYPE[(expr) ? 1 : 0]
+#endif
+
+/** @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.
+ */
+#ifdef RTASSERT_HAVE_STATIC_ASSERT
+# define AssertCompile(expr)    static_assert(!!(expr), #expr)
+#else
+# define AssertCompile(expr)    AssertCompileNS(expr)
+#endif
+
+/** @def RTASSERT_OFFSET_OF()
+ * A offsetof() macro suitable for compile time assertions.
+ * Both GCC v4 and VisualAge for C++ v3.08 has trouble using RT_OFFSETOF.
+ */
+#if defined(__GNUC__)
+# if __GNUC__ >= 4
+#  define RTASSERT_OFFSET_OF(a_Type, a_Member)  __builtin_offsetof(a_Type, a_Member)
+# else
+#  define RTASSERT_OFFSET_OF(a_Type, a_Member)  RT_OFFSETOF(a_Type, a_Member)
+# endif
+#elif (defined(__IBMC__) || defined(__IBMCPP__)) && defined(RT_OS_OS2)
+# define RTASSERT_OFFSET_OF(a_Type, a_Member)   __offsetof(a_Type, a_Member)
+#else
+# define RTASSERT_OFFSET_OF(a_Type, a_Member)   RT_OFFSETOF(a_Type, a_Member)
+#endif
+
+
+/** @def AssertCompileSize
+ * Asserts a size at compile.
+ * @param   type    The type.
+ * @param   size    The expected type size.
+ */
+#define AssertCompileSize(type, size) \
+    AssertCompile(sizeof(type) == (size))
+
+/** @def AssertCompileSizeAlignment
+ * Asserts a size alignment at compile.
+ * @param   type    The type.
+ * @param   align   The size alignment to assert.
+ */
+#define AssertCompileSizeAlignment(type, align) \
+    AssertCompile(!(sizeof(type) & ((align) - 1)))
+
+/** @def AssertCompileMemberSize
+ * Asserts a member offset alignment at compile.
+ * @param   type    The type.
+ * @param   member  The member.
+ * @param   size    The member size to assert.
+ */
+#define AssertCompileMemberSize(type, member, size) \
+    AssertCompile(RT_SIZEOFMEMB(type, member) == (size))
+
+/** @def AssertCompileMemberSizeAlignment
+ * Asserts a member size alignment at compile.
+ * @param   type    The type.
+ * @param   member  The member.
+ * @param   align   The member size alignment to assert.
+ */
+#define AssertCompileMemberSizeAlignment(type, member, align) \
+    AssertCompile(!(RT_SIZEOFMEMB(type, member) & ((align) - 1)))
+
+/** @def AssertCompileMemberAlignment
+ * Asserts a member offset alignment at compile.
+ * @param   type    The type.
+ * @param   member  The member.
+ * @param   align   The member offset alignment to assert.
+ */
+#define AssertCompileMemberAlignment(type, member, align) \
+    AssertCompile(!(RTASSERT_OFFSET_OF(type, member) & ((align) - 1)))
+
+/** @def AssertCompileMemberOffset
+ * Asserts an offset of a structure member at compile.
+ * @param   type    The type.
+ * @param   member  The member.
+ * @param   off     The expected offset.
+ */
+#define AssertCompileMemberOffset(type, member, off) \
+    AssertCompile(RTASSERT_OFFSET_OF(type, member) == (off))
+
+/** @def AssertCompile2MemberOffsets
+ * Asserts that two (sub-structure) members in union have the same offset.
+ * @param   type    The type.
+ * @param   member1 The first member.
+ * @param   member2 The second member.
+ */
+#define AssertCompile2MemberOffsets(type, member1, member2) \
+    AssertCompile(RTASSERT_OFFSET_OF(type, member1) == RTASSERT_OFFSET_OF(type, member2))
+
+/** @def AssertCompileAdjacentMembers
+ * Asserts that two structure members are adjacent.
+ * @param   type    The type.
+ * @param   member1 The first member.
+ * @param   member2 The second member.
+ */
+#define AssertCompileAdjacentMembers(type, member1, member2) \
+    AssertCompile(RTASSERT_OFFSET_OF(type, member1) + RT_SIZEOFMEMB(type, member1) == RTASSERT_OFFSET_OF(type, member2))
+
+/** @def AssertCompileMembersAtSameOffset
+ * Asserts that members of two different structures are at the same offset.
+ * @param   type1   The first type.
+ * @param   member1 The first member.
+ * @param   type2   The second type.
+ * @param   member2 The second member.
+ */
+#define AssertCompileMembersAtSameOffset(type1, member1, type2, member2) \
+    AssertCompile(RTASSERT_OFFSET_OF(type1, member1) == RTASSERT_OFFSET_OF(type2, member2))
+
+/** @def AssertCompileMembersSameSize
+ * Asserts that members of two different structures have the same size.
+ * @param   type1   The first type.
+ * @param   member1 The first member.
+ * @param   type2   The second type.
+ * @param   member2 The second member.
+ */
+#define AssertCompileMembersSameSize(type1, member1, type2, member2) \
+    AssertCompile(RT_SIZEOFMEMB(type1, member1) == RT_SIZEOFMEMB(type2, member2))
+
+/** @def AssertCompileMembersSameSizeAndOffset
+ * Asserts that members of two different structures have the same size and are
+ * at the same offset.
+ * @param   type1   The first type.
+ * @param   member1 The first member.
+ * @param   type2   The second type.
+ * @param   member2 The second member.
+ */
+#define AssertCompileMembersSameSizeAndOffset(type1, member1, type2, member2) \
+    AssertCompile(   RTASSERT_OFFSET_OF(type1, member1) == RTASSERT_OFFSET_OF(type2, member2) \
+                  && RT_SIZEOFMEMB(type1, member1) == RT_SIZEOFMEMB(type2, member2))
+
+/** @} */
+
+
+
+/** @name Assertions
+ *
+ * These assertions will only trigger when RT_STRICT is defined. When it is
+ * undefined they will all be no-ops and generate no code.
+ *
+ * @{
+ */
+
+
+/** @def RTASSERT_QUIET
+ * This can be defined to shut up the messages for a file where this would be
+ * problematic because the message printing code path passes thru it.
+ * @internal */
+#ifdef DOXYGEN_RUNNING
+# define RTASSERT_QUIET
+#endif
+#if defined(RTASSERT_QUIET) && !defined(DOXYGEN_RUNNING)
+# define RTAssertMsg1Weak(pszExpr, uLine, pszfile, pszFunction) \
+                                do { } while (0)
+# define RTAssertMsg2Weak       if (1) {} else RTAssertMsg2Weak
+#endif
+
+/** @def RTAssertDoPanic
+ * Raises an assertion panic appropriate to the current context.
+ * @remarks This macro does not depend on RT_STRICT.
+ */
+#if defined(IN_RING0) \
+ && (defined(RT_OS_DARWIN) || defined(RT_OS_HAIKU) || defined(RT_OS_SOLARIS))
+# define RTAssertDoPanic()      RTR0AssertPanicSystem()
+#else
+# define RTAssertDoPanic()      RTAssertDebugBreak()
+#endif
+
+/** @def AssertBreakpoint()
+ * Assertion Breakpoint.
+ * @deprecated Use RTAssertPanic or RTAssertDebugBreak instead.
+ */
+#ifdef RT_STRICT
+# define AssertBreakpoint()     RTAssertDebugBreak()
+#else
+# define AssertBreakpoint()     do { } while (0)
+#endif
+
+/** @def RTAssertPanic()
+ * If RT_STRICT is defined this macro will invoke RTAssertDoPanic if
+ * RTAssertShouldPanic returns true. If RT_STRICT isn't defined it won't do any
+ * thing.
+ */
+#if defined(RT_STRICT) && !defined(RTASSERT_DONT_PANIC)
+# define RTAssertPanic()        do { if (RTAssertShouldPanic()) RTAssertDoPanic(); } while (0)
+#else
+# define RTAssertPanic()        do { } while (0)
+#endif
+
+/** @def Assert
+ * Assert that an expression is true. If false, hit breakpoint.
+ * @param   expr    Expression which should be true.
+ */
+#ifdef RT_STRICT
+# define Assert(expr)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+            RTAssertPanic(); \
+        } \
+    } while (0)
+#else
+# define Assert(expr)     do { } while (0)
+#endif
+
+
+/** @def AssertStmt
+ * Assert that an expression is true. If false, hit breakpoint and execute the
+ * statement.
+ * @param   expr    Expression which should be true.
+ * @param   stmt    Statement to execute on failure.
+ */
+#ifdef RT_STRICT
+# define AssertStmt(expr, stmt)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+            RTAssertPanic(); \
+            stmt; \
+        } \
+    } while (0)
+#else
+# define AssertStmt(expr, stmt)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            stmt; \
+        } \
+    } while (0)
+#endif
+
+
+/** @def AssertReturn
+ * Assert that an expression is true and returns if it isn't.
+ * In RT_STRICT mode it will hit a breakpoint before returning.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   rc      What is to be presented to return.
+ */
+#ifdef RT_STRICT
+# define AssertReturn(expr, rc) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+            RTAssertPanic(); \
+            return (rc); \
+        } \
+    } while (0)
+#else
+# define AssertReturn(expr, rc) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+            return (rc); \
+    } while (0)
+#endif
+
+/** @def AssertReturnStmt
+ * Assert that an expression is true, if it isn't execute the given statement
+ * and return rc.
+ *
+ * In RT_STRICT mode it will hit a breakpoint before executing the statement and
+ * returning.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   stmt    Statement to execute before returning on failure.
+ * @param   rc      What is to be presented to return.
+ */
+#ifdef RT_STRICT
+# define AssertReturnStmt(expr, stmt, rc) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertPanic(); \
+            stmt; \
+            return (rc); \
+        } \
+    } while (0)
+#else
+# define AssertReturnStmt(expr, stmt, rc) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            stmt; \
+            return (rc); \
+        } \
+    } while (0)
+#endif
+
+/** @def AssertReturnVoid
+ * Assert that an expression is true and returns if it isn't.
+ * In RT_STRICT mode it will hit a breakpoint before returning.
+ *
+ * @param   expr    Expression which should be true.
+ */
+#ifdef RT_STRICT
+# define AssertReturnVoid(expr) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+            RTAssertPanic(); \
+            return; \
+        } \
+    } while (0)
+#else
+# define AssertReturnVoid(expr) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+            return; \
+    } while (0)
+#endif
+
+/** @def AssertReturnVoidStmt
+ * Assert that an expression is true, if it isn't execute the given statement
+ * and return.
+ *
+ * In RT_STRICT mode it will hit a breakpoint before returning.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   stmt    Statement to execute before returning on failure.
+ */
+#ifdef RT_STRICT
+# define AssertReturnVoidStmt(expr, stmt) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertPanic(); \
+            stmt; \
+            return; \
+        } \
+    } while (0)
+#else
+# define AssertReturnVoidStmt(expr, stmt) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            stmt; \
+            return; \
+        } \
+    } while (0)
+#endif
+
+
+/** @def AssertBreak
+ * Assert that an expression is true and breaks if it isn't.
+ * In RT_STRICT mode it will hit a breakpoint before breaking.
+ *
+ * @param   expr    Expression which should be true.
+ */
+#ifdef RT_STRICT
+# define AssertBreak(expr) \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else if (1) \
+    { \
+        RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        break; \
+    } else do {} while (0)
+#else
+# define AssertBreak(expr) \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else \
+        break
+#endif
+
+/** @def AssertContinue
+ * Assert that an expression is true and continue if it isn't.
+ * In RT_STRICT mode it will hit a breakpoint before continuing.
+ *
+ * @param   expr    Expression which should be true.
+ */
+#ifdef RT_STRICT
+# define AssertContinue(expr) \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else if (1) \
+    { \
+        RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        continue; \
+    } else do {} while (0)
+#else
+# define AssertContinue(expr) \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else \
+        continue
+#endif
+
+/** @def AssertBreakStmt
+ * Assert that an expression is true and breaks if it isn't.
+ * In RT_STRICT mode it will hit a breakpoint before doing break.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ */
+#ifdef RT_STRICT
+# define AssertBreakStmt(expr, stmt) \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else if (1) \
+    { \
+        RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        stmt; \
+        break; \
+    } else do {} while (0)
+#else
+# define AssertBreakStmt(expr, stmt) \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else if (1) \
+    { \
+        stmt; \
+        break; \
+    } else do {} while (0)
+#endif
+
+
+/** @def AssertMsg
+ * Assert that an expression is true. If it's not print message and hit breakpoint.
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ */
+#ifdef RT_STRICT
+# define AssertMsg(expr, a)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+            RTAssertMsg2Weak a; \
+            RTAssertPanic(); \
+        } \
+    } while (0)
+#else
+# define AssertMsg(expr, a)  do { } while (0)
+#endif
+
+/** @def AssertMsgStmt
+ * Assert that an expression is true.  If it's not print message and hit
+ * breakpoint and execute the statement.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute in case of a failed assertion.
+ *
+ * @remarks The expression and statement will be evaluated in all build types.
+ */
+#ifdef RT_STRICT
+# define AssertMsgStmt(expr, a, stmt)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertMsg2Weak a; \
+            RTAssertPanic(); \
+            stmt; \
+        } \
+    } while (0)
+#else
+# define AssertMsgStmt(expr, a, stmt)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            stmt; \
+        } \
+    } while (0)
+#endif
+
+/** @def AssertMsgReturn
+ * Assert that an expression is true and returns if it isn't.
+ * In RT_STRICT mode it will hit a breakpoint before returning.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ * @param   rc      What is to be presented to return.
+ */
+#ifdef RT_STRICT
+# define AssertMsgReturn(expr, a, rc)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+            RTAssertMsg2Weak a; \
+            RTAssertPanic(); \
+            return (rc); \
+        } \
+    } while (0)
+#else
+# define AssertMsgReturn(expr, a, rc) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+            return (rc); \
+    } while (0)
+#endif
+
+/** @def AssertMsgReturnStmt
+ * Assert that an expression is true, if it isn't execute the statement and
+ * return.
+ *
+ * In RT_STRICT mode it will hit a breakpoint before returning.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before returning in case of a failed
+ *                  assertion.
+ * @param   rc      What is to be presented to return.
+ */
+#ifdef RT_STRICT
+# define AssertMsgReturnStmt(expr, a, stmt, rc)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertMsg2Weak a; \
+            RTAssertPanic(); \
+            stmt; \
+            return (rc); \
+        } \
+    } while (0)
+#else
+# define AssertMsgReturnStmt(expr, a, stmt, rc) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            stmt; \
+            return (rc); \
+        } \
+    } while (0)
+#endif
+
+/** @def AssertMsgReturnVoid
+ * Assert that an expression is true and returns if it isn't.
+ * In RT_STRICT mode it will hit a breakpoint before returning.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ */
+#ifdef RT_STRICT
+# define AssertMsgReturnVoid(expr, a)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+            RTAssertMsg2Weak a; \
+            RTAssertPanic(); \
+            return; \
+        } \
+    } while (0)
+#else
+# define AssertMsgReturnVoid(expr, a) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+            return; \
+    } while (0)
+#endif
+
+/** @def AssertMsgReturnVoidStmt
+ * Assert that an expression is true, if it isn't execute the statement and
+ * return.
+ *
+ * In RT_STRICT mode it will hit a breakpoint before returning.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before return in case of a failed assertion.
+ */
+#ifdef RT_STRICT
+# define AssertMsgReturnVoidStmt(expr, a, stmt)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertMsg2Weak a; \
+            RTAssertPanic(); \
+            stmt; \
+            return; \
+        } \
+    } while (0)
+#else
+# define AssertMsgReturnVoidStmt(expr, a, stmt) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            stmt; \
+            return; \
+        } \
+    } while (0)
+#endif
+
+
+/** @def AssertMsgBreak
+ * Assert that an expression is true and breaks if it isn't.
+ * In RT_STRICT mode it will hit a breakpoint before returning.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ */
+#ifdef RT_STRICT
+# define AssertMsgBreak(expr, a) \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else if (1) \
+    { \
+        RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertMsg2Weak a; \
+        RTAssertPanic(); \
+        break; \
+    } else do {} while (0)
+#else
+# define AssertMsgBreak(expr, a) \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else \
+        break
+#endif
+
+/** @def AssertMsgBreakStmt
+ * Assert that an expression is true and breaks if it isn't.
+ * In RT_STRICT mode it will hit a breakpoint before doing break.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ */
+#ifdef RT_STRICT
+# define AssertMsgBreakStmt(expr, a, stmt) \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else if (1) \
+    { \
+        RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertMsg2Weak a; \
+        RTAssertPanic(); \
+        stmt; \
+        break; \
+    } else do {} while (0)
+#else
+# define AssertMsgBreakStmt(expr, a, stmt) \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else if (1) \
+    { \
+        stmt; \
+        break; \
+    } else do {} while (0)
+#endif
+
+/** @def AssertFailed
+ * An assertion failed, hit breakpoint.
+ */
+#ifdef RT_STRICT
+# define AssertFailed()  \
+    do { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+    } while (0)
+#else
+# define AssertFailed()         do { } while (0)
+#endif
+
+/** @def AssertFailedStmt
+ * An assertion failed, hit breakpoint and execute statement.
+ */
+#ifdef RT_STRICT
+# define AssertFailedStmt(stmt) \
+    do { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        stmt; \
+    } while (0)
+#else
+# define AssertFailedStmt(stmt)     do { stmt; } while (0)
+#endif
+
+/** @def AssertFailedReturn
+ * An assertion failed, hit breakpoint (RT_STRICT mode only) and return.
+ *
+ * @param   rc      The rc to return.
+ */
+#ifdef RT_STRICT
+# define AssertFailedReturn(rc)  \
+    do { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        return (rc); \
+    } while (0)
+#else
+# define AssertFailedReturn(rc)  \
+    do { \
+        return (rc); \
+    } while (0)
+#endif
+
+/** @def AssertFailedReturnStmt
+ * An assertion failed, hit breakpoint (RT_STRICT mode only), execute a
+ * statement and return a value.
+ *
+ * @param   stmt    The statement to execute before returning.
+ * @param   rc      The value to return.
+ */
+#ifdef RT_STRICT
+# define AssertFailedReturnStmt(stmt, rc)  \
+    do { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        stmt; \
+        return (rc); \
+    } while (0)
+#else
+# define AssertFailedReturnStmt(stmt, rc)  \
+    do { \
+        stmt; \
+        return (rc); \
+    } while (0)
+#endif
+
+/** @def AssertFailedReturnVoid
+ * An assertion failed, hit breakpoint (RT_STRICT mode only) and return.
+ */
+#ifdef RT_STRICT
+# define AssertFailedReturnVoid()  \
+    do { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        return; \
+    } while (0)
+#else
+# define AssertFailedReturnVoid()  \
+    do { \
+        return; \
+    } while (0)
+#endif
+
+/** @def AssertFailedReturnVoidStmt
+ * An assertion failed, hit breakpoint (RT_STRICT mode only), execute a
+ * statement and return.
+ *
+ * @param stmt The statement to execute before returning.
+ */
+#ifdef RT_STRICT
+# define AssertFailedReturnVoidStmt(stmt)  \
+    do { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        stmt; \
+        return; \
+    } while (0)
+#else
+# define AssertFailedReturnVoidStmt(stmt)  \
+    do { \
+        stmt; \
+        return; \
+    } while (0)
+#endif
+
+
+/** @def AssertFailedBreak
+ * An assertion failed, hit breakpoint (RT_STRICT mode only) and break.
+ */
+#ifdef RT_STRICT
+# define AssertFailedBreak()  \
+    if (1) { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        break; \
+    } else do {} while (0)
+#else
+# define AssertFailedBreak()  \
+    if (1) \
+        break; \
+    else do {} while (0)
+#endif
+
+/** @def AssertFailedBreakStmt
+ * An assertion failed, hit breakpoint (RT_STRICT mode only), execute
+ * the given statement and break.
+ *
+ * @param   stmt    Statement to execute before break.
+ */
+#ifdef RT_STRICT
+# define AssertFailedBreakStmt(stmt) \
+    if (1) { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        stmt; \
+        break; \
+    } else do {} while (0)
+#else
+# define AssertFailedBreakStmt(stmt) \
+    if (1) { \
+        stmt; \
+        break; \
+    } else do {} while (0)
+#endif
+
+
+/** @def AssertMsgFailed
+ * An assertion failed print a message and a hit breakpoint.
+ *
+ * @param   a   printf argument list (in parenthesis).
+ */
+#ifdef RT_STRICT
+# define AssertMsgFailed(a)  \
+    do { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+        RTAssertMsg2Weak a; \
+        RTAssertPanic(); \
+    } while (0)
+#else
+# define AssertMsgFailed(a)     do { } while (0)
+#endif
+
+/** @def AssertMsgFailedReturn
+ * An assertion failed, hit breakpoint with message (RT_STRICT mode only) and return.
+ *
+ * @param   a       printf argument list (in parenthesis).
+ * @param   rc      What is to be presented to return.
+ */
+#ifdef RT_STRICT
+# define AssertMsgFailedReturn(a, rc)  \
+    do { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertMsg2Weak a; \
+        RTAssertPanic(); \
+        return (rc); \
+    } while (0)
+#else
+# define AssertMsgFailedReturn(a, rc)  \
+    do { \
+        return (rc); \
+    } while (0)
+#endif
+
+/** @def AssertMsgFailedReturnVoid
+ * An assertion failed, hit breakpoint with message (RT_STRICT mode only) and return.
+ *
+ * @param   a       printf argument list (in parenthesis).
+ */
+#ifdef RT_STRICT
+# define AssertMsgFailedReturnVoid(a)  \
+    do { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertMsg2Weak a; \
+        RTAssertPanic(); \
+        return; \
+    } while (0)
+#else
+# define AssertMsgFailedReturnVoid(a)  \
+    do { \
+        return; \
+    } while (0)
+#endif
+
+
+/** @def AssertMsgFailedBreak
+ * An assertion failed, hit breakpoint with message (RT_STRICT mode only) and break.
+ *
+ * @param   a       printf argument list (in parenthesis).
+ */
+#ifdef RT_STRICT
+# define AssertMsgFailedBreak(a)  \
+    if (1) { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertMsg2Weak a; \
+        RTAssertPanic(); \
+        break; \
+    } else do {} while (0)
+#else
+# define AssertMsgFailedBreak(a)  \
+    if (1) \
+        break; \
+    else do {} while (0)
+#endif
+
+/** @def AssertMsgFailedBreakStmt
+ * An assertion failed, hit breakpoint (RT_STRICT mode only), execute
+ * the given statement and break.
+ *
+ * @param   a       printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before break.
+ */
+#ifdef RT_STRICT
+# define AssertMsgFailedBreakStmt(a, stmt) \
+    if (1) { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertMsg2Weak a; \
+        RTAssertPanic(); \
+        stmt; \
+        break; \
+    } else do {} while (0)
+#else
+# define AssertMsgFailedBreakStmt(a, stmt) \
+    if (1) { \
+        stmt; \
+        break; \
+    } else do {} while (0)
+#endif
+
+/** @} */
+
+
+
+/** @name Release Log Assertions
+ *
+ * These assertions will work like normal strict assertion when RT_STRICT is
+ * defined and LogRel statements when RT_STRICT is undefined. Typically used for
+ * things which shouldn't go wrong, but when it does you'd like to know one way
+ * or the other.
+ *
+ * @{
+ */
+
+/** @def RTAssertLogRelMsg1
+ * RTAssertMsg1Weak (strict builds) / LogRel wrapper (non-strict).
+ */
+#ifdef RT_STRICT
+# define RTAssertLogRelMsg1(pszExpr, iLine, pszFile, pszFunction) \
+    RTAssertMsg1Weak(pszExpr, iLine, pszFile, pszFunction)
+#else
+# define RTAssertLogRelMsg1(pszExpr, iLine, pszFile, pszFunction) \
+    LogRel(("AssertLogRel %s(%d) %s: %s\n",\
+            (pszFile), (iLine), (pszFunction), (pszExpr) ))
+#endif
+
+/** @def RTAssertLogRelMsg2
+ * RTAssertMsg2Weak (strict builds) / LogRel wrapper (non-strict).
+ */
+#ifdef RT_STRICT
+# define RTAssertLogRelMsg2(a)  RTAssertMsg2Weak a
+#else
+# define RTAssertLogRelMsg2(a)  LogRel(a)
+#endif
+
+/** @def AssertLogRel
+ * Assert that an expression is true.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   expr    Expression which should be true.
+ */
+#define AssertLogRel(expr) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertPanic(); \
+        } \
+    } while (0)
+
+/** @def AssertLogRelReturn
+ * Assert that an expression is true, return \a rc if it isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   rc      What is to be presented to return.
+ */
+#define AssertLogRelReturn(expr, rc) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertPanic(); \
+            return (rc); \
+        } \
+    } while (0)
+
+/** @def AssertLogRelReturnVoid
+ * Assert that an expression is true, return void if it isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   expr    Expression which should be true.
+ */
+#define AssertLogRelReturnVoid(expr) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertPanic(); \
+            return; \
+        } \
+    } while (0)
+
+/** @def AssertLogRelBreak
+ * Assert that an expression is true, break if it isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   expr    Expression which should be true.
+ */
+#define AssertLogRelBreak(expr) \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else if (1) \
+    { \
+        RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        break; \
+    } \
+    else do {} while (0)
+
+/** @def AssertLogRelBreakStmt
+ * Assert that an expression is true, execute \a stmt and break if it isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ */
+#define AssertLogRelBreakStmt(expr, stmt) \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else if (1) \
+    { \
+        RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        stmt; \
+        break; \
+    } else do {} while (0)
+
+/** @def AssertLogRelMsg
+ * Assert that an expression is true.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ */
+#define AssertLogRelMsg(expr, a) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else\
+        { \
+            RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertLogRelMsg2(a); \
+            RTAssertPanic(); \
+        } \
+    } while (0)
+
+/** @def AssertLogRelMsgStmt
+ * Assert that an expression is true, execute \a stmt and break if it isn't
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute in case of a failed assertion.
+ */
+#define AssertLogRelMsgStmt(expr, a, stmt) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else\
+        { \
+            RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertLogRelMsg2(a); \
+            RTAssertPanic(); \
+            stmt; \
+        } \
+    } while (0)
+
+/** @def AssertLogRelMsgReturn
+ * Assert that an expression is true, return \a rc if it isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ * @param   rc      What is to be presented to return.
+ */
+#define AssertLogRelMsgReturn(expr, a, rc) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else\
+        { \
+            RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertLogRelMsg2(a); \
+            RTAssertPanic(); \
+            return (rc); \
+        } \
+    } while (0)
+
+/** @def AssertLogRelMsgReturnStmt
+ * Assert that an expression is true, execute @a stmt and return @a rcRet if it
+ * isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before returning in case of a failed
+ *                  assertion.
+ * @param   rcRet   What is to be presented to return.
+ */
+#define AssertLogRelMsgReturnStmt(expr, a, stmt, rcRet) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else\
+        { \
+            RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertLogRelMsg2(a); \
+            RTAssertPanic(); \
+            stmt; \
+            return (rcRet); \
+        } \
+    } while (0)
+
+/** @def AssertLogRelMsgReturnVoid
+ * Assert that an expression is true, return (void) if it isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ */
+#define AssertLogRelMsgReturnVoid(expr, a) \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else\
+        { \
+            RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertLogRelMsg2(a); \
+            RTAssertPanic(); \
+            return; \
+        } \
+    } while (0)
+
+/** @def AssertLogRelMsgBreak
+ * Assert that an expression is true, break if it isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ */
+#define AssertLogRelMsgBreak(expr, a) \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else if (1) \
+    { \
+        RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertLogRelMsg2(a); \
+        RTAssertPanic(); \
+        break; \
+    } \
+    else do {} while (0)
+
+/** @def AssertLogRelMsgBreakStmt
+ * Assert that an expression is true, execute \a stmt and break if it isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ */
+#define AssertLogRelMsgBreakStmt(expr, a, stmt) \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else if (1) \
+    { \
+        RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertLogRelMsg2(a); \
+        RTAssertPanic(); \
+        stmt; \
+        break; \
+    } else do {} while (0)
+
+/** @def AssertLogRelFailed
+ * An assertion failed.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ */
+#define AssertLogRelFailed() \
+    do { \
+        RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+    } while (0)
+
+/** @def AssertLogRelFailedReturn
+ * An assertion failed.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   rc      What is to be presented to return.
+ */
+#define AssertLogRelFailedReturn(rc) \
+    do { \
+        RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        return (rc); \
+    } while (0)
+
+/** @def AssertLogRelFailedReturnVoid
+ * An assertion failed, hit a breakpoint and return.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ */
+#define AssertLogRelFailedReturnVoid() \
+    do { \
+        RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        return; \
+    } while (0)
+
+/** @def AssertLogRelFailedBreak
+ * An assertion failed, break.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ */
+#define AssertLogRelFailedBreak() \
+    if (1) \
+    { \
+        RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        break; \
+    } else do {} while (0)
+
+/** @def AssertLogRelFailedBreakStmt
+ * An assertion failed, execute \a stmt and break.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   stmt    Statement to execute before break.
+ */
+#define AssertLogRelFailedBreakStmt(stmt) \
+    if (1) \
+    { \
+        RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertPanic(); \
+        stmt; \
+        break; \
+    } else do {} while (0)
+
+/** @def AssertLogRelMsgFailed
+ * An assertion failed.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   a   printf argument list (in parenthesis).
+ */
+#define AssertLogRelMsgFailed(a) \
+    do { \
+        RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertLogRelMsg2(a); \
+        RTAssertPanic(); \
+    } while (0)
+
+/** @def AssertLogRelMsgFailedStmt
+ * An assertion failed, execute @a stmt.
+ *
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel. The
+ * statement will be executed in regardless of build type.
+ *
+ * @param   a       printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute after raising/logging the assertion.
+ */
+#define AssertLogRelMsgFailedStmt(a, stmt) \
+    do { \
+        RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertLogRelMsg2(a); \
+        RTAssertPanic(); \
+        stmt; \
+    } while (0)
+
+/** @def AssertLogRelMsgFailedReturn
+ * An assertion failed, return \a rc.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   a   printf argument list (in parenthesis).
+ * @param   rc  What is to be presented to return.
+ */
+#define AssertLogRelMsgFailedReturn(a, rc) \
+    do { \
+        RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertLogRelMsg2(a); \
+        RTAssertPanic(); \
+        return (rc); \
+    } while (0)
+
+/** @def AssertLogRelMsgFailedReturnStmt
+ * An assertion failed, execute @a stmt and return @a rc.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   a       printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before returning in case of a failed
+ *                  assertion.
+ * @param   rc      What is to be presented to return.
+ */
+#define AssertLogRelMsgFailedReturnStmt(a, stmt, rc) \
+    do { \
+        RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertLogRelMsg2(a); \
+        RTAssertPanic(); \
+        stmt; \
+        return (rc); \
+    } while (0)
+
+/** @def AssertLogRelMsgFailedReturnVoid
+ * An assertion failed, return void.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   a   printf argument list (in parenthesis).
+ */
+#define AssertLogRelMsgFailedReturnVoid(a) \
+    do { \
+        RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertLogRelMsg2(a); \
+        RTAssertPanic(); \
+        return; \
+    } while (0)
+
+/** @def AssertLogRelMsgFailedReturnVoidStmt
+ * An assertion failed, execute @a stmt and return void.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   a       printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before returning in case of a failed
+ *                  assertion.
+ */
+#define AssertLogRelMsgFailedReturnVoidStmt(a, stmt) \
+    do { \
+        RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertLogRelMsg2(a); \
+        RTAssertPanic(); \
+        stmt; \
+        return; \
+    } while (0)
+
+/** @def AssertLogRelMsgFailedBreak
+ * An assertion failed, break.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   a   printf argument list (in parenthesis).
+ */
+#define AssertLogRelMsgFailedBreak(a) \
+    if (1)\
+    { \
+        RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertLogRelMsg2(a); \
+        RTAssertPanic(); \
+        break; \
+    } else do {} while (0)
+
+/** @def AssertLogRelMsgFailedBreakStmt
+ * An assertion failed, execute \a stmt and break.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param   a   printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before break.
+ */
+#define AssertLogRelMsgFailedBreakStmt(a, stmt) \
+    if (1) \
+    { \
+        RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertLogRelMsg2(a); \
+        RTAssertPanic(); \
+        stmt; \
+        break; \
+    } else do {} while (0)
+
+/** @} */
+
+
+
+/** @name Release Assertions
+ *
+ * These assertions are always enabled.
+ * @{
+ */
+
+/** @def RTAssertReleasePanic()
+ * Invokes RTAssertShouldPanic and RTAssertDoPanic.
+ *
+ * It might seem odd that RTAssertShouldPanic is necessary when its result isn't
+ * checked, but it's done since RTAssertShouldPanic is overrideable and might be
+ * used to bail out before taking down the system (the VMMR0 case).
+ */
+#define RTAssertReleasePanic()   do { RTAssertShouldPanic(); RTAssertDoPanic(); } while (0)
+
+
+/** @def AssertRelease
+ * Assert that an expression is true. If it's not hit a breakpoint.
+ *
+ * @param   expr    Expression which should be true.
+ */
+#define AssertRelease(expr)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+            RTAssertReleasePanic(); \
+        } \
+    } while (0)
+
+/** @def AssertReleaseReturn
+ * Assert that an expression is true, hit a breakpoint and return if it isn't.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   rc      What is to be presented to return.
+ */
+#define AssertReleaseReturn(expr, rc)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertReleasePanic(); \
+            return (rc); \
+        } \
+    } while (0)
+
+/** @def AssertReleaseReturnVoid
+ * Assert that an expression is true, hit a breakpoint and return if it isn't.
+ *
+ * @param   expr    Expression which should be true.
+ */
+#define AssertReleaseReturnVoid(expr)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertReleasePanic(); \
+            return; \
+        } \
+    } while (0)
+
+
+/** @def AssertReleaseBreak
+ * Assert that an expression is true, hit a breakpoint and break if it isn't.
+ *
+ * @param   expr    Expression which should be true.
+ */
+#define AssertReleaseBreak(expr)  \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else if (1) \
+    { \
+        RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertReleasePanic(); \
+        break; \
+    } else do {} while (0)
+
+/** @def AssertReleaseBreakStmt
+ * Assert that an expression is true, hit a breakpoint and break if it isn't.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ */
+#define AssertReleaseBreakStmt(expr, stmt)  \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else if (1) \
+    { \
+        RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertReleasePanic(); \
+        stmt; \
+        break; \
+    } else do {} while (0)
+
+
+/** @def AssertReleaseMsg
+ * Assert that an expression is true, print the message and hit a breakpoint if it isn't.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ */
+#define AssertReleaseMsg(expr, a)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertMsg2Weak a; \
+            RTAssertReleasePanic(); \
+        } \
+    } while (0)
+
+/** @def AssertReleaseMsgReturn
+ * Assert that an expression is true, print the message and hit a breakpoint and return if it isn't.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ * @param   rc      What is to be presented to return.
+ */
+#define AssertReleaseMsgReturn(expr, a, rc)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertMsg2Weak a; \
+            RTAssertReleasePanic(); \
+            return (rc); \
+        } \
+    } while (0)
+
+/** @def AssertReleaseMsgReturnVoid
+ * Assert that an expression is true, print the message and hit a breakpoint and return if it isn't.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ */
+#define AssertReleaseMsgReturnVoid(expr, a)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+        { \
+            RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+            RTAssertMsg2Weak a; \
+            RTAssertReleasePanic(); \
+            return; \
+        } \
+    } while (0)
+
+
+/** @def AssertReleaseMsgBreak
+ * Assert that an expression is true, print the message and hit a breakpoint and break if it isn't.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ */
+#define AssertReleaseMsgBreak(expr, a)  \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else if (1) \
+    { \
+        RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertMsg2Weak a; \
+        RTAssertReleasePanic(); \
+        break; \
+    } else do {} while (0)
+
+/** @def AssertReleaseMsgBreakStmt
+ * Assert that an expression is true, print the message and hit a breakpoint and break if it isn't.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ */
+#define AssertReleaseMsgBreakStmt(expr, a, stmt)  \
+    if (RT_LIKELY(!!(expr))) \
+    { /* likely */ } \
+    else if (1) \
+    { \
+        RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertMsg2Weak a; \
+        RTAssertReleasePanic(); \
+        stmt; \
+        break; \
+    } else do {} while (0)
+
+
+/** @def AssertReleaseFailed
+ * An assertion failed, hit a breakpoint.
+ */
+#define AssertReleaseFailed()  \
+    do { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertReleasePanic(); \
+    } while (0)
+
+/** @def AssertReleaseFailedReturn
+ * An assertion failed, hit a breakpoint and return.
+ *
+ * @param   rc      What is to be presented to return.
+ */
+#define AssertReleaseFailedReturn(rc)  \
+    do { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertReleasePanic(); \
+        return (rc); \
+    } while (0)
+
+/** @def AssertReleaseFailedReturnVoid
+ * An assertion failed, hit a breakpoint and return.
+ */
+#define AssertReleaseFailedReturnVoid()  \
+    do { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertReleasePanic(); \
+        return; \
+    } while (0)
+
+
+/** @def AssertReleaseFailedBreak
+ * An assertion failed, hit a breakpoint and break.
+ */
+#define AssertReleaseFailedBreak()  \
+    if (1) { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertReleasePanic(); \
+        break; \
+    } else do {} while (0)
+
+/** @def AssertReleaseFailedBreakStmt
+ * An assertion failed, hit a breakpoint and break.
+ *
+ * @param   stmt    Statement to execute before break.
+ */
+#define AssertReleaseFailedBreakStmt(stmt)  \
+    if (1) { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertReleasePanic(); \
+        stmt; \
+        break; \
+    } else do {} while (0)
+
+
+/** @def AssertReleaseMsgFailed
+ * An assertion failed, print a message and hit a breakpoint.
+ *
+ * @param   a   printf argument list (in parenthesis).
+ */
+#define AssertReleaseMsgFailed(a)  \
+    do { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+        RTAssertMsg2Weak a; \
+        RTAssertReleasePanic(); \
+    } while (0)
+
+/** @def AssertReleaseMsgFailedReturn
+ * An assertion failed, print a message, hit a breakpoint and return.
+ *
+ * @param   a   printf argument list (in parenthesis).
+ * @param   rc      What is to be presented to return.
+ */
+#define AssertReleaseMsgFailedReturn(a, rc) \
+    do { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertMsg2Weak a; \
+        RTAssertReleasePanic(); \
+        return (rc); \
+    } while (0)
+
+/** @def AssertReleaseMsgFailedReturnVoid
+ * An assertion failed, print a message, hit a breakpoint and return.
+ *
+ * @param   a   printf argument list (in parenthesis).
+ */
+#define AssertReleaseMsgFailedReturnVoid(a) \
+    do { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertMsg2Weak a; \
+        RTAssertReleasePanic(); \
+        return; \
+    } while (0)
+
+
+/** @def AssertReleaseMsgFailedBreak
+ * An assertion failed, print a message, hit a breakpoint and break.
+ *
+ * @param   a   printf argument list (in parenthesis).
+ */
+#define AssertReleaseMsgFailedBreak(a) \
+    if (1) { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertMsg2Weak a; \
+        RTAssertReleasePanic(); \
+        break; \
+    } else do {} while (0)
+
+/** @def AssertReleaseMsgFailedBreakStmt
+ * An assertion failed, print a message, hit a breakpoint and break.
+ *
+ * @param   a   printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before break.
+ */
+#define AssertReleaseMsgFailedBreakStmt(a, stmt) \
+    if (1) { \
+        RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+        RTAssertMsg2Weak a; \
+        RTAssertReleasePanic(); \
+        stmt; \
+        break; \
+    } else do {} while (0)
+
+/** @} */
+
+
+
+/** @name Fatal Assertions
+ * These are similar to release assertions except that you cannot ignore them in
+ * any way, they will loop for ever if RTAssertDoPanic returns.
+ *
+ * @{
+ */
+
+/** @def AssertFatal
+ * Assert that an expression is true. If it's not hit a breakpoint (for ever).
+ *
+ * @param   expr    Expression which should be true.
+ */
+#define AssertFatal(expr)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+            for (;;) \
+            { \
+                RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+                RTAssertReleasePanic(); \
+            } \
+    } while (0)
+
+/** @def AssertFatalMsg
+ * Assert that an expression is true, print the message and hit a breakpoint (for ever) if it isn't.
+ *
+ * @param   expr    Expression which should be true.
+ * @param   a       printf argument list (in parenthesis).
+ */
+#define AssertFatalMsg(expr, a)  \
+    do { \
+        if (RT_LIKELY(!!(expr))) \
+        { /* likely */ } \
+        else \
+            for (;;) \
+            { \
+                RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+                RTAssertMsg2Weak a; \
+                RTAssertReleasePanic(); \
+            } \
+    } while (0)
+
+/** @def AssertFatalFailed
+ * An assertion failed, hit a breakpoint (for ever).
+ */
+#define AssertFatalFailed()  \
+    do { \
+        for (;;) \
+        { \
+            RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+            RTAssertReleasePanic(); \
+        } \
+    } while (0)
+
+/** @def AssertFatalMsgFailed
+ * An assertion failed, print a message and hit a breakpoint (for ever).
+ *
+ * @param   a   printf argument list (in parenthesis).
+ */
+#define AssertFatalMsgFailed(a)  \
+    do { \
+        for (;;) \
+        { \
+            RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+            RTAssertMsg2Weak a; \
+            RTAssertReleasePanic(); \
+        } \
+    } while (0)
+
+/** @} */
+
+
+
+/** @name Convenience Assertions Macros
+ * @{
+ */
+
+/** @def AssertRC
+ * Asserts a iprt status code successful.
+ *
+ * On failure it will print info about the rc and hit a breakpoint.
+ *
+ * @param   rc  iprt status code.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertRC(rc)                AssertMsgRC(rc, ("%Rra\n", (rc)))
+
+/** @def AssertRCStmt
+ * Asserts a iprt status code successful, bitch (RT_STRICT mode only) and execute
+ * @a stmt if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   stmt    Statement to execute before returning in case of a failed
+ *                  assertion.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertRCStmt(rc, stmt)   AssertMsgRCStmt(rc, ("%Rra\n", (rc)), stmt)
+
+/** @def AssertRCReturn
+ * Asserts a iprt status code successful, bitch (RT_STRICT mode only) and return if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   rcRet   What is to be presented to return.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertRCReturn(rc, rcRet)   AssertMsgRCReturn(rc, ("%Rra\n", (rc)), rcRet)
+
+/** @def AssertRCReturnStmt
+ * Asserts a iprt status code successful, bitch (RT_STRICT mode only), execute
+ * @a stmt and returns @a rcRet if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   stmt    Statement to execute before returning in case of a failed
+ *                  assertion.
+ * @param   rcRet   What is to be presented to return.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertRCReturnStmt(rc, stmt, rcRet) AssertMsgRCReturnStmt(rc, ("%Rra\n", (rc)), stmt, rcRet)
+
+/** @def AssertRCReturnVoid
+ * Asserts a iprt status code successful, bitch (RT_STRICT mode only) and return if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertRCReturnVoid(rc)      AssertMsgRCReturnVoid(rc, ("%Rra\n", (rc)))
+
+/** @def AssertRCReturnVoidStmt
+ * Asserts a iprt status code successful, bitch (RT_STRICT mode only), and
+ * execute the given statement/return if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   stmt    Statement to execute before returning on failure.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertRCReturnVoidStmt(rc, stmt) AssertMsgRCReturnVoidStmt(rc, ("%Rra\n", (rc)), stmt)
+
+/** @def AssertRCBreak
+ * Asserts a iprt status code successful, bitch (RT_STRICT mode only) and break if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertRCBreak(rc)           AssertMsgRCBreak(rc, ("%Rra\n", (rc)))
+
+/** @def AssertRCBreakStmt
+ * Asserts a iprt status code successful, bitch (RT_STRICT mode only) and break if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertRCBreakStmt(rc, stmt) AssertMsgRCBreakStmt(rc, ("%Rra\n", (rc)), stmt)
+
+/** @def AssertMsgRC
+ * Asserts a iprt status code successful.
+ *
+ * It prints a custom message and hits a breakpoint on FAILURE.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertMsgRC(rc, msg) \
+    do { AssertMsg(RT_SUCCESS_NP(rc), msg); NOREF(rc); } while (0)
+
+/** @def AssertMsgRCStmt
+ * Asserts a iprt status code successful, bitch (RT_STRICT mode only) and
+ * execute @a stmt if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before returning in case of a failed
+ *                  assertion.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertMsgRCStmt(rc, msg, stmt) \
+    do { AssertMsgStmt(RT_SUCCESS_NP(rc), msg, stmt); NOREF(rc); } while (0)
+
+/** @def AssertMsgRCReturn
+ * Asserts a iprt status code successful, bitch (RT_STRICT mode only) and return
+ * @a rcRet if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @param   rcRet   What is to be presented to return.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertMsgRCReturn(rc, msg, rcRet) \
+    do { AssertMsgReturn(RT_SUCCESS_NP(rc), msg, rcRet); NOREF(rc); } while (0)
+
+/** @def AssertMsgRCReturnStmt
+ * Asserts a iprt status code successful, bitch (RT_STRICT mode only), execute
+ * @a stmt and return @a rcRet if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before returning in case of a failed
+ *                  assertion.
+ * @param   rcRet   What is to be presented to return.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertMsgRCReturnStmt(rc, msg, stmt, rcRet) \
+    do { AssertMsgReturnStmt(RT_SUCCESS_NP(rc), msg, stmt, rcRet); NOREF(rc); } while (0)
+
+/** @def AssertMsgRCReturnVoid
+ * Asserts a iprt status code successful, bitch (RT_STRICT mode only) and return
+ * void if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertMsgRCReturnVoid(rc, msg) \
+    do { AssertMsgReturnVoid(RT_SUCCESS_NP(rc), msg); NOREF(rc); } while (0)
+
+/** @def AssertMsgRCReturnVoidStmt
+ * Asserts a iprt status code successful, bitch (RT_STRICT mode only), execute
+ * @a stmt and return void if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertMsgRCReturnVoidStmt(rc, msg, stmt) \
+    do { AssertMsgReturnVoidStmt(RT_SUCCESS_NP(rc), msg, stmt); NOREF(rc); } while (0)
+
+/** @def AssertMsgRCBreak
+ * Asserts a iprt status code successful, bitch (RT_STRICT mode only) and break
+ * if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertMsgRCBreak(rc, msg) \
+    if (1) { AssertMsgBreak(RT_SUCCESS(rc), msg); NOREF(rc); } else do {} while (0)
+
+/** @def AssertMsgRCBreakStmt
+ * Asserts a iprt status code successful, bitch (RT_STRICT mode only), execute
+ * @a stmt and break if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertMsgRCBreakStmt(rc, msg, stmt) \
+    if (1) { AssertMsgBreakStmt(RT_SUCCESS_NP(rc), msg, stmt); NOREF(rc); } else do {} while (0)
+
+/** @def AssertRCSuccess
+ * Asserts an iprt status code equals VINF_SUCCESS.
+ *
+ * On failure it will print info about the rc and hit a breakpoint.
+ *
+ * @param   rc  iprt status code.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertRCSuccess(rc)                 do { AssertMsg((rc) == VINF_SUCCESS, ("%Rra\n", (rc))); NOREF(rc); } while (0)
+
+/** @def AssertRCSuccessReturn
+ * Asserts that an iprt status code equals VINF_SUCCESS, bitch (RT_STRICT mode only) and return if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   rcRet   What is to be presented to return.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertRCSuccessReturn(rc, rcRet)    AssertMsgReturn((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), rcRet)
+
+/** @def AssertRCSuccessReturnVoid
+ * Asserts that an iprt status code equals VINF_SUCCESS, bitch (RT_STRICT mode only) and return if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertRCSuccessReturnVoid(rc)       AssertMsgReturnVoid((rc) == VINF_SUCCESS, ("%Rra\n", (rc)))
+
+/** @def AssertRCSuccessBreak
+ * Asserts that an iprt status code equals VINF_SUCCESS, bitch (RT_STRICT mode only) and break if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertRCSuccessBreak(rc)            AssertMsgBreak((rc) == VINF_SUCCESS, ("%Rra\n", (rc)))
+
+/** @def AssertRCSuccessBreakStmt
+ * Asserts that an iprt status code equals VINF_SUCCESS, bitch (RT_STRICT mode only) and break if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ * @remark  rc is referenced multiple times. In release mode is NOREF()'ed.
+ */
+#define AssertRCSuccessBreakStmt(rc, stmt)  AssertMsgBreakStmt((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), stmt)
+
+
+/** @def AssertLogRelRC
+ * Asserts a iprt status code successful.
+ *
+ * @param   rc  iprt status code.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelRC(rc)                      AssertLogRelMsgRC(rc, ("%Rra\n", (rc)))
+
+/** @def AssertLogRelRCReturn
+ * Asserts a iprt status code successful, returning \a rc if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   rcRet   What is to be presented to return.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelRCReturn(rc, rcRet)         AssertLogRelMsgRCReturn(rc, ("%Rra\n", (rc)), rcRet)
+
+/** @def AssertLogRelRCReturnStmt
+ * Asserts a iprt status code successful, executing \a stmt and returning \a rc
+ * if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   stmt    Statement to execute before returning in case of a failed
+ *                  assertion.
+ * @param   rcRet   What is to be presented to return.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelRCReturnStmt(rc, stmt, rcRet) AssertLogRelMsgRCReturnStmt(rc, ("%Rra\n", (rc)), stmt, rcRet)
+
+/** @def AssertLogRelRCReturnVoid
+ * Asserts a iprt status code successful, returning (void) if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelRCReturnVoid(rc)            AssertLogRelMsgRCReturnVoid(rc, ("%Rra\n", (rc)))
+
+/** @def AssertLogRelRCBreak
+ * Asserts a iprt status code successful, breaking if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelRCBreak(rc)                 AssertLogRelMsgRCBreak(rc, ("%Rra\n", (rc)))
+
+/** @def AssertLogRelRCBreakStmt
+ * Asserts a iprt status code successful, execute \a statement and break if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelRCBreakStmt(rc, stmt)       AssertLogRelMsgRCBreakStmt(rc, ("%Rra\n", (rc)), stmt)
+
+/** @def AssertLogRelMsgRC
+ * Asserts a iprt status code successful.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelMsgRC(rc, msg)              AssertLogRelMsg(RT_SUCCESS_NP(rc), msg)
+
+/** @def AssertLogRelMsgRCReturn
+ * Asserts a iprt status code successful.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @param   rcRet   What is to be presented to return.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelMsgRCReturn(rc, msg, rcRet) AssertLogRelMsgReturn(RT_SUCCESS_NP(rc), msg, rcRet)
+
+/** @def AssertLogRelMsgRCReturnStmt
+ * Asserts a iprt status code successful, execute \a stmt and return on
+ * failure.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before returning in case of a failed
+ *                  assertion.
+ * @param   rcRet   What is to be presented to return.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelMsgRCReturnStmt(rc, msg, stmt, rcRet) AssertLogRelMsgReturnStmt(RT_SUCCESS_NP(rc), msg, stmt, rcRet)
+
+/** @def AssertLogRelMsgRCReturnVoid
+ * Asserts a iprt status code successful.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelMsgRCReturnVoid(rc, msg)    AssertLogRelMsgReturnVoid(RT_SUCCESS_NP(rc), msg)
+
+/** @def AssertLogRelMsgRCBreak
+ * Asserts a iprt status code successful.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelMsgRCBreak(rc, msg)         AssertLogRelMsgBreak(RT_SUCCESS(rc), msg)
+
+/** @def AssertLogRelMsgRCBreakStmt
+ * Asserts a iprt status code successful, execute \a stmt and break if it isn't.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelMsgRCBreakStmt(rc, msg, stmt) AssertLogRelMsgBreakStmt(RT_SUCCESS_NP(rc), msg, stmt)
+
+/** @def AssertLogRelRCSuccess
+ * Asserts that an iprt status code equals VINF_SUCCESS.
+ *
+ * @param   rc  iprt status code.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelRCSuccess(rc)               AssertLogRelMsg((rc) == VINF_SUCCESS, ("%Rra\n", (rc)))
+
+/** @def AssertLogRelRCSuccessReturn
+ * Asserts that an iprt status code equals VINF_SUCCESS.
+ *
+ * @param   rc      iprt status code.
+ * @param   rcRet   What is to be presented to return.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelRCSuccessReturn(rc, rcRet)  AssertLogRelMsgReturn((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), rcRet)
+
+/** @def AssertLogRelRCSuccessReturnVoid
+ * Asserts that an iprt status code equals VINF_SUCCESS.
+ *
+ * @param   rc      iprt status code.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelRCSuccessReturnVoid(rc)     AssertLogRelMsgReturnVoid((rc) == VINF_SUCCESS, ("%Rra\n", (rc)))
+
+/** @def AssertLogRelRCSuccessBreak
+ * Asserts that an iprt status code equals VINF_SUCCESS.
+ *
+ * @param   rc      iprt status code.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelRCSuccessBreak(rc)          AssertLogRelMsgBreak((rc) == VINF_SUCCESS, ("%Rra\n", (rc)))
+
+/** @def AssertLogRelRCSuccessBreakStmt
+ * Asserts that an iprt status code equals VINF_SUCCESS.
+ *
+ * @param   rc      iprt status code.
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertLogRelRCSuccessBreakStmt(rc, stmt) AssertLogRelMsgBreakStmt((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), stmt)
+
+
+/** @def AssertReleaseRC
+ * Asserts a iprt status code successful.
+ *
+ * On failure information about the error will be printed and a breakpoint hit.
+ *
+ * @param   rc  iprt status code.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertReleaseRC(rc)                 AssertReleaseMsgRC(rc, ("%Rra\n", (rc)))
+
+/** @def AssertReleaseRCReturn
+ * Asserts a iprt status code successful, returning if it isn't.
+ *
+ * On failure information about the error will be printed, a breakpoint hit
+ * and finally returning from the function if the breakpoint is somehow ignored.
+ *
+ * @param   rc      iprt status code.
+ * @param   rcRet   What is to be presented to return.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertReleaseRCReturn(rc, rcRet)    AssertReleaseMsgRCReturn(rc, ("%Rra\n", (rc)), rcRet)
+
+/** @def AssertReleaseRCReturnVoid
+ * Asserts a iprt status code successful, returning if it isn't.
+ *
+ * On failure information about the error will be printed, a breakpoint hit
+ * and finally returning from the function if the breakpoint is somehow ignored.
+ *
+ * @param   rc      iprt status code.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertReleaseRCReturnVoid(rc)       AssertReleaseMsgRCReturnVoid(rc, ("%Rra\n", (rc)))
+
+/** @def AssertReleaseRCBreak
+ * Asserts a iprt status code successful, breaking if it isn't.
+ *
+ * On failure information about the error will be printed, a breakpoint hit
+ * and finally breaking the current statement if the breakpoint is somehow ignored.
+ *
+ * @param   rc      iprt status code.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertReleaseRCBreak(rc)            AssertReleaseMsgRCBreak(rc, ("%Rra\n", (rc)))
+
+/** @def AssertReleaseRCBreakStmt
+ * Asserts a iprt status code successful, break if it isn't.
+ *
+ * On failure information about the error will be printed, a breakpoint hit
+ * and finally the break statement will be issued if the breakpoint is somehow ignored.
+ *
+ * @param   rc      iprt status code.
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertReleaseRCBreakStmt(rc, stmt)  AssertReleaseMsgRCBreakStmt(rc, ("%Rra\n", (rc)), stmt)
+
+/** @def AssertReleaseMsgRC
+ * Asserts a iprt status code successful.
+ *
+ * On failure a custom message is printed and a breakpoint is hit.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertReleaseMsgRC(rc, msg)         AssertReleaseMsg(RT_SUCCESS_NP(rc), msg)
+
+/** @def AssertReleaseMsgRCReturn
+ * Asserts a iprt status code successful.
+ *
+ * On failure a custom message is printed, a breakpoint is hit, and finally
+ * returning from the function if the breakpoint is somehow ignored.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @param   rcRet   What is to be presented to return.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertReleaseMsgRCReturn(rc, msg, rcRet)    AssertReleaseMsgReturn(RT_SUCCESS_NP(rc), msg, rcRet)
+
+/** @def AssertReleaseMsgRCReturnVoid
+ * Asserts a iprt status code successful.
+ *
+ * On failure a custom message is printed, a breakpoint is hit, and finally
+ * returning from the function if the breakpoint is somehow ignored.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertReleaseMsgRCReturnVoid(rc, msg)    AssertReleaseMsgReturnVoid(RT_SUCCESS_NP(rc), msg)
+
+/** @def AssertReleaseMsgRCBreak
+ * Asserts a iprt status code successful.
+ *
+ * On failure a custom message is printed, a breakpoint is hit, and finally
+ * breaking the current status if the breakpoint is somehow ignored.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertReleaseMsgRCBreak(rc, msg)        AssertReleaseMsgBreak(RT_SUCCESS(rc), msg)
+
+/** @def AssertReleaseMsgRCBreakStmt
+ * Asserts a iprt status code successful.
+ *
+ * On failure a custom message is printed, a breakpoint is hit, and finally
+ * the break statement is issued if the breakpoint is somehow ignored.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertReleaseMsgRCBreakStmt(rc, msg, stmt)  AssertReleaseMsgBreakStmt(RT_SUCCESS_NP(rc), msg, stmt)
+
+/** @def AssertReleaseRCSuccess
+ * Asserts that an iprt status code equals VINF_SUCCESS.
+ *
+ * On failure information about the error will be printed and a breakpoint hit.
+ *
+ * @param   rc  iprt status code.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertReleaseRCSuccess(rc)                  AssertReleaseMsg((rc) == VINF_SUCCESS, ("%Rra\n", (rc)))
+
+/** @def AssertReleaseRCSuccessReturn
+ * Asserts that an iprt status code equals VINF_SUCCESS.
+ *
+ * On failure information about the error will be printed, a breakpoint hit
+ * and finally returning from the function if the breakpoint is somehow ignored.
+ *
+ * @param   rc      iprt status code.
+ * @param   rcRet   What is to be presented to return.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertReleaseRCSuccessReturn(rc, rcRet)     AssertReleaseMsgReturn((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), rcRet)
+
+/** @def AssertReleaseRCSuccessReturnVoid
+ * Asserts that an iprt status code equals VINF_SUCCESS.
+ *
+ * On failure information about the error will be printed, a breakpoint hit
+ * and finally returning from the function if the breakpoint is somehow ignored.
+ *
+ * @param   rc      iprt status code.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertReleaseRCSuccessReturnVoid(rc)     AssertReleaseMsgReturnVoid((rc) == VINF_SUCCESS, ("%Rra\n", (rc)))
+
+/** @def AssertReleaseRCSuccessBreak
+ * Asserts that an iprt status code equals VINF_SUCCESS.
+ *
+ * On failure information about the error will be printed, a breakpoint hit
+ * and finally breaking the current statement if the breakpoint is somehow ignored.
+ *
+ * @param   rc      iprt status code.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertReleaseRCSuccessBreak(rc)         AssertReleaseMsgBreak((rc) == VINF_SUCCESS, ("%Rra\n", (rc)))
+
+/** @def AssertReleaseRCSuccessBreakStmt
+ * Asserts that an iprt status code equals VINF_SUCCESS.
+ *
+ * On failure information about the error will be printed, a breakpoint hit
+ * and finally the break statement will be issued if the breakpoint is somehow ignored.
+ *
+ * @param   rc      iprt status code.
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertReleaseRCSuccessBreakStmt(rc, stmt)   AssertReleaseMsgBreakStmt((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), stmt)
+
+
+/** @def AssertFatalRC
+ * Asserts a iprt status code successful.
+ *
+ * On failure information about the error will be printed and a breakpoint hit.
+ *
+ * @param   rc  iprt status code.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertFatalRC(rc)               AssertFatalMsgRC(rc, ("%Rra\n", (rc)))
+
+/** @def AssertReleaseMsgRC
+ * Asserts a iprt status code successful.
+ *
+ * On failure a custom message is printed and a breakpoint is hit.
+ *
+ * @param   rc      iprt status code.
+ * @param   msg     printf argument list (in parenthesis).
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertFatalMsgRC(rc, msg)       AssertFatalMsg(RT_SUCCESS_NP(rc), msg)
+
+/** @def AssertFatalRCSuccess
+ * Asserts that an iprt status code equals VINF_SUCCESS.
+ *
+ * On failure information about the error will be printed and a breakpoint hit.
+ *
+ * @param   rc  iprt status code.
+ * @remark  rc is referenced multiple times.
+ */
+#define AssertFatalRCSuccess(rc)        AssertFatalMsg((rc) == VINF_SUCCESS, ("%Rra\n", (rc)))
+
+
+/** @def AssertPtr
+ * Asserts that a pointer is valid.
+ *
+ * @param   pv      The pointer.
+ */
+#define AssertPtr(pv)                   AssertMsg(VALID_PTR(pv), ("%p\n", (pv)))
+
+/** @def AssertPtrReturn
+ * Asserts that a pointer is valid.
+ *
+ * @param   pv      The pointer.
+ * @param   rcRet   What is to be presented to return.
+ */
+#define AssertPtrReturn(pv, rcRet)      AssertMsgReturn(VALID_PTR(pv), ("%p\n", (pv)), rcRet)
+
+/** @def AssertPtrReturnVoid
+ * Asserts that a pointer is valid.
+ *
+ * @param   pv      The pointer.
+ */
+#define AssertPtrReturnVoid(pv)         AssertMsgReturnVoid(VALID_PTR(pv), ("%p\n", (pv)))
+
+/** @def AssertPtrBreak
+ * Asserts that a pointer is valid.
+ *
+ * @param   pv      The pointer.
+ */
+#define AssertPtrBreak(pv)              AssertMsgBreak(VALID_PTR(pv), ("%p\n", (pv)))
+
+/** @def AssertPtrBreakStmt
+ * Asserts that a pointer is valid.
+ *
+ * @param   pv      The pointer.
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ */
+#define AssertPtrBreakStmt(pv, stmt)    AssertMsgBreakStmt(VALID_PTR(pv), ("%p\n", (pv)), stmt)
+
+/** @def AssertPtrNull
+ * Asserts that a pointer is valid or NULL.
+ *
+ * @param   pv      The pointer.
+ */
+#define AssertPtrNull(pv)               AssertMsg(VALID_PTR(pv) || (pv) == NULL, ("%p\n", (pv)))
+
+/** @def AssertPtrNullReturn
+ * Asserts that a pointer is valid or NULL.
+ *
+ * @param   pv      The pointer.
+ * @param   rcRet   What is to be presented to return.
+ */
+#define AssertPtrNullReturn(pv, rcRet)  AssertMsgReturn(VALID_PTR(pv) || (pv) == NULL, ("%p\n", (pv)), rcRet)
+
+/** @def AssertPtrNullReturnVoid
+ * Asserts that a pointer is valid or NULL.
+ *
+ * @param   pv      The pointer.
+ */
+#define AssertPtrNullReturnVoid(pv)     AssertMsgReturnVoid(VALID_PTR(pv) || (pv) == NULL, ("%p\n", (pv)))
+
+/** @def AssertPtrNullBreak
+ * Asserts that a pointer is valid or NULL.
+ *
+ * @param   pv      The pointer.
+ */
+#define AssertPtrNullBreak(pv)          AssertMsgBreak(VALID_PTR(pv) || (pv) == NULL, ("%p\n", (pv)))
+
+/** @def AssertPtrNullBreakStmt
+ * Asserts that a pointer is valid or NULL.
+ *
+ * @param   pv      The pointer.
+ * @param   stmt    Statement to execute before break in case of a failed assertion.
+ */
+#define AssertPtrNullBreakStmt(pv, stmt) AssertMsgBreakStmt(VALID_PTR(pv) || (pv) == NULL, ("%p\n", (pv)), stmt)
+
+/** @def AssertGCPhys32
+ * Asserts that the high dword of a physical address is zero
+ *
+ * @param   GCPhys      The address (RTGCPHYS).
+ */
+#define AssertGCPhys32(GCPhys)          AssertMsg(VALID_PHYS32(GCPhys), ("%RGp\n", (RTGCPHYS)(GCPhys)))
+
+/** @def AssertGCPtr32
+ * Asserts that the high dword of a physical address is zero
+ *
+ * @param   GCPtr       The address (RTGCPTR).
+ */
+#if GC_ARCH_BITS == 32
+# define AssertGCPtr32(GCPtr)           do { } while (0)
+#else
+# define AssertGCPtr32(GCPtr)           AssertMsg(!((GCPtr) & UINT64_C(0xffffffff00000000)), ("%RGv\n", GCPtr))
+#endif
+
+/** @def AssertForEach
+ * Equivalent to Assert for each value of the variable from the starting
+ * value to the finishing one.
+ *
+ * @param   var     Name of the counter variable.
+ * @param   vartype Type of the counter variable.
+ * @param   first   Lowest inclusive value of the counter variable.
+ *                  This must be free from side effects.
+ * @param   end     Highest exclusive value of the counter variable.
+ *                  This must be free from side effects.
+ * @param   expr    Expression which should be true for each value of @a var.
+ */
+#define AssertForEach(var, vartype, first, end, expr) \
+    do { \
+        vartype var; \
+        Assert((first) == (first) && (end) == (end)); /* partial check for side effects */ \
+        for (var = (first); var < (end); var++) \
+            AssertMsg(expr, ("%s = %#RX64 (%RI64)", #var, (uint64_t)var, (int64_t)var)); \
+    } while (0)
+
+#ifdef RT_OS_WINDOWS
+
+/** @def AssertNtStatus
+ * Asserts that the NT_SUCCESS() returns true for the given NTSTATUS value.
+ *
+ * @param   a_rcNt  The NTSTATUS to check.  Will be evaluated twice and
+ *                  subjected to NOREF().
+ * @sa      AssertRC()
+ */
+# define AssertNtStatus(a_rcNt) \
+    do { AssertMsg(NT_SUCCESS(a_rcNt), ("%#x\n", (a_rcNt))); NOREF(a_rcNt); } while (0)
+
+/** @def AssertNtStatusSuccess
+ * Asserts that the given NTSTATUS value equals STATUS_SUCCESS.
+ *
+ * @param   a_rcNt  The NTSTATUS to check.  Will be evaluated twice and
+ *                  subjected to NOREF().
+ * @sa      AssertRCSuccess()
+ */
+# define AssertNtStatusSuccess(a_rcNt) \
+    do { AssertMsg((a_rcNt) == STATUS_SUCCESS, ("%#x\n", (a_rcNt))); NOREF(a_rcNt); } while (0)
+
+#endif /* RT_OS_WINDOWS */
+
+/** @} */
+
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/avl.h b/ubuntu/vbox/include/iprt/avl.h
new file mode 100644 (file)
index 0000000..6dd46b6
--- /dev/null
@@ -0,0 +1,1136 @@
+/** @file
+ * IPRT - AVL Trees.
+ */
+
+/*
+ * Copyright (C) 2006-2017 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.
+ */
+
+#ifndef ___iprt_avl_h
+#define ___iprt_avl_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_avl    RTAvl - AVL Trees
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/** AVL tree of void pointers.
+ * @{
+ */
+
+/**
+ * AVL key type
+ */
+typedef void *  AVLPVKEY;
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLPVNodeCore
+{
+    AVLPVKEY                Key;        /** Key value. */
+    struct _AVLPVNodeCore  *pLeft;      /** Pointer to left leaf node. */
+    struct _AVLPVNodeCore  *pRight;     /** Pointer to right leaf node. */
+    unsigned char           uchHeight;  /** Height of this tree: max(height(left), height(right)) + 1 */
+} AVLPVNODECORE, *PAVLPVNODECORE, **PPAVLPVNODECORE;
+
+/** A tree with void pointer keys. */
+typedef PAVLPVNODECORE     AVLPVTREE;
+/** Pointer to a tree with void pointer keys. */
+typedef PPAVLPVNODECORE    PAVLPVTREE;
+
+/** Callback function for AVLPVDoWithAll().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int) AVLPVCALLBACK(PAVLPVNODECORE, void *);
+/** Pointer to callback function for AVLPVDoWithAll(). */
+typedef AVLPVCALLBACK *PAVLPVCALLBACK;
+
+/*
+ * Functions.
+ */
+RTDECL(bool)            RTAvlPVInsert(PAVLPVTREE ppTree, PAVLPVNODECORE pNode);
+RTDECL(PAVLPVNODECORE)  RTAvlPVRemove(PAVLPVTREE ppTree, AVLPVKEY Key);
+RTDECL(PAVLPVNODECORE)  RTAvlPVGet(PAVLPVTREE ppTree, AVLPVKEY Key);
+RTDECL(PAVLPVNODECORE)  RTAvlPVGetBestFit(PAVLPVTREE ppTree, AVLPVKEY Key, bool fAbove);
+RTDECL(PAVLPVNODECORE)  RTAvlPVRemoveBestFit(PAVLPVTREE ppTree, AVLPVKEY Key, bool fAbove);
+RTDECL(int)             RTAvlPVDoWithAll(PAVLPVTREE ppTree, int fFromLeft, PAVLPVCALLBACK pfnCallBack, void *pvParam);
+RTDECL(int)             RTAvlPVDestroy(PAVLPVTREE ppTree, PAVLPVCALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+
+/** AVL tree of unsigned long.
+ * @{
+ */
+
+/**
+ * AVL key type
+ */
+typedef unsigned long   AVLULKEY;
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLULNodeCore
+{
+    AVLULKEY                Key;        /** Key value. */
+    struct _AVLULNodeCore  *pLeft;      /** Pointer to left leaf node. */
+    struct _AVLULNodeCore  *pRight;     /** Pointer to right leaf node. */
+    unsigned char           uchHeight;  /** Height of this tree: max(height(left), height(right)) + 1 */
+} AVLULNODECORE, *PAVLULNODECORE, **PPAVLULNODECORE;
+
+
+/** Callback function for AVLULDoWithAll().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int) AVLULCALLBACK(PAVLULNODECORE, void*);
+/** Pointer to callback function for AVLULDoWithAll(). */
+typedef AVLULCALLBACK *PAVLULCALLBACK;
+
+
+/*
+ * Functions.
+ */
+RTDECL(bool)            RTAvlULInsert(PPAVLULNODECORE ppTree, PAVLULNODECORE pNode);
+RTDECL(PAVLULNODECORE)  RTAvlULRemove(PPAVLULNODECORE ppTree, AVLULKEY Key);
+RTDECL(PAVLULNODECORE)  RTAvlULGet(PPAVLULNODECORE ppTree, AVLULKEY Key);
+RTDECL(PAVLULNODECORE)  RTAvlULGetBestFit(PPAVLULNODECORE ppTree, AVLULKEY Key, bool fAbove);
+RTDECL(PAVLULNODECORE)  RTAvlULRemoveBestFit(PPAVLULNODECORE ppTree, AVLULKEY Key, bool fAbove);
+RTDECL(int)             RTAvlULDoWithAll(PPAVLULNODECORE ppTree, int fFromLeft, PAVLULCALLBACK pfnCallBack, void *pvParam);
+RTDECL(int)             RTAvlULDestroy(PPAVLULNODECORE pTree, PAVLULCALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+
+
+/** AVL tree of void pointer ranges.
+ * @{
+ */
+
+/**
+ * AVL key type
+ */
+typedef void *AVLRPVKEY;
+
+/**
+ * AVL Core node.
+ */
+typedef struct AVLRPVNodeCore
+{
+    AVLRPVKEY               Key;        /**< First key value in the range (inclusive). */
+    AVLRPVKEY               KeyLast;    /**< Last key value in the range (inclusive). */
+    struct AVLRPVNodeCore  *pLeft;      /**< Pointer to left leaf node. */
+    struct AVLRPVNodeCore  *pRight;     /**< Pointer to right leaf node. */
+    unsigned char           uchHeight;  /**< Height of this tree: max(height(left), height(right)) + 1 */
+} AVLRPVNODECORE, *PAVLRPVNODECORE, **PPAVLRPVNODECORE;
+
+/** A tree with void pointer keys. */
+typedef PAVLRPVNODECORE    AVLRPVTREE;
+/** Pointer to a tree with void pointer keys. */
+typedef PPAVLRPVNODECORE   PAVLRPVTREE;
+
+/** Callback function for AVLPVDoWithAll().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int) AVLRPVCALLBACK(PAVLRPVNODECORE, void *);
+/** Pointer to callback function for AVLPVDoWithAll(). */
+typedef AVLRPVCALLBACK *PAVLRPVCALLBACK;
+
+/*
+ * Functions.
+ */
+RTDECL(bool)            RTAvlrPVInsert(PAVLRPVTREE ppTree, PAVLRPVNODECORE pNode);
+RTDECL(PAVLRPVNODECORE) RTAvlrPVRemove(PAVLRPVTREE ppTree, AVLRPVKEY Key);
+RTDECL(PAVLRPVNODECORE) RTAvlrPVGet(PAVLRPVTREE ppTree, AVLRPVKEY Key);
+RTDECL(PAVLRPVNODECORE) RTAvlrPVRangeGet(PAVLRPVTREE ppTree, AVLRPVKEY Key);
+RTDECL(PAVLRPVNODECORE) RTAvlrPVRangeRemove(PAVLRPVTREE ppTree, AVLRPVKEY Key);
+RTDECL(PAVLRPVNODECORE) RTAvlrPVGetBestFit(PAVLRPVTREE ppTree, AVLRPVKEY Key, bool fAbove);
+RTDECL(PAVLRPVNODECORE) RTAvlrPVRemoveBestFit(PAVLRPVTREE ppTree, AVLRPVKEY Key, bool fAbove);
+RTDECL(int)             RTAvlrPVDoWithAll(PAVLRPVTREE ppTree, int fFromLeft, PAVLRPVCALLBACK pfnCallBack, void *pvParam);
+RTDECL(int)             RTAvlrPVDestroy(PAVLRPVTREE ppTree, PAVLRPVCALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+
+
+/** AVL tree of uint32_t
+ * @{
+ */
+
+/** AVL key type. */
+typedef uint32_t    AVLU32KEY;
+
+/** AVL Core node. */
+typedef struct _AVLU32NodeCore
+{
+    AVLU32KEY               Key;        /**< Key value. */
+    struct _AVLU32NodeCore *pLeft;      /**< Pointer to left leaf node. */
+    struct _AVLU32NodeCore *pRight;     /**< Pointer to right leaf node. */
+    unsigned char           uchHeight;  /**< Height of this tree: max(height(left), height(right)) + 1 */
+} AVLU32NODECORE, *PAVLU32NODECORE, **PPAVLU32NODECORE;
+
+/** A tree with void pointer keys. */
+typedef PAVLU32NODECORE     AVLU32TREE;
+/** Pointer to a tree with void pointer keys. */
+typedef PPAVLU32NODECORE    PAVLU32TREE;
+
+/** Callback function for AVLU32DoWithAll() & AVLU32Destroy().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int) AVLU32CALLBACK(PAVLU32NODECORE, void*);
+/** Pointer to callback function for AVLU32DoWithAll() & AVLU32Destroy(). */
+typedef AVLU32CALLBACK *PAVLU32CALLBACK;
+
+
+/*
+ * Functions.
+ */
+RTDECL(bool)            RTAvlU32Insert(PAVLU32TREE pTree, PAVLU32NODECORE pNode);
+RTDECL(PAVLU32NODECORE) RTAvlU32Remove(PAVLU32TREE pTree, AVLU32KEY Key);
+RTDECL(PAVLU32NODECORE) RTAvlU32Get(PAVLU32TREE pTree, AVLU32KEY Key);
+RTDECL(PAVLU32NODECORE) RTAvlU32GetBestFit(PAVLU32TREE pTree, AVLU32KEY Key, bool fAbove);
+RTDECL(PAVLU32NODECORE) RTAvlU32RemoveBestFit(PAVLU32TREE pTree, AVLU32KEY Key, bool fAbove);
+RTDECL(int)             RTAvlU32DoWithAll(PAVLU32TREE pTree, int fFromLeft, PAVLU32CALLBACK pfnCallBack, void *pvParam);
+RTDECL(int)             RTAvlU32Destroy(PAVLU32TREE pTree, PAVLU32CALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+/**
+ * AVL uint32_t type for the relative offset pointer scheme.
+ */
+typedef int32_t     AVLOU32;
+
+typedef uint32_t     AVLOU32KEY;
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLOU32NodeCore
+{
+    /** Key value. */
+    AVLOU32KEY          Key;
+    /** Offset to the left leaf node, relative to this field. */
+    AVLOU32             pLeft;
+    /** Offset to the right leaf node, relative to this field. */
+    AVLOU32             pRight;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char       uchHeight;
+} AVLOU32NODECORE, *PAVLOU32NODECORE;
+
+/** A offset base tree with uint32_t keys. */
+typedef AVLOU32         AVLOU32TREE;
+/** Pointer to an offset base tree with uint32_t keys. */
+typedef AVLOU32TREE    *PAVLOU32TREE;
+
+/** Pointer to an internal tree pointer.
+ * In this case it's a pointer to a relative offset. */
+typedef AVLOU32TREE    *PPAVLOU32NODECORE;
+
+/** Callback function for RTAvloU32DoWithAll().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)   AVLOU32CALLBACK(PAVLOU32NODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvloU32DoWithAll(). */
+typedef AVLOU32CALLBACK *PAVLOU32CALLBACK;
+
+RTDECL(bool)                  RTAvloU32Insert(PAVLOU32TREE pTree, PAVLOU32NODECORE pNode);
+RTDECL(PAVLOU32NODECORE)      RTAvloU32Remove(PAVLOU32TREE pTree, AVLOU32KEY Key);
+RTDECL(PAVLOU32NODECORE)      RTAvloU32Get(PAVLOU32TREE pTree, AVLOU32KEY Key);
+RTDECL(int)                   RTAvloU32DoWithAll(PAVLOU32TREE pTree, int fFromLeft, PAVLOU32CALLBACK pfnCallBack, void *pvParam);
+RTDECL(PAVLOU32NODECORE)      RTAvloU32GetBestFit(PAVLOU32TREE ppTree, AVLOU32KEY Key, bool fAbove);
+RTDECL(PAVLOU32NODECORE)      RTAvloU32RemoveBestFit(PAVLOU32TREE ppTree, AVLOU32KEY Key, bool fAbove);
+RTDECL(int)                   RTAvloU32Destroy(PAVLOU32TREE pTree, PAVLOU32CALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+
+/** AVL tree of uint32_t, list duplicates.
+ * @{
+ */
+
+/** AVL key type. */
+typedef uint32_t    AVLLU32KEY;
+
+/** AVL Core node. */
+typedef struct _AVLLU32NodeCore
+{
+    AVLLU32KEY                  Key;        /**< Key value. */
+    unsigned char               uchHeight;  /**< Height of this tree: max(height(left), height(right)) + 1 */
+    struct _AVLLU32NodeCore    *pLeft;      /**< Pointer to left leaf node. */
+    struct _AVLLU32NodeCore    *pRight;     /**< Pointer to right leaf node. */
+    struct _AVLLU32NodeCore    *pList;      /**< Pointer to next node with the same key. */
+} AVLLU32NODECORE, *PAVLLU32NODECORE, **PPAVLLU32NODECORE;
+
+/** Callback function for RTAvllU32DoWithAll() & RTAvllU32Destroy().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int) AVLLU32CALLBACK(PAVLLU32NODECORE, void*);
+/** Pointer to callback function for RTAvllU32DoWithAll() & RTAvllU32Destroy(). */
+typedef AVLLU32CALLBACK *PAVLLU32CALLBACK;
+
+
+/*
+ * Functions.
+ */
+RTDECL(bool)                RTAvllU32Insert(PPAVLLU32NODECORE ppTree, PAVLLU32NODECORE pNode);
+RTDECL(PAVLLU32NODECORE)    RTAvllU32Remove(PPAVLLU32NODECORE ppTree, AVLLU32KEY Key);
+RTDECL(PAVLLU32NODECORE)    RTAvllU32RemoveNode(PPAVLLU32NODECORE ppTree, PAVLLU32NODECORE pNode);
+RTDECL(PAVLLU32NODECORE)    RTAvllU32Get(PPAVLLU32NODECORE ppTree, AVLLU32KEY Key);
+RTDECL(PAVLLU32NODECORE)    RTAvllU32GetBestFit(PPAVLLU32NODECORE ppTree, AVLLU32KEY Key, bool fAbove);
+RTDECL(PAVLLU32NODECORE)    RTAvllU32RemoveBestFit(PPAVLLU32NODECORE ppTree, AVLLU32KEY Key, bool fAbove);
+RTDECL(int)                 RTAvllU32DoWithAll(PPAVLLU32NODECORE ppTree, int fFromLeft, PAVLLU32CALLBACK pfnCallBack, void *pvParam);
+RTDECL(int)                 RTAvllU32Destroy(PPAVLLU32NODECORE pTree, PAVLLU32CALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+
+
+/** AVL tree of uint64_t ranges.
+ * @{
+ */
+
+/**
+ * AVL key type
+ */
+typedef uint64_t AVLRU64KEY;
+
+/**
+ * AVL Core node.
+ */
+typedef struct AVLRU64NodeCore
+{
+    AVLRU64KEY               Key;        /**< First key value in the range (inclusive). */
+    AVLRU64KEY               KeyLast;    /**< Last key value in the range (inclusive). */
+    struct AVLRU64NodeCore  *pLeft;      /**< Pointer to left leaf node. */
+    struct AVLRU64NodeCore  *pRight;     /**< Pointer to right leaf node. */
+    unsigned char            uchHeight;  /**< Height of this tree: max(height(left), height(right)) + 1 */
+} AVLRU64NODECORE, *PAVLRU64NODECORE, **PPAVLRU64NODECORE;
+
+/** A tree with void pointer keys. */
+typedef PAVLRU64NODECORE    AVLRU64TREE;
+/** Pointer to a tree with void pointer keys. */
+typedef PPAVLRU64NODECORE   PAVLRU64TREE;
+
+/** Callback function for AVLRU64DoWithAll().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int) AVLRU64CALLBACK(PAVLRU64NODECORE, void *);
+/** Pointer to callback function for AVLU64DoWithAll(). */
+typedef AVLRU64CALLBACK *PAVLRU64CALLBACK;
+
+/*
+ * Functions.
+ */
+RTDECL(bool)             RTAvlrU64Insert(PAVLRU64TREE ppTree, PAVLRU64NODECORE pNode);
+RTDECL(PAVLRU64NODECORE) RTAvlrU64Remove(PAVLRU64TREE ppTree, AVLRU64KEY Key);
+RTDECL(PAVLRU64NODECORE) RTAvlrU64Get(PAVLRU64TREE ppTree, AVLRU64KEY Key);
+RTDECL(PAVLRU64NODECORE) RTAvlrU64RangeGet(PAVLRU64TREE ppTree, AVLRU64KEY Key);
+RTDECL(PAVLRU64NODECORE) RTAvlrU64RangeRemove(PAVLRU64TREE ppTree, AVLRU64KEY Key);
+RTDECL(PAVLRU64NODECORE) RTAvlrU64GetBestFit(PAVLRU64TREE ppTree, AVLRU64KEY Key, bool fAbove);
+RTDECL(PAVLRU64NODECORE) RTAvlrU64RemoveBestFit(PAVLRU64TREE ppTree, AVLRU64KEY Key, bool fAbove);
+RTDECL(int)              RTAvlrU64DoWithAll(PAVLRU64TREE ppTree, int fFromLeft, PAVLRU64CALLBACK pfnCallBack, void *pvParam);
+RTDECL(int)              RTAvlrU64Destroy(PAVLRU64TREE ppTree, PAVLRU64CALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+
+
+/** AVL tree of RTGCPHYSes - using relative offsets internally.
+ * @{
+ */
+
+/**
+ * AVL 'pointer' type for the relative offset pointer scheme.
+ */
+typedef int32_t     AVLOGCPHYS;
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLOGCPhysNodeCore
+{
+    /** Key value. */
+    RTGCPHYS            Key;
+    /** Offset to the left leaf node, relative to this field. */
+    AVLOGCPHYS          pLeft;
+    /** Offset to the right leaf node, relative to this field. */
+    AVLOGCPHYS          pRight;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char       uchHeight;
+    /** Padding */
+    unsigned char       Padding[7];
+} AVLOGCPHYSNODECORE, *PAVLOGCPHYSNODECORE;
+
+/** A offset base tree with uint32_t keys. */
+typedef AVLOGCPHYS         AVLOGCPHYSTREE;
+/** Pointer to an offset base tree with uint32_t keys. */
+typedef AVLOGCPHYSTREE    *PAVLOGCPHYSTREE;
+
+/** Pointer to an internal tree pointer.
+ * In this case it's a pointer to a relative offset. */
+typedef AVLOGCPHYSTREE    *PPAVLOGCPHYSNODECORE;
+
+/** Callback function for RTAvloGCPhysDoWithAll() and RTAvloGCPhysDestroy().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)   AVLOGCPHYSCALLBACK(PAVLOGCPHYSNODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvloGCPhysDoWithAll() and RTAvloGCPhysDestroy(). */
+typedef AVLOGCPHYSCALLBACK *PAVLOGCPHYSCALLBACK;
+
+RTDECL(bool)                    RTAvloGCPhysInsert(PAVLOGCPHYSTREE pTree, PAVLOGCPHYSNODECORE pNode);
+RTDECL(PAVLOGCPHYSNODECORE)     RTAvloGCPhysRemove(PAVLOGCPHYSTREE pTree, RTGCPHYS Key);
+RTDECL(PAVLOGCPHYSNODECORE)     RTAvloGCPhysGet(PAVLOGCPHYSTREE pTree, RTGCPHYS Key);
+RTDECL(int)                     RTAvloGCPhysDoWithAll(PAVLOGCPHYSTREE pTree, int fFromLeft, PAVLOGCPHYSCALLBACK pfnCallBack, void *pvParam);
+RTDECL(PAVLOGCPHYSNODECORE)     RTAvloGCPhysGetBestFit(PAVLOGCPHYSTREE ppTree, RTGCPHYS Key, bool fAbove);
+RTDECL(PAVLOGCPHYSNODECORE)     RTAvloGCPhysRemoveBestFit(PAVLOGCPHYSTREE ppTree, RTGCPHYS Key, bool fAbove);
+RTDECL(int)                     RTAvloGCPhysDestroy(PAVLOGCPHYSTREE pTree, PAVLOGCPHYSCALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+
+/** AVL tree of RTGCPHYS ranges - using relative offsets internally.
+ * @{
+ */
+
+/**
+ * AVL 'pointer' type for the relative offset pointer scheme.
+ */
+typedef int32_t     AVLROGCPHYS;
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLROGCPhysNodeCore
+{
+    /** First key value in the range (inclusive). */
+    RTGCPHYS            Key;
+    /** Last key value in the range (inclusive). */
+    RTGCPHYS            KeyLast;
+    /** Offset to the left leaf node, relative to this field. */
+    AVLROGCPHYS         pLeft;
+    /** Offset to the right leaf node, relative to this field. */
+    AVLROGCPHYS         pRight;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char       uchHeight;
+    /** Padding */
+    unsigned char       Padding[7];
+} AVLROGCPHYSNODECORE, *PAVLROGCPHYSNODECORE;
+
+/** A offset base tree with uint32_t keys. */
+typedef AVLROGCPHYS         AVLROGCPHYSTREE;
+/** Pointer to an offset base tree with uint32_t keys. */
+typedef AVLROGCPHYSTREE    *PAVLROGCPHYSTREE;
+
+/** Pointer to an internal tree pointer.
+ * In this case it's a pointer to a relative offset. */
+typedef AVLROGCPHYSTREE    *PPAVLROGCPHYSNODECORE;
+
+/** Callback function for RTAvlroGCPhysDoWithAll() and RTAvlroGCPhysDestroy().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)   AVLROGCPHYSCALLBACK(PAVLROGCPHYSNODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvlroGCPhysDoWithAll() and RTAvlroGCPhysDestroy(). */
+typedef AVLROGCPHYSCALLBACK *PAVLROGCPHYSCALLBACK;
+
+RTDECL(bool)                    RTAvlroGCPhysInsert(PAVLROGCPHYSTREE pTree, PAVLROGCPHYSNODECORE pNode);
+RTDECL(PAVLROGCPHYSNODECORE)    RTAvlroGCPhysRemove(PAVLROGCPHYSTREE pTree, RTGCPHYS Key);
+RTDECL(PAVLROGCPHYSNODECORE)    RTAvlroGCPhysGet(PAVLROGCPHYSTREE pTree, RTGCPHYS Key);
+RTDECL(PAVLROGCPHYSNODECORE)    RTAvlroGCPhysRangeGet(PAVLROGCPHYSTREE pTree, RTGCPHYS Key);
+RTDECL(PAVLROGCPHYSNODECORE)    RTAvlroGCPhysRangeRemove(PAVLROGCPHYSTREE pTree, RTGCPHYS Key);
+RTDECL(PAVLROGCPHYSNODECORE)    RTAvlroGCPhysGetBestFit(PAVLROGCPHYSTREE ppTree, RTGCPHYS Key, bool fAbove);
+RTDECL(int)                     RTAvlroGCPhysDoWithAll(PAVLROGCPHYSTREE pTree, int fFromLeft, PAVLROGCPHYSCALLBACK pfnCallBack, void *pvParam);
+RTDECL(int)                     RTAvlroGCPhysDestroy(PAVLROGCPHYSTREE pTree, PAVLROGCPHYSCALLBACK pfnCallBack, void *pvParam);
+RTDECL(PAVLROGCPHYSNODECORE)    RTAvlroGCPhysGetRoot(PAVLROGCPHYSTREE pTree);
+RTDECL(PAVLROGCPHYSNODECORE)    RTAvlroGCPhysGetLeft(PAVLROGCPHYSNODECORE pNode);
+RTDECL(PAVLROGCPHYSNODECORE)    RTAvlroGCPhysGetRight(PAVLROGCPHYSNODECORE pNode);
+
+/** @} */
+
+
+/** AVL tree of RTGCPTRs.
+ * @{
+ */
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLGCPtrNodeCore
+{
+    /** Key value. */
+    RTGCPTR             Key;
+    /** Pointer to the left node. */
+    struct _AVLGCPtrNodeCore *pLeft;
+    /** Pointer to the right node. */
+    struct _AVLGCPtrNodeCore *pRight;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char       uchHeight;
+} AVLGCPTRNODECORE, *PAVLGCPTRNODECORE, **PPAVLGCPTRNODECORE;
+
+/** A tree of RTGCPTR keys. */
+typedef PAVLGCPTRNODECORE     AVLGCPTRTREE;
+/** Pointer to a tree of RTGCPTR keys. */
+typedef PPAVLGCPTRNODECORE    PAVLGCPTRTREE;
+
+/** Callback function for RTAvlGCPtrDoWithAll().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)   AVLGCPTRCALLBACK(PAVLGCPTRNODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvlGCPtrDoWithAll(). */
+typedef AVLGCPTRCALLBACK *PAVLGCPTRCALLBACK;
+
+RTDECL(bool)                    RTAvlGCPtrInsert(PAVLGCPTRTREE pTree, PAVLGCPTRNODECORE pNode);
+RTDECL(PAVLGCPTRNODECORE)       RTAvlGCPtrRemove(PAVLGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(PAVLGCPTRNODECORE)       RTAvlGCPtrGet(PAVLGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(int)                     RTAvlGCPtrDoWithAll(PAVLGCPTRTREE pTree, int fFromLeft, PAVLGCPTRCALLBACK pfnCallBack, void *pvParam);
+RTDECL(PAVLGCPTRNODECORE)       RTAvlGCPtrGetBestFit(PAVLGCPTRTREE ppTree, RTGCPTR Key, bool fAbove);
+RTDECL(PAVLGCPTRNODECORE)       RTAvlGCPtrRemoveBestFit(PAVLGCPTRTREE ppTree, RTGCPTR Key, bool fAbove);
+RTDECL(int)                     RTAvlGCPtrDestroy(PAVLGCPTRTREE pTree, PAVLGCPTRCALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+
+/** AVL tree of RTGCPTRs - using relative offsets internally.
+ * @{
+ */
+
+/**
+ * AVL 'pointer' type for the relative offset pointer scheme.
+ */
+typedef int32_t     AVLOGCPTR;
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLOGCPtrNodeCore
+{
+    /** Key value. */
+    RTGCPTR             Key;
+    /** Offset to the left leaf node, relative to this field. */
+    AVLOGCPTR           pLeft;
+    /** Offset to the right leaf node, relative to this field. */
+    AVLOGCPTR           pRight;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char       uchHeight;
+    unsigned char       padding[GC_ARCH_BITS == 64 ? 7 : 3];
+} AVLOGCPTRNODECORE, *PAVLOGCPTRNODECORE;
+
+/** A offset base tree with uint32_t keys. */
+typedef AVLOGCPTR         AVLOGCPTRTREE;
+/** Pointer to an offset base tree with uint32_t keys. */
+typedef AVLOGCPTRTREE    *PAVLOGCPTRTREE;
+
+/** Pointer to an internal tree pointer.
+ * In this case it's a pointer to a relative offset. */
+typedef AVLOGCPTRTREE    *PPAVLOGCPTRNODECORE;
+
+/** Callback function for RTAvloGCPtrDoWithAll().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)   AVLOGCPTRCALLBACK(PAVLOGCPTRNODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvloGCPtrDoWithAll(). */
+typedef AVLOGCPTRCALLBACK *PAVLOGCPTRCALLBACK;
+
+RTDECL(bool)                    RTAvloGCPtrInsert(PAVLOGCPTRTREE pTree, PAVLOGCPTRNODECORE pNode);
+RTDECL(PAVLOGCPTRNODECORE)      RTAvloGCPtrRemove(PAVLOGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(PAVLOGCPTRNODECORE)      RTAvloGCPtrGet(PAVLOGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(int)                     RTAvloGCPtrDoWithAll(PAVLOGCPTRTREE pTree, int fFromLeft, PAVLOGCPTRCALLBACK pfnCallBack, void *pvParam);
+RTDECL(PAVLOGCPTRNODECORE)      RTAvloGCPtrGetBestFit(PAVLOGCPTRTREE ppTree, RTGCPTR Key, bool fAbove);
+RTDECL(PAVLOGCPTRNODECORE)      RTAvloGCPtrRemoveBestFit(PAVLOGCPTRTREE ppTree, RTGCPTR Key, bool fAbove);
+RTDECL(int)                     RTAvloGCPtrDestroy(PAVLOGCPTRTREE pTree, PAVLOGCPTRCALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+
+/** AVL tree of RTGCPTR ranges.
+ * @{
+ */
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLRGCPtrNodeCore
+{
+    /** First key value in the range (inclusive). */
+    RTGCPTR             Key;
+    /** Last key value in the range (inclusive). */
+    RTGCPTR             KeyLast;
+    /** Offset to the left leaf node, relative to this field. */
+    struct _AVLRGCPtrNodeCore  *pLeft;
+    /** Offset to the right leaf node, relative to this field. */
+    struct _AVLRGCPtrNodeCore  *pRight;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char       uchHeight;
+} AVLRGCPTRNODECORE, *PAVLRGCPTRNODECORE;
+
+/** A offset base tree with RTGCPTR keys. */
+typedef PAVLRGCPTRNODECORE AVLRGCPTRTREE;
+/** Pointer to an offset base tree with RTGCPTR keys. */
+typedef AVLRGCPTRTREE    *PAVLRGCPTRTREE;
+
+/** Pointer to an internal tree pointer.
+ * In this case it's a pointer to a relative offset. */
+typedef AVLRGCPTRTREE    *PPAVLRGCPTRNODECORE;
+
+/** Callback function for RTAvlrGCPtrDoWithAll() and RTAvlrGCPtrDestroy().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)   AVLRGCPTRCALLBACK(PAVLRGCPTRNODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvlrGCPtrDoWithAll() and RTAvlrGCPtrDestroy(). */
+typedef AVLRGCPTRCALLBACK *PAVLRGCPTRCALLBACK;
+
+RTDECL(bool)                   RTAvlrGCPtrInsert(       PAVLRGCPTRTREE pTree, PAVLRGCPTRNODECORE pNode);
+RTDECL(PAVLRGCPTRNODECORE)     RTAvlrGCPtrRemove(       PAVLRGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(PAVLRGCPTRNODECORE)     RTAvlrGCPtrGet(          PAVLRGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(PAVLRGCPTRNODECORE)     RTAvlrGCPtrGetBestFit(   PAVLRGCPTRTREE pTree, RTGCPTR Key, bool fAbove);
+RTDECL(PAVLRGCPTRNODECORE)     RTAvlrGCPtrRangeGet(     PAVLRGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(PAVLRGCPTRNODECORE)     RTAvlrGCPtrRangeRemove(  PAVLRGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(int)                    RTAvlrGCPtrDoWithAll(    PAVLRGCPTRTREE pTree, int fFromLeft, PAVLRGCPTRCALLBACK pfnCallBack, void *pvParam);
+RTDECL(int)                    RTAvlrGCPtrDestroy(      PAVLRGCPTRTREE pTree, PAVLRGCPTRCALLBACK pfnCallBack, void *pvParam);
+RTDECL(PAVLRGCPTRNODECORE)     RTAvlrGCPtrGetRoot(      PAVLRGCPTRTREE pTree);
+RTDECL(PAVLRGCPTRNODECORE)     RTAvlrGCPtrGetLeft(      PAVLRGCPTRNODECORE pNode);
+RTDECL(PAVLRGCPTRNODECORE)     RTAvlrGCPtrGetRight(     PAVLRGCPTRNODECORE pNode);
+
+/** @} */
+
+
+/** AVL tree of RTGCPTR ranges - using relative offsets internally.
+ * @{
+ */
+
+/**
+ * AVL 'pointer' type for the relative offset pointer scheme.
+ */
+typedef int32_t     AVLROGCPTR;
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLROGCPtrNodeCore
+{
+    /** First key value in the range (inclusive). */
+    RTGCPTR             Key;
+    /** Last key value in the range (inclusive). */
+    RTGCPTR             KeyLast;
+    /** Offset to the left leaf node, relative to this field. */
+    AVLROGCPTR          pLeft;
+    /** Offset to the right leaf node, relative to this field. */
+    AVLROGCPTR          pRight;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char       uchHeight;
+    unsigned char       padding[GC_ARCH_BITS == 64 ? 7 : 7];
+} AVLROGCPTRNODECORE, *PAVLROGCPTRNODECORE;
+
+/** A offset base tree with uint32_t keys. */
+typedef AVLROGCPTR         AVLROGCPTRTREE;
+/** Pointer to an offset base tree with uint32_t keys. */
+typedef AVLROGCPTRTREE    *PAVLROGCPTRTREE;
+
+/** Pointer to an internal tree pointer.
+ * In this case it's a pointer to a relative offset. */
+typedef AVLROGCPTRTREE    *PPAVLROGCPTRNODECORE;
+
+/** Callback function for RTAvlroGCPtrDoWithAll() and RTAvlroGCPtrDestroy().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)   AVLROGCPTRCALLBACK(PAVLROGCPTRNODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvlroGCPtrDoWithAll() and RTAvlroGCPtrDestroy(). */
+typedef AVLROGCPTRCALLBACK *PAVLROGCPTRCALLBACK;
+
+RTDECL(bool)                    RTAvlroGCPtrInsert(PAVLROGCPTRTREE pTree, PAVLROGCPTRNODECORE pNode);
+RTDECL(PAVLROGCPTRNODECORE)     RTAvlroGCPtrRemove(PAVLROGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(PAVLROGCPTRNODECORE)     RTAvlroGCPtrGet(PAVLROGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(PAVLROGCPTRNODECORE)     RTAvlroGCPtrGetBestFit(PAVLROGCPTRTREE ppTree, RTGCPTR Key, bool fAbove);
+RTDECL(PAVLROGCPTRNODECORE)     RTAvlroGCPtrRangeGet(PAVLROGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(PAVLROGCPTRNODECORE)     RTAvlroGCPtrRangeRemove(PAVLROGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(int)                     RTAvlroGCPtrDoWithAll(PAVLROGCPTRTREE pTree, int fFromLeft, PAVLROGCPTRCALLBACK pfnCallBack, void *pvParam);
+RTDECL(int)                     RTAvlroGCPtrDestroy(PAVLROGCPTRTREE pTree, PAVLROGCPTRCALLBACK pfnCallBack, void *pvParam);
+RTDECL(PAVLROGCPTRNODECORE)     RTAvlroGCPtrGetRoot(PAVLROGCPTRTREE pTree);
+RTDECL(PAVLROGCPTRNODECORE)     RTAvlroGCPtrGetLeft(PAVLROGCPTRNODECORE pNode);
+RTDECL(PAVLROGCPTRNODECORE)     RTAvlroGCPtrGetRight(PAVLROGCPTRNODECORE pNode);
+
+/** @} */
+
+
+/** AVL tree of RTGCPTR ranges (overlapping supported) - using relative offsets internally.
+ * @{
+ */
+
+/**
+ * AVL 'pointer' type for the relative offset pointer scheme.
+ */
+typedef int32_t     AVLROOGCPTR;
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLROOGCPtrNodeCore
+{
+    /** First key value in the range (inclusive). */
+    RTGCPTR             Key;
+    /** Last key value in the range (inclusive). */
+    RTGCPTR             KeyLast;
+    /** Offset to the left leaf node, relative to this field. */
+    AVLROOGCPTR         pLeft;
+    /** Offset to the right leaf node, relative to this field. */
+    AVLROOGCPTR         pRight;
+    /** Pointer to the list of string with the same key. Don't touch. */
+    AVLROOGCPTR         pList;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char       uchHeight;
+} AVLROOGCPTRNODECORE, *PAVLROOGCPTRNODECORE;
+
+/** A offset base tree with uint32_t keys. */
+typedef AVLROOGCPTR         AVLROOGCPTRTREE;
+/** Pointer to an offset base tree with uint32_t keys. */
+typedef AVLROOGCPTRTREE    *PAVLROOGCPTRTREE;
+
+/** Pointer to an internal tree pointer.
+ * In this case it's a pointer to a relative offset. */
+typedef AVLROOGCPTRTREE    *PPAVLROOGCPTRNODECORE;
+
+/** Callback function for RTAvlrooGCPtrDoWithAll() and RTAvlrooGCPtrDestroy().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)   AVLROOGCPTRCALLBACK(PAVLROOGCPTRNODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvlrooGCPtrDoWithAll() and RTAvlrooGCPtrDestroy(). */
+typedef AVLROOGCPTRCALLBACK *PAVLROOGCPTRCALLBACK;
+
+RTDECL(bool)                    RTAvlrooGCPtrInsert(PAVLROOGCPTRTREE pTree, PAVLROOGCPTRNODECORE pNode);
+RTDECL(PAVLROOGCPTRNODECORE)    RTAvlrooGCPtrRemove(PAVLROOGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(PAVLROOGCPTRNODECORE)    RTAvlrooGCPtrGet(PAVLROOGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(PAVLROOGCPTRNODECORE)    RTAvlrooGCPtrGetBestFit(PAVLROOGCPTRTREE ppTree, RTGCPTR Key, bool fAbove);
+RTDECL(PAVLROOGCPTRNODECORE)    RTAvlrooGCPtrRangeGet(PAVLROOGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(PAVLROOGCPTRNODECORE)    RTAvlrooGCPtrRangeRemove(PAVLROOGCPTRTREE pTree, RTGCPTR Key);
+RTDECL(int)                     RTAvlrooGCPtrDoWithAll(PAVLROOGCPTRTREE pTree, int fFromLeft, PAVLROOGCPTRCALLBACK pfnCallBack, void *pvParam);
+RTDECL(int)                     RTAvlrooGCPtrDestroy(PAVLROOGCPTRTREE pTree, PAVLROOGCPTRCALLBACK pfnCallBack, void *pvParam);
+RTDECL(PAVLROOGCPTRNODECORE)    RTAvlrooGCPtrGetRoot(PAVLROOGCPTRTREE pTree);
+RTDECL(PAVLROOGCPTRNODECORE)    RTAvlrooGCPtrGetLeft(PAVLROOGCPTRNODECORE pNode);
+RTDECL(PAVLROOGCPTRNODECORE)    RTAvlrooGCPtrGetRight(PAVLROOGCPTRNODECORE pNode);
+RTDECL(PAVLROOGCPTRNODECORE)    RTAvlrooGCPtrGetNextEqual(PAVLROOGCPTRNODECORE pNode);
+
+/** @} */
+
+
+/** AVL tree of RTUINTPTR.
+ * @{
+ */
+
+/**
+ * AVL RTUINTPTR node core.
+ */
+typedef struct _AVLUIntPtrNodeCore
+{
+    /** Key value. */
+    RTUINTPTR                   Key;
+    /** Offset to the left leaf node, relative to this field. */
+    struct _AVLUIntPtrNodeCore *pLeft;
+    /** Offset to the right leaf node, relative to this field. */
+    struct _AVLUIntPtrNodeCore *pRight;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char               uchHeight;
+} AVLUINTPTRNODECORE;
+/** Pointer to a RTUINTPTR AVL node core.*/
+typedef AVLUINTPTRNODECORE *PAVLUINTPTRNODECORE;
+
+/** A pointer based tree with RTUINTPTR keys. */
+typedef PAVLUINTPTRNODECORE AVLUINTPTRTREE;
+/** Pointer to an offset base tree with RTUINTPTR keys. */
+typedef AVLUINTPTRTREE     *PAVLUINTPTRTREE;
+
+/** Pointer to an internal tree pointer.
+ * In this case it's a pointer to a pointer. */
+typedef AVLUINTPTRTREE     *PPAVLUINTPTRNODECORE;
+
+/** Callback function for RTAvlUIntPtrDoWithAll() and RTAvlUIntPtrDestroy().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)    AVLUINTPTRCALLBACK(PAVLUINTPTRNODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvlUIntPtrDoWithAll() and RTAvlUIntPtrDestroy(). */
+typedef AVLUINTPTRCALLBACK *PAVLUINTPTRCALLBACK;
+
+RTDECL(bool)                    RTAvlUIntPtrInsert(    PAVLUINTPTRTREE pTree, PAVLUINTPTRNODECORE pNode);
+RTDECL(PAVLUINTPTRNODECORE)     RTAvlUIntPtrRemove(    PAVLUINTPTRTREE pTree, RTUINTPTR Key);
+RTDECL(PAVLUINTPTRNODECORE)     RTAvlUIntPtrGet(       PAVLUINTPTRTREE pTree, RTUINTPTR Key);
+RTDECL(PAVLUINTPTRNODECORE)     RTAvlUIntPtrGetBestFit(PAVLUINTPTRTREE pTree, RTUINTPTR Key, bool fAbove);
+RTDECL(int)                     RTAvlUIntPtrDoWithAll( PAVLUINTPTRTREE pTree, int fFromLeft, PAVLUINTPTRCALLBACK pfnCallBack, void *pvParam);
+RTDECL(int)                     RTAvlUIntPtrDestroy(   PAVLUINTPTRTREE pTree, PAVLUINTPTRCALLBACK pfnCallBack, void *pvParam);
+RTDECL(PAVLUINTPTRNODECORE)     RTAvlUIntPtrGetRoot(   PAVLUINTPTRTREE pTree);
+RTDECL(PAVLUINTPTRNODECORE)     RTAvlUIntPtrGetLeft(   PAVLUINTPTRNODECORE pNode);
+RTDECL(PAVLUINTPTRNODECORE)     RTAvlUIntPtrGetRight(  PAVLUINTPTRNODECORE pNode);
+
+/** @} */
+
+
+/** AVL tree of RTUINTPTR ranges.
+ * @{
+ */
+
+/**
+ * AVL RTUINTPTR range node core.
+ */
+typedef struct _AVLRUIntPtrNodeCore
+{
+    /** First key value in the range (inclusive). */
+    RTUINTPTR                       Key;
+    /** Last key value in the range (inclusive). */
+    RTUINTPTR                       KeyLast;
+    /** Offset to the left leaf node, relative to this field. */
+    struct _AVLRUIntPtrNodeCore    *pLeft;
+    /** Offset to the right leaf node, relative to this field. */
+    struct _AVLRUIntPtrNodeCore    *pRight;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char                   uchHeight;
+} AVLRUINTPTRNODECORE;
+/** Pointer to an AVL RTUINTPTR range node code. */
+typedef AVLRUINTPTRNODECORE *PAVLRUINTPTRNODECORE;
+
+/** A pointer based tree with RTUINTPTR ranges. */
+typedef PAVLRUINTPTRNODECORE AVLRUINTPTRTREE;
+/** Pointer to a pointer based tree with RTUINTPTR ranges. */
+typedef AVLRUINTPTRTREE     *PAVLRUINTPTRTREE;
+
+/** Pointer to an internal tree pointer.
+ * In this case it's a pointer to a pointer. */
+typedef AVLRUINTPTRTREE     *PPAVLRUINTPTRNODECORE;
+
+/** Callback function for RTAvlrUIntPtrDoWithAll() and RTAvlrUIntPtrDestroy().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)    AVLRUINTPTRCALLBACK(PAVLRUINTPTRNODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvlrUIntPtrDoWithAll() and RTAvlrUIntPtrDestroy(). */
+typedef AVLRUINTPTRCALLBACK *PAVLRUINTPTRCALLBACK;
+
+RTDECL(bool)                   RTAvlrUIntPtrInsert(     PAVLRUINTPTRTREE pTree, PAVLRUINTPTRNODECORE pNode);
+RTDECL(PAVLRUINTPTRNODECORE)   RTAvlrUIntPtrRemove(     PAVLRUINTPTRTREE pTree, RTUINTPTR Key);
+RTDECL(PAVLRUINTPTRNODECORE)   RTAvlrUIntPtrGet(        PAVLRUINTPTRTREE pTree, RTUINTPTR Key);
+RTDECL(PAVLRUINTPTRNODECORE)   RTAvlrUIntPtrGetBestFit( PAVLRUINTPTRTREE pTree, RTUINTPTR Key, bool fAbove);
+RTDECL(PAVLRUINTPTRNODECORE)   RTAvlrUIntPtrRangeGet(   PAVLRUINTPTRTREE pTree, RTUINTPTR Key);
+RTDECL(PAVLRUINTPTRNODECORE)   RTAvlrUIntPtrRangeRemove(PAVLRUINTPTRTREE pTree, RTUINTPTR Key);
+RTDECL(int)                    RTAvlrUIntPtrDoWithAll(  PAVLRUINTPTRTREE pTree, int fFromLeft, PAVLRUINTPTRCALLBACK pfnCallBack, void *pvParam);
+RTDECL(int)                    RTAvlrUIntPtrDestroy(    PAVLRUINTPTRTREE pTree, PAVLRUINTPTRCALLBACK pfnCallBack, void *pvParam);
+RTDECL(PAVLRUINTPTRNODECORE)   RTAvlrUIntPtrGetRoot(    PAVLRUINTPTRTREE pTree);
+RTDECL(PAVLRUINTPTRNODECORE)   RTAvlrUIntPtrGetLeft(    PAVLRUINTPTRNODECORE pNode);
+RTDECL(PAVLRUINTPTRNODECORE)   RTAvlrUIntPtrGetRight(   PAVLRUINTPTRNODECORE pNode);
+
+/** @} */
+
+
+/** AVL tree of RTHCPHYSes - using relative offsets internally.
+ * @{
+ */
+
+/**
+ * AVL 'pointer' type for the relative offset pointer scheme.
+ */
+typedef int32_t     AVLOHCPHYS;
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLOHCPhysNodeCore
+{
+    /** Key value. */
+    RTHCPHYS            Key;
+    /** Offset to the left leaf node, relative to this field. */
+    AVLOHCPHYS          pLeft;
+    /** Offset to the right leaf node, relative to this field. */
+    AVLOHCPHYS          pRight;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char       uchHeight;
+#if HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64
+    unsigned char       Padding[7]; /**< Alignment padding. */
+#endif
+} AVLOHCPHYSNODECORE, *PAVLOHCPHYSNODECORE;
+
+/** A offset base tree with uint32_t keys. */
+typedef AVLOHCPHYS         AVLOHCPHYSTREE;
+/** Pointer to an offset base tree with uint32_t keys. */
+typedef AVLOHCPHYSTREE    *PAVLOHCPHYSTREE;
+
+/** Pointer to an internal tree pointer.
+ * In this case it's a pointer to a relative offset. */
+typedef AVLOHCPHYSTREE    *PPAVLOHCPHYSNODECORE;
+
+/** Callback function for RTAvloHCPhysDoWithAll() and RTAvloHCPhysDestroy().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)   AVLOHCPHYSCALLBACK(PAVLOHCPHYSNODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvloHCPhysDoWithAll() and RTAvloHCPhysDestroy(). */
+typedef AVLOHCPHYSCALLBACK *PAVLOHCPHYSCALLBACK;
+
+RTDECL(bool)                    RTAvloHCPhysInsert(PAVLOHCPHYSTREE pTree, PAVLOHCPHYSNODECORE pNode);
+RTDECL(PAVLOHCPHYSNODECORE)     RTAvloHCPhysRemove(PAVLOHCPHYSTREE pTree, RTHCPHYS Key);
+RTDECL(PAVLOHCPHYSNODECORE)     RTAvloHCPhysGet(PAVLOHCPHYSTREE pTree, RTHCPHYS Key);
+RTDECL(int)                     RTAvloHCPhysDoWithAll(PAVLOHCPHYSTREE pTree, int fFromLeft, PAVLOHCPHYSCALLBACK pfnCallBack, void *pvParam);
+RTDECL(PAVLOHCPHYSNODECORE)     RTAvloHCPhysGetBestFit(PAVLOHCPHYSTREE ppTree, RTHCPHYS Key, bool fAbove);
+RTDECL(PAVLOHCPHYSNODECORE)     RTAvloHCPhysRemoveBestFit(PAVLOHCPHYSTREE ppTree, RTHCPHYS Key, bool fAbove);
+RTDECL(int)                     RTAvloHCPhysDestroy(PAVLOHCPHYSTREE pTree, PAVLOHCPHYSCALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+
+
+/** AVL tree of RTIOPORTs - using relative offsets internally.
+ * @{
+ */
+
+/**
+ * AVL 'pointer' type for the relative offset pointer scheme.
+ */
+typedef int32_t     AVLOIOPORTPTR;
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLOIOPortNodeCore
+{
+    /** Offset to the left leaf node, relative to this field. */
+    AVLOIOPORTPTR       pLeft;
+    /** Offset to the right leaf node, relative to this field. */
+    AVLOIOPORTPTR       pRight;
+    /** Key value. */
+    RTIOPORT            Key;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char       uchHeight;
+} AVLOIOPORTNODECORE, *PAVLOIOPORTNODECORE;
+
+/** A offset base tree with uint32_t keys. */
+typedef AVLOIOPORTPTR      AVLOIOPORTTREE;
+/** Pointer to an offset base tree with uint32_t keys. */
+typedef AVLOIOPORTTREE    *PAVLOIOPORTTREE;
+
+/** Pointer to an internal tree pointer.
+ * In this case it's a pointer to a relative offset. */
+typedef AVLOIOPORTTREE    *PPAVLOIOPORTNODECORE;
+
+/** Callback function for RTAvloIOPortDoWithAll() and RTAvloIOPortDestroy().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)   AVLOIOPORTCALLBACK(PAVLOIOPORTNODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvloIOPortDoWithAll() and RTAvloIOPortDestroy(). */
+typedef AVLOIOPORTCALLBACK *PAVLOIOPORTCALLBACK;
+
+RTDECL(bool)                    RTAvloIOPortInsert(PAVLOIOPORTTREE pTree, PAVLOIOPORTNODECORE pNode);
+RTDECL(PAVLOIOPORTNODECORE)     RTAvloIOPortRemove(PAVLOIOPORTTREE pTree, RTIOPORT Key);
+RTDECL(PAVLOIOPORTNODECORE)     RTAvloIOPortGet(PAVLOIOPORTTREE pTree, RTIOPORT Key);
+RTDECL(int)                     RTAvloIOPortDoWithAll(PAVLOIOPORTTREE pTree, int fFromLeft, PAVLOIOPORTCALLBACK pfnCallBack, void *pvParam);
+RTDECL(PAVLOIOPORTNODECORE)     RTAvloIOPortGetBestFit(PAVLOIOPORTTREE ppTree, RTIOPORT Key, bool fAbove);
+RTDECL(PAVLOIOPORTNODECORE)     RTAvloIOPortRemoveBestFit(PAVLOIOPORTTREE ppTree, RTIOPORT Key, bool fAbove);
+RTDECL(int)                     RTAvloIOPortDestroy(PAVLOIOPORTTREE pTree, PAVLOIOPORTCALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+
+/** AVL tree of RTIOPORT ranges - using relative offsets internally.
+ * @{
+ */
+
+/**
+ * AVL 'pointer' type for the relative offset pointer scheme.
+ */
+typedef int32_t     AVLROIOPORTPTR;
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLROIOPortNodeCore
+{
+    /** First key value in the range (inclusive). */
+    RTIOPORT            Key;
+    /** Last key value in the range (inclusive). */
+    RTIOPORT            KeyLast;
+    /** Offset to the left leaf node, relative to this field. */
+    AVLROIOPORTPTR      pLeft;
+    /** Offset to the right leaf node, relative to this field. */
+    AVLROIOPORTPTR      pRight;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char       uchHeight;
+} AVLROIOPORTNODECORE, *PAVLROIOPORTNODECORE;
+
+/** A offset base tree with uint32_t keys. */
+typedef AVLROIOPORTPTR      AVLROIOPORTTREE;
+/** Pointer to an offset base tree with uint32_t keys. */
+typedef AVLROIOPORTTREE    *PAVLROIOPORTTREE;
+
+/** Pointer to an internal tree pointer.
+ * In this case it's a pointer to a relative offset. */
+typedef AVLROIOPORTTREE    *PPAVLROIOPORTNODECORE;
+
+/** Callback function for RTAvlroIOPortDoWithAll() and RTAvlroIOPortDestroy().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)   AVLROIOPORTCALLBACK(PAVLROIOPORTNODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvlroIOPortDoWithAll() and RTAvlroIOPortDestroy(). */
+typedef AVLROIOPORTCALLBACK *PAVLROIOPORTCALLBACK;
+
+RTDECL(bool)                    RTAvlroIOPortInsert(PAVLROIOPORTTREE pTree, PAVLROIOPORTNODECORE pNode);
+RTDECL(PAVLROIOPORTNODECORE)    RTAvlroIOPortRemove(PAVLROIOPORTTREE pTree, RTIOPORT Key);
+RTDECL(PAVLROIOPORTNODECORE)    RTAvlroIOPortGet(PAVLROIOPORTTREE pTree, RTIOPORT Key);
+RTDECL(PAVLROIOPORTNODECORE)    RTAvlroIOPortRangeGet(PAVLROIOPORTTREE pTree, RTIOPORT Key);
+RTDECL(PAVLROIOPORTNODECORE)    RTAvlroIOPortRangeRemove(PAVLROIOPORTTREE pTree, RTIOPORT Key);
+RTDECL(int)                     RTAvlroIOPortDoWithAll(PAVLROIOPORTTREE pTree, int fFromLeft, PAVLROIOPORTCALLBACK pfnCallBack, void *pvParam);
+RTDECL(int)                     RTAvlroIOPortDestroy(PAVLROIOPORTTREE pTree, PAVLROIOPORTCALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+
+/** AVL tree of RTHCPHYSes.
+ * @{
+ */
+
+/**
+ * AVL 'pointer' type for the relative offset pointer scheme.
+ */
+typedef struct _AVLHCPhysNodeCore  *AVLHCPHYSPTR;
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLHCPhysNodeCore
+{
+    /** Offset to the left leaf node, relative to this field. */
+    AVLHCPHYSPTR        pLeft;
+    /** Offset to the right leaf node, relative to this field. */
+    AVLHCPHYSPTR        pRight;
+    /** Key value. */
+    RTHCPHYS            Key;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char       uchHeight;
+} AVLHCPHYSNODECORE, *PAVLHCPHYSNODECORE;
+
+/** A offset base tree with RTHCPHYS keys. */
+typedef AVLHCPHYSPTR      AVLHCPHYSTREE;
+/** Pointer to an offset base tree with RTHCPHYS keys. */
+typedef AVLHCPHYSTREE    *PAVLHCPHYSTREE;
+
+/** Pointer to an internal tree pointer.
+ * In this case it's a pointer to a relative offset. */
+typedef AVLHCPHYSTREE    *PPAVLHCPHYSNODECORE;
+
+/** Callback function for RTAvlHCPhysDoWithAll() and RTAvlHCPhysDestroy().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)   AVLHCPHYSCALLBACK(PAVLHCPHYSNODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvlHCPhysDoWithAll() and RTAvlHCPhysDestroy(). */
+typedef AVLHCPHYSCALLBACK *PAVLHCPHYSCALLBACK;
+
+RTDECL(bool)                    RTAvlHCPhysInsert(PAVLHCPHYSTREE pTree, PAVLHCPHYSNODECORE pNode);
+RTDECL(PAVLHCPHYSNODECORE)      RTAvlHCPhysRemove(PAVLHCPHYSTREE pTree, RTHCPHYS Key);
+RTDECL(PAVLHCPHYSNODECORE)      RTAvlHCPhysGet(PAVLHCPHYSTREE pTree, RTHCPHYS Key);
+RTDECL(int)                     RTAvlHCPhysDoWithAll(PAVLHCPHYSTREE pTree, int fFromLeft, PAVLHCPHYSCALLBACK pfnCallBack, void *pvParam);
+RTDECL(PAVLHCPHYSNODECORE)      RTAvlHCPhysGetBestFit(PAVLHCPHYSTREE ppTree, RTHCPHYS Key, bool fAbove);
+RTDECL(PAVLHCPHYSNODECORE)      RTAvlHCPhysRemoveBestFit(PAVLHCPHYSTREE ppTree, RTHCPHYS Key, bool fAbove);
+RTDECL(int)                     RTAvlHCPhysDestroy(PAVLHCPHYSTREE pTree, PAVLHCPHYSCALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+/** AVL tree of RTGCPHYSes.
+ * @{
+ */
+
+/**
+ * AVL 'pointer' type for the relative offset pointer scheme.
+ */
+typedef struct _AVLGCPhysNodeCore  *AVLGCPHYSPTR;
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLGCPhysNodeCore
+{
+    /** Offset to the left leaf node, relative to this field. */
+    AVLGCPHYSPTR        pLeft;
+    /** Offset to the right leaf node, relative to this field. */
+    AVLGCPHYSPTR        pRight;
+    /** Key value. */
+    RTGCPHYS            Key;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char       uchHeight;
+} AVLGCPHYSNODECORE, *PAVLGCPHYSNODECORE;
+
+/** A offset base tree with RTGCPHYS keys. */
+typedef AVLGCPHYSPTR      AVLGCPHYSTREE;
+/** Pointer to an offset base tree with RTGCPHYS keys. */
+typedef AVLGCPHYSTREE    *PAVLGCPHYSTREE;
+
+/** Pointer to an internal tree pointer.
+ * In this case it's a pointer to a relative offset. */
+typedef AVLGCPHYSTREE    *PPAVLGCPHYSNODECORE;
+
+/** Callback function for RTAvlGCPhysDoWithAll() and RTAvlGCPhysDestroy().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)   AVLGCPHYSCALLBACK(PAVLGCPHYSNODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvlGCPhysDoWithAll() and RTAvlGCPhysDestroy(). */
+typedef AVLGCPHYSCALLBACK *PAVLGCPHYSCALLBACK;
+
+RTDECL(bool)                    RTAvlGCPhysInsert(PAVLGCPHYSTREE pTree, PAVLGCPHYSNODECORE pNode);
+RTDECL(PAVLGCPHYSNODECORE)      RTAvlGCPhysRemove(PAVLGCPHYSTREE pTree, RTGCPHYS Key);
+RTDECL(PAVLGCPHYSNODECORE)      RTAvlGCPhysGet(PAVLGCPHYSTREE pTree, RTGCPHYS Key);
+RTDECL(int)                     RTAvlGCPhysDoWithAll(PAVLGCPHYSTREE pTree, int fFromLeft, PAVLGCPHYSCALLBACK pfnCallBack, void *pvParam);
+RTDECL(PAVLGCPHYSNODECORE)      RTAvlGCPhysGetBestFit(PAVLGCPHYSTREE ppTree, RTGCPHYS Key, bool fAbove);
+RTDECL(PAVLGCPHYSNODECORE)      RTAvlGCPhysRemoveBestFit(PAVLGCPHYSTREE ppTree, RTGCPHYS Key, bool fAbove);
+RTDECL(int)                     RTAvlGCPhysDestroy(PAVLGCPHYSTREE pTree, PAVLGCPHYSCALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+
+/** AVL tree of RTFOFF ranges.
+ * @{
+ */
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLRFOFFNodeCore
+{
+    /** First key value in the range (inclusive). */
+    RTFOFF             Key;
+    /** Last key value in the range (inclusive). */
+    RTFOFF             KeyLast;
+    /** Offset to the left leaf node, relative to this field. */
+    struct _AVLRFOFFNodeCore  *pLeft;
+    /** Offset to the right leaf node, relative to this field. */
+    struct _AVLRFOFFNodeCore  *pRight;
+    /** Height of this tree: max(height(left), height(right)) + 1 */
+    unsigned char       uchHeight;
+} AVLRFOFFNODECORE, *PAVLRFOFFNODECORE;
+
+/** A pointer based tree with RTFOFF ranges. */
+typedef PAVLRFOFFNODECORE AVLRFOFFTREE;
+/** Pointer to a pointer based tree with RTFOFF ranges. */
+typedef AVLRFOFFTREE    *PAVLRFOFFTREE;
+
+/** Pointer to an internal tree pointer.
+ * In this case it's a pointer to a relative offset. */
+typedef AVLRFOFFTREE    *PPAVLRFOFFNODECORE;
+
+/** Callback function for RTAvlrGCPtrDoWithAll() and RTAvlrGCPtrDestroy().
+ *  @returns IPRT status codes. */
+typedef DECLCALLBACK(int)   AVLRFOFFCALLBACK(PAVLRFOFFNODECORE pNode, void *pvUser);
+/** Pointer to callback function for RTAvlrGCPtrDoWithAll() and RTAvlrGCPtrDestroy(). */
+typedef AVLRFOFFCALLBACK *PAVLRFOFFCALLBACK;
+
+RTDECL(bool)                  RTAvlrFileOffsetInsert(       PAVLRFOFFTREE pTree, PAVLRFOFFNODECORE pNode);
+RTDECL(PAVLRFOFFNODECORE)     RTAvlrFileOffsetRemove(       PAVLRFOFFTREE pTree, RTFOFF Key);
+RTDECL(PAVLRFOFFNODECORE)     RTAvlrFileOffsetGet(          PAVLRFOFFTREE pTree, RTFOFF Key);
+RTDECL(PAVLRFOFFNODECORE)     RTAvlrFileOffsetGetBestFit(   PAVLRFOFFTREE pTree, RTFOFF Key, bool fAbove);
+RTDECL(PAVLRFOFFNODECORE)     RTAvlrFileOffsetRangeGet(     PAVLRFOFFTREE pTree, RTFOFF Key);
+RTDECL(PAVLRFOFFNODECORE)     RTAvlrFileOffsetRangeRemove(  PAVLRFOFFTREE pTree, RTFOFF Key);
+RTDECL(int)                   RTAvlrFileOffsetDoWithAll(    PAVLRFOFFTREE pTree, int fFromLeft, PAVLRFOFFCALLBACK pfnCallBack, void *pvParam);
+RTDECL(int)                   RTAvlrFileOffsetDestroy(      PAVLRFOFFTREE pTree, PAVLRFOFFCALLBACK pfnCallBack, void *pvParam);
+RTDECL(PAVLRFOFFNODECORE)     RTAvlrFileOffsetGetRoot(      PAVLRFOFFTREE pTree);
+RTDECL(PAVLRFOFFNODECORE)     RTAvlrFileOffsetGetLeft(      PAVLRFOFFNODECORE pNode);
+RTDECL(PAVLRFOFFNODECORE)     RTAvlrFileOffsetGetRight(     PAVLRFOFFNODECORE pNode);
+
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/cdefs.h b/ubuntu/vbox/include/iprt/cdefs.h
new file mode 100644 (file)
index 0000000..5fca8bc
--- /dev/null
@@ -0,0 +1,3801 @@
+/** @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.
+ */
+
+#ifndef ___iprt_cdefs_h
+#define ___iprt_cdefs_h
+
+
+/** @defgroup grp_rt_cdefs  IPRT Common Definitions and Macros
+ * @{
+ */
+
+/** @def RT_C_DECLS_BEGIN
+ * Used to start a block of function declarations which are shared
+ * between C and C++ program.
+ */
+
+/** @def RT_C_DECLS_END
+ * Used to end a block of function declarations which are shared
+ * between C and C++ program.
+ */
+
+#if defined(__cplusplus)
+# define RT_C_DECLS_BEGIN extern "C" {
+# define RT_C_DECLS_END   }
+#else
+# define RT_C_DECLS_BEGIN
+# define RT_C_DECLS_END
+#endif
+
+
+/*
+ * Shut up DOXYGEN warnings and guide it properly thru the code.
+ */
+#ifdef DOXYGEN_RUNNING
+# define __AMD64__
+# define __X86__
+# define RT_ARCH_AMD64
+# define RT_ARCH_X86
+# define RT_ARCH_SPARC
+# define RT_ARCH_SPARC64
+# define IN_RING0
+# define IN_RING3
+# define IN_RC
+# define IN_RC
+# define IN_RT_RC
+# define IN_RT_R0
+# define IN_RT_R3
+# define IN_RT_STATIC
+# define RT_STRICT
+# define RT_NO_STRICT
+# define RT_LOCK_STRICT
+# define RT_LOCK_NO_STRICT
+# define RT_LOCK_STRICT_ORDER
+# define RT_LOCK_NO_STRICT_ORDER
+# define RT_BREAKPOINT
+# define RT_NO_DEPRECATED_MACROS
+# define RT_EXCEPTIONS_ENABLED
+# define RT_BIG_ENDIAN
+# define RT_LITTLE_ENDIAN
+# define RT_COMPILER_GROKS_64BIT_BITFIELDS
+# define RT_COMPILER_WITH_80BIT_LONG_DOUBLE
+# define RT_NO_VISIBILITY_HIDDEN
+# define RT_GCC_SUPPORTS_VISIBILITY_HIDDEN
+# define RT_COMPILER_SUPPORTS_VA_ARGS
+# define RT_COMPILER_SUPPORTS_LAMBDA
+#endif /* DOXYGEN_RUNNING */
+
+/** @def RT_ARCH_X86
+ * Indicates that we're compiling for the X86 architecture.
+ */
+
+/** @def RT_ARCH_AMD64
+ * Indicates that we're compiling for the AMD64 architecture.
+ */
+
+/** @def RT_ARCH_SPARC
+ * Indicates that we're compiling for the SPARC V8 architecture (32-bit).
+ */
+
+/** @def RT_ARCH_SPARC64
+ * Indicates that we're compiling for the SPARC V9 architecture (64-bit).
+ */
+#if !defined(RT_ARCH_X86) \
+ && !defined(RT_ARCH_AMD64) \
+ && !defined(RT_ARCH_SPARC) \
+ && !defined(RT_ARCH_SPARC64) \
+ && !defined(RT_ARCH_ARM)
+# if defined(__amd64__) || defined(__x86_64__) || defined(_M_X64) || defined(__AMD64__)
+#  define RT_ARCH_AMD64
+# elif defined(__i386__) || defined(_M_IX86) || defined(__X86__)
+#  define RT_ARCH_X86
+# elif defined(__sparcv9)
+#  define RT_ARCH_SPARC64
+# elif defined(__sparc__)
+#  define RT_ARCH_SPARC
+# elif defined(__arm__) || defined(__arm32__)
+#  define RT_ARCH_ARM
+# else /* PORTME: append test for new archs. */
+#  error "Check what predefined macros your compiler uses to indicate architecture."
+# endif
+/* PORTME: append new archs checks. */
+#elif defined(RT_ARCH_X86) && defined(RT_ARCH_AMD64)
+# error "Both RT_ARCH_X86 and RT_ARCH_AMD64 cannot be defined at the same time!"
+#elif defined(RT_ARCH_X86) && defined(RT_ARCH_SPARC)
+# error "Both RT_ARCH_X86 and RT_ARCH_SPARC cannot be defined at the same time!"
+#elif defined(RT_ARCH_X86) && defined(RT_ARCH_SPARC64)
+# error "Both RT_ARCH_X86 and RT_ARCH_SPARC64 cannot be defined at the same time!"
+#elif defined(RT_ARCH_AMD64) && defined(RT_ARCH_SPARC)
+# error "Both RT_ARCH_AMD64 and RT_ARCH_SPARC cannot be defined at the same time!"
+#elif defined(RT_ARCH_AMD64) && defined(RT_ARCH_SPARC64)
+# error "Both RT_ARCH_AMD64 and RT_ARCH_SPARC64 cannot be defined at the same time!"
+#elif defined(RT_ARCH_SPARC) && defined(RT_ARCH_SPARC64)
+# error "Both RT_ARCH_SPARC and RT_ARCH_SPARC64 cannot be defined at the same time!"
+#elif defined(RT_ARCH_ARM) && defined(RT_ARCH_AMD64)
+# error "Both RT_ARCH_ARM and RT_ARCH_AMD64 cannot be defined at the same time!"
+#elif defined(RT_ARCH_ARM) && defined(RT_ARCH_X86)
+# error "Both RT_ARCH_ARM and RT_ARCH_X86 cannot be defined at the same time!"
+#elif defined(RT_ARCH_ARM) && defined(RT_ARCH_SPARC64)
+# error "Both RT_ARCH_ARM and RT_ARCH_SPARC64 cannot be defined at the same time!"
+#elif defined(RT_ARCH_ARM) && defined(RT_ARCH_SPARC)
+# error "Both RT_ARCH_ARM and RT_ARCH_SPARC cannot be defined at the same time!"
+#endif
+
+/* Final check (PORTME). */
+#if    (defined(RT_ARCH_X86) != 0) \
+     + (defined(RT_ARCH_AMD64) != 0) \
+     + (defined(RT_ARCH_SPARC) != 0) \
+     + (defined(RT_ARCH_SPARC64) != 0) \
+     + (defined(RT_ARCH_ARM) != 0) \
+  != 1
+# error "Exactly one RT_ARCH_XXX macro shall be defined"
+#endif
+
+/** @def RT_GNUC_PREREQ
+ * Shorter than fiddling with __GNUC__ and __GNUC_MINOR__.
+ *
+ * @param   a_MinMajor      Minimum major version
+ * @param   a_MinMinor      The minor version number part.
+ */
+#define RT_GNUC_PREREQ(a_MinMajor, a_MinMinor)      RT_GNUC_PREREQ_EX(a_MinMajor, a_MinMinor, 0)
+/** @def RT_GNUC_PREREQ_EX
+ * Simplified way of checking __GNUC__ and __GNUC_MINOR__ regardless of actual
+ * compiler used, returns @a a_OtherRet for other compilers.
+ *
+ * @param   a_MinMajor      Minimum major version
+ * @param   a_MinMinor      The minor version number part.
+ * @param   a_OtherRet      What to return for non-GCC compilers.
+ */
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define RT_GNUC_PREREQ_EX(a_MinMajor, a_MinMinor, a_OtherRet) \
+    ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((a_MinMajor) << 16) + (a_MinMinor))
+#else
+# define RT_GNUC_PREREQ_EX(a_MinMajor, a_MinMinor, a_OtherRet) (a_OtherRet)
+#endif
+
+/** @def RT_MSC_PREREQ
+ * Convenient way of checking _MSC_VER regardless of actual compiler used
+ * (returns false if not MSC).
+ *
+ * @param   a_MinVer        Preferably a RT_MSC_VER_XXX value.
+ */
+#define RT_MSC_PREREQ(a_MinVer)                     RT_MSC_PREREQ_EX(a_MinVer, 0)
+/** @def RT_MSC_PREREQ_EX
+ * Convenient way of checking _MSC_VER regardless of actual compiler used,
+ * returns @a a_OtherRet for other compilers.
+ *
+ * @param   a_MinVer        Preferably a RT_MSC_VER_XXX value.
+ * @param   a_OtherRet      What to return for non-MSC compilers.
+ */
+#if defined(_MSC_VER)
+# define RT_MSC_PREREQ_EX(a_MinVer, a_OtherRet)     ( (_MSC_VER) >= (a_MinVer) )
+#else
+# define RT_MSC_PREREQ_EX(a_MinVer, a_OtherRet)     (a_OtherRet)
+#endif
+/** @name RT_MSC_VER_XXX - _MSC_VER values to use with RT_MSC_PREREQ.
+ * @remarks The VCxxx values are derived from the CRT DLLs shipping with the
+ *          compilers.
+ * @{ */
+#define RT_MSC_VER_VC50     (1100)              /**< Visual C++ 5.0. */
+#define RT_MSC_VER_VC60     (1200)              /**< Visual C++ 6.0. */
+#define RT_MSC_VER_VC70     (1300)              /**< Visual C++ 7.0. */
+#define RT_MSC_VER_VC70     (1300)              /**< Visual C++ 7.0. */
+#define RT_MSC_VER_VS2003   (1310)              /**< Visual Studio 2003, aka Visual C++ 7.1. */
+#define RT_MSC_VER_VC71     RT_MSC_VER_VS2003   /**< Visual C++ 7.1, aka Visual Studio 2003. */
+#define RT_MSC_VER_VS2005   (1400)              /**< Visual Studio 2005. */
+#define RT_MSC_VER_VC80     RT_MSC_VER_VS2005   /**< Visual C++ 8.0, aka Visual Studio 2008. */
+#define RT_MSC_VER_VS2008   (1500)              /**< Visual Studio 2008. */
+#define RT_MSC_VER_VC90     RT_MSC_VER_VS2008   /**< Visual C++ 9.0, aka Visual Studio 2008. */
+#define RT_MSC_VER_VS2010   (1600)              /**< Visual Studio 2010. */
+#define RT_MSC_VER_VC100    RT_MSC_VER_VS2010   /**< Visual C++ 10.0, aka Visual Studio 2010. */
+#define RT_MSC_VER_VS2012   (1700)              /**< Visual Studio 2012. */
+#define RT_MSC_VER_VC110    RT_MSC_VER_VS2012   /**< Visual C++ 11.0, aka Visual Studio 2012. */
+#define RT_MSC_VER_VS2013   (1800)              /**< Visual Studio 2013. */
+#define RT_MSC_VER_VC120    RT_MSC_VER_VS2013   /**< Visual C++ 12.0, aka Visual Studio 2013. */
+#define RT_MSC_VER_VS2015   (1900)              /**< Visual Studio 2015. */
+#define RT_MSC_VER_VC140    RT_MSC_VER_VS2015   /**< Visual C++ 14.0, aka Visual Studio 2015. */
+/** @} */
+
+/** @def RT_CLANG_PREREQ
+ * Shorter than fiddling with __clang_major__ and __clang_minor__.
+ *
+ * @param   a_MinMajor      Minimum major version
+ * @param   a_MinMinor      The minor version number part.
+ */
+#define RT_CLANG_PREREQ(a_MinMajor, a_MinMinor)      RT_CLANG_PREREQ_EX(a_MinMajor, a_MinMinor, 0)
+/** @def RT_CLANG_PREREQ_EX
+ * Simplified way of checking __clang_major__ and __clang_minor__ regardless of
+ * actual compiler used, returns @a a_OtherRet for other compilers.
+ *
+ * @param   a_MinMajor      Minimum major version
+ * @param   a_MinMinor      The minor version number part.
+ * @param   a_OtherRet      What to return for non-GCC compilers.
+ */
+#if defined(__clang_major__) && defined(__clang_minor__)
+# define RT_CLANG_PREREQ_EX(a_MinMajor, a_MinMinor, a_OtherRet) \
+    ((__clang_major__ << 16) + __clang_minor__ >= ((a_MinMajor) << 16) + (a_MinMinor))
+#else
+# define RT_CLANG_PREREQ_EX(a_MinMajor, a_MinMinor, a_OtherRet) (a_OtherRet)
+#endif
+
+
+/** @def __X86__
+ * Indicates that we're compiling for the X86 architecture.
+ * @deprecated
+ */
+
+/** @def __AMD64__
+ * Indicates that we're compiling for the AMD64 architecture.
+ * @deprecated
+ */
+#if !defined(__X86__) && !defined(__AMD64__) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
+# if defined(RT_ARCH_AMD64)
+#  define __AMD64__
+# elif defined(RT_ARCH_X86)
+#  define __X86__
+# else
+#  error "Check what predefined macros your compiler uses to indicate architecture."
+# endif
+#elif defined(__X86__) && defined(__AMD64__)
+# error "Both __X86__ and __AMD64__ cannot be defined at the same time!"
+#elif defined(__X86__) && !defined(RT_ARCH_X86)
+# error "__X86__ without RT_ARCH_X86!"
+#elif defined(__AMD64__) && !defined(RT_ARCH_AMD64)
+# error "__AMD64__ without RT_ARCH_AMD64!"
+#endif
+
+/** @def RT_BIG_ENDIAN
+ * Defined if the architecture is big endian.  */
+/** @def RT_LITTLE_ENDIAN
+ * Defined if the architecture is little endian.  */
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) || defined(RT_ARCH_ARM)
+# define RT_LITTLE_ENDIAN
+#elif defined(RT_ARCH_SPARC) || defined(RT_ARCH_SPARC64)
+# define RT_BIG_ENDIAN
+#else
+# error "PORTME: architecture endianess"
+#endif
+#if defined(RT_BIG_ENDIAN) && defined(RT_LITTLE_ENDIAN)
+# error "Both RT_BIG_ENDIAN and RT_LITTLE_ENDIAN are defined"
+#endif
+
+
+/** @def IN_RING0
+ * Used to indicate that we're compiling code which is running
+ * in Ring-0 Host Context.
+ */
+
+/** @def IN_RING3
+ * Used to indicate that we're compiling code which is running
+ * in Ring-3 Host Context.
+ */
+
+/** @def IN_RC
+ * Used to indicate that we're compiling code which is running
+ * in the Raw-mode Context (implies R0).
+ */
+#if !defined(IN_RING3) && !defined(IN_RING0) && !defined(IN_RC) && !defined(IN_RC)
+# error "You must define which context the compiled code should run in; IN_RING3, IN_RING0 or IN_RC"
+#endif
+#if (defined(IN_RING3) && (defined(IN_RING0) || defined(IN_RC)) ) \
+ || (defined(IN_RING0) && (defined(IN_RING3) || defined(IN_RC)) ) \
+ || (defined(IN_RC)    && (defined(IN_RING3) || defined(IN_RING0)) )
+# error "Only one of the IN_RING3, IN_RING0, IN_RC defines should be defined."
+#endif
+
+
+/** @def ARCH_BITS
+ * Defines the bit count of the current context.
+ */
+#if !defined(ARCH_BITS) || defined(DOXYGEN_RUNNING)
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_SPARC64)
+#  define ARCH_BITS 64
+# elif !defined(__I86__) || !defined(__WATCOMC__)
+#  define ARCH_BITS 32
+# else
+#  define ARCH_BITS 16
+# endif
+#endif
+
+/* ARCH_BITS validation (PORTME). */
+#if ARCH_BITS == 64
+ #if defined(RT_ARCH_X86) || defined(RT_ARCH_SPARC) || defined(RT_ARCH_ARM)
+ # error "ARCH_BITS=64 but non-64-bit RT_ARCH_XXX defined."
+ #endif
+ #if !defined(RT_ARCH_AMD64) && !defined(RT_ARCH_SPARC64)
+ # error "ARCH_BITS=64 but no 64-bit RT_ARCH_XXX defined."
+ #endif
+
+#elif ARCH_BITS == 32
+ #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_SPARC64)
+ # error "ARCH_BITS=32 but non-32-bit RT_ARCH_XXX defined."
+ #endif
+ #if !defined(RT_ARCH_X86) && !defined(RT_ARCH_SPARC) && !defined(RT_ARCH_ARM)
+ # error "ARCH_BITS=32 but no 32-bit RT_ARCH_XXX defined."
+ #endif
+
+#elif ARCH_BITS == 16
+ #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_SPARC) || defined(RT_ARCH_SPARC64) || defined(RT_ARCH_ARM)
+ # error "ARCH_BITS=16 but non-16-bit RT_ARCH_XX defined."
+ #endif
+ #if !defined(RT_ARCH_X86)
+ # error "ARCH_BITS=16 but RT_ARCH_X86 isn't defined."
+ #endif
+
+#else
+# error "Unsupported ARCH_BITS value!"
+#endif
+
+/** @def HC_ARCH_BITS
+ * Defines the host architecture bit count.
+ */
+#if !defined(HC_ARCH_BITS) || defined(DOXYGEN_RUNNING)
+# ifndef IN_RC
+#  define HC_ARCH_BITS ARCH_BITS
+# else
+#  define HC_ARCH_BITS 32
+# endif
+#endif
+
+/** @def GC_ARCH_BITS
+ * Defines the guest architecture bit count.
+ */
+#if !defined(GC_ARCH_BITS) && !defined(DOXYGEN_RUNNING)
+# ifdef VBOX_WITH_64_BITS_GUESTS
+#  define GC_ARCH_BITS  64
+# else
+#  define GC_ARCH_BITS  32
+# endif
+#endif
+
+/** @def R3_ARCH_BITS
+ * Defines the host ring-3 architecture bit count.
+ */
+#if !defined(R3_ARCH_BITS) || defined(DOXYGEN_RUNNING)
+# ifdef IN_RING3
+#  define R3_ARCH_BITS ARCH_BITS
+# else
+#  define R3_ARCH_BITS HC_ARCH_BITS
+# endif
+#endif
+
+/** @def R0_ARCH_BITS
+ * Defines the host ring-0 architecture bit count.
+ */
+#if !defined(R0_ARCH_BITS) || defined(DOXYGEN_RUNNING)
+# ifdef IN_RING0
+#  define R0_ARCH_BITS ARCH_BITS
+# else
+#  define R0_ARCH_BITS HC_ARCH_BITS
+# endif
+#endif
+
+/** @def GC_ARCH_BITS
+ * Defines the guest architecture bit count.
+ */
+#if !defined(GC_ARCH_BITS) || defined(DOXYGEN_RUNNING)
+# ifdef IN_RC
+#  define GC_ARCH_BITS ARCH_BITS
+# else
+#  define GC_ARCH_BITS 32
+# endif
+#endif
+
+
+
+/** @name RT_OPSYS_XXX - Operative System Identifiers.
+ * These are the value that the RT_OPSYS \#define can take. @{
+ */
+/** Unknown OS. */
+#define RT_OPSYS_UNKNOWN    0
+/** OS Agnostic. */
+#define RT_OPSYS_AGNOSTIC   1
+/** Darwin - aka Mac OS X. */
+#define RT_OPSYS_DARWIN     2
+/** DragonFly BSD. */
+#define RT_OPSYS_DRAGONFLY  3
+/** DOS. */
+#define RT_OPSYS_DOS        4
+/** FreeBSD. */
+#define RT_OPSYS_FREEBSD    5
+/** Haiku. */
+#define RT_OPSYS_HAIKU      6
+/** Linux. */
+#define RT_OPSYS_LINUX      7
+/** L4. */
+#define RT_OPSYS_L4         8
+/** Minix. */
+#define RT_OPSYS_MINIX      9
+/** NetBSD. */
+#define RT_OPSYS_NETBSD     11
+/** Netware. */
+#define RT_OPSYS_NETWARE    12
+/** NT (native). */
+#define RT_OPSYS_NT         13
+/** OpenBSD. */
+#define RT_OPSYS_OPENBSD    14
+/** OS/2. */
+#define RT_OPSYS_OS2        15
+/** Plan 9. */
+#define RT_OPSYS_PLAN9      16
+/** QNX. */
+#define RT_OPSYS_QNX        17
+/** Solaris. */
+#define RT_OPSYS_SOLARIS    18
+/** UEFI. */
+#define RT_OPSYS_UEFI       19
+/** Windows. */
+#define RT_OPSYS_WINDOWS    20
+/** The max RT_OPSYS_XXX value (exclusive). */
+#define RT_OPSYS_MAX        21
+/** @} */
+
+/** @def RT_OPSYS
+ * Indicates which OS we're targeting. It's a \#define with is
+ * assigned one of the RT_OPSYS_XXX defines above.
+ *
+ * So to test if we're on FreeBSD do the following:
+ * @code
+ *  #if RT_OPSYS == RT_OPSYS_FREEBSD
+ *  some_funky_freebsd_specific_stuff();
+ *  #endif
+ * @endcode
+ */
+
+/*
+ * Set RT_OPSYS_XXX according to RT_OS_XXX.
+ *
+ * Search:  #define RT_OPSYS_([A-Z0-9]+) .*
+ * Replace: # elif defined(RT_OS_\1)\n#  define RT_OPSYS RT_OPSYS_\1
+ */
+#ifndef RT_OPSYS
+# if defined(RT_OS_UNKNOWN) || defined(DOXYGEN_RUNNING)
+#  define RT_OPSYS RT_OPSYS_UNKNOWN
+# elif defined(RT_OS_AGNOSTIC)
+#  define RT_OPSYS RT_OPSYS_AGNOSTIC
+# elif defined(RT_OS_DARWIN)
+#  define RT_OPSYS RT_OPSYS_DARWIN
+# elif defined(RT_OS_DRAGONFLY)
+#  define RT_OPSYS RT_OPSYS_DRAGONFLY
+# elif defined(RT_OS_DOS)
+#  define RT_OPSYS RT_OPSYS_DOS
+# elif defined(RT_OS_FREEBSD)
+#  define RT_OPSYS RT_OPSYS_FREEBSD
+# elif defined(RT_OS_HAIKU)
+#  define RT_OPSYS RT_OPSYS_HAIKU
+# elif defined(RT_OS_LINUX)
+#  define RT_OPSYS RT_OPSYS_LINUX
+# elif defined(RT_OS_L4)
+#  define RT_OPSYS RT_OPSYS_L4
+# elif defined(RT_OS_MINIX)
+#  define RT_OPSYS RT_OPSYS_MINIX
+# elif defined(RT_OS_NETBSD)
+#  define RT_OPSYS RT_OPSYS_NETBSD
+# elif defined(RT_OS_NETWARE)
+#  define RT_OPSYS RT_OPSYS_NETWARE
+# elif defined(RT_OS_NT)
+#  define RT_OPSYS RT_OPSYS_NT
+# elif defined(RT_OS_OPENBSD)
+#  define RT_OPSYS RT_OPSYS_OPENBSD
+# elif defined(RT_OS_OS2)
+#  define RT_OPSYS RT_OPSYS_OS2
+# elif defined(RT_OS_PLAN9)
+#  define RT_OPSYS RT_OPSYS_PLAN9
+# elif defined(RT_OS_QNX)
+#  define RT_OPSYS RT_OPSYS_QNX
+# elif defined(RT_OS_SOLARIS)
+#  define RT_OPSYS RT_OPSYS_SOLARIS
+# elif defined(RT_OS_UEFI)
+#  define RT_OPSYS RT_OPSYS_UEFI
+# elif defined(RT_OS_WINDOWS)
+#  define RT_OPSYS RT_OPSYS_WINDOWS
+# endif
+#endif
+
+/*
+ * Guess RT_OPSYS based on compiler predefined macros.
+ */
+#ifndef RT_OPSYS
+# if defined(__APPLE__)
+#  define RT_OPSYS      RT_OPSYS_DARWIN
+# elif defined(__DragonFly__)
+#  define RT_OPSYS      RT_OPSYS_DRAGONFLY
+# elif defined(__FreeBSD__) /*??*/
+#  define RT_OPSYS      RT_OPSYS_FREEBSD
+# elif defined(__gnu_linux__)
+#  define RT_OPSYS      RT_OPSYS_LINUX
+# elif defined(__NetBSD__) /*??*/
+#  define RT_OPSYS      RT_OPSYS_NETBSD
+# elif defined(__OpenBSD__) /*??*/
+#  define RT_OPSYS      RT_OPSYS_OPENBSD
+# elif defined(__OS2__)
+#  define RT_OPSYS      RT_OPSYS_OS2
+# elif defined(__sun__) || defined(__SunOS__) || defined(__sun) || defined(__SunOS)
+#  define RT_OPSYS      RT_OPSYS_SOLARIS
+# elif defined(_WIN32) || defined(_WIN64)
+#  define RT_OPSYS      RT_OPSYS_WINDOWS
+# elif defined(MSDOS) || defined(_MSDOS) || defined(DOS16RM) /* OW+MSC || MSC || DMC */
+#  define RT_OPSYS      RT_OPSYS_DOS
+# else
+#  error "Port Me"
+# endif
+#endif
+
+#if RT_OPSYS < RT_OPSYS_UNKNOWN || RT_OPSYS >= RT_OPSYS_MAX
+# error "Invalid RT_OPSYS value."
+#endif
+
+/*
+ * Do some consistency checks.
+ *
+ * Search:  #define RT_OPSYS_([A-Z0-9]+) .*
+ * Replace: #if defined(RT_OS_\1) && RT_OPSYS != RT_OPSYS_\1\n# error RT_OPSYS vs RT_OS_\1\n#endif
+ */
+#if defined(RT_OS_UNKNOWN) && RT_OPSYS != RT_OPSYS_UNKNOWN
+# error RT_OPSYS vs RT_OS_UNKNOWN
+#endif
+#if defined(RT_OS_AGNOSTIC) && RT_OPSYS != RT_OPSYS_AGNOSTIC
+# error RT_OPSYS vs RT_OS_AGNOSTIC
+#endif
+#if defined(RT_OS_DARWIN) && RT_OPSYS != RT_OPSYS_DARWIN
+# error RT_OPSYS vs RT_OS_DARWIN
+#endif
+#if defined(RT_OS_DRAGONFLY) && RT_OPSYS != RT_OPSYS_DRAGONFLY
+# error RT_OPSYS vs RT_OS_DRAGONFLY
+#endif
+#if defined(RT_OS_DOS) && RT_OPSYS != RT_OPSYS_DOS
+# error RT_OPSYS vs RT_OS_DOS
+#endif
+#if defined(RT_OS_FREEBSD) && RT_OPSYS != RT_OPSYS_FREEBSD
+# error RT_OPSYS vs RT_OS_FREEBSD
+#endif
+#if defined(RT_OS_HAIKU) && RT_OPSYS != RT_OPSYS_HAIKU
+# error RT_OPSYS vs RT_OS_HAIKU
+#endif
+#if defined(RT_OS_LINUX) && RT_OPSYS != RT_OPSYS_LINUX
+# error RT_OPSYS vs RT_OS_LINUX
+#endif
+#if defined(RT_OS_L4) && RT_OPSYS != RT_OPSYS_L4
+# error RT_OPSYS vs RT_OS_L4
+#endif
+#if defined(RT_OS_MINIX) && RT_OPSYS != RT_OPSYS_MINIX
+# error RT_OPSYS vs RT_OS_MINIX
+#endif
+#if defined(RT_OS_NETBSD) && RT_OPSYS != RT_OPSYS_NETBSD
+# error RT_OPSYS vs RT_OS_NETBSD
+#endif
+#if defined(RT_OS_NETWARE) && RT_OPSYS != RT_OPSYS_NETWARE
+# error RT_OPSYS vs RT_OS_NETWARE
+#endif
+#if defined(RT_OS_NT) && RT_OPSYS != RT_OPSYS_NT
+# error RT_OPSYS vs RT_OS_NT
+#endif
+#if defined(RT_OS_OPENBSD) && RT_OPSYS != RT_OPSYS_OPENBSD
+# error RT_OPSYS vs RT_OS_OPENBSD
+#endif
+#if defined(RT_OS_OS2) && RT_OPSYS != RT_OPSYS_OS2
+# error RT_OPSYS vs RT_OS_OS2
+#endif
+#if defined(RT_OS_PLAN9) && RT_OPSYS != RT_OPSYS_PLAN9
+# error RT_OPSYS vs RT_OS_PLAN9
+#endif
+#if defined(RT_OS_QNX) && RT_OPSYS != RT_OPSYS_QNX
+# error RT_OPSYS vs RT_OS_QNX
+#endif
+#if defined(RT_OS_SOLARIS) && RT_OPSYS != RT_OPSYS_SOLARIS
+# error RT_OPSYS vs RT_OS_SOLARIS
+#endif
+#if defined(RT_OS_UEFI) && RT_OPSYS != RT_OPSYS_UEFI
+# error RT_OPSYS vs RT_OS_UEFI
+#endif
+#if defined(RT_OS_WINDOWS) && RT_OPSYS != RT_OPSYS_WINDOWS
+# error RT_OPSYS vs RT_OS_WINDOWS
+#endif
+
+/*
+ * Make sure the RT_OS_XXX macro is defined.
+ *
+ * Search:  #define RT_OPSYS_([A-Z0-9]+) .*
+ * Replace: #elif RT_OPSYS == RT_OPSYS_\1\n# ifndef RT_OS_\1\n#  define RT_OS_\1\n# endif
+ */
+#if RT_OPSYS == RT_OPSYS_UNKNOWN
+# ifndef RT_OS_UNKNOWN
+#  define RT_OS_UNKNOWN
+# endif
+#elif RT_OPSYS == RT_OPSYS_AGNOSTIC
+# ifndef RT_OS_AGNOSTIC
+#  define RT_OS_AGNOSTIC
+# endif
+#elif RT_OPSYS == RT_OPSYS_DARWIN
+# ifndef RT_OS_DARWIN
+#  define RT_OS_DARWIN
+# endif
+#elif RT_OPSYS == RT_OPSYS_DRAGONFLY
+# ifndef RT_OS_DRAGONFLY
+#  define RT_OS_DRAGONFLY
+# endif
+#elif RT_OPSYS == RT_OPSYS_DOS
+# ifndef RT_OS_DOS
+#  define RT_OS_DOS
+# endif
+#elif RT_OPSYS == RT_OPSYS_FREEBSD
+# ifndef RT_OS_FREEBSD
+#  define RT_OS_FREEBSD
+# endif
+#elif RT_OPSYS == RT_OPSYS_HAIKU
+# ifndef RT_OS_HAIKU
+#  define RT_OS_HAIKU
+# endif
+#elif RT_OPSYS == RT_OPSYS_LINUX
+# ifndef RT_OS_LINUX
+#  define RT_OS_LINUX
+# endif
+#elif RT_OPSYS == RT_OPSYS_L4
+# ifndef RT_OS_L4
+#  define RT_OS_L4
+# endif
+#elif RT_OPSYS == RT_OPSYS_MINIX
+# ifndef RT_OS_MINIX
+#  define RT_OS_MINIX
+# endif
+#elif RT_OPSYS == RT_OPSYS_NETBSD
+# ifndef RT_OS_NETBSD
+#  define RT_OS_NETBSD
+# endif
+#elif RT_OPSYS == RT_OPSYS_NETWARE
+# ifndef RT_OS_NETWARE
+#  define RT_OS_NETWARE
+# endif
+#elif RT_OPSYS == RT_OPSYS_NT
+# ifndef RT_OS_NT
+#  define RT_OS_NT
+# endif
+#elif RT_OPSYS == RT_OPSYS_OPENBSD
+# ifndef RT_OS_OPENBSD
+#  define RT_OS_OPENBSD
+# endif
+#elif RT_OPSYS == RT_OPSYS_OS2
+# ifndef RT_OS_OS2
+#  define RT_OS_OS2
+# endif
+#elif RT_OPSYS == RT_OPSYS_PLAN9
+# ifndef RT_OS_PLAN9
+#  define RT_OS_PLAN9
+# endif
+#elif RT_OPSYS == RT_OPSYS_QNX
+# ifndef RT_OS_QNX
+#  define RT_OS_QNX
+# endif
+#elif RT_OPSYS == RT_OPSYS_SOLARIS
+# ifndef RT_OS_SOLARIS
+#  define RT_OS_SOLARIS
+# endif
+#elif RT_OPSYS == RT_OPSYS_UEFI
+# ifndef RT_OS_UEFI
+#  define RT_OS_UEFI
+# endif
+#elif RT_OPSYS == RT_OPSYS_WINDOWS
+# ifndef RT_OS_WINDOWS
+#  define RT_OS_WINDOWS
+# endif
+#else
+# error "Bad RT_OPSYS value."
+#endif
+
+
+/**
+ * Checks whether the given OpSys uses DOS-style paths or not.
+ *
+ * By DOS-style paths we include drive lettering and UNC paths.
+ *
+ * @returns true / false
+ * @param   a_OpSys     The RT_OPSYS_XXX value to check, will be reference
+ *                      multiple times.
+ */
+#define RT_OPSYS_USES_DOS_PATHS(a_OpSys) \
+    (   (a_OpSys) == RT_OPSYS_WINDOWS \
+     || (a_OpSys) == RT_OPSYS_OS2 \
+     || (a_OpSys) == RT_OPSYS_DOS )
+
+
+
+/** @def CTXTYPE
+ * Declare a type differently in GC, R3 and R0.
+ *
+ * @param   GCType  The GC type.
+ * @param   R3Type  The R3 type.
+ * @param   R0Type  The R0 type.
+ * @remark  For pointers used only in one context use RCPTRTYPE(), R3R0PTRTYPE(), R3PTRTYPE() or R0PTRTYPE().
+ */
+#ifdef IN_RC
+# define CTXTYPE(GCType, R3Type, R0Type)  GCType
+#elif defined(IN_RING3)
+# define CTXTYPE(GCType, R3Type, R0Type)  R3Type
+#else
+# define CTXTYPE(GCType, R3Type, R0Type)  R0Type
+#endif
+
+/** @def RCPTRTYPE
+ * Declare a pointer which is used in the raw mode context but appears in structure(s) used by
+ * both HC and RC. The main purpose is to make sure structures have the same
+ * size when built for different architectures.
+ *
+ * @param   RCType  The RC type.
+ */
+#define RCPTRTYPE(RCType)       CTXTYPE(RCType, RTRCPTR, RTRCPTR)
+
+/** @def R3R0PTRTYPE
+ * Declare a pointer which is used in HC, is explicitly valid in ring 3 and 0,
+ * but appears in structure(s) used by both HC and GC. The main purpose is to
+ * make sure structures have the same size when built for different architectures.
+ *
+ * @param   R3R0Type  The R3R0 type.
+ * @remarks This used to be called HCPTRTYPE.
+ */
+#define R3R0PTRTYPE(R3R0Type)   CTXTYPE(RTHCPTR, R3R0Type, R3R0Type)
+
+/** @def R3PTRTYPE
+ * Declare a pointer which is used in R3 but appears in structure(s) used by
+ * both HC and GC. The main purpose is to make sure structures have the same
+ * size when built for different architectures.
+ *
+ * @param   R3Type  The R3 type.
+ */
+#define R3PTRTYPE(R3Type)       CTXTYPE(RTHCUINTPTR, R3Type, RTHCUINTPTR)
+
+/** @def R0PTRTYPE
+ * Declare a pointer which is used in R0 but appears in structure(s) used by
+ * both HC and GC. The main purpose is to make sure structures have the same
+ * size when built for different architectures.
+ *
+ * @param   R0Type  The R0 type.
+ */
+#define R0PTRTYPE(R0Type)       CTXTYPE(RTHCUINTPTR, RTHCUINTPTR, R0Type)
+
+/** @def CTXSUFF
+ * Adds the suffix of the current context to the passed in
+ * identifier name. The suffix is HC or GC.
+ *
+ * This is macro should only be used in shared code to avoid a forest of ifdefs.
+ * @param   var     Identifier name.
+ * @deprecated Use CTX_SUFF. Do NOT use this for new code.
+ */
+/** @def OTHERCTXSUFF
+ * Adds the suffix of the other context to the passed in
+ * identifier name. The suffix is HC or GC.
+ *
+ * This is macro should only be used in shared code to avoid a forest of ifdefs.
+ * @param   var     Identifier name.
+ * @deprecated Use CTX_SUFF. Do NOT use this for new code.
+ */
+#ifdef IN_RC
+# define CTXSUFF(var)       var##GC
+# define OTHERCTXSUFF(var)  var##HC
+#else
+# define CTXSUFF(var)       var##HC
+# define OTHERCTXSUFF(var)  var##GC
+#endif
+
+/** @def CTXALLSUFF
+ * Adds the suffix of the current context to the passed in
+ * identifier name. The suffix is R3, R0 or GC.
+ *
+ * This is macro should only be used in shared code to avoid a forest of ifdefs.
+ * @param   var     Identifier name.
+ * @deprecated Use CTX_SUFF. Do NOT use this for new code.
+ */
+#ifdef IN_RC
+# define CTXALLSUFF(var)    var##GC
+#elif defined(IN_RING0)
+# define CTXALLSUFF(var)    var##R0
+#else
+# define CTXALLSUFF(var)    var##R3
+#endif
+
+/** @def CTX_SUFF
+ * Adds the suffix of the current context to the passed in
+ * identifier name. The suffix is R3, R0 or RC.
+ *
+ * This is macro should only be used in shared code to avoid a forest of ifdefs.
+ * @param   var     Identifier name.
+ *
+ * @remark  This will replace CTXALLSUFF and CTXSUFF before long.
+ */
+#ifdef IN_RC
+# define CTX_SUFF(var)      var##RC
+#elif defined(IN_RING0)
+# define CTX_SUFF(var)      var##R0
+#else
+# define CTX_SUFF(var)      var##R3
+#endif
+
+/** @def CTX_SUFF_Z
+ * Adds the suffix of the current context to the passed in
+ * identifier name, combining RC and R0 into RZ.
+ * The suffix thus is R3 or RZ.
+ *
+ * This is macro should only be used in shared code to avoid a forest of ifdefs.
+ * @param   var     Identifier name.
+ *
+ * @remark  This will replace CTXALLSUFF and CTXSUFF before long.
+ */
+#ifdef IN_RING3
+# define CTX_SUFF_Z(var)    var##R3
+#else
+# define CTX_SUFF_Z(var)    var##RZ
+#endif
+
+
+/** @def CTXMID
+ * Adds the current context as a middle name of an identifier name
+ * The middle name is HC or GC.
+ *
+ * This is macro should only be used in shared code to avoid a forest of ifdefs.
+ * @param   first   First name.
+ * @param   last    Surname.
+ */
+/** @def OTHERCTXMID
+ * Adds the other context as a middle name of an identifier name
+ * The middle name is HC or GC.
+ *
+ * This is macro should only be used in shared code to avoid a forest of ifdefs.
+ * @param   first   First name.
+ * @param   last    Surname.
+ * @deprecated use CTX_MID or CTX_MID_Z
+ */
+#ifdef IN_RC
+# define CTXMID(first, last)        first##GC##last
+# define OTHERCTXMID(first, last)   first##HC##last
+#else
+# define CTXMID(first, last)        first##HC##last
+# define OTHERCTXMID(first, last)   first##GC##last
+#endif
+
+/** @def CTXALLMID
+ * Adds the current context as a middle name of an identifier name.
+ * The middle name is R3, R0 or GC.
+ *
+ * This is macro should only be used in shared code to avoid a forest of ifdefs.
+ * @param   first   First name.
+ * @param   last    Surname.
+ * @deprecated use CTX_MID or CTX_MID_Z
+ */
+#ifdef IN_RC
+# define CTXALLMID(first, last)     first##GC##last
+#elif defined(IN_RING0)
+# define CTXALLMID(first, last)     first##R0##last
+#else
+# define CTXALLMID(first, last)     first##R3##last
+#endif
+
+/** @def CTX_MID
+ * Adds the current context as a middle name of an identifier name.
+ * The middle name is R3, R0 or RC.
+ *
+ * This is macro should only be used in shared code to avoid a forest of ifdefs.
+ * @param   first   First name.
+ * @param   last    Surname.
+ */
+#ifdef IN_RC
+# define CTX_MID(first, last)       first##RC##last
+#elif defined(IN_RING0)
+# define CTX_MID(first, last)       first##R0##last
+#else
+# define CTX_MID(first, last)       first##R3##last
+#endif
+
+/** @def CTX_MID_Z
+ * Adds the current context as a middle name of an identifier name, combining RC
+ * and R0 into RZ.
+ * The middle name thus is either R3 or RZ.
+ *
+ * This is macro should only be used in shared code to avoid a forest of ifdefs.
+ * @param   first   First name.
+ * @param   last    Surname.
+ */
+#ifdef IN_RING3
+# define CTX_MID_Z(first, last)     first##R3##last
+#else
+# define CTX_MID_Z(first, last)     first##RZ##last
+#endif
+
+
+/** @def R3STRING
+ * A macro which in GC and R0 will return a dummy string while in R3 it will return
+ * the parameter.
+ *
+ * This is typically used to wrap description strings in structures shared
+ * between R3, R0 and/or GC. The intention is to avoid the \#ifdef IN_RING3 mess.
+ *
+ * @param   pR3String   The R3 string. Only referenced in R3.
+ * @see R0STRING and GCSTRING
+ */
+#ifdef IN_RING3
+# define R3STRING(pR3String)    (pR3String)
+#else
+# define R3STRING(pR3String)    ("<R3_STRING>")
+#endif
+
+/** @def R0STRING
+ * A macro which in GC and R3 will return a dummy string while in R0 it will return
+ * the parameter.
+ *
+ * This is typically used to wrap description strings in structures shared
+ * between R3, R0 and/or GC. The intention is to avoid the \#ifdef IN_RING0 mess.
+ *
+ * @param   pR0String   The R0 string. Only referenced in R0.
+ * @see R3STRING and GCSTRING
+ */
+#ifdef IN_RING0
+# define R0STRING(pR0String)    (pR0String)
+#else
+# define R0STRING(pR0String)    ("<R0_STRING>")
+#endif
+
+/** @def RCSTRING
+ * A macro which in R3 and R0 will return a dummy string while in RC it will return
+ * the parameter.
+ *
+ * This is typically used to wrap description strings in structures shared
+ * between R3, R0 and/or RC. The intention is to avoid the \#ifdef IN_RC mess.
+ *
+ * @param   pRCString   The RC string. Only referenced in RC.
+ * @see R3STRING, R0STRING
+ */
+#ifdef IN_RC
+# define RCSTRING(pRCString)    (pRCString)
+#else
+# define RCSTRING(pRCString)    ("<RC_STRING>")
+#endif
+
+
+/** @def RT_NOTHING
+ * A macro that expands to nothing.
+ * This is primarily intended as a dummy argument for macros to avoid the
+ * undefined behavior passing empty arguments to an macro (ISO C90 and C++98,
+ * gcc v4.4 warns about it).
+ */
+#define RT_NOTHING
+
+/** @def RT_GCC_EXTENSION
+ * Macro for shutting up GCC warnings about using language extensions. */
+#ifdef __GNUC__
+# define RT_GCC_EXTENSION       __extension__
+#else
+# define RT_GCC_EXTENSION
+#endif
+
+/** @def RT_GCC_NO_WARN_DEPRECATED_BEGIN
+ * Used to start a block of code where GCC should not warn about deprecated
+ * declarations. */
+#if RT_GNUC_PREREQ(4, 6)
+# define RT_GCC_NO_WARN_DEPRECATED_BEGIN \
+   _Pragma("GCC diagnostic push") \
+   _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+/** @def RT_GCC_NO_WARN_DEPRECATED_END
+ * Used to end a block of code where GCC should not warn about deprecated
+ * declarations. */
+# define RT_GCC_NO_WARN_DEPRECATED_END \
+   _Pragma("GCC diagnostic pop")
+#else
+# define RT_GCC_NO_WARN_DEPRECATED_BEGIN
+# define RT_GCC_NO_WARN_DEPRECATED_END
+#endif
+
+/** @def RT_GCC_NO_WARN_CONVERSION_BEGIN
+ * Used to start a block of code where GCC should not warn about implicit
+ * conversions that may alter a value. */
+#if RT_GNUC_PREREQ(4, 6)
+# define RT_GCC_NO_WARN_CONVERSION_BEGIN \
+   _Pragma("GCC diagnostic push") \
+   _Pragma("GCC diagnostic ignored \"-Wconversion\"")
+/** @def RT_GCC_NO_WARN_CONVERSION_END
+ * Used to end a block of code where GCC should not warn about implicit
+ * conversions that may alter a value. */
+# define RT_GCC_NO_WARN_CONVERSION_END \
+   _Pragma("GCC diagnostic pop")
+#else
+# define RT_GCC_NO_WARN_CONVERSION_BEGIN
+# define RT_GCC_NO_WARN_CONVERSION_END
+#endif
+
+/** @def RT_COMPILER_GROKS_64BIT_BITFIELDS
+ * Macro that is defined if the compiler understands 64-bit bitfields. */
+#if !defined(RT_OS_OS2) || (!defined(__IBMC__) && !defined(__IBMCPP__))
+# if !defined(__WATCOMC__) /* watcom compiler doesn't grok it either. */
+#  define RT_COMPILER_GROKS_64BIT_BITFIELDS
+# endif
+#endif
+
+/** @def RT_COMPILER_WITH_80BIT_LONG_DOUBLE
+ * Macro that is defined if the compiler implements long double as the
+ * IEEE extended precision floating. */
+#if (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)) && !defined(RT_OS_WINDOWS)
+# define RT_COMPILER_WITH_80BIT_LONG_DOUBLE
+#endif
+
+
+/** @def RT_EXCEPTIONS_ENABLED
+ * Defined when C++ exceptions are enabled.
+ */
+#if !defined(RT_EXCEPTIONS_ENABLED) \
+ &&  defined(__cplusplus) \
+ && (   (defined(_MSC_VER) && defined(_CPPUNWIND)) \
+     || (defined(__GNUC__) && defined(__EXCEPTIONS)))
+# define RT_EXCEPTIONS_ENABLED
+#endif
+
+/** @def RT_NO_THROW_PROTO
+ * How to express that a function doesn't throw C++ exceptions
+ * and the compiler can thus save itself the bother of trying
+ * to catch any of them. Put this between the closing parenthesis
+ * and the semicolon in function prototypes (and implementation if C++).
+ *
+ * @remarks May not work on C++ methods, mainly intented for C-style APIs.
+ *
+ * @remarks The use of the nothrow attribute with GCC is because old compilers
+ *          (4.1.1, 32-bit) leaking the nothrow into global space or something
+ *          when used with RTDECL or similar.  Using this forces use to have two
+ *          macros, as the nothrow attribute is not for the function definition.
+ */
+#ifdef RT_EXCEPTIONS_ENABLED
+# ifdef __GNUC__
+#  define RT_NO_THROW_PROTO     __attribute__((__nothrow__))
+# else
+#  define RT_NO_THROW_PROTO     throw()
+# endif
+#else
+# define RT_NO_THROW_PROTO
+#endif
+
+/** @def RT_NO_THROW_DEF
+ * The counter part to RT_NO_THROW_PROTO that is added to the function
+ * definition.
+ */
+#if defined(RT_EXCEPTIONS_ENABLED) && !defined(__GNUC__)
+# define RT_NO_THROW_DEF        RT_NO_THROW_PROTO
+#else
+# define RT_NO_THROW_DEF
+#endif
+
+/** @def RT_THROW
+ * How to express that a method or function throws a type of exceptions. Some
+ * compilers does not want this kind of information and will warning about it.
+ *
+ * @param   type    The type exception.
+ *
+ * @remarks If the actual throwing is done from the header, enclose it by
+ *          \#ifdef RT_EXCEPTIONS_ENABLED ... \#else ... \#endif so the header
+ *          compiles cleanly without exceptions enabled.
+ *
+ *          Do NOT use this for the actual throwing of exceptions!
+ */
+#ifdef RT_EXCEPTIONS_ENABLED
+# if RT_MSC_PREREQ_EX(RT_MSC_VER_VC71, 0)
+#   define RT_THROW(type)
+# elif RT_GNUC_PREREQ(7, 0)
+#   define RT_THROW(type)
+# else
+#   define RT_THROW(type)       throw(type)
+# endif
+#else
+# define RT_THROW(type)
+#endif
+
+/** @def RT_IPRT_FORMAT_ATTR
+ * Identifies a function taking an IPRT format string.
+ * @param   a_iFmt  The index (1-based) of the format string argument.
+ * @param   a_iArgs The index (1-based) of the first format argument, use 0 for
+ *                  va_list.
+ */
+#if defined(__GNUC__) && defined(WITH_IPRT_FORMAT_ATTRIBUTE)
+# define RT_IPRT_FORMAT_ATTR(a_iFmt, a_iArgs)   __attribute__((__iprt_format__(a_iFmt, a_iArgs)))
+#else
+# define RT_IPRT_FORMAT_ATTR(a_iFmt, a_iArgs)
+#endif
+
+/** @def RT_IPRT_FORMAT_ATTR_MAYBE_NULL
+ * Identifies a function taking an IPRT format string, NULL is allowed.
+ * @param   a_iFmt  The index (1-based) of the format string argument.
+ * @param   a_iArgs The index (1-based) of the first format argument, use 0 for
+ *                  va_list.
+ */
+#if defined(__GNUC__) && defined(WITH_IPRT_FORMAT_ATTRIBUTE)
+# define RT_IPRT_FORMAT_ATTR_MAYBE_NULL(a_iFmt, a_iArgs)   __attribute__((__iprt_format_maybe_null__(a_iFmt, a_iArgs)))
+#else
+# define RT_IPRT_FORMAT_ATTR_MAYBE_NULL(a_iFmt, a_iArgs)
+#endif
+
+
+/** @def RT_GCC_SUPPORTS_VISIBILITY_HIDDEN
+ * Indicates that the "hidden" visibility attribute can be used (GCC) */
+#if defined(__GNUC__)
+# if __GNUC__ >= 4 && !defined(RT_OS_OS2) && !defined(RT_OS_WINDOWS)
+#  define RT_GCC_SUPPORTS_VISIBILITY_HIDDEN
+# endif
+#endif
+
+/** @def RT_COMPILER_SUPPORTS_VA_ARGS
+ * If the defined, the compiler supports the variadic macro feature (..., __VA_ARGS__). */
+#if defined(_MSC_VER)
+# if _MSC_VER >= 1600 /* Visual C++ v10.0 / 2010 */
+#  define RT_COMPILER_SUPPORTS_VA_ARGS
+# endif
+#elif defined(__GNUC__)
+# if __GNUC__ >= 3 /* not entirely sure when this was added */
+#  define RT_COMPILER_SUPPORTS_VA_ARGS
+# endif
+#endif
+
+
+
+/** @def RTCALL
+ * The standard calling convention for the Runtime interfaces.
+ *
+ * @remarks The regparm(0) in the X86/GNUC variant deals with -mregparm=x use in
+ *          the linux kernel and potentially elsewhere (3rd party).
+ */
+#if defined(_MSC_VER) || defined(__WATCOMC__)
+# define RTCALL                 __cdecl
+#elif defined(RT_OS_OS2)
+# define RTCALL                 __cdecl
+#elif defined(__GNUC__) && defined(RT_ARCH_X86)
+# define RTCALL                 __attribute__((__cdecl__,__regparm__(0)))
+#else
+# define RTCALL
+#endif
+
+/** @def DECLEXPORT
+ * How to declare an exported function.
+ * @param   type    The return type of the function declaration.
+ */
+#if defined(_MSC_VER) || defined(RT_OS_OS2)
+# define DECLEXPORT(type)       __declspec(dllexport) type
+#elif defined(RT_USE_VISIBILITY_DEFAULT)
+# define DECLEXPORT(type)      __attribute__((visibility("default"))) type
+#else
+# define DECLEXPORT(type)      type
+#endif
+
+/** @def DECLIMPORT
+ * How to declare an imported function.
+ * @param   type    The return type of the function declaration.
+ */
+#if defined(_MSC_VER) || (defined(RT_OS_OS2) && !defined(__IBMC__) && !defined(__IBMCPP__))
+# define DECLIMPORT(type)       __declspec(dllimport) type
+#else
+# define DECLIMPORT(type)       type
+#endif
+
+/** @def DECLHIDDEN
+ * How to declare a non-exported function or variable.
+ * @param   type    The return type of the function or the data type of the variable.
+ */
+#if !defined(RT_GCC_SUPPORTS_VISIBILITY_HIDDEN) || defined(RT_NO_VISIBILITY_HIDDEN)
+# define DECLHIDDEN(type)       type
+#else
+# define DECLHIDDEN(type)       __attribute__((visibility("hidden"))) type
+#endif
+
+/** @def DECL_HIDDEN_CONST
+ * Workaround for g++ warnings when applying the hidden attribute to a const
+ * definition.  Use DECLHIDDEN for the declaration.
+ * @param   a_Type      The return type of the function or the data type of
+ *                      the variable.
+ */
+#if defined(__cplusplus) && defined(__GNUC__)
+# define DECL_HIDDEN_CONST(a_Type)   a_Type
+#else
+# define DECL_HIDDEN_CONST(a_Type)   DECLHIDDEN(a_Type)
+#endif
+
+/** @def DECL_INVALID
+ * How to declare a function not available for linking in the current context.
+ * The purpose is to create compile or like time errors when used.  This isn't
+ * possible on all platforms.
+ * @param   type    The return type of the function.
+ */
+#if defined(_MSC_VER)
+# define DECL_INVALID(type)     __declspec(dllimport) type __stdcall
+#elif defined(__GNUC__) && defined(__cplusplus)
+# define DECL_INVALID(type)     extern "C++" type
+#else
+# define DECL_INVALID(type)     type
+#endif
+
+/** @def DECLASM
+ * How to declare an internal assembly function.
+ * @param   type    The return type of the function declaration.
+ */
+#ifdef __cplusplus
+# define DECLASM(type)           extern "C" type RTCALL
+#else
+# define DECLASM(type)           type RTCALL
+#endif
+
+/** @def DECLASMTYPE
+ * How to declare an internal assembly function type.
+ * @param   type    The return type of the function.
+ */
+#define DECLASMTYPE(type)       type RTCALL
+
+/** @def DECL_NO_RETURN
+ * How to declare a function which does not return.
+ * @note This macro can be combined with other macros, for example
+ * @code
+ *   EMR3DECL(DECL_NO_RETURN(void)) foo(void);
+ * @endcode
+ */
+#ifdef _MSC_VER
+# define DECL_NO_RETURN(type)   __declspec(noreturn) type
+#elif defined(__GNUC__)
+# define DECL_NO_RETURN(type)   __attribute__((noreturn)) type
+#else
+# define DECL_NO_RETURN(type)   type
+#endif
+/** @deprecated Use DECL_NO_RETURN instead. */
+#define DECLNORETURN(type) DECL_NO_RETURN(type)
+
+/** @def DECL_RETURNS_TWICE
+ * How to declare a function which may return more than once.
+ * @note This macro can be combined with other macros, for example
+ * @code
+ *   EMR3DECL(DECL_RETURNS_TWICE(void)) MySetJmp(void);
+ * @endcode
+ */
+#if RT_GNUC_PREREQ(4, 1)
+# define DECL_RETURNS_TWICE(type)  __attribute__((returns_twice)) type
+# else
+# define DECL_RETURNS_TWICE(type)   type
+#endif
+
+/** @def DECLWEAK
+ * How to declare a variable which is not necessarily resolved at
+ * runtime.
+ * @note This macro can be combined with other macros, for example
+ * @code
+ *   EMR3DECL(DECLWEAK(int)) foo;
+ * @endcode
+ */
+#if defined(__GNUC__)
+# define DECLWEAK(type)         type __attribute__((weak))
+#else
+# define DECLWEAK(type)         type
+#endif
+
+/** @def DECLCALLBACK
+ * How to declare an call back function type.
+ * @param   type    The return type of the function declaration.
+ */
+#define DECLCALLBACK(type)      type RTCALL
+
+/** @def DECLCALLBACKPTR
+ * How to declare an call back function pointer.
+ * @param   type    The return type of the function declaration.
+ * @param   name    The name of the variable member.
+ */
+#if defined(__IBMC__) || defined(__IBMCPP__)
+# define DECLCALLBACKPTR(type, name)    type (* RTCALL name)
+#else
+# define DECLCALLBACKPTR(type, name)    type (RTCALL * name)
+#endif
+
+/** @def DECLCALLBACKMEMBER
+ * How to declare an call back function pointer member.
+ * @param   type    The return type of the function declaration.
+ * @param   name    The name of the struct/union/class member.
+ */
+#if defined(__IBMC__) || defined(__IBMCPP__)
+# define DECLCALLBACKMEMBER(type, name) type (* RTCALL name)
+#else
+# define DECLCALLBACKMEMBER(type, name) type (RTCALL * name)
+#endif
+
+/** @def DECLR3CALLBACKMEMBER
+ * How to declare an call back function pointer member - R3 Ptr.
+ * @param   type    The return type of the function declaration.
+ * @param   name    The name of the struct/union/class member.
+ * @param   args    The argument list enclosed in parentheses.
+ */
+#ifdef IN_RING3
+# define DECLR3CALLBACKMEMBER(type, name, args)  DECLCALLBACKMEMBER(type, name) args
+#else
+# define DECLR3CALLBACKMEMBER(type, name, args)  RTR3PTR name
+#endif
+
+/** @def DECLRCCALLBACKMEMBER
+ * How to declare an call back function pointer member - RC Ptr.
+ * @param   type    The return type of the function declaration.
+ * @param   name    The name of the struct/union/class member.
+ * @param   args    The argument list enclosed in parentheses.
+ */
+#ifdef IN_RC
+# define DECLRCCALLBACKMEMBER(type, name, args)  DECLCALLBACKMEMBER(type, name)  args
+#else
+# define DECLRCCALLBACKMEMBER(type, name, args)  RTRCPTR name
+#endif
+
+/** @def DECLR0CALLBACKMEMBER
+ * How to declare an call back function pointer member - R0 Ptr.
+ * @param   type    The return type of the function declaration.
+ * @param   name    The name of the struct/union/class member.
+ * @param   args    The argument list enclosed in parentheses.
+ */
+#ifdef IN_RING0
+# define DECLR0CALLBACKMEMBER(type, name, args)  DECLCALLBACKMEMBER(type, name) args
+#else
+# define DECLR0CALLBACKMEMBER(type, name, args)  RTR0PTR name
+#endif
+
+/** @def DECLINLINE
+ * How to declare a function as inline.
+ * @param   type    The return type of the function declaration.
+ * @remarks Don't use this macro on C++ methods.
+ */
+#ifdef __GNUC__
+# define DECLINLINE(type) static __inline__ type
+#elif defined(__cplusplus)
+# define DECLINLINE(type) static inline type
+#elif defined(_MSC_VER)
+# define DECLINLINE(type) static _inline type
+#elif defined(__IBMC__)
+# define DECLINLINE(type) _Inline type
+#else
+# define DECLINLINE(type) inline type
+#endif
+
+
+/** @def DECL_FORCE_INLINE
+ * How to declare a function as inline and try convince the compiler to always
+ * inline it regardless of optimization switches.
+ * @param   type    The return type of the function declaration.
+ * @remarks Use sparsely and with care. Don't use this macro on C++ methods.
+ */
+#ifdef __GNUC__
+# define DECL_FORCE_INLINE(type)    __attribute__((__always_inline__)) DECLINLINE(type)
+#elif defined(_MSC_VER)
+# define DECL_FORCE_INLINE(type)    __forceinline type
+#else
+# define DECL_FORCE_INLINE(type)    DECLINLINE(type)
+#endif
+
+
+/** @def DECL_NO_INLINE
+ * How to declare a function telling the compiler not to inline it.
+ * @param   scope   The function scope, static or RT_NOTHING.
+ * @param   type    The return type of the function declaration.
+ * @remarks Don't use this macro on C++ methods.
+ */
+#ifdef __GNUC__
+# define DECL_NO_INLINE(scope,type) __attribute__((__noinline__)) scope type
+#elif defined(_MSC_VER)
+# define DECL_NO_INLINE(scope,type) __declspec(noinline) scope type
+#else
+# define DECL_NO_INLINE(scope,type) scope type
+#endif
+
+
+/** @def IN_RT_STATIC
+ * Used to indicate whether we're linking against a static IPRT
+ * or not.
+ *
+ * The IPRT symbols will be declared as hidden (if supported).  Note that this
+ * define has no effect without also setting one of the IN_RT_R0, IN_RT_R3 or
+ * IN_RT_RC indicators.
+ */
+
+/** @def IN_RT_R0
+ * Used to indicate whether we're inside the same link module as the host
+ * context ring-0 Runtime Library.
+ */
+/** @def RTR0DECL(type)
+ * Runtime Library host context ring-0 export or import declaration.
+ * @param   type    The return type of the function declaration.
+ * @remarks This is only used inside IPRT.  Other APIs need to define their own
+ *          XXXX_DECL macros for dealing with import/export/static visibility.
+ */
+#ifdef IN_RT_R0
+# ifdef IN_RT_STATIC
+#  define RTR0DECL(type)    DECLHIDDEN(type) RTCALL
+# else
+#  define RTR0DECL(type)    DECLEXPORT(type) RTCALL
+# endif
+#else
+# define RTR0DECL(type)     DECLIMPORT(type) RTCALL
+#endif
+
+/** @def IN_RT_R3
+ * Used to indicate whether we're inside the same link module as the host
+ * context ring-3 Runtime Library.
+ */
+/** @def RTR3DECL(type)
+ * Runtime Library host context ring-3 export or import declaration.
+ * @param   type    The return type of the function declaration.
+ * @remarks This is only used inside IPRT.  Other APIs need to define their own
+ *          XXXX_DECL macros for dealing with import/export/static visibility.
+ */
+#ifdef IN_RT_R3
+# ifdef IN_RT_STATIC
+#  define RTR3DECL(type)    DECLHIDDEN(type) RTCALL
+# else
+#  define RTR3DECL(type)    DECLEXPORT(type) RTCALL
+# endif
+#else
+# define RTR3DECL(type)     DECLIMPORT(type) RTCALL
+#endif
+
+/** @def IN_RT_RC
+ * Used to indicate whether we're inside the same link module as the raw-mode
+ * context (RC) runtime library.
+ */
+/** @def RTRCDECL(type)
+ * Runtime Library raw-mode context export or import declaration.
+ * @param   type    The return type of the function declaration.
+ * @remarks This is only used inside IPRT.  Other APIs need to define their own
+ *          XXXX_DECL macros for dealing with import/export/static visibility.
+ */
+#ifdef IN_RT_RC
+# ifdef IN_RT_STATIC
+#  define RTRCDECL(type)    DECLHIDDEN(type) RTCALL
+# else
+#  define RTRCDECL(type)    DECLEXPORT(type) RTCALL
+# endif
+#else
+# define RTRCDECL(type)     DECLIMPORT(type) RTCALL
+#endif
+
+/** @def RTDECL(type)
+ * Runtime Library export or import declaration.
+ * Functions declared using this macro exists in all contexts.
+ * @param   type    The return type of the function declaration.
+ * @remarks This is only used inside IPRT.  Other APIs need to define their own
+ *          XXXX_DECL macros for dealing with import/export/static visibility.
+ */
+#if defined(IN_RT_R3) || defined(IN_RT_RC) || defined(IN_RT_R0)
+# ifdef IN_RT_STATIC
+#  define RTDECL(type)      DECLHIDDEN(type) RTCALL
+# else
+#  define RTDECL(type)      DECLEXPORT(type) RTCALL
+# endif
+#else
+# define RTDECL(type)       DECLIMPORT(type) RTCALL
+#endif
+
+/** @def RTDATADECL(type)
+ * Runtime Library export or import declaration.
+ * Data declared using this macro exists in all contexts.
+ * @param   type    The data type.
+ * @remarks This is only used inside IPRT.  Other APIs need to define their own
+ *          XXXX_DECL macros for dealing with import/export/static visibility.
+ */
+/** @def RT_DECL_DATA_CONST(type)
+ * Definition of a const variable. See DECL_HIDDEN_CONST.
+ * @param   type    The const data type.
+ * @remarks This is only used inside IPRT.  Other APIs need to define their own
+ *          XXXX_DECL macros for dealing with import/export/static visibility.
+ */
+#if defined(IN_RT_R3) || defined(IN_RT_RC) || defined(IN_RT_R0)
+# ifdef IN_RT_STATIC
+#  define RTDATADECL(type)          DECLHIDDEN(type)
+#  define RT_DECL_DATA_CONST(type)  DECL_HIDDEN_CONST(type)
+# else
+#  define RTDATADECL(type)          DECLEXPORT(type)
+#  if defined(__cplusplus) && defined(__GNUC__)
+#   define RT_DECL_DATA_CONST(type) type
+#  else
+#   define RT_DECL_DATA_CONST(type) DECLEXPORT(type)
+#  endif
+# endif
+#else
+# define RTDATADECL(type)           DECLIMPORT(type)
+# define RT_DECL_DATA_CONST(type)   DECLIMPORT(type)
+#endif
+
+/** @def RT_DECL_CLASS
+ * Declares an class living in the runtime.
+ * @remarks This is only used inside IPRT.  Other APIs need to define their own
+ *          XXXX_DECL macros for dealing with import/export/static visibility.
+ */
+#if defined(IN_RT_R3) || defined(IN_RT_RC) || defined(IN_RT_R0)
+# ifdef IN_RT_STATIC
+#  define RT_DECL_CLASS
+# else
+#  define RT_DECL_CLASS     DECLEXPORT_CLASS
+# endif
+#else
+# define RT_DECL_CLASS      DECLIMPORT_CLASS
+#endif
+
+
+/** @def RT_NOCRT
+ * Symbol name wrapper for the No-CRT bits.
+ *
+ * In order to coexist in the same process as other CRTs, we need to
+ * decorate the symbols such that they don't conflict the ones in the
+ * other CRTs. The result of such conflicts / duplicate symbols can
+ * confuse the dynamic loader on Unix like systems.
+ *
+ * Define RT_WITHOUT_NOCRT_WRAPPERS to drop the wrapping.
+ * Define RT_WITHOUT_NOCRT_WRAPPER_ALIASES to drop the aliases to the
+ * wrapped names.
+ */
+/** @def RT_NOCRT_STR
+ * Same as RT_NOCRT only it'll return a double quoted string of the result.
+ */
+#ifndef RT_WITHOUT_NOCRT_WRAPPERS
+# define RT_NOCRT(name) nocrt_ ## name
+# define RT_NOCRT_STR(name) "nocrt_" # name
+#else
+# define RT_NOCRT(name) name
+# define RT_NOCRT_STR(name) #name
+#endif
+
+
+
+/** @def RT_LIKELY
+ * Give the compiler a hint that an expression is very likely to hold true.
+ *
+ * Some compilers support explicit branch prediction so that the CPU backend
+ * can hint the processor and also so that code blocks can be reordered such
+ * that the predicted path sees a more linear flow, thus improving cache
+ * behaviour, etc.
+ *
+ * IPRT provides the macros RT_LIKELY() and RT_UNLIKELY() as a way to utilize
+ * this compiler feature when present.
+ *
+ * A few notes about the usage:
+ *
+ *      - Generally, order your code use RT_LIKELY() instead of RT_UNLIKELY().
+ *
+ *      - Generally, use RT_UNLIKELY() with error condition checks (unless you
+ *        have some _strong_ reason to do otherwise, in which case document it),
+ *        and/or RT_LIKELY() with success condition checks, assuming you want
+ *        to optimize for the success path.
+ *
+ *      - Other than that, if you don't know the likelihood of a test succeeding
+ *        from empirical or other 'hard' evidence, don't make predictions unless
+ *        you happen to be a Dirk Gently character.
+ *
+ *      - These macros are meant to be used in places that get executed a lot. It
+ *        is wasteful to make predictions in code that is executed rarely (e.g.
+ *        at subsystem initialization time) as the basic block reordering that this
+ *        affects can often generate larger code.
+ *
+ *      - Note that RT_SUCCESS() and RT_FAILURE() already makes use of RT_LIKELY()
+ *        and RT_UNLIKELY().  Should you wish for prediction free status checks,
+ *        use the RT_SUCCESS_NP() and RT_FAILURE_NP() macros instead.
+ *
+ *
+ * @returns the boolean result of the expression.
+ * @param   expr        The expression that's very likely to be true.
+ * @see     RT_UNLIKELY
+ */
+/** @def RT_UNLIKELY
+ * Give the compiler a hint that an expression is highly unlikely to hold true.
+ *
+ * See the usage instructions give in the RT_LIKELY() docs.
+ *
+ * @returns the boolean result of the expression.
+ * @param   expr        The expression that's very unlikely to be true.
+ * @see     RT_LIKELY
+ *
+ * @deprecated Please use RT_LIKELY() instead wherever possible!  That gives us
+ *          a better chance of the windows compilers to generate favorable code
+ *          too.  The belief is that the compiler will by default assume the
+ *          if-case is more likely than the else-case.
+ */
+#if defined(__GNUC__)
+# if __GNUC__ >= 3 && !defined(FORTIFY_RUNNING)
+#  define RT_LIKELY(expr)       __builtin_expect(!!(expr), 1)
+#  define RT_UNLIKELY(expr)     __builtin_expect(!!(expr), 0)
+# else
+#  define RT_LIKELY(expr)       (expr)
+#  define RT_UNLIKELY(expr)     (expr)
+# endif
+#else
+# define RT_LIKELY(expr)        (expr)
+# define RT_UNLIKELY(expr)      (expr)
+#endif
+
+/** @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_STR
+ * Returns the argument as a string constant.
+ * @param   str     Argument to stringify.  */
+#define RT_STR(str)             #str
+/** @def RT_XSTR
+ * Returns the expanded argument as a string.
+ * @param   str     Argument to expand and stringify. */
+#define RT_XSTR(str)            RT_STR(str)
+
+/** @def RT_LSTR_2
+ * Helper for RT_WSTR that gets the expanded @a str.
+ * @param   str     String litteral to prefix with 'L'.  */
+#define RT_LSTR_2(str)          L##str
+/** @def RT_LSTR
+ * Returns the expanded argument with a L string prefix.
+ *
+ * Intended for converting ASCII string \#defines into wide char string
+ * litterals on Windows.
+ *
+ * @param   str     String litteral to . */
+#define RT_LSTR(str)            RT_LSTR_2(str)
+
+/** @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
+
+#if defined(RT_COMPILER_SUPPORTS_VA_ARGS) || defined(DOXYGEN_RUNNING)
+
+/** @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))
+
+#endif /* RT_COMPILER_SUPPORTS_VA_ARGS */
+
+
+/** @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
+
+/** @def RT_CONCAT4
+ * 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.
+ * @param   d       The 4th part.
+ */
+#define RT_CONCAT4(a,b,c,d)         RT_CONCAT4_HLP(a,b,c,d)
+/** RT_CONCAT4 helper, don't use.  */
+#define RT_CONCAT4_HLP(a,b,c,d)     a##b##c##d
+
+/** @def RT_CONCAT5
+ * 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.
+ * @param   d       The 4th part.
+ * @param   e       The 5th part.
+ */
+#define RT_CONCAT5(a,b,c,d,e)         RT_CONCAT5_HLP(a,b,c,d,e)
+/** RT_CONCAT5 helper, don't use.  */
+#define RT_CONCAT5_HLP(a,b,c,d,e)     a##b##c##d##e
+
+/** @def RT_CONCAT6
+ * 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.
+ * @param   d       The 4th part.
+ * @param   e       The 5th part.
+ * @param   f       The 6th part.
+ */
+#define RT_CONCAT6(a,b,c,d,e,f)       RT_CONCAT6_HLP(a,b,c,d,e,f)
+/** RT_CONCAT6 helper, don't use.  */
+#define RT_CONCAT6_HLP(a,b,c,d,e,f)   a##b##c##d##e##f
+
+/** @def RT_CONCAT7
+ * 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.
+ * @param   d       The 4th part.
+ * @param   e       The 5th part.
+ * @param   f       The 6th part.
+ * @param   g       The 7th part.
+ */
+#define RT_CONCAT7(a,b,c,d,e,f,g)       RT_CONCAT7_HLP(a,b,c,d,e,f,g)
+/** RT_CONCAT7 helper, don't use.  */
+#define RT_CONCAT7_HLP(a,b,c,d,e,f,g)   a##b##c##d##e##f##g
+
+/** @def RT_CONCAT8
+ * 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.
+ * @param   d       The 4th part.
+ * @param   e       The 5th part.
+ * @param   f       The 6th part.
+ * @param   g       The 7th part.
+ * @param   h       The 8th part.
+ */
+#define RT_CONCAT8(a,b,c,d,e,f,g,h)     RT_CONCAT8_HLP(a,b,c,d,e,f,g,h)
+/** RT_CONCAT8 helper, don't use.  */
+#define RT_CONCAT8_HLP(a,b,c,d,e,f,g,h) a##b##c##d##e##f##g##h
+
+/** @def RT_CONCAT9
+ * 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.
+ * @param   d       The 4th part.
+ * @param   e       The 5th part.
+ * @param   f       The 6th part.
+ * @param   g       The 7th part.
+ * @param   h       The 8th part.
+ * @param   i       The 9th part.
+ */
+#define RT_CONCAT9(a,b,c,d,e,f,g,h,i)   RT_CONCAT9_HLP(a,b,c,d,e,f,g,h,i)
+/** RT_CONCAT9 helper, don't use.  */
+#define RT_CONCAT9_HLP(a,b,c,d,e,f,g,h,i) a##b##c##d##e##f##g##h##i
+
+/**
+ * String constant tuple - string constant, strlen(string constant).
+ *
+ * @param   a_szConst   String constant.
+ * @sa      RTSTRTUPLE
+ */
+#define RT_STR_TUPLE(a_szConst)  a_szConst, (sizeof(a_szConst) - 1)
+
+
+/**
+ * Macro for using in switch statements that turns constants into strings.
+ *
+ * @param   a_Const     The constant (not string).
+ */
+#define RT_CASE_RET_STR(a_Const)     case a_Const: return #a_Const
+
+
+/** @def RT_BIT
+ * Convert a bit number into an integer bitmask (unsigned).
+ * @param   bit     The bit number.
+ */
+#define RT_BIT(bit)                             ( 1U << (bit) )
+
+/** @def RT_BIT_32
+ * Convert a bit number into a 32-bit bitmask (unsigned).
+ * @param   bit     The bit number.
+ */
+#define RT_BIT_32(bit)                          ( UINT32_C(1) << (bit) )
+
+/** @def RT_BIT_64
+ * Convert a bit number into a 64-bit bitmask (unsigned).
+ * @param   bit     The bit number.
+ */
+#define RT_BIT_64(bit)                          ( UINT64_C(1) << (bit) )
+
+
+/** @def RT_BF_GET
+ * Gets the value of a bit field in an integer value.
+ *
+ * This requires a couple of macros to be defined for the field:
+ *      - \<a_FieldNm\>_SHIFT: The shift count to get to the field.
+ *      - \<a_FieldNm\>_MASK:  The field mask.
+ *
+ * @returns The bit field value.
+ * @param   a_uValue        The integer value containing the field.
+ * @param   a_FieldNm       The field name prefix for getting at the _SHIFT and
+ *                          _MASK macros.
+ * @sa      #RT_BF_CLEAR, #RT_BF_SET, #RT_BF_MAKE, #RT_BF_ZMASK
+ */
+#define RT_BF_GET(a_uValue, a_FieldNm)          ( ((a_uValue) >> RT_CONCAT(a_FieldNm,_SHIFT)) & RT_BF_ZMASK(a_FieldNm) )
+
+/** @def RT_BF_SET
+ * Sets the given bit field in the integer value.
+ *
+ * This requires a couple of macros to be defined for the field:
+ *      - \<a_FieldNm\>_SHIFT: The shift count to get to the field.
+ *      - \<a_FieldNm\>_MASK:  The field mask.  Must have the same type as the
+ *        integer value!!
+ *
+ * @returns Integer value with bit field set to @a a_uFieldValue.
+ * @param   a_uValue        The integer value containing the field.
+ * @param   a_FieldNm       The field name prefix for getting at the _SHIFT and
+ *                          _MASK macros.
+ * @param   a_uFieldValue   The new field value.
+ * @sa      #RT_BF_GET, #RT_BF_CLEAR, #RT_BF_MAKE, #RT_BF_ZMASK
+ */
+#define RT_BF_SET(a_uValue, a_FieldNm, a_uFieldValue) ( RT_BF_CLEAR(a_uValue, a_FieldNm) | RT_BF_MAKE(a_FieldNm, a_uFieldValue) )
+
+/** @def RT_BF_CLEAR
+ * Clears the given bit field in the integer value.
+ *
+ * This requires a couple of macros to be defined for the field:
+ *      - \<a_FieldNm\>_SHIFT: The shift count to get to the field.
+ *      - \<a_FieldNm\>_MASK:  The field mask.  Must have the same type as the
+ *        integer value!!
+ *
+ * @returns Integer value with bit field set to zero.
+ * @param   a_uValue        The integer value containing the field.
+ * @param   a_FieldNm       The field name prefix for getting at the _SHIFT and
+ *                          _MASK macros.
+ * @sa      #RT_BF_GET, #RT_BF_SET, #RT_BF_MAKE, #RT_BF_ZMASK
+ */
+#define RT_BF_CLEAR(a_uValue, a_FieldNm)        ( (a_uValue) & ~RT_CONCAT(a_FieldNm,_MASK) )
+
+/** @def RT_BF_MAKE
+ * Shifts and masks a bit field value into position in the integer value.
+ *
+ * This requires a couple of macros to be defined for the field:
+ *      - \<a_FieldNm\>_SHIFT: The shift count to get to the field.
+ *      - \<a_FieldNm\>_MASK:  The field mask.
+ *
+ * @param   a_FieldNm       The field name prefix for getting at the _SHIFT and
+ *                          _MASK macros.
+ * @param   a_uFieldValue   The field value that should be masked and shifted
+ *                          into position.
+ * @sa      #RT_BF_GET, #RT_BF_SET, #RT_BF_CLEAR, #RT_BF_ZMASK
+ */
+#define RT_BF_MAKE(a_FieldNm, a_uFieldValue)    ( ((a_uFieldValue) & RT_BF_ZMASK(a_FieldNm) ) << RT_CONCAT(a_FieldNm,_SHIFT) )
+
+/** @def RT_BF_ZMASK
+ * Helper for getting the field mask shifted to bit position zero.
+ *
+ * @param   a_FieldNm       The field name prefix for getting at the _SHIFT and
+ *                          _MASK macros.
+ * @sa      #RT_BF_GET, #RT_BF_SET, #RT_BF_CLEAR, #RT_BF_MAKE
+ */
+#define RT_BF_ZMASK(a_FieldNm)                  ( RT_CONCAT(a_FieldNm,_MASK) >> RT_CONCAT(a_FieldNm,_SHIFT) )
+
+/** 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)
+#define RT_BF_CHECK_DO_34(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, f34) \
+    RT_BF_CHECK_DO_33(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, f34)
+#define RT_BF_CHECK_DO_35(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, f34, f35) \
+    RT_BF_CHECK_DO_34(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, f34, f35)
+#define RT_BF_CHECK_DO_36(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, f34, f35, f36) \
+    RT_BF_CHECK_DO_35(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, f34, f35, f36)
+#define RT_BF_CHECK_DO_37(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, f34, f35, f36, f37) \
+    RT_BF_CHECK_DO_36(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, f34, f35, f36, f37)
+#define RT_BF_CHECK_DO_38(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, f34, f35, f36, f37, f38) \
+    RT_BF_CHECK_DO_37(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, f34, f35, f36, f37, f38)
+#define RT_BF_CHECK_DO_39(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, f34, f35, f36, f37, f38, f39) \
+    RT_BF_CHECK_DO_38(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, f34, f35, f36, f37, f38, f39)
+#define RT_BF_CHECK_DO_40(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, f34, f35, f36, f37, f38, f39, f40) \
+    RT_BF_CHECK_DO_39(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, f34, f35, f36, f37, f38, f39, f40)
+#define RT_BF_CHECK_DO_41(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, f34, f35, f36, f37, f38, f39, f40, f41) \
+    RT_BF_CHECK_DO_40(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, f34, f35, f36, f37, f38, f39, f40, f41)
+#define RT_BF_CHECK_DO_42(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, f34, f35, f36, f37, f38, f39, f40, f41, f42) \
+    RT_BF_CHECK_DO_41(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, f34, f35, f36, f37, f38, f39, f40, f41, f42)
+#define RT_BF_CHECK_DO_43(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43) \
+    RT_BF_CHECK_DO_42(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43)
+#define RT_BF_CHECK_DO_44(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44) \
+    RT_BF_CHECK_DO_43(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44)
+#define RT_BF_CHECK_DO_45(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45) \
+    RT_BF_CHECK_DO_44(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45)
+#define RT_BF_CHECK_DO_46(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46) \
+    RT_BF_CHECK_DO_45(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46)
+#define RT_BF_CHECK_DO_47(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47) \
+    RT_BF_CHECK_DO_46(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47)
+#define RT_BF_CHECK_DO_48(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48) \
+    RT_BF_CHECK_DO_47(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48)
+#define RT_BF_CHECK_DO_49(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49) \
+    RT_BF_CHECK_DO_48(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49)
+#define RT_BF_CHECK_DO_50(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50) \
+    RT_BF_CHECK_DO_49(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50)
+#define RT_BF_CHECK_DO_51(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51) \
+    RT_BF_CHECK_DO_40(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51)
+#define RT_BF_CHECK_DO_52(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52) \
+    RT_BF_CHECK_DO_51(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52)
+#define RT_BF_CHECK_DO_53(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53) \
+    RT_BF_CHECK_DO_52(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53)
+#define RT_BF_CHECK_DO_54(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54) \
+    RT_BF_CHECK_DO_53(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54)
+#define RT_BF_CHECK_DO_55(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55) \
+    RT_BF_CHECK_DO_54(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55)
+#define RT_BF_CHECK_DO_56(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56) \
+    RT_BF_CHECK_DO_55(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56)
+#define RT_BF_CHECK_DO_57(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57) \
+    RT_BF_CHECK_DO_56(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57)
+#define RT_BF_CHECK_DO_58(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57, f58) \
+    RT_BF_CHECK_DO_57(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57, f58)
+#define RT_BF_CHECK_DO_59(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57, f58, f59) \
+    RT_BF_CHECK_DO_58(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57, f58, f59)
+#define RT_BF_CHECK_DO_60(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57, f58, f59, f60) \
+    RT_BF_CHECK_DO_59(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57, f58, f59, f60)
+#define RT_BF_CHECK_DO_61(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57, f58, f59, f60, f61) \
+    RT_BF_CHECK_DO_60(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57, f58, f59, f60, f61)
+#define RT_BF_CHECK_DO_62(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57, f58, f59, f60, f61, f62) \
+    RT_BF_CHECK_DO_61(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57, f58, f59, f60, f61, f62)
+#define RT_BF_CHECK_DO_63(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57, f58, f59, f60, f61, f62, f63) \
+    RT_BF_CHECK_DO_62(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57, f58, f59, f60, f61, f62, f63)
+#define RT_BF_CHECK_DO_64(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57, f58, f59, f60, f61, f62, f63, f64) \
+    RT_BF_CHECK_DO_63(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, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, f50, f51, f52, f53, f54, f55, f56, f57, f58, f59, f60, f61, f62, f63, f64)
+/** @} */
+
+/** @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.
+ */
+#if defined(RT_COMPILER_SUPPORTS_VA_ARGS) || defined(DOXYGEN_RUNNING)
+# 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__))
+#else
+# define RT_BF_ASSERT_COMPILE_CHECKS(a_Prefix, a_uZero, a_uCovered, a_Fields) AssertCompile(true)
+#endif
+
+
+/** @def RT_ALIGN
+ * Align macro.
+ * @param   u           Value to align.
+ * @param   uAlignment  The alignment. Power of two!
+ *
+ * @remark  Be extremely careful when using this macro with type which sizeof != sizeof int.
+ *          When possible use any of the other RT_ALIGN_* macros. And when that's not
+ *          possible, make 101% sure that uAlignment is specified with a right sized type.
+ *
+ *          Specifying an unsigned 32-bit alignment constant with a 64-bit value will give
+ *          you a 32-bit return value!
+ *
+ *          In short: Don't use this macro. Use RT_ALIGN_T() instead.
+ */
+#define RT_ALIGN(u, uAlignment)                 ( ((u) + ((uAlignment) - 1)) & ~((uAlignment) - 1) )
+
+/** @def RT_ALIGN_T
+ * Align macro.
+ * @param   u           Value to align.
+ * @param   uAlignment  The alignment. Power of two!
+ * @param   type        Integer type to use while aligning.
+ * @remark  This macro is the preferred alignment macro, it doesn't have any of the pitfalls RT_ALIGN has.
+ */
+#define RT_ALIGN_T(u, uAlignment, type)         ( ((type)(u) + ((uAlignment) - 1)) & ~(type)((uAlignment) - 1) )
+
+/** @def RT_ALIGN_32
+ * Align macro for a 32-bit value.
+ * @param   u32         Value to align.
+ * @param   uAlignment  The alignment. Power of two!
+ */
+#define RT_ALIGN_32(u32, uAlignment)            RT_ALIGN_T(u32, uAlignment, uint32_t)
+
+/** @def RT_ALIGN_64
+ * Align macro for a 64-bit value.
+ * @param   u64         Value to align.
+ * @param   uAlignment  The alignment. Power of two!
+ */
+#define RT_ALIGN_64(u64, uAlignment)            RT_ALIGN_T(u64, uAlignment, uint64_t)
+
+/** @def RT_ALIGN_Z
+ * Align macro for size_t.
+ * @param   cb          Value to align.
+ * @param   uAlignment  The alignment. Power of two!
+ */
+#define RT_ALIGN_Z(cb, uAlignment)              RT_ALIGN_T(cb, uAlignment, size_t)
+
+/** @def RT_ALIGN_P
+ * Align macro for pointers.
+ * @param   pv          Value to align.
+ * @param   uAlignment  The alignment. Power of two!
+ */
+#define RT_ALIGN_P(pv, uAlignment)              RT_ALIGN_PT(pv, uAlignment, void *)
+
+/** @def RT_ALIGN_PT
+ * Align macro for pointers with type cast.
+ * @param   u           Value to align.
+ * @param   uAlignment  The alignment. Power of two!
+ * @param   CastType    The type to cast the result to.
+ */
+#define RT_ALIGN_PT(u, uAlignment, CastType)    ( (CastType)RT_ALIGN_T(u, uAlignment, uintptr_t) )
+
+/** @def RT_ALIGN_R3PT
+ * Align macro for ring-3 pointers with type cast.
+ * @param   u           Value to align.
+ * @param   uAlignment  The alignment. Power of two!
+ * @param   CastType    The type to cast the result to.
+ */
+#define RT_ALIGN_R3PT(u, uAlignment, CastType)  ( (CastType)RT_ALIGN_T(u, uAlignment, RTR3UINTPTR) )
+
+/** @def RT_ALIGN_R0PT
+ * Align macro for ring-0 pointers with type cast.
+ * @param   u           Value to align.
+ * @param   uAlignment  The alignment. Power of two!
+ * @param   CastType    The type to cast the result to.
+ */
+#define RT_ALIGN_R0PT(u, uAlignment, CastType)  ( (CastType)RT_ALIGN_T(u, uAlignment, RTR0UINTPTR) )
+
+/** @def RT_ALIGN_GCPT
+ * Align macro for GC pointers with type cast.
+ * @param   u           Value to align.
+ * @param   uAlignment  The alignment. Power of two!
+ * @param   CastType        The type to cast the result to.
+ */
+#define RT_ALIGN_GCPT(u, uAlignment, CastType)  ( (CastType)RT_ALIGN_T(u, uAlignment, RTGCUINTPTR) )
+
+
+/** @def RT_OFFSETOF
+ * Our own special offsetof() variant, returns a signed result.
+ *
+ * This differs from the usual offsetof() in that it's not relying on builtin
+ * compiler stuff and thus can use variables in arrays the structure may
+ * contain. This is useful to determine the sizes of structures ending
+ * with a variable length field. For gcc >= 4.4 see @bugref{7775}.
+ *
+ * @returns offset into the structure of the specified member. signed.
+ * @param   type    Structure type.
+ * @param   member  Member.
+ */
+#if defined(__cplusplus) && RT_GNUC_PREREQ(4, 4)
+# define RT_OFFSETOF(type, member)              ( (int)(uintptr_t)&( ((type *)(void *)0x1000)->member) - 0x1000 )
+#else
+# define RT_OFFSETOF(type, member)              ( (int)(uintptr_t)&( ((type *)(void *)0)->member) )
+#endif
+
+/** @def RT_UOFFSETOF
+ * Our own special offsetof() variant, returns an unsigned result.
+ *
+ * This differs from the usual offsetof() in that it's not relying on builtin
+ * compiler stuff and thus can use variables in arrays the structure may
+ * contain. This is useful to determine the sizes of structures ending
+ * with a variable length field. For gcc >= 4.4 see @bugref{7775}.
+ *
+ * @returns offset into the structure of the specified member. unsigned.
+ * @param   type    Structure type.
+ * @param   member  Member.
+ */
+#if defined(__cplusplus) && RT_GNUC_PREREQ(4, 4)
+# define RT_UOFFSETOF(type, member)             ( (uintptr_t)&( ((type *)(void *)0x1000)->member) - 0x1000 )
+#else
+# define RT_UOFFSETOF(type, member)             ( (uintptr_t)&( ((type *)(void *)0)->member) )
+#endif
+
+/** @def RT_OFFSETOF_ADD
+ * RT_OFFSETOF with an addend.
+ *
+ * @returns offset into the structure of the specified member. signed.
+ * @param   type    Structure type.
+ * @param   member  Member.
+ * @param   addend  The addend to add to the offset.
+ */
+#define RT_OFFSETOF_ADD(type, member, addend)   ( (int)RT_UOFFSETOF_ADD(type, member, addend) )
+
+/** @def RT_UOFFSETOF_ADD
+ * RT_UOFFSETOF with an addend.
+ *
+ * @returns offset into the structure of the specified member. signed.
+ * @param   type    Structure type.
+ * @param   member  Member.
+ * @param   addend  The addend to add to the offset.
+ */
+#define RT_UOFFSETOF_ADD(type, member, addend)  ( (uintptr_t)&( ((type *)(void *)(uintptr_t)(addend))->member) )
+
+/** @def RT_SIZEOFMEMB
+ * Get the size of a structure member.
+ *
+ * @returns size of the structure member.
+ * @param   type    Structure type.
+ * @param   member  Member.
+ */
+#define RT_SIZEOFMEMB(type, member)             ( sizeof(((type *)(void *)0)->member) )
+
+/** @def RT_UOFFSET_AFTER
+ * Returns the offset of the first byte following a structure/union member.
+ *
+ * @return byte offset into the struct.
+ * @param   a_Type      Structure type.
+ * @param   a_Member    The member name.
+ */
+#define RT_UOFFSET_AFTER(a_Type, a_Member)      ( RT_UOFFSETOF(a_Type, a_Member) + RT_SIZEOFMEMB(a_Type, a_Member) )
+
+/** @def RT_FROM_MEMBER
+ * Convert a pointer to a structure member into a pointer to the structure.
+ *
+ * @returns pointer to the structure.
+ * @param   pMem    Pointer to the member.
+ * @param   Type    Structure type.
+ * @param   Member  Member name.
+ */
+#define RT_FROM_MEMBER(pMem, Type, Member)      ( (Type *) ((uint8_t *)(void *)(pMem) - RT_UOFFSETOF(Type, Member)) )
+
+/** @def RT_FROM_CPP_MEMBER
+ * Same as RT_FROM_MEMBER except it avoids the annoying g++ warnings about
+ * invalid access to non-static data member of NULL object.
+ *
+ * @returns pointer to the structure.
+ * @param   pMem    Pointer to the member.
+ * @param   Type    Structure type.
+ * @param   Member  Member name.
+ *
+ * @remarks Using the __builtin_offsetof does not shut up the compiler.
+ */
+#if defined(__GNUC__) && defined(__cplusplus)
+# define RT_FROM_CPP_MEMBER(pMem, Type, Member) \
+        ( (Type *) ((uintptr_t)(pMem) - (uintptr_t)&((Type *)0x1000)->Member + 0x1000U) )
+#else
+# define RT_FROM_CPP_MEMBER(pMem, Type, Member) RT_FROM_MEMBER(pMem, Type, Member)
+#endif
+
+/** @def RT_ELEMENTS
+ * Calculates the number of elements in a statically sized array.
+ * @returns Element count.
+ * @param   aArray      Array in question.
+ */
+#define RT_ELEMENTS(aArray)                     ( sizeof(aArray) / sizeof((aArray)[0]) )
+
+/** @def RT_FLEXIBLE_ARRAY
+ * What to up inside the square brackets when declaring a structure member
+ * with a flexible size.
+ *
+ * @note    Use RT_UOFFSETOF() to calculate the structure size.
+ *
+ * @note    Never to a sizeof() on the structure or member!
+ *
+ * @note    The member must be the last one.
+ *
+ * @note    GCC does not permit using this in a union.  So, for unions you must
+ *          use RT_FLEXIBLE_ARRAY_IN_UNION instead.
+ *
+ * @note    GCC does not permit using this in nested structures, where as MSC
+ *          does.  So, use RT_FLEXIBLE_ARRAY_NESTED for that.
+ *
+ * @sa      RT_FLEXIBLE_ARRAY_NESTED, RT_FLEXIBLE_ARRAY_IN_UNION
+ */
+#if RT_MSC_PREREQ(RT_MSC_VER_VS2005) /** @todo Probably much much earlier. */ \
+ || (defined(__cplusplus) && RT_GNUC_PREREQ(6, 1) && !RT_GNUC_PREREQ(7, 0)) /* gcc-7 warns again */\
+ || defined(__WATCOMC__) /* openwatcom 1.9 supports it, we don't care about older atm. */
+# define RT_FLEXIBLE_ARRAY
+# if defined(__cplusplus) && defined(_MSC_VER)
+#  pragma warning(disable:4200) /* -wd4200 does not work with VS2010 */
+# endif
+#elif defined(__STDC_VERSION__)
+# if __STDC_VERSION__ >= 1999901L
+#  define RT_FLEXIBLE_ARRAY
+# else
+#  define RT_FLEXIBLE_ARRAY                     1
+# endif
+#else
+# define RT_FLEXIBLE_ARRAY                      1
+#endif
+
+/** @def RT_FLEXIBLE_ARRAY_NESTED
+ * Variant of RT_FLEXIBLE_ARRAY for use in structures that are nested.
+ *
+ * GCC only allow the use of flexible array member in the top structure, whereas
+ * MSC is less strict and let you do struct { struct { char szName[]; } s; };
+ *
+ * @note    See notes for RT_FLEXIBLE_ARRAY.
+ *
+ * @note    GCC does not permit using this in a union.  So, for unions you must
+ *          use RT_FLEXIBLE_ARRAY_IN_NESTED_UNION instead.
+ *
+ * @sa      RT_FLEXIBLE_ARRAY, RT_FLEXIBLE_ARRAY_IN_NESTED_UNION
+ */
+#ifdef _MSC_VER
+# define RT_FLEXIBLE_ARRAY_NESTED               RT_FLEXIBLE_ARRAY
+#else
+# define RT_FLEXIBLE_ARRAY_NESTED               1
+#endif
+
+/** @def RT_FLEXIBLE_ARRAY_IN_UNION
+ * The union version of RT_FLEXIBLE_ARRAY.
+ *
+ * @remarks GCC does not support flexible array members in unions, 6.1.x
+ *          actively checks for this.  Visual C++ 2010 seems happy with it.
+ *
+ * @note    See notes for RT_FLEXIBLE_ARRAY.
+ *
+ * @sa      RT_FLEXIBLE_ARRAY, RT_FLEXIBLE_ARRAY_IN_NESTED_UNION
+ */
+#ifdef _MSC_VER
+# define RT_FLEXIBLE_ARRAY_IN_UNION             RT_FLEXIBLE_ARRAY
+#else
+# define RT_FLEXIBLE_ARRAY_IN_UNION             1
+#endif
+
+/** @def RT_FLEXIBLE_ARRAY_IN_NESTED_UNION
+ * The union version of RT_FLEXIBLE_ARRAY_NESTED.
+ *
+ * @note    See notes for RT_FLEXIBLE_ARRAY.
+ *
+ * @sa      RT_FLEXIBLE_ARRAY, RT_FLEXIBLE_ARRAY_IN_NESTED_UNION
+ */
+#ifdef _MSC_VER
+# define RT_FLEXIBLE_ARRAY_IN_NESTED_UNION      RT_FLEXIBLE_ARRAY_NESTED
+#else
+# define RT_FLEXIBLE_ARRAY_IN_NESTED_UNION      1
+#endif
+
+/**
+ * Checks if the value is a power of two.
+ *
+ * @returns true if power of two, false if not.
+ * @param   uVal                The value to test.
+ * @remarks 0 is a power of two.
+ * @see     VERR_NOT_POWER_OF_TWO
+ */
+#define RT_IS_POWER_OF_TWO(uVal)                ( ((uVal) & ((uVal) - 1)) == 0)
+
+#ifdef RT_OS_OS2
+/* Undefine RT_MAX since there is an unfortunate clash with the max
+   resource type define in os2.h. */
+# undef RT_MAX
+#endif
+
+/** @def RT_MAX
+ * Finds the maximum value.
+ * @returns The higher of the two.
+ * @param   Value1      Value 1
+ * @param   Value2      Value 2
+ */
+#define RT_MAX(Value1, Value2)                  ( (Value1) >= (Value2) ? (Value1) : (Value2) )
+
+/** @def RT_MIN
+ * Finds the minimum value.
+ * @returns The lower of the two.
+ * @param   Value1      Value 1
+ * @param   Value2      Value 2
+ */
+#define RT_MIN(Value1, Value2)                  ( (Value1) <= (Value2) ? (Value1) : (Value2) )
+
+/** @def RT_CLAMP
+ * Clamps the value to minimum and maximum values.
+ * @returns The clamped value.
+ * @param   Value       The value to check.
+ * @param   Min         Minimum value.
+ * @param   Max         Maximum value.
+ */
+#define RT_CLAMP(Value, Min, Max)               ( (Value) > (Max) ? (Max) : (Value) < (Min) ? (Min) : (Value) )
+
+/** @def RT_ABS
+ * Get the absolute (non-negative) value.
+ * @returns The absolute value of Value.
+ * @param   Value       The value.
+ */
+#define RT_ABS(Value)                           ( (Value) >= 0 ? (Value) : -(Value) )
+
+/** @def RT_BOOL
+ * Turn non-zero/zero into true/false
+ * @returns The resulting boolean value.
+ * @param   Value       The value.
+ */
+#define RT_BOOL(Value)                          ( !!(Value) )
+
+/** @def RT_LO_U8
+ * Gets the low uint8_t of a uint16_t or something equivalent. */
+#ifdef __GNUC__
+# define RT_LO_U8(a)    __extension__ ({ AssertCompile(sizeof((a)) == sizeof(uint16_t)); (uint8_t)(a); })
+#elif defined(_MSC_VER) /* shut up cast truncates constant value warnings */
+# define RT_LO_U8(a)                            ( (uint8_t)(UINT8_MAX & (a)) )
+#else
+# define RT_LO_U8(a)                            ( (uint8_t)(a) )
+#endif
+/** @def RT_HI_U8
+ * Gets the high uint8_t of a uint16_t or something equivalent. */
+#ifdef __GNUC__
+# define RT_HI_U8(a)    __extension__ ({ AssertCompile(sizeof((a)) == sizeof(uint16_t)); (uint8_t)((a) >> 8); })
+#else
+# define RT_HI_U8(a)                            ( (uint8_t)((a) >> 8) )
+#endif
+
+/** @def RT_LO_U16
+ * Gets the low uint16_t of a uint32_t or something equivalent. */
+#ifdef __GNUC__
+# define RT_LO_U16(a)   __extension__ ({ AssertCompile(sizeof((a)) == sizeof(uint32_t)); (uint16_t)(a); })
+#elif defined(_MSC_VER) /* shut up cast truncates constant value warnings */
+# define RT_LO_U16(a)                           ( (uint16_t)(UINT16_MAX & (a)) )
+#else
+# define RT_LO_U16(a)                           ( (uint16_t)(a) )
+#endif
+/** @def RT_HI_U16
+ * Gets the high uint16_t of a uint32_t or something equivalent. */
+#ifdef __GNUC__
+# define RT_HI_U16(a)   __extension__ ({ AssertCompile(sizeof((a)) == sizeof(uint32_t)); (uint16_t)((a) >> 16); })
+#else
+# define RT_HI_U16(a)                           ( (uint16_t)((a) >> 16) )
+#endif
+
+/** @def RT_LO_U32
+ * Gets the low uint32_t of a uint64_t or something equivalent. */
+#ifdef __GNUC__
+# define RT_LO_U32(a)   __extension__ ({ AssertCompile(sizeof((a)) == sizeof(uint64_t)); (uint32_t)(a); })
+#elif defined(_MSC_VER) /* shut up cast truncates constant value warnings */
+# define RT_LO_U32(a)                           ( (uint32_t)(UINT32_MAX & (a)) )
+#else
+# define RT_LO_U32(a)                           ( (uint32_t)(a) )
+#endif
+/** @def RT_HI_U32
+ * Gets the high uint32_t of a uint64_t or something equivalent. */
+#ifdef __GNUC__
+# define RT_HI_U32(a)   __extension__ ({ AssertCompile(sizeof((a)) == sizeof(uint64_t)); (uint32_t)((a) >> 32); })
+#else
+# define RT_HI_U32(a)                           ( (uint32_t)((a) >> 32) )
+#endif
+
+/** @def RT_BYTE1
+ * Gets the first byte of something. */
+#define RT_BYTE1(a)                             ( (a)         & 0xff )
+/** @def RT_BYTE2
+ * Gets the second byte of something. */
+#define RT_BYTE2(a)                             ( ((a) >>  8) & 0xff )
+/** @def RT_BYTE3
+ * Gets the second byte of something. */
+#define RT_BYTE3(a)                             ( ((a) >> 16) & 0xff )
+/** @def RT_BYTE4
+ * Gets the fourth byte of something. */
+#define RT_BYTE4(a)                             ( ((a) >> 24) & 0xff )
+/** @def RT_BYTE5
+ * Gets the fifth byte of something. */
+#define RT_BYTE5(a)                             ( ((a) >> 32) & 0xff )
+/** @def RT_BYTE6
+ * Gets the sixth byte of something. */
+#define RT_BYTE6(a)                             ( ((a) >> 40) & 0xff )
+/** @def RT_BYTE7
+ * Gets the seventh byte of something. */
+#define RT_BYTE7(a)                             ( ((a) >> 48) & 0xff )
+/** @def RT_BYTE8
+ * Gets the eight byte of something. */
+#define RT_BYTE8(a)                             ( ((a) >> 56) & 0xff )
+
+
+/** @def RT_LODWORD
+ * Gets the low dword (=uint32_t) of something.
+ * @deprecated  Use RT_LO_U32. */
+#define RT_LODWORD(a)                           ( (uint32_t)(a) )
+/** @def RT_HIDWORD
+ * Gets the high dword (=uint32_t) of a 64-bit of something.
+ * @deprecated  Use RT_HI_U32. */
+#define RT_HIDWORD(a)                           ( (uint32_t)((a) >> 32) )
+
+/** @def RT_LOWORD
+ * Gets the low word (=uint16_t) of something.
+ * @deprecated  Use RT_LO_U16. */
+#define RT_LOWORD(a)                            ( (a) & 0xffff )
+/** @def RT_HIWORD
+ * Gets the high word (=uint16_t) of a 32-bit something.
+ * @deprecated  Use RT_HI_U16. */
+#define RT_HIWORD(a)                            ( (a) >> 16 )
+
+/** @def RT_LOBYTE
+ * Gets the low byte of something.
+ * @deprecated  Use RT_LO_U8. */
+#define RT_LOBYTE(a)                            ( (a) & 0xff )
+/** @def RT_HIBYTE
+ * Gets the high byte of a 16-bit something.
+ * @deprecated  Use RT_HI_U8. */
+#define RT_HIBYTE(a)                            ( (a) >> 8 )
+
+
+/** @def RT_MAKE_U64
+ * Constructs a uint64_t value from two uint32_t values.
+ */
+#define RT_MAKE_U64(Lo, Hi)                     ( (uint64_t)((uint32_t)(Hi)) << 32 | (uint32_t)(Lo) )
+
+/** @def RT_MAKE_U64_FROM_U16
+ * Constructs a uint64_t value from four uint16_t values.
+ */
+#define RT_MAKE_U64_FROM_U16(w0, w1, w2, w3) \
+    ((uint64_t)(  (uint64_t)((uint16_t)(w3)) << 48 \
+                | (uint64_t)((uint16_t)(w2)) << 32 \
+                | (uint32_t)((uint16_t)(w1)) << 16 \
+                |            (uint16_t)(w0) ))
+
+/** @def RT_MAKE_U64_FROM_U8
+ * Constructs a uint64_t value from eight uint8_t values.
+ */
+#define RT_MAKE_U64_FROM_U8(b0, b1, b2, b3, b4, b5, b6, b7) \
+    ((uint64_t)(  (uint64_t)((uint8_t)(b7)) << 56 \
+                | (uint64_t)((uint8_t)(b6)) << 48 \
+                | (uint64_t)((uint8_t)(b5)) << 40 \
+                | (uint64_t)((uint8_t)(b4)) << 32 \
+                | (uint32_t)((uint8_t)(b3)) << 24 \
+                | (uint32_t)((uint8_t)(b2)) << 16 \
+                | (uint16_t)((uint8_t)(b1)) << 8 \
+                |            (uint8_t)(b0) ))
+
+/** @def RT_MAKE_U32
+ * Constructs a uint32_t value from two uint16_t values.
+ */
+#define RT_MAKE_U32(Lo, Hi) \
+    ((uint32_t)(  (uint32_t)((uint16_t)(Hi)) << 16 \
+                | (uint16_t)(Lo) ))
+
+/** @def RT_MAKE_U32_FROM_U8
+ * Constructs a uint32_t value from four uint8_t values.
+ */
+#define RT_MAKE_U32_FROM_U8(b0, b1, b2, b3) \
+    ((uint32_t)(  (uint32_t)((uint8_t)(b3)) << 24 \
+                | (uint32_t)((uint8_t)(b2)) << 16 \
+                | (uint16_t)((uint8_t)(b1)) << 8 \
+                |            (uint8_t)(b0) ))
+
+/** @def RT_MAKE_U16
+ * Constructs a uint16_t value from two uint8_t values.
+ */
+#define RT_MAKE_U16(Lo, Hi) \
+    ((uint16_t)(  (uint16_t)((uint8_t)(Hi)) << 8 \
+                | (uint8_t)(Lo) ))
+
+
+/** @def RT_BSWAP_U64
+ * Reverses the byte order of an uint64_t value. */
+#if 0
+# define RT_BSWAP_U64(u64)  RT_BSWAP_U64_C(u64)
+#elif defined(__GNUC__)
+# define RT_BSWAP_U64(u64)  (__builtin_constant_p((u64)) \
+                            ? RT_BSWAP_U64_C(u64) : ASMByteSwapU64(u64))
+#else
+# define RT_BSWAP_U64(u64)  ASMByteSwapU64(u64)
+#endif
+
+/** @def RT_BSWAP_U32
+ * Reverses the byte order of an uint32_t value. */
+#if 0
+# define RT_BSWAP_U32(u32)  RT_BSWAP_U32_C(u32)
+#elif defined(__GNUC__)
+# define RT_BSWAP_U32(u32)  (__builtin_constant_p((u32)) \
+                            ? RT_BSWAP_U32_C(u32) : ASMByteSwapU32(u32))
+#else
+# define RT_BSWAP_U32(u32)  ASMByteSwapU32(u32)
+#endif
+
+/** @def RT_BSWAP_U16
+ * Reverses the byte order of an uint16_t value. */
+#if 0
+# define RT_BSWAP_U16(u16)  RT_BSWAP_U16_C(u16)
+#elif defined(__GNUC__)
+# define RT_BSWAP_U16(u16)  (__builtin_constant_p((u16)) \
+                            ? RT_BSWAP_U16_C(u16) : ASMByteSwapU16(u16))
+#else
+# define RT_BSWAP_U16(u16)  ASMByteSwapU16(u16)
+#endif
+
+
+/** @def RT_BSWAP_U64_C
+ * Reverses the byte order of an uint64_t constant. */
+#define RT_BSWAP_U64_C(u64) RT_MAKE_U64(RT_BSWAP_U32_C((u64) >> 32), RT_BSWAP_U32_C((u64) & 0xffffffff))
+
+/** @def RT_BSWAP_U32_C
+ * Reverses the byte order of an uint32_t constant. */
+#define RT_BSWAP_U32_C(u32) RT_MAKE_U32_FROM_U8(RT_BYTE4(u32), RT_BYTE3(u32), RT_BYTE2(u32), RT_BYTE1(u32))
+
+/** @def RT_BSWAP_U16_C
+ * Reverses the byte order of an uint16_t constant. */
+#define RT_BSWAP_U16_C(u16) RT_MAKE_U16(RT_HIBYTE(u16), RT_LOBYTE(u16))
+
+
+/** @def RT_H2LE_U64
+ * Converts an uint64_t value from host to little endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2LE_U64(u64)   RT_BSWAP_U64(u64)
+#else
+# define RT_H2LE_U64(u64)   (u64)
+#endif
+
+/** @def RT_H2LE_U64_C
+ * Converts an uint64_t constant from host to little endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2LE_U64_C(u64) RT_BSWAP_U64_C(u64)
+#else
+# define RT_H2LE_U64_C(u64) (u64)
+#endif
+
+/** @def RT_H2LE_U32
+ * Converts an uint32_t value from host to little endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2LE_U32(u32)   RT_BSWAP_U32(u32)
+#else
+# define RT_H2LE_U32(u32)   (u32)
+#endif
+
+/** @def RT_H2LE_U32_C
+ * Converts an uint32_t constant from host to little endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2LE_U32_C(u32) RT_BSWAP_U32_C(u32)
+#else
+# define RT_H2LE_U32_C(u32) (u32)
+#endif
+
+/** @def RT_H2LE_U16
+ * Converts an uint16_t value from host to little endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2LE_U16(u16)   RT_BSWAP_U16(u16)
+#else
+# define RT_H2LE_U16(u16)   (u16)
+#endif
+
+/** @def RT_H2LE_U16_C
+ * Converts an uint16_t constant from host to little endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2LE_U16_C(u16) RT_BSWAP_U16_C(u16)
+#else
+# define RT_H2LE_U16_C(u16) (u16)
+#endif
+
+
+/** @def RT_LE2H_U64
+ * Converts an uint64_t value from little endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_LE2H_U64(u64)   RT_BSWAP_U64(u64)
+#else
+# define RT_LE2H_U64(u64)   (u64)
+#endif
+
+/** @def RT_LE2H_U64_C
+ * Converts an uint64_t constant from little endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_LE2H_U64_C(u64) RT_BSWAP_U64_C(u64)
+#else
+# define RT_LE2H_U64_C(u64) (u64)
+#endif
+
+/** @def RT_LE2H_U32
+ * Converts an uint32_t value from little endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_LE2H_U32(u32)   RT_BSWAP_U32(u32)
+#else
+# define RT_LE2H_U32(u32)   (u32)
+#endif
+
+/** @def RT_LE2H_U32_C
+ * Converts an uint32_t constant from little endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_LE2H_U32_C(u32) RT_BSWAP_U32_C(u32)
+#else
+# define RT_LE2H_U32_C(u32) (u32)
+#endif
+
+/** @def RT_LE2H_U16
+ * Converts an uint16_t value from little endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_LE2H_U16(u16)   RT_BSWAP_U16(u16)
+#else
+# define RT_LE2H_U16(u16)   (u16)
+#endif
+
+/** @def RT_LE2H_U16_C
+ * Converts an uint16_t constant from little endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_LE2H_U16_C(u16) RT_BSWAP_U16_C(u16)
+#else
+# define RT_LE2H_U16_C(u16) (u16)
+#endif
+
+
+/** @def RT_H2BE_U64
+ * Converts an uint64_t value from host to big endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2BE_U64(u64)   (u64)
+#else
+# define RT_H2BE_U64(u64)   RT_BSWAP_U64(u64)
+#endif
+
+/** @def RT_H2BE_U64_C
+ * Converts an uint64_t constant from host to big endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2BE_U64_C(u64) (u64)
+#else
+# define RT_H2BE_U64_C(u64) RT_BSWAP_U64_C(u64)
+#endif
+
+/** @def RT_H2BE_U32
+ * Converts an uint32_t value from host to big endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2BE_U32(u32)   (u32)
+#else
+# define RT_H2BE_U32(u32)   RT_BSWAP_U32(u32)
+#endif
+
+/** @def RT_H2BE_U32_C
+ * Converts an uint32_t constant from host to big endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2BE_U32_C(u32) (u32)
+#else
+# define RT_H2BE_U32_C(u32) RT_BSWAP_U32_C(u32)
+#endif
+
+/** @def RT_H2BE_U16
+ * Converts an uint16_t value from host to big endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2BE_U16(u16)   (u16)
+#else
+# define RT_H2BE_U16(u16)   RT_BSWAP_U16(u16)
+#endif
+
+/** @def RT_H2BE_U16_C
+ * Converts an uint16_t constant from host to big endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2BE_U16_C(u16) (u16)
+#else
+# define RT_H2BE_U16_C(u16) RT_BSWAP_U16_C(u16)
+#endif
+
+/** @def RT_BE2H_U64
+ * Converts an uint64_t value from big endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_BE2H_U64(u64)   (u64)
+#else
+# define RT_BE2H_U64(u64)   RT_BSWAP_U64(u64)
+#endif
+
+/** @def RT_BE2H_U64
+ * Converts an uint64_t constant from big endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_BE2H_U64_C(u64) (u64)
+#else
+# define RT_BE2H_U64_C(u64) RT_BSWAP_U64_C(u64)
+#endif
+
+/** @def RT_BE2H_U32
+ * Converts an uint32_t value from big endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_BE2H_U32(u32)   (u32)
+#else
+# define RT_BE2H_U32(u32)   RT_BSWAP_U32(u32)
+#endif
+
+/** @def RT_BE2H_U32_C
+ * Converts an uint32_t value from big endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_BE2H_U32_C(u32) (u32)
+#else
+# define RT_BE2H_U32_C(u32) RT_BSWAP_U32_C(u32)
+#endif
+
+/** @def RT_BE2H_U16
+ * Converts an uint16_t value from big endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_BE2H_U16(u16)   (u16)
+#else
+# define RT_BE2H_U16(u16)   RT_BSWAP_U16(u16)
+#endif
+
+/** @def RT_BE2H_U16_C
+ * Converts an uint16_t constant from big endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_BE2H_U16_C(u16) (u16)
+#else
+# define RT_BE2H_U16_C(u16) RT_BSWAP_U16_C(u16)
+#endif
+
+
+/** @def RT_H2N_U64
+ * Converts an uint64_t value from host to network byte order. */
+#define RT_H2N_U64(u64)     RT_H2BE_U64(u64)
+
+/** @def RT_H2N_U64_C
+ * Converts an uint64_t constant from host to network byte order. */
+#define RT_H2N_U64_C(u64)   RT_H2BE_U64_C(u64)
+
+/** @def RT_H2N_U32
+ * Converts an uint32_t value from host to network byte order. */
+#define RT_H2N_U32(u32)     RT_H2BE_U32(u32)
+
+/** @def RT_H2N_U32_C
+ * Converts an uint32_t constant from host to network byte order. */
+#define RT_H2N_U32_C(u32)   RT_H2BE_U32_C(u32)
+
+/** @def RT_H2N_U16
+ * Converts an uint16_t value from host to network byte order. */
+#define RT_H2N_U16(u16)     RT_H2BE_U16(u16)
+
+/** @def RT_H2N_U16_C
+ * Converts an uint16_t constant from host to network byte order. */
+#define RT_H2N_U16_C(u16)   RT_H2BE_U16_C(u16)
+
+/** @def RT_N2H_U64
+ * Converts an uint64_t value from network to host byte order. */
+#define RT_N2H_U64(u64)     RT_BE2H_U64(u64)
+
+/** @def RT_N2H_U64_C
+ * Converts an uint64_t constant from network to host byte order. */
+#define RT_N2H_U64_C(u64)   RT_BE2H_U64_C(u64)
+
+/** @def RT_N2H_U32
+ * Converts an uint32_t value from network to host byte order. */
+#define RT_N2H_U32(u32)     RT_BE2H_U32(u32)
+
+/** @def RT_N2H_U32_C
+ * Converts an uint32_t constant from network to host byte order. */
+#define RT_N2H_U32_C(u32)   RT_BE2H_U32_C(u32)
+
+/** @def RT_N2H_U16
+ * Converts an uint16_t value from network to host byte order. */
+#define RT_N2H_U16(u16)     RT_BE2H_U16(u16)
+
+/** @def RT_N2H_U16_C
+ * Converts an uint16_t value from network to host byte order. */
+#define RT_N2H_U16_C(u16)   RT_BE2H_U16_C(u16)
+
+
+/*
+ * The BSD sys/param.h + machine/param.h file is a major source of
+ * namespace pollution. Kill off some of the worse ones unless we're
+ * compiling kernel code.
+ */
+#if defined(RT_OS_DARWIN) \
+  && !defined(KERNEL) \
+  && !defined(RT_NO_BSD_PARAM_H_UNDEFING) \
+  && ( defined(_SYS_PARAM_H_) || defined(_I386_PARAM_H_) )
+/* sys/param.h: */
+# undef PSWP
+# undef PVM
+# undef PINOD
+# undef PRIBO
+# undef PVFS
+# undef PZERO
+# undef PSOCK
+# undef PWAIT
+# undef PLOCK
+# undef PPAUSE
+# undef PUSER
+# undef PRIMASK
+# undef MINBUCKET
+# undef MAXALLOCSAVE
+# undef FSHIFT
+# undef FSCALE
+
+/* i386/machine.h: */
+# undef ALIGN
+# undef ALIGNBYTES
+# undef DELAY
+# undef STATUS_WORD
+# undef USERMODE
+# undef BASEPRI
+# undef MSIZE
+# undef CLSIZE
+# undef CLSIZELOG2
+#endif
+
+/** @def NIL_OFFSET
+ * NIL offset.
+ * Whenever we use offsets instead of pointers to save space and relocation effort
+ * NIL_OFFSET shall be used as the equivalent to NULL.
+ */
+#define NIL_OFFSET   (~0U)
+
+
+/** @def NOREF
+ * Keeps the compiler from bitching about an unused parameter, local variable,
+ * or other stuff, will never use _Pragma are is thus more flexible.
+ */
+#define NOREF(var)               (void)(var)
+
+/** @def RT_NOREF_PV
+ * Keeps the compiler from bitching about an unused parameter or local variable.
+ * This one cannot be used with structure members and such, like for instance
+ * AssertRC may end up doing due to its generic nature.
+ */
+#if defined(__cplusplus) && RT_CLANG_PREREQ(6, 0)
+# define RT_NOREF_PV(var)       _Pragma(RT_STR(unused(var)))
+#else
+# define RT_NOREF_PV(var)       (void)(var)
+#endif
+
+/** @def RT_NOREF1
+ * RT_NOREF_PV shorthand taking on parameter. */
+#define RT_NOREF1(var1)                                 RT_NOREF_PV(var1)
+/** @def RT_NOREF2
+ * RT_NOREF_PV shorthand taking two parameters. */
+#define RT_NOREF2(var1, var2)                           RT_NOREF_PV(var1); RT_NOREF1(var2)
+/** @def RT_NOREF3
+ * RT_NOREF_PV shorthand taking three parameters. */
+#define RT_NOREF3(var1, var2, var3)                     RT_NOREF_PV(var1); RT_NOREF2(var2, var3)
+/** @def RT_NOREF4
+ * RT_NOREF_PV shorthand taking four parameters. */
+#define RT_NOREF4(var1, var2, var3, var4)               RT_NOREF_PV(var1); RT_NOREF3(var2, var3, var4)
+/** @def RT_NOREF5
+ * RT_NOREF_PV shorthand taking five parameters. */
+#define RT_NOREF5(var1, var2, var3, var4, var5)         RT_NOREF_PV(var1); RT_NOREF4(var2, var3, var4, var5)
+/** @def RT_NOREF6
+ * RT_NOREF_PV shorthand taking six parameters.  */
+#define RT_NOREF6(var1, var2, var3, var4, var5, var6)   RT_NOREF_PV(var1); RT_NOREF5(var2, var3, var4, var5, var6)
+/** @def RT_NOREF7
+ * RT_NOREF_PV shorthand taking seven parameters.  */
+#define RT_NOREF7(var1, var2, var3, var4, var5, var6, var7) \
+    RT_NOREF_PV(var1); RT_NOREF6(var2, var3, var4, var5, var6, var7)
+/** @def RT_NOREF8
+ * RT_NOREF_PV shorthand taking eight parameters.  */
+#define RT_NOREF8(var1, var2, var3, var4, var5, var6, var7, var8) \
+    RT_NOREF_PV(var1); RT_NOREF7(var2, var3, var4, var5, var6, var7, var8)
+/** @def RT_NOREF9
+ * RT_NOREF_PV shorthand taking nine parameters.  */
+#define RT_NOREF9(var1, var2, var3, var4, var5, var6, var7, var8, var9) \
+    RT_NOREF_PV(var1); RT_NOREF8(var2, var3, var4, var5, var6, var7, var8, var9)
+/** @def RT_NOREF10
+ * RT_NOREF_PV shorthand taking ten parameters.  */
+#define RT_NOREF10(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10) \
+    RT_NOREF_PV(var1); RT_NOREF_PV(var2); RT_NOREF_PV(var3); RT_NOREF_PV(var4); RT_NOREF_PV(var5); RT_NOREF_PV(var6); \
+    RT_NOREF_PV(var7); RT_NOREF_PV(var8); RT_NOREF_PV(var9); RT_NOREF_PV(var10)
+/** @def RT_NOREF11
+ * RT_NOREF_PV shorthand taking eleven parameters.  */
+#define RT_NOREF11(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11) \
+    RT_NOREF_PV(var1); RT_NOREF10(var2, var3, var4, var5, var6, var7, var8, var9, var10)
+/** @def RT_NOREF12
+ * RT_NOREF_PV shorthand taking twelve parameters.  */
+#define RT_NOREF12(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12) \
+    RT_NOREF_PV(var1); RT_NOREF11(var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12)
+/** @def RT_NOREF13
+ * RT_NOREF_PV shorthand taking thirteen parameters.  */
+#define RT_NOREF13(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13) \
+    RT_NOREF_PV(var1); RT_NOREF12(var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13)
+/** @def RT_NOREF14
+ * RT_NOREF_PV shorthand taking fourteen parameters.  */
+#define RT_NOREF14(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14) \
+    RT_NOREF_PV(var1); RT_NOREF13(var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14)
+/** @def RT_NOREF15
+ * RT_NOREF_PV shorthand taking fifteen parameters.  */
+#define RT_NOREF15(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15) \
+    RT_NOREF_PV(var1); RT_NOREF14(var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15)
+/** @def RT_NOREF16
+ * RT_NOREF_PV shorthand taking fifteen parameters.  */
+#define RT_NOREF16(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16) \
+    RT_NOREF_PV(var1); RT_NOREF15(var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16)
+/** @def RT_NOREF17
+ * RT_NOREF_PV shorthand taking seventeen parameters.  */
+#define RT_NOREF17(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) \
+    RT_NOREF_PV(v1); RT_NOREF16(v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
+/** @def RT_NOREF18
+ * RT_NOREF_PV shorthand taking eighteen parameters.  */
+#define RT_NOREF18(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) \
+    RT_NOREF_PV(v1); RT_NOREF17(v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
+/** @def RT_NOREF19
+ * RT_NOREF_PV shorthand taking nineteen parameters.  */
+#define RT_NOREF19(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) \
+    RT_NOREF_PV(v1); RT_NOREF18(v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
+/** @def RT_NOREF20
+ * RT_NOREF_PV shorthand taking twenty parameters.  */
+#define RT_NOREF20(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) \
+    RT_NOREF_PV(v1); RT_NOREF19(v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
+/** @def RT_NOREF21
+ * RT_NOREF_PV shorthand taking twentyone parameters.  */
+#define RT_NOREF21(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) \
+    RT_NOREF_PV(v1); RT_NOREF20(v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
+/** @def RT_NOREF22
+ * RT_NOREF_PV shorthand taking twentytwo parameters.  */
+#define RT_NOREF22(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) \
+    RT_NOREF_PV(v1); RT_NOREF21(v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
+
+/** @def RT_NOREF
+ * RT_NOREF_PV variant using the variadic macro feature of C99.
+ * @remarks Only use this in sources */
+#ifdef RT_COMPILER_SUPPORTS_VA_ARGS
+# define RT_NOREF(...) \
+    RT_UNPACK_CALL(RT_CONCAT(RT_NOREF, RT_EXPAND(RT_COUNT_VA_ARGS(__VA_ARGS__))),(__VA_ARGS__))
+#endif
+
+
+/** @def RT_BREAKPOINT
+ * Emit a debug breakpoint instruction.
+ *
+ * @remarks In the x86/amd64 gnu world we add a nop instruction after the int3
+ *          to force gdb to remain at the int3 source line.
+ * @remarks The L4 kernel will try make sense of the breakpoint, thus the jmp on
+ *          x86/amd64.
+ */
+#ifdef __GNUC__
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+#  if !defined(__L4ENV__)
+#   define RT_BREAKPOINT()      __asm__ __volatile__("int $3\n\tnop\n\t")
+#  else
+#   define RT_BREAKPOINT()      __asm__ __volatile__("int3; jmp 1f; 1:\n\t")
+#  endif
+# elif defined(RT_ARCH_SPARC64)
+#  define RT_BREAKPOINT()       __asm__ __volatile__("illtrap 0\n\t")   /** @todo Sparc64: this is just a wild guess. */
+# elif defined(RT_ARCH_SPARC)
+#  define RT_BREAKPOINT()       __asm__ __volatile__("unimp 0\n\t")     /** @todo Sparc: this is just a wild guess (same as Sparc64, just different name). */
+# endif
+#endif
+#ifdef _MSC_VER
+# define RT_BREAKPOINT()        __debugbreak()
+#endif
+#if defined(__IBMC__) || defined(__IBMCPP__)
+# define RT_BREAKPOINT()        __interrupt(3)
+#endif
+#if defined(__WATCOMC__)
+# define RT_BREAKPOINT()        _asm { int 3 }
+#endif
+#ifndef RT_BREAKPOINT
+# error "This compiler/arch is not supported!"
+#endif
+
+
+/** @defgroup grp_rt_cdefs_size     Size Constants
+ * (Of course, these are binary computer terms, not SI.)
+ * @{
+ */
+/** 1 K (Kilo)                     (1 024). */
+#define _1K                     0x00000400
+/** 2 K (Kilo)                     (2 048). */
+#define _2K                     0x00000800
+/** 4 K (Kilo)                     (4 096). */
+#define _4K                     0x00001000
+/** 8 K (Kilo)                     (8 192). */
+#define _8K                     0x00002000
+/** 16 K (Kilo)                   (16 384). */
+#define _16K                    0x00004000
+/** 32 K (Kilo)                   (32 768). */
+#define _32K                    0x00008000
+/** 64 K (Kilo)                   (65 536). */
+#if ARCH_BITS != 16
+# define _64K                   0x00010000
+#else
+# define _64K           UINT32_C(0x00010000)
+#endif
+/** 128 K (Kilo)                 (131 072). */
+#if ARCH_BITS != 16
+# define _128K                   0x00020000
+#else
+# define _128K          UINT32_C(0x00020000)
+#endif
+/** 256 K (Kilo)                 (262 144). */
+#if ARCH_BITS != 16
+# define _256K                   0x00040000
+#else
+# define _256K          UINT32_C(0x00040000)
+#endif
+/** 512 K (Kilo)                 (524 288). */
+#if ARCH_BITS != 16
+# define _512K                   0x00080000
+#else
+# define _512K          UINT32_C(0x00080000)
+#endif
+/** 1 M (Mega)                 (1 048 576). */
+#if ARCH_BITS != 16
+# define _1M                     0x00100000
+#else
+# define _1M            UINT32_C(0x00100000)
+#endif
+/** 2 M (Mega)                 (2 097 152). */
+#if ARCH_BITS != 16
+# define _2M                     0x00200000
+#else
+# define _2M            UINT32_C(0x00200000)
+#endif
+/** 4 M (Mega)                 (4 194 304). */
+#if ARCH_BITS != 16
+# define _4M                     0x00400000
+#else
+# define _4M            UINT32_C(0x00400000)
+#endif
+/** 8 M (Mega)                 (8 388 608). */
+#define _8M             UINT32_C(0x00800000)
+/** 16 M (Mega)               (16 777 216). */
+#define _16M            UINT32_C(0x01000000)
+/** 32 M (Mega)               (33 554 432). */
+#define _32M            UINT32_C(0x02000000)
+/** 64 M (Mega)               (67 108 864). */
+#define _64M            UINT32_C(0x04000000)
+/** 128 M (Mega)             (134 217 728). */
+#define _128M           UINT32_C(0x08000000)
+/** 256 M (Mega)             (268 435 456). */
+#define _256M           UINT32_C(0x10000000)
+/** 512 M (Mega)             (536 870 912). */
+#define _512M           UINT32_C(0x20000000)
+/** 1 G (Giga)             (1 073 741 824). (32-bit) */
+#if ARCH_BITS != 16
+# define _1G                     0x40000000
+#else
+# define _1G            UINT32_C(0x40000000)
+#endif
+/** 1 G (Giga)             (1 073 741 824). (64-bit) */
+#if ARCH_BITS != 16
+# define _1G64                   0x40000000LL
+#else
+# define _1G64          UINT64_C(0x40000000)
+#endif
+/** 2 G (Giga)             (2 147 483 648). (32-bit) */
+#define _2G32           UINT32_C(0x80000000)
+/** 2 G (Giga)             (2 147 483 648). (64-bit) */
+#if ARCH_BITS != 16
+# define _2G             0x0000000080000000LL
+#else
+# define _2G    UINT64_C(0x0000000080000000)
+#endif
+/** 4 G (Giga)             (4 294 967 296). */
+#if ARCH_BITS != 16
+# define _4G             0x0000000100000000LL
+#else
+# define _4G    UINT64_C(0x0000000100000000)
+#endif
+/** 1 T (Tera)         (1 099 511 627 776). */
+#if ARCH_BITS != 16
+# define _1T             0x0000010000000000LL
+#else
+# define _1T    UINT64_C(0x0000010000000000)
+#endif
+/** 1 P (Peta)     (1 125 899 906 842 624). */
+#if ARCH_BITS != 16
+# define _1P             0x0004000000000000LL
+#else
+# define _1P    UINT64_C(0x0004000000000000)
+#endif
+/** 1 E (Exa)  (1 152 921 504 606 846 976). */
+#if ARCH_BITS != 16
+# define _1E             0x1000000000000000LL
+#else
+# define _1E    UINT64_C(0x1000000000000000)
+#endif
+/** 2 E (Exa)  (2 305 843 009 213 693 952). */
+#if ARCH_BITS != 16
+# define _2E             0x2000000000000000ULL
+#else
+# define _2E    UINT64_C(0x2000000000000000)
+#endif
+/** @} */
+
+/** @defgroup grp_rt_cdefs_decimal_grouping   Decimal Constant Grouping Macros
+ * @{ */
+#define RT_D1(g1)                                   g1
+#define RT_D2(g1, g2)                               g1#g2
+#define RT_D3(g1, g2, g3)                           g1#g2#g3
+#define RT_D4(g1, g2, g3, g4)                       g1#g2#g3#g4
+#define RT_D5(g1, g2, g3, g4, g5)                   g1#g2#g3#g4#g5
+#define RT_D6(g1, g2, g3, g4, g5, g6)               g1#g2#g3#g4#g5#g6
+#define RT_D7(g1, g2, g3, g4, g5, g6, g7)           g1#g2#g3#g4#g5#g6#g7
+
+#define RT_D1_U(g1)                                 UINT32_C(g1)
+#define RT_D2_U(g1, g2)                             UINT32_C(g1#g2)
+#define RT_D3_U(g1, g2, g3)                         UINT32_C(g1#g2#g3)
+#define RT_D4_U(g1, g2, g3, g4)                     UINT64_C(g1#g2#g3#g4)
+#define RT_D5_U(g1, g2, g3, g4, g5)                 UINT64_C(g1#g2#g3#g4#g5)
+#define RT_D6_U(g1, g2, g3, g4, g5, g6)             UINT64_C(g1#g2#g3#g4#g5#g6)
+#define RT_D7_U(g1, g2, g3, g4, g5, g6, g7)         UINT64_C(g1#g2#g3#g4#g5#g6#g7)
+
+#define RT_D1_S(g1)                                 INT32_C(g1)
+#define RT_D2_S(g1, g2)                             INT32_C(g1#g2)
+#define RT_D3_S(g1, g2, g3)                         INT32_C(g1#g2#g3)
+#define RT_D4_S(g1, g2, g3, g4)                     INT64_C(g1#g2#g3#g4)
+#define RT_D5_S(g1, g2, g3, g4, g5)                 INT64_C(g1#g2#g3#g4#g5)
+#define RT_D6_S(g1, g2, g3, g4, g5, g6)             INT64_C(g1#g2#g3#g4#g5#g6)
+#define RT_D7_S(g1, g2, g3, g4, g5, g6, g7)         INT64_C(g1#g2#g3#g4#g5#g6#g7)
+
+#define RT_D1_U32(g1)                               UINT32_C(g1)
+#define RT_D2_U32(g1, g2)                           UINT32_C(g1#g2)
+#define RT_D3_U32(g1, g2, g3)                       UINT32_C(g1#g2#g3)
+#define RT_D4_U32(g1, g2, g3, g4)                   UINT32_C(g1#g2#g3#g4)
+
+#define RT_D1_S32(g1)                               INT32_C(g1)
+#define RT_D2_S32(g1, g2)                           INT32_C(g1#g2)
+#define RT_D3_S32(g1, g2, g3)                       INT32_C(g1#g2#g3)
+#define RT_D4_S32(g1, g2, g3, g4)                   INT32_C(g1#g2#g3#g4)
+
+#define RT_D1_U64(g1)                               UINT64_C(g1)
+#define RT_D2_U64(g1, g2)                           UINT64_C(g1#g2)
+#define RT_D3_U64(g1, g2, g3)                       UINT64_C(g1#g2#g3)
+#define RT_D4_U64(g1, g2, g3, g4)                   UINT64_C(g1#g2#g3#g4)
+#define RT_D5_U64(g1, g2, g3, g4, g5)               UINT64_C(g1#g2#g3#g4#g5)
+#define RT_D6_U64(g1, g2, g3, g4, g5, g6)           UINT64_C(g1#g2#g3#g4#g5#g6)
+#define RT_D7_U64(g1, g2, g3, g4, g5, g6, g7)       UINT64_C(g1#g2#g3#g4#g5#g6#g7)
+
+#define RT_D1_S64(g1)                               INT64_C(g1)
+#define RT_D2_S64(g1, g2)                           INT64_C(g1#g2)
+#define RT_D3_S64(g1, g2, g3)                       INT64_C(g1#g2#g3)
+#define RT_D4_S64(g1, g2, g3, g4)                   INT64_C(g1#g2#g3#g4)
+#define RT_D5_S64(g1, g2, g3, g4, g5)               INT64_C(g1#g2#g3#g4#g5)
+#define RT_D6_S64(g1, g2, g3, g4, g5, g6)           INT64_C(g1#g2#g3#g4#g5#g6)
+#define RT_D7_S64(g1, g2, g3, g4, g5, g6, g7)       INT64_C(g1#g2#g3#g4#g5#g6#g7)
+/** @}  */
+
+
+/** @defgroup grp_rt_cdefs_time     Time Constants
+ * @{
+ */
+/** 1 hour expressed in nanoseconds (64-bit). */
+#define RT_NS_1HOUR             UINT64_C(3600000000000)
+/** 1 minute expressed in nanoseconds (64-bit). */
+#define RT_NS_1MIN              UINT64_C(60000000000)
+/** 45 second expressed in nanoseconds. */
+#define RT_NS_45SEC             UINT64_C(45000000000)
+/** 30 second expressed in nanoseconds. */
+#define RT_NS_30SEC             UINT64_C(30000000000)
+/** 20 second expressed in nanoseconds. */
+#define RT_NS_20SEC             UINT64_C(20000000000)
+/** 15 second expressed in nanoseconds. */
+#define RT_NS_15SEC             UINT64_C(15000000000)
+/** 10 second expressed in nanoseconds. */
+#define RT_NS_10SEC             UINT64_C(10000000000)
+/** 1 second expressed in nanoseconds. */
+#define RT_NS_1SEC              UINT32_C(1000000000)
+/** 100 millsecond expressed in nanoseconds. */
+#define RT_NS_100MS             UINT32_C(100000000)
+/** 10 millsecond expressed in nanoseconds. */
+#define RT_NS_10MS              UINT32_C(10000000)
+/** 1 millsecond expressed in nanoseconds. */
+#define RT_NS_1MS               UINT32_C(1000000)
+/** 100 microseconds expressed in nanoseconds. */
+#define RT_NS_100US             UINT32_C(100000)
+/** 10 microseconds expressed in nanoseconds. */
+#define RT_NS_10US              UINT32_C(10000)
+/** 1 microsecond expressed in nanoseconds. */
+#define RT_NS_1US               UINT32_C(1000)
+
+/** 1 second expressed in nanoseconds - 64-bit type. */
+#define RT_NS_1SEC_64           UINT64_C(1000000000)
+/** 100 millsecond expressed in nanoseconds - 64-bit type. */
+#define RT_NS_100MS_64          UINT64_C(100000000)
+/** 10 millsecond expressed in nanoseconds - 64-bit type. */
+#define RT_NS_10MS_64           UINT64_C(10000000)
+/** 1 millsecond expressed in nanoseconds - 64-bit type. */
+#define RT_NS_1MS_64            UINT64_C(1000000)
+/** 100 microseconds expressed in nanoseconds - 64-bit type. */
+#define RT_NS_100US_64          UINT64_C(100000)
+/** 10 microseconds expressed in nanoseconds - 64-bit type. */
+#define RT_NS_10US_64           UINT64_C(10000)
+/** 1 microsecond expressed in nanoseconds - 64-bit type. */
+#define RT_NS_1US_64            UINT64_C(1000)
+
+/** 1 hour expressed in microseconds. */
+#define RT_US_1HOUR             UINT32_C(3600000000)
+/** 1 minute expressed in microseconds. */
+#define RT_US_1MIN              UINT32_C(60000000)
+/** 1 second expressed in microseconds. */
+#define RT_US_1SEC              UINT32_C(1000000)
+/** 100 millsecond expressed in microseconds. */
+#define RT_US_100MS             UINT32_C(100000)
+/** 10 millsecond expressed in microseconds. */
+#define RT_US_10MS              UINT32_C(10000)
+/** 1 millsecond expressed in microseconds. */
+#define RT_US_1MS               UINT32_C(1000)
+
+/** 1 hour expressed in microseconds - 64-bit type. */
+#define RT_US_1HOUR_64          UINT64_C(3600000000)
+/** 1 minute expressed in microseconds - 64-bit type. */
+#define RT_US_1MIN_64           UINT64_C(60000000)
+/** 1 second expressed in microseconds - 64-bit type. */
+#define RT_US_1SEC_64           UINT64_C(1000000)
+/** 100 millsecond expressed in microseconds - 64-bit type. */
+#define RT_US_100MS_64          UINT64_C(100000)
+/** 10 millsecond expressed in microseconds - 64-bit type. */
+#define RT_US_10MS_64           UINT64_C(10000)
+/** 1 millsecond expressed in microseconds - 64-bit type. */
+#define RT_US_1MS_64            UINT64_C(1000)
+
+/** 1 hour expressed in milliseconds. */
+#define RT_MS_1HOUR             UINT32_C(3600000)
+/** 1 minute expressed in milliseconds. */
+#define RT_MS_1MIN              UINT32_C(60000)
+/** 1 second expressed in milliseconds. */
+#define RT_MS_1SEC              UINT32_C(1000)
+
+/** 1 hour expressed in milliseconds - 64-bit type. */
+#define RT_MS_1HOUR_64          UINT64_C(3600000)
+/** 1 minute expressed in milliseconds - 64-bit type. */
+#define RT_MS_1MIN_64           UINT64_C(60000)
+/** 1 second expressed in milliseconds - 64-bit type. */
+#define RT_MS_1SEC_64           UINT64_C(1000)
+
+/** The number of seconds per week. */
+#define RT_SEC_1WEEK            UINT32_C(604800)
+/** The number of seconds per day. */
+#define RT_SEC_1DAY             UINT32_C(86400)
+/** The number of seconds per hour. */
+#define RT_SEC_1HOUR            UINT32_C(3600)
+
+/** The number of seconds per week - 64-bit type. */
+#define RT_SEC_1WEEK_64         UINT64_C(604800)
+/** The number of seconds per day - 64-bit type. */
+#define RT_SEC_1DAY_64          UINT64_C(86400)
+/** The number of seconds per hour - 64-bit type. */
+#define RT_SEC_1HOUR_64         UINT64_C(3600)
+/** @}  */
+
+
+/** @defgroup grp_rt_cdefs_dbgtype  Debug Info Types
+ * @{ */
+/** Other format. */
+#define RT_DBGTYPE_OTHER        RT_BIT_32(0)
+/** Stabs. */
+#define RT_DBGTYPE_STABS        RT_BIT_32(1)
+/** Debug With Arbitrary Record Format (DWARF). */
+#define RT_DBGTYPE_DWARF        RT_BIT_32(2)
+/** Microsoft Codeview debug info. */
+#define RT_DBGTYPE_CODEVIEW     RT_BIT_32(3)
+/** Watcom debug info. */
+#define RT_DBGTYPE_WATCOM       RT_BIT_32(4)
+/** IBM High Level Language debug info. */
+#define RT_DBGTYPE_HLL          RT_BIT_32(5)
+/** Old OS/2 and Windows symbol file. */
+#define RT_DBGTYPE_SYM          RT_BIT_32(6)
+/** Map file. */
+#define RT_DBGTYPE_MAP          RT_BIT_32(7)
+/** @} */
+
+
+/** @defgroup grp_rt_cdefs_exetype  Executable Image Types
+ * @{ */
+/** Some other format. */
+#define RT_EXETYPE_OTHER        RT_BIT_32(0)
+/** Portable Executable. */
+#define RT_EXETYPE_PE           RT_BIT_32(1)
+/** Linear eXecutable. */
+#define RT_EXETYPE_LX           RT_BIT_32(2)
+/** Linear Executable. */
+#define RT_EXETYPE_LE           RT_BIT_32(3)
+/** New Executable. */
+#define RT_EXETYPE_NE           RT_BIT_32(4)
+/** DOS Executable (Mark Zbikowski). */
+#define RT_EXETYPE_MZ           RT_BIT_32(5)
+/** COM Executable. */
+#define RT_EXETYPE_COM          RT_BIT_32(6)
+/** a.out Executable. */
+#define RT_EXETYPE_AOUT         RT_BIT_32(7)
+/** Executable and Linkable Format. */
+#define RT_EXETYPE_ELF          RT_BIT_32(8)
+/** Mach-O Executable (including FAT ones). */
+#define RT_EXETYPE_MACHO        RT_BIT_32(9)
+/** TE from UEFI. */
+#define RT_EXETYPE_TE           RT_BIT_32(9)
+/** @} */
+
+
+/** @def VALID_PTR
+ * Pointer validation macro.
+ * @param   ptr         The pointer.
+ */
+#if defined(RT_ARCH_AMD64)
+# ifdef IN_RING3
+#  if defined(RT_OS_DARWIN) /* first 4GB is reserved for legacy kernel. */
+#   define RT_VALID_PTR(ptr)    (   (uintptr_t)(ptr) >= _4G \
+                                 && !((uintptr_t)(ptr) & 0xffff800000000000ULL) )
+#  elif defined(RT_OS_SOLARIS) /* The kernel only used the top 2TB, but keep it simple. */
+#   define RT_VALID_PTR(ptr)    (   (uintptr_t)(ptr) + 0x1000U >= 0x2000U \
+                                 && (   ((uintptr_t)(ptr) & 0xffff800000000000ULL) == 0xffff800000000000ULL \
+                                     || ((uintptr_t)(ptr) & 0xffff800000000000ULL) == 0) )
+#  else
+#   define RT_VALID_PTR(ptr)    (   (uintptr_t)(ptr) + 0x1000U >= 0x2000U \
+                                 && !((uintptr_t)(ptr) & 0xffff800000000000ULL) )
+#  endif
+# else /* !IN_RING3 */
+#  define RT_VALID_PTR(ptr)     (   (uintptr_t)(ptr) + 0x1000U >= 0x2000U \
+                                 && (   ((uintptr_t)(ptr) & 0xffff800000000000ULL) == 0xffff800000000000ULL \
+                                     || ((uintptr_t)(ptr) & 0xffff800000000000ULL) == 0) )
+# endif /* !IN_RING3 */
+
+#elif defined(RT_ARCH_X86)
+# define RT_VALID_PTR(ptr)      ( (uintptr_t)(ptr) + 0x1000U >= 0x2000U )
+
+#elif defined(RT_ARCH_SPARC64)
+# ifdef IN_RING3
+#  if defined(RT_OS_SOLARIS)
+/** Sparc64 user mode: According to Figure 9.4 in solaris internals */
+/** @todo #   define RT_VALID_PTR(ptr)    ( (uintptr_t)(ptr) + 0x80004000U >= 0x80004000U + 0x100000000ULL ) - figure this. */
+#   define RT_VALID_PTR(ptr)    ( (uintptr_t)(ptr) + 0x80000000U >= 0x80000000U + 0x100000000ULL )
+#  else
+#   error "Port me"
+#  endif
+# else  /* !IN_RING3 */
+#  if defined(RT_OS_SOLARIS)
+/** @todo Sparc64 kernel mode: This is according to Figure 11.1 in solaris
+ *        internals. Verify in sources. */
+#   define RT_VALID_PTR(ptr)    ( (uintptr_t)(ptr) >= 0x01000000U )
+#  else
+#   error "Port me"
+#  endif
+# endif /* !IN_RING3 */
+
+#elif defined(RT_ARCH_SPARC)
+# ifdef IN_RING3
+#  ifdef RT_OS_SOLARIS
+/** Sparc user mode: According to
+ * http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/sun4/os/startup.c#510 */
+#   define RT_VALID_PTR(ptr)    ( (uintptr_t)(ptr) + 0x400000U >= 0x400000U + 0x2000U )
+
+#  else
+#   error "Port me"
+#  endif
+# else  /* !IN_RING3 */
+#  ifdef RT_OS_SOLARIS
+/** @todo Sparc kernel mode: Check the sources! */
+#   define RT_VALID_PTR(ptr)    ( (uintptr_t)(ptr) + 0x1000U >= 0x2000U )
+#  else
+#   error "Port me"
+#  endif
+# endif /* !IN_RING3 */
+
+#elif defined(RT_ARCH_ARM)
+/* ASSUMES that at least the last and first 4K are out of bounds. */
+# define RT_VALID_PTR(ptr)      ( (uintptr_t)(ptr) + 0x1000U >= 0x2000U )
+
+#else
+# error "Architecture identifier missing / not implemented."
+#endif
+
+/** Old name for RT_VALID_PTR.  */
+#define VALID_PTR(ptr)          RT_VALID_PTR(ptr)
+
+/** @def RT_VALID_ALIGNED_PTR
+ * Pointer validation macro that also checks the alignment.
+ * @param   ptr         The pointer.
+ * @param   align       The alignment, must be a power of two.
+ */
+#define RT_VALID_ALIGNED_PTR(ptr, align)   \
+    (   !((uintptr_t)(ptr) & (uintptr_t)((align) - 1)) \
+     && VALID_PTR(ptr) )
+
+
+/** @def VALID_PHYS32
+ * 32 bits physical address validation macro.
+ * @param   Phys          The RTGCPHYS address.
+ */
+#define VALID_PHYS32(Phys)  ( (uint64_t)(Phys) < (uint64_t)_4G )
+
+/** @def N_
+ * The \#define N_ is used to mark a string for translation. This is usable in
+ * any part of the code, as it is only used by the tools that create message
+ * catalogs. This macro is a no-op as far as the compiler and code generation
+ * is concerned.
+ *
+ * If you want to both mark a string for translation and translate it, use _().
+ */
+#define N_(s) (s)
+
+/** @def _
+ * The \#define _ is used to mark a string for translation and to translate it
+ * in one step.
+ *
+ * If you want to only mark a string for translation, use N_().
+ */
+#define _(s) gettext(s)
+
+
+/** @def __PRETTY_FUNCTION__
+ *  With GNU C we'd like to use the builtin __PRETTY_FUNCTION__, so define that
+ *  for the other compilers.
+ */
+#if !defined(__GNUC__) && !defined(__PRETTY_FUNCTION__)
+# ifdef _MSC_VER
+#  define __PRETTY_FUNCTION__    __FUNCSIG__
+# else
+#  define __PRETTY_FUNCTION__    __FUNCTION__
+# endif
+#endif
+
+
+/** @def RT_STRICT
+ * The \#define RT_STRICT controls whether or not assertions and other runtime
+ * checks should be compiled in or not.  This is defined when DEBUG is defined.
+ * If RT_NO_STRICT is defined, it will unconditionally be undefined.
+ *
+ * If you want assertions which are not subject to compile time options use
+ * the AssertRelease*() flavors.
+ */
+#if !defined(RT_STRICT) && defined(DEBUG)
+# define RT_STRICT
+#endif
+#ifdef RT_NO_STRICT
+# undef RT_STRICT
+#endif
+
+/** @todo remove this: */
+#if !defined(RT_LOCK_STRICT) && !defined(DEBUG_bird)
+# define RT_LOCK_NO_STRICT
+#endif
+#if !defined(RT_LOCK_STRICT_ORDER) && !defined(DEBUG_bird)
+# define RT_LOCK_NO_STRICT_ORDER
+#endif
+
+/** @def RT_LOCK_STRICT
+ * The \#define RT_LOCK_STRICT controls whether deadlock detection and related
+ * checks are done in the lock and semaphore code.  It is by default enabled in
+ * RT_STRICT builds, but this behavior can be overridden by defining
+ * RT_LOCK_NO_STRICT. */
+#if !defined(RT_LOCK_STRICT) && !defined(RT_LOCK_NO_STRICT) && defined(RT_STRICT)
+# define RT_LOCK_STRICT
+#endif
+/** @def RT_LOCK_NO_STRICT
+ * The \#define RT_LOCK_NO_STRICT disables RT_LOCK_STRICT.  */
+#if defined(RT_LOCK_NO_STRICT) && defined(RT_LOCK_STRICT)
+# undef RT_LOCK_STRICT
+#endif
+
+/** @def RT_LOCK_STRICT_ORDER
+ * The \#define RT_LOCK_STRICT_ORDER controls whether locking order is checked
+ * by the lock and semaphore code.  It is by default enabled in RT_STRICT
+ * builds, but this behavior can be overridden by defining
+ * RT_LOCK_NO_STRICT_ORDER. */
+#if !defined(RT_LOCK_STRICT_ORDER) && !defined(RT_LOCK_NO_STRICT_ORDER) && defined(RT_STRICT)
+# define RT_LOCK_STRICT_ORDER
+#endif
+/** @def RT_LOCK_NO_STRICT_ORDER
+ * The \#define RT_LOCK_NO_STRICT_ORDER disables RT_LOCK_STRICT_ORDER.  */
+#if defined(RT_LOCK_NO_STRICT_ORDER) && defined(RT_LOCK_STRICT_ORDER)
+# undef RT_LOCK_STRICT_ORDER
+#endif
+
+
+/** Source position. */
+#define RT_SRC_POS         __FILE__, __LINE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__
+
+/** Source position declaration. */
+#define RT_SRC_POS_DECL    const char *pszFile, unsigned iLine, const char *pszFunction
+
+/** Source position arguments. */
+#define RT_SRC_POS_ARGS    pszFile, iLine, pszFunction
+
+/** Applies NOREF() to the source position arguments. */
+#define RT_SRC_POS_NOREF() do { NOREF(pszFile); NOREF(iLine); NOREF(pszFunction); } while (0)
+
+
+/** @def RT_INLINE_ASM_EXTERNAL
+ * Defined as 1 if the compiler does not support inline assembly.
+ * The ASM* functions will then be implemented in external .asm files.
+ */
+#if (defined(_MSC_VER) && defined(RT_ARCH_AMD64)) \
+ || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86)) \
+ || defined(__WATCOMC__)
+# define RT_INLINE_ASM_EXTERNAL 1
+#else
+# define RT_INLINE_ASM_EXTERNAL 0
+#endif
+
+/** @def RT_INLINE_ASM_GNU_STYLE
+ * Defined as 1 if the compiler understands GNU style inline assembly.
+ */
+#if defined(_MSC_VER) || defined(__WATCOMC__)
+# define RT_INLINE_ASM_GNU_STYLE 0
+#else
+# define RT_INLINE_ASM_GNU_STYLE 1
+#endif
+
+/** @def RT_INLINE_ASM_USES_INTRIN
+ * Defined as the major MSC version if the compiler have and uses intrin.h.
+ * Otherwise it is 0. */
+#ifdef _MSC_VER
+# if   _MSC_VER >= 1700 /* Visual C++ v11.0 / 2012 */
+#  define RT_INLINE_ASM_USES_INTRIN 17
+# elif _MSC_VER >= 1600 /* Visual C++ v10.0 / 2010 */
+#  define RT_INLINE_ASM_USES_INTRIN 16
+# elif _MSC_VER >= 1500 /* Visual C++ v9.0 / 2008 */
+#  define RT_INLINE_ASM_USES_INTRIN 15
+# elif _MSC_VER >= 1400 /* Visual C++ v8.0 / 2005 */
+#  define RT_INLINE_ASM_USES_INTRIN 14
+# endif
+#endif
+#ifndef RT_INLINE_ASM_USES_INTRIN
+# define RT_INLINE_ASM_USES_INTRIN 0
+#endif
+
+/** @def RT_COMPILER_SUPPORTS_LAMBDA
+ * If the defined, the compiler supports lambda expressions.   These expressions
+ * are useful for embedding assertions and type checks into macros. */
+#if defined(_MSC_VER) && defined(__cplusplus)
+# if _MSC_VER >= 1600 /* Visual C++ v10.0 / 2010 */
+#  define RT_COMPILER_SUPPORTS_LAMBDA
+# endif
+#elif defined(__GNUC__) && defined(__cplusplus)
+/* 4.5 or later, I think, if in ++11 mode... */
+#endif
+
+/** @def RT_FAR_DATA
+ * Set to 1 if we're in 16-bit mode and use far pointers.
+ */
+#if ARCH_BITS == 16 && defined(__WATCOMC__) \
+  && (defined(__COMPACT__) || defined(__LARGE__))
+# define RT_FAR_DATA 1
+#else
+# define RT_FAR_DATA 0
+#endif
+
+/** @} */
+
+
+/** @defgroup grp_rt_cdefs_cpp  Special Macros for C++
+ * @ingroup grp_rt_cdefs
+ * @{
+ */
+
+#ifdef __cplusplus
+
+/** @def DECLEXPORT_CLASS
+ * How to declare an exported class. Place this macro after the 'class'
+ * keyword in the declaration of every class you want to export.
+ *
+ * @note It is necessary to use this macro even for inner classes declared
+ * inside the already exported classes. This is a GCC specific requirement,
+ * but it seems not to harm other compilers.
+ */
+#if defined(_MSC_VER) || defined(RT_OS_OS2)
+# define DECLEXPORT_CLASS       __declspec(dllexport)
+#elif defined(RT_USE_VISIBILITY_DEFAULT)
+# define DECLEXPORT_CLASS       __attribute__((visibility("default")))
+#else
+# define DECLEXPORT_CLASS
+#endif
+
+/** @def DECLIMPORT_CLASS
+ * How to declare an imported class Place this macro after the 'class'
+ * keyword in the declaration of every class you want to export.
+ *
+ * @note It is necessary to use this macro even for inner classes declared
+ * inside the already exported classes. This is a GCC specific requirement,
+ * but it seems not to harm other compilers.
+ */
+#if defined(_MSC_VER) || (defined(RT_OS_OS2) && !defined(__IBMC__) && !defined(__IBMCPP__))
+# define DECLIMPORT_CLASS       __declspec(dllimport)
+#elif defined(RT_USE_VISIBILITY_DEFAULT)
+# define DECLIMPORT_CLASS       __attribute__((visibility("default")))
+#else
+# define DECLIMPORT_CLASS
+#endif
+
+/** @def WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP
+ * Macro to work around error C2593 of the not-so-smart MSVC 7.x ambiguity
+ * resolver. The following snippet clearly demonstrates the code causing this
+ * error:
+ * @code
+ *      class A
+ *      {
+ *      public:
+ *          operator bool() const { return false; }
+ *          operator int*() const { return NULL; }
+ *      };
+ *      int main()
+ *      {
+ *          A a;
+ *          if (!a);
+ *          if (a && 0);
+ *          return 0;
+ *      }
+ * @endcode
+ * The code itself seems pretty valid to me and GCC thinks the same.
+ *
+ * This macro fixes the compiler error by explicitly overloading implicit
+ * global operators !, && and || that take the given class instance as one of
+ * their arguments.
+ *
+ * The best is to use this macro right after the class declaration.
+ *
+ * @note The macro expands to nothing for compilers other than MSVC.
+ *
+ * @param Cls Class to apply the workaround to
+ */
+#if defined(_MSC_VER)
+# define WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP(Cls) \
+    inline bool operator! (const Cls &that) { return !bool (that); } \
+    inline bool operator&& (const Cls &that, bool b) { return bool (that) && b; } \
+    inline bool operator|| (const Cls &that, bool b) { return bool (that) || b; } \
+    inline bool operator&& (bool b, const Cls &that) { return b && bool (that); } \
+    inline bool operator|| (bool b, const Cls &that) { return b || bool (that); }
+#else
+# define WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP(Cls)
+#endif
+
+/** @def WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP_TPL
+ * Version of WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP for template classes.
+ *
+ * @param Tpl       Name of the template class to apply the workaround to
+ * @param ArgsDecl  arguments of the template, as declared in |<>| after the
+ *                  |template| keyword, including |<>|
+ * @param Args      arguments of the template, as specified in |<>| after the
+ *                  template class name when using the, including |<>|
+ *
+ * Example:
+ * @code
+ *      // template class declaration
+ *      template <class C>
+ *      class Foo { ... };
+ *      // applied workaround
+ *      WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP_TPL (Foo, <class C>, <C>)
+ * @endcode
+ */
+#if defined(_MSC_VER)
+# define WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP_TPL(Tpl, ArgsDecl, Args) \
+    template ArgsDecl \
+    inline bool operator! (const Tpl Args &that) { return !bool (that); } \
+    template ArgsDecl \
+    inline bool operator&& (const Tpl Args  &that, bool b) { return bool (that) && b; } \
+    template ArgsDecl \
+    inline bool operator|| (const Tpl Args  &that, bool b) { return bool (that) || b; } \
+    template ArgsDecl \
+    inline bool operator&& (bool b, const Tpl Args  &that) { return b && bool (that); } \
+    template ArgsDecl \
+    inline bool operator|| (bool b, const Tpl Args  &that) { return b || bool (that); }
+#else
+# define WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP_TPL(Tpl, ArgsDecl, Args)
+#endif
+
+
+/** @def DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP
+ * Declares the copy constructor and the assignment operation as inlined no-ops
+ * (non-existent functions) for the given class. Use this macro inside the
+ * private section if you want to effectively disable these operations for your
+ * class.
+ *
+ * @param      Cls     class name to declare for
+ */
+#define DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(Cls) \
+    inline Cls(const Cls &); \
+    inline Cls &operator= (const Cls &)
+
+
+/** @def DECLARE_CLS_NEW_DELETE_NOOP
+ * Declares the new and delete operations as no-ops (non-existent functions)
+ * for the given class. Use this macro inside the private section if you want
+ * to effectively limit creating class instances on the stack only.
+ *
+ * @note The destructor of the given class must not be virtual, otherwise a
+ * compile time error will occur. Note that this is not a drawback: having
+ * the virtual destructor for a stack-based class is absolutely useless
+ * (the real class of the stack-based instance is always known to the compiler
+ * at compile time, so it will always call the correct destructor).
+ *
+ * @param      Cls     class name to declare for
+ */
+#define DECLARE_CLS_NEW_DELETE_NOOP(Cls) \
+    inline static void *operator new (size_t); \
+    inline static void operator delete (void *)
+
+#endif /* __cplusplus */
+
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/cpuset.h b/ubuntu/vbox/include/iprt/cpuset.h
new file mode 100644 (file)
index 0000000..e929409
--- /dev/null
@@ -0,0 +1,340 @@
+/** @file
+ * IPRT - CPU Set.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+#ifndef ___iprt_cpuset_h
+#define ___iprt_cpuset_h
+
+#include <iprt/types.h>
+#include <iprt/mp.h> /* RTMpCpuIdToSetIndex */
+#include <iprt/asm.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_cpuset RTCpuSet - CPU Set
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/**
+ * Clear all CPUs.
+ *
+ * @returns pSet.
+ * @param   pSet    Pointer to the set.
+ */
+DECLINLINE(PRTCPUSET) RTCpuSetEmpty(PRTCPUSET pSet)
+{
+    size_t i;
+    for (i = 0; i < RT_ELEMENTS(pSet->bmSet); i++)
+        pSet->bmSet[i] = 0;
+    return pSet;
+}
+
+
+/**
+ * Set all CPUs.
+ *
+ * @returns pSet.
+ * @param   pSet    Pointer to the set.
+ */
+DECLINLINE(PRTCPUSET) RTCpuSetFill(PRTCPUSET pSet)
+{
+    size_t i;
+    for (i = 0; i < RT_ELEMENTS(pSet->bmSet); i++)
+        pSet->bmSet[i] = UINT64_MAX;
+    return pSet;
+}
+
+
+/**
+ * Copies one set to another.
+ *
+ * @param   pDst    Pointer to the destination set.
+ * @param   pSrc    Pointer to the source set.
+ */
+DECLINLINE(void) RTCpuSetCopy(PRTCPUSET pDst, PRTCPUSET pSrc)
+{
+    size_t i;
+    for (i = 0; i < RT_ELEMENTS(pDst->bmSet); i++)
+        pDst->bmSet[i] = pSrc->bmSet[i];
+}
+
+
+/**
+ * ANDs the given CPU set with another.
+ *
+ * @returns pSet.
+ * @param   pSet          Pointer to the set.
+ * @param   pAndMaskSet   Pointer to the AND-mask set.
+ */
+DECLINLINE(PRTCPUSET) RTCpuSetAnd(PRTCPUSET pSet, PRTCPUSET pAndMaskSet)
+{
+    size_t i;
+    for (i = 0; i < RT_ELEMENTS(pSet->bmSet); i++)
+        ASMAtomicAndU64((volatile uint64_t *)&pSet->bmSet[i], pAndMaskSet->bmSet[i]);
+    return pSet;
+}
+
+
+/**
+ * Adds a CPU given by its identifier to the set.
+ *
+ * @returns 0 on success, -1 if idCpu isn't valid.
+ * @param   pSet    Pointer to the set.
+ * @param   idCpu   The identifier of the CPU to add.
+ * @remarks The modification is atomic.
+ */
+DECLINLINE(int) RTCpuSetAdd(PRTCPUSET pSet, RTCPUID idCpu)
+{
+    int iCpu = RTMpCpuIdToSetIndex(idCpu);
+    if (RT_LIKELY(iCpu >= 0))
+    {
+        ASMAtomicBitSet(pSet, iCpu);
+        return 0;
+    }
+    return -1;
+}
+
+
+/**
+ * Adds a CPU given by its identifier to the set.
+ *
+ * @returns 0 on success, -1 if iCpu isn't valid.
+ * @param   pSet    Pointer to the set.
+ * @param   iCpu    The index of the CPU to add.
+ * @remarks The modification is atomic.
+ */
+DECLINLINE(int) RTCpuSetAddByIndex(PRTCPUSET pSet, int iCpu)
+{
+    if (RT_LIKELY((unsigned)iCpu < RTCPUSET_MAX_CPUS))
+    {
+        ASMAtomicBitSet(pSet, iCpu);
+        return 0;
+    }
+    return -1;
+}
+
+
+/**
+ * Removes a CPU given by its identifier from the set.
+ *
+ * @returns 0 on success, -1 if idCpu isn't valid.
+ * @param   pSet    Pointer to the set.
+ * @param   idCpu   The identifier of the CPU to delete.
+ * @remarks The modification is atomic.
+ */
+DECLINLINE(int) RTCpuSetDel(PRTCPUSET pSet, RTCPUID idCpu)
+{
+    int iCpu = RTMpCpuIdToSetIndex(idCpu);
+    if (RT_LIKELY(iCpu >= 0))
+    {
+        ASMAtomicBitClear(pSet, iCpu);
+        return 0;
+    }
+    return -1;
+}
+
+
+/**
+ * Removes a CPU given by its index from the set.
+ *
+ * @returns 0 on success, -1 if iCpu isn't valid.
+ * @param   pSet    Pointer to the set.
+ * @param   iCpu    The index of the CPU to delete.
+ * @remarks The modification is atomic.
+ */
+DECLINLINE(int) RTCpuSetDelByIndex(PRTCPUSET pSet, int iCpu)
+{
+    if (RT_LIKELY((unsigned)iCpu < RTCPUSET_MAX_CPUS))
+    {
+        ASMAtomicBitClear(pSet, iCpu);
+        return 0;
+    }
+    return -1;
+}
+
+
+/**
+ * Checks if a CPU given by its identifier is a member of the set.
+ *
+ * @returns true / false accordingly.
+ * @param   pSet    Pointer to the set.
+ * @param   idCpu   The identifier of the CPU to look for.
+ * @remarks The test is atomic.
+ */
+DECLINLINE(bool) RTCpuSetIsMember(PCRTCPUSET pSet, RTCPUID idCpu)
+{
+    int iCpu = RTMpCpuIdToSetIndex(idCpu);
+    if (RT_LIKELY(iCpu >= 0))
+        return ASMBitTest((volatile void *)pSet, iCpu);
+    return false;
+}
+
+
+/**
+ * Checks if a CPU given by its index is a member of the set.
+ *
+ * @returns true / false accordingly.
+ * @param   pSet    Pointer to the set.
+ * @param   iCpu    The index of the CPU in the set.
+ * @remarks The test is atomic.
+ */
+DECLINLINE(bool) RTCpuSetIsMemberByIndex(PCRTCPUSET pSet, int iCpu)
+{
+    if (RT_LIKELY((unsigned)iCpu < RTCPUSET_MAX_CPUS))
+        return ASMBitTest((volatile void *)pSet, iCpu);
+    return false;
+}
+
+
+/**
+ * Checks if the two sets match or not.
+ *
+ * @returns true / false accordingly.
+ * @param   pSet1       The first set.
+ * @param   pSet2       The second set.
+ */
+DECLINLINE(bool) RTCpuSetIsEqual(PCRTCPUSET pSet1, PCRTCPUSET pSet2)
+{
+    size_t i;
+    for (i = 0; i < RT_ELEMENTS(pSet1->bmSet); i++)
+        if (pSet1->bmSet[i] != pSet2->bmSet[i])
+            return false;
+    return true;
+}
+
+
+/**
+ * Checks if the CPU set is empty or not.
+ *
+ * @returns true / false accordingly.
+ * @param   pSet    Pointer to the set.
+ */
+DECLINLINE(bool) RTCpuSetIsEmpty(PRTCPUSET pSet)
+{
+    size_t i;
+    for (i = 0; i < RT_ELEMENTS(pSet->bmSet); i++)
+        if (pSet->bmSet[i])
+            return false;
+    return true;
+}
+
+
+/**
+ * Converts the CPU set to a 64-bit mask.
+ *
+ * @returns The mask.
+ * @param   pSet    Pointer to the set.
+ * @remarks Use with extreme care as it may lose information!
+ */
+DECLINLINE(uint64_t) RTCpuSetToU64(PCRTCPUSET pSet)
+{
+    return pSet->bmSet[0];
+}
+
+
+/**
+ * Initializes the CPU set from a 64-bit mask.
+ *
+ * @param   pSet    Pointer to the set.
+ * @param   fMask   The mask.
+ */
+DECLINLINE(PRTCPUSET) RTCpuSetFromU64(PRTCPUSET pSet, uint64_t fMask)
+{
+    size_t i;
+
+    pSet->bmSet[0] = fMask;
+    for (i = 1; i < RT_ELEMENTS(pSet->bmSet); i++)
+        pSet->bmSet[i] = 0;
+
+    return pSet;
+}
+
+
+/**
+ * Count the CPUs in the set.
+ *
+ * @returns CPU count.
+ * @param   pSet    Pointer to the set.
+ */
+DECLINLINE(int) RTCpuSetCount(PCRTCPUSET pSet)
+{
+    int         cCpus = 0;
+    size_t      i;
+
+    for (i = 0; i < RT_ELEMENTS(pSet->bmSet); i++)
+    {
+        uint64_t u64 = pSet->bmSet[i];
+        if (u64 != 0)
+        {
+            unsigned iCpu = 64;
+            while (iCpu-- > 0)
+            {
+                if (u64 & 1)
+                    cCpus++;
+                u64 >>= 1;
+            }
+        }
+    }
+    return cCpus;
+}
+
+
+/**
+ * Get the highest set index.
+ *
+ * @returns The higest set index, -1 if all bits are clear.
+ * @param   pSet    Pointer to the set.
+ */
+DECLINLINE(int) RTCpuLastIndex(PCRTCPUSET pSet)
+{
+    size_t i = RT_ELEMENTS(pSet->bmSet);
+    while (i-- > 0)
+    {
+        uint64_t u64 = pSet->bmSet[i];
+        if (u64)
+        {
+            /* There are more efficient ways to do this in asm.h... */
+            unsigned iBit;
+            for (iBit = 63; iBit > 0; iBit--)
+            {
+                if (u64 & RT_BIT_64(63))
+                    break;
+                u64 <<= 1;
+            }
+            return (int)i * 64 + iBit;
+        }
+    }
+    return 0;
+}
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/ctype.h b/ubuntu/vbox/include/iprt/ctype.h
new file mode 100644 (file)
index 0000000..010c7ac
--- /dev/null
@@ -0,0 +1,240 @@
+/** @file
+ * IPRT - Simple character type classiciation and conversion.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_ctype_h
+#define ___iprt_ctype_h
+
+#include <iprt/types.h>
+
+/** @name C locale predicates and conversions.
+ *
+ * For most practical purposes, this can safely be used when parsing UTF-8
+ * strings.  Just keep in mind that we only deal with the first 127 chars and
+ * that full correctness is only archived using the non-existing RTLocIs* API.
+ *
+ * @remarks Use the marcros, not the inlined functions.
+ *
+ * @remarks ASSUMES the source code includes the basic ASCII chars. This is a
+ *          general IPRT assumption.
+ * @{ */
+#define RT_C_IS_BLANK(ch)   RTLocCIsBlank((ch))
+#define RT_C_IS_ALNUM(ch)   RTLocCIsAlNum((ch))
+#define RT_C_IS_ALPHA(ch)   RTLocCIsAlpha((ch))
+#define RT_C_IS_CNTRL(ch)   RTLocCIsCntrl((ch))
+#define RT_C_IS_DIGIT(ch)   RTLocCIsDigit((ch))
+#define RT_C_IS_LOWER(ch)   RTLocCIsLower((ch))
+#define RT_C_IS_GRAPH(ch)   RTLocCIsGraph((ch))
+#define RT_C_IS_ODIGIT(ch)  RTLocCIsODigit((ch))
+#define RT_C_IS_PRINT(ch)   RTLocCIsPrint((ch))
+#define RT_C_IS_PUNCT(ch)   RTLocCIsPunct((ch))
+#define RT_C_IS_SPACE(ch)   RTLocCIsSpace((ch))
+#define RT_C_IS_UPPER(ch)   RTLocCIsUpper((ch))
+#define RT_C_IS_XDIGIT(ch)  RTLocCIsXDigit((ch))
+
+#define RT_C_TO_LOWER(ch)   RTLocCToLower((ch))
+#define RT_C_TO_UPPER(ch)   RTLocCToUpper((ch))
+
+/**
+ * Checks for a blank character.
+ *
+ * @returns true / false.
+ * @param   ch      The character to test.
+ */
+DECL_FORCE_INLINE(bool) RTLocCIsBlank(int ch)
+{
+    return ch == 0x20  /* space */
+        || ch == 0x09; /* horizontal tab */
+}
+
+/**
+ * Checks for a control character.
+ *
+ * @returns true / false.
+ * @param   ch      The character to test.
+ *
+ * @note    Will return true of ch is '\0'!
+ */
+DECL_FORCE_INLINE(bool) RTLocCIsCntrl(int ch)
+{
+    return (unsigned)ch < 32U /* 0..2f */
+        || ch == 0x7f;
+}
+
+/**
+ * Checks for a decimal digit.
+ *
+ * @returns true / false.
+ * @param   ch      The character to test.
+ */
+DECL_FORCE_INLINE(bool) RTLocCIsDigit(int ch)
+{
+    return (unsigned)ch - 0x30 < 10U; /* 30..39 */
+}
+
+/**
+ * Checks for a lower case character.
+ *
+ * @returns true / false.
+ * @param   ch      The character to test.
+ */
+DECL_FORCE_INLINE(bool) RTLocCIsLower(int ch)
+{
+    return (unsigned)ch - 0x61U < 26U; /* 61..7a */
+}
+
+/**
+ * Checks for an octal digit.
+ *
+ * @returns true / false.
+ * @param   ch      The character to test.
+ */
+DECL_FORCE_INLINE(bool) RTLocCIsODigit(int ch)
+{
+    return (unsigned)ch - 0x30 < 8U; /* 30..37 */
+}
+
+/**
+ * Checks for a printable character (whitespace included).
+ *
+ * @returns true / false.
+ * @param   ch      The character to test.
+ */
+DECL_FORCE_INLINE(bool) RTLocCIsPrint(int ch)
+{
+    return (unsigned)ch - 0x20U < 95U; /* 20..7e */
+}
+
+/**
+ * Checks for punctuation (?).
+ *
+ * @returns true / false.
+ * @param   ch      The character to test.
+ */
+DECL_FORCE_INLINE(bool) RTLocCIsPunct(int ch)
+{
+    return (unsigned)ch - 0x21U < 15U /* 21..2f */
+        || (unsigned)ch - 0x2aU <  6U /* 2a..2f */
+        || (unsigned)ch - 0x3aU <  7U /* 3a..40 */
+        || (unsigned)ch - 0x5bU <  6U /* 5a..60 */
+        || (unsigned)ch - 0x7bU <  4U /* 7b..7e */;
+}
+
+/**
+ * Checks for a white-space character.
+ *
+ * @returns true / false.
+ * @param   ch      The character to test.
+ */
+DECL_FORCE_INLINE(bool) RTLocCIsSpace(int ch)
+{
+    return ch == 0x20                 /* 20 (space) */
+        || (unsigned)ch - 0x09U < 5U; /* 09..0d */
+}
+
+/**
+ * Checks for an upper case character.
+ *
+ * @returns true / false.
+ * @param   ch      The character to test.
+ */
+DECL_FORCE_INLINE(bool) RTLocCIsUpper(int ch)
+{
+    return (unsigned)ch - 0x41 < 26U; /* 41..5a */
+}
+
+/**
+ * Checks for a hexadecimal digit.
+ *
+ * @returns true / false.
+ * @param   ch      The character to test.
+ */
+DECL_FORCE_INLINE(bool) RTLocCIsXDigit(int ch)
+{
+    return (unsigned)ch - 0x30 < 10U /* 30..39 (0-9) */
+        || (unsigned)ch - 0x41 < 6   /* 41..46 (A-F) */
+        || (unsigned)ch - 0x61 < 6;  /* 61..66 (a-f) */
+}
+
+/**
+ * Checks for an alphabetic character.
+ *
+ * @returns true / false.
+ * @param   ch      The character to test.
+ */
+DECL_FORCE_INLINE(bool) RTLocCIsAlpha(int ch)
+{
+    return RTLocCIsLower(ch) || RTLocCIsUpper(ch);
+}
+
+/**
+ * Checks for an alphanumerical character.
+ *
+ * @returns true / false.
+ * @param   ch      The character to test.
+ */
+DECL_FORCE_INLINE(bool) RTLocCIsAlNum(int ch)
+{
+    return RTLocCIsDigit(ch) || RTLocCIsAlpha(ch);
+}
+
+/**
+ * Checks for a printable character whitespace excluded.
+ *
+ * @returns true / false.
+ * @param   ch      The character to test.
+ */
+DECL_FORCE_INLINE(bool) RTLocCIsGraph(int ch)
+{
+    return RTLocCIsPrint(ch) && !RTLocCIsBlank(ch);
+}
+
+
+/**
+ * Converts the character to lower case if applictable.
+ *
+ * @returns lower cased character or ch.
+ * @param   ch      The character to test.
+ */
+DECL_FORCE_INLINE(int) RTLocCToLower(int ch)
+{
+    return RTLocCIsUpper(ch) ? (ch) + 0x20 : (ch);
+}
+
+/**
+ * Converts the character to upper case if applictable.
+ *
+ * @returns upper cased character or ch.
+ * @param   ch      The character to test.
+ */
+DECL_FORCE_INLINE(int) RTLocCToUpper(int ch)
+{
+    return RTLocCIsLower(ch) ? (ch) - 0x20 : (ch);
+}
+
+
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/err.h b/ubuntu/vbox/include/iprt/err.h
new file mode 100644 (file)
index 0000000..3075b2e
--- /dev/null
@@ -0,0 +1,2565 @@
+/** @file
+ * IPRT - Status Codes.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_err_h
+#define ___iprt_err_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+
+
+/** @defgroup grp_rt_err            RTErr - Status Codes
+ * @ingroup grp_rt
+ *
+ * The IPRT status codes are in two ranges: {0..999} and {22000..32766}.  The
+ * IPRT users are free to use the range {1000..21999}.  See RTERR_RANGE1_FIRST,
+ * RTERR_RANGE1_LAST, RTERR_RANGE2_FIRST, RTERR_RANGE2_LAST, RTERR_USER_FIRST
+ * and RTERR_USER_LAST.
+ *
+ * @{
+ */
+
+/** @defgroup grp_rt_err_hlp        Status Code Helpers
+ * @{
+ */
+
+#ifdef __cplusplus
+/**
+ * Strict type validation class.
+ *
+ * This is only really useful for type checking the arguments to RT_SUCCESS,
+ * RT_SUCCESS_NP, RT_FAILURE and RT_FAILURE_NP.  The RTErrStrictType2
+ * constructor is for integration with external status code strictness regimes.
+ */
+class RTErrStrictType
+{
+protected:
+    int32_t m_rc;
+
+public:
+    /**
+     * Constructor for interaction with external status code strictness regimes.
+     *
+     * This is a special constructor for helping external return code validator
+     * classes interact cleanly with RT_SUCCESS, RT_SUCCESS_NP, RT_FAILURE and
+     * RT_FAILURE_NP while barring automatic cast to integer.
+     *
+     * @param   rcObj       IPRT status code object from an automatic cast.
+     */
+    RTErrStrictType(RTErrStrictType2 const rcObj)
+        : m_rc(rcObj.getValue())
+    {
+    }
+
+    /**
+     * Integer constructor used by RT_SUCCESS_NP.
+     *
+     * @param   rc          IPRT style status code.
+     */
+    RTErrStrictType(int32_t rc)
+        : m_rc(rc)
+    {
+    }
+
+#if 0 /** @todo figure where int32_t is long instead of int. */
+    /**
+     * Integer constructor used by RT_SUCCESS_NP.
+     *
+     * @param   rc          IPRT style status code.
+     */
+    RTErrStrictType(signed int rc)
+        : m_rc(rc)
+    {
+    }
+#endif
+
+    /**
+     * Test for success.
+     */
+    bool success() const
+    {
+        return m_rc >= 0;
+    }
+
+private:
+    /** @name Try ban a number of wrong types.
+     * @{ */
+    RTErrStrictType(uint8_t rc)         : m_rc(-999) { NOREF(rc); }
+    RTErrStrictType(uint16_t rc)        : m_rc(-999) { NOREF(rc); }
+    RTErrStrictType(uint32_t rc)        : m_rc(-999) { NOREF(rc); }
+    RTErrStrictType(uint64_t rc)        : m_rc(-999) { NOREF(rc); }
+    RTErrStrictType(int8_t rc)          : m_rc(-999) { NOREF(rc); }
+    RTErrStrictType(int16_t rc)         : m_rc(-999) { NOREF(rc); }
+    RTErrStrictType(int64_t rc)         : m_rc(-999) { NOREF(rc); }
+    /** @todo fight long here - clashes with int32_t/int64_t on some platforms. */
+    /** @} */
+};
+#endif /* __cplusplus */
+
+
+/** @def RTERR_STRICT_RC
+ * Indicates that RT_SUCCESS_NP, RT_SUCCESS, RT_FAILURE_NP and RT_FAILURE should
+ * make type enforcing at compile time.
+ *
+ * @remarks     Only define this for C++ code.
+ */
+#if defined(__cplusplus) \
+ && !defined(RTERR_STRICT_RC) \
+ && (   defined(DOXYGEN_RUNNING) \
+     || defined(DEBUG) \
+     || defined(RT_STRICT) )
+# define RTERR_STRICT_RC        1
+#endif
+
+
+/** @def RT_SUCCESS
+ * Check for success. We expect success in normal cases, that is the code path depending on
+ * this check is normally taken. To prevent any prediction use RT_SUCCESS_NP instead.
+ *
+ * @returns true if rc indicates success.
+ * @returns false if rc indicates failure.
+ *
+ * @param   rc  The iprt status code to test.
+ */
+#define RT_SUCCESS(rc)      ( RT_LIKELY(RT_SUCCESS_NP(rc)) )
+
+/** @def RT_SUCCESS_NP
+ * Check for success. Don't predict the result.
+ *
+ * @returns true if rc indicates success.
+ * @returns false if rc indicates failure.
+ *
+ * @param   rc  The iprt status code to test.
+ */
+#ifdef RTERR_STRICT_RC
+# define RT_SUCCESS_NP(rc)   ( RTErrStrictType(rc).success() )
+#else
+# define RT_SUCCESS_NP(rc)   ( (int)(rc) >= VINF_SUCCESS )
+#endif
+
+/** @def RT_FAILURE
+ * Check for failure, predicting unlikely.
+ *
+ * We don't expect in normal cases, that is the code path depending on this
+ * check is normally NOT taken. To prevent any prediction use RT_FAILURE_NP
+ * instead.
+ *
+ * @returns true if rc indicates failure.
+ * @returns false if rc indicates success.
+ *
+ * @param   rc  The iprt status code to test.
+ *
+ * @remarks Please structure your code to use the RT_SUCCESS() macro instead of
+ *          RT_FAILURE() where possible, as that gives us a better shot at good
+ *          code with the windows compilers.
+ */
+#define RT_FAILURE(rc)      ( RT_UNLIKELY(!RT_SUCCESS_NP(rc)) )
+
+/** @def RT_FAILURE_NP
+ * Check for failure, no prediction.
+ *
+ * @returns true if rc indicates failure.
+ * @returns false if rc indicates success.
+ *
+ * @param   rc  The iprt status code to test.
+ */
+#define RT_FAILURE_NP(rc)   ( !RT_SUCCESS_NP(rc) )
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Converts a Darwin HRESULT error to an iprt status code.
+ *
+ * @returns iprt status code.
+ * @param   iNativeCode    HRESULT error code.
+ * @remark  Darwin ring-3 only.
+ */
+RTDECL(int)  RTErrConvertFromDarwinCOM(int32_t iNativeCode);
+
+/**
+ * Converts a Darwin IOReturn error to an iprt status code.
+ *
+ * @returns iprt status code.
+ * @param   iNativeCode    IOReturn error code.
+ * @remark  Darwin only.
+ */
+RTDECL(int)  RTErrConvertFromDarwinIO(int iNativeCode);
+
+/**
+ * Converts a Darwin kern_return_t error to an iprt status code.
+ *
+ * @returns iprt status code.
+ * @param   iNativeCode    kern_return_t error code.
+ * @remark  Darwin only.
+ */
+RTDECL(int)  RTErrConvertFromDarwinKern(int iNativeCode);
+
+/**
+ * Converts a Darwin error to an iprt status code.
+ *
+ * This will consult RTErrConvertFromDarwinKern, RTErrConvertFromDarwinIO
+ * and RTErrConvertFromDarwinCOM in this order. The latter is ring-3 only as it
+ * doesn't apply elsewhere.
+ *
+ * @returns iprt status code.
+ * @param   iNativeCode    Darwin error code.
+ * @remarks Darwin only.
+ * @remarks This is recommended over RTErrConvertFromDarwinKern and RTErrConvertFromDarwinIO
+ *          since these are really just subsets of the same error space.
+ */
+RTDECL(int)  RTErrConvertFromDarwin(int iNativeCode);
+
+/**
+ * Converts errno to iprt status code.
+ *
+ * @returns iprt status code.
+ * @param   uNativeCode    errno code.
+ */
+RTDECL(int)  RTErrConvertFromErrno(unsigned uNativeCode);
+
+/**
+ * Converts a L4 errno to a iprt status code.
+ *
+ * @returns iprt status code.
+ * @param   uNativeCode l4 errno.
+ * @remark  L4 only.
+ */
+RTDECL(int)  RTErrConvertFromL4Errno(unsigned uNativeCode);
+
+/**
+ * Converts NT status code to iprt status code.
+ *
+ * Needless to say, this is only available on NT and winXX targets.
+ *
+ * @returns iprt status code.
+ * @param   lNativeCode    NT status code.
+ * @remark  Windows only.
+ */
+RTDECL(int)  RTErrConvertFromNtStatus(long lNativeCode);
+
+/**
+ * Converts OS/2 error code to iprt status code.
+ *
+ * @returns iprt status code.
+ * @param   uNativeCode    OS/2 error code.
+ * @remark  OS/2 only.
+ */
+RTDECL(int)  RTErrConvertFromOS2(unsigned uNativeCode);
+
+/**
+ * Converts Win32 error code to iprt status code.
+ *
+ * @returns iprt status code.
+ * @param   uNativeCode    Win32 error code.
+ * @remark  Windows only.
+ */
+RTDECL(int)  RTErrConvertFromWin32(unsigned uNativeCode);
+
+/**
+ * Converts an iprt status code to a errno status code.
+ *
+ * @returns errno status code.
+ * @param   iErr    iprt status code.
+ */
+RTDECL(int)  RTErrConvertToErrno(int iErr);
+
+#ifdef IN_RING3
+
+/**
+ * iprt status code message.
+ */
+typedef struct RTSTATUSMSG
+{
+    /** Pointer to the short message string. */
+    const char *pszMsgShort;
+    /** Pointer to the full message string. */
+    const char *pszMsgFull;
+    /** Pointer to the define string. */
+    const char *pszDefine;
+    /** Status code number. */
+    int         iCode;
+} RTSTATUSMSG;
+/** Pointer to iprt status code message. */
+typedef RTSTATUSMSG *PRTSTATUSMSG;
+/** Pointer to const iprt status code message. */
+typedef const RTSTATUSMSG *PCRTSTATUSMSG;
+
+/**
+ * Get the message structure corresponding to a given iprt status code.
+ *
+ * @returns Pointer to read-only message description.
+ * @param   rc      The status code.
+ */
+RTDECL(PCRTSTATUSMSG) RTErrGet(int rc);
+
+/**
+ * Get the define corresponding to a given iprt status code.
+ *
+ * @returns Pointer to read-only string with the \#define identifier.
+ * @param   rc      The status code.
+ */
+#define RTErrGetDefine(rc)      (RTErrGet(rc)->pszDefine)
+
+/**
+ * Get the short description corresponding to a given iprt status code.
+ *
+ * @returns Pointer to read-only string with the description.
+ * @param   rc      The status code.
+ */
+#define RTErrGetShort(rc)       (RTErrGet(rc)->pszMsgShort)
+
+/**
+ * Get the full description corresponding to a given iprt status code.
+ *
+ * @returns Pointer to read-only string with the description.
+ * @param   rc      The status code.
+ */
+#define RTErrGetFull(rc)        (RTErrGet(rc)->pszMsgFull)
+
+#ifdef RT_OS_WINDOWS
+/**
+ * Windows error code message.
+ */
+typedef struct RTWINERRMSG
+{
+    /** Pointer to the full message string. */
+    const char *pszMsgFull;
+    /** Pointer to the define string. */
+    const char *pszDefine;
+    /** Error code number. */
+    long        iCode;
+} RTWINERRMSG;
+/** Pointer to Windows error code message. */
+typedef RTWINERRMSG *PRTWINERRMSG;
+/** Pointer to const Windows error code message. */
+typedef const RTWINERRMSG *PCRTWINERRMSG;
+
+/**
+ * Get the message structure corresponding to a given Windows error code.
+ *
+ * @returns Pointer to read-only message description.
+ * @param   rc      The status code.
+ */
+RTDECL(PCRTWINERRMSG) RTErrWinGet(long rc);
+
+/** On windows COM errors are part of the Windows error database. */
+typedef RTWINERRMSG RTCOMERRMSG;
+
+#else  /* !RT_OS_WINDOWS */
+
+/**
+ * COM/XPCOM error code message.
+ */
+typedef struct RTCOMERRMSG
+{
+    /** Pointer to the full message string. */
+    const char *pszMsgFull;
+    /** Pointer to the define string. */
+    const char *pszDefine;
+    /** Error code number. */
+    uint32_t    iCode;
+} RTCOMERRMSG;
+#endif /* !RT_OS_WINDOWS */
+/** Pointer to a XPCOM/COM error code message. */
+typedef RTCOMERRMSG *PRTCOMERRMSG;
+/** Pointer to const a XPCOM/COM error code message. */
+typedef const RTCOMERRMSG *PCRTCOMERRMSG;
+
+/**
+ * Get the message structure corresponding to a given COM/XPCOM error code.
+ *
+ * @returns Pointer to read-only message description.
+ * @param   rc      The status code.
+ */
+RTDECL(PCRTCOMERRMSG) RTErrCOMGet(uint32_t rc);
+
+#endif /* IN_RING3 */
+
+/** @defgroup RTERRINFO_FLAGS_XXX   RTERRINFO::fFlags
+ * @{ */
+/** Custom structure (the default). */
+#define RTERRINFO_FLAGS_T_CUSTOM    UINT32_C(0)
+/** Static structure (RTERRINFOSTATIC). */
+#define RTERRINFO_FLAGS_T_STATIC    UINT32_C(1)
+/** Allocated structure (RTErrInfoAlloc). */
+#define RTERRINFO_FLAGS_T_ALLOC     UINT32_C(2)
+/** Reserved type. */
+#define RTERRINFO_FLAGS_T_RESERVED  UINT32_C(3)
+/** Type mask. */
+#define RTERRINFO_FLAGS_T_MASK      UINT32_C(3)
+/** Error info is set. */
+#define RTERRINFO_FLAGS_SET         RT_BIT_32(2)
+/** Fixed flags (magic). */
+#define RTERRINFO_FLAGS_MAGIC       UINT32_C(0xbabe0000)
+/** The bit mask for the magic value. */
+#define RTERRINFO_FLAGS_MAGIC_MASK  UINT32_C(0xffff0000)
+/** @} */
+
+/**
+ * Initializes an error info structure.
+ *
+ * @returns @a pErrInfo.
+ * @param   pErrInfo            The error info structure to init.
+ * @param   pszMsg              The message buffer.  Must be at least one byte.
+ * @param   cbMsg               The size of the message buffer.
+ */
+DECLINLINE(PRTERRINFO) RTErrInfoInit(PRTERRINFO pErrInfo, char *pszMsg, size_t cbMsg)
+{
+    *pszMsg = '\0';
+
+    pErrInfo->fFlags         = RTERRINFO_FLAGS_T_CUSTOM | RTERRINFO_FLAGS_MAGIC;
+    pErrInfo->rc             = /*VINF_SUCCESS*/ 0;
+    pErrInfo->pszMsg         = pszMsg;
+    pErrInfo->cbMsg          = cbMsg;
+    pErrInfo->apvReserved[0] = NULL;
+    pErrInfo->apvReserved[1] = NULL;
+
+    return pErrInfo;
+}
+
+/**
+ * Initialize a static error info structure.
+ *
+ * @returns Pointer to the core error info structure.
+ * @param   pStaticErrInfo      The static error info structure to init.
+ */
+DECLINLINE(PRTERRINFO) RTErrInfoInitStatic(PRTERRINFOSTATIC pStaticErrInfo)
+{
+    RTErrInfoInit(&pStaticErrInfo->Core, pStaticErrInfo->szMsg, sizeof(pStaticErrInfo->szMsg));
+    pStaticErrInfo->Core.fFlags = RTERRINFO_FLAGS_T_STATIC | RTERRINFO_FLAGS_MAGIC;
+    return &pStaticErrInfo->Core;
+}
+
+/**
+ * Allocates a error info structure with a buffer at least the given size.
+ *
+ * @returns Pointer to an error info structure on success, NULL on failure.
+ *
+ * @param   cbMsg               The minimum message buffer size.  Use 0 to get
+ *                              the default buffer size.
+ */
+RTDECL(PRTERRINFO)  RTErrInfoAlloc(size_t cbMsg);
+
+/**
+ * Same as RTErrInfoAlloc, except that an IPRT status code is returned.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   cbMsg               The minimum message buffer size.  Use 0 to get
+ *                              the default buffer size.
+ * @param   ppErrInfo           Where to store the pointer to the allocated
+ *                              error info structure on success.  This is
+ *                              always set to NULL.
+ */
+RTDECL(int)         RTErrInfoAllocEx(size_t cbMsg, PRTERRINFO *ppErrInfo);
+
+/**
+ * Frees an error info structure allocated by RTErrInfoAlloc or
+ * RTErrInfoAllocEx.
+ *
+ * @param   pErrInfo            The error info structure.
+ */
+RTDECL(void)        RTErrInfoFree(PRTERRINFO pErrInfo);
+
+/**
+ * Fills in the error info details.
+ *
+ * @returns @a rc.
+ *
+ * @param   pErrInfo            The error info structure to fill in.
+ * @param   rc                  The status code to return.
+ * @param   pszMsg              The error message string.
+ */
+RTDECL(int)         RTErrInfoSet(PRTERRINFO pErrInfo, int rc, const char *pszMsg);
+
+/**
+ * Fills in the error info details, with a sprintf style message.
+ *
+ * @returns @a rc.
+ *
+ * @param   pErrInfo            The error info structure to fill in.
+ * @param   rc                  The status code to return.
+ * @param   pszFormat           The format string.
+ * @param   ...                 The format arguments.
+ */
+RTDECL(int)         RTErrInfoSetF(PRTERRINFO pErrInfo, int rc, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Fills in the error info details, with a vsprintf style message.
+ *
+ * @returns @a rc.
+ *
+ * @param   pErrInfo            The error info structure to fill in.
+ * @param   rc                  The status code to return.
+ * @param   pszFormat           The format string.
+ * @param   va                  The format arguments.
+ */
+RTDECL(int)         RTErrInfoSetV(PRTERRINFO pErrInfo, int rc, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Adds more error info details.
+ *
+ * @returns @a rc.
+ *
+ * @param   pErrInfo            The error info structure to fill in.
+ * @param   rc                  The status code to return.
+ * @param   pszMsg              The error message string to add.
+ */
+RTDECL(int)         RTErrInfoAdd(PRTERRINFO pErrInfo, int rc, const char *pszMsg);
+
+/**
+ * Adds more error info details, with a sprintf style message.
+ *
+ * @returns @a rc.
+ *
+ * @param   pErrInfo            The error info structure to fill in.
+ * @param   rc                  The status code to return.
+ * @param   pszFormat           The format string to add.
+ * @param   ...                 The format arguments.
+ */
+RTDECL(int)         RTErrInfoAddF(PRTERRINFO pErrInfo, int rc, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Adds more error info details, with a vsprintf style message.
+ *
+ * @returns @a rc.
+ *
+ * @param   pErrInfo            The error info structure to fill in.
+ * @param   rc                  The status code to return.
+ * @param   pszFormat           The format string to add.
+ * @param   va                  The format arguments.
+ */
+RTDECL(int)         RTErrInfoAddV(PRTERRINFO pErrInfo, int rc, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Checks if the error info is set.
+ *
+ * @returns true if set, false if not.
+ * @param   pErrInfo            The error info structure. NULL is OK.
+ */
+DECLINLINE(bool)    RTErrInfoIsSet(PCRTERRINFO pErrInfo)
+{
+    if (!pErrInfo)
+        return false;
+    return (pErrInfo->fFlags & (RTERRINFO_FLAGS_MAGIC_MASK | RTERRINFO_FLAGS_SET))
+        == (RTERRINFO_FLAGS_MAGIC | RTERRINFO_FLAGS_SET);
+}
+
+/**
+ * Clears the error info structure.
+ *
+ * @param   pErrInfo            The error info structure. NULL is OK.
+ */
+DECLINLINE(void)    RTErrInfoClear(PRTERRINFO pErrInfo)
+{
+    if (pErrInfo)
+    {
+        pErrInfo->fFlags &= ~RTERRINFO_FLAGS_SET;
+        pErrInfo->rc      = /*VINF_SUCCESS*/0;
+        *pErrInfo->pszMsg = '\0';
+    }
+}
+
+/**
+ * Storage for error variables.
+ *
+ * @remarks Do NOT touch the members!  They are platform specific and what's
+ *          where may change at any time!
+ */
+typedef union RTERRVARS
+{
+    int8_t  ai8Vars[32];
+    int16_t ai16Vars[16];
+    int32_t ai32Vars[8];
+    int64_t ai64Vars[4];
+} RTERRVARS;
+/** Pointer to an error variable storage union.  */
+typedef RTERRVARS *PRTERRVARS;
+/** Pointer to a const error variable storage union.  */
+typedef RTERRVARS const *PCRTERRVARS;
+
+/**
+ * Saves the error variables.
+ *
+ * @returns @a pVars.
+ * @param   pVars       The variable storage union.
+ */
+RTDECL(PRTERRVARS) RTErrVarsSave(PRTERRVARS pVars);
+
+/**
+ * Restores the error variables.
+ *
+ * @param   pVars       The variable storage union.
+ */
+RTDECL(void) RTErrVarsRestore(PCRTERRVARS pVars);
+
+/**
+ * Checks if the first variable set equals the second.
+ *
+ * @returns true if they are equal, false if not.
+ * @param   pVars1      The first variable storage union.
+ * @param   pVars2      The second variable storage union.
+ */
+RTDECL(bool) RTErrVarsAreEqual(PCRTERRVARS pVars1, PCRTERRVARS pVars2);
+
+/**
+ * Checks if the (live) error variables have changed since we saved them.
+ *
+ * @returns @c true if they have changed, @c false if not.
+ * @param   pVars       The saved variables to compare the current state
+ *                      against.
+ */
+RTDECL(bool) RTErrVarsHaveChanged(PCRTERRVARS pVars);
+
+RT_C_DECLS_END
+
+/** @} */
+
+/** @name Status Code Ranges
+ * @{ */
+/** The first status code in the primary IPRT range. */
+#define RTERR_RANGE1_FIRST                  0
+/** The last status code in the primary IPRT range. */
+#define RTERR_RANGE1_LAST                   999
+
+/** The first status code in the secondary IPRT range. */
+#define RTERR_RANGE2_FIRST                  22000
+/** The last status code in the secondary IPRT range. */
+#define RTERR_RANGE2_LAST                   32766
+
+/** The first status code in the user range. */
+#define RTERR_USER_FIRST                    1000
+/** The last status code in the user range. */
+#define RTERR_USER_LAST                     21999
+/** @}  */
+
+
+/* SED-START */
+
+/** @name Misc. Status Codes
+ * @{
+ */
+/** Success. */
+#define VINF_SUCCESS                        0
+
+/** General failure - DON'T USE THIS!!! */
+#define VERR_GENERAL_FAILURE                (-1)
+/** Invalid parameter. */
+#define VERR_INVALID_PARAMETER              (-2)
+/** Invalid parameter. */
+#define VWRN_INVALID_PARAMETER              2
+/** Invalid magic or cookie. */
+#define VERR_INVALID_MAGIC                  (-3)
+/** Invalid magic or cookie. */
+#define VWRN_INVALID_MAGIC                  3
+/** Invalid loader handle. */
+#define VERR_INVALID_HANDLE                 (-4)
+/** Invalid loader handle. */
+#define VWRN_INVALID_HANDLE                 4
+/** Failed to lock the address range. */
+#define VERR_LOCK_FAILED                    (-5)
+/** Invalid memory pointer. */
+#define VERR_INVALID_POINTER                (-6)
+/** Failed to patch the IDT. */
+#define VERR_IDT_FAILED                     (-7)
+/** Memory allocation failed. */
+#define VERR_NO_MEMORY                      (-8)
+/** Already loaded. */
+#define VERR_ALREADY_LOADED                 (-9)
+/** Permission denied. */
+#define VERR_PERMISSION_DENIED              (-10)
+/** Permission denied. */
+#define VINF_PERMISSION_DENIED              10
+/** Version mismatch. */
+#define VERR_VERSION_MISMATCH               (-11)
+/** The request function is not implemented. */
+#define VERR_NOT_IMPLEMENTED                (-12)
+/** Invalid flags was given. */
+#define VERR_INVALID_FLAGS                  (-13)
+
+/** Not equal. */
+#define VERR_NOT_EQUAL                      (-18)
+/** The specified path does not point at a symbolic link. */
+#define VERR_NOT_SYMLINK                    (-19)
+/** Failed to allocate temporary memory. */
+#define VERR_NO_TMP_MEMORY                  (-20)
+/** Invalid file mode mask (RTFMODE). */
+#define VERR_INVALID_FMODE                  (-21)
+/** Incorrect call order. */
+#define VERR_WRONG_ORDER                    (-22)
+/** There is no TLS (thread local storage) available for storing the current thread. */
+#define VERR_NO_TLS_FOR_SELF                (-23)
+/** Failed to set the TLS (thread local storage) entry which points to our thread structure. */
+#define VERR_FAILED_TO_SET_SELF_TLS         (-24)
+/** Not able to allocate contiguous memory. */
+#define VERR_NO_CONT_MEMORY                 (-26)
+/** No memory available for page table or page directory. */
+#define VERR_NO_PAGE_MEMORY                 (-27)
+/** Already initialized. */
+#define VINF_ALREADY_INITIALIZED            28
+/** The specified thread is dead. */
+#define VERR_THREAD_IS_DEAD                 (-29)
+/** The specified thread is not waitable. */
+#define VERR_THREAD_NOT_WAITABLE            (-30)
+/** Pagetable not present. */
+#define VERR_PAGE_TABLE_NOT_PRESENT         (-31)
+/** Invalid context.
+ * Typically an API was used by the wrong thread. */
+#define VERR_INVALID_CONTEXT                (-32)
+/** The per process timer is busy. */
+#define VERR_TIMER_BUSY                     (-33)
+/** Address conflict. */
+#define VERR_ADDRESS_CONFLICT               (-34)
+/** Unresolved (unknown) host platform error. */
+#define VERR_UNRESOLVED_ERROR               (-35)
+/** Invalid function. */
+#define VERR_INVALID_FUNCTION               (-36)
+/** Not supported. */
+#define VERR_NOT_SUPPORTED                  (-37)
+/** Not supported. */
+#define VINF_NOT_SUPPORTED                  37
+/** Access denied. */
+#define VERR_ACCESS_DENIED                  (-38)
+/** Call interrupted. */
+#define VERR_INTERRUPTED                    (-39)
+/** Call interrupted. */
+#define VINF_INTERRUPTED                    39
+/** Timeout. */
+#define VERR_TIMEOUT                        (-40)
+/** Timeout. */
+#define VINF_TIMEOUT                        40
+/** Buffer too small to save result. */
+#define VERR_BUFFER_OVERFLOW                (-41)
+/** Buffer too small to save result. */
+#define VINF_BUFFER_OVERFLOW                41
+/** Data size overflow. */
+#define VERR_TOO_MUCH_DATA                  (-42)
+/** Max threads number reached. */
+#define VERR_MAX_THRDS_REACHED              (-43)
+/** Max process number reached. */
+#define VERR_MAX_PROCS_REACHED              (-44)
+/** The recipient process has refused the signal. */
+#define VERR_SIGNAL_REFUSED                 (-45)
+/** A signal is already pending. */
+#define VERR_SIGNAL_PENDING                 (-46)
+/** The signal being posted is not correct. */
+#define VERR_SIGNAL_INVALID                 (-47)
+/** The state changed.
+ * This is a generic error message and needs a context to make sense. */
+#define VERR_STATE_CHANGED                  (-48)
+/** Warning, the state changed.
+ * This is a generic error message and needs a context to make sense. */
+#define VWRN_STATE_CHANGED                  48
+/** Error while parsing UUID string */
+#define VERR_INVALID_UUID_FORMAT            (-49)
+/** The specified process was not found. */
+#define VERR_PROCESS_NOT_FOUND              (-50)
+/** The process specified to a non-block wait had not exited. */
+#define VERR_PROCESS_RUNNING                (-51)
+/** Retry the operation. */
+#define VERR_TRY_AGAIN                      (-52)
+/** Retry the operation. */
+#define VINF_TRY_AGAIN                      52
+/** Generic parse error. */
+#define VERR_PARSE_ERROR                    (-53)
+/** Value out of range. */
+#define VERR_OUT_OF_RANGE                   (-54)
+/** A numeric conversion encountered a value which was too big for the target. */
+#define VERR_NUMBER_TOO_BIG                 (-55)
+/** A numeric conversion encountered a value which was too big for the target. */
+#define VWRN_NUMBER_TOO_BIG                 55
+/** The number begin converted (string) contained no digits. */
+#define VERR_NO_DIGITS                      (-56)
+/** The number begin converted (string) contained no digits. */
+#define VWRN_NO_DIGITS                      56
+/** Encountered a '-' during conversion to an unsigned value. */
+#define VERR_NEGATIVE_UNSIGNED              (-57)
+/** Encountered a '-' during conversion to an unsigned value. */
+#define VWRN_NEGATIVE_UNSIGNED              57
+/** Error while characters translation (unicode and so). */
+#define VERR_NO_TRANSLATION                 (-58)
+/** Error while characters translation (unicode and so). */
+#define VWRN_NO_TRANSLATION                 58
+/** Encountered unicode code point which is reserved for use as endian indicator (0xffff or 0xfffe). */
+#define VERR_CODE_POINT_ENDIAN_INDICATOR    (-59)
+/** Encountered unicode code point in the surrogate range (0xd800 to 0xdfff). */
+#define VERR_CODE_POINT_SURROGATE           (-60)
+/** A string claiming to be UTF-8 is incorrectly encoded. */
+#define VERR_INVALID_UTF8_ENCODING          (-61)
+/** A string claiming to be in UTF-16 is incorrectly encoded. */
+#define VERR_INVALID_UTF16_ENCODING         (-62)
+/** Encountered a unicode code point which cannot be represented as UTF-16. */
+#define VERR_CANT_RECODE_AS_UTF16           (-63)
+/** Got an out of memory condition trying to allocate a string. */
+#define VERR_NO_STR_MEMORY                  (-64)
+/** Got an out of memory condition trying to allocate a UTF-16 (/UCS-2) string. */
+#define VERR_NO_UTF16_MEMORY                (-65)
+/** Get an out of memory condition trying to allocate a code point array. */
+#define VERR_NO_CODE_POINT_MEMORY           (-66)
+/** Can't free the memory because it's used in mapping. */
+#define VERR_MEMORY_BUSY                    (-67)
+/** The timer can't be started because it's already active. */
+#define VERR_TIMER_ACTIVE                   (-68)
+/** The timer can't be stopped because it's already suspended. */
+#define VERR_TIMER_SUSPENDED                (-69)
+/** The operation was cancelled by the user (copy) or another thread (local ipc). */
+#define VERR_CANCELLED                      (-70)
+/** Failed to initialize a memory object.
+ * Exactly what this means is OS specific. */
+#define VERR_MEMOBJ_INIT_FAILED             (-71)
+/** Out of memory condition when allocating memory with low physical backing. */
+#define VERR_NO_LOW_MEMORY                  (-72)
+/** Out of memory condition when allocating physical memory (without mapping). */
+#define VERR_NO_PHYS_MEMORY                 (-73)
+/** The address (virtual or physical) is too big. */
+#define VERR_ADDRESS_TOO_BIG                (-74)
+/** Failed to map a memory object. */
+#define VERR_MAP_FAILED                     (-75)
+/** Trailing characters. */
+#define VERR_TRAILING_CHARS                 (-76)
+/** Trailing characters. */
+#define VWRN_TRAILING_CHARS                 76
+/** Trailing spaces. */
+#define VERR_TRAILING_SPACES                (-77)
+/** Trailing spaces. */
+#define VWRN_TRAILING_SPACES                77
+/** Generic not found error. */
+#define VERR_NOT_FOUND                      (-78)
+/** Generic not found warning. */
+#define VWRN_NOT_FOUND                      78
+/** Generic invalid state error. */
+#define VERR_INVALID_STATE                  (-79)
+/** Generic invalid state warning. */
+#define VWRN_INVALID_STATE                  79
+/** Generic out of resources error. */
+#define VERR_OUT_OF_RESOURCES               (-80)
+/** Generic out of resources warning. */
+#define VWRN_OUT_OF_RESOURCES               80
+/** No more handles available, too many open handles. */
+#define VERR_NO_MORE_HANDLES                (-81)
+/** Preemption is disabled.
+ * The requested operation can only be performed when preemption is enabled. */
+#define VERR_PREEMPT_DISABLED               (-82)
+/** End of string. */
+#define VERR_END_OF_STRING                  (-83)
+/** End of string. */
+#define VINF_END_OF_STRING                  83
+/** A page count is out of range. */
+#define VERR_PAGE_COUNT_OUT_OF_RANGE        (-84)
+/** Generic object destroyed status. */
+#define VERR_OBJECT_DESTROYED               (-85)
+/** Generic object was destroyed by the call status. */
+#define VINF_OBJECT_DESTROYED               85
+/** Generic dangling objects status. */
+#define VERR_DANGLING_OBJECTS               (-86)
+/** Generic dangling objects status. */
+#define VWRN_DANGLING_OBJECTS               86
+/** Invalid Base64 encoding. */
+#define VERR_INVALID_BASE64_ENCODING        (-87)
+/** Return instigated by a callback or similar. */
+#define VERR_CALLBACK_RETURN                (-88)
+/** Return instigated by a callback or similar. */
+#define VINF_CALLBACK_RETURN                88
+/** Authentication failure. */
+#define VERR_AUTHENTICATION_FAILURE         (-89)
+/** Not a power of two. */
+#define VERR_NOT_POWER_OF_TWO               (-90)
+/** Status code, typically given as a parameter, that isn't supposed to be used. */
+#define VERR_IGNORED                        (-91)
+/** Concurrent access to the object is not allowed. */
+#define VERR_CONCURRENT_ACCESS              (-92)
+/** The caller does not have a reference to the object.
+ * This status is used when two threads is caught sharing the same object
+ * reference. */
+#define VERR_CALLER_NO_REFERENCE            (-93)
+/** Generic no change error. */
+#define VERR_NO_CHANGE                      (-95)
+/** Generic no change info. */
+#define VINF_NO_CHANGE                      95
+/** Out of memory condition when allocating executable memory. */
+#define VERR_NO_EXEC_MEMORY                 (-96)
+/** The alignment is not supported. */
+#define VERR_UNSUPPORTED_ALIGNMENT          (-97)
+/** The alignment is not really supported, however we got lucky with this
+ * allocation. */
+#define VINF_UNSUPPORTED_ALIGNMENT          97
+/** Duplicate something. */
+#define VERR_DUPLICATE                      (-98)
+/** Something is missing. */
+#define VERR_MISSING                        (-99)
+/** An unexpected (/unknown) exception was caught. */
+#define VERR_UNEXPECTED_EXCEPTION           (-22400)
+/** Buffer underflow. */
+#define VERR_BUFFER_UNDERFLOW               (-22401)
+/** Buffer underflow. */
+#define VINF_BUFFER_UNDERFLOW               22401
+/** Uneven input. */
+#define VERR_UNEVEN_INPUT                   (-22402)
+/** Something is not available or not working properly. */
+#define VERR_NOT_AVAILABLE                  (-22403)
+/** The RTPROC_FLAGS_DETACHED flag isn't supported. */
+#define VERR_PROC_DETACH_NOT_SUPPORTED      (-22404)
+/** An account is restricted in a certain way. */
+#define VERR_ACCOUNT_RESTRICTED             (-22405)
+/** An account is restricted in a certain way. */
+#define VINF_ACCOUNT_RESTRICTED             22405
+/** Not able satisfy all the requirements of the request. */
+#define VERR_UNABLE_TO_SATISFY_REQUIREMENTS (-22406)
+/** Not able satisfy all the requirements of the request. */
+#define VWRN_UNABLE_TO_SATISFY_REQUIREMENTS 22406
+/** The requested allocation is too big. */
+#define VERR_ALLOCATION_TOO_BIG             (-22407)
+/** Mismatch. */
+#define VERR_MISMATCH                       (-22408)
+/** Wrong type. */
+#define VERR_WRONG_TYPE                     (-22409)
+/** This indicates that the process does not have sufficient privileges to
+ * perform the operation. */
+#define VERR_PRIVILEGE_NOT_HELD             (-22410)
+/** Process does not have the trusted code base (TCB) privilege needed for user
+ * authentication or/and process creation as a given user.  TCB is also called
+ * 'Act as part of the operating system'. */
+#define VERR_PROC_TCB_PRIV_NOT_HELD         (-22411)
+/** Process does not have the assign primary token (APT) privilege needed
+ * for creating process as a given user.  APT is also called 'Replace a process
+ * level token'. */
+#define VERR_PROC_APT_PRIV_NOT_HELD         (-22412)
+/** Process does not have the increase quota (IQ) privilege needed for
+ * creating a process as a given user. IQ is also called 'Increase quotas'. */
+#define VERR_PROC_IQ_PRIV_NOT_HELD          (-22413)
+/** The system has too many CPUs. */
+#define VERR_MP_TOO_MANY_CPUS               (-22414)
+/** @} */
+
+
+/** @name Common File/Disk/Pipe/etc Status Codes
+ * @{
+ */
+/** Unresolved (unknown) file i/o error. */
+#define VERR_FILE_IO_ERROR                  (-100)
+/** File/Device open failed. */
+#define VERR_OPEN_FAILED                    (-101)
+/** File not found. */
+#define VERR_FILE_NOT_FOUND                 (-102)
+/** Path not found. */
+#define VERR_PATH_NOT_FOUND                 (-103)
+/** Invalid (malformed) file/path name. */
+#define VERR_INVALID_NAME                   (-104)
+/** The object in question already exists. */
+#define VERR_ALREADY_EXISTS                 (-105)
+/** The object in question already exists. */
+#define VWRN_ALREADY_EXISTS                 105
+/** Too many open files. */
+#define VERR_TOO_MANY_OPEN_FILES            (-106)
+/** Seek error. */
+#define VERR_SEEK                           (-107)
+/** Seek below file start. */
+#define VERR_NEGATIVE_SEEK                  (-108)
+/** Trying to seek on device. */
+#define VERR_SEEK_ON_DEVICE                 (-109)
+/** Reached the end of the file. */
+#define VERR_EOF                            (-110)
+/** Reached the end of the file. */
+#define VINF_EOF                            110
+/** Generic file read error. */
+#define VERR_READ_ERROR                     (-111)
+/** Generic file write error. */
+#define VERR_WRITE_ERROR                    (-112)
+/** Write protect error. */
+#define VERR_WRITE_PROTECT                  (-113)
+/** Sharing violation, file is being used by another process. */
+#define VERR_SHARING_VIOLATION              (-114)
+/** Unable to lock a region of a file. */
+#define VERR_FILE_LOCK_FAILED               (-115)
+/** File access error, another process has locked a portion of the file. */
+#define VERR_FILE_LOCK_VIOLATION            (-116)
+/** File or directory can't be created. */
+#define VERR_CANT_CREATE                    (-117)
+/** Directory can't be deleted. */
+#define VERR_CANT_DELETE_DIRECTORY          (-118)
+/** Can't move file to another disk. */
+#define VERR_NOT_SAME_DEVICE                (-119)
+/** The filename or extension is too long. */
+#define VERR_FILENAME_TOO_LONG              (-120)
+/** Media not present in drive. */
+#define VERR_MEDIA_NOT_PRESENT              (-121)
+/** The type of media was not recognized. Not formatted? */
+#define VERR_MEDIA_NOT_RECOGNIZED           (-122)
+/** Can't unlock - region was not locked. */
+#define VERR_FILE_NOT_LOCKED                (-123)
+/** Unrecoverable error: lock was lost. */
+#define VERR_FILE_LOCK_LOST                 (-124)
+/** Can't delete directory with files. */
+#define VERR_DIR_NOT_EMPTY                  (-125)
+/** A directory operation was attempted on a non-directory object. */
+#define VERR_NOT_A_DIRECTORY                (-126)
+/** A non-directory operation was attempted on a directory object. */
+#define VERR_IS_A_DIRECTORY                 (-127)
+/** Tried to grow a file beyond the limit imposed by the process or the filesystem. */
+#define VERR_FILE_TOO_BIG                   (-128)
+/** No pending request the aio context has to wait for completion. */
+#define VERR_FILE_AIO_NO_REQUEST            (-129)
+/** The request could not be canceled or prepared for another transfer
+ *  because it is still in progress. */
+#define VERR_FILE_AIO_IN_PROGRESS           (-130)
+/** The request could not be canceled because it already completed. */
+#define VERR_FILE_AIO_COMPLETED             (-131)
+/** The I/O context couldn't be destroyed because there are still pending requests. */
+#define VERR_FILE_AIO_BUSY                  (-132)
+/** The requests couldn't be submitted because that would exceed the capacity of the context. */
+#define VERR_FILE_AIO_LIMIT_EXCEEDED        (-133)
+/** The request was canceled. */
+#define VERR_FILE_AIO_CANCELED              (-134)
+/** The request wasn't submitted so it can't be canceled. */
+#define VERR_FILE_AIO_NOT_SUBMITTED         (-135)
+/** A request was not prepared and thus could not be submitted. */
+#define VERR_FILE_AIO_NOT_PREPARED          (-136)
+/** Not all requests could be submitted due to resource shortage. */
+#define VERR_FILE_AIO_INSUFFICIENT_RESSOURCES (-137)
+/** Device or resource is busy. */
+#define VERR_RESOURCE_BUSY                  (-138)
+/** A file operation was attempted on a non-file object. */
+#define VERR_NOT_A_FILE                     (-139)
+/** A non-file operation was attempted on a file object. */
+#define VERR_IS_A_FILE                      (-140)
+/** Unexpected filesystem object type. */
+#define VERR_UNEXPECTED_FS_OBJ_TYPE         (-141)
+/** A path does not start with a root specification. */
+#define VERR_PATH_DOES_NOT_START_WITH_ROOT  (-142)
+/** A path is relative, expected an absolute path. */
+#define VERR_PATH_IS_RELATIVE               (-143)
+/** A path is not relative (start with root), expected an relative path. */
+#define VERR_PATH_IS_NOT_RELATIVE           (-144)
+/** Zero length path. */
+#define VERR_PATH_ZERO_LENGTH               (-145)
+/** There are not enough events available on the host to create the I/O context.
+ * This exact meaning is host platform dependent. */
+#define VERR_FILE_AIO_INSUFFICIENT_EVENTS   (-146)
+/** @} */
+
+
+/** @name Generic Filesystem I/O Status Codes
+ * @{
+ */
+/** Unresolved (unknown) disk i/o error.  */
+#define VERR_DISK_IO_ERROR                  (-150)
+/** Invalid drive number. */
+#define VERR_INVALID_DRIVE                  (-151)
+/** Disk is full. */
+#define VERR_DISK_FULL                      (-152)
+/** Disk was changed. */
+#define VERR_DISK_CHANGE                    (-153)
+/** Drive is locked. */
+#define VERR_DRIVE_LOCKED                   (-154)
+/** The specified disk or diskette cannot be accessed. */
+#define VERR_DISK_INVALID_FORMAT            (-155)
+/** Too many symbolic links. */
+#define VERR_TOO_MANY_SYMLINKS              (-156)
+/** The OS does not support setting the time stamps on a symbolic link. */
+#define VERR_NS_SYMLINK_SET_TIME            (-157)
+/** The OS does not support changing the owner of a symbolic link. */
+#define VERR_NS_SYMLINK_CHANGE_OWNER        (-158)
+/** @} */
+
+
+/** @name Generic Directory Enumeration Status Codes
+ * @{
+ */
+/** Unresolved (unknown) search error. */
+#define VERR_SEARCH_ERROR                   (-200)
+/** No more files found. */
+#define VERR_NO_MORE_FILES                  (-201)
+/** No more search handles available. */
+#define VERR_NO_MORE_SEARCH_HANDLES         (-202)
+/** RTDirReadEx() failed to retrieve the extra data which was requested. */
+#define VWRN_NO_DIRENT_INFO                 203
+/** @} */
+
+
+/** @name Internal Processing Errors
+ * @{
+ */
+/** Internal error - this should never happen.  */
+#define VERR_INTERNAL_ERROR                 (-225)
+/** Internal error no. 2. */
+#define VERR_INTERNAL_ERROR_2               (-226)
+/** Internal error no. 3. */
+#define VERR_INTERNAL_ERROR_3               (-227)
+/** Internal error no. 4. */
+#define VERR_INTERNAL_ERROR_4               (-228)
+/** Internal error no. 5. */
+#define VERR_INTERNAL_ERROR_5               (-229)
+/** Internal error: Unexpected status code. */
+#define VERR_IPE_UNEXPECTED_STATUS          (-230)
+/** Internal error: Unexpected status code. */
+#define VERR_IPE_UNEXPECTED_INFO_STATUS     (-231)
+/** Internal error: Unexpected status code. */
+#define VERR_IPE_UNEXPECTED_ERROR_STATUS    (-232)
+/** Internal error: Uninitialized status code.
+ * @remarks This is used by value elsewhere.  */
+#define VERR_IPE_UNINITIALIZED_STATUS       (-233)
+/** Internal error: Supposedly unreachable default case in a switch. */
+#define VERR_IPE_NOT_REACHED_DEFAULT_CASE   (-234)
+/** @} */
+
+
+/** @name Generic Device I/O Status Codes
+ * @{
+ */
+/** Unresolved (unknown) device i/o error. */
+#define VERR_DEV_IO_ERROR                   (-250)
+/** Device i/o: Bad unit. */
+#define VERR_IO_BAD_UNIT                    (-251)
+/** Device i/o: Not ready. */
+#define VERR_IO_NOT_READY                   (-252)
+/** Device i/o: Bad command. */
+#define VERR_IO_BAD_COMMAND                 (-253)
+/** Device i/o: CRC error. */
+#define VERR_IO_CRC                         (-254)
+/** Device i/o: Bad length. */
+#define VERR_IO_BAD_LENGTH                  (-255)
+/** Device i/o: Sector not found. */
+#define VERR_IO_SECTOR_NOT_FOUND            (-256)
+/** Device i/o: General failure. */
+#define VERR_IO_GEN_FAILURE                 (-257)
+/** @} */
+
+
+/** @name Generic Pipe I/O Status Codes
+ * @{
+ */
+/** Unresolved (unknown) pipe i/o error. */
+#define VERR_PIPE_IO_ERROR                  (-300)
+/** Broken pipe. */
+#define VERR_BROKEN_PIPE                    (-301)
+/** Bad pipe. */
+#define VERR_BAD_PIPE                       (-302)
+/** Pipe is busy. */
+#define VERR_PIPE_BUSY                      (-303)
+/** No data in pipe. */
+#define VERR_NO_DATA                        (-304)
+/** Pipe is not connected. */
+#define VERR_PIPE_NOT_CONNECTED             (-305)
+/** More data available in pipe. */
+#define VERR_MORE_DATA                      (-306)
+/** Expected read pipe, got a write pipe instead. */
+#define VERR_PIPE_NOT_READ                  (-307)
+/** Expected write pipe, got a read pipe instead. */
+#define VERR_PIPE_NOT_WRITE                 (-308)
+/** @} */
+
+
+/** @name Generic Semaphores Status Codes
+ * @{
+ */
+/** Unresolved (unknown) semaphore error. */
+#define VERR_SEM_ERROR                      (-350)
+/** Too many semaphores. */
+#define VERR_TOO_MANY_SEMAPHORES            (-351)
+/** Exclusive semaphore is owned by another process. */
+#define VERR_EXCL_SEM_ALREADY_OWNED         (-352)
+/** The semaphore is set and cannot be closed. */
+#define VERR_SEM_IS_SET                     (-353)
+/** The semaphore cannot be set again. */
+#define VERR_TOO_MANY_SEM_REQUESTS          (-354)
+/** Attempt to release mutex not owned by caller. */
+#define VERR_NOT_OWNER                      (-355)
+/** The semaphore has been opened too many times. */
+#define VERR_TOO_MANY_OPENS                 (-356)
+/** The maximum posts for the event semaphore has been reached. */
+#define VERR_TOO_MANY_POSTS                 (-357)
+/** The event semaphore has already been posted. */
+#define VERR_ALREADY_POSTED                 (-358)
+/** The event semaphore has already been reset. */
+#define VERR_ALREADY_RESET                  (-359)
+/** The semaphore is in use. */
+#define VERR_SEM_BUSY                       (-360)
+/** The previous ownership of this semaphore has ended. */
+#define VERR_SEM_OWNER_DIED                 (-361)
+/** Failed to open semaphore by name - not found. */
+#define VERR_SEM_NOT_FOUND                  (-362)
+/** Semaphore destroyed while waiting. */
+#define VERR_SEM_DESTROYED                  (-363)
+/** Nested ownership requests are not permitted for this semaphore type. */
+#define VERR_SEM_NESTED                     (-364)
+/** The release call only release a semaphore nesting, i.e. the caller is still
+ * holding the semaphore. */
+#define VINF_SEM_NESTED                     (364)
+/** Deadlock detected. */
+#define VERR_DEADLOCK                       (-365)
+/** Ping-Pong listen or speak out of turn error. */
+#define VERR_SEM_OUT_OF_TURN                (-366)
+/** Tried to take a semaphore in a bad context. */
+#define VERR_SEM_BAD_CONTEXT                (-367)
+/** Don't spin for the semaphore, but it is safe to try grab it. */
+#define VINF_SEM_BAD_CONTEXT                (367)
+/** Wrong locking order detected. */
+#define VERR_SEM_LV_WRONG_ORDER             (-368)
+/** Wrong release order detected. */
+#define VERR_SEM_LV_WRONG_RELEASE_ORDER     (-369)
+/** Attempt to recursively enter a non-recursive lock. */
+#define VERR_SEM_LV_NESTED                  (-370)
+/** Invalid parameters passed to the lock validator. */
+#define VERR_SEM_LV_INVALID_PARAMETER       (-371)
+/** The lock validator detected a deadlock. */
+#define VERR_SEM_LV_DEADLOCK                (-372)
+/** The lock validator detected an existing deadlock.
+ * The deadlock was not caused by the current operation, but existed already. */
+#define VERR_SEM_LV_EXISTING_DEADLOCK       (-373)
+/** Not the lock owner according our records. */
+#define VERR_SEM_LV_NOT_OWNER               (-374)
+/** An illegal lock upgrade was attempted. */
+#define VERR_SEM_LV_ILLEGAL_UPGRADE         (-375)
+/** The thread is not a valid signaller of the event. */
+#define VERR_SEM_LV_NOT_SIGNALLER           (-376)
+/** Internal error in the lock validator or related components. */
+#define VERR_SEM_LV_INTERNAL_ERROR          (-377)
+/** @} */
+
+
+/** @name Generic Network I/O Status Codes
+ * @{
+ */
+/** Unresolved (unknown) network error. */
+#define VERR_NET_IO_ERROR                       (-400)
+/** The network is busy or is out of resources. */
+#define VERR_NET_OUT_OF_RESOURCES               (-401)
+/** Net host name not found. */
+#define VERR_NET_HOST_NOT_FOUND                 (-402)
+/** Network path not found. */
+#define VERR_NET_PATH_NOT_FOUND                 (-403)
+/** General network printing error. */
+#define VERR_NET_PRINT_ERROR                    (-404)
+/** The machine is not on the network. */
+#define VERR_NET_NO_NETWORK                     (-405)
+/** Name is not unique on the network. */
+#define VERR_NET_NOT_UNIQUE_NAME                (-406)
+
+/* These are BSD networking error codes - numbers correspond, don't mess! */
+/** Operation in progress. */
+#define VERR_NET_IN_PROGRESS                    (-436)
+/** Operation already in progress. */
+#define VERR_NET_ALREADY_IN_PROGRESS            (-437)
+/** Attempted socket operation with a non-socket handle.
+ * (This includes closed handles.) */
+#define VERR_NET_NOT_SOCKET                     (-438)
+/** Destination address required. */
+#define VERR_NET_DEST_ADDRESS_REQUIRED          (-439)
+/** Message too long. */
+#define VERR_NET_MSG_SIZE                       (-440)
+/** Protocol wrong type for socket. */
+#define VERR_NET_PROTOCOL_TYPE                  (-441)
+/** Protocol not available. */
+#define VERR_NET_PROTOCOL_NOT_AVAILABLE         (-442)
+/** Protocol not supported. */
+#define VERR_NET_PROTOCOL_NOT_SUPPORTED         (-443)
+/** Socket type not supported. */
+#define VERR_NET_SOCKET_TYPE_NOT_SUPPORTED      (-444)
+/** Operation not supported. */
+#define VERR_NET_OPERATION_NOT_SUPPORTED        (-445)
+/** Protocol family not supported. */
+#define VERR_NET_PROTOCOL_FAMILY_NOT_SUPPORTED  (-446)
+/** Address family not supported by protocol family. */
+#define VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED   (-447)
+/** Address already in use. */
+#define VERR_NET_ADDRESS_IN_USE                 (-448)
+/** Can't assign requested address. */
+#define VERR_NET_ADDRESS_NOT_AVAILABLE          (-449)
+/** Network is down. */
+#define VERR_NET_DOWN                           (-450)
+/** Network is unreachable. */
+#define VERR_NET_UNREACHABLE                    (-451)
+/** Network dropped connection on reset. */
+#define VERR_NET_CONNECTION_RESET               (-452)
+/** Software caused connection abort. */
+#define VERR_NET_CONNECTION_ABORTED             (-453)
+/** Connection reset by peer. */
+#define VERR_NET_CONNECTION_RESET_BY_PEER       (-454)
+/** No buffer space available. */
+#define VERR_NET_NO_BUFFER_SPACE                (-455)
+/** Socket is already connected. */
+#define VERR_NET_ALREADY_CONNECTED              (-456)
+/** Socket is not connected. */
+#define VERR_NET_NOT_CONNECTED                  (-457)
+/** Can't send after socket shutdown. */
+#define VERR_NET_SHUTDOWN                       (-458)
+/** Too many references: can't splice. */
+#define VERR_NET_TOO_MANY_REFERENCES            (-459)
+/** Too many references: can't splice. */
+#define VERR_NET_CONNECTION_TIMED_OUT           (-460)
+/** Connection refused. */
+#define VERR_NET_CONNECTION_REFUSED             (-461)
+/* ELOOP is not net. */
+/* ENAMETOOLONG is not net. */
+/** Host is down. */
+#define VERR_NET_HOST_DOWN                      (-464)
+/** No route to host. */
+#define VERR_NET_HOST_UNREACHABLE               (-465)
+/** Protocol error. */
+#define VERR_NET_PROTOCOL_ERROR                 (-466)
+/** Incomplete packet was submitted by guest. */
+#define VERR_NET_INCOMPLETE_TX_PACKET           (-467)
+/** @} */
+
+
+/** @name TCP Status Codes
+ * @{
+ */
+/** Stop the TCP server. */
+#define VERR_TCP_SERVER_STOP                    (-500)
+/** The server was stopped. */
+#define VINF_TCP_SERVER_STOP                    500
+/** The TCP server was shut down using RTTcpServerShutdown. */
+#define VERR_TCP_SERVER_SHUTDOWN                (-501)
+/** The TCP server was destroyed. */
+#define VERR_TCP_SERVER_DESTROYED               (-502)
+/** The TCP server has no client associated with it. */
+#define VINF_TCP_SERVER_NO_CLIENT               503
+/** @} */
+
+
+/** @name UDP Status Codes
+ * @{
+ */
+/** Stop the UDP server. */
+#define VERR_UDP_SERVER_STOP                    (-520)
+/** The server was stopped. */
+#define VINF_UDP_SERVER_STOP                    520
+/** The UDP server was shut down using RTUdpServerShutdown. */
+#define VERR_UDP_SERVER_SHUTDOWN                (-521)
+/** The UDP server was destroyed. */
+#define VERR_UDP_SERVER_DESTROYED               (-522)
+/** The UDP server has no client associated with it. */
+#define VINF_UDP_SERVER_NO_CLIENT               523
+/** @} */
+
+
+/** @name L4 Specific Status Codes
+ * @{
+ */
+/** Invalid offset in an L4 dataspace */
+#define VERR_L4_INVALID_DS_OFFSET               (-550)
+/** IPC error */
+#define VERR_IPC                                (-551)
+/** Item already used */
+#define VERR_RESOURCE_IN_USE                    (-552)
+/** Source/destination not found */
+#define VERR_IPC_PROCESS_NOT_FOUND              (-553)
+/** Receive timeout */
+#define VERR_IPC_RECEIVE_TIMEOUT                (-554)
+/** Send timeout */
+#define VERR_IPC_SEND_TIMEOUT                   (-555)
+/** Receive cancelled */
+#define VERR_IPC_RECEIVE_CANCELLED              (-556)
+/** Send cancelled */
+#define VERR_IPC_SEND_CANCELLED                 (-557)
+/** Receive aborted */
+#define VERR_IPC_RECEIVE_ABORTED                (-558)
+/** Send aborted */
+#define VERR_IPC_SEND_ABORTED                   (-559)
+/** Couldn't map pages during receive */
+#define VERR_IPC_RECEIVE_MAP_FAILED             (-560)
+/** Couldn't map pages during send */
+#define VERR_IPC_SEND_MAP_FAILED                (-561)
+/** Send pagefault timeout in receive */
+#define VERR_IPC_RECEIVE_SEND_PF_TIMEOUT        (-562)
+/** Send pagefault timeout in send */
+#define VERR_IPC_SEND_SEND_PF_TIMEOUT           (-563)
+/** (One) receive buffer was too small, or too few buffers */
+#define VINF_IPC_RECEIVE_MSG_CUT                564
+/** (One) send buffer was too small, or too few buffers */
+#define VINF_IPC_SEND_MSG_CUT                   565
+/** Dataspace manager server not found */
+#define VERR_L4_DS_MANAGER_NOT_FOUND            (-566)
+/** @} */
+
+
+/** @name Loader Status Codes.
+ * @{
+ */
+/** Invalid executable signature. */
+#define VERR_INVALID_EXE_SIGNATURE              (-600)
+/** The iprt loader recognized a ELF image, but doesn't support loading it. */
+#define VERR_ELF_EXE_NOT_SUPPORTED              (-601)
+/** The iprt loader recognized a PE image, but doesn't support loading it. */
+#define VERR_PE_EXE_NOT_SUPPORTED               (-602)
+/** The iprt loader recognized a LX image, but doesn't support loading it. */
+#define VERR_LX_EXE_NOT_SUPPORTED               (-603)
+/** The iprt loader recognized a LE image, but doesn't support loading it. */
+#define VERR_LE_EXE_NOT_SUPPORTED               (-604)
+/** The iprt loader recognized a NE image, but doesn't support loading it. */
+#define VERR_NE_EXE_NOT_SUPPORTED               (-605)
+/** The iprt loader recognized a MZ image, but doesn't support loading it. */
+#define VERR_MZ_EXE_NOT_SUPPORTED               (-606)
+/** The iprt loader recognized an a.out image, but doesn't support loading it. */
+#define VERR_AOUT_EXE_NOT_SUPPORTED             (-607)
+/** Bad executable. */
+#define VERR_BAD_EXE_FORMAT                     (-608)
+/** Symbol (export) not found. */
+#define VERR_SYMBOL_NOT_FOUND                   (-609)
+/** Module not found. */
+#define VERR_MODULE_NOT_FOUND                   (-610)
+/** The loader resolved an external symbol to an address to big for the image format. */
+#define VERR_SYMBOL_VALUE_TOO_BIG               (-611)
+/** The image is too big. */
+#define VERR_IMAGE_TOO_BIG                      (-612)
+/** The image base address is to high for this image type. */
+#define VERR_IMAGE_BASE_TOO_HIGH                (-614)
+/** Mismatching architecture. */
+#define VERR_LDR_ARCH_MISMATCH                  (-615)
+/** Mismatch between IPRT and native loader. */
+#define VERR_LDR_MISMATCH_NATIVE                (-616)
+/** Failed to resolve an imported (external) symbol. */
+#define VERR_LDR_IMPORTED_SYMBOL_NOT_FOUND      (-617)
+/** Generic loader failure. */
+#define VERR_LDR_GENERAL_FAILURE                (-618)
+/** Code signing error.  */
+#define VERR_LDR_IMAGE_HASH                     (-619)
+/** The PE loader encountered delayed imports, a feature which hasn't been implemented yet. */
+#define VERR_LDRPE_DELAY_IMPORT                 (-620)
+/** The PE loader encountered a malformed certificate. */
+#define VERR_LDRPE_CERT_MALFORMED               (-621)
+/** The PE loader encountered a certificate with an unsupported type or structure revision. */
+#define VERR_LDRPE_CERT_UNSUPPORTED             (-622)
+/** The PE loader doesn't know how to deal with the global pointer data directory entry yet. */
+#define VERR_LDRPE_GLOBALPTR                    (-623)
+/** The PE loader doesn't support the TLS data directory yet. */
+#define VERR_LDRPE_TLS                          (-624)
+/** The PE loader doesn't grok the COM descriptor data directory entry. */
+#define VERR_LDRPE_COM_DESCRIPTOR               (-625)
+/** The PE loader encountered an unknown load config directory/header size. */
+#define VERR_LDRPE_LOAD_CONFIG_SIZE             (-626)
+/** The PE loader encountered a lock prefix table, a feature which hasn't been implemented yet. */
+#define VERR_LDRPE_LOCK_PREFIX_TABLE            (-627)
+/** The PE loader encountered some Guard CF stuff in the load config.   */
+#define VERR_LDRPE_GUARD_CF_STUFF               (-628)
+/** The ELF loader doesn't handle foreign endianness. */
+#define VERR_LDRELF_ODD_ENDIAN                  (-630)
+/** The ELF image is 'dynamic', the ELF loader can only deal with 'relocatable' images at present. */
+#define VERR_LDRELF_DYN                         (-631)
+/** The ELF image is 'executable', the ELF loader can only deal with 'relocatable' images at present. */
+#define VERR_LDRELF_EXEC                        (-632)
+/** The ELF image was created for an unsupported target machine type. */
+#define VERR_LDRELF_MACHINE                     (-633)
+/** The ELF version is not supported. */
+#define VERR_LDRELF_VERSION                     (-634)
+/** The ELF loader cannot handle multiple SYMTAB sections. */
+#define VERR_LDRELF_MULTIPLE_SYMTABS            (-635)
+/** The ELF loader encountered a relocation type which is not implemented. */
+#define VERR_LDRELF_RELOCATION_NOT_SUPPORTED    (-636)
+/** The ELF loader encountered a bad symbol index. */
+#define VERR_LDRELF_INVALID_SYMBOL_INDEX        (-637)
+/** The ELF loader encountered an invalid symbol name offset. */
+#define VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET  (-638)
+/** The ELF loader encountered an invalid relocation offset. */
+#define VERR_LDRELF_INVALID_RELOCATION_OFFSET   (-639)
+/** The ELF loader didn't find the symbol/string table for the image. */
+#define VERR_LDRELF_NO_SYMBOL_OR_NO_STRING_TABS (-640)
+/** Invalid link address. */
+#define VERR_LDR_INVALID_LINK_ADDRESS           (-647)
+/** Invalid image relative virtual address. */
+#define VERR_LDR_INVALID_RVA                    (-648)
+/** Invalid segment:offset address. */
+#define VERR_LDR_INVALID_SEG_OFFSET             (-649)
+/** @}*/
+
+/** @name Debug Info Reader Status Codes.
+ * @{
+ */
+/** The module contains no line number information. */
+#define VERR_DBG_NO_LINE_NUMBERS                (-650)
+/** The module contains no symbol information. */
+#define VERR_DBG_NO_SYMBOLS                     (-651)
+/** The specified segment:offset address was invalid. Typically an attempt at
+ * addressing outside the segment boundary. */
+#define VERR_DBG_INVALID_ADDRESS                (-652)
+/** Invalid segment index. */
+#define VERR_DBG_INVALID_SEGMENT_INDEX          (-653)
+/** Invalid segment offset. */
+#define VERR_DBG_INVALID_SEGMENT_OFFSET         (-654)
+/** Invalid image relative virtual address. */
+#define VERR_DBG_INVALID_RVA                    (-655)
+/** Invalid image relative virtual address. */
+#define VERR_DBG_SPECIAL_SEGMENT                (-656)
+/** Address conflict within a module/segment.
+ * Attempted to add a segment, symbol or line number that fully or partially
+ * overlaps with an existing one. */
+#define VERR_DBG_ADDRESS_CONFLICT               (-657)
+/** Duplicate symbol within the module.
+ * Attempted to add a symbol which name already exists within the module.  */
+#define VERR_DBG_DUPLICATE_SYMBOL               (-658)
+/** The segment index specified when adding a new segment is already in use. */
+#define VERR_DBG_SEGMENT_INDEX_CONFLICT         (-659)
+/** No line number was found for the specified address/ordinal/whatever. */
+#define VERR_DBG_LINE_NOT_FOUND                 (-660)
+/** The length of the symbol name is out of range.
+ * This means it is an empty string or that it's greater or equal to
+ * RTDBG_SYMBOL_NAME_LENGTH. */
+#define VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE       (-661)
+/** The length of the file name is out of range.
+ * This means it is an empty string or that it's greater or equal to
+ * RTDBG_FILE_NAME_LENGTH. */
+#define VERR_DBG_FILE_NAME_OUT_OF_RANGE         (-662)
+/** The length of the segment name is out of range.
+ * This means it is an empty string or that it is greater or equal to
+ * RTDBG_SEGMENT_NAME_LENGTH. */
+#define VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE      (-663)
+/** The specified address range wraps around. */
+#define VERR_DBG_ADDRESS_WRAP                   (-664)
+/** The file is not a valid NM map file. */
+#define VERR_DBG_NOT_NM_MAP_FILE                (-665)
+/** The file is not a valid /proc/kallsyms file. */
+#define VERR_DBG_NOT_LINUX_KALLSYMS             (-666)
+/** No debug module interpreter matching the debug info. */
+#define VERR_DBG_NO_MATCHING_INTERPRETER        (-667)
+/** Bad DWARF line number header. */
+#define VERR_DWARF_BAD_LINE_NUMBER_HEADER       (-668)
+/** Unexpected end of DWARF unit. */
+#define VERR_DWARF_UNEXPECTED_END               (-669)
+/** DWARF LEB value overflows the decoder type. */
+#define VERR_DWARF_LEB_OVERFLOW                 (-670)
+/** Bad DWARF extended line number opcode. */
+#define VERR_DWARF_BAD_LNE                      (-671)
+/** Bad DWARF string. */
+#define VERR_DWARF_BAD_STRING                   (-672)
+/** Bad DWARF position. */
+#define VERR_DWARF_BAD_POS                      (-673)
+/** Bad DWARF info. */
+#define VERR_DWARF_BAD_INFO                     (-674)
+/** Bad DWARF abbreviation data. */
+#define VERR_DWARF_BAD_ABBREV                   (-675)
+/** A DWARF abbreviation was not found. */
+#define VERR_DWARF_ABBREV_NOT_FOUND             (-676)
+/** Encountered an unknown attribute form. */
+#define VERR_DWARF_UNKNOWN_FORM                 (-677)
+/** Encountered an unexpected attribute form. */
+#define VERR_DWARF_UNEXPECTED_FORM              (-678)
+/** Unfinished code. */
+#define VERR_DWARF_TODO                         (-679)
+/** Unknown location opcode. */
+#define VERR_DWARF_UNKNOWN_LOC_OPCODE           (-680)
+/** Expression stack overflow. */
+#define VERR_DWARF_STACK_OVERFLOW               (-681)
+/** Expression stack underflow. */
+#define VERR_DWARF_STACK_UNDERFLOW              (-682)
+/** Internal processing error in the DWARF code. */
+#define VERR_DWARF_IPE                          (-683)
+/** Invalid configuration property value. */
+#define VERR_DBG_CFG_INVALID_VALUE              (-684)
+/** Not an integer property. */
+#define VERR_DBG_CFG_NOT_UINT_PROP              (-685)
+/** Deferred loading of information failed. */
+#define VERR_DBG_DEFERRED_LOAD_FAILED           (-686)
+/** Unfinished debug info reader code. */
+#define VERR_DBG_TODO                           (-687)
+/** Found file, but it didn't match the search criteria. */
+#define VERR_DBG_FILE_MISMATCH                  (-688)
+/** Internal processing error in the debug module reader code. */
+#define VERR_DBG_MOD_IPE                        (-689)
+/** The symbol size was adjusted while adding it. */
+#define VINF_DBG_ADJUSTED_SYM_SIZE              690
+/** Unable to parse the CodeView debug information. */
+#define VERR_CV_BAD_FORMAT                      (-691)
+/** Unfinished CodeView debug information feature. */
+#define VERR_CV_TODO                            (-692)
+/** Internal processing error the CodeView debug information reader. */
+#define VERR_CV_IPE                             (-693)
+/** @} */
+
+/** @name Request Packet Status Codes.
+ * @{
+ */
+/** Invalid RT request type.
+ * For the RTReqAlloc() case, the caller just specified an illegal enmType. For
+ * all the other occurrences it means indicates corruption, broken logic, or stupid
+ * interface user. */
+#define VERR_RT_REQUEST_INVALID_TYPE            (-700)
+/** Invalid RT request state.
+ * The state of the request packet was not the expected and accepted one(s). Either
+ * the interface user screwed up, or we've got corruption/broken logic. */
+#define VERR_RT_REQUEST_STATE                   (-701)
+/** Invalid RT request packet.
+ * One or more of the RT controlled packet members didn't contain the correct
+ * values. Some thing's broken. */
+#define VERR_RT_REQUEST_INVALID_PACKAGE         (-702)
+/** The status field has not been updated yet as the request is still
+ * pending completion. Someone queried the iStatus field before the request
+ * has been fully processed. */
+#define VERR_RT_REQUEST_STATUS_STILL_PENDING    (-703)
+/** The request has been freed, don't read the status now.
+ * Someone is reading the iStatus field of a freed request packet. */
+#define VERR_RT_REQUEST_STATUS_FREED            (-704)
+/** @} */
+
+/** @name Environment Status Code
+ * @{
+ */
+/** The specified environment variable was not found. (RTEnvGetEx) */
+#define VERR_ENV_VAR_NOT_FOUND                  (-750)
+/** The specified environment variable was not found. (RTEnvUnsetEx) */
+#define VINF_ENV_VAR_NOT_FOUND                  (750)
+/** Unable to translate all the variables in the default environment due to
+ * codeset issues (LANG / LC_ALL / LC_CTYPE). */
+#define VWRN_ENV_NOT_FULLY_TRANSLATED           (751)
+/** Invalid environment variable name. */
+#define VERR_ENV_INVALID_VAR_NAME               (-752)
+/** The environment variable is an unset record. */
+#define VINF_ENV_VAR_UNSET                      (753)
+/** The environment variable has been recorded as being unset. */
+#define VERR_ENV_VAR_UNSET                      (-753)
+/** @} */
+
+/** @name Multiprocessor Status Codes.
+ * @{
+ */
+/** The specified cpu is offline. */
+#define VERR_CPU_OFFLINE                        (-800)
+/** The specified cpu was not found. */
+#define VERR_CPU_NOT_FOUND                      (-801)
+/** Not all of the requested CPUs showed up in the PFNRTMPWORKER. */
+#define VERR_NOT_ALL_CPUS_SHOWED                (-802)
+/** Internal processing error in the RTMp code.*/
+#define VERR_CPU_IPE_1                          (-803)
+/** @} */
+
+/** @name RTGetOpt status codes
+ * @{ */
+/** RTGetOpt: Command line option not recognized. */
+#define VERR_GETOPT_UNKNOWN_OPTION              (-825)
+/** RTGetOpt: Command line option needs argument. */
+#define VERR_GETOPT_REQUIRED_ARGUMENT_MISSING   (-826)
+/** RTGetOpt: Command line option has argument with bad format. */
+#define VERR_GETOPT_INVALID_ARGUMENT_FORMAT     (-827)
+/** RTGetOpt: Not an option. */
+#define VINF_GETOPT_NOT_OPTION                  828
+/** RTGetOpt: Command line option needs an index. */
+#define VERR_GETOPT_INDEX_MISSING               (-829)
+/** @} */
+
+/** @name RTCache status codes
+ * @{ */
+/** RTCache: cache is full. */
+#define VERR_CACHE_FULL                         (-850)
+/** RTCache: cache is empty. */
+#define VERR_CACHE_EMPTY                        (-851)
+/** @} */
+
+/** @name RTMemCache status codes
+ * @{ */
+/** Reached the max cache size. */
+#define VERR_MEM_CACHE_MAX_SIZE                 (-855)
+/** @} */
+
+/** @name RTS3 status codes
+ * @{ */
+/** Access denied error. */
+#define VERR_S3_ACCESS_DENIED                   (-875)
+/** The bucket/key wasn't found. */
+#define VERR_S3_NOT_FOUND                       (-876)
+/** Bucket already exists. */
+#define VERR_S3_BUCKET_ALREADY_EXISTS           (-877)
+/** Can't delete bucket with keys. */
+#define VERR_S3_BUCKET_NOT_EMPTY                (-878)
+/** The current operation was canceled. */
+#define VERR_S3_CANCELED                        (-879)
+/** @} */
+
+/** @name HTTP status codes
+ * @{ */
+/** HTTP initialization failed. */
+#define VERR_HTTP_INIT_FAILED                   (-885)
+/** The server has not found anything matching the URI given. */
+#define VERR_HTTP_NOT_FOUND                     (-886)
+/** The request is for something forbidden. Authorization will not help. */
+#define VERR_HTTP_ACCESS_DENIED                 (-887)
+/** The server did not understand the request due to bad syntax. */
+#define VERR_HTTP_BAD_REQUEST                   (-888)
+/** Couldn't connect to the server (proxy?). */
+#define VERR_HTTP_COULDNT_CONNECT               (-889)
+/** SSL connection error. */
+#define VERR_HTTP_SSL_CONNECT_ERROR             (-890)
+/** CAcert is missing or has the wrong format. */
+#define VERR_HTTP_CACERT_WRONG_FORMAT           (-891)
+/** Certificate cannot be authenticated with the given CA certificates. */
+#define VERR_HTTP_CACERT_CANNOT_AUTHENTICATE    (-892)
+/** The current HTTP request was forcefully aborted */
+#define VERR_HTTP_ABORTED                       (-893)
+/** Request was redirected. */
+#define VERR_HTTP_REDIRECTED                    (-894)
+/** Proxy couldn't be resolved. */
+#define VERR_HTTP_PROXY_NOT_FOUND               (-895)
+/** The remote host couldn't be resolved. */
+#define VERR_HTTP_HOST_NOT_FOUND                (-896)
+/** Unexpected cURL error configure the proxy. */
+#define VERR_HTTP_CURL_PROXY_CONFIG             (-897)
+/** Generic CURL error. */
+#define VERR_HTTP_CURL_ERROR                    (-899)
+/** @} */
+
+/** @name RTManifest status codes
+ * @{ */
+/** A digest type used in the manifest file isn't supported. */
+#define VERR_MANIFEST_UNSUPPORTED_DIGEST_TYPE   (-900)
+/** An entry in the manifest file couldn't be interpreted correctly. */
+#define VERR_MANIFEST_WRONG_FILE_FORMAT         (-901)
+/** A digest doesn't match the corresponding file. */
+#define VERR_MANIFEST_DIGEST_MISMATCH           (-902)
+/** The file list doesn't match to the content of the manifest file. */
+#define VERR_MANIFEST_FILE_MISMATCH             (-903)
+/** The specified attribute (name) was not found in the manifest.  */
+#define VERR_MANIFEST_ATTR_NOT_FOUND            (-904)
+/** The attribute type did not match. */
+#define VERR_MANIFEST_ATTR_TYPE_MISMATCH        (-905)
+/** No attribute of the specified types was found. */
+#define VERR_MANIFEST_ATTR_TYPE_NOT_FOUND        (-906)
+/** @} */
+
+/** @name RTTar status codes
+ * @{ */
+/** The checksum of a tar header record doesn't match. */
+#define VERR_TAR_CHKSUM_MISMATCH                (-925)
+/** The tar end of file record was read. */
+#define VERR_TAR_END_OF_FILE                    (-926)
+/** The tar file ended unexpectedly. */
+#define VERR_TAR_UNEXPECTED_EOS                 (-927)
+/** The tar termination records was encountered without reaching the end of
+  * the input stream. */
+#define VERR_TAR_EOS_MORE_INPUT                 (-928)
+/** A number tar header field was malformed.  */
+#define VERR_TAR_BAD_NUM_FIELD                  (-929)
+/** A numeric tar header field was not terminated correctly. */
+#define VERR_TAR_BAD_NUM_FIELD_TERM             (-930)
+/** A number tar header field was encoded using base-256 which this
+ * tar implementation currently does not support.  */
+#define VERR_TAR_BASE_256_NOT_SUPPORTED         (-931)
+/** A number tar header field yielded a value too large for the internal
+ * variable of the tar interpreter. */
+#define VERR_TAR_NUM_VALUE_TOO_LARGE            (-932)
+/** The combined minor and major device number type is too small to hold the
+ * value stored in the tar header.  */
+#define VERR_TAR_DEV_VALUE_TOO_LARGE            (-933)
+/** The mode field in a tar header is bad. */
+#define VERR_TAR_BAD_MODE_FIELD                 (-934)
+/** The mode field should not include the type. */
+#define VERR_TAR_MODE_WITH_TYPE                 (-935)
+/** The size field should be zero for links and symlinks. */
+#define VERR_TAR_SIZE_NOT_ZERO                  (-936)
+/** Encountered an unknown type flag. */
+#define VERR_TAR_UNKNOWN_TYPE_FLAG              (-937)
+/** The tar header is all zeros. */
+#define VERR_TAR_ZERO_HEADER                    (-938)
+/** Not a uniform standard tape v0.0 archive header. */
+#define VERR_TAR_NOT_USTAR_V00                  (-939)
+/** The name is empty. */
+#define VERR_TAR_EMPTY_NAME                     (-940)
+/** A non-directory entry has a name ending with a slash. */
+#define VERR_TAR_NON_DIR_ENDS_WITH_SLASH        (-941)
+/** Encountered an unsupported portable archive exchange (pax) header. */
+#define VERR_TAR_UNSUPPORTED_PAX_TYPE           (-942)
+/** Encountered an unsupported Solaris Tar extension. */
+#define VERR_TAR_UNSUPPORTED_SOLARIS_HDR_TYPE   (-943)
+/** Encountered an unsupported GNU Tar extension. */
+#define VERR_TAR_UNSUPPORTED_GNU_HDR_TYPE       (-944)
+/** Malformed checksum field in the tar header. */
+#define VERR_TAR_BAD_CHKSUM_FIELD               (-945)
+/** Malformed checksum field in the tar header. */
+#define VERR_TAR_MALFORMED_GNU_LONGXXXX         (-946)
+/** Too long name or link string. */
+#define VERR_TAR_NAME_TOO_LONG                  (-947)
+/** A directory entry in the archive. */
+#define VINF_TAR_DIR_PATH                        (948)
+/** @} */
+
+/** @name RTPoll status codes
+ * @{ */
+/** The handle is not pollable. */
+#define VERR_POLL_HANDLE_NOT_POLLABLE           (-950)
+/** The handle ID is already present in the poll set. */
+#define VERR_POLL_HANDLE_ID_EXISTS              (-951)
+/** The handle ID was not found in the set. */
+#define VERR_POLL_HANDLE_ID_NOT_FOUND           (-952)
+/** The poll set is full. */
+#define VERR_POLL_SET_IS_FULL                   (-953)
+/** @} */
+
+/** @name Pkzip status codes
+ * @{ */
+/** No end of central directory record found. */
+#define VERR_PKZIP_NO_EOCB                      (-960)
+/** Too long name string. */
+#define VERR_PKZIP_NAME_TOO_LONG                (-961)
+/** Local file header corrupt. */
+#define VERR_PKZIP_BAD_LF_HEADER                (-962)
+/** Central directory file header corrupt. */
+#define VERR_PKZIP_BAD_CDF_HEADER               (-963)
+/** Encountered an unknown type flag. */
+#define VERR_PKZIP_UNKNOWN_TYPE_FLAG            (-964)
+/** Found a ZIP64 Extra Information Field in a ZIP32 file. */
+#define VERR_PKZIP_ZIP64EX_IN_ZIP32             (-965)
+
+
+/** @name RTZip status codes
+ * @{ */
+/** Generic zip error. */
+#define VERR_ZIP_ERROR                          (-22000)
+/** The compressed data was corrupted. */
+#define VERR_ZIP_CORRUPTED                      (-22001)
+/** Ran out of memory while compressing or uncompressing. */
+#define VERR_ZIP_NO_MEMORY                      (-22002)
+/** The compression format version is unsupported. */
+#define VERR_ZIP_UNSUPPORTED_VERSION            (-22003)
+/** The compression method is unsupported. */
+#define VERR_ZIP_UNSUPPORTED_METHOD             (-22004)
+/** The compressed data started with a bad header. */
+#define VERR_ZIP_BAD_HEADER                     (-22005)
+/** @} */
+
+/** @name RTVfs status codes
+ * @{ */
+/** The VFS chain specification does not have a valid prefix. */
+#define VERR_VFS_CHAIN_NO_PREFIX                    (-22100)
+/** The VFS chain specification is empty. */
+#define VERR_VFS_CHAIN_EMPTY                        (-22101)
+/** Expected an element. */
+#define VERR_VFS_CHAIN_EXPECTED_ELEMENT             (-22102)
+/** The VFS object type is not known. */
+#define VERR_VFS_CHAIN_UNKNOWN_TYPE                 (-22103)
+/** Expected a left parentheses. */
+#define VERR_VFS_CHAIN_EXPECTED_LEFT_PARENTHESES    (-22104)
+/** Expected a right parentheses. */
+#define VERR_VFS_CHAIN_EXPECTED_RIGHT_PARENTHESES   (-22105)
+/** Expected a provider name. */
+#define VERR_VFS_CHAIN_EXPECTED_PROVIDER_NAME       (-22106)
+/** Expected an action (> or |). */
+#define VERR_VFS_CHAIN_EXPECTED_ACTION              (-22107)
+/** Only one action element is currently supported. */
+#define VERR_VFS_CHAIN_MULTIPLE_ACTIONS             (-22108)
+/** Expected to find a driving action (>), but there is none. */
+#define VERR_VFS_CHAIN_NO_ACTION                    (-22109)
+/** Expected pipe action. */
+#define VERR_VFS_CHAIN_EXPECTED_PIPE                (-22110)
+/** Unexpected action type. */
+#define VERR_VFS_CHAIN_UNEXPECTED_ACTION_TYPE       (-22111)
+/** @} */
+
+/** @name RTDvm status codes
+ * @{ */
+/** The volume map doesn't contain any valid volume. */
+#define VERR_DVM_MAP_EMPTY                          (-22200)
+/** There is no volume behind the current one. */
+#define VERR_DVM_MAP_NO_VOLUME                      (-22201)
+/** @} */
+
+/** @name Logger status codes
+ * @{ */
+/** The internal logger revision did not match. */
+#define VERR_LOG_REVISION_MISMATCH                  (-22300)
+/** @} */
+
+/* see above, 22400..22499 is used for misc codes! */
+
+/** @name Logger status codes
+ * @{ */
+/** Power off is not supported by the hardware or the OS. */
+#define VERR_SYS_CANNOT_POWER_OFF                   (-22500)
+/** The halt action was requested, but the OS may actually power
+ * off the machine. */
+#define VINF_SYS_MAY_POWER_OFF                      (22501)
+/** Shutdown failed. */
+#define VERR_SYS_SHUTDOWN_FAILED                    (-22502)
+/** @} */
+
+/** @name Filesystem status codes
+ * @{ */
+/** Filesystem can't be opened because it is corrupt. */
+#define VERR_FILESYSTEM_CORRUPT                     (-22600)
+/** @} */
+
+/** @name RTZipXar status codes.
+ * @{ */
+/** Wrong magic value. */
+#define VERR_XAR_WRONG_MAGIC                        (-22700)
+/** Bad header size. */
+#define VERR_XAR_BAD_HDR_SIZE                       (-22701)
+/** Unsupported version. */
+#define VERR_XAR_UNSUPPORTED_VERSION                (-22702)
+/** Unsupported hashing function. */
+#define VERR_XAR_UNSUPPORTED_HASH_FUNCTION          (-22703)
+/** The table of content (TOC) is too small and therefore can't be valid. */
+#define VERR_XAR_TOC_TOO_SMALL                      (-22704)
+/** The table of content (TOC) is too big. */
+#define VERR_XAR_TOC_TOO_BIG                        (-22705)
+/** The compressed table of content is too big. */
+#define VERR_XAR_TOC_TOO_BIG_COMPRESSED             (-22706)
+/** The uncompressed table of content size in the header didn't match what
+ * ZLib returned. */
+#define VERR_XAR_TOC_UNCOMP_SIZE_MISMATCH           (-22707)
+/** The table of content string length didn't match the size specified in the
+ *  header. */
+#define VERR_XAR_TOC_STRLEN_MISMATCH                (-22708)
+/** The table of content isn't valid UTF-8. */
+#define VERR_XAR_TOC_UTF8_ENCODING                  (-22709)
+/** XML error while parsing the table of content. */
+#define VERR_XAR_TOC_XML_PARSE_ERROR                (-22710)
+/** The table of content XML document does not have a toc element. */
+#define VERR_XML_TOC_ELEMENT_MISSING                (-22711)
+/** The table of content XML element (toc) has siblings, we expected it to be
+ *  an only child or the root element (xar). */
+#define VERR_XML_TOC_ELEMENT_HAS_SIBLINGS           (-22712)
+/** The XAR table of content digest doesn't match. */
+#define VERR_XAR_TOC_DIGEST_MISMATCH                (-22713)
+/** Bad or missing XAR checksum element. */
+#define VERR_XAR_BAD_CHECKSUM_ELEMENT               (-22714)
+/** The hash function in the header doesn't match the one in the table of
+ *  content. */
+#define VERR_XAR_HASH_FUNCTION_MISMATCH             (-22715)
+/** Bad digest length encountered in the table of content.  */
+#define VERR_XAR_BAD_DIGEST_LENGTH                  (-22716)
+/** The order of elements in the XAR file does not lend it self to expansion
+ *  from via an I/O stream. */
+#define VERR_XAR_NOT_STREAMBLE_ELEMENT_ORDER        (-22717)
+/** Missing offset element in table of content sub-element. */
+#define VERR_XAR_MISSING_OFFSET_ELEMENT             (-22718)
+/** Bad offset element in table of content sub-element. */
+#define VERR_XAR_BAD_OFFSET_ELEMENT                 (-22719)
+/** Missing size element in table of content sub-element. */
+#define VERR_XAR_MISSING_SIZE_ELEMENT               (-22720)
+/** Bad size element in table of content sub-element. */
+#define VERR_XAR_BAD_SIZE_ELEMENT                   (-22721)
+/** Missing length element in table of content sub-element. */
+#define VERR_XAR_MISSING_LENGTH_ELEMENT             (-22722)
+/** Bad length element in table of content sub-element. */
+#define VERR_XAR_BAD_LENGTH_ELEMENT                 (-22723)
+/** Bad file element in XAR table of content. */
+#define VERR_XAR_BAD_FILE_ELEMENT                   (-22724)
+/** Missing data element for XAR file. */
+#define VERR_XAR_MISSING_DATA_ELEMENT               (-22725)
+/** Unknown XAR file type value. */
+#define VERR_XAR_UNKNOWN_FILE_TYPE                  (-22726)
+/** Missing encoding element for XAR data stream. */
+#define VERR_XAR_NO_ENCODING                        (-22727)
+/** Bad timestamp for XAR file. */
+#define VERR_XAR_BAD_FILE_TIMESTAMP                 (-22728)
+/** Bad file mode for XAR file. */
+#define VERR_XAR_BAD_FILE_MODE                      (-22729)
+/** Bad file user id for XAR file. */
+#define VERR_XAR_BAD_FILE_UID                       (-22730)
+/** Bad file group id for XAR file. */
+#define VERR_XAR_BAD_FILE_GID                       (-22731)
+/** Bad file inode device number for XAR file. */
+#define VERR_XAR_BAD_FILE_DEVICE_NO                 (-22732)
+/** Bad file inode number for XAR file. */
+#define VERR_XAR_BAD_FILE_INODE                     (-22733)
+/** Invalid name for XAR file. */
+#define VERR_XAR_INVALID_FILE_NAME                  (-22734)
+/** The message digest of the extracted data does not match the one supplied. */
+#define VERR_XAR_EXTRACTED_HASH_MISMATCH            (-22735)
+/** The extracted data has exceeded the expected size. */
+#define VERR_XAR_EXTRACTED_SIZE_EXCEEDED            (-22736)
+/** The message digest of the archived data does not match the one supplied. */
+#define VERR_XAR_ARCHIVED_HASH_MISMATCH             (-22737)
+/** The decompressor completed without using all the input data. */
+#define VERR_XAR_UNUSED_ARCHIVED_DATA               (-22738)
+/** Expected the archived and extracted XAR data sizes to be the same for
+ * uncompressed data. */
+#define VERR_XAR_ARCHIVED_AND_EXTRACTED_SIZES_MISMATCH (-22739)
+/** @} */
+
+/** @name RTX509 status codes
+ * @{ */
+/** Error reading a certificate in PEM format from BIO. */
+#define VERR_X509_READING_CERT_FROM_BIO                  (-23100)
+/** Error extracting a public key from the certificate. */
+#define VERR_X509_EXTRACT_PUBKEY_FROM_CERT               (-23101)
+/** Error extracting RSA from the public key. */
+#define VERR_X509_EXTRACT_RSA_FROM_PUBLIC_KEY            (-23102)
+/** Signature verification failed. */
+#define VERR_X509_RSA_VERIFICATION_FUILURE               (-23103)
+/** Basic constraints were not found. */
+#define VERR_X509_NO_BASIC_CONSTARAINTS                  (-23104)
+/** Error getting extensions from the certificate. */
+#define VERR_X509_GETTING_EXTENSION_FROM_CERT            (-23105)
+/** Error getting a data from the extension. */
+#define VERR_X509_GETTING_DATA_FROM_EXTENSION            (-23106)
+/** Error formatting an extension. */
+#define VERR_X509_PRINT_EXTENSION_TO_BIO                 (-23107)
+/** X509 certificate verification error. */
+#define VERR_X509_CERTIFICATE_VERIFICATION_FAILURE       (-23108)
+/** X509 certificate isn't self signed. */
+#define VERR_X509_NOT_SELFSIGNED_CERTIFICATE             (-23109)
+/** Warning X509 certificate isn't self signed.  */
+#define VINF_X509_NOT_SELFSIGNED_CERTIFICATE             23109
+/** @} */
+
+/** @name RTAsn1 status codes
+ * @{ */
+/** Temporary place holder.  */
+#define VERR_ASN1_ERROR                             (-22800)
+/** Encountered an ASN.1 string type that is not supported. */
+#define VERR_ASN1_STRING_TYPE_NOT_IMPLEMENTED       (-22801)
+/** Invalid ASN.1 UTF-8 STRING encoding. */
+#define VERR_ASN1_INVALID_UTF8_STRING_ENCODING      (-22802)
+/** Invalid ASN.1 NUMERIC STRING encoding. */
+#define VERR_ASN1_INVALID_NUMERIC_STRING_ENCODING   (-22803)
+/** Invalid ASN.1 PRINTABLE STRING encoding. */
+#define VERR_ASN1_INVALID_PRINTABLE_STRING_ENCODING (-22804)
+/** Invalid ASN.1 T61/TELETEX STRING encoding. */
+#define VERR_ASN1_INVALID_T61_STRING_ENCODING       (-22805)
+/** Invalid ASN.1 VIDEOTEX STRING encoding. */
+#define VERR_ASN1_INVALID_VIDEOTEX_STRING_ENCODING  (-22806)
+/** Invalid ASN.1 IA5 STRING encoding. */
+#define VERR_ASN1_INVALID_IA5_STRING_ENCODING       (-22807)
+/** Invalid ASN.1 GRAPHIC STRING encoding. */
+#define VERR_ASN1_INVALID_GRAPHIC_STRING_ENCODING   (-22808)
+/** Invalid ASN.1 ISO-646/VISIBLE STRING encoding. */
+#define VERR_ASN1_INVALID_VISIBLE_STRING_ENCODING   (-22809)
+/** Invalid ASN.1 GENERAL STRING encoding. */
+#define VERR_ASN1_INVALID_GENERAL_STRING_ENCODING   (-22810)
+/** Invalid ASN.1 UNIVERSAL STRING encoding. */
+#define VERR_ASN1_INVALID_UNIVERSAL_STRING_ENCODING (-22811)
+/** Invalid ASN.1 BMP STRING encoding. */
+#define VERR_ASN1_INVALID_BMP_STRING_ENCODING       (-22812)
+/** Invalid ASN.1 OBJECT IDENTIFIER encoding. */
+#define VERR_ASN1_INVALID_OBJID_ENCODING            (-22813)
+/** A component value of an ASN.1 OBJECT IDENTIFIER is too big for our
+ * internal representation (32-bits). */
+#define VERR_ASN1_OBJID_COMPONENT_TOO_BIG           (-22814)
+/** Too many components in an ASN.1 OBJECT IDENTIFIER for our internal
+ * representation. */
+#define VERR_ASN1_OBJID_TOO_MANY_COMPONENTS         (-22815)
+/** The dotted-string representation of an ASN.1 OBJECT IDENTIFIER would be too
+ * long for our internal representation. */
+#define VERR_ASN1_OBJID_TOO_LONG_STRING_FORM        (-22816)
+/** Invalid dotted string. */
+#define VERR_ASN1_OBJID_INVALID_DOTTED_STRING       (-22817)
+/** Constructed string type not implemented. */
+#define VERR_ASN1_CONSTRUCTED_STRING_NOT_IMPL       (-22818)
+/** Expected a different string tag. */
+#define VERR_ASN1_STRING_TAG_MISMATCH               (-22819)
+/** Expected a different time tag. */
+#define VERR_ASN1_TIME_TAG_MISMATCH                 (-22820)
+/** More unconsumed data available. */
+#define VINF_ASN1_MORE_DATA                         (22821)
+/** RTAsnEncodeWriteHeader return code indicating that nothing was written
+ *  and the content should be skipped as well. */
+#define VINF_ASN1_NOT_ENCODED                       (22822)
+/** Unknown escape sequence encountered in TeletexString. */
+#define VERR_ASN1_TELETEX_UNKNOWN_ESC_SEQ           (-22823)
+/** Unsupported escape sequence encountered in TeletexString. */
+#define VERR_ASN1_TELETEX_UNSUPPORTED_ESC_SEQ       (-22824)
+/** Unsupported character set. */
+#define VERR_ASN1_TELETEX_UNSUPPORTED_CHARSET       (-22825)
+/** ASN.1 object has no virtual method table. */
+#define VERR_ASN1_NO_VTABLE                         (-22826)
+/** ASN.1 object has no pfnCheckSanity method.  */
+#define VERR_ASN1_NO_CHECK_SANITY_METHOD            (-22827)
+/** ASN.1 object is not present */
+#define VERR_ASN1_NOT_PRESENT                       (-22828)
+/** There are unconsumed bytes after decoding an ASN.1 object. */
+#define VERR_ASN1_CURSOR_NOT_AT_END                 (-22829)
+/** Long ASN.1 tag form is not implemented. */
+#define VERR_ASN1_CURSOR_LONG_TAG                   (-22830)
+/** Bad ASN.1 object length encoding. */
+#define VERR_ASN1_CURSOR_BAD_LENGTH_ENCODING        (-22831)
+/** Indefinite length form is against the rules. */
+#define VERR_ASN1_CURSOR_ILLEGAL_IDEFINITE_LENGTH   (-22832)
+/** Indefinite length form is not implemented. */
+#define VERR_ASN1_CURSOR_IDEFINITE_LENGTH_NOT_SUP   (-22833)
+/** ASN.1 object length goes beyond the end of the byte stream being decoded. */
+#define VERR_ASN1_CURSOR_BAD_LENGTH                 (-22834)
+/** Not more data in ASN.1 byte stream. */
+#define VERR_ASN1_CURSOR_NO_MORE_DATA               (-22835)
+/** Too little data in ASN.1 byte stream. */
+#define VERR_ASN1_CURSOR_TOO_LITTLE_DATA_LEFT       (-22836)
+/** Constructed string is not according to the encoding rules. */
+#define VERR_ASN1_CURSOR_ILLEGAL_CONSTRUCTED_STRING (-22837)
+/** Unexpected ASN.1 tag encountered while decoding. */
+#define VERR_ASN1_CURSOR_TAG_MISMATCH               (-22838)
+/** Unexpected ASN.1 tag class/flag encountered while decoding. */
+#define VERR_ASN1_CURSOR_TAG_FLAG_CLASS_MISMATCH    (-22839)
+/** ASN.1 bit string object is out of bounds. */
+#define VERR_ASN1_BITSTRING_OUT_OF_BOUNDS           (-22840)
+/** Bad ASN.1 time object. */
+#define VERR_ASN1_TIME_BAD_NORMALIZE_INPUT          (-22841)
+/** Failed to normalize ASN.1 time object. */
+#define VERR_ASN1_TIME_NORMALIZE_ERROR              (-22842)
+/** Normalization of ASN.1 time object didn't work out. */
+#define VERR_ASN1_TIME_NORMALIZE_MISMATCH           (-22843)
+/** Invalid ASN.1 UTC TIME encoding. */
+#define VERR_ASN1_INVALID_UTC_TIME_ENCODING         (-22844)
+/** Invalid ASN.1 GENERALIZED TIME encoding. */
+#define VERR_ASN1_INVALID_GENERALIZED_TIME_ENCODING (-22845)
+/** Invalid ASN.1 BOOLEAN encoding. */
+#define VERR_ASN1_INVALID_BOOLEAN_ENCODING          (-22846)
+/** Invalid ASN.1 NULL encoding. */
+#define VERR_ASN1_INVALID_NULL_ENCODING             (-22847)
+/** Invalid ASN.1 BIT STRING encoding. */
+#define VERR_ASN1_INVALID_BITSTRING_ENCODING        (-22848)
+/** Unimplemented ASN.1 tag reached the RTAsn1DynType code. */
+#define VERR_ASN1_DYNTYPE_TAG_NOT_IMPL              (-22849)
+/** ASN.1 tag and flags/class mismatch in RTAsn1DynType code. */
+#define VERR_ASN1_DYNTYPE_BAD_TAG                   (-22850)
+/** Unexpected ASN.1 fake/dummy object. */
+#define VERR_ASN1_DUMMY_OBJECT                      (-22851)
+/** ASN.1 object is too long. */
+#define VERR_ASN1_TOO_LONG                          (-22852)
+/** Expected primitive ASN.1 object. */
+#define VERR_ASN1_EXPECTED_PRIMITIVE                (-22853)
+/** Expected valid data pointer for ASN.1 object. */
+#define VERR_ASN1_INVALID_DATA_POINTER              (-22854)
+/** The ASN.1 encoding is too deeply nested for the decoder. */
+#define VERR_ASN1_TOO_DEEPLY_NESTED                 (-22855)
+/** Generic unexpected object ID error. */
+#define VERR_ASN1_UNEXPECTED_OBJ_ID                 (-22856)
+
+/** ANS.1 internal error 1. */
+#define VERR_ASN1_INTERNAL_ERROR_1                  (-22895)
+/** ANS.1 internal error 2. */
+#define VERR_ASN1_INTERNAL_ERROR_2                  (-22896)
+/** ANS.1 internal error 3. */
+#define VERR_ASN1_INTERNAL_ERROR_3                  (-22897)
+/** ANS.1 internal error 4. */
+#define VERR_ASN1_INTERNAL_ERROR_4                  (-22898)
+/** ANS.1 internal error 5. */
+#define VERR_ASN1_INTERNAL_ERROR_5                  (-22899)
+/** @} */
+
+/** @name More RTLdr status codes.
+ * @{ */
+/** Image Verification Failure: No Authenticode Signature. */
+#define VERR_LDRVI_NOT_SIGNED                       (-22900)
+/** Image Verification Warning: No Authenticode Signature, but on whitelist. */
+#define VINF_LDRVI_NOT_SIGNED                       (22900)
+/** Image Verification Failure: Error reading image headers.  */
+#define VERR_LDRVI_READ_ERROR_HDR                   (-22901)
+/** Image Verification Failure: Error reading section headers. */
+#define VERR_LDRVI_READ_ERROR_SHDRS                 (-22902)
+/** Image Verification Failure: Error reading authenticode signature data. */
+#define VERR_LDRVI_READ_ERROR_SIGNATURE             (-22903)
+/** Image Verification Failure: Error reading file for hashing. */
+#define VERR_LDRVI_READ_ERROR_HASH                  (-22904)
+/** Image Verification Failure: Error determining the file length. */
+#define VERR_LDRVI_FILE_LENGTH_ERROR                (-22905)
+/** Image Verification Failure: Error allocating memory for state data. */
+#define VERR_LDRVI_NO_MEMORY_STATE                  (-22906)
+/** Image Verification Failure: Error allocating memory for authenticode
+ *  signature data. */
+#define VERR_LDRVI_NO_MEMORY_SIGNATURE              (-22907)
+/** Image Verification Failure: Error allocating memory for section headers. */
+#define VERR_LDRVI_NO_MEMORY_SHDRS                  (-22908)
+/** Image Verification Failure: Authenticode parsing output. */
+#define VERR_LDRVI_NO_MEMORY_PARSE_OUTPUT           (-22909)
+/** Image Verification Failure: Invalid security directory entry. */
+#define VERR_LDRVI_INVALID_SECURITY_DIR_ENTRY       (-22910)
+/** Image Verification Failure:  */
+#define VERR_LDRVI_BAD_CERT_HDR_LENGTH              (-22911)
+/** Image Verification Failure:  */
+#define VERR_LDRVI_BAD_CERT_HDR_REVISION            (-22912)
+/** Image Verification Failure:  */
+#define VERR_LDRVI_BAD_CERT_HDR_TYPE                (-22913)
+/** Image Verification Failure: More than one certificate table entry.  */
+#define VERR_LDRVI_BAD_CERT_MULTIPLE                (-22914)
+
+/** Image Verification Failure:  */
+#define VERR_LDRVI_BAD_MZ_OFFSET                    (-22915)
+/** Image Verification Failure: Invalid section count. */
+#define VERR_LDRVI_INVALID_SECTION_COUNT            (-22916)
+/** Image Verification Failure: Raw data offsets and sizes are out of range. */
+#define VERR_LDRVI_SECTION_RAW_DATA_VALUES          (-22917)
+/** Optional header magic and target machine does not match. */
+#define VERR_LDRVI_MACHINE_OPT_HDR_MAGIC_MISMATCH   (-22918)
+/** Unsupported image target architecture. */
+#define VERR_LDRVI_UNSUPPORTED_ARCH                 (-22919)
+
+/** Image Verification Failure: Internal error in signature parser. */
+#define VERR_LDRVI_PARSE_IPE                        (-22921)
+/** Generic BER parse error. Will be refined later. */
+#define VERR_LDRVI_PARSE_BER_ERROR                  (-22922)
+
+/** Expected the signed data content to be the object ID of
+ * SpcIndirectDataContent, found something else instead. */
+#define VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID (-22923)
+/** Page hash table size overflow. */
+#define VERR_LDRVI_PAGE_HASH_TAB_SIZE_OVERFLOW      (-22924)
+/** Page hash table is too long (covers signature data, i.e. itself). */
+#define VERR_LDRVI_PAGE_HASH_TAB_TOO_LONG           (-22925)
+/** The page hash table is not strictly ordered by offset. */
+#define VERR_LDRVI_PAGE_HASH_TAB_NOT_STRICTLY_SORTED (-22926)
+/** The page hash table hashes data outside the defined and implicit sections. */
+#define VERR_PAGE_HASH_TAB_HASHES_NON_SECTION_DATA  (-22927)
+/** Page hash mismatch. */
+#define VERR_LDRVI_PAGE_HASH_MISMATCH               (-22928)
+/** Image hash mismatch. */
+#define VERR_LDRVI_IMAGE_HASH_MISMATCH              (-22929)
+
+/** Cannot resolve symbol because it's a forwarder. */
+#define VERR_LDR_FORWARDER                          (-22950)
+/** The symbol is not a forwarder. */
+#define VERR_LDR_NOT_FORWARDER                      (-22951)
+/** Malformed forwarder entry. */
+#define VERR_LDR_BAD_FORWARDER                      (-22952)
+/** Too long forwarder chain or there is a loop. */
+#define VERR_LDR_FORWARDER_CHAIN_TOO_LONG           (-22953)
+/** Support for forwarders has not been implemented. */
+#define VERR_LDR_FORWARDERS_NOT_SUPPORTED           (-22954)
+/** @} */
+
+/** @name RTCrX509 status codes.
+ * @{ */
+/** Generic X.509 error. */
+#define VERR_CR_X509_GENERIC_ERROR                  (-23000)
+/** Internal error in the X.509 code. */
+#define VERR_CR_X509_INTERNAL_ERROR                 (-23001)
+/** Internal error in the X.509 certificate path building and verification
+ * code. */
+#define VERR_CR_X509_CERTPATHS_INTERNAL_ERROR       (-23002)
+/** Path not verified yet. */
+#define VERR_CR_X509_NOT_VERIFIED                   (-23003)
+/** The certificate path has no trust anchor. */
+#define VERR_CR_X509_NO_TRUST_ANCHOR                (-23004)
+/** Unknown X.509 certificate signature algorithm. */
+#define VERR_CR_X509_UNKNOWN_CERT_SIGN_ALGO         (-23005)
+/** Certificate signature algorithm mismatch. */
+#define VERR_CR_X509_CERT_SIGN_ALGO_MISMATCH        (-23006)
+/** The signature algorithm in the to-be-signed certificate part does not match
+ * the one associated with the signature. */
+#define VERR_CR_X509_CERT_TBS_SIGN_ALGO_MISMATCH    (-23007)
+/** Certificate extensions requires certificate version 3 or later.  */
+#define VERR_CR_X509_TBSCERT_EXTS_REQ_V3            (-23008)
+/** Unique issuer and subject IDs require version certificate 2. */
+#define VERR_CR_X509_TBSCERT_UNIQUE_IDS_REQ_V2      (-23009)
+/** Certificate serial number length is out of bounds. */
+#define VERR_CR_X509_TBSCERT_SERIAL_NUMBER_OUT_OF_BOUNDS (-23010)
+/** Unsupported X.509 certificate version. */
+#define VERR_CR_X509_TBSCERT_UNSUPPORTED_VERSION    (-23011)
+/** Public key is too small. */
+#define VERR_CR_X509_PUBLIC_KEY_TOO_SMALL           (-23012)
+/** Invalid string tag for a X.509 name object. */
+#define VERR_CR_X509_INVALID_NAME_STRING_TAG        (-23013)
+/** Empty string in X.509 name object. */
+#define VERR_CR_X509_NAME_EMPTY_STRING              (-23014)
+/** Non-string object inside X.509 name object. */
+#define VERR_CR_X509_NAME_NOT_STRING                (-23015)
+/** Empty set inside X.509 name. */
+#define VERR_CR_X509_NAME_EMPTY_SET                 (-23016)
+/** Empty sub-string set inside X.509 name. */
+#define VERR_CR_X509_NAME_EMPTY_SUB_SET             (-23017)
+/** The NotBefore and NotAfter values of an X.509 Validity object seems to
+ * have been swapped around. */
+#define VERR_CR_X509_VALIDITY_SWAPPED               (-23018)
+/** Duplicate certificate extension. */
+#define VERR_CR_X509_TBSCERT_DUPLICATE_EXTENSION    (-23019)
+/** Missing relative distinguished name map entry. */
+#define VERR_CR_X509_NAME_MISSING_RDN_MAP_ENTRY     (-23020)
+/** Certificate path validator: No trusted certificate paths. */
+#define VERR_CR_X509_CPV_NO_TRUSTED_PATHS           (-23021)
+/** Certificate path validator: No valid certificate policy. */
+#define VERR_CR_X509_CPV_NO_VALID_POLICY            (-23022)
+/** Certificate path validator: Unknown critical certificate extension. */
+#define VERR_CR_X509_CPV_UNKNOWN_CRITICAL_EXTENSION (-23023)
+/** Certificate path validator: Intermediate certificate is missing the
+ *  KeyCertSign usage flag. */
+#define VERR_CR_X509_CPV_MISSING_KEY_CERT_SIGN      (-23024)
+/** Certificate path validator: Hit the max certificate path length before
+ *  reaching trust anchor. */
+#define VERR_CR_X509_CPV_MAX_PATH_LENGTH            (-23025)
+/** Certificate path validator: Intermediate certificate is not marked as a
+ *  certificate authority (CA). */
+#define VERR_CR_X509_CPV_NOT_CA_CERT                (-23026)
+/** Certificate path validator: Intermediate certificate is not a version 3
+ *  certificate. */
+#define VERR_CR_X509_CPV_NOT_V3_CERT                (-23027)
+/** Certificate path validator: Invalid policy mapping (to/from anyPolicy). */
+#define VERR_CR_X509_CPV_INVALID_POLICY_MAPPING     (-23028)
+/** Certificate path validator: Name constraints permits no names. */
+#define VERR_CR_X509_CPV_NO_PERMITTED_NAMES         (-23029)
+/** Certificate path validator: Name constraints does not permits the
+ *  certificate name. */
+#define VERR_CR_X509_CPV_NAME_NOT_PERMITTED         (-23030)
+/** Certificate path validator: Name constraints does not permits the
+ *  alternative certificate name. */
+#define VERR_CR_X509_CPV_ALT_NAME_NOT_PERMITTED     (-23031)
+/** Certificate path validator: Intermediate certificate subject does not
+ *  match child issuer property. */
+#define VERR_CR_X509_CPV_ISSUER_MISMATCH            (-23032)
+/** Certificate path validator: The certificate is not valid at the
+ *  specified time. */
+#define VERR_CR_X509_CPV_NOT_VALID_AT_TIME          (-23033)
+/** Certificate path validator: Unexpected choice found in general subtree
+ *  object (name constraints). */
+#define VERR_CR_X509_CPV_UNEXP_GENERAL_SUBTREE_CHOICE (-23034)
+/** Certificate path validator: Unexpected minimum value found in general
+ *  subtree object (name constraints). */
+#define VERR_CR_X509_CPV_UNEXP_GENERAL_SUBTREE_MIN  (-23035)
+/** Certificate path validator: Unexpected maximum value found in
+ *  general subtree object (name constraints). */
+#define VERR_CR_X509_CPV_UNEXP_GENERAL_SUBTREE_MAX  (-23036)
+/** Certificate path builder: Encountered bad certificate context. */
+#define VERR_CR_X509_CPB_BAD_CERT_CTX               (-23037)
+/** OpenSSL d2i_X509 failed. */
+#define VERR_CR_X509_OSSL_D2I_FAILED                (-23090)
+/** @} */
+
+/** @name RTCrPkcs7 status codes.
+ * @{ */
+/** Generic PKCS \#7 error. */
+#define VERR_CR_PKCS7_GENERIC_ERROR                             (-23300)
+/** Signed data verification failed because there are zero signer infos. */
+#define VERR_CR_PKCS7_NO_SIGNER_INFOS                           (-23301)
+/** Signed data certificate not found. */
+#define VERR_CR_PKCS7_SIGNED_DATA_CERT_NOT_FOUND                (-23302)
+/** Signed data verification failed due to key usage issues. */
+#define VERR_CR_PKCS7_KEY_USAGE_MISMATCH                        (-23303)
+/** Signed data verification failed because of missing (or duplicate)
+ * authenticated content-type attribute. */
+#define VERR_CR_PKCS7_MISSING_CONTENT_TYPE_ATTRIB               (-23304)
+/** Signed data verification failed because of the authenticated content-type
+ *  attribute did not match. */
+#define VERR_CR_PKCS7_CONTENT_TYPE_ATTRIB_MISMATCH              (-23305)
+/** Signed data verification failed because of a malformed authenticated
+ *  content-type attribute. */
+#define VERR_CR_PKCS7_BAD_CONTENT_TYPE_ATTRIB                   (-23306)
+/** Signed data verification failed because of missing (or duplicate)
+ * authenticated message-digest attribute. */
+#define VERR_CR_PKCS7_MISSING_MESSAGE_DIGEST_ATTRIB             (-23307)
+/** Signed data verification failed because the authenticated message-digest
+ *  attribute did not match. */
+#define VERR_CR_PKCS7_MESSAGE_DIGEST_ATTRIB_MISMATCH            (-23308)
+/** Signed data verification failed because of a malformed authenticated
+ *  message-digest attribute. */
+#define VERR_CR_PKCS7_BAD_MESSAGE_DIGEST_ATTRIB                 (-23309)
+/** Signature verification failed. */
+#define VERR_CR_PKCS7_SIGNATURE_VERIFICATION_FAILED             (-23310)
+/** Internal PKCS \#7 error. */
+#define VERR_CR_PKCS7_INTERNAL_ERROR                            (-22311)
+/** OpenSSL d2i_PKCS7 failed. */
+#define VERR_CR_PKCS7_OSSL_D2I_FAILED                           (-22312)
+/** OpenSSL PKCS \#7 verification failed. */
+#define VERR_CR_PKCS7_OSSL_VERIFY_FAILED                        (-22313)
+/** Digest algorithm parameters are not supported by the PKCS \#7 code. */
+#define VERR_CR_PKCS7_DIGEST_PARAMS_NOT_IMPL                    (-22314)
+/** The digest algorithm of a signer info entry was not found in the list of
+ *  digest algorithms in the signed data. */
+#define VERR_CR_PKCS7_DIGEST_ALGO_NOT_FOUND_IN_LIST             (-22315)
+/** The PKCS \#7 content is not signed data. */
+#define VERR_CR_PKCS7_NOT_SIGNED_DATA                           (-22316)
+/** No digest algorithms listed in PKCS \#7 signed data. */
+#define VERR_CR_PKCS7_NO_DIGEST_ALGORITHMS                      (-22317)
+/** Too many digest algorithms used by PKCS \#7 signed data.  This is an
+ * internal limitation of the code that aims at saving kernel stack space. */
+#define VERR_CR_PKCS7_TOO_MANY_DIGEST_ALGORITHMS                (-22318)
+/** Error creating digest algorithm calculator. */
+#define VERR_CR_PKCS7_DIGEST_CREATE_ERROR                       (-22319)
+/** Error while calculating a digest for a PKCS \#7 verification operation. */
+#define VERR_CR_PKCS7_DIGEST_CALC_ERROR                         (-22320)
+/** Unsupported PKCS \#7 signed data version. */
+#define VERR_CR_PKCS7_SIGNED_DATA_VERSION                       (-22350)
+/** PKCS \#7 signed data has no digest algorithms listed. */
+#define VERR_CR_PKCS7_SIGNED_DATA_NO_DIGEST_ALGOS               (-22351)
+/** Unknown digest algorithm used by PKCS \#7 object. */
+#define VERR_CR_PKCS7_UNKNOWN_DIGEST_ALGORITHM                  (-22352)
+/** Expected PKCS \#7 object to ship at least one certificate. */
+#define VERR_CR_PKCS7_NO_CERTIFICATES                           (-22353)
+/** Expected PKCS \#7 object to not contain any CRLs. */
+#define VERR_CR_PKCS7_EXPECTED_NO_CRLS                          (-22354)
+/** Expected PKCS \#7 object to contain exactly on signer info entry. */
+#define VERR_CR_PKCS7_EXPECTED_ONE_SIGNER_INFO                  (-22355)
+/** Unsupported PKCS \#7 signer info version. */
+#define VERR_CR_PKCS7_SIGNER_INFO_VERSION                       (-22356)
+/** PKCS \#7 singer info contains no issuer serial number. */
+#define VERR_CR_PKCS7_SIGNER_INFO_NO_ISSUER_SERIAL_NO           (-22357)
+/** Expected PKCS \#7 object to ship the signer certificate(s). */
+#define VERR_CR_PKCS7_SIGNER_CERT_NOT_SHIPPED                   (-22358)
+/** The encrypted digest algorithm does not match the one in the certificate. */
+#define VERR_CR_PKCS7_SIGNER_INFO_DIGEST_ENCRYPT_MISMATCH       (-22359)
+/** @} */
+
+/** @name RTCrSpc status codes.
+ * @{ */
+/** Generic SPC error. */
+#define VERR_CR_SPC_GENERIC_ERROR                               (-23400)
+/** SPC requires there to be exactly one SignerInfo entry. */
+#define VERR_CR_SPC_NOT_EXACTLY_ONE_SIGNER_INFOS                (-23401)
+/** There shall be exactly one digest algorithm to go with the single
+ *  SingerInfo entry required by SPC. */
+#define VERR_CR_SPC_NOT_EXACTLY_ONE_DIGEST_ALGO                 (-23402)
+/** The digest algorithm in the SignerInfo does not match the one in the
+ *  indirect data. */
+#define VERR_CR_SPC_SIGNED_IND_DATA_DIGEST_ALGO_MISMATCH        (-23403)
+/** The digest algorithm in the indirect data was not found in the list of
+ * digest algorithms in the signed data structure. */
+#define VERR_CR_SPC_IND_DATA_DIGEST_ALGO_NOT_IN_DIGEST_ALGOS    (-23404)
+/** The digest algorithm is not known to us. */
+#define VERR_CR_SPC_UNKNOWN_DIGEST_ALGO                         (-23405)
+/** The indirect data digest size does not match the digest algorithm. */
+#define VERR_CR_SPC_IND_DATA_DIGEST_SIZE_MISMATCH               (-23406)
+/** Expected PE image data inside indirect data object. */
+#define VERR_CR_SPC_EXPECTED_PE_IMAGE_DATA                      (-23407)
+/** Internal SPC error: The PE image data is missing.  */
+#define VERR_CR_SPC_PEIMAGE_DATA_NOT_PRESENT                    (-23408)
+/** Bad SPC object moniker UUID field. */
+#define VERR_CR_SPC_BAD_MONIKER_UUID                            (-23409)
+/** Unknown SPC object moniker UUID. */
+#define VERR_CR_SPC_UNKNOWN_MONIKER_UUID                        (-23410)
+/** Internal SPC error: Bad object moniker choice value. */
+#define VERR_CR_SPC_BAD_MONIKER_CHOICE                          (-23411)
+/** Internal SPC error: Bad object moniker data pointer. */
+#define VERR_CR_SPC_MONIKER_BAD_DATA                             (-23412)
+/** Multiple PE image page hash tables. */
+#define VERR_CR_SPC_PEIMAGE_MULTIPLE_HASH_TABS                  (-23413)
+/** Unknown SPC PE image attribute. */
+#define VERR_CR_SPC_PEIMAGE_UNKNOWN_ATTRIBUTE                   (-23414)
+/** URL not expected in SPC PE image data. */
+#define VERR_CR_SPC_PEIMAGE_URL_UNEXPECTED                      (-23415)
+/** PE image data without any valid content was not expected. */
+#define VERR_CR_SPC_PEIMAGE_NO_CONTENT                          (-23416)
+/** @} */
+
+/** @name RTCrPkix status codes.
+ * @{ */
+/** Generic PKCS \#7 error. */
+#define VERR_CR_PKIX_GENERIC_ERROR                  (-23500)
+/** Parameters was presented to a signature schema that does not take any. */
+#define VERR_CR_PKIX_SIGNATURE_TAKES_NO_PARAMETERS  (-23501)
+/** Unknown hash digest type. */
+#define VERR_CR_PKIX_UNKNOWN_DIGEST_TYPE            (-23502)
+/** Internal error. */
+#define VERR_CR_PKIX_INTERNAL_ERROR                 (-23503)
+/** The hash is too long for the key used when signing/verifying. */
+#define VERR_CR_PKIX_HASH_TOO_LONG_FOR_KEY          (-23504)
+/** The signature is too long for the scratch buffer. */
+#define VERR_CR_PKIX_SIGNATURE_TOO_LONG             (-23505)
+/** The signature is greater than or equal to the key. */
+#define VERR_CR_PKIX_SIGNATURE_GE_KEY               (-23506)
+/** The signature is negative. */
+#define VERR_CR_PKIX_SIGNATURE_NEGATIVE             (-23507)
+/** Invalid signature length. */
+#define VERR_CR_PKIX_INVALID_SIGNATURE_LENGTH       (-23508)
+/** PKIX signature no does not match up to the current data. */
+#define VERR_CR_PKIX_SIGNATURE_MISMATCH             (-23509)
+/** PKIX cipher algorithm parameters are not implemented. */
+#define VERR_CR_PKIX_CIPHER_ALGO_PARAMS_NOT_IMPL    (-23510)
+/** Cipher algorithm is not known to us. */
+#define VERR_CR_PKIX_CIPHER_ALGO_NOT_KNOWN          (-23511)
+/** PKIX cipher algorithm is not known to OpenSSL. */
+#define VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN     (-23512)
+/** PKIX cipher algorithm is not known to OpenSSL EVP API. */
+#define VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP (-23513)
+/** OpenSSL failed to init PKIX cipher algorithm context. */
+#define VERR_CR_PKIX_OSSL_CIPHER_ALOG_INIT_FAILED   (-23514)
+/** Final OpenSSL PKIX verification failed. */
+#define VERR_CR_PKIX_OSSL_VERIFY_FINAL_FAILED       (-23515)
+/** OpenSSL failed to decode the public key. */
+#define VERR_CR_PKIX_OSSL_D2I_PUBLIC_KEY_FAILED     (-23516)
+/** The EVP_PKEY_type API in OpenSSL failed.  */
+#define VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR       (-23517)
+/** @} */
+
+/** @name RTCrStore status codes.
+ * @{ */
+/** Generic store error. */
+#define VERR_CR_STORE_GENERIC_ERROR                 (-23700)
+/** @} */
+
+/** @name RTCrRsa status codes.
+ * @{ */
+/** Generic RSA error. */
+#define VERR_CR_RSA_GENERIC_ERROR                   (-23900)
+/** @} */
+
+/** @name RTBigNum status codes.
+ * @{ */
+/** Sensitive input requires the result(s) to be initialized as sensitive. */
+#define VERR_BIGNUM_SENSITIVE_INPUT                 (-24000)
+/** Attempt to divide by zero. */
+#define VERR_BIGNUM_DIV_BY_ZERO                     (-24001)
+/** Negative exponent makes no sense to integer math. */
+#define VERR_BIGNUM_NEGATIVE_EXPONENT               (-24002)
+
+/** @} */
+
+/** @name RTCrDigest status codes.
+ * @{ */
+/** OpenSSL failed to initialize the digest algorithm context. */
+#define VERR_CR_DIGEST_OSSL_DIGEST_INIT_ERROR       (-24200)
+/** OpenSSL failed to clone the digest algorithm context. */
+#define VERR_CR_DIGEST_OSSL_DIGEST_CTX_COPY_ERROR   (-24201)
+/** @} */
+
+/** @name RTPath  status codes.
+ * @{ */
+/** Unknown glob variable.  */
+#define VERR_PATH_MATCH_UNKNOWN_VARIABLE            (-24400)
+/** The specified glob variable must be first in the pattern. */
+#define VERR_PATH_MATCH_VARIABLE_MUST_BE_FIRST      (-24401)
+/** Hit unimplemented glob pattern matching feature.  */
+#define VERR_PATH_MATCH_FEATURE_NOT_IMPLEMENTED     (-24402)
+/** Unknown character class in glob pattern.   */
+#define VERR_PATH_GLOB_UNKNOWN_CHAR_CLASS           (-24403)
+/** @} */
+
+/** @name RTUri status codes.
+ * @{ */
+/** The URI is empty */
+#define VERR_URI_EMPTY                              (-24600)
+/** The URI is too short to be a valid URI. */
+#define VERR_URI_TOO_SHORT                          (-24601)
+/** Invalid scheme.  */
+#define VERR_URI_INVALID_SCHEME                     (-24602)
+/** Invalid port number.  */
+#define VERR_URI_INVALID_PORT_NUMBER                (-24603)
+/** Invalid escape sequence.  */
+#define VERR_URI_INVALID_ESCAPE_SEQ                 (-24604)
+/** Escape URI char decodes as zero (the C string terminator). */
+#define VERR_URI_ESCAPED_ZERO                       (-24605)
+/** Escaped URI characters does not decode to valid UTF-8. */
+#define VERR_URI_ESCAPED_CHARS_NOT_VALID_UTF8       (-24606)
+/** Escaped URI character is not a valid UTF-8 lead byte. */
+#define VERR_URI_INVALID_ESCAPED_UTF8_LEAD_BYTE     (-24607)
+/** Escaped URI character sequence with invalid UTF-8 continutation byte. */
+#define VERR_URI_INVALID_ESCAPED_UTF8_CONTINUATION_BYTE (-24608)
+/** Missing UTF-8 continutation in escaped URI character sequence. */
+#define VERR_URI_MISSING_UTF8_CONTINUATION_BYTE     (-24609)
+/** Expected URI using the 'file:' scheme. */
+#define VERR_URI_NOT_FILE_SCHEME                    (-24610)
+/** @} */
+
+/** @name RTJson status codes.
+ * @{ */
+/** The called method does not work with the value type of the given JSON value. */
+#define VERR_JSON_VALUE_INVALID_TYPE                (-24700)
+/** The iterator reached the end. */
+#define VERR_JSON_ITERATOR_END                      (-24701)
+/** The JSON document is malformed. */
+#define VERR_JSON_MALFORMED                         (-24702)
+/** @} */
+
+/* SED-END */
+
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/errno.h b/ubuntu/vbox/include/iprt/errno.h
new file mode 100644 (file)
index 0000000..b9d1ee3
--- /dev/null
@@ -0,0 +1,320 @@
+/** @file
+ * IPRT - errno.h wrapper.
+ */
+
+/*
+ * Copyright (C) 2012-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.
+ */
+
+
+#ifndef ___iprt_errno_h___
+#define ___iprt_errno_h___
+
+#ifndef IPRT_NO_CRT
+# if defined(RT_OS_DARWIN) && defined(KERNEL)
+#  include <sys/errno.h>
+# elif defined(RT_OS_LINUX) && defined(__KERNEL__)
+#  include <linux/errno.h>
+# elif defined(RT_OS_FREEBSD) && defined(_KERNEL)
+#  include <sys/errno.h>
+# elif defined(RT_OS_NETBSD) && defined(_KERNEL)
+#  include <sys/errno.h>
+# else
+#  include <errno.h>
+# endif
+#endif
+
+
+/*
+ * Supply missing errno values according to the current RT_OS_XXX definition.
+ *
+ * Note! These supplements are for making no-CRT mode, as well as making UNIXy
+ *       code that makes used of odd errno defines internally, work smoothly.
+ *
+ * When adding more error codes, always check the following errno.h sources:
+ *  - RT_OS_DARWIN:  http://fxr.watson.org/fxr/source/bsd/sys/errno.h?v=xnu-1699.24.8
+ *  - RT_OS_FREEBSD: http://fxr.watson.org/fxr/source/sys/errno.h?v=DFBSD
+ *  - RT_OS_NETBSD:  http://fxr.watson.org/fxr/source/sys/errno.h?v=NETBSD
+ *  - RT_OS_OPENBSD: http://fxr.watson.org/fxr/source/sys/errno.h?v=OPENBSD
+ *  - RT_OS_OS2:     http://svn.netlabs.org/libc/browser/trunk/libc/include/sys/errno.h
+ *  - RT_OS_LINUX:   http://fxr.watson.org/fxr/source/include/asm-generic/errno.h?v=linux-2.6
+ *  - RT_OS_SOLARIS: http://fxr.watson.org/fxr/source/common/sys/errno.h?v=OPENSOLARIS
+ *  - RT_OS_WINDOWS: tools/win.x86/vcc/v8sp1/include/errno.h
+ */
+
+#if defined(RT_OS_DARWIN) \
+ || defined(RT_OS_FREEBSD) \
+ || defined(RT_OS_NETBSD) \
+ || defined(RT_OS_OPENBSD) \
+ || defined(RT_OS_OS2)
+# define RT_ERRNO_OS_BSD
+#endif
+#ifdef RT_OS_SOLARIS
+# define RT_ERRNO_OS_SYSV_HARDCORE /* ?? */
+#endif
+
+/* The relatively similar part. */
+#ifndef EPERM
+# define EPERM                  (1)
+#endif
+#ifndef ENOENT
+# define ENOENT                 (2)
+#endif
+#ifndef ESRCH
+# define ESRCH                  (3)
+#endif
+#ifndef EINTR
+# define EINTR                  (4)
+#endif
+#ifndef EIO
+# define EIO                    (5)
+#endif
+#ifndef ENXIO
+# define ENXIO                  (6)
+#endif
+#ifndef E2BIG
+# define E2BIG                  (7)
+#endif
+#ifndef ENOEXEC
+# define ENOEXEC                (8)
+#endif
+#ifndef EBADF
+# define EBADF                  (9)
+#endif
+#ifndef ECHILD
+# define ECHILD                 (10)
+#endif
+#ifndef EAGAIN
+# if defined(RT_ERRNO_OS_BSD)
+#  define EAGAIN                (35)
+# else
+#  define EAGAIN                (11)
+# endif
+#endif
+#ifndef EWOULDBLOCK
+# define EWOULDBLOCK            EAGAIN
+#endif
+#ifndef EDEADLK
+# if defined(RT_ERRNO_OS_BSD)
+#  define EDEADLK               (11)
+# elif defined(RT_OS_LINUX)
+#  define EDEADLK               (35)
+# elif defined(RT_OS_WINDOWS)
+#  define EDEADLK               (36)
+# else
+#  define EDEADLK               (45)
+# endif
+#endif
+#ifndef EDEADLOCK
+# define EDEADLOCK              EDEADLK
+#endif
+#ifndef ENOMEM
+# define ENOMEM                 (12)
+#endif
+#ifndef EACCES
+# define EACCES                 (13)
+#endif
+#ifndef EFAULT
+# define EFAULT                 (14)
+#endif
+#ifndef ENOTBLK
+# define ENOTBLK                (15)
+#endif
+#ifndef EBUSY
+# define EBUSY                  (16)
+#endif
+#ifndef EEXIST
+# define EEXIST                 (17)
+#endif
+#ifndef EXDEV
+# define EXDEV                  (18)
+#endif
+#ifndef ENODEV
+# define ENODEV                 (19)
+#endif
+#ifndef ENOTDIR
+# define ENOTDIR                (20)
+#endif
+#ifndef EISDIR
+# define EISDIR                 (21)
+#endif
+#ifndef EINVAL
+# define EINVAL                 (22)
+#endif
+#ifndef ENFILE
+# define ENFILE                 (23)
+#endif
+#ifndef EMFILE
+# define EMFILE                 (24)
+#endif
+#ifndef ENOTTY
+# define ENOTTY                 (25)
+#endif
+#ifndef ETXTBSY
+# define ETXTBSY                (26)
+#endif
+#ifndef EFBIG
+# define EFBIG                  (27)
+#endif
+#ifndef ENOSPC
+# define ENOSPC                 (28)
+#endif
+#ifndef ESPIPE
+# define ESPIPE                 (29)
+#endif
+#ifndef EROFS
+# define EROFS                  (30)
+#endif
+#ifndef EMLINK
+# define EMLINK                 (31)
+#endif
+#ifndef EPIPE
+# define EPIPE                  (32)
+#endif
+#ifndef EDOM
+# define EDOM                   (33)
+#endif
+#ifndef ERANGE
+# define ERANGE                 (34)
+#endif
+
+/* 35 - also EAGAIN on BSD and EDEADLK on Linux. */
+#ifndef ENOMSG
+# if defined(RT_OS_DARWIN)
+#  define ENOMSG                (91)
+# elif defined(RT_OS_FREEBSD)
+#  define ENOMSG                (83)
+# elif defined(RT_OS_LINUX)
+#  define ENOMSG                (42)
+# else
+#  define ENOMSG                (35)
+# endif
+#endif
+
+/* 36 - Also EDEADLK on Windows.  */
+#ifndef EIDRM
+# if defined(RT_OS_DARWIN)
+#  define EIDRM                 (90)
+# elif defined(RT_OS_FREEBSD) || defined(RT_OS_NETBSD)
+#  define EIDRM                 (82)
+# elif defined(RT_OS_OPENBSD)
+#  define EIDRM                 (89)
+# elif defined(RT_OS_LINUX)
+#  define EIDRM                 (43)
+# elif defined(RT_OS_WINDOWS)
+#  define EIDRM                 (600)
+# else
+#  define EIDRM                 (36)
+# endif
+#endif
+#ifndef EINPROGRESS
+# if defined(RT_ERRNO_OS_BSD)
+#  define EINPROGRESS           (36)
+# elif defined(RT_OS_LINUX)
+#  define EINPROGRESS           (115)
+# else
+#  define EINPROGRESS           (150)
+# endif
+#endif
+#ifndef ENAMETOOLONG
+# if defined(RT_ERRNO_OS_BSD)
+#  define ENAMETOOLONG          (63)
+# elif defined(RT_OS_LINUX)
+#  define ENAMETOOLONG          (36)
+# else
+#  define ENAMETOOLONG          (78)
+# endif
+#endif
+
+/* 37 */
+#ifndef ECHRNG
+# if defined(RT_ERRNO_OS_SYSV_HARDCORE)
+#  define ECHRNG                (37)
+# else
+#  define ECHRNG                (599)
+# endif
+#endif
+#ifndef ENOLCK
+# if defined(RT_ERRNO_OS_BSD)
+#  define ENOLCK                (77)
+# elif defined(RT_OS_LINUX)
+#  define ENOLCK                (37)
+# else
+#  define ENOLCK                (46)
+# endif
+#endif
+#ifndef EALREADY
+# if defined(RT_ERRNO_OS_BSD)
+#  define EALREADY              (37)
+# elif defined(RT_OS_LINUX)
+#  define EALREADY              (114)
+# else
+#  define EALREADY              (149)
+# endif
+#endif
+
+/** @todo errno constants {37..44}. */
+
+/* 45 - also EDEADLK on Solaris, EL2NSYNC on Linux. */
+#ifndef ENOTSUP
+# if defined(RT_ERRNO_OS_BSD)
+#  define ENOTSUP               (45)
+# elif defined(RT_OS_LINUX)
+#  define ENOTSUP               (95)
+# else
+#  define ENOTSUP               (48)
+# endif
+#endif
+#ifndef EOPNOTSUPP
+# if defined(RT_ERRNO_OS_BSD)
+#  define EOPNOTSUPP            ENOTSUP
+# elif defined(RT_OS_LINUX)
+#  define EOPNOTSUPP            ENOTSUP
+# else
+#  define EOPNOTSUPP            (122)
+# endif
+#endif
+
+/** @todo errno constants {46..74}. */
+
+/* 75 - note that Solaris has constant with value 75. */
+#ifndef EOVERFLOW
+# if defined(RT_OS_OPENBSD)
+#  define EOVERFLOW             (87)
+# elif defined(RT_ERRNO_OS_BSD)
+#  define EOVERFLOW             (84)
+# elif defined(RT_OS_LINUX)
+#  define EOVERFLOW             (75)
+# else
+#  define EOVERFLOW             (79)
+# endif
+#endif
+#ifndef EPROGMISMATCH
+# if defined(RT_ERRNO_OS_BSD)
+#  define EPROGMISMATCH         (75)
+# else
+#  define EPROGMISMATCH         (598)
+# endif
+#endif
+
+/** @todo errno constants {76..}. */
+
+
+#endif
diff --git a/ubuntu/vbox/include/iprt/fs.h b/ubuntu/vbox/include/iprt/fs.h
new file mode 100644 (file)
index 0000000..b62c564
--- /dev/null
@@ -0,0 +1,637 @@
+/** @file
+ * IPRT - Filesystem.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_fs_h
+#define ___iprt_fs_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/time.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_fs    RTFs - Filesystem and Volume
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/** @name Filesystem Object Mode Flags.
+ *
+ * There are two sets of flags: the unix mode flags and the dos attributes.
+ *
+ * APIs returning mode flags will provide both sets.
+ *
+ * When specifying mode flags to any API at least one of them must be given. If
+ * one set is missing the API will synthesize it from the one given if it
+ * requires it.
+ *
+ * Both sets match their x86 ABIs, the DOS/NT one is simply shifted up 16 bits.
+ * The DOS/NT range is bits 16 to 31 inclusively. The Unix range is bits 0 to 15
+ * (inclusively).
+ *
+ * @remarks These constants have been comitted to a binary format and must not
+ *          be changed in any incompatible ways.
+ *
+ * @{
+ */
+
+/** Set user id on execution (S_ISUID). */
+#define RTFS_UNIX_ISUID             0004000U
+/** Set group id on execution (S_ISGID). */
+#define RTFS_UNIX_ISGID             0002000U
+/** Sticky bit (S_ISVTX / S_ISTXT). */
+#define RTFS_UNIX_ISTXT             0001000U
+
+/** Owner RWX mask (S_IRWXU). */
+#define RTFS_UNIX_IRWXU             0000700U
+/** Owner readable (S_IRUSR). */
+#define RTFS_UNIX_IRUSR             0000400U
+/** Owner writable (S_IWUSR). */
+#define RTFS_UNIX_IWUSR             0000200U
+/** Owner executable (S_IXUSR). */
+#define RTFS_UNIX_IXUSR             0000100U
+
+/** Group RWX mask (S_IRWXG). */
+#define RTFS_UNIX_IRWXG             0000070U
+/** Group readable (S_IRGRP). */
+#define RTFS_UNIX_IRGRP             0000040U
+/** Group writable (S_IWGRP). */
+#define RTFS_UNIX_IWGRP             0000020U
+/** Group executable (S_IXGRP). */
+#define RTFS_UNIX_IXGRP             0000010U
+
+/** Other RWX mask (S_IRWXO). */
+#define RTFS_UNIX_IRWXO             0000007U
+/** Other readable (S_IROTH). */
+#define RTFS_UNIX_IROTH             0000004U
+/** Other writable (S_IWOTH). */
+#define RTFS_UNIX_IWOTH             0000002U
+/** Other executable (S_IXOTH). */
+#define RTFS_UNIX_IXOTH             0000001U
+
+/** All UNIX access permission bits (0777). */
+#define RTFS_UNIX_ALL_ACCESS_PERMS  0000777U
+/** All UNIX permission bits, including set id and sticky bits.  */
+#define RTFS_UNIX_ALL_PERMS         0007777U
+
+/** Named pipe (fifo) (S_IFIFO). */
+#define RTFS_TYPE_FIFO              0010000U
+/** Character device (S_IFCHR). */
+#define RTFS_TYPE_DEV_CHAR          0020000U
+/** Directory (S_IFDIR). */
+#define RTFS_TYPE_DIRECTORY         0040000U
+/** Block device (S_IFBLK). */
+#define RTFS_TYPE_DEV_BLOCK         0060000U
+/** Regular file (S_IFREG). */
+#define RTFS_TYPE_FILE              0100000U
+/** Symbolic link (S_IFLNK). */
+#define RTFS_TYPE_SYMLINK           0120000U
+/** Socket (S_IFSOCK). */
+#define RTFS_TYPE_SOCKET            0140000U
+/** Whiteout (S_IFWHT). */
+#define RTFS_TYPE_WHITEOUT          0160000U
+/** Type mask (S_IFMT). */
+#define RTFS_TYPE_MASK              0170000U
+/** The shift count to convert between RTFS_TYPE_MASK and DIRENTRYTYPE. */
+#define RTFS_TYPE_DIRENTRYTYPE_SHIFT    12
+
+/** Unix attribute mask. */
+#define RTFS_UNIX_MASK              0xffffU
+/** The mask of all the NT, OS/2 and DOS attributes. */
+#define RTFS_DOS_MASK               (0x7fffU << RTFS_DOS_SHIFT)
+
+/** The shift value. */
+#define RTFS_DOS_SHIFT              16
+/** The mask of the OS/2 and DOS attributes. */
+#define RTFS_DOS_MASK_OS2           (0x003fU << RTFS_DOS_SHIFT)
+/** The mask of the NT attributes. */
+#define RTFS_DOS_MASK_NT            (0x7fffU << RTFS_DOS_SHIFT)
+
+/** Readonly object. */
+#define RTFS_DOS_READONLY           (0x0001U << RTFS_DOS_SHIFT)
+/** Hidden object. */
+#define RTFS_DOS_HIDDEN             (0x0002U << RTFS_DOS_SHIFT)
+/** System object. */
+#define RTFS_DOS_SYSTEM             (0x0004U << RTFS_DOS_SHIFT)
+/** Directory. */
+#define RTFS_DOS_DIRECTORY          (0x0010U << RTFS_DOS_SHIFT)
+/** Archived object.
+ * This bit is set by the filesystem after each modification of a file. */
+#define RTFS_DOS_ARCHIVED           (0x0020U << RTFS_DOS_SHIFT)
+/** Undocumented / Reserved, used to be the FAT volume label. */
+#define RTFS_DOS_NT_DEVICE          (0x0040U << RTFS_DOS_SHIFT)
+/** Normal object, no other attribute set (NT). */
+#define RTFS_DOS_NT_NORMAL          (0x0080U << RTFS_DOS_SHIFT)
+/** Temporary object (NT). */
+#define RTFS_DOS_NT_TEMPORARY       (0x0100U << RTFS_DOS_SHIFT)
+/** Sparse file (NT). */
+#define RTFS_DOS_NT_SPARSE_FILE     (0x0200U << RTFS_DOS_SHIFT)
+/** Reparse point (NT). */
+#define RTFS_DOS_NT_REPARSE_POINT   (0x0400U << RTFS_DOS_SHIFT)
+/** Compressed object (NT).
+ * For a directory, compression is the default for new files. */
+#define RTFS_DOS_NT_COMPRESSED      (0x0800U << RTFS_DOS_SHIFT)
+/** Physically offline data (NT).
+ * MSDN say, don't mess with this one. */
+#define RTFS_DOS_NT_OFFLINE         (0x1000U << RTFS_DOS_SHIFT)
+/** Not content indexed by the content indexing service (NT). */
+#define RTFS_DOS_NT_NOT_CONTENT_INDEXED (0x2000U << RTFS_DOS_SHIFT)
+/** Encryped object (NT).
+ * For a directory, encrypted is the default for new files. */
+#define RTFS_DOS_NT_ENCRYPTED       (0x4000U << RTFS_DOS_SHIFT)
+
+/** @} */
+
+
+/** @name Filesystem Object Type Predicates.
+ * @{ */
+/** Checks the mode flags indicate a named pipe (fifo) (S_ISFIFO). */
+#define RTFS_IS_FIFO(fMode)         ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_FIFO )
+/** Checks the mode flags indicate a character device (S_ISCHR). */
+#define RTFS_IS_DEV_CHAR(fMode)     ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_DEV_CHAR )
+/** Checks the mode flags indicate a directory (S_ISDIR). */
+#define RTFS_IS_DIRECTORY(fMode)    ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_DIRECTORY )
+/** Checks the mode flags indicate a block device (S_ISBLK). */
+#define RTFS_IS_DEV_BLOCK(fMode)    ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_DEV_BLOCK )
+/** Checks the mode flags indicate a regular file (S_ISREG). */
+#define RTFS_IS_FILE(fMode)         ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_FILE )
+/** Checks the mode flags indicate a symbolic link (S_ISLNK). */
+#define RTFS_IS_SYMLINK(fMode)      ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_SYMLINK )
+/** Checks the mode flags indicate a socket (S_ISSOCK). */
+#define RTFS_IS_SOCKET(fMode)       ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_SOCKET )
+/** Checks the mode flags indicate a whiteout (S_ISWHT). */
+#define RTFS_IS_WHITEOUT(fMode)     ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_WHITEOUT )
+/** @} */
+
+
+/**
+ * Filesystem type IDs returned by RTFsQueryType.
+ *
+ * This enum is subject to changes and must not be used as part of any ABI or
+ * binary format (file, network, etc).
+ *
+ * @remarks When adding new entries, please update RTFsTypeName().  Also, try
+ *          add them to the most natural group.
+ */
+typedef enum RTFSTYPE
+{
+    /** Unknown file system. */
+    RTFSTYPE_UNKNOWN = 0,
+
+    /** Universal Disk Format. */
+    RTFSTYPE_UDF,
+    /** ISO 9660, aka Compact Disc File System (CDFS). */
+    RTFSTYPE_ISO9660,
+    /** Filesystem in Userspace. */
+    RTFSTYPE_FUSE,
+    /** VirtualBox shared folders.  */
+    RTFSTYPE_VBOXSHF,
+
+    /* Linux: */
+    RTFSTYPE_EXT,
+    RTFSTYPE_EXT2,
+    RTFSTYPE_EXT3,
+    RTFSTYPE_EXT4,
+    RTFSTYPE_XFS,
+    RTFSTYPE_CIFS,
+    RTFSTYPE_SMBFS,
+    RTFSTYPE_TMPFS,
+    RTFSTYPE_SYSFS,
+    RTFSTYPE_PROC,
+    RTFSTYPE_OCFS2,
+    RTFSTYPE_BTRFS,
+
+    /* Windows: */
+    /** New Technology File System. */
+    RTFSTYPE_NTFS,
+    /** FAT12, FAT16 and FAT32 lumped into one basket.
+     * The partition size limit of FAT12 and FAT16 will be the factor
+     * limiting the file size (except, perhaps for the 64KB cluster case on
+     * non-Windows hosts). */
+    RTFSTYPE_FAT,
+
+    /* Solaris: */
+    /** Zettabyte File System.  */
+    RTFSTYPE_ZFS,
+    /** Unix File System. */
+    RTFSTYPE_UFS,
+    /** Network File System. */
+    RTFSTYPE_NFS,
+
+    /* Mac OS X: */
+    /** Hierarchical File System. */
+    RTFSTYPE_HFS,
+    /** @todo RTFSTYPE_HFS_PLUS? */
+    RTFSTYPE_AUTOFS,
+    RTFSTYPE_DEVFS,
+
+    /* *BSD: */
+
+    /* OS/2: */
+    /** High Performance File System. */
+    RTFSTYPE_HPFS,
+    /** Journaled File System (v2).  */
+    RTFSTYPE_JFS,
+
+    /** The end of valid Filesystem types IDs. */
+    RTFSTYPE_END,
+    /** The usual 32-bit type blow up. */
+    RTFSTYPE_32BIT_HACK = 0x7fffffff
+} RTFSTYPE;
+/** Pointer to a Filesystem type ID. */
+typedef RTFSTYPE *PRTFSTYPE;
+
+
+/**
+ * The available additional information in a RTFSOBJATTR object.
+ */
+typedef enum RTFSOBJATTRADD
+{
+    /** No additional information is available / requested. */
+    RTFSOBJATTRADD_NOTHING = 1,
+    /** The additional unix attributes (RTFSOBJATTR::u::Unix) are available /
+     *  requested. */
+    RTFSOBJATTRADD_UNIX,
+    /** The additional unix attributes (RTFSOBJATTR::u::UnixOwner) are
+     * available / requested. */
+    RTFSOBJATTRADD_UNIX_OWNER,
+    /** The additional unix attributes (RTFSOBJATTR::u::UnixGroup) are
+     * available / requested. */
+    RTFSOBJATTRADD_UNIX_GROUP,
+    /** The additional extended attribute size (RTFSOBJATTR::u::EASize) is available / requested. */
+    RTFSOBJATTRADD_EASIZE,
+    /** The last valid item (inclusive).
+     * The valid range is RTFSOBJATTRADD_NOTHING thru RTFSOBJATTRADD_LAST.  */
+    RTFSOBJATTRADD_LAST = RTFSOBJATTRADD_EASIZE,
+
+    /** The usual 32-bit hack. */
+    RTFSOBJATTRADD_32BIT_SIZE_HACK = 0x7fffffff
+} RTFSOBJATTRADD;
+
+/** The number of bytes reserved for the additional attribute union. */
+#define RTFSOBJATTRUNION_MAX_SIZE       128
+
+/**
+ * Additional Unix Attributes (RTFSOBJATTRADD_UNIX).
+ */
+typedef struct RTFSOBJATTRUNIX
+{
+    /** The user owning the filesystem object (st_uid).
+     * This field is NIL_UID if not supported. */
+    RTUID           uid;
+
+    /** The group the filesystem object is assigned (st_gid).
+     * This field is NIL_GID if not supported. */
+    RTGID           gid;
+
+    /** Number of hard links to this filesystem object (st_nlink).
+     * This field is 1 if the filesystem doesn't support hardlinking or
+     * the information isn't available.
+     */
+    uint32_t        cHardlinks;
+
+    /** The device number of the device which this filesystem object resides on (st_dev).
+     * This field is 0 if this information is not available. */
+    RTDEV           INodeIdDevice;
+
+    /** The unique identifier (within the filesystem) of this filesystem object (st_ino).
+     * Together with INodeIdDevice, this field can be used as a OS wide unique id
+     * when both their values are not 0.
+     * This field is 0 if the information is not available. */
+    RTINODE         INodeId;
+
+    /** User flags (st_flags).
+     * This field is 0 if this information is not available. */
+    uint32_t        fFlags;
+
+    /** The current generation number (st_gen).
+     * This field is 0 if this information is not available. */
+    uint32_t        GenerationId;
+
+    /** The device number of a character or block device type object (st_rdev).
+     * This field is 0 if the file isn't of a character or block device type and
+     * when the OS doesn't subscribe to the major+minor device idenfication scheme. */
+    RTDEV           Device;
+} RTFSOBJATTRUNIX;
+
+
+/**
+ * Additional Unix Attributes (RTFSOBJATTRADD_UNIX_OWNER).
+ *
+ * @remarks This interface is mainly for TAR.
+ */
+typedef struct RTFSOBJATTRUNIXOWNER
+{
+    /** The user owning the filesystem object (st_uid).
+     * This field is NIL_UID if not supported. */
+    RTUID           uid;
+    /** The user name.
+     * Empty if not available or not supported, truncated if too long. */
+    char            szName[RTFSOBJATTRUNION_MAX_SIZE - sizeof(RTUID)];
+} RTFSOBJATTRUNIXOWNER;
+
+
+/**
+ * Additional Unix Attributes (RTFSOBJATTRADD_UNIX_GROUP).
+ *
+ * @remarks This interface is mainly for TAR.
+ */
+typedef struct RTFSOBJATTRUNIXGROUP
+{
+    /** The user owning the filesystem object (st_uid).
+     * This field is NIL_GID if not supported. */
+    RTGID           gid;
+    /** The group name.
+     * Empty if not available or not supported, truncated if too long. */
+    char            szName[RTFSOBJATTRUNION_MAX_SIZE - sizeof(RTGID)];
+} RTFSOBJATTRUNIXGROUP;
+
+
+/**
+ * Filesystem object attributes.
+ */
+typedef struct RTFSOBJATTR
+{
+    /** Mode flags (st_mode). RTFS_UNIX_*, RTFS_TYPE_*, and RTFS_DOS_*. */
+    RTFMODE         fMode;
+
+    /** The additional attributes available. */
+    RTFSOBJATTRADD  enmAdditional;
+
+    /**
+     * Additional attributes.
+     *
+     * Unless explicitly specified to an API, the API can provide additional
+     * data as it is provided by the underlying OS.
+     */
+    union RTFSOBJATTRUNION
+    {
+        /** Additional Unix Attributes - RTFSOBJATTRADD_UNIX. */
+        RTFSOBJATTRUNIX         Unix;
+        /** Additional Unix Owner Attributes - RTFSOBJATTRADD_UNIX_OWNER. */
+        RTFSOBJATTRUNIXOWNER    UnixOwner;
+        /** Additional Unix Group Attributes - RTFSOBJATTRADD_UNIX_GROUP. */
+        RTFSOBJATTRUNIXGROUP    UnixGroup;
+
+        /**
+         * Extended attribute size is available when RTFS_DOS_HAVE_EA_SIZE is set.
+         */
+        struct RTFSOBJATTREASIZE
+        {
+            /** Size of EAs. */
+            RTFOFF          cb;
+        } EASize;
+        /** Reserved space. */
+        uint8_t         abReserveSpace[128];
+    } u;
+} RTFSOBJATTR;
+/** Pointer to a filesystem object attributes structure. */
+typedef RTFSOBJATTR *PRTFSOBJATTR;
+/** Pointer to a const filesystem object attributes structure. */
+typedef const RTFSOBJATTR *PCRTFSOBJATTR;
+
+
+/**
+ * Filesystem object information structure.
+ *
+ * This is returned by the RTPathQueryInfo(), RTFileQueryInfo() and RTDirRead() APIs.
+ */
+typedef struct RTFSOBJINFO
+{
+   /** Logical size (st_size).
+    * For normal files this is the size of the file.
+    * For symbolic links, this is the length of the path name contained
+    * in the symbolic link.
+    * For other objects this fields needs to be specified.
+    */
+   RTFOFF       cbObject;
+
+   /** Disk allocation size (st_blocks * DEV_BSIZE). */
+   RTFOFF       cbAllocated;
+
+   /** Time of last access (st_atime). */
+   RTTIMESPEC   AccessTime;
+
+   /** Time of last data modification (st_mtime). */
+   RTTIMESPEC   ModificationTime;
+
+   /** Time of last status change (st_ctime).
+    * If not available this is set to ModificationTime.
+    */
+   RTTIMESPEC   ChangeTime;
+
+   /** Time of file birth (st_birthtime).
+    * If not available this is set to ChangeTime.
+    */
+   RTTIMESPEC   BirthTime;
+
+   /** Attributes. */
+   RTFSOBJATTR  Attr;
+
+} RTFSOBJINFO;
+/** Pointer to a filesystem object information structure. */
+typedef RTFSOBJINFO *PRTFSOBJINFO;
+/** Pointer to a const filesystem object information structure. */
+typedef const RTFSOBJINFO *PCRTFSOBJINFO;
+
+
+#ifdef IN_RING3
+
+/**
+ * Query the sizes of a filesystem.
+ *
+ * @returns iprt status code.
+ * @param   pszFsPath       Path within the mounted filesystem.
+ * @param   pcbTotal        Where to store the total filesystem space. (Optional)
+ * @param   pcbFree         Where to store the remaining free space in the filesystem. (Optional)
+ * @param   pcbBlock        Where to store the block size. (Optional)
+ * @param   pcbSector       Where to store the sector size. (Optional)
+ *
+ * @sa      RTFileQueryFsSizes
+ */
+RTR3DECL(int) RTFsQuerySizes(const char *pszFsPath, PRTFOFF pcbTotal, RTFOFF *pcbFree,
+                             uint32_t *pcbBlock, uint32_t *pcbSector);
+
+/**
+ * Query the mountpoint of a filesystem.
+ *
+ * @returns iprt status code.
+ * @returns VERR_BUFFER_OVERFLOW if cbMountpoint isn't enough.
+ * @param   pszFsPath       Path within the mounted filesystem.
+ * @param   pszMountpoint   Where to store the mountpoint path.
+ * @param   cbMountpoint    Size of the buffer pointed to by pszMountpoint.
+ */
+RTR3DECL(int) RTFsQueryMountpoint(const char *pszFsPath, char *pszMountpoint, size_t cbMountpoint);
+
+/**
+ * Query the label of a filesystem.
+ *
+ * @returns iprt status code.
+ * @returns VERR_BUFFER_OVERFLOW if cbLabel isn't enough.
+ * @param   pszFsPath       Path within the mounted filesystem.
+ * @param   pszLabel        Where to store the label.
+ * @param   cbLabel         Size of the buffer pointed to by pszLabel.
+ */
+RTR3DECL(int) RTFsQueryLabel(const char *pszFsPath, char *pszLabel, size_t cbLabel);
+
+/**
+ * Query the serial number of a filesystem.
+ *
+ * @returns iprt status code.
+ * @param   pszFsPath       Path within the mounted filesystem.
+ * @param   pu32Serial      Where to store the serial number.
+ */
+RTR3DECL(int) RTFsQuerySerial(const char *pszFsPath, uint32_t *pu32Serial);
+
+/**
+ * Query the name of the filesystem driver.
+ *
+ * @returns iprt status code.
+ * @returns VERR_BUFFER_OVERFLOW if cbFsDriver isn't enough.
+ * @param   pszFsPath       Path within the mounted filesystem.
+ * @param   pszFsDriver     Where to store the filesystem driver name.
+ * @param   cbFsDriver      Size of the buffer pointed to by pszFsDriver.
+ */
+RTR3DECL(int) RTFsQueryDriver(const char *pszFsPath, char *pszFsDriver, size_t cbFsDriver);
+
+/**
+ * Query the name of the filesystem the file is located on.
+ *
+ * @returns iprt status code.
+ * @param   pszFsPath       Path within the mounted filesystem.  It must exist.
+ *                          In case this is a symlink, the file it refers to is
+ *                          evaluated.
+ * @param   penmType        Where to store the filesystem type, this is always
+ *                          set.  See RTFSTYPE for the values.
+ */
+RTR3DECL(int) RTFsQueryType(const char *pszFsPath, PRTFSTYPE penmType);
+
+#endif /* IN_RING3 */
+
+/**
+ * Gets the name of a filesystem type.
+ *
+ * @returns Pointer to a read-only string containing the name.
+ * @param   enmType         A valid filesystem ID.  If outside the valid range,
+ *                          the returned string will be pointing to a static
+ *                          memory buffer which will be changed on subsequent
+ *                          calls to this function by any thread.
+ */
+RTDECL(const char *) RTFsTypeName(RTFSTYPE enmType);
+
+/**
+ * Filesystem properties.
+ */
+typedef struct RTFSPROPERTIES
+{
+    /** The maximum size of a filesystem object name.
+     * This does not include the '\\0'. */
+    uint32_t cbMaxComponent;
+
+    /** True if the filesystem is remote.
+     * False if the filesystem is local. */
+    bool    fRemote;
+
+    /** True if the filesystem is case sensitive.
+     * False if the filesystem is case insensitive. */
+    bool    fCaseSensitive;
+
+    /** True if the filesystem is mounted read only.
+     * False if the filesystem is mounted read write. */
+    bool    fReadOnly;
+
+    /** True if the filesystem can encode unicode object names.
+     * False if it can't. */
+    bool    fSupportsUnicode;
+
+    /** True if the filesystem is compresses.
+     * False if it isn't or we don't know. */
+    bool    fCompressed;
+
+    /** True if the filesystem compresses of individual files.
+     * False if it doesn't or we don't know. */
+    bool    fFileCompression;
+
+    /** @todo more? */
+} RTFSPROPERTIES;
+/** Pointer to a filesystem properties structure. */
+typedef RTFSPROPERTIES *PRTFSPROPERTIES;
+/** Pointer to a const filesystem properties structure. */
+typedef RTFSPROPERTIES const *PCRTFSPROPERTIES;
+
+#ifdef IN_RING3
+
+/**
+ * Query the properties of a mounted filesystem.
+ *
+ * @returns iprt status code.
+ * @param   pszFsPath       Path within the mounted filesystem.
+ * @param   pProperties     Where to store the properties.
+ */
+RTR3DECL(int) RTFsQueryProperties(const char *pszFsPath, PRTFSPROPERTIES pProperties);
+
+/**
+ * Checks if the given volume is case sensitive or not.
+ *
+ * This may be misleading in some cases as we lack the necessary APIs to query
+ * the information on some system (or choose not to use them) and are instead
+ * returning the general position on case sensitive file name of the system.
+ *
+ * @returns @c true if case sensitive, @c false if not.
+ * @param   pszFsPath       Path within the mounted file system.
+ */
+RTR3DECL(bool) RTFsIsCaseSensitive(const char *pszFsPath);
+
+/**
+ * Mountpoint enumerator callback.
+ *
+ * @returns iprt status code. Failure terminates the enumeration.
+ * @param   pszMountpoint   The mountpoint name.
+ * @param   pvUser          The user argument.
+ */
+typedef DECLCALLBACK(int) FNRTFSMOUNTPOINTENUM(const char *pszMountpoint, void *pvUser);
+/** Pointer to a FNRTFSMOUNTPOINTENUM(). */
+typedef FNRTFSMOUNTPOINTENUM *PFNRTFSMOUNTPOINTENUM;
+
+/**
+ * Enumerate mount points.
+ *
+ * @returns iprt status code.
+ * @param   pfnCallback     The callback function.
+ * @param   pvUser          The user argument to the callback.
+ */
+RTR3DECL(int) RTFsMountpointsEnum(PFNRTFSMOUNTPOINTENUM pfnCallback, void *pvUser);
+
+
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !___iprt_fs_h */
+
diff --git a/ubuntu/vbox/include/iprt/heap.h b/ubuntu/vbox/include/iprt/heap.h
new file mode 100644 (file)
index 0000000..eefcc6b
--- /dev/null
@@ -0,0 +1,356 @@
+/** @file
+ * IPRT - Heap Implementations
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_heap_h
+#define ___iprt_heap_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_heap       RTHeap - Heap Implementations
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/** @defgroup grp_rt_heap_simple    RTHeapSimple - Simple Heap
+ * @{
+ */
+
+/**
+ * Initializes the heap.
+ *
+ * @returns IPRT status code.
+ * @param   pHeap       Where to store the heap anchor block on success.
+ * @param   pvMemory    Pointer to the heap memory.
+ * @param   cbMemory    The size of the heap memory.
+ */
+RTDECL(int) RTHeapSimpleInit(PRTHEAPSIMPLE pHeap, void *pvMemory, size_t cbMemory);
+
+/**
+ * Merge two simple heaps into one.
+ *
+ * The requirement is of course that they next two each other memory wise.
+ *
+ * @returns IPRT status code.
+ * @param   pHeap       Where to store the handle to the merged heap on success.
+ * @param   Heap1       Handle to the first heap.
+ * @param   Heap2       Handle to the second heap.
+ * @remark  This API isn't implemented yet.
+ */
+RTDECL(int) RTHeapSimpleMerge(PRTHEAPSIMPLE pHeap, RTHEAPSIMPLE Heap1, RTHEAPSIMPLE Heap2);
+
+/**
+ * Relocater the heap internal structures after copying it to a new location.
+ *
+ * This can be used when loading a saved heap.
+ *
+ * @returns IPRT status code.
+ * @param   hHeap       Heap handle that has already been adjusted by to the new
+ *                      location.  That is to say, when calling
+ *                      RTHeapSimpleInit, the caller must note the offset of the
+ *                      returned heap handle into the heap memory.  This offset
+ *                      must be used when calcuating the handle value for the
+ *                      new location.  The offset may in some cases not be zero!
+ * @param   offDelta    The delta between the new and old location, i.e. what
+ *                      should be added to the internal pointers.
+ */
+RTDECL(int) RTHeapSimpleRelocate(RTHEAPSIMPLE hHeap, uintptr_t offDelta);
+
+/**
+ * Allocates memory from the specified simple heap.
+ *
+ * @returns Pointer to the allocated memory block on success.
+ * @returns NULL if the request cannot be satisfied. (A VERR_NO_MEMORY condition.)
+ *
+ * @param   Heap        The heap to allocate the memory on.
+ * @param   cb          The requested heap block size.
+ * @param   cbAlignment The requested heap block alignment. Pass 0 for default alignment.
+ *                      Must be a power of 2.
+ */
+RTDECL(void *) RTHeapSimpleAlloc(RTHEAPSIMPLE Heap, size_t cb, size_t cbAlignment);
+
+/**
+ * Allocates zeroed memory from the specified simple heap.
+ *
+ * @returns Pointer to the allocated memory block on success.
+ * @returns NULL if the request cannot be satisfied. (A VERR_NO_MEMORY condition.)
+ *
+ * @param   Heap        The heap to allocate the memory on.
+ * @param   cb          The requested heap block size.
+ * @param   cbAlignment The requested heap block alignment. Pass 0 for default alignment.
+ *                      Must be a power of 2.
+ */
+RTDECL(void *) RTHeapSimpleAllocZ(RTHEAPSIMPLE Heap, size_t cb, size_t cbAlignment);
+
+/**
+ * Reallocates / Allocates / Frees a heap block.
+ *
+ * @param   Heap        The heap. This is optional and will only be used for strict assertions.
+ * @param   pv          The heap block returned by RTHeapSimple. If NULL it behaves like RTHeapSimpleAlloc().
+ * @param   cbNew       The new size of the heap block. If NULL it behaves like RTHeapSimpleFree().
+ * @param   cbAlignment The requested heap block alignment. Pass 0 for default alignment.
+ *                      Must be a power of 2.
+ * @remark  This API isn't implemented yet.
+ */
+RTDECL(void *) RTHeapSimpleRealloc(RTHEAPSIMPLE Heap, void *pv, size_t cbNew, size_t cbAlignment);
+
+/**
+ * Reallocates / Allocates / Frees a heap block, zeroing any new bits.
+ *
+ * @param   Heap        The heap. This is optional and will only be used for strict assertions.
+ * @param   pv          The heap block returned by RTHeapSimple. If NULL it behaves like RTHeapSimpleAllocZ().
+ * @param   cbNew       The new size of the heap block. If NULL it behaves like RTHeapSimpleFree().
+ * @param   cbAlignment The requested heap block alignment. Pass 0 for default alignment.
+ *                      Must be a power of 2.
+ * @remark  This API isn't implemented yet.
+ */
+RTDECL(void *) RTHeapSimpleReallocZ(RTHEAPSIMPLE Heap, void *pv, size_t cbNew, size_t cbAlignment);
+
+/**
+ * Frees memory allocated from a simple heap.
+ *
+ * @param   Heap    The heap. This is optional and will only be used for strict assertions.
+ * @param   pv      The heap block returned by RTHeapSimple
+ */
+RTDECL(void) RTHeapSimpleFree(RTHEAPSIMPLE Heap, void *pv);
+
+/**
+ * Gets the size of the specified heap block.
+ *
+ * @returns The actual size of the heap block.
+ * @returns 0 if \a pv is NULL or it doesn't point to a valid heap block. An invalid \a pv
+ *          can also cause traps or trigger assertions.
+ * @param   Heap    The heap. This is optional and will only be used for strict assertions.
+ * @param   pv      The heap block returned by RTHeapSimple
+ */
+RTDECL(size_t) RTHeapSimpleSize(RTHEAPSIMPLE Heap, void *pv);
+
+/**
+ * Gets the size of the heap.
+ *
+ * This size includes all the internal heap structures. So, even if the heap is
+ * empty the RTHeapSimpleGetFreeSize() will never reach the heap size returned
+ * by this function.
+ *
+ * @returns The heap size.
+ * @returns 0 if heap was safely detected as being bad.
+ * @param   Heap    The heap.
+ */
+RTDECL(size_t) RTHeapSimpleGetHeapSize(RTHEAPSIMPLE Heap);
+
+/**
+ * Returns the sum of all free heap blocks.
+ *
+ * This is the amount of memory you can theoretically allocate
+ * if you do allocations exactly matching the free blocks.
+ *
+ * @returns The size of the free blocks.
+ * @returns 0 if heap was safely detected as being bad.
+ * @param   Heap    The heap.
+ */
+RTDECL(size_t) RTHeapSimpleGetFreeSize(RTHEAPSIMPLE Heap);
+
+/**
+ * Printf like callbaclk function for RTHeapSimpleDump.
+ * @param   pszFormat   IPRT format string.
+ * @param   ...         Format arguments.
+ */
+typedef DECLCALLBACK(void) FNRTHEAPSIMPLEPRINTF(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+/** Pointer to a FNRTHEAPSIMPLEPRINTF function. */
+typedef FNRTHEAPSIMPLEPRINTF *PFNRTHEAPSIMPLEPRINTF;
+
+/**
+ * Dumps the hypervisor heap.
+ *
+ * @param   Heap        The heap handle.
+ * @param   pfnPrintf   Printf like function that groks IPRT formatting.
+ */
+RTDECL(void) RTHeapSimpleDump(RTHEAPSIMPLE Heap, PFNRTHEAPSIMPLEPRINTF pfnPrintf);
+
+/** @}  */
+
+
+
+/** @defgroup grp_rt_heap_offset    RTHeapOffset - Offset Based Heap
+ *
+ * This is a variation on the simple heap that doesn't use pointers internally
+ * and therefore can be saved and restored without any extra effort.
+ *
+ * @{
+ */
+
+/**
+ * Initializes the heap.
+ *
+ * @returns IPRT status code.
+ * @param   phHeap      Where to store the heap anchor block on success.
+ * @param   pvMemory    Pointer to the heap memory.
+ * @param   cbMemory    The size of the heap memory.
+ */
+RTDECL(int) RTHeapOffsetInit(PRTHEAPOFFSET phHeap, void *pvMemory, size_t cbMemory);
+
+/**
+ * Merge two simple heaps into one.
+ *
+ * The requirement is of course that they next two each other memory wise.
+ *
+ * @returns IPRT status code.
+ * @param   phHeap      Where to store the handle to the merged heap on success.
+ * @param   hHeap1      Handle to the first heap.
+ * @param   hHeap2      Handle to the second heap.
+ * @remark  This API isn't implemented yet.
+ */
+RTDECL(int) RTHeapOffsetMerge(PRTHEAPOFFSET phHeap, RTHEAPOFFSET hHeap1, RTHEAPOFFSET hHeap2);
+
+/**
+ * Allocates memory from the specified simple heap.
+ *
+ * @returns Pointer to the allocated memory block on success.
+ * @returns NULL if the request cannot be satisfied. (A VERR_NO_MEMORY condition.)
+ *
+ * @param   hHeap       The heap to allocate the memory on.
+ * @param   cb          The requested heap block size.
+ * @param   cbAlignment The requested heap block alignment. Pass 0 for default alignment.
+ *                      Must be a power of 2.
+ */
+RTDECL(void *) RTHeapOffsetAlloc(RTHEAPOFFSET hHeap, size_t cb, size_t cbAlignment);
+
+/**
+ * Allocates zeroed memory from the specified simple heap.
+ *
+ * @returns Pointer to the allocated memory block on success.
+ * @returns NULL if the request cannot be satisfied. (A VERR_NO_MEMORY condition.)
+ *
+ * @param   hHeap       The heap to allocate the memory on.
+ * @param   cb          The requested heap block size.
+ * @param   cbAlignment The requested heap block alignment. Pass 0 for default
+ *                      alignment. Must be a power of 2.
+ */
+RTDECL(void *) RTHeapOffsetAllocZ(RTHEAPOFFSET hHeap, size_t cb, size_t cbAlignment);
+
+/**
+ * Reallocates / Allocates / Frees a heap block.
+ *
+ * @param   hHeap       The heap handle. This is optional and will only be used
+ *                      for strict assertions.
+ * @param   pv          The heap block returned by RTHeapOffset. If NULL it
+ *                      behaves like RTHeapOffsetAlloc().
+ * @param   cbNew       The new size of the heap block. If NULL it behaves like
+ *                      RTHeapOffsetFree().
+ * @param   cbAlignment The requested heap block alignment. Pass 0 for default
+ *                      alignment. Must be a power of 2.
+ * @remark  This API isn't implemented yet.
+ */
+RTDECL(void *) RTHeapOffsetRealloc(RTHEAPOFFSET hHeap, void *pv, size_t cbNew, size_t cbAlignment);
+
+/**
+ * Reallocates / Allocates / Frees a heap block, zeroing any new bits.
+ *
+ * @param   hHeap       The heap handle. This is optional and will only be used
+ *                      for strict assertions.
+ * @param   pv          The heap block returned by RTHeapOffset. If NULL it
+ *                      behaves like RTHeapOffsetAllocZ().
+ * @param   cbNew       The new size of the heap block. If NULL it behaves like
+ *                      RTHeapOffsetFree().
+ * @param   cbAlignment The requested heap block alignment. Pass 0 for default
+ *                      alignment. Must be a power of 2.
+ * @remark  This API isn't implemented yet.
+ */
+RTDECL(void *) RTHeapOffsetReallocZ(RTHEAPOFFSET hHeap, void *pv, size_t cbNew, size_t cbAlignment);
+
+/**
+ * Frees memory allocated from a simple heap.
+ *
+ * @param   hHeap       The heap handle. This is optional and will only be used
+ *                      for strict assertions.
+ * @param   pv          The heap block returned by RTHeapOffset
+ */
+RTDECL(void) RTHeapOffsetFree(RTHEAPOFFSET hHeap, void *pv);
+
+/**
+ * Gets the size of the specified heap block.
+ *
+ * @returns The actual size of the heap block.
+ * @returns 0 if \a pv is NULL or it doesn't point to a valid heap block. An
+ *          invalid \a pv can also cause traps or trigger assertions.
+ *
+ * @param   hHeap       The heap handle. This is optional and will only be used
+ *                      for strict assertions.
+ * @param   pv          The heap block returned by RTHeapOffset
+ */
+RTDECL(size_t) RTHeapOffsetSize(RTHEAPOFFSET hHeap, void *pv);
+
+/**
+ * Gets the size of the heap.
+ *
+ * This size includes all the internal heap structures. So, even if the heap is
+ * empty the RTHeapOffsetGetFreeSize() will never reach the heap size returned
+ * by this function.
+ *
+ * @returns The heap size.
+ * @returns 0 if heap was safely detected as being bad.
+ * @param   hHeap       The heap handle.
+ */
+RTDECL(size_t) RTHeapOffsetGetHeapSize(RTHEAPOFFSET hHeap);
+
+/**
+ * Returns the sum of all free heap blocks.
+ *
+ * This is the amount of memory you can theoretically allocate
+ * if you do allocations exactly matching the free blocks.
+ *
+ * @returns The size of the free blocks.
+ * @returns 0 if heap was safely detected as being bad.
+ * @param   hHeap       The heap handle.
+ */
+RTDECL(size_t) RTHeapOffsetGetFreeSize(RTHEAPOFFSET hHeap);
+
+/**
+ * Printf like callbaclk function for RTHeapOffsetDump.
+ * @param   pszFormat   IPRT format string.
+ * @param   ...         Format arguments.
+ */
+typedef DECLCALLBACK(void) FNRTHEAPOFFSETPRINTF(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+/** Pointer to a FNRTHEAPOFFSETPRINTF function. */
+typedef FNRTHEAPOFFSETPRINTF *PFNRTHEAPOFFSETPRINTF;
+
+/**
+ * Dumps the hypervisor heap.
+ *
+ * @param   hHeap       The heap handle.
+ * @param   pfnPrintf   Printf like function that groks IPRT formatting.
+ */
+RTDECL(void) RTHeapOffsetDump(RTHEAPOFFSET hHeap, PFNRTHEAPOFFSETPRINTF pfnPrintf);
+
+/** @}  */
+
+/** @}  */
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/initterm.h b/ubuntu/vbox/include/iprt/initterm.h
new file mode 100644 (file)
index 0000000..18ca2e9
--- /dev/null
@@ -0,0 +1,263 @@
+/** @file
+ * IPRT - Runtime Init/Term.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_initterm_h
+#define ___iprt_initterm_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt    IPRT C/C++ APIs
+ * @{
+ */
+
+/** @defgroup grp_rt_initterm  RTInit/RTTerm - Initialization and Termination
+ *
+ * APIs for initializing and terminating the IPRT, optionally it can also
+ * convert input arguments to UTF-8 (in ring-3).
+ *
+ * @sa RTOnce, RTOnceEx.
+ *
+ * @{
+ */
+
+#ifdef IN_RING3
+/** @name RTR3Init flags (RTR3INIT_XXX).
+ * @{ */
+/** Try initialize SUPLib. */
+#define RTR3INIT_FLAGS_SUPLIB       RT_BIT(0)
+/** Initializing IPRT from a DLL. */
+#define RTR3INIT_FLAGS_DLL          RT_BIT(1)
+/** We are sharing a process space, so we need to behave. */
+#define RTR3INIT_FLAGS_UNOBTRUSIVE  RT_BIT(2)
+/** The caller ensures that the argument bector is UTF-8. */
+#define RTR3INIT_FLAGS_UTF8_ARGV    RT_BIT(3)
+/** Indicates that this is a standalone application without any additional
+ * shared libraries in the application directory. Mainly windows loader mess. */
+#define RTR3INIT_FLAGS_STANDALONE_APP RT_BIT(4)
+/** @} */
+
+/** @name RTR3InitEx version
+ * @{ */
+/** Version 1. */
+#define RTR3INIT_VER_1              UINT32_C(1)
+/** The current version. */
+#define RTR3INIT_VER_CUR            RTR3INIT_VER_1
+/** @} */
+
+/**
+ * Initializes the runtime library.
+ *
+ * @returns iprt status code.
+ * @param   fFlags          Flags, see RTR3INIT_XXX.
+ */
+RTR3DECL(int) RTR3InitExeNoArguments(uint32_t fFlags);
+
+/**
+ * Initializes the runtime library.
+ *
+ * @returns iprt status code.
+ * @param   cArgs           Pointer to the argument count.
+ * @param   ppapszArgs      Pointer to the argument vector pointer.
+ * @param   fFlags          Flags, see RTR3INIT_XXX.
+ */
+RTR3DECL(int) RTR3InitExe(int cArgs, char ***ppapszArgs, uint32_t fFlags);
+
+/**
+ * Initializes the runtime library.
+ *
+ * @returns iprt status code.
+ * @param   fFlags          Flags, see RTR3INIT_XXX.
+ */
+RTR3DECL(int) RTR3InitDll(uint32_t fFlags);
+
+/**
+ * Initializes the runtime library and possibly also SUPLib too.
+ *
+ * Avoid this interface, it's not considered stable.
+ *
+ * @returns IPRT status code.
+ * @param   iVersion        The interface version. Must be 0 atm.
+ * @param   fFlags          Flags, see RTR3INIT_XXX.
+ * @param   cArgs           Pointer to the argument count.
+ * @param   ppapszArgs      Pointer to the argument vector pointer. NULL
+ *                          allowed if @a cArgs is 0.
+ * @param   pszProgramPath  The program path.  Pass NULL if we're to figure it
+ *                          out ourselves.
+ */
+RTR3DECL(int) RTR3InitEx(uint32_t iVersion, uint32_t fFlags, int cArgs, char ***ppapszArgs, const char *pszProgramPath);
+
+/**
+ * Terminates the runtime library.
+ */
+RTR3DECL(void) RTR3Term(void);
+
+/**
+ * Is IPRT succesfully initialized?
+ *
+ * @returns true/false.
+ */
+RTR3DECL(bool) RTR3InitIsInitialized(void);
+
+/**
+ * Are we running in unobtrusive mode?
+ * @returns true/false.
+ */
+RTR3DECL(bool) RTR3InitIsUnobtrusive(void);
+#endif /* IN_RING3 */
+
+
+#ifdef IN_RING0
+/**
+ * Initializes the ring-0 driver runtime library.
+ *
+ * @returns iprt status code.
+ * @param   fReserved       Flags reserved for the future.
+ */
+RTR0DECL(int) RTR0Init(unsigned fReserved);
+
+/**
+ * Terminates the ring-0 driver runtime library.
+ */
+RTR0DECL(void) RTR0Term(void);
+
+/**
+ * Forcibily terminates the ring-0 driver runtime library.
+ *
+ * This should be used when statically linking the IPRT.  Module using dynamic
+ * linking shall use RTR0Term.  If you're not sure, use RTR0Term!
+ */
+RTR0DECL(void) RTR0TermForced(void);
+#endif
+
+#ifdef IN_RC
+/**
+ * Initializes the raw-mode context runtime library.
+ *
+ * @returns iprt status code.
+ *
+ * @param   u64ProgramStartNanoTS  The startup timestamp.
+ */
+RTRCDECL(int) RTRCInit(uint64_t u64ProgramStartNanoTS);
+
+/**
+ * Terminates the raw-mode context runtime library.
+ */
+RTRCDECL(void) RTRCTerm(void);
+#endif
+
+
+/**
+ * Termination reason.
+ */
+typedef enum RTTERMREASON
+{
+    /** Normal exit. iStatus contains the exit code. */
+    RTTERMREASON_EXIT = 1,
+    /** Any abnormal exit. iStatus is 0 and has no meaning. */
+    RTTERMREASON_ABEND,
+    /** Killed by a signal. The iStatus contains the signal number. */
+    RTTERMREASON_SIGNAL,
+    /** The IPRT module is being unloaded. iStatus is 0 and has no meaning. */
+    RTTERMREASON_UNLOAD
+} RTTERMREASON;
+
+/** Whether lazy clean up is Okay or not.
+ * When the process is exiting, it is a waste of time to for instance free heap
+ * memory or close open files. OTOH, when the runtime is unloaded from the
+ * process, it is important to release absolutely all resources to prevent
+ * resource leaks. */
+#define RTTERMREASON_IS_LAZY_CLEANUP_OK(enmReason)  ((enmReason) != RTTERMREASON_UNLOAD)
+
+
+/**
+ * IPRT termination callback function.
+ *
+ * @param   enmReason           The cause of the termination.
+ * @param   iStatus             The meaning of this depends on enmReason.
+ * @param   pvUser              User argument passed to RTTermRegisterCallback.
+ */
+typedef DECLCALLBACK(void) FNRTTERMCALLBACK(RTTERMREASON enmReason, int32_t iStatus, void *pvUser);
+/** Pointer to an IPRT termination callback function. */
+typedef FNRTTERMCALLBACK *PFNRTTERMCALLBACK;
+
+
+/**
+ * Registers a termination callback.
+ *
+ * This is intended for performing clean up during IPRT termination. Frequently
+ * paired with lazy initialization thru RTOnce.
+ *
+ * The callbacks are called in LIFO order.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   pfnCallback         The callback function.
+ * @param   pvUser              The user argument for the callback.
+ *
+ * @remarks May need to acquire a fast mutex or critical section, so use with
+ *          some care in ring-0 context.
+ *
+ * @remarks Be very careful using this from code that may be unloaded before
+ *          IPRT terminates. Unlike some atexit and on_exit implementations,
+ *          IPRT will not automatically unregister callbacks when a module gets
+ *          unloaded.
+ */
+RTDECL(int) RTTermRegisterCallback(PFNRTTERMCALLBACK pfnCallback, void *pvUser);
+
+/**
+ * Deregister a termination callback.
+ *
+ * @returns VINF_SUCCESS if found, VERR_NOT_FOUND if the callback/pvUser pair
+ *          wasn't found.
+ *
+ * @param   pfnCallback         The callback function.
+ * @param   pvUser              The user argument for the callback.
+ */
+RTDECL(int) RTTermDeregisterCallback(PFNRTTERMCALLBACK pfnCallback, void *pvUser);
+
+/**
+ * Runs the termination callback queue.
+ *
+ * Normally called by an internal IPRT termination function, but may also be
+ * called by external code immediately prior to terminating IPRT if it is in a
+ * better position to state the termination reason and/or status.
+ *
+ * @param   enmReason           The reason why it's called.
+ * @param   iStatus             The associated exit status or signal number.
+ */
+RTDECL(void) RTTermRunCallbacks(RTTERMREASON enmReason, int32_t iStatus);
+
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/latin1.h b/ubuntu/vbox/include/iprt/latin1.h
new file mode 100644 (file)
index 0000000..6a851f2
--- /dev/null
@@ -0,0 +1,392 @@
+/** @file
+ * IPRT - String Manipulation, Latin-1 (ISO-8859-1) encoding.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_latin1_h
+#define ___iprt_latin1_h
+
+#include <iprt/string.h>
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup rt_str_latin1     Latin-1 (ISO-8859-1) String Manipulation
+ * @ingroup grp_rt_str
+ *
+ * Deals with Latin-1 encoded strings.
+ *
+ * @warning Make sure to name all variables dealing with Latin-1 strings
+ *          suchthat there is no way to mistake them for normal UTF-8 strings.
+ *          There may be severe security issues resulting from mistaking Latin-1
+ *          for UTF-8!
+ *
+ * @{
+ */
+
+/**
+ * Get the unicode code point at the given string position.
+ *
+ * @returns unicode code point.
+ * @returns RTUNICP_INVALID if the encoding is invalid.
+ * @param   pszLatin1   The Latin-1 string.
+ */
+DECLINLINE(RTUNICP) RTLatin1GetCp(const char *pszLatin1)
+{
+    return *(const unsigned char *)pszLatin1;
+}
+
+/**
+ * Get the unicode code point at the given string position.
+ *
+ * @returns iprt status code.
+ * @param   ppszLatin1  Pointer to the string pointer. This will be updated to
+ *                      point to the char following the current code point. This
+ *                      is advanced one character forward on failure.
+ * @param   pCp         Where to store the code point. RTUNICP_INVALID is stored
+ *                      here on failure.
+ */
+DECLINLINE(int) RTLatin1GetCpEx(const char **ppszLatin1, PRTUNICP pCp)
+{
+    const unsigned char uch = **(const unsigned char **)ppszLatin1;
+    (*ppszLatin1)++;
+    *pCp = uch;
+    return VINF_SUCCESS;
+}
+
+/**
+ * Get the unicode code point at the given string position for a string of a
+ * given maximum length.
+ *
+ * @returns iprt status code.
+ * @retval  VERR_END_OF_STRING if *pcch is 0. *pCp is set to RTUNICP_INVALID.
+ *
+ * @param   ppszLatin1  Pointer to the string pointer. This will be updated to
+ *                      point to the char following the current code point.
+ * @param   pcchLatin1  Pointer to the maximum string length.  This will be
+ *                      decremented by the size of the code point found.
+ * @param   pCp         Where to store the code point.
+ *                      RTUNICP_INVALID is stored here on failure.
+ */
+DECLINLINE(int) RTLatin1GetCpNEx(const char **ppszLatin1, size_t *pcchLatin1, PRTUNICP pCp)
+{
+    if (RT_LIKELY(*pcchLatin1 != 0))
+    {
+        const unsigned char uch = **(const unsigned char **)ppszLatin1;
+        (*ppszLatin1)++;
+        (*pcchLatin1)--;
+        *pCp = uch;
+        return VINF_SUCCESS;
+    }
+    *pCp = RTUNICP_INVALID;
+    return VERR_END_OF_STRING;
+}
+
+/**
+ * Get the Latin-1 size in characters of a given Unicode code point.
+ *
+ * The code point is expected to be a valid Unicode one, but not necessarily in
+ * the range supported by Latin-1.
+ *
+ * @returns the size in characters, or zero if there is no Latin-1 encoding
+ */
+DECLINLINE(size_t) RTLatin1CpSize(RTUNICP CodePoint)
+{
+    if (CodePoint < 0x100)
+        return 1;
+    return 0;
+}
+
+/**
+ * Put the unicode code point at the given string position
+ * and return the pointer to the char following it.
+ *
+ * This function will not consider anything at or following the
+ * buffer area pointed to by psz. It is therefore not suitable for
+ * inserting code points into a string, only appending/overwriting.
+ *
+ * @returns pointer to the char following the written code point.
+ * @param   pszLatin1   The string.
+ * @param   CodePoint   The code point to write.
+ *                      This should not be RTUNICP_INVALID or any other
+ *                      character out of the Latin-1 range.
+ */
+DECLINLINE(char *) RTLatin1PutCp(char *pszLatin1, RTUNICP CodePoint)
+{
+    AssertReturn(CodePoint < 0x100, NULL);
+    *pszLatin1++ = (unsigned char)CodePoint;
+    return pszLatin1;
+}
+
+/**
+ * Skips ahead, past the current code point.
+ *
+ * @returns Pointer to the char after the current code point.
+ * @param   pszLatin1   Pointer to the current code point.
+ * @remark  This will not move the next valid code point, only past the current one.
+ */
+DECLINLINE(char *) RTLatin1NextCp(const char *pszLatin1)
+{
+    pszLatin1++;
+    return (char *)pszLatin1;
+}
+
+/**
+ * Skips back to the previous code point.
+ *
+ * @returns Pointer to the char before the current code point.
+ * @returns pszLatin1Start on failure.
+ * @param   pszLatin1Start  Pointer to the start of the string.
+ * @param   pszLatin1       Pointer to the current code point.
+ */
+DECLINLINE(char *) RTLatin1PrevCp(const char *pszLatin1Start, const char *pszLatin1)
+{
+    if ((uintptr_t)pszLatin1 > (uintptr_t)pszLatin1Start)
+    {
+        pszLatin1--;
+        return (char *)pszLatin1;
+    }
+    return (char *)pszLatin1Start;
+}
+
+/**
+ * Translate a Latin1 string into a UTF-8 allocating the result buffer (default
+ * tag).
+ *
+ * @returns iprt status code.
+ * @param   pszLatin1       Latin1 string to convert.
+ * @param   ppszString      Receives pointer of allocated UTF-8 string on
+ *                          success, and is always set to NULL on failure.
+ *                          The returned pointer must be freed using RTStrFree().
+ */
+#define RTLatin1ToUtf8(pszLatin1, ppszString)       RTLatin1ToUtf8Tag((pszLatin1), (ppszString), RTSTR_TAG)
+
+/**
+ * Translate a Latin-1 string into a UTF-8 allocating the result buffer.
+ *
+ * @returns iprt status code.
+ * @param   pszLatin1       Latin-1 string to convert.
+ * @param   ppszString      Receives pointer of allocated UTF-8 string on
+ *                          success, and is always set to NULL on failure.
+ *                          The returned pointer must be freed using RTStrFree().
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTDECL(int)  RTLatin1ToUtf8Tag(const char *pszLatin1, char **ppszString, const char *pszTag);
+
+/**
+ * Translates Latin-1 to UTF-8 using buffer provided by the caller or a fittingly
+ * sized buffer allocated by the function (default tag).
+ *
+ * @returns iprt status code.
+ * @param   pszLatin1       The Latin-1 string to convert.
+ * @param   cchLatin1       The number of Latin-1 characters to translate from
+ *                          pszLatin1. The translation will stop when reaching
+ *                          cchLatin1 or the terminator ('\\0').  Use RTSTR_MAX
+ *                          to translate the entire string.
+ * @param   ppsz            If @a cch is non-zero, this must either be pointing
+ *                          to a pointer to a buffer of the specified size, or
+ *                          pointer to a NULL pointer.  If *ppsz is NULL or
+ *                          @a cch is zero a buffer of at least @a cch chars
+ *                          will be allocated to hold the translated string. If
+ *                          a buffer was requested it must be freed using
+ *                          RTStrFree().
+ * @param   cch             The buffer size in chars (the type). This includes the terminator.
+ * @param   pcch            Where to store the length of the translated string,
+ *                          excluding the terminator. (Optional)
+ *
+ *                          This may be set under some error conditions,
+ *                          however, only for VERR_BUFFER_OVERFLOW and
+ *                          VERR_NO_STR_MEMORY will it contain a valid string
+ *                          length that can be used to resize the buffer.
+ */
+#define RTLatin1ToUtf8Ex(pszLatin1, cchLatin1, ppsz, cch, pcch) \
+    RTLatin1ToUtf8ExTag((pszLatin1), (cchLatin1), (ppsz), (cch), (pcch), RTSTR_TAG)
+
+/**
+ * Translates Latin1 to UTF-8 using buffer provided by the caller or a fittingly
+ * sized buffer allocated by the function (custom tag).
+ *
+ * @returns iprt status code.
+ * @param   pszLatin1       The Latin1 string to convert.
+ * @param   cchLatin1       The number of Latin1 characters to translate from
+ *                          pwszString.  The translation will stop when
+ *                          reaching cchLatin1 or the terminator ('\\0').  Use
+ *                          RTSTR_MAX to translate the entire string.
+ * @param   ppsz            If cch is non-zero, this must either be pointing to
+ *                          a pointer to a buffer of the specified size, or
+ *                          pointer to a NULL pointer.  If *ppsz is NULL or cch
+ *                          is zero a buffer of at least cch chars will be
+ *                          allocated to hold the translated string.  If a
+ *                          buffer was requested it must be freed using
+ *                          RTStrFree().
+ * @param   cch             The buffer size in chars (the type).  This includes
+ *                          the terminator.
+ * @param   pcch            Where to store the length of the translated string,
+ *                          excluding the terminator. (Optional)
+ *
+ *                          This may be set under some error conditions,
+ *                          however, only for VERR_BUFFER_OVERFLOW and
+ *                          VERR_NO_STR_MEMORY will it contain a valid string
+ *                          length that can be used to resize the buffer.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTDECL(int)  RTLatin1ToUtf8ExTag(const char *pszLatin1, size_t cchLatin1, char **ppsz, size_t cch, size_t *pcch,
+                                 const char *pszTag);
+
+/**
+ * Calculates the length of the Latin-1 string in UTF-8 chars (bytes).
+ *
+ * The primary purpose of this function is to help allocate buffers for
+ * RTLatin1ToUtf8() of the correct size. For most other purposes
+ * RTLatin1ToUtf8Ex() should be used.
+ *
+ * @returns Number of chars (bytes).
+ * @returns 0 if the string was incorrectly encoded.
+ * @param   pszLatin1     The Latin-1 string.
+ */
+RTDECL(size_t) RTLatin1CalcUtf8Len(const char *pszLatin1);
+
+/**
+ * Calculates the length of the Latin-1 string in UTF-8 chars (bytes).
+ *
+ * @returns iprt status code.
+ * @param   pszLatin1   The Latin-1 string.
+ * @param   cchLatin1   The max string length. Use RTSTR_MAX to process the
+ *                      entire string.
+ * @param   pcch        Where to store the string length (in bytes).  Optional.
+ *                      This is undefined on failure.
+ */
+RTDECL(int) RTLatin1CalcUtf8LenEx(const char *pszLatin1, size_t cchLatin1, size_t *pcch);
+
+/**
+ * Calculates the length of the Latin-1 (ISO-8859-1) string in RTUTF16 items.
+ *
+ * @returns Number of RTUTF16 items.
+ * @param   pszLatin1       The Latin-1 string.
+ */
+RTDECL(size_t) RTLatin1CalcUtf16Len(const char *pszLatin1);
+
+/**
+ * Calculates the length of the Latin-1 (ISO-8859-1) string in RTUTF16 items.
+ *
+ * @returns iprt status code.
+ * @param   pszLatin1       The Latin-1 string.
+ * @param   cchLatin1       The max string length. Use RTSTR_MAX to process the
+ *                          entire string.
+ * @param   pcwc            Where to store the string length. Optional.
+ *                          This is undefined on failure.
+ */
+RTDECL(int) RTLatin1CalcUtf16LenEx(const char *pszLatin1, size_t cchLatin1, size_t *pcwc);
+
+/**
+ * Translate a Latin-1 (ISO-8859-1) string into a UTF-16 allocating the result
+ * buffer (default tag).
+ *
+ * @returns iprt status code.
+ * @param   pszLatin1       The Latin-1 string to convert.
+ * @param   ppwszString     Receives pointer to the allocated UTF-16 string. The
+ *                          returned string must be freed using RTUtf16Free().
+ */
+#define RTLatin1ToUtf16(pszLatin1, ppwszString)     RTLatin1ToUtf16Tag((pszLatin1), (ppwszString), RTSTR_TAG)
+
+/**
+ * Translate a Latin-1 (ISO-8859-1) string into a UTF-16 allocating the result
+ * buffer (custom tag).
+ *
+ * @returns iprt status code.
+ * @param   pszLatin1       The Latin-1 string to convert.
+ * @param   ppwszString     Receives pointer to the allocated UTF-16 string. The
+ *                          returned string must be freed using RTUtf16Free().
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTLatin1ToUtf16Tag(const char *pszLatin1, PRTUTF16 *ppwszString, const char *pszTag);
+
+/**
+ * Translates pszLatin1 from Latin-1 (ISO-8859-1) to UTF-16, allocating the
+ * result buffer if requested (default tag).
+ *
+ * @returns iprt status code.
+ * @param   pszLatin1       The Latin-1 string to convert.
+ * @param   cchLatin1       The maximum size in chars (the type) to convert. The
+ *                          conversion stops when it reaches cchLatin1 or the
+ *                          string terminator ('\\0'). Use RTSTR_MAX to
+ *                          translate the entire string.
+ * @param   ppwsz           If cwc is non-zero, this must either be pointing
+ *                          to pointer to a buffer of the specified size, or
+ *                          pointer to a NULL pointer.
+ *                          If *ppwsz is NULL or cwc is zero a buffer of at
+ *                          least cwc items will be allocated to hold the
+ *                          translated string. If a buffer was requested it
+ *                          must be freed using RTUtf16Free().
+ * @param   cwc             The buffer size in RTUTF16s. This includes the
+ *                          terminator.
+ * @param   pcwc            Where to store the length of the translated string,
+ *                          excluding the terminator. (Optional)
+ *
+ *                          This may be set under some error conditions,
+ *                          however, only for VERR_BUFFER_OVERFLOW and
+ *                          VERR_NO_STR_MEMORY will it contain a valid string
+ *                          length that can be used to resize the buffer.
+ */
+#define RTLatin1ToUtf16Ex(pszLatin1, cchLatin1, ppwsz, cwc, pcwc) \
+    RTLatin1ToUtf16ExTag((pszLatin1), (cchLatin1), (ppwsz), (cwc), (pcwc), RTSTR_TAG)
+
+/**
+ * Translates pszLatin1 from Latin-1 (ISO-8859-1) to UTF-16, allocating the
+ * result buffer if requested.
+ *
+ * @returns iprt status code.
+ * @param   pszLatin1       The Latin-1 string to convert.
+ * @param   cchLatin1       The maximum size in chars (the type) to convert. The
+ *                          conversion stops when it reaches cchLatin1 or the
+ *                          string terminator ('\\0'). Use RTSTR_MAX to
+ *                          translate the entire string.
+ * @param   ppwsz           If cwc is non-zero, this must either be pointing
+ *                          to pointer to a buffer of the specified size, or
+ *                          pointer to a NULL pointer.
+ *                          If *ppwsz is NULL or cwc is zero a buffer of at
+ *                          least cwc items will be allocated to hold the
+ *                          translated string. If a buffer was requested it
+ *                          must be freed using RTUtf16Free().
+ * @param   cwc             The buffer size in RTUTF16s. This includes the
+ *                          terminator.
+ * @param   pcwc            Where to store the length of the translated string,
+ *                          excluding the terminator. (Optional)
+ *
+ *                          This may be set under some error conditions,
+ *                          however, only for VERR_BUFFER_OVERFLOW and
+ *                          VERR_NO_STR_MEMORY will it contain a valid string
+ *                          length that can be used to resize the buffer.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTLatin1ToUtf16ExTag(const char *pszLatin1, size_t cchLatin1,
+                                 PRTUTF16 *ppwsz, size_t cwc, size_t *pcwc, const char *pszTag);
+
+/** @} */
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/list.h b/ubuntu/vbox/include/iprt/list.h
new file mode 100644 (file)
index 0000000..7f38e10
--- /dev/null
@@ -0,0 +1,534 @@
+/** @file
+ * IPRT - Generic Doubly Linked List.
+ */
+
+/*
+ * Copyright (C) 2010-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.
+ */
+
+#ifndef ___iprt_list_h
+#define ___iprt_list_h
+
+#include <iprt/types.h>
+
+/** @defgroup grp_rt_list    RTList - Generic Doubly Linked List
+ * @ingroup grp_rt
+ *
+ * The list implementation is circular without any type wise distintion between
+ * the list and its nodes.  This can be confusing since the list head usually
+ * resides in a different structure than the nodes, so care must be taken when
+ * walking the list.
+ *
+ * @{
+ */
+
+RT_C_DECLS_BEGIN
+
+/**
+ * A list node of a doubly linked list.
+ */
+typedef struct RTLISTNODE
+{
+    /** Pointer to the next list node. */
+    struct RTLISTNODE *pNext;
+    /** Pointer to the previous list node. */
+    struct RTLISTNODE *pPrev;
+} RTLISTNODE;
+/** Pointer to a list node. */
+typedef RTLISTNODE *PRTLISTNODE;
+/** Pointer to a const list node. */
+typedef RTLISTNODE const *PCRTLISTNODE;
+/** Pointer to a list node pointer. */
+typedef PRTLISTNODE *PPRTLISTNODE;
+
+/** The anchor (head/tail) of a doubly linked list.
+ *
+ * @remarks Please use this instead of RTLISTNODE to indicate a list
+ *          head/tail.  It makes the code so much easier to read.  Also,
+ *          always mention the actual list node type(s) in the comment.  */
+typedef RTLISTNODE RTLISTANCHOR;
+/** Pointer to a doubly linked list anchor. */
+typedef RTLISTANCHOR *PRTLISTANCHOR;
+/** Pointer to a const doubly linked list anchor. */
+typedef RTLISTANCHOR const *PCRTLISTANCHOR;
+
+/** Version of RTLISTNODE for holding a ring-3 only list in data which gets
+ * shared between multiple contexts */
+#if defined(IN_RING3)
+typedef RTLISTNODE RTLISTNODER3;
+#else
+typedef struct { RTR3PTR aOffLimits[2]; } RTLISTNODER3;
+#endif
+/** Version of RTLISTANCHOR for holding a ring-3 only list in data which gets
+ * shared between multiple contexts */
+typedef RTLISTNODER3 RTLISTANCHORR3;
+
+
+/**
+ * Initialize a list.
+ *
+ * @param   pList               Pointer to an unitialised list.
+ */
+DECLINLINE(void) RTListInit(PRTLISTNODE pList)
+{
+    pList->pNext = pList;
+    pList->pPrev = pList;
+}
+
+/**
+ * Append a node to the end of the list.
+ *
+ * @param   pList               The list to append the node to.
+ * @param   pNode               The node to append.
+ */
+DECLINLINE(void) RTListAppend(PRTLISTNODE pList, PRTLISTNODE pNode)
+{
+    pList->pPrev->pNext = pNode;
+    pNode->pPrev        = pList->pPrev;
+    pNode->pNext        = pList;
+    pList->pPrev        = pNode;
+}
+
+/**
+ * Add a node as the first element of the list.
+ *
+ * @param   pList               The list to prepend the node to.
+ * @param   pNode               The node to prepend.
+ */
+DECLINLINE(void) RTListPrepend(PRTLISTNODE pList, PRTLISTNODE pNode)
+{
+    pList->pNext->pPrev = pNode;
+    pNode->pNext        = pList->pNext;
+    pNode->pPrev        = pList;
+    pList->pNext        = pNode;
+}
+
+/**
+ * Inserts a node after the specified one.
+ *
+ * @param   pCurNode            The current node.
+ * @param   pNewNode            The node to insert.
+ */
+DECLINLINE(void) RTListNodeInsertAfter(PRTLISTNODE pCurNode, PRTLISTNODE pNewNode)
+{
+    RTListPrepend(pCurNode, pNewNode);
+}
+
+/**
+ * Inserts a node before the specified one.
+ *
+ * @param   pCurNode            The current node.
+ * @param   pNewNode            The node to insert.
+ */
+DECLINLINE(void) RTListNodeInsertBefore(PRTLISTNODE pCurNode, PRTLISTNODE pNewNode)
+{
+    RTListAppend(pCurNode, pNewNode);
+}
+
+/**
+ * Remove a node from a list.
+ *
+ * @param   pNode               The node to remove.
+ */
+DECLINLINE(void) RTListNodeRemove(PRTLISTNODE pNode)
+{
+    PRTLISTNODE pPrev = pNode->pPrev;
+    PRTLISTNODE pNext = pNode->pNext;
+
+    pPrev->pNext = pNext;
+    pNext->pPrev = pPrev;
+
+    /* poison */
+    pNode->pNext = NULL;
+    pNode->pPrev = NULL;
+}
+
+
+/**
+ * Remove a node from a list, returns value.
+ *
+ * @returns pNode
+ * @param   pNode               The node to remove.
+ */
+DECLINLINE(PRTLISTNODE) RTListNodeRemoveRet(PRTLISTNODE pNode)
+{
+    PRTLISTNODE pPrev = pNode->pPrev;
+    PRTLISTNODE pNext = pNode->pNext;
+
+    pPrev->pNext = pNext;
+    pNext->pPrev = pPrev;
+
+    /* poison */
+    pNode->pNext = NULL;
+    pNode->pPrev = NULL;
+
+    return pNode;
+}
+
+/**
+ * Checks if a node is the last element in the list.
+ *
+ * @retval  true if the node is the last element in the list.
+ * @retval  false otherwise
+ *
+ * @param   pList               The list.
+ * @param   pNode               The node to check.
+ */
+#define RTListNodeIsLast(pList, pNode)  ((pNode)->pNext == (pList))
+
+/**
+ * Checks if a node is the first element in the list.
+ *
+ * @retval  true if the node is the first element in the list.
+ * @retval  false otherwise.
+ *
+ * @param   pList               The list.
+ * @param   pNode               The node to check.
+ */
+#define RTListNodeIsFirst(pList, pNode) ((pNode)->pPrev == (pList))
+
+/**
+ * Checks if a type converted node is actually the dummy element (@a pList).
+ *
+ * @retval  true if the node is the dummy element in the list.
+ * @retval  false otherwise.
+ *
+ * @param   pList               The list.
+ * @param   pNode               The node structure to check.  Typically
+ *                              something obtained from RTListNodeGetNext() or
+ *                              RTListNodeGetPrev().  This is NOT a PRTLISTNODE
+ *                              but something that contains a RTLISTNODE member!
+ * @param   Type                Structure the list node is a member of.
+ * @param   Member              The list node member.
+ */
+#define RTListNodeIsDummy(pList, pNode, Type, Member) \
+         ( (pNode) == RT_FROM_MEMBER((pList), Type, Member) )
+/** @copydoc RTListNodeIsDummy */
+#define RTListNodeIsDummyCpp(pList, pNode, Type, Member) \
+         ( (pNode) == RT_FROM_CPP_MEMBER((pList), Type, Member) )
+
+/**
+ * Checks if a list is empty.
+ *
+ * @retval  true if the list is empty.
+ * @retval  false otherwise.
+ *
+ * @param   pList               The list to check.
+ */
+#define RTListIsEmpty(pList)            ((pList)->pPrev == (pList))
+
+/**
+ * Returns the next node in the list.
+ *
+ * @returns The next node.
+ *
+ * @param   pCurNode            The current node.
+ * @param   Type                Structure the list node is a member of.
+ * @param   Member              The list node member.
+ */
+#define RTListNodeGetNext(pCurNode, Type, Member) \
+    RT_FROM_MEMBER((pCurNode)->pNext, Type, Member)
+/** @copydoc RTListNodeGetNext */
+#define RTListNodeGetNextCpp(pCurNode, Type, Member) \
+    RT_FROM_CPP_MEMBER((pCurNode)->pNext, Type, Member)
+
+/**
+ * Returns the previous node in the list.
+ *
+ * @returns The previous node.
+ *
+ * @param   pCurNode            The current node.
+ * @param   Type                Structure the list node is a member of.
+ * @param   Member              The list node member.
+ */
+#define RTListNodeGetPrev(pCurNode, Type, Member) \
+    RT_FROM_MEMBER((pCurNode)->pPrev, Type, Member)
+/** @copydoc RTListNodeGetPrev */
+#define RTListNodeGetPrevCpp(pCurNode, Type, Member) \
+    RT_FROM_CPP_MEMBER((pCurNode)->pPrev, Type, Member)
+
+/**
+ * Returns the first element in the list (checks for empty list).
+ *
+ * @returns Pointer to the first list element, or NULL if empty list.
+ *
+ * @param   pList               List to get the first element from.
+ * @param   Type                Structure the list node is a member of.
+ * @param   Member              The list node member.
+ */
+#define RTListGetFirst(pList, Type, Member) \
+    (!RTListIsEmpty(pList) ? RTListNodeGetNext(pList, Type, Member) : NULL)
+/** @copydoc RTListGetFirst */
+#define RTListGetFirstCpp(pList, Type, Member) \
+    (!RTListIsEmpty(pList) ? RTListNodeGetNextCpp(pList, Type, Member) : NULL)
+
+/**
+ * Returns the last element in the list (checks for empty list).
+ *
+ * @returns Pointer to the last list element, or NULL if empty list.
+ *
+ * @param   pList               List to get the last element from.
+ * @param   Type                Structure the list node is a member of.
+ * @param   Member              The list node member.
+ */
+#define RTListGetLast(pList, Type, Member) \
+    (!RTListIsEmpty(pList) ? RTListNodeGetPrev(pList, Type, Member) : NULL)
+/** @copydoc RTListGetLast */
+#define RTListGetLastCpp(pList, Type, Member) \
+    (!RTListIsEmpty(pList) ? RTListNodeGetPrevCpp(pList, Type, Member) : NULL)
+
+/**
+ * Returns the next node in the list or NULL if the end has been reached.
+ *
+ * @returns The next node, or NULL if end of list.
+ *
+ * @param   pList               The list @a pCurNode is linked on.
+ * @param   pCurNode            The current node, of type @a Type.
+ * @param   Type                Structure the list node is a member of.
+ * @param   Member              The list node member.
+ */
+#define RTListGetNext(pList, pCurNode, Type, Member) \
+    ( (pCurNode)->Member.pNext != (pList) ? RT_FROM_MEMBER((pCurNode)->Member.pNext, Type, Member) : NULL )
+/** @copydoc RTListGetNext */
+#define RTListGetNextCpp(pList, pCurNode, Type, Member) \
+    ( (pCurNode)->Member.pNext != (pList) ? RT_FROM_CPP_MEMBER((pCurNode)->Member.pNext, Type, Member) : NULL )
+
+/**
+ * Returns the previous node in the list or NULL if the start has been reached.
+ *
+ * @returns The previous node, or NULL if end of list.
+ *
+ * @param   pList               The list @a pCurNode is linked on.
+ * @param   pCurNode            The current node, of type @a Type.
+ * @param   Type                Structure the list node is a member of.
+ * @param   Member              The list node member.
+ */
+#define RTListGetPrev(pList, pCurNode, Type, Member) \
+    ( (pCurNode)->Member.pPrev != (pList) ? RT_FROM_MEMBER((pCurNode)->Member.pPrev, Type, Member) : NULL )
+/** @copydoc RTListGetPrev */
+#define RTListGetPrevCpp(pList, pCurNode, Type, Member) \
+    ( (pCurNode)->Member.pPrev != (pList) ? RT_FROM_CPP_MEMBER((pCurNode)->Member.pPrev, Type, Member) : NULL )
+
+
+/**
+ * Removes and returns the first element in the list (checks for empty list).
+ *
+ * @returns Pointer to the first list element, or NULL if empty list.
+ *
+ * @param   pList               List to get the first element from.
+ * @param   Type                Structure the list node is a member of.
+ * @param   Member              The list node member.
+ */
+#define RTListRemoveFirst(pList, Type, Member) \
+    (!RTListIsEmpty(pList) ? RT_FROM_MEMBER(RTListNodeRemoveRet((pList)->pNext), Type, Member) : NULL)
+/** @copydoc RTListRemoveFirst */
+#define RTListRemoveFirstCpp(pList, Type, Member) \
+    (!RTListIsEmpty(pList) ? RT_FROM_CPP_MEMBER(RTListNodeRemoveRet((pList)->pNext), Type, Member) : NULL)
+
+/**
+ * Removes and returns the last element in the list (checks for empty list).
+ *
+ * @returns Pointer to the last list element, or NULL if empty list.
+ *
+ * @param   pList               List to get the last element from.
+ * @param   Type                Structure the list node is a member of.
+ * @param   Member              The list node member.
+ */
+#define RTListRemoveLast(pList, Type, Member) \
+    (!RTListIsEmpty(pList) ? RT_FROM_MEMBER(RTListNodeRemoveRet((pList)->pPrev), Type, Member) : NULL)
+/** @copydoc RTListRemoveLast */
+#define RTListRemoveLastCpp(pList, Type, Member) \
+    (!RTListIsEmpty(pList) ? RT_FROM_CPP_MEMBER(RTListNodeRemoveRet((pList)->pPrev), Type, Member) : NULL)
+
+/**
+ * Removes and returns the next node in the list or NULL if the end has been
+ * reached.
+ *
+ * @returns The next node, or NULL if end of list.
+ *
+ * @param   pList               The list @a pCurNode is linked on.
+ * @param   pCurNode            The current node, of type @a Type.
+ * @param   Type                Structure the list node is a member of.
+ * @param   Member              The list node member.
+ */
+#define RTListRemoveNext(pList, pCurNode, Type, Member) \
+    ( (pCurNode)->Member.pNext != (pList) ? RT_FROM_MEMBER(RTListNodeRemoveRet((pCurNode)->Member.pNext), Type, Member) : NULL )
+/** @copydoc RTListRemoveNext */
+#define RTListRemoveNextCpp(pList, pCurNode, Type, Member) \
+    ( (pCurNode)->Member.pNext != (pList) ? RT_FROM_CPP_MEMBER(RTListNodeRemoveRet((pCurNode)->Member.pNext), Type, Member) : NULL )
+
+/**
+ * Removes and returns the previous node in the list or NULL if the start has
+ * been reached.
+ *
+ * @returns The previous node, or NULL if end of list.
+ *
+ * @param   pList               The list @a pCurNode is linked on.
+ * @param   pCurNode            The current node, of type @a Type.
+ * @param   Type                Structure the list node is a member of.
+ * @param   Member              The list node member.
+ */
+#define RTListRemovePrev(pList, pCurNode, Type, Member) \
+    ( (pCurNode)->Member.pNext != (pList) ? RT_FROM_MEMBER(RTListNodeRemoveRet((pCurNode)->Member.pPrev), Type, Member) : NULL )
+/** @copydoc RTListRemovePrev */
+#define RTListRemovePrevCpp(pList, pCurNode, Type, Member) \
+    ( (pCurNode)->Member.pNext != (pList) ? RT_FROM_CPP_MEMBER(RTListNodeRemoveRet((pCurNode)->Member.pPrev), Type, Member) : NULL )
+
+
+/**
+ * Enumerate the list in head to tail order.
+ *
+ * @param   pList               List to enumerate.
+ * @param   pIterator           The iterator variable name.
+ * @param   Type                Structure the list node is a member of.
+ * @param   Member              The list node member name.
+ */
+#define RTListForEach(pList, pIterator, Type, Member) \
+    for (pIterator = RTListNodeGetNext(pList, Type, Member); \
+         !RTListNodeIsDummy(pList, pIterator, Type, Member); \
+         pIterator = RT_FROM_MEMBER((pIterator)->Member.pNext, Type, Member) )
+/** @copydoc RTListForEach */
+#define RTListForEachCpp(pList, pIterator, Type, Member) \
+    for (pIterator = RTListNodeGetNextCpp(pList, Type, Member); \
+         !RTListNodeIsDummyCpp(pList, pIterator, Type, Member); \
+         pIterator = RT_FROM_CPP_MEMBER((pIterator)->Member.pNext, Type, Member) )
+
+
+/**
+ * Enumerate the list in head to tail order, safe against removal of the
+ * current node.
+ *
+ * @param   pList               List to enumerate.
+ * @param   pIterator           The iterator variable name.
+ * @param   pIterNext           The name of the variable saving the pointer to
+ *                              the next element.
+ * @param   Type                Structure the list node is a member of.
+ * @param   Member              The list node member name.
+ */
+#define RTListForEachSafe(pList, pIterator, pIterNext, Type, Member) \
+    for (pIterator = RTListNodeGetNext(pList, Type, Member), \
+         pIterNext = RT_FROM_MEMBER((pIterator)->Member.pNext, Type, Member); \
+         !RTListNodeIsDummy(pList, pIterator, Type, Member); \
+         pIterator = pIterNext, \
+         pIterNext = RT_FROM_MEMBER((pIterator)->Member.pNext, Type, Member) )
+/** @copydoc RTListForEachSafe */
+#define RTListForEachSafeCpp(pList, pIterator, pIterNext, Type, Member) \
+    for (pIterator = RTListNodeGetNextCpp(pList, Type, Member), \
+         pIterNext = RT_FROM_CPP_MEMBER((pIterator)->Member.pNext, Type, Member); \
+         !RTListNodeIsDummyCpp(pList, pIterator, Type, Member); \
+         pIterator = pIterNext, \
+         pIterNext = RT_FROM_CPP_MEMBER((pIterator)->Member.pNext, Type, Member) )
+
+
+/**
+ * Enumerate the list in reverse order (tail to head).
+ *
+ * @param   pList               List to enumerate.
+ * @param   pIterator           The iterator variable name.
+ * @param   Type                Structure the list node is a member of.
+ * @param   Member              The list node member name.
+ */
+#define RTListForEachReverse(pList, pIterator, Type, Member) \
+    for (pIterator = RTListNodeGetPrev(pList, Type, Member); \
+         !RTListNodeIsDummy(pList, pIterator, Type, Member); \
+         pIterator = RT_FROM_MEMBER((pIterator)->Member.pPrev, Type, Member) )
+/** @copydoc RTListForEachReverse */
+#define RTListForEachReverseCpp(pList, pIterator, Type, Member) \
+    for (pIterator = RTListNodeGetPrevCpp(pList, Type, Member); \
+         !RTListNodeIsDummyCpp(pList, pIterator, Type, Member); \
+         pIterator = RT_FROM_CPP_MEMBER((pIterator)->Member.pPrev, Type, Member) )
+
+
+/**
+ * Enumerate the list in reverse order (tail to head).
+ *
+ * @param   pList               List to enumerate.
+ * @param   pIterator           The iterator variable name.
+ * @param   pIterPrev           The name of the variable saving the pointer to
+ *                              the previous element.
+ * @param   Type                Structure the list node is a member of.
+ * @param   Member              The list node member name.
+ */
+#define RTListForEachReverseSafe(pList, pIterator, pIterPrev, Type, Member) \
+    for (pIterator = RTListNodeGetPrev(pList, Type, Member), \
+         pIterPrev = RT_FROM_MEMBER((pIterator)->Member.pPrev, Type, Member); \
+         !RTListNodeIsDummy(pList, pIterator, Type, Member); \
+         pIterator = pIterPrev, \
+         pIterPrev = RT_FROM_MEMBER((pIterator)->Member.pPrev, Type, Member) )
+/** @copydoc RTListForEachReverseSafe */
+#define RTListForEachReverseSafeCpp(pList, pIterator, pIterPrev, Type, Member) \
+    for (pIterator = RTListNodeGetPrevCpp(pList, Type, Member), \
+         pIterPrev = RT_FROM_CPP_MEMBER((pIterator)->Member.pPrev, Type, Member); \
+         !RTListNodeIsDummyCpp(pList, pIterator, Type, Member); \
+         pIterator = pIterPrev, \
+         pIterPrev = RT_FROM_CPP_MEMBER((pIterator)->Member.pPrev, Type, Member) )
+
+
+/**
+ * Move the given list to a new list header.
+ *
+ * @param   pListDst            The new list.
+ * @param   pListSrc            The list to move.
+ */
+DECLINLINE(void) RTListMove(PRTLISTNODE pListDst, PRTLISTNODE pListSrc)
+{
+    if (!RTListIsEmpty(pListSrc))
+    {
+        pListDst->pNext = pListSrc->pNext;
+        pListDst->pPrev = pListSrc->pPrev;
+
+        /* Adjust the first and last element links */
+        pListDst->pNext->pPrev = pListDst;
+        pListDst->pPrev->pNext = pListDst;
+
+        /* Finally remove the elements from the source list */
+        RTListInit(pListSrc);
+    }
+}
+
+/**
+ * List concatenation.
+ *
+ * @returns nothing.
+ * @param   pListDst            The destination list.
+ * @param   pListSrc            The source list to concatenate.
+ */
+DECLINLINE(void) RTListConcatenate(PRTLISTANCHOR pListDst, PRTLISTANCHOR pListSrc)
+{
+    if (!RTListIsEmpty(pListSrc))
+    {
+        PRTLISTNODE pFirst = pListSrc->pNext;
+        PRTLISTNODE pLast = pListSrc->pPrev;
+
+        pListDst->pPrev->pNext = pFirst;
+        pFirst->pPrev          = pListDst->pPrev;
+        pLast->pNext           = pListDst;
+        pListDst->pPrev        = pLast;
+
+        /* Finally remove the elements from the source list */
+        RTListInit(pListSrc);
+    }
+}
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif
diff --git a/ubuntu/vbox/include/iprt/lockvalidator.h b/ubuntu/vbox/include/iprt/lockvalidator.h
new file mode 100644 (file)
index 0000000..c11a9de
--- /dev/null
@@ -0,0 +1,1130 @@
+/** @file
+ * IPRT - Lock Validator.
+ */
+
+/*
+ * Copyright (C) 2009-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.
+ */
+
+#ifndef ___iprt_lockvalidator_h
+#define ___iprt_lockvalidator_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/assert.h>
+#include <iprt/thread.h>
+#include <iprt/stdarg.h>
+
+
+/** @defgroup grp_rtlockval     RTLockValidator - Lock Validator
+ * @ingroup grp_rt
+ * @{
+ */
+
+RT_C_DECLS_BEGIN
+
+/** Pointer to a record union.
+ * @internal  */
+typedef union RTLOCKVALRECUNION *PRTLOCKVALRECUNION;
+
+/**
+ * Source position.
+ */
+typedef struct RTLOCKVALSRCPOS
+{
+    /** The file where the lock was taken. */
+    R3R0PTRTYPE(const char * volatile)  pszFile;
+    /** The function where the lock was taken. */
+    R3R0PTRTYPE(const char * volatile)  pszFunction;
+    /** Some ID indicating where the lock was taken, typically an address. */
+    RTHCUINTPTR volatile                uId;
+    /** The line number in the file. */
+    uint32_t volatile                   uLine;
+#if HC_ARCH_BITS == 64
+    uint32_t                            u32Padding; /**< Alignment padding. */
+#endif
+} RTLOCKVALSRCPOS;
+AssertCompileSize(RTLOCKVALSRCPOS, HC_ARCH_BITS == 32 ? 16 : 32);
+/* The pointer types are defined in iprt/types.h. */
+
+/** @def RTLOCKVALSRCPOS_INIT
+ * Initializer for a RTLOCKVALSRCPOS variable.
+ *
+ * @param   pszFile         The file name.  Optional (NULL).
+ * @param   uLine           The line number in that file. Optional (0).
+ * @param   pszFunction     The function.  Optional (NULL).
+ * @param   uId             Some location ID, normally the return address.
+ *                          Optional (NULL).
+ */
+#if HC_ARCH_BITS == 64
+# define RTLOCKVALSRCPOS_INIT(pszFile, uLine, pszFunction, uId) \
+    { (pszFile), (pszFunction), (uId), (uLine), 0 }
+#else
+# define RTLOCKVALSRCPOS_INIT(pszFile, uLine, pszFunction, uId) \
+    { (pszFile), (pszFunction), (uId), (uLine) }
+#endif
+
+/** @def RTLOCKVALSRCPOS_INIT_DEBUG_API
+ * Initializer for a RTLOCKVALSRCPOS variable in a typicial debug API
+ * variant.  Assumes RT_SRC_POS_DECL and RTHCUINTPTR uId as arguments.
+ */
+#define RTLOCKVALSRCPOS_INIT_DEBUG_API()  \
+    RTLOCKVALSRCPOS_INIT(pszFile, iLine, pszFunction, uId)
+
+/** @def RTLOCKVALSRCPOS_INIT_NORMAL_API
+ * Initializer for a RTLOCKVALSRCPOS variable in a normal API
+ * variant.  Assumes iprt/asm.h is included.
+ */
+#define RTLOCKVALSRCPOS_INIT_NORMAL_API() \
+    RTLOCKVALSRCPOS_INIT(__FILE__, __LINE__, __PRETTY_FUNCTION__, (uintptr_t)ASMReturnAddress())
+
+/** @def RTLOCKVALSRCPOS_INIT_POS_NO_ID
+ * Initializer for a RTLOCKVALSRCPOS variable when no @c uId is present.
+ * Assumes iprt/asm.h is included.
+ */
+#define RTLOCKVALSRCPOS_INIT_POS_NO_ID() \
+    RTLOCKVALSRCPOS_INIT(pszFile, iLine, pszFunction, (uintptr_t)ASMReturnAddress())
+
+
+/**
+ * Lock validator record core.
+ */
+typedef struct RTLOCKVALRECORE
+{
+    /** The magic value indicating the record type. */
+    uint32_t volatile                   u32Magic;
+} RTLOCKVALRECCORE;
+/** Pointer to a lock validator record core. */
+typedef RTLOCKVALRECCORE *PRTLOCKVALRECCORE;
+/** Pointer to a const lock validator record core. */
+typedef RTLOCKVALRECCORE const *PCRTLOCKVALRECCORE;
+
+
+/**
+ * Record recording the exclusive ownership of a lock.
+ *
+ * This is typically part of the per-lock data structure when compiling with
+ * the lock validator.
+ */
+typedef struct RTLOCKVALRECEXCL
+{
+    /** Record core with RTLOCKVALRECEXCL_MAGIC as the magic value. */
+    RTLOCKVALRECCORE                    Core;
+    /** Whether it's enabled or not. */
+    bool                                fEnabled;
+    /** Reserved. */
+    bool                                afReserved[3];
+    /** Source position where the lock was taken. */
+    RTLOCKVALSRCPOS                     SrcPos;
+    /** The current owner thread. */
+    RTTHREAD volatile                   hThread;
+    /** Pointer to the lock record below us. Only accessed by the owner. */
+    R3R0PTRTYPE(PRTLOCKVALRECUNION)     pDown;
+    /** Recursion count */
+    uint32_t                            cRecursion;
+    /** The lock sub-class. */
+    uint32_t volatile                   uSubClass;
+    /** The lock class. */
+    RTLOCKVALCLASS                      hClass;
+    /** Pointer to the lock. */
+    RTHCPTR                             hLock;
+    /** Pointer to the next sibling record.
+     * This is used to find the read side of a read-write lock.  */
+    R3R0PTRTYPE(PRTLOCKVALRECUNION)     pSibling;
+    /** The lock name.
+     * @remarks The bytes beyond 32 are for better size alignment and can be
+     *          taken and used for other purposes if it becomes necessary. */
+    char                                szName[32 + (HC_ARCH_BITS == 32 ? 12 : 8)];
+} RTLOCKVALRECEXCL;
+AssertCompileSize(RTLOCKVALRECEXCL, HC_ARCH_BITS == 32 ? 0x60 : 0x80);
+/* The pointer type is defined in iprt/types.h. */
+
+/**
+ * For recording the one ownership share.
+ */
+typedef struct RTLOCKVALRECSHRDOWN
+{
+    /** Record core with RTLOCKVALRECSHRDOWN_MAGIC as the magic value. */
+    RTLOCKVALRECCORE                    Core;
+    /** Recursion count */
+    uint16_t                            cRecursion;
+    /** Static (true) or dynamic (false) allocated record. */
+    bool                                fStaticAlloc;
+    /** Reserved. */
+    bool                                fReserved;
+    /** The current owner thread. */
+    RTTHREAD volatile                   hThread;
+    /** Pointer to the lock record below us. Only accessed by the owner. */
+    R3R0PTRTYPE(PRTLOCKVALRECUNION)     pDown;
+    /** Pointer back to the shared record. */
+    R3R0PTRTYPE(PRTLOCKVALRECSHRD)      pSharedRec;
+#if HC_ARCH_BITS == 32
+    /** Reserved. */
+    RTHCPTR                             pvReserved;
+#endif
+    /** Source position where the lock was taken. */
+    RTLOCKVALSRCPOS                     SrcPos;
+} RTLOCKVALRECSHRDOWN;
+AssertCompileSize(RTLOCKVALRECSHRDOWN, HC_ARCH_BITS == 32 ? 24 + 16 : 32 + 32);
+/** Pointer to a RTLOCKVALRECSHRDOWN. */
+typedef RTLOCKVALRECSHRDOWN *PRTLOCKVALRECSHRDOWN;
+
+/**
+ * Record recording the shared ownership of a lock.
+ *
+ * This is typically part of the per-lock data structure when compiling with
+ * the lock validator.
+ */
+typedef struct RTLOCKVALRECSHRD
+{
+    /** Record core with RTLOCKVALRECSHRD_MAGIC as the magic value. */
+    RTLOCKVALRECCORE                    Core;
+    /** The lock sub-class. */
+    uint32_t volatile                   uSubClass;
+    /** The lock class. */
+    RTLOCKVALCLASS                      hClass;
+    /** Pointer to the lock. */
+    RTHCPTR                             hLock;
+    /** Pointer to the next sibling record.
+     * This is used to find the write side of a read-write lock.  */
+    R3R0PTRTYPE(PRTLOCKVALRECUNION)     pSibling;
+
+    /** The number of entries in the table.
+     * Updated before inserting and after removal. */
+    uint32_t volatile                   cEntries;
+    /** The index of the last entry (approximately). */
+    uint32_t volatile                   iLastEntry;
+    /** The max table size. */
+    uint32_t volatile                   cAllocated;
+    /** Set if the table is being reallocated, clear if not.
+     * This is used together with rtLockValidatorSerializeDetectionEnter to make
+     * sure there is exactly one thread doing the reallocation and that nobody is
+     * using the table at that point. */
+    bool volatile                       fReallocating;
+    /** Whether it's enabled or not. */
+    bool                                fEnabled;
+    /** Set if event semaphore signaller, clear if read-write semaphore. */
+    bool                                fSignaller;
+    /** Alignment padding. */
+    bool                                fPadding;
+    /** Pointer to a table containing pointers to records of all the owners. */
+    R3R0PTRTYPE(PRTLOCKVALRECSHRDOWN volatile *) papOwners;
+
+    /** The lock name.
+     * @remarks The bytes beyond 32 are for better size alignment and can be
+     *          taken and used for other purposes if it becomes necessary. */
+    char                                szName[32 + (HC_ARCH_BITS == 32 ? 8 : 8)];
+} RTLOCKVALRECSHRD;
+AssertCompileSize(RTLOCKVALRECSHRD, HC_ARCH_BITS == 32 ? 0x50 : 0x60);
+
+
+/**
+ * Makes the two records siblings.
+ *
+ * @returns VINF_SUCCESS on success, VERR_SEM_LV_INVALID_PARAMETER if either of
+ *          the records are invalid.
+ * @param   pRec1               Record 1.
+ * @param   pRec2               Record 2.
+ */
+RTDECL(int) RTLockValidatorRecMakeSiblings(PRTLOCKVALRECCORE pRec1, PRTLOCKVALRECCORE pRec2);
+
+/**
+ * Initialize a lock validator record.
+ *
+ * Use RTLockValidatorRecExclDelete to deinitialize it.
+ *
+ * @param   pRec                The record.
+ * @param   hClass              The class (no reference consumed). If NIL, the
+ *                              no lock order validation will be performed on
+ *                              this lock.
+ * @param   uSubClass           The sub-class.  This is used to define lock
+ *                              order inside the same class.  If you don't know,
+ *                              then pass RTLOCKVAL_SUB_CLASS_NONE.
+ * @param   hLock               The lock handle.
+ * @param   fEnabled            Pass @c false to explicitly disable lock
+ *                              validation, otherwise @c true.
+ * @param   pszNameFmt          Name format string for the lock validator,
+ *                              optional (NULL). Max length is 32 bytes.
+ * @param   ...                 Format string arguments.
+ */
+RTDECL(void) RTLockValidatorRecExclInit(PRTLOCKVALRECEXCL pRec, RTLOCKVALCLASS hClass, uint32_t uSubClass, void *hLock,
+                                        bool fEnabled, const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(6, 7);
+/**
+ * Initialize a lock validator record.
+ *
+ * Use RTLockValidatorRecExclDelete to deinitialize it.
+ *
+ * @param   pRec                The record.
+ * @param   hClass              The class (no reference consumed). If NIL, the
+ *                              no lock order validation will be performed on
+ *                              this lock.
+ * @param   uSubClass           The sub-class.  This is used to define lock
+ *                              order inside the same class.  If you don't know,
+ *                              then pass RTLOCKVAL_SUB_CLASS_NONE.
+ * @param   hLock               The lock handle.
+ * @param   fEnabled            Pass @c false to explicitly disable lock
+ *                              validation, otherwise @c true.
+ * @param   pszNameFmt          Name format string for the lock validator,
+ *                              optional (NULL). Max length is 32 bytes.
+ * @param   va                  Format string arguments.
+ */
+RTDECL(void) RTLockValidatorRecExclInitV(PRTLOCKVALRECEXCL pRec, RTLOCKVALCLASS hClass, uint32_t uSubClass, void *hLock,
+                                         bool fEnabled, const char *pszNameFmt, va_list va) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(6, 0);
+/**
+ * Uninitialize a lock validator record previously initialized by
+ * RTLockRecValidatorInit.
+ *
+ * @param   pRec                The record.  Must be valid.
+ */
+RTDECL(void) RTLockValidatorRecExclDelete(PRTLOCKVALRECEXCL pRec);
+
+/**
+ * Create and initialize a lock validator record.
+ *
+ * Use RTLockValidatorRecExclDestroy to deinitialize and destroy the returned
+ * record.
+ *
+ * @return VINF_SUCCESS or VERR_NO_MEMORY.
+ * @param   ppRec               Where to return the record pointer.
+ * @param   hClass              The class (no reference consumed). If NIL, the
+ *                              no lock order validation will be performed on
+ *                              this lock.
+ * @param   uSubClass           The sub-class.  This is used to define lock
+ *                              order inside the same class.  If you don't know,
+ *                              then pass RTLOCKVAL_SUB_CLASS_NONE.
+ * @param   hLock               The lock handle.
+ * @param   fEnabled            Pass @c false to explicitly disable lock
+ *                              validation, otherwise @c true.
+ * @param   pszNameFmt          Name format string for the lock validator,
+ *                              optional (NULL). Max length is 32 bytes.
+ * @param   ...                 Format string arguments.
+ */
+RTDECL(int)  RTLockValidatorRecExclCreate(PRTLOCKVALRECEXCL *ppRec, RTLOCKVALCLASS hClass, uint32_t uSubClass, void *hLock,
+                                          bool fEnabled, const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(6, 7);
+
+/**
+ * Create and initialize a lock validator record.
+ *
+ * Use RTLockValidatorRecExclDestroy to deinitialize and destroy the returned
+ * record.
+ *
+ * @return VINF_SUCCESS or VERR_NO_MEMORY.
+ * @param   ppRec               Where to return the record pointer.
+ * @param   hClass              The class (no reference consumed). If NIL, the
+ *                              no lock order validation will be performed on
+ *                              this lock.
+ * @param   uSubClass           The sub-class.  This is used to define lock
+ *                              order inside the same class.  If you don't know,
+ *                              then pass RTLOCKVAL_SUB_CLASS_NONE.
+ * @param   hLock               The lock handle.
+ * @param   fEnabled            Pass @c false to explicitly disable lock
+ *                              validation, otherwise @c true.
+ * @param   pszNameFmt          Name format string for the lock validator,
+ *                              optional (NULL). Max length is 32 bytes.
+ * @param   va                  Format string arguments.
+ */
+RTDECL(int)  RTLockValidatorRecExclCreateV(PRTLOCKVALRECEXCL *ppRec, RTLOCKVALCLASS hClass, uint32_t uSubClass, void *hLock,
+                                           bool fEnabled, const char *pszNameFmt, va_list va) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(6, 0);
+
+/**
+ * Deinitialize and destroy a record created by RTLockValidatorRecExclCreate.
+ *
+ * @param   ppRec               Pointer to the record pointer.  Will be set to
+ *                              NULL.
+ */
+RTDECL(void) RTLockValidatorRecExclDestroy(PRTLOCKVALRECEXCL *ppRec);
+
+/**
+ * Sets the sub-class of the record.
+ *
+ * It is recommended to try make sure that nobody is using this class while
+ * changing the value.
+ *
+ * @returns The old sub-class.  RTLOCKVAL_SUB_CLASS_INVALID is returns if the
+ *          lock validator isn't compiled in or either of the parameters are
+ *          invalid.
+ * @param   pRec                The validator record.
+ * @param   uSubClass           The new sub-class value.
+ */
+RTDECL(uint32_t) RTLockValidatorRecExclSetSubClass(PRTLOCKVALRECEXCL pRec, uint32_t uSubClass);
+
+/**
+ * Record the specified thread as lock owner and increment the write lock count.
+ *
+ * This function is typically called after acquiring the lock.  It accounts for
+ * recursions so it can be used instead of RTLockValidatorRecExclRecursion.  Use
+ * RTLockValidatorRecExclReleaseOwner to reverse the effect.
+ *
+ * @param   pRec                The validator record.
+ * @param   hThreadSelf         The handle of the calling thread.  If not known,
+ *                              pass NIL_RTTHREAD and we'll figure it out.
+ * @param   pSrcPos             The source position of the lock operation.
+ * @param   fFirstRecursion     Set if it is the first recursion, clear if not
+ *                              sure.
+ */
+RTDECL(void) RTLockValidatorRecExclSetOwner(PRTLOCKVALRECEXCL pRec, RTTHREAD hThreadSelf,
+                                            PCRTLOCKVALSRCPOS pSrcPos, bool fFirstRecursion);
+
+/**
+ * Check the exit order and release (unset) the ownership.
+ *
+ * This is called by routines implementing releasing an exclusive lock,
+ * typically before getting down to the final lock releasing.  Can be used for
+ * recursive releasing instead of RTLockValidatorRecExclUnwind.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_SEM_LV_WRONG_RELEASE_ORDER if the order is wrong.  Will have
+ *          done all necessary whining and breakpointing before returning.
+ * @retval  VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
+ *
+ * @param   pRec                The validator record.
+ * @param   fFinalRecursion     Set if it's the final recursion, clear if not
+ *                              sure.
+ */
+RTDECL(int) RTLockValidatorRecExclReleaseOwner(PRTLOCKVALRECEXCL pRec, bool fFinalRecursion);
+
+/**
+ * Clear the lock ownership and decrement the write lock count.
+ *
+ * This is only for special cases where we wish to drop lock validation
+ * recording.  See RTLockValidatorRecExclCheckAndRelease.
+ *
+ * @param   pRec                The validator record.
+ */
+RTDECL(void) RTLockValidatorRecExclReleaseOwnerUnchecked(PRTLOCKVALRECEXCL pRec);
+
+/**
+ * Checks and records a lock recursion.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_SEM_LV_NESTED if the semaphore class forbids recursion.  Gone
+ *          thru the motions.
+ * @retval  VERR_SEM_LV_WRONG_ORDER if the locking order is wrong.  Gone thru
+ *          the motions.
+ * @retval  VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
+ *
+ * @param   pRec                The validator record.
+ * @param   pSrcPos             The source position of the lock operation.
+ */
+RTDECL(int) RTLockValidatorRecExclRecursion(PRTLOCKVALRECEXCL pRec, PCRTLOCKVALSRCPOS pSrcPos);
+
+/**
+ * Checks and records a lock unwind (releasing one recursion).
+ *
+ * This should be coupled with called to RTLockValidatorRecExclRecursion.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_SEM_LV_WRONG_RELEASE_ORDER if the release order is wrong.  Gone
+ *          thru the motions.
+ * @retval  VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
+ *
+ * @param   pRec                The validator record.
+ */
+RTDECL(int) RTLockValidatorRecExclUnwind(PRTLOCKVALRECEXCL pRec);
+
+/**
+ * Checks and records a mixed recursion.
+ *
+ * An example of a mixed recursion is a writer requesting read access to a
+ * SemRW.
+ *
+ * This should be coupled with called to RTLockValidatorRecExclUnwindMixed.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_SEM_LV_NESTED if the semaphore class forbids recursion.  Gone
+ *          thru the motions.
+ * @retval  VERR_SEM_LV_WRONG_ORDER if the locking order is wrong.  Gone thru
+ *          the motions.
+ * @retval  VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
+ *
+ * @param   pRec                The validator record it to accounted it to.
+ * @param   pRecMixed           The validator record it came in on.
+ * @param   pSrcPos             The source position of the lock operation.
+ */
+RTDECL(int) RTLockValidatorRecExclRecursionMixed(PRTLOCKVALRECEXCL pRec, PRTLOCKVALRECCORE pRecMixed, PCRTLOCKVALSRCPOS pSrcPos);
+
+/**
+ * Checks and records the unwinding of a mixed recursion.
+ *
+ * This should be coupled with called to RTLockValidatorRecExclRecursionMixed.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_SEM_LV_WRONG_RELEASE_ORDER if the release order is wrong.  Gone
+ *          thru the motions.
+ * @retval  VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
+ *
+ * @param   pRec                The validator record it was accounted to.
+ * @param   pRecMixed           The validator record it came in on.
+ */
+RTDECL(int) RTLockValidatorRecExclUnwindMixed(PRTLOCKVALRECEXCL pRec, PRTLOCKVALRECCORE pRecMixed);
+
+/**
+ * Check the exclusive locking order.
+ *
+ * This is called by routines implementing exclusive lock acquisition.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_SEM_LV_WRONG_ORDER if the order is wrong.  Will have done all
+ *          necessary whining and breakpointing before returning.
+ * @retval  VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
+ *
+ * @param   pRec                The validator record.
+ * @param   hThreadSelf         The handle of the calling thread.  If not known,
+ *                              pass NIL_RTTHREAD and we'll figure it out.
+ * @param   pSrcPos             The source position of the lock operation.
+ * @param   cMillies            The timeout, in milliseconds.
+ */
+RTDECL(int)  RTLockValidatorRecExclCheckOrder(PRTLOCKVALRECEXCL pRec, RTTHREAD hThreadSelf,
+                                              PCRTLOCKVALSRCPOS pSrcPos, RTMSINTERVAL cMillies);
+
+/**
+ * Do deadlock detection before blocking on exclusive access to a lock and
+ * change the thread state.
+ *
+ * @retval  VINF_SUCCESS - thread is in the specified sleep state.
+ * @retval  VERR_SEM_LV_DEADLOCK if blocking would deadlock.  Gone thru the
+ *          motions.
+ * @retval  VERR_SEM_LV_NESTED if the semaphore isn't recursive and hThread is
+ *          already the owner.  Gone thru the motions.
+ * @retval  VERR_SEM_LV_ILLEGAL_UPGRADE if it's a deadlock on the same lock.
+ *          The caller must handle any legal upgrades without invoking this
+ *          function (for now).
+ * @retval  VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
+ *
+ * @param   pRec                The validator record we're blocking on.
+ * @param   hThreadSelf         The current thread.  Shall not be NIL_RTTHREAD!
+ * @param   pSrcPos             The source position of the lock operation.
+ * @param   fRecursiveOk        Whether it's ok to recurse.
+ * @param   cMillies            The timeout, in milliseconds.
+ * @param   enmSleepState       The sleep state to enter on successful return.
+ * @param   fReallySleeping     Is it really going to sleep now or not.  Use
+ *                              false before calls to other IPRT synchronization
+ *                              methods.
+ */
+RTDECL(int) RTLockValidatorRecExclCheckBlocking(PRTLOCKVALRECEXCL pRec, RTTHREAD hThreadSelf,
+                                                PCRTLOCKVALSRCPOS pSrcPos, bool fRecursiveOk, RTMSINTERVAL cMillies,
+                                                RTTHREADSTATE enmSleepState, bool fReallySleeping);
+
+/**
+ * RTLockValidatorRecExclCheckOrder and RTLockValidatorRecExclCheckBlocking
+ * baked into one call.
+ *
+ * @returns Any of the statuses returned by the two APIs.
+ * @param   pRec                The validator record.
+ * @param   hThreadSelf         The current thread.  Shall not be NIL_RTTHREAD!
+ * @param   pSrcPos             The source position of the lock operation.
+ * @param   fRecursiveOk        Whether it's ok to recurse.
+ * @param   cMillies            The timeout, in milliseconds.
+ * @param   enmSleepState       The sleep state to enter on successful return.
+ * @param   fReallySleeping     Is it really going to sleep now or not.  Use
+ *                              false before calls to other IPRT synchronization
+ *                              methods.
+ */
+RTDECL(int) RTLockValidatorRecExclCheckOrderAndBlocking(PRTLOCKVALRECEXCL pRec, RTTHREAD hThreadSelf,
+                                                        PCRTLOCKVALSRCPOS pSrcPos, bool fRecursiveOk, RTMSINTERVAL cMillies,
+                                                        RTTHREADSTATE enmSleepState, bool fReallySleeping);
+
+/**
+ * Initialize a lock validator record for a shared lock.
+ *
+ * Use RTLockValidatorRecSharedDelete to deinitialize it.
+ *
+ * @param   pRec                The shared lock record.
+ * @param   hClass              The class (no reference consumed). If NIL, the
+ *                              no lock order validation will be performed on
+ *                              this lock.
+ * @param   uSubClass           The sub-class.  This is used to define lock
+ *                              order inside the same class.  If you don't know,
+ *                              then pass RTLOCKVAL_SUB_CLASS_NONE.
+ * @param   hLock               The lock handle.
+ * @param   fSignaller          Set if event semaphore signaller logic should be
+ *                              applied to this record, clear if read-write
+ *                              semaphore logic should be used.
+ * @param   fEnabled            Pass @c false to explicitly disable lock
+ *                              validation, otherwise @c true.
+ * @param   pszNameFmt          Name format string for the lock validator,
+ *                              optional (NULL). Max length is 32 bytes.
+ * @param   ...                 Format string arguments.
+ */
+RTDECL(void) RTLockValidatorRecSharedInit(PRTLOCKVALRECSHRD pRec, RTLOCKVALCLASS hClass, uint32_t uSubClass,
+                                          void *hLock, bool fSignaller, bool fEnabled,
+                                          const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(7, 8);
+
+/**
+ * Initialize a lock validator record for a shared lock.
+ *
+ * Use RTLockValidatorRecSharedDelete to deinitialize it.
+ *
+ * @param   pRec                The shared lock record.
+ * @param   hClass              The class (no reference consumed). If NIL, the
+ *                              no lock order validation will be performed on
+ *                              this lock.
+ * @param   uSubClass           The sub-class.  This is used to define lock
+ *                              order inside the same class.  If you don't know,
+ *                              then pass RTLOCKVAL_SUB_CLASS_NONE.
+ * @param   hLock               The lock handle.
+ * @param   fSignaller          Set if event semaphore signaller logic should be
+ *                              applied to this record, clear if read-write
+ *                              semaphore logic should be used.
+ * @param   fEnabled            Pass @c false to explicitly disable lock
+ *                              validation, otherwise @c true.
+ * @param   pszNameFmt          Name format string for the lock validator,
+ *                              optional (NULL). Max length is 32 bytes.
+ * @param   va                  Format string arguments.
+ */
+RTDECL(void) RTLockValidatorRecSharedInitV(PRTLOCKVALRECSHRD pRec, RTLOCKVALCLASS hClass, uint32_t uSubClass,
+                                           void *hLock, bool fSignaller, bool fEnabled,
+                                           const char *pszNameFmt, va_list va) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(7, 0);
+
+/**
+ * Uninitialize a lock validator record previously initialized by
+ * RTLockValidatorRecSharedInit.
+ *
+ * @param   pRec                The shared lock record.  Must be valid.
+ */
+RTDECL(void) RTLockValidatorRecSharedDelete(PRTLOCKVALRECSHRD pRec);
+
+/**
+ * Create and initialize a lock validator record for a shared lock.
+ *
+ * Use RTLockValidatorRecSharedDestroy to deinitialize and destroy the returned
+ * record.
+ *
+ * @returns IPRT status code.
+ * @param   ppRec               Where to return the record pointer.
+ * @param   hClass              The class (no reference consumed). If NIL, the
+ *                              no lock order validation will be performed on
+ *                              this lock.
+ * @param   uSubClass           The sub-class.  This is used to define lock
+ *                              order inside the same class.  If you don't know,
+ *                              then pass RTLOCKVAL_SUB_CLASS_NONE.
+ * @param   pvLock              The lock handle or address.
+ * @param   fSignaller          Set if event semaphore signaller logic should be
+ *                              applied to this record, clear if read-write
+ *                              semaphore logic should be used.
+ * @param   fEnabled            Pass @c false to explicitly disable lock
+ *                              validation, otherwise @c true.
+ * @param   pszNameFmt          Name format string for the lock validator,
+ *                              optional (NULL). Max length is 32 bytes.
+ * @param   ...                 Format string arguments.
+ */
+RTDECL(int) RTLockValidatorRecSharedCreate(PRTLOCKVALRECSHRD *ppRec, RTLOCKVALCLASS hClass, uint32_t uSubClass,
+                                           void *pvLock, bool fSignaller, bool fEnabled,
+                                           const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(7, 8);
+
+/**
+ * Create and initialize a lock validator record for a shared lock.
+ *
+ * Use RTLockValidatorRecSharedDestroy to deinitialize and destroy the returned
+ * record.
+ *
+ * @returns IPRT status code.
+ * @param   ppRec               Where to return the record pointer.
+ * @param   hClass              The class (no reference consumed). If NIL, the
+ *                              no lock order validation will be performed on
+ *                              this lock.
+ * @param   uSubClass           The sub-class.  This is used to define lock
+ *                              order inside the same class.  If you don't know,
+ *                              then pass RTLOCKVAL_SUB_CLASS_NONE.
+ * @param   pvLock              The lock handle or address.
+ * @param   fSignaller          Set if event semaphore signaller logic should be
+ *                              applied to this record, clear if read-write
+ *                              semaphore logic should be used.
+ * @param   fEnabled            Pass @c false to explicitly disable lock
+ *                              validation, otherwise @c true.
+ * @param   pszNameFmt          Name format string for the lock validator,
+ *                              optional (NULL). Max length is 32 bytes.
+ * @param   va                  Format string arguments.
+ */
+RTDECL(int) RTLockValidatorRecSharedCreateV(PRTLOCKVALRECSHRD *ppRec, RTLOCKVALCLASS hClass, uint32_t uSubClass,
+                                            void *pvLock, bool fSignaller, bool fEnabled,
+                                            const char *pszNameFmt, va_list va) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(7, 0);
+
+/**
+ * Deinitialize and destroy a record created by RTLockValidatorRecSharedCreate.
+ *
+ * @param   ppRec               Pointer to the record pointer.  Will be set to
+ *                              NULL.
+ */
+RTDECL(void) RTLockValidatorRecSharedDestroy(PRTLOCKVALRECSHRD *ppRec);
+
+/**
+ * Sets the sub-class of the record.
+ *
+ * It is recommended to try make sure that nobody is using this class while
+ * changing the value.
+ *
+ * @returns The old sub-class.  RTLOCKVAL_SUB_CLASS_INVALID is returns if the
+ *          lock validator isn't compiled in or either of the parameters are
+ *          invalid.
+ * @param   pRec                The validator record.
+ * @param   uSubClass           The new sub-class value.
+ */
+RTDECL(uint32_t) RTLockValidatorRecSharedSetSubClass(PRTLOCKVALRECSHRD pRec, uint32_t uSubClass);
+
+/**
+ * Check the shared locking order.
+ *
+ * This is called by routines implementing shared lock acquisition.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_SEM_LV_WRONG_ORDER if the order is wrong.  Will have done all
+ *          necessary whining and breakpointing before returning.
+ * @retval  VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
+ *
+ * @param   pRec                The validator record.
+ * @param   hThreadSelf         The handle of the calling thread.  If not known,
+ *                              pass NIL_RTTHREAD and we'll figure it out.
+ * @param   pSrcPos             The source position of the lock operation.
+ * @param   cMillies            Intended sleep time in milliseconds.
+ */
+RTDECL(int)  RTLockValidatorRecSharedCheckOrder(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf,
+                                                PCRTLOCKVALSRCPOS pSrcPos, RTMSINTERVAL cMillies);
+
+/**
+ * Do deadlock detection before blocking on shared access to a lock and change
+ * the thread state.
+ *
+ * @retval  VINF_SUCCESS - thread is in the specified sleep state.
+ * @retval  VERR_SEM_LV_DEADLOCK if blocking would deadlock.  Gone thru the
+ *          motions.
+ * @retval  VERR_SEM_LV_NESTED if the semaphore isn't recursive and hThread is
+ *          already the owner.  Gone thru the motions.
+ * @retval  VERR_SEM_LV_ILLEGAL_UPGRADE if it's a deadlock on the same lock.
+ *          The caller must handle any legal upgrades without invoking this
+ *          function (for now).
+ * @retval  VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
+ *
+ * @param   pRec                The validator record we're blocking on.
+ * @param   hThreadSelf         The current thread.  Shall not be NIL_RTTHREAD!
+ * @param   pSrcPos             The source position of the lock operation.
+ * @param   fRecursiveOk        Whether it's ok to recurse.
+ * @param   cMillies            Intended sleep time in milliseconds.
+ * @param   enmSleepState       The sleep state to enter on successful return.
+ * @param   fReallySleeping     Is it really going to sleep now or not.  Use
+ *                              false before calls to other IPRT synchronization
+ *                              methods.
+ */
+RTDECL(int) RTLockValidatorRecSharedCheckBlocking(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf,
+                                                  PCRTLOCKVALSRCPOS pSrcPos, bool fRecursiveOk, RTMSINTERVAL cMillies,
+                                                  RTTHREADSTATE enmSleepState, bool fReallySleeping);
+
+/**
+ * RTLockValidatorRecSharedCheckOrder and RTLockValidatorRecSharedCheckBlocking
+ * baked into one call.
+ *
+ * @returns Any of the statuses returned by the two APIs.
+ * @param   pRec                The validator record.
+ * @param   hThreadSelf         The current thread.  Shall not be NIL_RTTHREAD!
+ * @param   pSrcPos             The source position of the lock operation.
+ * @param   fRecursiveOk        Whether it's ok to recurse.
+ * @param   cMillies            Intended sleep time in milliseconds.
+ * @param   enmSleepState       The sleep state to enter on successful return.
+ * @param   fReallySleeping     Is it really going to sleep now or not.  Use
+ *                              false before calls to other IPRT synchronization
+ *                              methods.
+ */
+RTDECL(int) RTLockValidatorRecSharedCheckOrderAndBlocking(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf,
+                                                          PCRTLOCKVALSRCPOS pSrcPos, bool fRecursiveOk, RTMSINTERVAL cMillies,
+                                                          RTTHREADSTATE enmSleepState, bool fReallySleeping);
+
+/**
+ * Removes all current owners and makes hThread the only owner.
+ *
+ * @param   pRec                The validator record.
+ * @param   hThread             The thread handle of the owner.  NIL_RTTHREAD is
+ *                              an alias for the current thread.
+ * @param   pSrcPos             The source position of the lock operation.
+ */
+RTDECL(void) RTLockValidatorRecSharedResetOwner(PRTLOCKVALRECSHRD pRec, RTTHREAD hThread, PCRTLOCKVALSRCPOS pSrcPos);
+
+/**
+ * Adds an owner to a shared locking record.
+ *
+ * Takes recursion into account.  This function is typically called after
+ * acquiring the lock in shared mode.
+ *
+ * @param   pRec                The validator record.
+ * @param   hThread             The thread handle of the owner.  NIL_RTTHREAD is
+ *                              an alias for the current thread.
+ * @param   pSrcPos             The source position of the lock operation.
+ */
+RTDECL(void) RTLockValidatorRecSharedAddOwner(PRTLOCKVALRECSHRD pRec, RTTHREAD hThread, PCRTLOCKVALSRCPOS pSrcPos);
+
+/**
+ * Removes an owner from a shared locking record.
+ *
+ * Takes recursion into account.  This function is typically called before
+ * releasing the lock.
+ *
+ * @param   pRec                The validator record.
+ * @param   hThread             The thread handle of the owner.  NIL_RTTHREAD is
+ *                              an alias for the current thread.
+ */
+RTDECL(void) RTLockValidatorRecSharedRemoveOwner(PRTLOCKVALRECSHRD pRec, RTTHREAD hThread);
+
+/**
+ * Checks if the specified thread is one of the owners.
+ *
+ * @returns true if it is, false if not.
+ *
+ * @param   pRec                The validator record.
+ * @param   hThread             The thread handle of the owner.  NIL_RTTHREAD is
+ *                              an alias for the current thread.
+ */
+RTDECL(bool) RTLockValidatorRecSharedIsOwner(PRTLOCKVALRECSHRD pRec, RTTHREAD hThread);
+
+/**
+ * Check the exit order and release (unset) the shared ownership.
+ *
+ * This is called by routines implementing releasing the read/write lock.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_SEM_LV_WRONG_RELEASE_ORDER if the order is wrong.  Will have
+ *          done all necessary whining and breakpointing before returning.
+ * @retval  VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
+ *
+ * @param   pRec                The validator record.
+ * @param   hThreadSelf         The handle of the calling thread.  NIL_RTTHREAD
+ *                              is an alias for the current thread.
+ */
+RTDECL(int) RTLockValidatorRecSharedCheckAndRelease(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf);
+
+/**
+ * Check the signaller of an event.
+ *
+ * This is called by routines implementing releasing the event semaphore (both
+ * kinds).
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_SEM_LV_NOT_SIGNALLER if the thread is not in the record.  Will
+ *          have done all necessary whining and breakpointing before returning.
+ * @retval  VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
+ *
+ * @param   pRec                The validator record.
+ * @param   hThreadSelf         The handle of the calling thread.  NIL_RTTHREAD
+ *                              is an alias for the current thread.
+ */
+RTDECL(int) RTLockValidatorRecSharedCheckSignaller(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf);
+
+/**
+ * Gets the number of write locks and critical sections the specified
+ * thread owns.
+ *
+ * This number does not include any nested lock/critect entries.
+ *
+ * Note that it probably will return 0 for non-strict builds since
+ * release builds doesn't do unnecessary diagnostic counting like this.
+ *
+ * @returns Number of locks on success (0+) and VERR_INVALID_HANDLER on failure
+ * @param   Thread          The thread we're inquiring about.
+ * @remarks Will only work for strict builds.
+ */
+RTDECL(int32_t) RTLockValidatorWriteLockGetCount(RTTHREAD Thread);
+
+/**
+ * Works the THREADINT::cWriteLocks member, mostly internal.
+ *
+ * @param   Thread      The current thread.
+ */
+RTDECL(void) RTLockValidatorWriteLockInc(RTTHREAD Thread);
+
+/**
+ * Works the THREADINT::cWriteLocks member, mostly internal.
+ *
+ * @param   Thread      The current thread.
+ */
+RTDECL(void) RTLockValidatorWriteLockDec(RTTHREAD Thread);
+
+/**
+ * Gets the number of read locks the specified thread owns.
+ *
+ * Note that nesting read lock entry will be included in the
+ * total sum. And that it probably will return 0 for non-strict
+ * builds since release builds doesn't do unnecessary diagnostic
+ * counting like this.
+ *
+ * @returns Number of read locks on success (0+) and VERR_INVALID_HANDLER on failure
+ * @param   Thread          The thread we're inquiring about.
+ */
+RTDECL(int32_t) RTLockValidatorReadLockGetCount(RTTHREAD Thread);
+
+/**
+ * Works the THREADINT::cReadLocks member.
+ *
+ * @param   Thread      The current thread.
+ */
+RTDECL(void) RTLockValidatorReadLockInc(RTTHREAD Thread);
+
+/**
+ * Works the THREADINT::cReadLocks member.
+ *
+ * @param   Thread      The current thread.
+ */
+RTDECL(void) RTLockValidatorReadLockDec(RTTHREAD Thread);
+
+/**
+ * Query which lock the specified thread is waiting on.
+ *
+ * @returns The lock handle value or NULL.
+ * @param   hThread     The thread in question.
+ */
+RTDECL(void *) RTLockValidatorQueryBlocking(RTTHREAD hThread);
+
+/**
+ * Checks if the thread is running in the lock validator after it has entered a
+ * block state.
+ *
+ * @returns true if it is, false if it isn't.
+ * @param   hThread     The thread in question.
+ */
+RTDECL(bool) RTLockValidatorIsBlockedThreadInValidator(RTTHREAD hThread);
+
+/**
+ * Checks if the calling thread is holding a lock in the specified class.
+ *
+ * @returns true if it holds a lock in the specific class, false if it
+ *          doesn't.
+ *
+ * @param   hCurrentThread      The current thread.  Pass NIL_RTTHREAD if you're
+ *                              lazy.
+ * @param   hClass              The class.
+ */
+RTDECL(bool) RTLockValidatorHoldsLocksInClass(RTTHREAD hCurrentThread, RTLOCKVALCLASS hClass);
+
+/**
+ * Checks if the calling thread is holding a lock in the specified sub-class.
+ *
+ * @returns true if it holds a lock in the specific sub-class, false if it
+ *          doesn't.
+ *
+ * @param   hCurrentThread      The current thread.  Pass NIL_RTTHREAD if you're
+ *                              lazy.
+ * @param   hClass              The class.
+ * @param   uSubClass           The new sub-class value.
+ */
+RTDECL(bool) RTLockValidatorHoldsLocksInSubClass(RTTHREAD hCurrentThread, RTLOCKVALCLASS hClass, uint32_t uSubClass);
+
+
+
+/**
+ * Creates a new lock validator class, all properties specified.
+ *
+ * @returns IPRT status code
+ * @param   phClass             Where to return the class handle.
+ * @param   pSrcPos             The source position of the create call.
+ * @param   fAutodidact         Whether the class should be allowed to teach
+ *                              itself new locking order rules (true), or if the
+ *                              user will teach it all it needs to know (false).
+ * @param   fRecursionOk        Whether to allow lock recursion or not.
+ * @param   fStrictReleaseOrder Enforce strict lock release order or not.
+ * @param   cMsMinDeadlock      Used to raise the sleep interval at which
+ *                              deadlock detection kicks in.  Minimum is 1 ms,
+ *                              while RT_INDEFINITE_WAIT will disable it.
+ * @param   cMsMinOrder         Used to raise the sleep interval at which lock
+ *                              order validation kicks in.  Minimum is 1 ms,
+ *                              while RT_INDEFINITE_WAIT will disable it.
+ * @param   pszNameFmt          Class name format string, optional (NULL).  Max
+ *                              length is 32 bytes.
+ * @param   ...                 Format string arguments.
+ *
+ * @remarks The properties can be modified after creation by the
+ *          RTLockValidatorClassSet* methods.
+ */
+RTDECL(int) RTLockValidatorClassCreateEx(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos,
+                                         bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder,
+                                         RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder,
+                                         const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(8, 9);
+
+/**
+ * Creates a new lock validator class, all properties specified.
+ *
+ * @returns IPRT status code
+ * @param   phClass             Where to return the class handle.
+ * @param   pSrcPos             The source position of the create call.
+ * @param   fAutodidact         Whether the class should be allowed to teach
+ *                              itself new locking order rules (true), or if the
+ *                              user will teach it all it needs to know (false).
+ * @param   fRecursionOk        Whether to allow lock recursion or not.
+ * @param   fStrictReleaseOrder Enforce strict lock release order or not.
+ * @param   cMsMinDeadlock      Used to raise the sleep interval at which
+ *                              deadlock detection kicks in.  Minimum is 1 ms,
+ *                              while RT_INDEFINITE_WAIT will disable it.
+ * @param   cMsMinOrder         Used to raise the sleep interval at which lock
+ *                              order validation kicks in.  Minimum is 1 ms,
+ *                              while RT_INDEFINITE_WAIT will disable it.
+ * @param   pszNameFmt          Class name format string, optional (NULL).  Max
+ *                              length is 32 bytes.
+ * @param   va                  Format string arguments.
+ *
+ * @remarks The properties can be modified after creation by the
+ *          RTLockValidatorClassSet* methods.
+ */
+RTDECL(int) RTLockValidatorClassCreateExV(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos,
+                                          bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder,
+                                          RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder,
+                                          const char *pszNameFmt, va_list va) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(8, 0);
+
+/**
+ * Creates a new lock validator class.
+ *
+ * @returns IPRT status code
+ * @param   phClass             Where to return the class handle.
+ * @param   fAutodidact         Whether the class should be allowed to teach
+ *                              itself new locking order rules (true), or if the
+ *                              user will teach it all it needs to know (false).
+ * @param   SRC_POS             The source position where call is being made from.
+ *                              Use RT_SRC_POS when possible.  Optional.
+ * @param   pszNameFmt          Class name format string, optional (NULL).  Max
+ *                              length is 32 bytes.
+ * @param   ...                 Format string arguments.
+ */
+RTDECL(int) RTLockValidatorClassCreate(PRTLOCKVALCLASS phClass, bool fAutodidact, RT_SRC_POS_DECL,
+                                       const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(6, 7);
+
+/**
+ * Creates a new lock validator class with a reference that is consumed by the
+ * first call to RTLockValidatorClassRetain.
+ *
+ * This is tailored for use in the parameter list of a semaphore constructor.
+ *
+ * @returns Class handle with a reference that is automatically consumed by the
+ *          first retainer.  NIL_RTLOCKVALCLASS if we run into trouble.
+ *
+ * @param   SRC_POS             The source position where call is being made from.
+ *                              Use RT_SRC_POS when possible.  Optional.
+ * @param   pszNameFmt          Class name format string, optional (NULL).  Max
+ *                              length is 32 bytes.
+ * @param   ...                 Format string arguments.
+ */
+RTDECL(RTLOCKVALCLASS) RTLockValidatorClassCreateUnique(RT_SRC_POS_DECL,
+                                                        const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(4, 5);
+
+/**
+ * Finds a class for the specified source position.
+ *
+ * @returns A handle to the class (not retained!) or NIL_RTLOCKVALCLASS.
+ * @param   pSrcPos             The source position.
+ */
+RTDECL(RTLOCKVALCLASS) RTLockValidatorClassFindForSrcPos(PRTLOCKVALSRCPOS pSrcPos);
+
+/**
+ * Finds or creates a class given the source position.
+ *
+ * @returns Class handle (not retained!) or NIL_RTLOCKVALCLASS.
+ * @param   SRC_POS             The source position where call is being made from.
+ *                              Use RT_SRC_POS when possible.  Optional.
+ * @param   pszNameFmt          Class name format string, optional (NULL).  Max
+ *                              length is 32 bytes.
+ * @param   ...                 Format string arguments.
+ */
+RTDECL(RTLOCKVALCLASS) RTLockValidatorClassForSrcPos(RT_SRC_POS_DECL,
+                                                     const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(4, 5);
+
+/**
+ * Retains a reference to a lock validator class.
+ *
+ * @returns New reference count; UINT32_MAX if the handle is invalid.
+ * @param   hClass              Handle to the class.
+ */
+RTDECL(uint32_t) RTLockValidatorClassRetain(RTLOCKVALCLASS hClass);
+
+/**
+ * Releases a reference to a lock validator class.
+ *
+ * @returns New reference count. 0 if hClass is NIL_RTLOCKVALCLASS. UINT32_MAX
+ *          if the handle is invalid.
+ * @param   hClass              Handle to the class.
+ */
+RTDECL(uint32_t) RTLockValidatorClassRelease(RTLOCKVALCLASS hClass);
+
+/**
+ * Teaches the class @a hClass that locks in the class @a hPriorClass can be
+ * held when taking a lock of class @a hClass
+ *
+ * @returns IPRT status.
+ * @param   hClass              Handle to the pupil class.
+ * @param   hPriorClass         Handle to the class that can be held prior to
+ *                              taking a lock in the pupil class.  (No reference
+ *                              is consumed.)
+ */
+RTDECL(int) RTLockValidatorClassAddPriorClass(RTLOCKVALCLASS hClass, RTLOCKVALCLASS hPriorClass);
+
+/**
+ * Enables or disables the strict release order enforcing.
+ *
+ * @returns IPRT status.
+ * @param   hClass              Handle to the class to change.
+ * @param   fEnabled            Enable it (true) or disable it (false).
+ */
+RTDECL(int) RTLockValidatorClassEnforceStrictReleaseOrder(RTLOCKVALCLASS hClass, bool fEnabled);
+
+/**
+ * Enables / disables the lock validator for new locks.
+ *
+ * @returns The old setting.
+ * @param   fEnabled    The new setting.
+ */
+RTDECL(bool) RTLockValidatorSetEnabled(bool fEnabled);
+
+/**
+ * Is the lock validator enabled?
+ *
+ * @returns True if enabled, false if not.
+ */
+RTDECL(bool) RTLockValidatorIsEnabled(void);
+
+/**
+ * Controls whether the lock validator should be quiet or noisy (default).
+ *
+ * @returns The old setting.
+ * @param   fQuiet              The new setting.
+ */
+RTDECL(bool) RTLockValidatorSetQuiet(bool fQuiet);
+
+/**
+ * Is the lock validator quiet or noisy?
+ *
+ * @returns True if it is quiet, false if noisy.
+ */
+RTDECL(bool) RTLockValidatorIsQuiet(void);
+
+/**
+ * Makes the lock validator panic (default) or not.
+ *
+ * @returns The old setting.
+ * @param   fPanic              The new setting.
+ */
+RTDECL(bool) RTLockValidatorSetMayPanic(bool fPanic);
+
+/**
+ * Can the lock validator cause panic.
+ *
+ * @returns True if it can, false if not.
+ */
+RTDECL(bool) RTLockValidatorMayPanic(void);
+
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/log.h b/ubuntu/vbox/include/iprt/log.h
new file mode 100644 (file)
index 0000000..f7e4204
--- /dev/null
@@ -0,0 +1,2527 @@
+/** @file
+ * IPRT - Logging.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_log_h
+#define ___iprt_log_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_log    RTLog - Logging
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * IPRT Logging Groups.
+ * (Remember to update RT_LOGGROUP_NAMES!)
+ *
+ * @remark It should be pretty obvious, but just to have
+ *         mentioned it, the values are sorted alphabetically (using the
+ *         english alphabet) except for _DEFAULT which is always first.
+ *
+ *         If anyone might be wondering what the alphabet looks like:
+ *              a b c d e f g h i j k l m n o p q r s t u v w x y z
+ */
+typedef enum RTLOGGROUP
+{
+    /** Default logging group. */
+    RTLOGGROUP_DEFAULT,
+    RTLOGGROUP_CRYPTO,
+    RTLOGGROUP_DBG,
+    RTLOGGROUP_DBG_DWARF,
+    RTLOGGROUP_DIR,
+    RTLOGGROUP_FILE,
+    RTLOGGROUP_FS,
+    RTLOGGROUP_HTTP,
+    RTLOGGROUP_LDR,
+    RTLOGGROUP_PATH,
+    RTLOGGROUP_PROCESS,
+    RTLOGGROUP_SYMLINK,
+    RTLOGGROUP_THREAD,
+    RTLOGGROUP_TIME,
+    RTLOGGROUP_TIMER,
+    RTLOGGROUP_LOCALIPC,
+    RTLOGGROUP_VFS,
+    RTLOGGROUP_ZIP = 31,
+    RTLOGGROUP_FIRST_USER = 32
+} RTLOGGROUP;
+
+/** @def RT_LOGGROUP_NAMES
+ * IPRT Logging group names.
+ *
+ * Must correspond 100% to RTLOGGROUP!
+ * Don't forget commas!
+ *
+ * @remark It should be pretty obvious, but just to have
+ *         mentioned it, the values are sorted alphabetically (using the
+ *         english alphabet) except for _DEFAULT which is always first.
+ *
+ *         If anyone might be wondering what the alphabet looks like:
+ *              a b c d e f g h i j k l m n o p q r s t u v w x y z
+ */
+#define RT_LOGGROUP_NAMES \
+    "DEFAULT",      \
+    "RT_CRYPTO",    \
+    "RT_DBG",       \
+    "RT_DBG_DWARF", \
+    "RT_DIR",       \
+    "RT_FILE",      \
+    "RT_FS",        \
+    "RT_HTTP", \
+    "RT_LDR",       \
+    "RT_PATH",      \
+    "RT_PROCESS",   \
+    "RT_SYMLINK",   \
+    "RT_THREAD",    \
+    "RT_TIME",      \
+    "RT_TIMER",     \
+    "RT_LOCALIPC", \
+    "RT_VFS", \
+    "RT_17", \
+    "RT_18", \
+    "RT_19", \
+    "RT_20", \
+    "RT_21", \
+    "RT_22", \
+    "RT_23", \
+    "RT_24", \
+    "RT_25", \
+    "RT_26", \
+    "RT_27", \
+    "RT_28", \
+    "RT_29", \
+    "RT_30", \
+    "RT_ZIP"  \
+
+
+/** @def LOG_GROUP
+ * Active logging group.
+ */
+#ifndef LOG_GROUP
+# define LOG_GROUP          RTLOGGROUP_DEFAULT
+#endif
+
+/** @def LOG_FN_FMT
+ * You can use this to specify you desired way of printing __PRETTY_FUNCTION__
+ * if you dislike the default one.
+ */
+#ifndef LOG_FN_FMT
+# define LOG_FN_FMT "%Rfn"
+#endif
+
+#ifdef LOG_INSTANCE
+# error "LOG_INSTANCE is no longer supported."
+#endif
+#ifdef LOG_REL_INSTANCE
+# error "LOG_REL_INSTANCE is no longer supported."
+#endif
+
+/** Logger structure. */
+#ifdef IN_RC
+typedef struct RTLOGGERRC RTLOGGER;
+#else
+typedef struct RTLOGGER RTLOGGER;
+#endif
+/** Pointer to logger structure. */
+typedef RTLOGGER *PRTLOGGER;
+/** Pointer to const logger structure. */
+typedef const RTLOGGER *PCRTLOGGER;
+
+
+/** Guest context logger structure. */
+typedef struct RTLOGGERRC RTLOGGERRC;
+/** Pointer to guest context logger structure. */
+typedef RTLOGGERRC *PRTLOGGERRC;
+/** Pointer to const guest context logger structure. */
+typedef const RTLOGGERRC *PCRTLOGGERRC;
+
+
+/**
+ * Logger phase.
+ *
+ * Used for signalling the log header/footer callback what to do.
+ */
+typedef enum RTLOGPHASE
+{
+    /** Begin of the logging. */
+    RTLOGPHASE_BEGIN = 0,
+    /** End of the logging. */
+    RTLOGPHASE_END,
+    /** Before rotating the log file. */
+    RTLOGPHASE_PREROTATE,
+    /** After rotating the log file. */
+    RTLOGPHASE_POSTROTATE,
+    /** 32-bit type blow up hack.  */
+    RTLOGPHASE_32BIT_HACK = 0x7fffffff
+} RTLOGPHASE;
+
+
+/**
+ * Logger function.
+ *
+ * @param   pszFormat   Format string.
+ * @param   ...         Optional arguments as specified in the format string.
+ */
+typedef DECLCALLBACK(void) FNRTLOGGER(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+/** Pointer to logger function. */
+typedef FNRTLOGGER *PFNRTLOGGER;
+
+/**
+ * Flush function.
+ *
+ * @param   pLogger     Pointer to the logger instance which is to be flushed.
+ */
+typedef DECLCALLBACK(void) FNRTLOGFLUSH(PRTLOGGER pLogger);
+/** Pointer to flush function. */
+typedef FNRTLOGFLUSH *PFNRTLOGFLUSH;
+
+/**
+ * Flush function.
+ *
+ * @param   pLogger     Pointer to the logger instance which is to be flushed.
+ */
+typedef DECLCALLBACK(void) FNRTLOGFLUSHGC(PRTLOGGERRC pLogger);
+/** Pointer to logger function. */
+typedef RCPTRTYPE(FNRTLOGFLUSHGC *) PFNRTLOGFLUSHGC;
+
+/**
+ * Header/footer message callback.
+ *
+ * @param   pLogger     Pointer to the logger instance.
+ * @param   pszFormat   Format string.
+ * @param   ...         Optional arguments specified in the format string.
+ */
+typedef DECLCALLBACK(void) FNRTLOGPHASEMSG(PRTLOGGER pLogger, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+/** Pointer to header/footer message callback function. */
+typedef FNRTLOGPHASEMSG *PFNRTLOGPHASEMSG;
+
+/**
+ * Log file header/footer callback.
+ *
+ * @param   pLogger         Pointer to the logger instance.
+ * @param   enmLogPhase     Indicates at what time the callback is invoked.
+ * @param   pfnLogPhaseMsg  Callback for writing the header/footer (RTLogPrintf
+ *                          and others are out of bounds).
+ */
+typedef DECLCALLBACK(void) FNRTLOGPHASE(PRTLOGGER pLogger, RTLOGPHASE enmLogPhase, PFNRTLOGPHASEMSG pfnLogPhaseMsg);
+/** Pointer to log header/footer callback function. */
+typedef FNRTLOGPHASE *PFNRTLOGPHASE;
+
+/**
+ * Custom log prefix callback.
+ *
+ *
+ * @returns The number of chars written.
+ *
+ * @param   pLogger     Pointer to the logger instance.
+ * @param   pchBuf      Output buffer pointer.
+ *                      No need to terminate the output.
+ * @param   cchBuf      The size of the output buffer.
+ * @param   pvUser      The user argument.
+ */
+typedef DECLCALLBACK(size_t) FNRTLOGPREFIX(PRTLOGGER pLogger, char *pchBuf, size_t cchBuf, void *pvUser);
+/** Pointer to prefix callback function. */
+typedef FNRTLOGPREFIX *PFNRTLOGPREFIX;
+
+
+
+/**
+ * Logger instance structure for raw-mode context (RC).
+ */
+struct RTLOGGERRC
+{
+    /** Pointer to temporary scratch buffer.
+     * This is used to format the log messages. */
+    char                    achScratch[32768];
+    /** Current scratch buffer position. */
+    uint32_t                offScratch;
+    /** This is set if a prefix is pending. */
+    bool                    fPendingPrefix;
+    bool                    afAlignment[3];
+    /** Pointer to the logger function.
+     * This is actually pointer to a wrapper which will push a pointer to the
+     * instance pointer onto the stack before jumping to the real logger function.
+     * A very unfortunate hack to work around the missing variadic macro support in C++. */
+    RCPTRTYPE(PFNRTLOGGER)  pfnLogger;
+    /** Pointer to the flush function. */
+    PFNRTLOGFLUSHGC         pfnFlush;
+    /** Magic number (RTLOGGERRC_MAGIC). */
+    uint32_t                u32Magic;
+    /** Logger instance flags - RTLOGFLAGS. */
+    uint32_t                fFlags;
+    /** Number of groups in the afGroups member. */
+    uint32_t                cGroups;
+    /** Group flags array - RTLOGGRPFLAGS.
+     * This member have variable length and may extend way beyond
+     * the declared size of 1 entry. */
+    uint32_t                afGroups[1];
+};
+
+/** RTLOGGERRC::u32Magic value. (John Rogers Searle) */
+#define RTLOGGERRC_MAGIC    0x19320731
+
+
+
+#ifndef IN_RC
+
+/** Pointer to internal logger bits. */
+typedef struct RTLOGGERINTERNAL *PRTLOGGERINTERNAL;
+
+/**
+ * Logger instance structure.
+ */
+struct RTLOGGER
+{
+    /** Pointer to temporary scratch buffer.
+     * This is used to format the log messages. */
+    char                    achScratch[49152];
+    /** Current scratch buffer position. */
+    uint32_t                offScratch;
+    /** Magic number. */
+    uint32_t                u32Magic;
+    /** Logger instance flags - RTLOGFLAGS. */
+    uint32_t                fFlags;
+    /** Destination flags - RTLOGDEST. */
+    uint32_t                fDestFlags;
+    /** Pointer to the internal bits of the logger.
+     * (The memory is allocated in the same block as RTLOGGER.) */
+    PRTLOGGERINTERNAL       pInt;
+    /** Pointer to the logger function (used in non-C99 mode only).
+     *
+     * This is actually pointer to a wrapper which will push a pointer to the
+     * instance pointer onto the stack before jumping to the real logger function.
+     * A very unfortunate hack to work around the missing variadic macro
+     * support in older C++/C standards.  (The memory is allocated using
+     * RTMemExecAlloc(), except for agnostic R0 code.) */
+    PFNRTLOGGER             pfnLogger;
+    /** Number of groups in the afGroups and papszGroups members. */
+    uint32_t                cGroups;
+    /** Group flags array - RTLOGGRPFLAGS.
+     * This member have variable length and may extend way beyond
+     * the declared size of 1 entry. */
+    uint32_t                afGroups[1];
+};
+
+/** RTLOGGER::u32Magic value. (Avram Noam Chomsky) */
+# define RTLOGGER_MAGIC     UINT32_C(0x19281207)
+
+#endif /* !IN_RC */
+
+
+/**
+ * Logger flags.
+ */
+typedef enum RTLOGFLAGS
+{
+    /** The logger instance is disabled for normal output. */
+    RTLOGFLAGS_DISABLED             = 0x00000001,
+    /** The logger instance is using buffered output. */
+    RTLOGFLAGS_BUFFERED             = 0x00000002,
+    /** The logger instance expands LF to CR/LF. */
+    RTLOGFLAGS_USECRLF              = 0x00000010,
+    /** Append to the log destination where applicable. */
+    RTLOGFLAGS_APPEND               = 0x00000020,
+    /** Show relative timestamps with PREFIX_TSC and PREFIX_TS */
+    RTLOGFLAGS_REL_TS               = 0x00000040,
+    /** Show decimal timestamps with PREFIX_TSC and PREFIX_TS */
+    RTLOGFLAGS_DECIMAL_TS           = 0x00000080,
+    /** Open the file in write through mode. */
+    RTLOGFLAGS_WRITE_THROUGH        = 0x00000100,
+    /** Flush the file to disk when flushing the buffer. */
+    RTLOGFLAGS_FLUSH                = 0x00000200,
+    /** Restrict the number of log entries per group. */
+    RTLOGFLAGS_RESTRICT_GROUPS      = 0x00000400,
+    /** New lines should be prefixed with the write and read lock counts. */
+    RTLOGFLAGS_PREFIX_LOCK_COUNTS   = 0x00008000,
+    /** New lines should be prefixed with the CPU id (ApicID on intel/amd). */
+    RTLOGFLAGS_PREFIX_CPUID         = 0x00010000,
+    /** New lines should be prefixed with the native process id. */
+    RTLOGFLAGS_PREFIX_PID           = 0x00020000,
+    /** New lines should be prefixed with group flag number causing the output. */
+    RTLOGFLAGS_PREFIX_FLAG_NO       = 0x00040000,
+    /** New lines should be prefixed with group flag name causing the output. */
+    RTLOGFLAGS_PREFIX_FLAG          = 0x00080000,
+    /** New lines should be prefixed with group number. */
+    RTLOGFLAGS_PREFIX_GROUP_NO      = 0x00100000,
+    /** New lines should be prefixed with group name. */
+    RTLOGFLAGS_PREFIX_GROUP         = 0x00200000,
+    /** New lines should be prefixed with the native thread id. */
+    RTLOGFLAGS_PREFIX_TID           = 0x00400000,
+    /** New lines should be prefixed with thread name. */
+    RTLOGFLAGS_PREFIX_THREAD        = 0x00800000,
+    /** New lines should be prefixed with data from a custom callback. */
+    RTLOGFLAGS_PREFIX_CUSTOM        = 0x01000000,
+    /** New lines should be prefixed with formatted timestamp since program start. */
+    RTLOGFLAGS_PREFIX_TIME_PROG     = 0x04000000,
+    /** New lines should be prefixed with formatted timestamp (UCT). */
+    RTLOGFLAGS_PREFIX_TIME          = 0x08000000,
+    /** New lines should be prefixed with milliseconds since program start. */
+    RTLOGFLAGS_PREFIX_MS_PROG       = 0x10000000,
+    /** New lines should be prefixed with timestamp. */
+    RTLOGFLAGS_PREFIX_TSC           = 0x20000000,
+    /** New lines should be prefixed with timestamp. */
+    RTLOGFLAGS_PREFIX_TS            = 0x40000000,
+    /** The prefix mask. */
+    RTLOGFLAGS_PREFIX_MASK          = 0x7dff8000
+} RTLOGFLAGS;
+
+/**
+ * Logger per group flags.
+ *
+ * @remarks We only use the lower 16 bits here.  We'll be combining it with the
+ *          group number in a few places.
+ */
+typedef enum RTLOGGRPFLAGS
+{
+    /** Enabled. */
+    RTLOGGRPFLAGS_ENABLED      = 0x0001,
+    /** Flow logging. */
+    RTLOGGRPFLAGS_FLOW         = 0x0002,
+    /** Warnings logging. */
+    RTLOGGRPFLAGS_WARN         = 0x0004,
+    /* 0x0008 for later. */
+    /** Level 1 logging. */
+    RTLOGGRPFLAGS_LEVEL_1      = 0x0010,
+    /** Level 2 logging. */
+    RTLOGGRPFLAGS_LEVEL_2      = 0x0020,
+    /** Level 3 logging. */
+    RTLOGGRPFLAGS_LEVEL_3      = 0x0040,
+    /** Level 4 logging. */
+    RTLOGGRPFLAGS_LEVEL_4      = 0x0080,
+    /** Level 5 logging. */
+    RTLOGGRPFLAGS_LEVEL_5      = 0x0100,
+    /** Level 6 logging. */
+    RTLOGGRPFLAGS_LEVEL_6      = 0x0200,
+    /** Level 7 logging. */
+    RTLOGGRPFLAGS_LEVEL_7      = 0x0400,
+    /** Level 8 logging. */
+    RTLOGGRPFLAGS_LEVEL_8      = 0x0800,
+    /** Level 9 logging. */
+    RTLOGGRPFLAGS_LEVEL_9      = 0x1000,
+    /** Level 10 logging. */
+    RTLOGGRPFLAGS_LEVEL_10     = 0x2000,
+    /** Level 11 logging. */
+    RTLOGGRPFLAGS_LEVEL_11     = 0x4000,
+    /** Level 12 logging. */
+    RTLOGGRPFLAGS_LEVEL_12     = 0x8000,
+
+    /** Restrict the number of log entries. */
+    RTLOGGRPFLAGS_RESTRICT     = 0x40000000,
+    /** Blow up the type. */
+    RTLOGGRPFLAGS_32BIT_HACK   = 0x7fffffff
+} RTLOGGRPFLAGS;
+
+/**
+ * Logger destination type.
+ */
+typedef enum RTLOGDEST
+{
+    /** Log to file. */
+    RTLOGDEST_FILE          = 0x00000001,
+    /** Log to stdout. */
+    RTLOGDEST_STDOUT        = 0x00000002,
+    /** Log to stderr. */
+    RTLOGDEST_STDERR        = 0x00000004,
+    /** Log to debugger (win32 only). */
+    RTLOGDEST_DEBUGGER      = 0x00000008,
+    /** Log to com port. */
+    RTLOGDEST_COM           = 0x00000010,
+    /** Log a memory ring buffer. */
+    RTLOGDEST_RINGBUF       = 0x00000020,
+    /** Just a dummy flag to be used when no other flag applies. */
+    RTLOGDEST_DUMMY         = 0x20000000,
+    /** Log to a user defined output stream. */
+    RTLOGDEST_USER          = 0x40000000
+} RTLOGDEST;
+
+
+RTDECL(void) RTLogPrintfEx(void *pvInstance, unsigned fFlags, unsigned iGroup,
+                           const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(4, 5);
+
+
+#ifdef DOXYGEN_RUNNING
+# define LOG_DISABLED
+# define LOG_ENABLED
+# define LOG_ENABLE_FLOW
+#endif
+
+/** @def LOG_DISABLED
+ * Use this compile time define to disable all logging macros. It can
+ * be overridden for each of the logging macros by the LOG_ENABLE*
+ * compile time defines.
+ */
+
+/** @def LOG_ENABLED
+ * Use this compile time define to enable logging when not in debug mode
+ * or LOG_DISABLED is set.
+ * This will enabled Log() only.
+ */
+
+/** @def LOG_ENABLE_FLOW
+ * Use this compile time define to enable flow logging when not in
+ * debug mode or LOG_DISABLED is defined.
+ * This will enable LogFlow() only.
+ */
+
+/*
+ * Determine whether logging is enabled and forcefully normalize the indicators.
+ */
+#if (defined(DEBUG) || defined(LOG_ENABLED)) && !defined(LOG_DISABLED)
+# undef  LOG_DISABLED
+# undef  LOG_ENABLED
+# define LOG_ENABLED
+#else
+# undef  LOG_ENABLED
+# undef  LOG_DISABLED
+# define LOG_DISABLED
+#endif
+
+
+/** @def LOG_USE_C99
+ * Governs the use of variadic macros.
+ */
+#ifndef LOG_USE_C99
+# if defined(RT_ARCH_AMD64) || defined(RT_OS_DARWIN) || defined(RT_ARCH_SPARC) || defined(RT_ARCH_SPARC64)
+#  define LOG_USE_C99
+# endif
+#endif
+
+
+/** @name Macros for checking whether a log level is enabled.
+ * @{ */
+/** @def LogIsItEnabled
+ * Checks whether the specified logging group is enabled or not.
+ */
+#ifdef LOG_ENABLED
+# define LogIsItEnabled(a_fFlags, a_iGroup) ( RTLogDefaultInstanceEx(RT_MAKE_U32(a_fFlags, a_iGroup)) != NULL )
+#else
+# define LogIsItEnabled(a_fFlags, a_iGroup) (false)
+#endif
+
+/** @def LogIsEnabled
+ * Checks whether level 1 logging is enabled.
+ */
+#define LogIsEnabled()      LogIsItEnabled(RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP)
+
+/** @def LogIs2Enabled
+ * Checks whether level 2 logging is enabled.
+ */
+#define LogIs2Enabled()     LogIsItEnabled(RTLOGGRPFLAGS_LEVEL_2, LOG_GROUP)
+
+/** @def LogIs3Enabled
+ * Checks whether level 3 logging is enabled.
+ */
+#define LogIs3Enabled()     LogIsItEnabled(RTLOGGRPFLAGS_LEVEL_3, LOG_GROUP)
+
+/** @def LogIs4Enabled
+ * Checks whether level 4 logging is enabled.
+ */
+#define LogIs4Enabled()     LogIsItEnabled(RTLOGGRPFLAGS_LEVEL_4, LOG_GROUP)
+
+/** @def LogIs5Enabled
+ * Checks whether level 5 logging is enabled.
+ */
+#define LogIs5Enabled()     LogIsItEnabled(RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP)
+
+/** @def LogIs6Enabled
+ * Checks whether level 6 logging is enabled.
+ */
+#define LogIs6Enabled()     LogIsItEnabled(RTLOGGRPFLAGS_LEVEL_6, LOG_GROUP)
+
+/** @def LogIs7Enabled
+ * Checks whether level 7 logging is enabled.
+ */
+#define LogIs7Enabled()     LogIsItEnabled(RTLOGGRPFLAGS_LEVEL_7, LOG_GROUP)
+
+/** @def LogIs8Enabled
+ * Checks whether level 8 logging is enabled.
+ */
+#define LogIs8Enabled()     LogIsItEnabled(RTLOGGRPFLAGS_LEVEL_8, LOG_GROUP)
+
+/** @def LogIs9Enabled
+ * Checks whether level 9 logging is enabled.
+ */
+#define LogIs9Enabled()     LogIsItEnabled(RTLOGGRPFLAGS_LEVEL_9, LOG_GROUP)
+
+/** @def LogIs10Enabled
+ * Checks whether level 10 logging is enabled.
+ */
+#define LogIs10Enabled()    LogIsItEnabled(RTLOGGRPFLAGS_LEVEL_10, LOG_GROUP)
+
+/** @def LogIs11Enabled
+ * Checks whether level 11 logging is enabled.
+ */
+#define LogIs11Enabled()    LogIsItEnabled(RTLOGGRPFLAGS_LEVEL_11, LOG_GROUP)
+
+/** @def LogIs12Enabled
+ * Checks whether level 12 logging is enabled.
+ */
+#define LogIs12Enabled()    LogIsItEnabled(RTLOGGRPFLAGS_LEVEL_12, LOG_GROUP)
+
+/** @def LogIsFlowEnabled
+ * Checks whether execution flow logging is enabled.
+ */
+#define LogIsFlowEnabled()  LogIsItEnabled(RTLOGGRPFLAGS_FLOW, LOG_GROUP)
+
+/** @def LogIsWarnEnabled
+ * Checks whether execution flow logging is enabled.
+ */
+#define LogIsWarnEnabled()  LogIsItEnabled(RTLOGGRPFLAGS_WARN, LOG_GROUP)
+/** @} */
+
+
+/** @def LogIt
+ * Write to specific logger if group enabled.
+ */
+#ifdef LOG_ENABLED
+# if defined(LOG_USE_C99)
+#  define _LogRemoveParentheseis(...)                   __VA_ARGS__
+#  define _LogIt(a_fFlags, a_iGroup, ...) \
+   do \
+   { \
+        register PRTLOGGER LogIt_pLogger = RTLogDefaultInstanceEx(RT_MAKE_U32(a_fFlags, a_iGroup)); \
+        if (RT_LIKELY(!LogIt_pLogger)) \
+        {   /* likely */ } \
+        else \
+            RTLogLoggerEx(LogIt_pLogger, a_fFlags, a_iGroup, __VA_ARGS__); \
+   } while (0)
+#  define LogIt(a_fFlags, a_iGroup, fmtargs)            _LogIt(a_fFlags, a_iGroup, _LogRemoveParentheseis fmtargs)
+#  define _LogItAlways(a_fFlags, a_iGroup, ...)          RTLogLoggerEx(NULL, a_fFlags, UINT32_MAX, __VA_ARGS__)
+#  define LogItAlways(a_fFlags, a_iGroup, fmtargs)      _LogItAlways(a_fFlags, a_iGroup, _LogRemoveParentheseis fmtargs)
+        /** @todo invent a flag or something for skipping the group check so we can pass iGroup. LogItAlways. */
+# else
+#  define LogIt(a_fFlags, a_iGroup, fmtargs) \
+    do \
+    { \
+        register PRTLOGGER LogIt_pLogger = RTLogDefaultInstanceEx(RT_MAKE_U32(a_fFlags, a_iGroup)); \
+        if (RT_LIKELY(!LogIt_pLogger)) \
+        {   /* likely */ } \
+        else \
+        { \
+            LogIt_pLogger->pfnLogger fmtargs; \
+        } \
+    } while (0)
+#  define LogItAlways(a_fFlags, a_iGroup, fmtargs) \
+    do \
+    { \
+        register PRTLOGGER LogIt_pLogger = RTLogDefaultInstanceEx(RT_MAKE_U32(0, UINT16_MAX)); \
+        if (LogIt_pLogger) \
+            LogIt_pLogger->pfnLogger fmtargs; \
+    } while (0)
+# endif
+#else
+# define LogIt(a_fFlags, a_iGroup, fmtargs)             do { } while (0)
+# define LogItAlways(a_fFlags, a_iGroup, fmtargs)       do { } while (0)
+# if defined(LOG_USE_C99)
+#  define _LogRemoveParentheseis(...)                   __VA_ARGS__
+#  define _LogIt(a_fFlags, a_iGroup, ...)               do { } while (0)
+#  define _LogItAlways(a_fFlags, a_iGroup, ...)         do { } while (0)
+# endif
+#endif
+
+
+/** @name Basic logging macros
+ * @{ */
+/** @def Log
+ * Level 1 logging that works regardless of the group settings.
+ */
+#define LogAlways(a)    LogItAlways(RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, a)
+
+/** @def Log
+ * Level 1 logging.
+ */
+#define Log(a)          LogIt(RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, a)
+
+/** @def Log2
+ * Level 2 logging.
+ */
+#define Log2(a)         LogIt(RTLOGGRPFLAGS_LEVEL_2,  LOG_GROUP, a)
+
+/** @def Log3
+ * Level 3 logging.
+ */
+#define Log3(a)         LogIt(RTLOGGRPFLAGS_LEVEL_3,  LOG_GROUP, a)
+
+/** @def Log4
+ * Level 4 logging.
+ */
+#define Log4(a)         LogIt(RTLOGGRPFLAGS_LEVEL_4,  LOG_GROUP, a)
+
+/** @def Log5
+ * Level 5 logging.
+ */
+#define Log5(a)         LogIt(RTLOGGRPFLAGS_LEVEL_5,  LOG_GROUP, a)
+
+/** @def Log6
+ * Level 6 logging.
+ */
+#define Log6(a)         LogIt(RTLOGGRPFLAGS_LEVEL_6,  LOG_GROUP, a)
+
+/** @def Log7
+ * Level 7 logging.
+ */
+#define Log7(a)         LogIt(RTLOGGRPFLAGS_LEVEL_7,  LOG_GROUP, a)
+
+/** @def Log8
+ * Level 8 logging.
+ */
+#define Log8(a)         LogIt(RTLOGGRPFLAGS_LEVEL_8,  LOG_GROUP, a)
+
+/** @def Log9
+ * Level 9 logging.
+ */
+#define Log9(a)         LogIt(RTLOGGRPFLAGS_LEVEL_9,  LOG_GROUP, a)
+
+/** @def Log10
+ * Level 10 logging.
+ */
+#define Log10(a)        LogIt(RTLOGGRPFLAGS_LEVEL_10, LOG_GROUP, a)
+
+/** @def Log11
+ * Level 11 logging.
+ */
+#define Log11(a)        LogIt(RTLOGGRPFLAGS_LEVEL_11, LOG_GROUP, a)
+
+/** @def Log12
+ * Level 12 logging.
+ */
+#define Log12(a)        LogIt(RTLOGGRPFLAGS_LEVEL_12,  LOG_GROUP, a)
+
+/** @def LogFlow
+ * Logging of execution flow.
+ */
+#define LogFlow(a)      LogIt(RTLOGGRPFLAGS_FLOW,      LOG_GROUP, a)
+
+/** @def LogWarn
+ * Logging of warnings.
+ */
+#define LogWarn(a)      LogIt(RTLOGGRPFLAGS_WARN,      LOG_GROUP, a)
+/** @} */
+
+
+/** @name Logging macros prefixing the current function name.
+ * @{ */
+/** @def LogFunc
+ * Level 1 logging inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by a
+ * semicolon and space.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define LogFunc(a)   _LogIt(RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, LOG_FN_FMT ": %M", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogFunc(a)   do { Log((LOG_FN_FMT ": ", RT_GCC_EXTENSION __PRETTY_FUNCTION__)); Log(a); } while (0)
+#endif
+
+/** @def Log2Func
+ * Level 2 logging inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by a
+ * semicolon and space.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log2Func(a)  _LogIt(RTLOGGRPFLAGS_LEVEL_2, LOG_GROUP, LOG_FN_FMT ": %M", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log2Func(a)  do { Log2((LOG_FN_FMT ": ", RT_GCC_EXTENSION __PRETTY_FUNCTION__)); Log2(a); } while (0)
+#endif
+
+/** @def Log3Func
+ * Level 3 logging inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by a
+ * semicolon and space.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log3Func(a)  _LogIt(RTLOGGRPFLAGS_LEVEL_3, LOG_GROUP, LOG_FN_FMT ": %M", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log3Func(a)  do { Log3((LOG_FN_FMT ": ", RT_GCC_EXTENSION __PRETTY_FUNCTION__)); Log3(a); } while (0)
+#endif
+
+/** @def Log4Func
+ * Level 4 logging inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by a
+ * semicolon and space.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log4Func(a)  _LogIt(RTLOGGRPFLAGS_LEVEL_4, LOG_GROUP, LOG_FN_FMT ": %M", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log4Func(a)  do { Log4((LOG_FN_FMT ": ", RT_GCC_EXTENSION __PRETTY_FUNCTION__)); Log4(a); } while (0)
+#endif
+
+/** @def Log5Func
+ * Level 5 logging inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by a
+ * semicolon and space.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log5Func(a)  _LogIt(RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP, LOG_FN_FMT ": %M", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log5Func(a)  do { Log5((LOG_FN_FMT ": ", RT_GCC_EXTENSION __PRETTY_FUNCTION__)); Log5(a); } while (0)
+#endif
+
+/** @def Log6Func
+ * Level 6 logging inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by a
+ * semicolon and space.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log6Func(a)  _LogIt(RTLOGGRPFLAGS_LEVEL_6, LOG_GROUP, LOG_FN_FMT ": %M", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log6Func(a)  do { Log6((LOG_FN_FMT ": ", RT_GCC_EXTENSION __PRETTY_FUNCTION__)); Log6(a); } while (0)
+#endif
+
+/** @def Log7Func
+ * Level 7 logging inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by a
+ * semicolon and space.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log7Func(a)  _LogIt(RTLOGGRPFLAGS_LEVEL_7, LOG_GROUP, LOG_FN_FMT ": %M", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log7Func(a)  do { Log7((LOG_FN_FMT ": ", RT_GCC_EXTENSION __PRETTY_FUNCTION__)); Log7(a); } while (0)
+#endif
+
+/** @def Log8Func
+ * Level 8 logging inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by a
+ * semicolon and space.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log8Func(a)  _LogIt(RTLOGGRPFLAGS_LEVEL_8, LOG_GROUP, LOG_FN_FMT ": %M", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log8Func(a)  do { Log8((LOG_FN_FMT ": ", RT_GCC_EXTENSION __PRETTY_FUNCTION__)); Log8(a); } while (0)
+#endif
+
+/** @def Log9Func
+ * Level 9 logging inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by a
+ * semicolon and space.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log9Func(a)  _LogIt(RTLOGGRPFLAGS_LEVEL_9, LOG_GROUP, LOG_FN_FMT ": %M", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log9Func(a)  do { Log9((LOG_FN_FMT ": ", RT_GCC_EXTENSION __PRETTY_FUNCTION__)); Log9(a); } while (0)
+#endif
+
+/** @def Log10Func
+ * Level 10 logging inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by a
+ * semicolon and space.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log10Func(a) _LogIt(RTLOGGRPFLAGS_LEVEL_10, LOG_GROUP, LOG_FN_FMT ": %M", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log10Func(a) do { Log10((LOG_FN_FMT ": ", RT_GCC_EXTENSION __PRETTY_FUNCTION__)); Log10(a); } while (0)
+#endif
+
+/** @def Log11Func
+ * Level 11 logging inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by a
+ * semicolon and space.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log11Func(a) _LogIt(RTLOGGRPFLAGS_LEVEL_11, LOG_GROUP, LOG_FN_FMT ": %M", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log11Func(a) do { Log11((LOG_FN_FMT ": ", RT_GCC_EXTENSION __PRETTY_FUNCTION__)); Log11(a); } while (0)
+#endif
+
+/** @def Log12Func
+ * Level 12 logging inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by a
+ * semicolon and space.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log12Func(a) _LogIt(RTLOGGRPFLAGS_LEVEL_12, LOG_GROUP, LOG_FN_FMT ": %M", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log12Func(a) do { Log12((LOG_FN_FMT ": ", RT_GCC_EXTENSION __PRETTY_FUNCTION__)); Log12(a); } while (0)
+#endif
+
+/** @def LogFlowFunc
+ * Macro to log the execution flow inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by
+ * a semicolon and space.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define LogFlowFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_FLOW, LOG_GROUP, LOG_FN_FMT ": %M", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogFlowFunc(a) \
+    do { LogFlow((LOG_FN_FMT ": ", RT_GCC_EXTENSION __PRETTY_FUNCTION__)); LogFlow(a); } while (0)
+#endif
+
+/** @def LogWarnFunc
+ * Macro to log a warning inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by
+ * a semicolon and space.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define LogWarnFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_WARN, LOG_GROUP, LOG_FN_FMT ": %M", __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogWarnFunc(a) \
+    do { LogFlow((LOG_FN_FMT ": ", __PRETTY_FUNCTION__)); LogFlow(a); } while (0)
+#endif
+/** @} */
+
+
+/** @name Logging macros prefixing the this pointer value and method name.
+ * @{ */
+
+/** @def LogThisFunc
+ * Level 1 logging inside a C++ non-static method, with object pointer and
+ * method name prefixed to the given message.
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define LogThisFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogThisFunc(a) do { Log(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); Log(a); } while (0)
+#endif
+
+/** @def Log2ThisFunc
+ * Level 2 logging inside a C++ non-static method, with object pointer and
+ * method name prefixed to the given message.
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log2ThisFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_LEVEL_2, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log2ThisFunc(a) do { Log2(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); Log2(a); } while (0)
+#endif
+
+/** @def Log3ThisFunc
+ * Level 3 logging inside a C++ non-static method, with object pointer and
+ * method name prefixed to the given message.
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log3ThisFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_LEVEL_3, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log3ThisFunc(a) do { Log3(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); Log3(a); } while (0)
+#endif
+
+/** @def Log4ThisFunc
+ * Level 4 logging inside a C++ non-static method, with object pointer and
+ * method name prefixed to the given message.
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log4ThisFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_LEVEL_4, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log4ThisFunc(a) do { Log4(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); Log4(a); } while (0)
+#endif
+
+/** @def Log5ThisFunc
+ * Level 5 logging inside a C++ non-static method, with object pointer and
+ * method name prefixed to the given message.
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log5ThisFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log5ThisFunc(a) do { Log5(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); Log5(a); } while (0)
+#endif
+
+/** @def Log6ThisFunc
+ * Level 6 logging inside a C++ non-static method, with object pointer and
+ * method name prefixed to the given message.
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log6ThisFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_LEVEL_6, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log6ThisFunc(a) do { Log6(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); Log6(a); } while (0)
+#endif
+
+/** @def Log7ThisFunc
+ * Level 7 logging inside a C++ non-static method, with object pointer and
+ * method name prefixed to the given message.
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log7ThisFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_LEVEL_7, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log7ThisFunc(a) do { Log7(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); Log7(a); } while (0)
+#endif
+
+/** @def Log8ThisFunc
+ * Level 8 logging inside a C++ non-static method, with object pointer and
+ * method name prefixed to the given message.
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log8ThisFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_LEVEL_8, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log8ThisFunc(a) do { Log8(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); Log8(a); } while (0)
+#endif
+
+/** @def Log9ThisFunc
+ * Level 9 logging inside a C++ non-static method, with object pointer and
+ * method name prefixed to the given message.
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log9ThisFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_LEVEL_9, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log9ThisFunc(a) do { Log9(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); Log9(a); } while (0)
+#endif
+
+/** @def Log10ThisFunc
+ * Level 10 logging inside a C++ non-static method, with object pointer and
+ * method name prefixed to the given message.
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log10ThisFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_LEVEL_10, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log10ThisFunc(a) do { Log10(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); Log10(a); } while (0)
+#endif
+
+/** @def Log11ThisFunc
+ * Level 11 logging inside a C++ non-static method, with object pointer and
+ * method name prefixed to the given message.
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log11ThisFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_LEVEL_11, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log11ThisFunc(a) do { Log11(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); Log11(a); } while (0)
+#endif
+
+/** @def Log12ThisFunc
+ * Level 12 logging inside a C++ non-static method, with object pointer and
+ * method name prefixed to the given message.
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log12ThisFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_LEVEL_12, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log12ThisFunc(a) do { Log12(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); Log12(a); } while (0)
+#endif
+
+/** @def LogFlowThisFunc
+ * Flow level logging inside a C++ non-static method, with object pointer and
+ * method name prefixed to the given message.
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define LogFlowThisFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_FLOW, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogFlowThisFunc(a) do { LogFlow(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); LogFlow(a); } while (0)
+#endif
+
+/** @def LogWarnThisFunc
+ * Warning level logging inside a C++ non-static method, with object pointer and
+ * method name prefixed to the given message.
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define LogWarnThisFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_WARN, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogWarnThisFunc(a) do { LogWarn(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); LogWarn(a); } while (0)
+#endif
+/** @} */
+
+
+/** @name Misc Logging Macros
+ * @{ */
+
+/** @def Log1Warning
+ * The same as Log(), but prepents a <tt>"WARNING! "</tt> string to the message.
+ *
+ * @param   a   Custom log message in format <tt>("string\n" [, args])</tt>.
+ */
+#if defined(LOG_USE_C99)
+# define Log1Warning(a)     _LogIt(RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, "WARNING! %M", _LogRemoveParentheseis a )
+#else
+# define Log1Warning(a)     do { Log(("WARNING! ")); Log(a); } while (0)
+#endif
+
+/** @def Log1WarningFunc
+ * The same as LogWarning(), but prepents the log message with the function name.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log1WarningFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, LOG_FN_FMT ": WARNING! %M", __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log1WarningFunc(a) \
+    do { Log((LOG_FN_FMT ": WARNING! ", __PRETTY_FUNCTION__)); Log(a); } while (0)
+#endif
+
+/** @def Log1WarningThisFunc
+ * The same as LogWarningFunc() but for class functions (methods): the resulting
+ * log line is additionally prepended with a hex value of |this| pointer.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define Log1WarningThisFunc(a) \
+    _LogIt(RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, "{%p} " LOG_FN_FMT ": WARNING! %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log1WarningThisFunc(a) \
+    do { Log(("{%p} " LOG_FN_FMT ": WARNING! ", this, __PRETTY_FUNCTION__)); Log(a); } while (0)
+#endif
+
+
+/** Shortcut to |LogFlowFunc ("ENTER\n")|, marks the beginnig of the function. */
+#define LogFlowFuncEnter()      LogFlowFunc(("ENTER\n"))
+
+/** Shortcut to |LogFlowFunc ("LEAVE\n")|, marks the end of the function. */
+#define LogFlowFuncLeave()      LogFlowFunc(("LEAVE\n"))
+
+/** Shortcut to |LogFlowFunc ("LEAVE: %Rrc\n")|, marks the end of the function. */
+#define LogFlowFuncLeaveRC(rc)  LogFlowFunc(("LEAVE: %Rrc\n", (rc)))
+
+/** Shortcut to |LogFlowThisFunc ("ENTER\n")|, marks the beginnig of the function. */
+#define LogFlowThisFuncEnter()  LogFlowThisFunc(("ENTER\n"))
+
+/** Shortcut to |LogFlowThisFunc ("LEAVE\n")|, marks the end of the function. */
+#define LogFlowThisFuncLeave()  LogFlowThisFunc(("LEAVE\n"))
+
+
+/** @def LogObjRefCnt
+ * Helper macro to print the current reference count of the given COM object
+ * to the log file.
+ *
+ * @param pObj  Pointer to the object in question (must be a pointer to an
+ *              IUnknown subclass or simply define COM-style AddRef() and
+ *              Release() methods)
+ */
+#define LogObjRefCnt(pObj) \
+    do { \
+        if (LogIsFlowEnabled()) \
+        { \
+            int cRefsForLog = (pObj)->AddRef(); \
+            LogFlow((#pObj "{%p}.refCnt=%d\n", (pObj), cRefsForLog - 1)); \
+            (pObj)->Release(); \
+        } \
+    } while (0)
+/** @} */
+
+
+
+/** @name Passing Function Call Position When Logging.
+ *
+ * This is a little bit ugly as we have to omit the comma before the
+ * position parameters so that we don't inccur any overhead in non-logging
+ * builds (!defined(LOG_ENABLED).
+ *
+ * @{  */
+/** Source position for passing to a function call. */
+#ifdef LOG_ENABLED
+# define RTLOG_COMMA_SRC_POS        , __FILE__, __LINE__, __PRETTY_FUNCTION__
+#else
+# define RTLOG_COMMA_SRC_POS        RT_NOTHING
+#endif
+/** Source position declaration. */
+#ifdef LOG_ENABLED
+# define RTLOG_COMMA_SRC_POS_DECL   , const char *pszFile, unsigned iLine, const char *pszFunction
+#else
+# define RTLOG_COMMA_SRC_POS_DECL   RT_NOTHING
+#endif
+/** Source position arguments. */
+#ifdef LOG_ENABLED
+# define RTLOG_COMMA_SRC_POS_ARGS   , pszFile, iLine, pszFunction
+#else
+# define RTLOG_COMMA_SRC_POS_ARGS   RT_NOTHING
+#endif
+/** Applies NOREF() to the source position arguments. */
+#ifdef LOG_ENABLED
+# define RTLOG_SRC_POS_NOREF()      do { NOREF(pszFile); NOREF(iLine); NOREF(pszFunction); } while (0)
+#else
+# define RTLOG_SRC_POS_NOREF()      do { } while (0)
+#endif
+/** @}  */
+
+
+
+/** @name Release Logging
+ * @{
+ */
+
+#ifdef DOXYGEN_RUNNING
+# define RTLOG_REL_DISABLED
+# define RTLOG_REL_ENABLED
+#endif
+
+/** @def RTLOG_REL_DISABLED
+ * Use this compile time define to disable all release logging
+ * macros.
+ */
+
+/** @def RTLOG_REL_ENABLED
+ * Use this compile time define to override RTLOG_REL_DISABLE.
+ */
+
+/*
+ * Determine whether release logging is enabled and forcefully normalize the indicators.
+ */
+#if !defined(RTLOG_REL_DISABLED) || defined(RTLOG_REL_ENABLED)
+# undef  RTLOG_REL_DISABLED
+# undef  RTLOG_REL_ENABLED
+# define RTLOG_REL_ENABLED
+#else
+# undef  RTLOG_REL_ENABLED
+# undef  RTLOG_REL_DISABLED
+# define RTLOG_REL_DISABLED
+#endif
+
+/** @name Macros for checking whether a release log level is enabled.
+ * @{ */
+/** @def LogRelIsItEnabled
+ * Checks whether the specified release logging group is enabled or not.
+ */
+#define LogRelIsItEnabled(a_fFlags, a_iGroup) ( RTLogRelGetDefaultInstanceEx(RT_MAKE_U32(a_fFlags, a_iGroup)) != NULL )
+
+/** @def LogRelIsEnabled
+ * Checks whether level 1 release logging is enabled.
+ */
+#define LogRelIsEnabled()      LogRelIsItEnabled(RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP)
+
+/** @def LogRelIs2Enabled
+ * Checks whether level 2 release logging is enabled.
+ */
+#define LogRelIs2Enabled()     LogRelIsItEnabled(RTLOGGRPFLAGS_LEVEL_2, LOG_GROUP)
+
+/** @def LogRelIs3Enabled
+ * Checks whether level 3 release logging is enabled.
+ */
+#define LogRelIs3Enabled()     LogRelIsItEnabled(RTLOGGRPFLAGS_LEVEL_3, LOG_GROUP)
+
+/** @def LogRelIs4Enabled
+ * Checks whether level 4 release logging is enabled.
+ */
+#define LogRelIs4Enabled()     LogRelIsItEnabled(RTLOGGRPFLAGS_LEVEL_4, LOG_GROUP)
+
+/** @def LogRelIs5Enabled
+ * Checks whether level 5 release logging is enabled.
+ */
+#define LogRelIs5Enabled()     LogRelIsItEnabled(RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP)
+
+/** @def LogRelIs6Enabled
+ * Checks whether level 6 release logging is enabled.
+ */
+#define LogRelIs6Enabled()     LogRelIsItEnabled(RTLOGGRPFLAGS_LEVEL_6, LOG_GROUP)
+
+/** @def LogRelIs7Enabled
+ * Checks whether level 7 release logging is enabled.
+ */
+#define LogRelIs7Enabled()     LogRelIsItEnabled(RTLOGGRPFLAGS_LEVEL_7, LOG_GROUP)
+
+/** @def LogRelIs8Enabled
+ * Checks whether level 8 release logging is enabled.
+ */
+#define LogRelIs8Enabled()     LogRelIsItEnabled(RTLOGGRPFLAGS_LEVEL_8, LOG_GROUP)
+
+/** @def LogRelIs2Enabled
+ * Checks whether level 9 release logging is enabled.
+ */
+#define LogRelIs9Enabled()     LogRelIsItEnabled(RTLOGGRPFLAGS_LEVEL_9, LOG_GROUP)
+
+/** @def LogRelIs10Enabled
+ * Checks whether level 10 release logging is enabled.
+ */
+#define LogRelIs10Enabled()    LogRelIsItEnabled(RTLOGGRPFLAGS_LEVEL_10, LOG_GROUP)
+
+/** @def LogRelIs11Enabled
+ * Checks whether level 10 release logging is enabled.
+ */
+#define LogRelIs11Enabled()    LogRelIsItEnabled(RTLOGGRPFLAGS_LEVEL_11, LOG_GROUP)
+
+/** @def LogRelIs12Enabled
+ * Checks whether level 12 release logging is enabled.
+ */
+#define LogRelIs12Enabled()    LogRelIsItEnabled(RTLOGGRPFLAGS_LEVEL_12, LOG_GROUP)
+
+/** @def LogRelIsFlowEnabled
+ * Checks whether execution flow release logging is enabled.
+ */
+#define LogRelIsFlowEnabled()  LogRelIsItEnabled(RTLOGGRPFLAGS_FLOW, LOG_GROUP)
+
+/** @def LogRelIsWarnEnabled
+ * Checks whether warning level release logging is enabled.
+ */
+#define LogRelIsWarnEnabled()  LogRelIsItEnabled(RTLOGGRPFLAGS_FLOW, LOG_GROUP)
+/** @} */
+
+
+/** @def LogRelIt
+ * Write to specific logger if group enabled.
+ */
+/** @def LogRelItLikely
+ * Write to specific logger if group enabled, assuming it likely it is enabled.
+ */
+/** @def LogRelMaxIt
+ * Write to specific logger if group enabled and at less than a_cMax messages
+ * have hit the log.  Uses a static variable to count.
+ */
+#ifdef RTLOG_REL_ENABLED
+# if defined(LOG_USE_C99)
+#  define _LogRelRemoveParentheseis(...)                    __VA_ARGS__
+#  define _LogRelIt(a_fFlags, a_iGroup, ...) \
+    do \
+    { \
+        PRTLOGGER LogRelIt_pLogger = RTLogRelGetDefaultInstanceEx(RT_MAKE_U32(a_fFlags, a_iGroup)); \
+        if (RT_LIKELY(!LogRelIt_pLogger)) \
+        { /* likely */ } \
+        else \
+            RTLogLoggerEx(LogRelIt_pLogger, a_fFlags, a_iGroup, __VA_ARGS__); \
+        _LogIt(a_fFlags, a_iGroup, __VA_ARGS__); \
+    } while (0)
+#  define LogRelIt(a_fFlags, a_iGroup, fmtargs) \
+    _LogRelIt(a_fFlags, a_iGroup, _LogRelRemoveParentheseis fmtargs)
+#  define _LogRelItLikely(a_fFlags, a_iGroup, ...) \
+    do \
+    { \
+        PRTLOGGER LogRelIt_pLogger = RTLogRelGetDefaultInstanceEx(RT_MAKE_U32(a_fFlags, a_iGroup)); \
+        if (LogRelIt_pLogger) \
+            RTLogLoggerEx(LogRelIt_pLogger, a_fFlags, a_iGroup, __VA_ARGS__); \
+        _LogIt(a_fFlags, a_iGroup, __VA_ARGS__); \
+    } while (0)
+#  define LogRelItLikely(a_fFlags, a_iGroup, fmtargs) \
+    _LogRelItLikely(a_fFlags, a_iGroup, _LogRelRemoveParentheseis fmtargs)
+#  define _LogRelMaxIt(a_cMax, a_fFlags, a_iGroup, ...) \
+    do \
+    { \
+        PRTLOGGER LogRelIt_pLogger = RTLogRelGetDefaultInstanceEx(RT_MAKE_U32(a_fFlags, a_iGroup)); \
+        if (LogRelIt_pLogger) \
+        { \
+            static uint32_t s_LogRelMaxIt_cLogged = 0; \
+            if (s_LogRelMaxIt_cLogged < (a_cMax)) \
+            { \
+                s_LogRelMaxIt_cLogged++; \
+                RTLogLoggerEx(LogRelIt_pLogger, a_fFlags, a_iGroup, __VA_ARGS__); \
+            } \
+        } \
+        _LogIt(a_fFlags, a_iGroup, __VA_ARGS__); \
+    } while (0)
+#  define LogRelMaxIt(a_cMax, a_fFlags, a_iGroup, fmtargs) \
+    _LogRelMaxIt(a_cMax, a_fFlags, a_iGroup, _LogRelRemoveParentheseis fmtargs)
+# else
+#  define LogRelItLikely(a_fFlags, a_iGroup, fmtargs) \
+   do \
+   { \
+       PRTLOGGER LogRelIt_pLogger = RTLogRelGetDefaultInstanceEx(RT_MAKE_U32(a_fFlags, a_iGroup)); \
+       if (LogRelIt_pLogger) \
+       { \
+           LogRelIt_pLogger->pfnLogger fmtargs; \
+       } \
+       LogIt(a_fFlags, a_iGroup, fmtargs); \
+  } while (0)
+#  define LogRelIt(a_fFlags, a_iGroup, fmtargs) \
+   do \
+   { \
+       PRTLOGGER LogRelIt_pLogger = RTLogRelGetDefaultInstanceEx(RT_MAKE_U32(a_fFlags, a_iGroup)); \
+       if (RT_LIKELY(!LogRelIt_pLogger)) \
+       { /* likely */ } \
+       else \
+       { \
+           LogRelIt_pLogger->pfnLogger fmtargs; \
+       } \
+       LogIt(a_fFlags, a_iGroup, fmtargs); \
+  } while (0)
+#  define LogRelMaxIt(a_cMax, a_fFlags, a_iGroup, fmtargs) \
+   do \
+   { \
+       PRTLOGGER LogRelIt_pLogger = RTLogRelGetDefaultInstanceEx(RT_MAKE_U32(a_fFlags, a_iGroup)); \
+       if (LogRelIt_pLogger) \
+       { \
+           static uint32_t s_LogRelMaxIt_cLogged = 0; \
+           if (s_LogRelMaxIt_cLogged < (a_cMax)) \
+           { \
+               s_LogRelMaxIt_cLogged++; \
+               LogRelIt_pLogger->pfnLogger fmtargs; \
+           } \
+       } \
+       LogIt(a_fFlags, a_iGroup, fmtargs); \
+  } while (0)
+# endif
+#else   /* !RTLOG_REL_ENABLED */
+# define LogRelIt(a_fFlags, a_iGroup, fmtargs)              do { } while (0)
+# define LogRelItLikely(a_fFlags, a_iGroup, fmtargs)        do { } while (0)
+# define LogRelMaxIt(a_cMax, a_fFlags, a_iGroup, fmtargs)   do { } while (0)
+# if defined(LOG_USE_C99)
+#  define _LogRelRemoveParentheseis(...)                    __VA_ARGS__
+#  define _LogRelIt(a_fFlags, a_iGroup, ...)                do { } while (0)
+#  define _LogRelItLikely(a_fFlags, a_iGroup, ...)          do { } while (0)
+#  define _LogRelMaxIt(a_cMax, a_fFlags, a_iGroup, ...)     do { } while (0)
+# endif
+#endif  /* !RTLOG_REL_ENABLED */
+
+
+/** @name Basic release logging macros
+ * @{ */
+/** @def LogRel
+ * Level 1 release logging.
+ */
+#define LogRel(a)           LogRelItLikely(RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, a)
+
+/** @def LogRel2
+ * Level 2 release logging.
+ */
+#define LogRel2(a)          LogRelIt(RTLOGGRPFLAGS_LEVEL_2,  LOG_GROUP, a)
+
+/** @def LogRel3
+ * Level 3 release logging.
+ */
+#define LogRel3(a)          LogRelIt(RTLOGGRPFLAGS_LEVEL_3,  LOG_GROUP, a)
+
+/** @def LogRel4
+ * Level 4 release logging.
+ */
+#define LogRel4(a)          LogRelIt(RTLOGGRPFLAGS_LEVEL_4,  LOG_GROUP, a)
+
+/** @def LogRel5
+ * Level 5 release logging.
+ */
+#define LogRel5(a)          LogRelIt(RTLOGGRPFLAGS_LEVEL_5,  LOG_GROUP, a)
+
+/** @def LogRel6
+ * Level 6 release logging.
+ */
+#define LogRel6(a)          LogRelIt(RTLOGGRPFLAGS_LEVEL_6,  LOG_GROUP, a)
+
+/** @def LogRel7
+ * Level 7 release logging.
+ */
+#define LogRel7(a)          LogRelIt(RTLOGGRPFLAGS_LEVEL_7,  LOG_GROUP, a)
+
+/** @def LogRel8
+ * Level 8 release logging.
+ */
+#define LogRel8(a)          LogRelIt(RTLOGGRPFLAGS_LEVEL_8,  LOG_GROUP, a)
+
+/** @def LogRel9
+ * Level 9 release logging.
+ */
+#define LogRel9(a)          LogRelIt(RTLOGGRPFLAGS_LEVEL_9,  LOG_GROUP, a)
+
+/** @def LogRel10
+ * Level 10 release logging.
+ */
+#define LogRel10(a)         LogRelIt(RTLOGGRPFLAGS_LEVEL_10, LOG_GROUP, a)
+
+/** @def LogRel11
+ * Level 11 release logging.
+ */
+#define LogRel11(a)         LogRelIt(RTLOGGRPFLAGS_LEVEL_11, LOG_GROUP, a)
+
+/** @def LogRel12
+ * Level 12 release logging.
+ */
+#define LogRel12(a)         LogRelIt(RTLOGGRPFLAGS_LEVEL_12, LOG_GROUP, a)
+
+/** @def LogRelFlow
+ * Logging of execution flow.
+ */
+#define LogRelFlow(a)       LogRelIt(RTLOGGRPFLAGS_FLOW,     LOG_GROUP, a)
+
+/** @def LogRelWarn
+ * Warning level release logging.
+ */
+#define LogRelWarn(a)       LogRelIt(RTLOGGRPFLAGS_WARN,     LOG_GROUP, a)
+/** @} */
+
+
+
+/** @name Basic release logging macros with local max
+ * @{ */
+/** @def LogRelMax
+ * Level 1 release logging with a max number of log entries.
+ */
+#define LogRelMax(a_cMax, a)        LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, a)
+
+/** @def LogRelMax2
+ * Level 2 release logging with a max number of log entries.
+ */
+#define LogRelMax2(a_cMax, a)       LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_LEVEL_2,  LOG_GROUP, a)
+
+/** @def LogRelMax3
+ * Level 3 release logging with a max number of log entries.
+ */
+#define LogRelMax3(a_cMax, a)       LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_LEVEL_3,  LOG_GROUP, a)
+
+/** @def LogRelMax4
+ * Level 4 release logging with a max number of log entries.
+ */
+#define LogRelMax4(a_cMax, a)       LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_LEVEL_4,  LOG_GROUP, a)
+
+/** @def LogRelMax5
+ * Level 5 release logging with a max number of log entries.
+ */
+#define LogRelMax5(a_cMax, a)       LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_LEVEL_5,  LOG_GROUP, a)
+
+/** @def LogRelMax6
+ * Level 6 release logging with a max number of log entries.
+ */
+#define LogRelMax6(a_cMax, a)       LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_LEVEL_6,  LOG_GROUP, a)
+
+/** @def LogRelMax7
+ * Level 7 release logging with a max number of log entries.
+ */
+#define LogRelMax7(a_cMax, a)       LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_LEVEL_7,  LOG_GROUP, a)
+
+/** @def LogRelMax8
+ * Level 8 release logging with a max number of log entries.
+ */
+#define LogRelMax8(a_cMax, a)       LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_LEVEL_8,  LOG_GROUP, a)
+
+/** @def LogRelMax9
+ * Level 9 release logging with a max number of log entries.
+ */
+#define LogRelMax9(a_cMax, a)       LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_LEVEL_9,  LOG_GROUP, a)
+
+/** @def LogRelMax10
+ * Level 10 release logging with a max number of log entries.
+ */
+#define LogRelMax10(a_cMax, a)      LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_LEVEL_10, LOG_GROUP, a)
+
+/** @def LogRelMax11
+ * Level 11 release logging with a max number of log entries.
+ */
+#define LogRelMax11(a_cMax, a)      LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_LEVEL_11, LOG_GROUP, a)
+
+/** @def LogRelMax12
+ * Level 12 release logging with a max number of log entries.
+ */
+#define LogRelMax12(a_cMax, a)      LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_LEVEL_12, LOG_GROUP, a)
+
+/** @def LogRelMaxFlow
+ * Logging of execution flow with a max number of log entries.
+ */
+#define LogRelMaxFlow(a_cMax, a)    LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_FLOW,     LOG_GROUP, a)
+/** @} */
+
+
+/** @name Release logging macros prefixing the current function name.
+ * @{ */
+
+/** @def LogRelFunc
+ * Release logging.  Prepends the given log message with the function name
+ * followed by a semicolon and space.
+ */
+#ifdef LOG_USE_C99
+# define LogRelFunc(a) \
+    _LogRelItLikely(RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, LOG_FN_FMT ": %M", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogRelFunc(a)      do { LogRel((LOG_FN_FMT ": ", RT_GCC_EXTENSION __PRETTY_FUNCTION__)); LogRel(a); } while (0)
+#endif
+
+/** @def LogRelFlowFunc
+ * Release logging.  Macro to log the execution flow inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by
+ * a semicolon and space.
+ *
+ * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define LogRelFlowFunc(a)  _LogRelIt(RTLOGGRPFLAGS_FLOW, LOG_GROUP, LOG_FN_FMT ": %M", __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogRelFlowFunc(a)  do { LogRelFlow((LOG_FN_FMT ": ", __PRETTY_FUNCTION__)); LogRelFlow(a); } while (0)
+#endif
+
+/** @def LogRelMaxFunc
+ * Release logging.  Prepends the given log message with the function name
+ * followed by a semicolon and space.
+ */
+#ifdef LOG_USE_C99
+# define LogRelMaxFunc(a_cMax, a) \
+    _LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, LOG_FN_FMT ": %M", __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogRelMaxFunc(a_cMax, a) \
+    do { LogRelMax(a_cMax, (LOG_FN_FMT ": ", __PRETTY_FUNCTION__)); LogRelMax(a_cMax, a); } while (0)
+#endif
+
+/** @def LogRelMaxFlowFunc
+ * Release logging.  Macro to log the execution flow inside C/C++ functions.
+ *
+ * Prepends the given log message with the function name followed by
+ * a semicolon and space.
+ *
+ * @param   a_cMax  Max number of times this should hit the log.
+ * @param   a       Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define LogRelMaxFlowFunc(a_cMax, a) \
+    _LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_FLOW, LOG_GROUP, LOG_FN_FMT ": %M", __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogRelMaxFlowFunc(a_cMax, a) \
+    do { LogRelMaxFlow(a_cMax, (LOG_FN_FMT ": ", __PRETTY_FUNCTION__)); LogRelFlow(a_cMax, a); } while (0)
+#endif
+
+/** @} */
+
+
+/** @name Release Logging macros prefixing the this pointer value and method name.
+ * @{ */
+
+/** @def LogRelThisFunc
+ * The same as LogRelFunc but for class functions (methods): the resulting log
+ * line is additionally prepended with a hex value of |this| pointer.
+ */
+#ifdef LOG_USE_C99
+# define LogRelThisFunc(a) \
+    _LogRelItLikely(RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogRelThisFunc(a) \
+    do { LogRel(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); LogRel(a); } while (0)
+#endif
+
+/** @def LogRelMaxThisFunc
+ * The same as LogRelFunc but for class functions (methods): the resulting log
+ * line is additionally prepended with a hex value of |this| pointer.
+ * @param   a_cMax  Max number of times this should hit the log.
+ * @param   a       Log message in format <tt>("string\n" [, args])</tt>.
+ */
+#ifdef LOG_USE_C99
+# define LogRelMaxThisFunc(a_cMax, a) \
+    _LogRelMaxIt(a_cMax, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogRelMaxThisFunc(a_cMax, a) \
+    do { LogRelMax(a_cMax, ("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); LogRelMax(a_cMax, a); } while (0)
+#endif
+
+/** @} */
+
+
+#ifndef IN_RC
+/**
+ * Sets the default release logger instance.
+ *
+ * @returns The old default instance.
+ * @param   pLogger     The new default release logger instance.
+ */
+RTDECL(PRTLOGGER) RTLogRelSetDefaultInstance(PRTLOGGER pLogger);
+#endif /* !IN_RC */
+
+/**
+ * Gets the default release logger instance.
+ *
+ * @returns Pointer to default release logger instance if availble, otherwise NULL.
+ */
+RTDECL(PRTLOGGER) RTLogRelGetDefaultInstance(void);
+
+/**
+ * Gets the default release logger instance.
+ *
+ * @returns Pointer to default release logger instance if availble, otherwise NULL.
+ * @param   fFlagsAndGroup  The flags in the lower 16 bits, the group number in
+ *                          the high 16 bits.
+ */
+RTDECL(PRTLOGGER) RTLogRelGetDefaultInstanceEx(uint32_t fFlagsAndGroup);
+
+/**
+ * Write to a logger instance, defaulting to the release one.
+ *
+ * This function will check whether the instance, group and flags makes up a
+ * logging kind which is currently enabled before writing anything to the log.
+ *
+ * @param   pLogger     Pointer to logger instance.
+ * @param   fFlags      The logging flags.
+ * @param   iGroup      The group.
+ *                      The value ~0U is reserved for compatibility with RTLogLogger[V] and is
+ *                      only for internal usage!
+ * @param   pszFormat   Format string.
+ * @param   ...         Format arguments.
+ * @remark  This is a worker function for LogRelIt.
+ */
+RTDECL(void) RTLogRelLogger(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup,
+                            const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(4, 5);
+
+/**
+ * Write to a logger instance, defaulting to the release one.
+ *
+ * This function will check whether the instance, group and flags makes up a
+ * logging kind which is currently enabled before writing anything to the log.
+ *
+ * @param   pLogger     Pointer to logger instance. If NULL the default release instance is attempted.
+ * @param   fFlags      The logging flags.
+ * @param   iGroup      The group.
+ *                      The value ~0U is reserved for compatibility with RTLogLogger[V] and is
+ *                      only for internal usage!
+ * @param   pszFormat   Format string.
+ * @param   args        Format arguments.
+ */
+RTDECL(void) RTLogRelLoggerV(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup,
+                             const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(4, 0);
+
+/**
+ * printf like function for writing to the default release log.
+ *
+ * @param   pszFormat   Printf like format string.
+ * @param   ...         Optional arguments as specified in pszFormat.
+ *
+ * @remark The API doesn't support formatting of floating point numbers at the moment.
+ */
+RTDECL(void) RTLogRelPrintf(const char *pszFormat, ...)  RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * vprintf like function for writing to the default release log.
+ *
+ * @param   pszFormat   Printf like format string.
+ * @param   args        Optional arguments as specified in pszFormat.
+ *
+ * @remark The API doesn't support formatting of floating point numbers at the moment.
+ */
+RTDECL(void) RTLogRelPrintfV(const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Changes the buffering setting of the default release logger.
+ *
+ * This can be used for optimizing longish logging sequences.
+ *
+ * @returns The old state.
+ * @param   fBuffered       The new state.
+ */
+RTDECL(bool) RTLogRelSetBuffering(bool fBuffered);
+
+/** @} */
+
+
+
+/** @name COM port logging
+ * {
+ */
+
+#ifdef DOXYGEN_RUNNING
+# define LOG_TO_COM
+# define LOG_NO_COM
+#endif
+
+/** @def LOG_TO_COM
+ * Redirects the normal logging macros to the serial versions.
+ */
+
+/** @def LOG_NO_COM
+ * Disables all LogCom* macros.
+ */
+
+/** @def LogCom
+ * Generic logging to serial port.
+ */
+#if defined(LOG_ENABLED) && !defined(LOG_NO_COM)
+# define LogCom(a) RTLogComPrintf a
+#else
+# define LogCom(a) do { } while (0)
+#endif
+
+/** @def LogComFlow
+ * Logging to serial port of execution flow.
+ */
+#if defined(LOG_ENABLED) && defined(LOG_ENABLE_FLOW) && !defined(LOG_NO_COM)
+# define LogComFlow(a) RTLogComPrintf a
+#else
+# define LogComFlow(a) do { } while (0)
+#endif
+
+#ifdef LOG_TO_COM
+# undef Log
+# define Log(a)             LogCom(a)
+# undef LogFlow
+# define LogFlow(a)         LogComFlow(a)
+#endif
+
+/** @} */
+
+
+/** @name Backdoor Logging
+ * @{
+ */
+
+#ifdef DOXYGEN_RUNNING
+# define LOG_TO_BACKDOOR
+# define LOG_NO_BACKDOOR
+#endif
+
+/** @def LOG_TO_BACKDOOR
+ * Redirects the normal logging macros to the backdoor versions.
+ */
+
+/** @def LOG_NO_BACKDOOR
+ * Disables all LogBackdoor* macros.
+ */
+
+/** @def LogBackdoor
+ * Generic logging to the VBox backdoor via port I/O.
+ */
+#if defined(LOG_ENABLED) && !defined(LOG_NO_BACKDOOR)
+# define LogBackdoor(a)     RTLogBackdoorPrintf a
+#else
+# define LogBackdoor(a)     do { } while (0)
+#endif
+
+/** @def LogBackdoorFlow
+ * Logging of execution flow messages to the backdoor I/O port.
+ */
+#if defined(LOG_ENABLED) && !defined(LOG_NO_BACKDOOR)
+# define LogBackdoorFlow(a) RTLogBackdoorPrintf a
+#else
+# define LogBackdoorFlow(a) do { } while (0)
+#endif
+
+/** @def LogRelBackdoor
+ * Release logging to the VBox backdoor via port I/O.
+ */
+#if !defined(LOG_NO_BACKDOOR)
+# define LogRelBackdoor(a)  RTLogBackdoorPrintf a
+#else
+# define LogRelBackdoor(a)  do { } while (0)
+#endif
+
+#ifdef LOG_TO_BACKDOOR
+# undef Log
+# define Log(a)         LogBackdoor(a)
+# undef LogFlow
+# define LogFlow(a)     LogBackdoorFlow(a)
+# undef LogRel
+# define LogRel(a)      LogRelBackdoor(a)
+# if defined(LOG_USE_C99)
+#  undef _LogIt
+#  define _LogIt(a_fFlags, a_iGroup, ...)  LogBackdoor((__VA_ARGS__))
+# endif
+#endif
+
+/** @} */
+
+
+
+/**
+ * Gets the default logger instance, creating it if necessary.
+ *
+ * @returns Pointer to default logger instance if availble, otherwise NULL.
+ */
+RTDECL(PRTLOGGER)   RTLogDefaultInstance(void);
+
+/**
+ * Gets the logger instance if enabled, creating it if necessary.
+ *
+ * @returns Pointer to default logger instance, if group has the specified
+ *          flags enabled.  Otherwise NULL is returned.
+ * @param   fFlagsAndGroup  The flags in the lower 16 bits, the group number in
+ *                          the high 16 bits.
+ */
+RTDECL(PRTLOGGER)   RTLogDefaultInstanceEx(uint32_t fFlagsAndGroup);
+
+/**
+ * Gets the default logger instance.
+ *
+ * @returns Pointer to default logger instance if availble, otherwise NULL.
+ */
+RTDECL(PRTLOGGER)   RTLogGetDefaultInstance(void);
+
+/**
+ * Gets the default logger instance if enabled.
+ *
+ * @returns Pointer to default logger instance, if group has the specified
+ *          flags enabled.  Otherwise NULL is returned.
+ * @param   fFlagsAndGroup  The flags in the lower 16 bits, the group number in
+ *                          the high 16 bits.
+ */
+RTDECL(PRTLOGGER)   RTLogGetDefaultInstanceEx(uint32_t fFlagsAndGroup);
+
+#ifndef IN_RC
+/**
+ * Sets the default logger instance.
+ *
+ * @returns The old default instance.
+ * @param   pLogger     The new default logger instance.
+ */
+RTDECL(PRTLOGGER)   RTLogSetDefaultInstance(PRTLOGGER pLogger);
+#endif /* !IN_RC */
+
+#ifdef IN_RING0
+/**
+ * Changes the default logger instance for the current thread.
+ *
+ * @returns IPRT status code.
+ * @param   pLogger     The logger instance. Pass NULL for deregistration.
+ * @param   uKey        Associated key for cleanup purposes. If pLogger is NULL,
+ *                      all instances with this key will be deregistered. So in
+ *                      order to only deregister the instance associated with the
+ *                      current thread use 0.
+ */
+RTDECL(int)         RTLogSetDefaultInstanceThread(PRTLOGGER pLogger, uintptr_t uKey);
+#endif /* IN_RING0 */
+
+
+#ifndef IN_RC
+/**
+ * Creates the default logger instance for a iprt users.
+ *
+ * Any user of the logging features will need to implement
+ * this or use the generic dummy.
+ *
+ * @returns Pointer to the logger instance.
+ */
+RTDECL(PRTLOGGER) RTLogDefaultInit(void);
+
+/**
+ * Create a logger instance.
+ *
+ * @returns iprt status code.
+ *
+ * @param   ppLogger            Where to store the logger instance.
+ * @param   fFlags              Logger instance flags, a combination of the
+ *                              RTLOGFLAGS_* values.
+ * @param   pszGroupSettings    The initial group settings.
+ * @param   pszEnvVarBase       Base name for the environment variables for
+ *                              this instance.
+ * @param   cGroups             Number of groups in the array.
+ * @param   papszGroups         Pointer to array of groups.  This must stick
+ *                              around for the life of the logger instance.
+ * @param   fDestFlags          The destination flags.  RTLOGDEST_FILE is ORed
+ *                              if pszFilenameFmt specified.
+ * @param   pszFilenameFmt      Log filename format string.  Standard
+ *                              RTStrFormat().
+ * @param   ...                 Format arguments.
+ */
+RTDECL(int) RTLogCreate(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings,
+                        const char *pszEnvVarBase, unsigned cGroups, const char * const * papszGroups,
+                        uint32_t fDestFlags, const char *pszFilenameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(8, 9);
+
+/**
+ * Create a logger instance.
+ *
+ * @returns iprt status code.
+ *
+ * @param   ppLogger            Where to store the logger instance.
+ * @param   fFlags              Logger instance flags, a combination of the
+ *                              RTLOGFLAGS_* values.
+ * @param   pszGroupSettings    The initial group settings.
+ * @param   pszEnvVarBase       Base name for the environment variables for
+ *                              this instance.
+ * @param   cGroups             Number of groups in the array.
+ * @param   papszGroups         Pointer to array of groups.  This must stick
+ *                              around for the life of the logger instance.
+ * @param   fDestFlags          The destination flags.  RTLOGDEST_FILE is ORed
+ *                              if pszFilenameFmt specified.
+ * @param   pfnPhase            Callback function for starting logging and for
+ *                              ending or starting a new file for log history
+ *                              rotation.  NULL is OK.
+ * @param   cHistory            Number of old log files to keep when performing
+ *                              log history rotation.  0 means no history.
+ * @param   cbHistoryFileMax    Maximum size of log file when performing
+ *                              history rotation. 0 means no size limit.
+ * @param   cSecsHistoryTimeSlot Maximum time interval per log file when
+ *                              performing history rotation, in seconds.
+ *                              0 means time limit.
+ * @param   pszErrorMsg         A buffer which is filled with an error message if something fails. May be NULL.
+ * @param   cchErrorMsg         The size of the error message buffer.
+ * @param   pszFilenameFmt      Log filename format string. Standard RTStrFormat().
+ * @param   ...                 Format arguments.
+ */
+RTDECL(int) RTLogCreateEx(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings,
+                          const char *pszEnvVarBase, unsigned cGroups, const char * const * papszGroups,
+                          uint32_t fDestFlags, PFNRTLOGPHASE pfnPhase, uint32_t cHistory,
+                          uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot, char *pszErrorMsg, size_t cchErrorMsg,
+                          const char *pszFilenameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(14, 15);
+
+/**
+ * Create a logger instance.
+ *
+ * @returns iprt status code.
+ *
+ * @param   ppLogger            Where to store the logger instance.
+ * @param   fFlags              Logger instance flags, a combination of the
+ *                              RTLOGFLAGS_* values.
+ * @param   pszGroupSettings    The initial group settings.
+ * @param   pszEnvVarBase       Base name for the environment variables for
+ *                              this instance.
+ * @param   cGroups             Number of groups in the array.
+ * @param   papszGroups         Pointer to array of groups.  This must stick
+ *                              around for the life of the logger instance.
+ * @param   fDestFlags          The destination flags.  RTLOGDEST_FILE is ORed
+ *                              if pszFilenameFmt specified.
+ * @param   pfnPhase            Callback function for starting logging and for
+ *                              ending or starting a new file for log history
+ *                              rotation.
+ * @param   cHistory            Number of old log files to keep when performing
+ *                              log history rotation.  0 means no history.
+ * @param   cbHistoryFileMax    Maximum size of log file when performing
+ *                              history rotation.  0 means no size limit.
+ * @param   cSecsHistoryTimeSlot  Maximum time interval per log file when
+ *                              performing history rotation, in seconds.
+ *                              0 means no time limit.
+ * @param   pszErrorMsg         A buffer which is filled with an error message
+ *                              if something fails.  May be NULL.
+ * @param   cchErrorMsg         The size of the error message buffer.
+ * @param   pszFilenameFmt      Log filename format string.  Standard
+ *                              RTStrFormat().
+ * @param   args                Format arguments.
+ */
+RTDECL(int) RTLogCreateExV(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings,
+                           const char *pszEnvVarBase, unsigned cGroups, const char * const * papszGroups,
+                           uint32_t fDestFlags, PFNRTLOGPHASE pfnPhase, uint32_t cHistory,
+                           uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot, char *pszErrorMsg, size_t cchErrorMsg,
+                           const char *pszFilenameFmt, va_list args) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(14, 0);
+
+/**
+ * Create a logger instance for singled threaded ring-0 usage.
+ *
+ * @returns iprt status code.
+ *
+ * @param   pLogger             Where to create the logger instance.
+ * @param   cbLogger            The amount of memory available for the logger instance.
+ * @param   pLoggerR0Ptr        The ring-0 address corresponding to @a pLogger.
+ * @param   pfnLoggerR0Ptr      Pointer to logger wrapper function.
+ * @param   pfnFlushR0Ptr       Pointer to flush function.
+ * @param   fFlags              Logger instance flags, a combination of the RTLOGFLAGS_* values.
+ * @param   fDestFlags          The destination flags.
+ */
+RTDECL(int) RTLogCreateForR0(PRTLOGGER pLogger, size_t cbLogger,
+                             RTR0PTR pLoggerR0Ptr, RTR0PTR pfnLoggerR0Ptr, RTR0PTR pfnFlushR0Ptr,
+                             uint32_t fFlags, uint32_t fDestFlags);
+
+/**
+ * Calculates the minimum size of a ring-0 logger instance.
+ *
+ * @returns The minimum size.
+ * @param   cGroups             The number of groups.
+ * @param   fFlags              Relevant flags.
+ */
+RTDECL(size_t) RTLogCalcSizeForR0(uint32_t cGroups, uint32_t fFlags);
+
+/**
+ * Destroys a logger instance.
+ *
+ * The instance is flushed and all output destinations closed (where applicable).
+ *
+ * @returns iprt status code.
+ * @param   pLogger             The logger instance which close destroyed. NULL is fine.
+ */
+RTDECL(int) RTLogDestroy(PRTLOGGER pLogger);
+
+/**
+ * Create a logger instance clone for RC usage.
+ *
+ * @returns iprt status code.
+ *
+ * @param   pLogger             The logger instance to be cloned.
+ * @param   pLoggerRC           Where to create the RC logger instance.
+ * @param   cbLoggerRC          Amount of memory allocated to for the RC logger
+ *                              instance clone.
+ * @param   pfnLoggerRCPtr      Pointer to logger wrapper function for this
+ *                              instance (RC Ptr).
+ * @param   pfnFlushRCPtr       Pointer to flush function (RC Ptr).
+ * @param   fFlags              Logger instance flags, a combination of the RTLOGFLAGS_* values.
+ */
+RTDECL(int) RTLogCloneRC(PRTLOGGER pLogger, PRTLOGGERRC pLoggerRC, size_t cbLoggerRC,
+                         RTRCPTR pfnLoggerRCPtr, RTRCPTR pfnFlushRCPtr, uint32_t fFlags);
+
+/**
+ * Flushes a RC logger instance to a R3 logger.
+ *
+ * @returns iprt status code.
+ * @param   pLogger     The R3 logger instance to flush pLoggerRC to. If NULL
+ *                      the default logger is used.
+ * @param   pLoggerRC   The RC logger instance to flush.
+ */
+RTDECL(void) RTLogFlushRC(PRTLOGGER pLogger, PRTLOGGERRC pLoggerRC);
+
+/**
+ * Flushes the buffer in one logger instance onto another logger.
+ *
+ * @returns iprt status code.
+ *
+ * @param   pSrcLogger   The logger instance to flush.
+ * @param   pDstLogger   The logger instance to flush onto.
+ *                       If NULL the default logger will be used.
+ */
+RTDECL(void) RTLogFlushToLogger(PRTLOGGER pSrcLogger, PRTLOGGER pDstLogger);
+
+/**
+ * Flushes a R0 logger instance to a R3 logger.
+ *
+ * @returns iprt status code.
+ * @param   pLogger      The R3 logger instance to flush pLoggerR0 to. If NULL
+ *                       the default logger is used.
+ * @param   pLoggerR0    The R0 logger instance to flush.
+ */
+RTDECL(void) RTLogFlushR0(PRTLOGGER pLogger, PRTLOGGER pLoggerR0);
+
+/**
+ * Sets the custom prefix callback.
+ *
+ * @returns IPRT status code.
+ * @param   pLogger     The logger instance.
+ * @param   pfnCallback The callback.
+ * @param   pvUser      The user argument for the callback.
+ *  */
+RTDECL(int) RTLogSetCustomPrefixCallback(PRTLOGGER pLogger, PFNRTLOGPREFIX pfnCallback, void *pvUser);
+
+/**
+ * Same as RTLogSetCustomPrefixCallback for loggers created by
+ * RTLogCreateForR0.
+ *
+ * @returns IPRT status code.
+ * @param   pLogger             The logger instance.
+ * @param   pLoggerR0Ptr        The ring-0 address corresponding to @a pLogger.
+ * @param   pfnCallbackR0Ptr    The callback.
+ * @param   pvUserR0Ptr         The user argument for the callback.
+ *  */
+RTDECL(int) RTLogSetCustomPrefixCallbackForR0(PRTLOGGER pLogger, RTR0PTR pLoggerR0Ptr,
+                                              RTR0PTR pfnCallbackR0Ptr, RTR0PTR pvUserR0Ptr);
+
+/**
+ * Copies the group settings and flags from logger instance to another.
+ *
+ * @returns IPRT status code.
+ * @param   pDstLogger      The destination logger instance.
+ * @param   pDstLoggerR0Ptr The ring-0 address corresponding to @a pDstLogger.
+ * @param   pSrcLogger      The source logger instance. If NULL the default one is used.
+ * @param   fFlagsOr        OR mask for the flags.
+ * @param   fFlagsAnd       AND mask for the flags.
+ */
+RTDECL(int) RTLogCopyGroupsAndFlagsForR0(PRTLOGGER pDstLogger, RTR0PTR pDstLoggerR0Ptr,
+                                         PCRTLOGGER pSrcLogger, uint32_t fFlagsOr, uint32_t fFlagsAnd);
+
+/**
+ * Get the current log group settings as a string.
+ *
+ * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
+ * @param   pLogger             Logger instance (NULL for default logger).
+ * @param   pszBuf              The output buffer.
+ * @param   cchBuf              The size of the output buffer. Must be greater
+ *                              than zero.
+ */
+RTDECL(int) RTLogGetGroupSettings(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf);
+
+/**
+ * Updates the group settings for the logger instance using the specified
+ * specification string.
+ *
+ * @returns iprt status code.
+ *          Failures can safely be ignored.
+ * @param   pLogger     Logger instance (NULL for default logger).
+ * @param   pszValue    Value to parse.
+ */
+RTDECL(int) RTLogGroupSettings(PRTLOGGER pLogger, const char *pszValue);
+#endif /* !IN_RC */
+
+/**
+ * Updates the flags for the logger instance using the specified
+ * specification string.
+ *
+ * @returns iprt status code.
+ *          Failures can safely be ignored.
+ * @param   pLogger     Logger instance (NULL for default logger).
+ * @param   pszValue    Value to parse.
+ */
+RTDECL(int) RTLogFlags(PRTLOGGER pLogger, const char *pszValue);
+
+/**
+ * Changes the buffering setting of the specified logger.
+ *
+ * This can be used for optimizing longish logging sequences.
+ *
+ * @returns The old state.
+ * @param   pLogger         The logger instance (NULL is an alias for the
+ *                          default logger).
+ * @param   fBuffered       The new state.
+ */
+RTDECL(bool) RTLogSetBuffering(PRTLOGGER pLogger, bool fBuffered);
+
+/**
+ * Sets the max number of entries per group.
+ *
+ * @returns Old restriction.
+ *
+ * @param   pLogger             The logger instance (NULL is an alias for the
+ *                              default logger).
+ * @param   cMaxEntriesPerGroup The max number of entries per group.
+ *
+ * @remarks Lowering the limit of an active logger may quietly mute groups.
+ *          Raising it may reactive already muted groups.
+ */
+RTDECL(uint32_t) RTLogSetGroupLimit(PRTLOGGER pLogger, uint32_t cMaxEntriesPerGroup);
+
+#ifndef IN_RC
+/**
+ * Get the current log flags as a string.
+ *
+ * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
+ * @param   pLogger             Logger instance (NULL for default logger).
+ * @param   pszBuf              The output buffer.
+ * @param   cchBuf              The size of the output buffer. Must be greater
+ *                              than zero.
+ */
+RTDECL(int) RTLogGetFlags(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf);
+
+/**
+ * Updates the logger destination using the specified string.
+ *
+ * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
+ * @param   pLogger             Logger instance (NULL for default logger).
+ * @param   pszValue            The value to parse.
+ */
+RTDECL(int) RTLogDestinations(PRTLOGGER pLogger, char const *pszValue);
+
+/**
+ * Get the current log destinations as a string.
+ *
+ * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
+ * @param   pLogger             Logger instance (NULL for default logger).
+ * @param   pszBuf              The output buffer.
+ * @param   cchBuf              The size of the output buffer. Must be greater
+ *                              than 0.
+ */
+RTDECL(int) RTLogGetDestinations(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf);
+#endif /* !IN_RC */
+
+/**
+ * Flushes the specified logger.
+ *
+ * @param   pLogger     The logger instance to flush.
+ *                      If NULL the default instance is used. The default instance
+ *                      will not be initialized by this call.
+ */
+RTDECL(void) RTLogFlush(PRTLOGGER pLogger);
+
+/**
+ * Write to a logger instance.
+ *
+ * @param   pLogger     Pointer to logger instance.
+ * @param   pvCallerRet Ignored.
+ * @param   pszFormat   Format string.
+ * @param   ...         Format arguments.
+ */
+RTDECL(void) RTLogLogger(PRTLOGGER pLogger, void *pvCallerRet, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Write to a logger instance.
+ *
+ * @param   pLogger     Pointer to logger instance.
+ * @param   pszFormat   Format string.
+ * @param   args        Format arguments.
+ */
+RTDECL(void) RTLogLoggerV(PRTLOGGER pLogger, const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Write to a logger instance.
+ *
+ * This function will check whether the instance, group and flags makes up a
+ * logging kind which is currently enabled before writing anything to the log.
+ *
+ * @param   pLogger     Pointer to logger instance. If NULL the default logger instance will be attempted.
+ * @param   fFlags      The logging flags.
+ * @param   iGroup      The group.
+ *                      The value ~0U is reserved for compatibility with RTLogLogger[V] and is
+ *                      only for internal usage!
+ * @param   pszFormat   Format string.
+ * @param   ...         Format arguments.
+ * @remark  This is a worker function of LogIt.
+ */
+RTDECL(void) RTLogLoggerEx(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup,
+                           const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(4, 5);
+
+/**
+ * Write to a logger instance.
+ *
+ * This function will check whether the instance, group and flags makes up a
+ * logging kind which is currently enabled before writing anything to the log.
+ *
+ * @param   pLogger     Pointer to logger instance. If NULL the default logger instance will be attempted.
+ * @param   fFlags      The logging flags.
+ * @param   iGroup      The group.
+ *                      The value ~0U is reserved for compatibility with RTLogLogger[V] and is
+ *                      only for internal usage!
+ * @param   pszFormat   Format string.
+ * @param   args        Format arguments.
+ */
+RTDECL(void) RTLogLoggerExV(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup,
+                            const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(4, 0);
+
+/**
+ * printf like function for writing to the default log.
+ *
+ * @param   pszFormat   Printf like format string.
+ * @param   ...         Optional arguments as specified in pszFormat.
+ *
+ * @remark The API doesn't support formatting of floating point numbers at the moment.
+ */
+RTDECL(void) RTLogPrintf(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * vprintf like function for writing to the default log.
+ *
+ * @param   pszFormat   Printf like format string.
+ * @param   va          Optional arguments as specified in pszFormat.
+ *
+ * @remark The API doesn't support formatting of floating point numbers at the moment.
+ */
+RTDECL(void) RTLogPrintfV(const char *pszFormat, va_list va)  RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Dumper vprintf-like function outputting to a logger.
+ *
+ * @param   pvUser          Pointer to the logger instance to use, NULL for
+ *                          default instance.
+ * @param   pszFormat       Format string.
+ * @param   va              Format arguments.
+ */
+RTDECL(void) RTLogDumpPrintfV(void *pvUser, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+
+
+#ifndef DECLARED_FNRTSTROUTPUT          /* duplicated in iprt/string.h */
+#define DECLARED_FNRTSTROUTPUT
+/**
+ * Output callback.
+ *
+ * @returns number of bytes written.
+ * @param   pvArg       User argument.
+ * @param   pachChars   Pointer to an array of utf-8 characters.
+ * @param   cbChars     Number of bytes in the character array pointed to by pachChars.
+ */
+typedef DECLCALLBACK(size_t) FNRTSTROUTPUT(void *pvArg, const char *pachChars, size_t cbChars);
+/** Pointer to callback function. */
+typedef FNRTSTROUTPUT *PFNRTSTROUTPUT;
+#endif
+
+/**
+ * Partial vsprintf worker implementation.
+ *
+ * @returns number of bytes formatted.
+ * @param   pfnOutput   Output worker.
+ *                      Called in two ways. Normally with a string an it's length.
+ *                      For termination, it's called with NULL for string, 0 for length.
+ * @param   pvArg       Argument to output worker.
+ * @param   pszFormat   Format string.
+ * @param   args        Argument list.
+ */
+RTDECL(size_t) RTLogFormatV(PFNRTSTROUTPUT pfnOutput, void *pvArg, const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Write log buffer to COM port.
+ *
+ * @param   pach        Pointer to the buffer to write.
+ * @param   cb          Number of bytes to write.
+ */
+RTDECL(void) RTLogWriteCom(const char *pach, size_t cb);
+
+/**
+ * Prints a formatted string to the serial port used for logging.
+ *
+ * @returns Number of bytes written.
+ * @param   pszFormat   Format string.
+ * @param   ...         Optional arguments specified in the format string.
+ */
+RTDECL(size_t) RTLogComPrintf(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Prints a formatted string to the serial port used for logging.
+ *
+ * @returns Number of bytes written.
+ * @param   pszFormat   Format string.
+ * @param   args        Optional arguments specified in the format string.
+ */
+RTDECL(size_t)  RTLogComPrintfV(const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(1, 0);
+
+
+#if 0 /* not implemented yet */
+
+/** Indicates that the semaphores shall be used to notify the other
+ * part about buffer changes. */
+#define LOGHOOKBUFFER_FLAGS_SEMAPHORED      1
+
+/**
+ * Log Hook Buffer.
+ * Use to communicate between the logger and a log consumer.
+ */
+typedef struct RTLOGHOOKBUFFER
+{
+    /** Write pointer. */
+    volatile void          *pvWrite;
+    /** Read pointer. */
+    volatile void          *pvRead;
+    /** Buffer start. */
+    void                   *pvStart;
+    /** Buffer end (exclusive). */
+    void                   *pvEnd;
+    /** Signaling semaphore used by the writer to wait on a full buffer.
+     * Only used when indicated in flags. */
+    void                   *pvSemWriter;
+    /** Signaling semaphore used by the read to wait on an empty buffer.
+     * Only used when indicated in flags. */
+    void                   *pvSemReader;
+    /** Buffer flags. Current reserved and set to zero. */
+    volatile unsigned       fFlags;
+} RTLOGHOOKBUFFER;
+/** Pointer to a log hook buffer. */
+typedef RTLOGHOOKBUFFER *PRTLOGHOOKBUFFER;
+
+
+/**
+ * Register a logging hook.
+ *
+ * This type of logging hooks are expecting different threads acting
+ * producer and consumer. They share a circular buffer which have two
+ * pointers one for each end. When the buffer is full there are two
+ * alternatives (indicated by a buffer flag), either wait for the
+ * consumer to get it's job done, or to write a generic message saying
+ * buffer overflow.
+ *
+ * Since the waiting would need a signal semaphore, we'll skip that for now.
+ *
+ * @returns iprt status code.
+ * @param   pBuffer     Pointer to a logger hook buffer.
+ */
+RTDECL(int)     RTLogRegisterHook(PRTLOGGER pLogger, PRTLOGHOOKBUFFER pBuffer);
+
+/**
+ * Deregister a logging hook registered with RTLogRegisterHook().
+ *
+ * @returns iprt status code.
+ * @param   pBuffer     Pointer to a logger hook buffer.
+ */
+RTDECL(int)     RTLogDeregisterHook(PRTLOGGER pLogger, PRTLOGHOOKBUFFER pBuffer);
+
+#endif /* not implemented yet */
+
+
+
+/**
+ * Write log buffer to a debugger (RTLOGDEST_DEBUGGER).
+ *
+ * @param   pach        What to write.
+ * @param   cb          How much to write.
+ * @remark  When linking statically, this function can be replaced by defining your own.
+ */
+RTDECL(void) RTLogWriteDebugger(const char *pach, size_t cb);
+
+/**
+ * Write log buffer to a user defined output stream (RTLOGDEST_USER).
+ *
+ * @param   pach        What to write.
+ * @param   cb          How much to write.
+ * @remark  When linking statically, this function can be replaced by defining your own.
+ */
+RTDECL(void) RTLogWriteUser(const char *pach, size_t cb);
+
+/**
+ * Write log buffer to stdout (RTLOGDEST_STDOUT).
+ *
+ * @param   pach        What to write.
+ * @param   cb          How much to write.
+ * @remark  When linking statically, this function can be replaced by defining your own.
+ */
+RTDECL(void) RTLogWriteStdOut(const char *pach, size_t cb);
+
+/**
+ * Write log buffer to stdout (RTLOGDEST_STDERR).
+ *
+ * @param   pach        What to write.
+ * @param   cb          How much to write.
+ * @remark  When linking statically, this function can be replaced by defining your own.
+ */
+RTDECL(void) RTLogWriteStdErr(const char *pach, size_t cb);
+
+#ifdef VBOX
+
+/**
+ * Prints a formatted string to the backdoor port.
+ *
+ * @returns Number of bytes written.
+ * @param   pszFormat   Format string.
+ * @param   ...         Optional arguments specified in the format string.
+ */
+RTDECL(size_t) RTLogBackdoorPrintf(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Prints a formatted string to the backdoor port.
+ *
+ * @returns Number of bytes written.
+ * @param   pszFormat   Format string.
+ * @param   args        Optional arguments specified in the format string.
+ */
+RTDECL(size_t)  RTLogBackdoorPrintfV(const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(1, 0);
+
+#endif /* VBOX */
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/mangling.h b/ubuntu/vbox/include/iprt/mangling.h
new file mode 100644 (file)
index 0000000..40c0c07
--- /dev/null
@@ -0,0 +1,3520 @@
+/** @file
+ * IPRT - Symbol Mangling.
+ *
+ * This header is used to mangle public IPRT symbol to make it possible to have
+ * several IPRT version loaded into one symbol space at the same time.  To
+ * enable symbol mangling you create a header which the compiler includes for
+ * every compilation unit (check out the -include option of gcc).  Your header
+ * will define RT_MANGLER(name) and then include this header to set up the
+ * actual mappings.
+ */
+
+/*
+ * Copyright (C) 2011-2017 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.
+ */
+
+#ifndef ___iprt_mangling_h
+#define ___iprt_mangling_h
+
+#ifndef RT_MANGLER
+# error "RT_MANGLER is not defined."
+#endif
+
+#ifndef DOXYGEN_RUNNING
+
+/** @def RT_WITH_MANGLING
+ * Indicates that we're mangling symbols.  */
+# define RT_WITH_MANGLING
+
+
+/*
+ * Stable functions (alphabetical order):
+ */
+/* ASM*:
+ grep -h DECLASM include/iprt/asm.h include/iprt/asm-amd64-x86.h \
+  | kmk_sed -e 's/^DECLASM.[^)]*. *\(ASM[^(]*\)[(].*$/# define \1 :RT_MANGLER(\1)\n# define \1_EndProc :RT_MANGLER(\1_EndProc)/' \
+  | sort \
+  | awk -F: '{ printf("%-55s %s\n", $1, $2);' */
+# define ASMAddFlags                                    RT_MANGLER(ASMAddFlags)
+# define ASMAddFlags_EndProc                            RT_MANGLER(ASMAddFlags_EndProc)
+# define ASMAtomicAddU16                                RT_MANGLER(ASMAtomicAddU16)
+# define ASMAtomicAddU16_EndProc                        RT_MANGLER(ASMAtomicAddU16_EndProc)
+# define ASMAtomicAddU32                                RT_MANGLER(ASMAtomicAddU32)
+# define ASMAtomicAddU32_EndProc                        RT_MANGLER(ASMAtomicAddU32_EndProc)
+# define ASMAtomicAddU64                                RT_MANGLER(ASMAtomicAddU64)
+# define ASMAtomicAddU64_EndProc                        RT_MANGLER(ASMAtomicAddU64_EndProc)
+# define ASMAtomicAndU32                                RT_MANGLER(ASMAtomicAndU32)
+# define ASMAtomicAndU32_EndProc                        RT_MANGLER(ASMAtomicAndU32_EndProc)
+# define ASMAtomicAndU64                                RT_MANGLER(ASMAtomicAndU64)
+# define ASMAtomicAndU64_EndProc                        RT_MANGLER(ASMAtomicAndU64_EndProc)
+# define ASMAtomicBitClear                              RT_MANGLER(ASMAtomicBitClear)
+# define ASMAtomicBitClear_EndProc                      RT_MANGLER(ASMAtomicBitClear_EndProc)
+# define ASMAtomicBitSet                                RT_MANGLER(ASMAtomicBitSet)
+# define ASMAtomicBitSet_EndProc                        RT_MANGLER(ASMAtomicBitSet_EndProc)
+# define ASMAtomicBitTestAndClear                       RT_MANGLER(ASMAtomicBitTestAndClear)
+# define ASMAtomicBitTestAndClear_EndProc               RT_MANGLER(ASMAtomicBitTestAndClear_EndProc)
+# define ASMAtomicBitTestAndSet                         RT_MANGLER(ASMAtomicBitTestAndSet)
+# define ASMAtomicBitTestAndSet_EndProc                 RT_MANGLER(ASMAtomicBitTestAndSet_EndProc)
+# define ASMAtomicBitTestAndToggle                      RT_MANGLER(ASMAtomicBitTestAndToggle)
+# define ASMAtomicBitTestAndToggle_EndProc              RT_MANGLER(ASMAtomicBitTestAndToggle_EndProc)
+# define ASMAtomicBitToggle                             RT_MANGLER(ASMAtomicBitToggle)
+# define ASMAtomicBitToggle_EndProc                     RT_MANGLER(ASMAtomicBitToggle_EndProc)
+# define ASMAtomicCmpXchgExU32                          RT_MANGLER(ASMAtomicCmpXchgExU32)
+# define ASMAtomicCmpXchgExU32_EndProc                  RT_MANGLER(ASMAtomicCmpXchgExU32_EndProc)
+# define ASMAtomicCmpXchgExU64                          RT_MANGLER(ASMAtomicCmpXchgExU64)
+# define ASMAtomicCmpXchgExU64_EndProc                  RT_MANGLER(ASMAtomicCmpXchgExU64_EndProc)
+# define ASMAtomicCmpXchgU32                            RT_MANGLER(ASMAtomicCmpXchgU32)
+# define ASMAtomicCmpXchgU32_EndProc                    RT_MANGLER(ASMAtomicCmpXchgU32_EndProc)
+# define ASMAtomicCmpXchgU64                            RT_MANGLER(ASMAtomicCmpXchgU64)
+# define ASMAtomicCmpXchgU64_EndProc                    RT_MANGLER(ASMAtomicCmpXchgU64_EndProc)
+# define ASMAtomicCmpXchgU8                             RT_MANGLER(ASMAtomicCmpXchgU8)
+# define ASMAtomicCmpXchgU8_EndProc                     RT_MANGLER(ASMAtomicCmpXchgU8_EndProc)
+# define ASMAtomicDecU16                                RT_MANGLER(ASMAtomicDecU16)
+# define ASMAtomicDecU16_EndProc                        RT_MANGLER(ASMAtomicDecU16_EndProc)
+# define ASMAtomicDecU32                                RT_MANGLER(ASMAtomicDecU32)
+# define ASMAtomicDecU32_EndProc                        RT_MANGLER(ASMAtomicDecU32_EndProc)
+# define ASMAtomicDecU64                                RT_MANGLER(ASMAtomicDecU64)
+# define ASMAtomicDecU64_EndProc                        RT_MANGLER(ASMAtomicDecU64_EndProc)
+# define ASMAtomicIncU16                                RT_MANGLER(ASMAtomicIncU16)
+# define ASMAtomicIncU16_EndProc                        RT_MANGLER(ASMAtomicIncU16_EndProc)
+# define ASMAtomicIncU32                                RT_MANGLER(ASMAtomicIncU32)
+# define ASMAtomicIncU32_EndProc                        RT_MANGLER(ASMAtomicIncU32_EndProc)
+# define ASMAtomicIncU64                                RT_MANGLER(ASMAtomicIncU64)
+# define ASMAtomicIncU64_EndProc                        RT_MANGLER(ASMAtomicIncU64_EndProc)
+# define ASMAtomicOrU32                                 RT_MANGLER(ASMAtomicOrU32)
+# define ASMAtomicOrU32_EndProc                         RT_MANGLER(ASMAtomicOrU32_EndProc)
+# define ASMAtomicOrU64                                 RT_MANGLER(ASMAtomicOrU64)
+# define ASMAtomicOrU64_EndProc                         RT_MANGLER(ASMAtomicOrU64_EndProc)
+# define ASMAtomicReadU64                               RT_MANGLER(ASMAtomicReadU64)
+# define ASMAtomicReadU64_EndProc                       RT_MANGLER(ASMAtomicReadU64_EndProc)
+# define ASMAtomicUoAndU32                              RT_MANGLER(ASMAtomicUoAndU32)
+# define ASMAtomicUoAndU32_EndProc                      RT_MANGLER(ASMAtomicUoAndU32_EndProc)
+# define ASMAtomicUoAndU64                              RT_MANGLER(ASMAtomicUoAndU64)
+# define ASMAtomicUoAndU64_EndProc                      RT_MANGLER(ASMAtomicUoAndU64_EndProc)
+# define ASMAtomicUoDecU32                              RT_MANGLER(ASMAtomicUoDecU32)
+# define ASMAtomicUoDecU32_EndProc                      RT_MANGLER(ASMAtomicUoDecU32_EndProc)
+# define ASMAtomicUoIncU32                              RT_MANGLER(ASMAtomicUoIncU32)
+# define ASMAtomicUoIncU32_EndProc                      RT_MANGLER(ASMAtomicUoIncU32_EndProc)
+# define ASMAtomicUoOrU32                               RT_MANGLER(ASMAtomicUoOrU32)
+# define ASMAtomicUoOrU32_EndProc                       RT_MANGLER(ASMAtomicUoOrU32_EndProc)
+# define ASMAtomicUoOrU64                               RT_MANGLER(ASMAtomicUoOrU64)
+# define ASMAtomicUoOrU64_EndProc                       RT_MANGLER(ASMAtomicUoOrU64_EndProc)
+# define ASMAtomicUoReadU64                             RT_MANGLER(ASMAtomicUoReadU64)
+# define ASMAtomicUoReadU64_EndProc                     RT_MANGLER(ASMAtomicUoReadU64_EndProc)
+# define ASMAtomicXchgU16                               RT_MANGLER(ASMAtomicXchgU16)
+# define ASMAtomicXchgU16_EndProc                       RT_MANGLER(ASMAtomicXchgU16_EndProc)
+# define ASMAtomicXchgU32                               RT_MANGLER(ASMAtomicXchgU32)
+# define ASMAtomicXchgU32_EndProc                       RT_MANGLER(ASMAtomicXchgU32_EndProc)
+# define ASMAtomicXchgU64                               RT_MANGLER(ASMAtomicXchgU64)
+# define ASMAtomicXchgU64_EndProc                       RT_MANGLER(ASMAtomicXchgU64_EndProc)
+# define ASMAtomicXchgU8                                RT_MANGLER(ASMAtomicXchgU8)
+# define ASMAtomicXchgU8_EndProc                        RT_MANGLER(ASMAtomicXchgU8_EndProc)
+# define ASMBitClear                                    RT_MANGLER(ASMBitClear)
+# define ASMBitClear_EndProc                            RT_MANGLER(ASMBitClear_EndProc)
+# define ASMBitFirstClear                               RT_MANGLER(ASMBitFirstClear)
+# define ASMBitFirstClear_EndProc                       RT_MANGLER(ASMBitFirstClear_EndProc)
+# define ASMBitFirstSet                                 RT_MANGLER(ASMBitFirstSet)
+# define ASMBitFirstSet_EndProc                         RT_MANGLER(ASMBitFirstSet_EndProc)
+# define ASMBitFirstSetU16                              RT_MANGLER(ASMBitFirstSetU16)
+# define ASMBitFirstSetU16_EndProc                      RT_MANGLER(ASMBitFirstSetU16_EndProc)
+# define ASMBitFirstSetU32                              RT_MANGLER(ASMBitFirstSetU32)
+# define ASMBitFirstSetU32_EndProc                      RT_MANGLER(ASMBitFirstSetU32_EndProc)
+# define ASMBitFirstSetU64                              RT_MANGLER(ASMBitFirstSetU64)
+# define ASMBitFirstSetU64_EndProc                      RT_MANGLER(ASMBitFirstSetU64_EndProc)
+# define ASMBitLastSetU16                               RT_MANGLER(ASMBitLastSetU16)
+# define ASMBitLastSetU16_EndProc                       RT_MANGLER(ASMBitLastSetU16_EndProc)
+# define ASMBitLastSetU32                               RT_MANGLER(ASMBitLastSetU32)
+# define ASMBitLastSetU32_EndProc                       RT_MANGLER(ASMBitLastSetU32_EndProc)
+# define ASMBitLastSetU64                               RT_MANGLER(ASMBitLastSetU64)
+# define ASMBitLastSetU64_EndProc                       RT_MANGLER(ASMBitLastSetU64_EndProc)
+# define ASMBitNextClear                                RT_MANGLER(ASMBitNextClear)
+# define ASMBitNextClear_EndProc                        RT_MANGLER(ASMBitNextClear_EndProc)
+# define ASMBitNextSet                                  RT_MANGLER(ASMBitNextSet)
+# define ASMBitNextSet_EndProc                          RT_MANGLER(ASMBitNextSet_EndProc)
+# define ASMBitSet                                      RT_MANGLER(ASMBitSet)
+# define ASMBitSet_EndProc                              RT_MANGLER(ASMBitSet_EndProc)
+# define ASMBitTest                                     RT_MANGLER(ASMBitTest)
+# define ASMBitTest_EndProc                             RT_MANGLER(ASMBitTest_EndProc)
+# define ASMBitTestAndClear                             RT_MANGLER(ASMBitTestAndClear)
+# define ASMBitTestAndClear_EndProc                     RT_MANGLER(ASMBitTestAndClear_EndProc)
+# define ASMBitTestAndSet                               RT_MANGLER(ASMBitTestAndSet)
+# define ASMBitTestAndSet_EndProc                       RT_MANGLER(ASMBitTestAndSet_EndProc)
+# define ASMBitTestAndToggle                            RT_MANGLER(ASMBitTestAndToggle)
+# define ASMBitTestAndToggle_EndProc                    RT_MANGLER(ASMBitTestAndToggle_EndProc)
+# define ASMBitToggle                                   RT_MANGLER(ASMBitToggle)
+# define ASMBitToggle_EndProc                           RT_MANGLER(ASMBitToggle_EndProc)
+# define ASMByteSwapU16                                 RT_MANGLER(ASMByteSwapU16)
+# define ASMByteSwapU16_EndProc                         RT_MANGLER(ASMByteSwapU16_EndProc)
+# define ASMByteSwapU32                                 RT_MANGLER(ASMByteSwapU32)
+# define ASMByteSwapU32_EndProc                         RT_MANGLER(ASMByteSwapU32_EndProc)
+# define ASMChangeFlags                                 RT_MANGLER(ASMChangeFlags)
+# define ASMChangeFlags_EndProc                         RT_MANGLER(ASMChangeFlags_EndProc)
+# define ASMClearFlags                                  RT_MANGLER(ASMClearFlags)
+# define ASMClearFlags_EndProc                          RT_MANGLER(ASMClearFlags_EndProc)
+# define ASMCpuId                                       RT_MANGLER(ASMCpuId)
+# define ASMCpuId_EAX                                   RT_MANGLER(ASMCpuId_EAX)
+# define ASMCpuId_EAX_EndProc                           RT_MANGLER(ASMCpuId_EAX_EndProc)
+# define ASMCpuId_EBX                                   RT_MANGLER(ASMCpuId_EBX)
+# define ASMCpuId_EBX_EndProc                           RT_MANGLER(ASMCpuId_EBX_EndProc)
+# define ASMCpuId_ECX                                   RT_MANGLER(ASMCpuId_ECX)
+# define ASMCpuId_ECX_EDX                               RT_MANGLER(ASMCpuId_ECX_EDX)
+# define ASMCpuId_ECX_EDX_EndProc                       RT_MANGLER(ASMCpuId_ECX_EDX_EndProc)
+# define ASMCpuId_ECX_EndProc                           RT_MANGLER(ASMCpuId_ECX_EndProc)
+# define ASMCpuId_EDX                                   RT_MANGLER(ASMCpuId_EDX)
+# define ASMCpuId_EDX_EndProc                           RT_MANGLER(ASMCpuId_EDX_EndProc)
+# define ASMCpuId_EndProc                               RT_MANGLER(ASMCpuId_EndProc)
+# define ASMCpuId_Idx_ECX                               RT_MANGLER(ASMCpuId_Idx_ECX)
+# define ASMCpuId_Idx_ECX_EndProc                       RT_MANGLER(ASMCpuId_Idx_ECX_EndProc)
+# define ASMCpuIdExSlow                                 RT_MANGLER(ASMCpuIdExSlow)
+# define ASMCpuIdExSlow_EndProc                         RT_MANGLER(ASMCpuIdExSlow_EndProc)
+# define ASMGetAndClearDR6                              RT_MANGLER(ASMGetAndClearDR6)
+# define ASMGetAndClearDR6_EndProc                      RT_MANGLER(ASMGetAndClearDR6_EndProc)
+# define ASMGetApicId                                   RT_MANGLER(ASMGetApicId)
+# define ASMGetApicId_EndProc                           RT_MANGLER(ASMGetApicId_EndProc)
+# define ASMGetCR0                                      RT_MANGLER(ASMGetCR0)
+# define ASMGetCR0_EndProc                              RT_MANGLER(ASMGetCR0_EndProc)
+# define ASMGetCR2                                      RT_MANGLER(ASMGetCR2)
+# define ASMGetCR2_EndProc                              RT_MANGLER(ASMGetCR2_EndProc)
+# define ASMGetCR3                                      RT_MANGLER(ASMGetCR3)
+# define ASMGetCR3_EndProc                              RT_MANGLER(ASMGetCR3_EndProc)
+# define ASMGetCR4                                      RT_MANGLER(ASMGetCR4)
+# define ASMGetCR4_EndProc                              RT_MANGLER(ASMGetCR4_EndProc)
+# define ASMGetCR8                                      RT_MANGLER(ASMGetCR8)
+# define ASMGetCR8_EndProc                              RT_MANGLER(ASMGetCR8_EndProc)
+# define ASMGetCS                                       RT_MANGLER(ASMGetCS)
+# define ASMGetCS_EndProc                               RT_MANGLER(ASMGetCS_EndProc)
+# define ASMGetDR0                                      RT_MANGLER(ASMGetDR0)
+# define ASMGetDR0_EndProc                              RT_MANGLER(ASMGetDR0_EndProc)
+# define ASMGetDR1                                      RT_MANGLER(ASMGetDR1)
+# define ASMGetDR1_EndProc                              RT_MANGLER(ASMGetDR1_EndProc)
+# define ASMGetDR2                                      RT_MANGLER(ASMGetDR2)
+# define ASMGetDR2_EndProc                              RT_MANGLER(ASMGetDR2_EndProc)
+# define ASMGetDR3                                      RT_MANGLER(ASMGetDR3)
+# define ASMGetDR3_EndProc                              RT_MANGLER(ASMGetDR3_EndProc)
+# define ASMGetDR6                                      RT_MANGLER(ASMGetDR6)
+# define ASMGetDR6_EndProc                              RT_MANGLER(ASMGetDR6_EndProc)
+# define ASMGetDR7                                      RT_MANGLER(ASMGetDR7)
+# define ASMGetDR7_EndProc                              RT_MANGLER(ASMGetDR7_EndProc)
+# define ASMGetDS                                       RT_MANGLER(ASMGetDS)
+# define ASMGetDS_EndProc                               RT_MANGLER(ASMGetDS_EndProc)
+# define ASMGetES                                       RT_MANGLER(ASMGetES)
+# define ASMGetES_EndProc                               RT_MANGLER(ASMGetES_EndProc)
+# define ASMGetFlags                                    RT_MANGLER(ASMGetFlags)
+# define ASMGetFlags_EndProc                            RT_MANGLER(ASMGetFlags_EndProc)
+# define ASMGetFS                                       RT_MANGLER(ASMGetFS)
+# define ASMGetFS_EndProc                               RT_MANGLER(ASMGetFS_EndProc)
+# define ASMGetGDTR                                     RT_MANGLER(ASMGetGDTR)
+# define ASMGetGDTR_EndProc                             RT_MANGLER(ASMGetGDTR_EndProc)
+# define ASMGetGS                                       RT_MANGLER(ASMGetGS)
+# define ASMGetGS_EndProc                               RT_MANGLER(ASMGetGS_EndProc)
+# define ASMGetIDTR                                     RT_MANGLER(ASMGetIDTR)
+# define ASMGetIDTR_EndProc                             RT_MANGLER(ASMGetIDTR_EndProc)
+# define ASMGetIdtrLimit                                RT_MANGLER(ASMGetIdtrLimit)
+# define ASMGetIdtrLimit_EndProc                        RT_MANGLER(ASMGetIdtrLimit_EndProc)
+# define ASMGetLDTR                                     RT_MANGLER(ASMGetLDTR)
+# define ASMGetLDTR_EndProc                             RT_MANGLER(ASMGetLDTR_EndProc)
+# define ASMGetSegAttr                                  RT_MANGLER(ASMGetSegAttr)
+# define ASMGetSegAttr_EndProc                          RT_MANGLER(ASMGetSegAttr_EndProc)
+# define ASMGetSS                                       RT_MANGLER(ASMGetSS)
+# define ASMGetSS_EndProc                               RT_MANGLER(ASMGetSS_EndProc)
+# define ASMGetTR                                       RT_MANGLER(ASMGetTR)
+# define ASMGetTR_EndProc                               RT_MANGLER(ASMGetTR_EndProc)
+# define ASMGetXcr0                                     RT_MANGLER(ASMGetXcr0)
+# define ASMGetXcr0_EndProc                             RT_MANGLER(ASMGetXcr0_EndProc)
+# define ASMHalt                                        RT_MANGLER(ASMHalt)
+# define ASMHalt_EndProc                                RT_MANGLER(ASMHalt_EndProc)
+# define ASMInStrU16                                    RT_MANGLER(ASMInStrU16)
+# define ASMInStrU16_EndProc                            RT_MANGLER(ASMInStrU16_EndProc)
+# define ASMInStrU32                                    RT_MANGLER(ASMInStrU32)
+# define ASMInStrU32_EndProc                            RT_MANGLER(ASMInStrU32_EndProc)
+# define ASMInStrU8                                     RT_MANGLER(ASMInStrU8)
+# define ASMInStrU8_EndProc                             RT_MANGLER(ASMInStrU8_EndProc)
+# define ASMIntDisable                                  RT_MANGLER(ASMIntDisable)
+# define ASMIntDisable_EndProc                          RT_MANGLER(ASMIntDisable_EndProc)
+# define ASMIntDisableFlags                             RT_MANGLER(ASMIntDisableFlags)
+# define ASMIntDisableFlags_EndProc                     RT_MANGLER(ASMIntDisableFlags_EndProc)
+# define ASMIntEnable                                   RT_MANGLER(ASMIntEnable)
+# define ASMIntEnable_EndProc                           RT_MANGLER(ASMIntEnable_EndProc)
+# define ASMInU16                                       RT_MANGLER(ASMInU16)
+# define ASMInU16_EndProc                               RT_MANGLER(ASMInU16_EndProc)
+# define ASMInU32                                       RT_MANGLER(ASMInU32)
+# define ASMInU32_EndProc                               RT_MANGLER(ASMInU32_EndProc)
+# define ASMInU8                                        RT_MANGLER(ASMInU8)
+# define ASMInU8_EndProc                                RT_MANGLER(ASMInU8_EndProc)
+# define ASMInvalidateInternalCaches                    RT_MANGLER(ASMInvalidateInternalCaches)
+# define ASMInvalidateInternalCaches_EndProc            RT_MANGLER(ASMInvalidateInternalCaches_EndProc)
+# define ASMInvalidatePage                              RT_MANGLER(ASMInvalidatePage)
+# define ASMInvalidatePage_EndProc                      RT_MANGLER(ASMInvalidatePage_EndProc)
+# define ASMMemFill32                                   RT_MANGLER(ASMMemFill32)
+# define ASMMemFill32_EndProc                           RT_MANGLER(ASMMemFill32_EndProc)
+# define ASMMemFirstNonZero                             RT_MANGLER(ASMMemFirstNonZero)
+# define ASMMemFirstNonZero_EndProc                     RT_MANGLER(ASMMemFirstNonZero_EndProc)
+# define ASMMemFirstMismatchingU8                       RT_MANGLER(ASMMemFirstMismatchingU8)
+# define ASMMemFirstMismatchingU8_EndProc               RT_MANGLER(ASMMemFirstMismatchingU8_EndProc)
+# define ASMMemFirstMismatchingU32                      RT_MANGLER(ASMMemFirstMismatchingU32)
+# define ASMMemFirstMismatchingU32_EndProc              RT_MANGLER(ASMMemFirstMismatchingU32_EndProc)
+# define ASMMemIsZero                                   RT_MANGLER(ASMMemIsZero)
+# define ASMMemIsZero_EndProc                           RT_MANGLER(ASMMemIsZero_EndProc)
+# define ASMMemIsAllU8                                  RT_MANGLER(ASMMemIsAllU8)
+# define ASMMemIsAllU8_EndProc                          RT_MANGLER(ASMMemIsAllU8_EndProc)
+# define ASMMemZero32                                   RT_MANGLER(ASMMemZero32)
+# define ASMMemZero32_EndProc                           RT_MANGLER(ASMMemZero32_EndProc)
+# define ASMMemZeroPage                                 RT_MANGLER(ASMMemZeroPage)
+# define ASMMemZeroPage_EndProc                         RT_MANGLER(ASMMemZeroPage_EndProc)
+# define ASMNopPause                                    RT_MANGLER(ASMNopPause)
+# define ASMNopPause_EndProc                            RT_MANGLER(ASMNopPause_EndProc)
+# define ASMOutStrU16                                   RT_MANGLER(ASMOutStrU16)
+# define ASMOutStrU16_EndProc                           RT_MANGLER(ASMOutStrU16_EndProc)
+# define ASMOutStrU32                                   RT_MANGLER(ASMOutStrU32)
+# define ASMOutStrU32_EndProc                           RT_MANGLER(ASMOutStrU32_EndProc)
+# define ASMOutStrU8                                    RT_MANGLER(ASMOutStrU8)
+# define ASMOutStrU8_EndProc                            RT_MANGLER(ASMOutStrU8_EndProc)
+# define ASMOutU16                                      RT_MANGLER(ASMOutU16)
+# define ASMOutU16_EndProc                              RT_MANGLER(ASMOutU16_EndProc)
+# define ASMOutU32                                      RT_MANGLER(ASMOutU32)
+# define ASMOutU32_EndProc                              RT_MANGLER(ASMOutU32_EndProc)
+# define ASMOutU8                                       RT_MANGLER(ASMOutU8)
+# define ASMOutU8_EndProc                               RT_MANGLER(ASMOutU8_EndProc)
+# define ASMProbeReadByte                               RT_MANGLER(ASMProbeReadByte)
+# define ASMProbeReadByte_EndProc                       RT_MANGLER(ASMProbeReadByte_EndProc)
+# define ASMRdMsr                                       RT_MANGLER(ASMRdMsr)
+# define ASMRdMsr_EndProc                               RT_MANGLER(ASMRdMsr_EndProc)
+# define ASMRdMsr_High                                  RT_MANGLER(ASMRdMsr_High)
+# define ASMRdMsr_High_EndProc                          RT_MANGLER(ASMRdMsr_High_EndProc)
+# define ASMRdMsr_Low                                   RT_MANGLER(ASMRdMsr_Low)
+# define ASMRdMsr_Low_EndProc                           RT_MANGLER(ASMRdMsr_Low_EndProc)
+# define ASMRdMsrEx                                     RT_MANGLER(ASMRdMsrEx)
+# define ASMRdMsrEx_EndProc                             RT_MANGLER(ASMRdMsrEx_EndProc)
+# define ASMReadTSC                                     RT_MANGLER(ASMReadTSC)
+# define ASMReadTSC_EndProc                             RT_MANGLER(ASMReadTSC_EndProc)
+# define ASMReadTscWithAux                              RT_MANGLER(ASMReadTscWithAux)
+# define ASMReadTscWithAux_EndProc                      RT_MANGLER(ASMReadTscWithAux_EndProc)
+# define ASMReloadCR3                                   RT_MANGLER(ASMReloadCR3)
+# define ASMReloadCR3_EndProc                           RT_MANGLER(ASMReloadCR3_EndProc)
+# define ASMRotateLeftU32                               RT_MANGLER(ASMRotateLeftU32)
+# define ASMRotateLeftU32_EndProc                       RT_MANGLER(ASMRotateLeftU32_EndProc)
+# define ASMRotateRightU32                              RT_MANGLER(ASMRotateRightU32)
+# define ASMRotateRightU32_EndProc                      RT_MANGLER(ASMRotateRightU32_EndProc)
+# define ASMSerializeInstructionCpuId                   RT_MANGLER(ASMSerializeInstructionCpuId)
+# define ASMSerializeInstructionCpuId_EndProc           RT_MANGLER(ASMSerializeInstructionCpuId_EndProc)
+# define ASMSerializeInstructionIRet                    RT_MANGLER(ASMSerializeInstructionIRet)
+# define ASMSerializeInstructionIRet_EndProc            RT_MANGLER(ASMSerializeInstructionIRet_EndProc)
+# define ASMSerializeInstructionRdTscp                  RT_MANGLER(ASMSerializeInstructionRdTscp)
+# define ASMSerializeInstructionRdTscp_EndProc          RT_MANGLER(ASMSerializeInstructionRdTscp_EndProc)
+# define ASMSetCR0                                      RT_MANGLER(ASMSetCR0)
+# define ASMSetCR0_EndProc                              RT_MANGLER(ASMSetCR0_EndProc)
+# define ASMSetCR2                                      RT_MANGLER(ASMSetCR2)
+# define ASMSetCR2_EndProc                              RT_MANGLER(ASMSetCR2_EndProc)
+# define ASMSetCR3                                      RT_MANGLER(ASMSetCR3)
+# define ASMSetCR3_EndProc                              RT_MANGLER(ASMSetCR3_EndProc)
+# define ASMSetCR4                                      RT_MANGLER(ASMSetCR4)
+# define ASMSetCR4_EndProc                              RT_MANGLER(ASMSetCR4_EndProc)
+# define ASMSetDR0                                      RT_MANGLER(ASMSetDR0)
+# define ASMSetDR0_EndProc                              RT_MANGLER(ASMSetDR0_EndProc)
+# define ASMSetDR1                                      RT_MANGLER(ASMSetDR1)
+# define ASMSetDR1_EndProc                              RT_MANGLER(ASMSetDR1_EndProc)
+# define ASMSetDR2                                      RT_MANGLER(ASMSetDR2)
+# define ASMSetDR2_EndProc                              RT_MANGLER(ASMSetDR2_EndProc)
+# define ASMSetDR3                                      RT_MANGLER(ASMSetDR3)
+# define ASMSetDR3_EndProc                              RT_MANGLER(ASMSetDR3_EndProc)
+# define ASMSetDR6                                      RT_MANGLER(ASMSetDR6)
+# define ASMSetDR6_EndProc                              RT_MANGLER(ASMSetDR6_EndProc)
+# define ASMSetDR7                                      RT_MANGLER(ASMSetDR7)
+# define ASMSetDR7_EndProc                              RT_MANGLER(ASMSetDR7_EndProc)
+# define ASMSetFlags                                    RT_MANGLER(ASMSetFlags)
+# define ASMSetFlags_EndProc                            RT_MANGLER(ASMSetFlags_EndProc)
+# define ASMSetGDTR                                     RT_MANGLER(ASMSetGDTR)
+# define ASMSetGDTR_EndProc                             RT_MANGLER(ASMSetGDTR_EndProc)
+# define ASMSetIDTR                                     RT_MANGLER(ASMSetIDTR)
+# define ASMSetIDTR_EndProc                             RT_MANGLER(ASMSetIDTR_EndProc)
+# define ASMSetXcr0                                     RT_MANGLER(ASMSetXcr0)
+# define ASMSetXcr0_EndProc                             RT_MANGLER(ASMSetXcr0_EndProc)
+# define ASMWriteBackAndInvalidateCaches                RT_MANGLER(ASMWriteBackAndInvalidateCaches)
+# define ASMWriteBackAndInvalidateCaches_EndProc        RT_MANGLER(ASMWriteBackAndInvalidateCaches_EndProc)
+# define ASMWrMsr                                       RT_MANGLER(ASMWrMsr)
+# define ASMWrMsr_EndProc                               RT_MANGLER(ASMWrMsr_EndProc)
+# define ASMWrMsrEx                                     RT_MANGLER(ASMWrMsrEx)
+# define ASMWrMsrEx_EndProc                             RT_MANGLER(ASMWrMsrEx_EndProc)
+# define ASMXRstor                                      RT_MANGLER(ASMXRstor)
+# define ASMXRstor_EndProc                              RT_MANGLER(ASMXRstor_EndProc)
+# define ASMXSave                                       RT_MANGLER(ASMXSave)
+# define ASMXSave_EndProc                               RT_MANGLER(ASMXSave_EndProc)
+# define ASMFxRstor                                     RT_MANGLER(ASMFxRstor)
+# define ASMFxRstor_EndProc                             RT_MANGLER(ASMFxRstor_EndProc)
+# define ASMFxSave                                      RT_MANGLER(ASMFxSave)
+# define ASMFxSave_EndProc                              RT_MANGLER(ASMFxSave_EndProc)
+
+# define RTAssertAreQuiet                               RT_MANGLER(RTAssertAreQuiet)
+# define RTAssertMayPanic                               RT_MANGLER(RTAssertMayPanic)
+# define RTAssertMsg1                                   RT_MANGLER(RTAssertMsg1)
+# define RTAssertMsg1Weak                               RT_MANGLER(RTAssertMsg1Weak)
+# define RTAssertMsg2                                   RT_MANGLER(RTAssertMsg2)
+# define RTAssertMsg2Add                                RT_MANGLER(RTAssertMsg2Add)
+# define RTAssertMsg2AddV                               RT_MANGLER(RTAssertMsg2AddV)
+# define RTAssertMsg2AddWeak                            RT_MANGLER(RTAssertMsg2AddWeak)
+# define RTAssertMsg2AddWeakV                           RT_MANGLER(RTAssertMsg2AddWeakV)
+# define RTAssertMsg2V                                  RT_MANGLER(RTAssertMsg2V)
+# define RTAssertMsg2Weak                               RT_MANGLER(RTAssertMsg2Weak)
+# define RTAssertMsg2WeakV                              RT_MANGLER(RTAssertMsg2WeakV)
+# define RTAssertSetMayPanic                            RT_MANGLER(RTAssertSetMayPanic)
+# define RTAssertSetQuiet                               RT_MANGLER(RTAssertSetQuiet)
+# define RTAssertShouldPanic                            RT_MANGLER(RTAssertShouldPanic)
+# define RTAvlGCPhysDestroy                             RT_MANGLER(RTAvlGCPhysDestroy)
+# define RTAvlGCPhysDoWithAll                           RT_MANGLER(RTAvlGCPhysDoWithAll)
+# define RTAvlGCPhysGet                                 RT_MANGLER(RTAvlGCPhysGet)
+# define RTAvlGCPhysGetBestFit                          RT_MANGLER(RTAvlGCPhysGetBestFit)
+# define RTAvlGCPhysInsert                              RT_MANGLER(RTAvlGCPhysInsert)
+# define RTAvlGCPhysRemove                              RT_MANGLER(RTAvlGCPhysRemove)
+# define RTAvlGCPhysRemoveBestFit                       RT_MANGLER(RTAvlGCPhysRemoveBestFit)
+# define RTAvlGCPtrDestroy                              RT_MANGLER(RTAvlGCPtrDestroy)
+# define RTAvlGCPtrDoWithAll                            RT_MANGLER(RTAvlGCPtrDoWithAll)
+# define RTAvlGCPtrGet                                  RT_MANGLER(RTAvlGCPtrGet)
+# define RTAvlGCPtrGetBestFit                           RT_MANGLER(RTAvlGCPtrGetBestFit)
+# define RTAvlGCPtrInsert                               RT_MANGLER(RTAvlGCPtrInsert)
+# define RTAvlGCPtrRemove                               RT_MANGLER(RTAvlGCPtrRemove)
+# define RTAvlGCPtrRemoveBestFit                        RT_MANGLER(RTAvlGCPtrRemoveBestFit)
+# define RTAvlHCPhysDestroy                             RT_MANGLER(RTAvlHCPhysDestroy)
+# define RTAvlHCPhysDoWithAll                           RT_MANGLER(RTAvlHCPhysDoWithAll)
+# define RTAvlHCPhysGet                                 RT_MANGLER(RTAvlHCPhysGet)
+# define RTAvlHCPhysGetBestFit                          RT_MANGLER(RTAvlHCPhysGetBestFit)
+# define RTAvlHCPhysInsert                              RT_MANGLER(RTAvlHCPhysInsert)
+# define RTAvlHCPhysRemove                              RT_MANGLER(RTAvlHCPhysRemove)
+# define RTAvlHCPhysRemoveBestFit                       RT_MANGLER(RTAvlHCPhysRemoveBestFit)
+# define RTAvllU32Destroy                               RT_MANGLER(RTAvllU32Destroy)
+# define RTAvllU32DoWithAll                             RT_MANGLER(RTAvllU32DoWithAll)
+# define RTAvllU32Get                                   RT_MANGLER(RTAvllU32Get)
+# define RTAvllU32GetBestFit                            RT_MANGLER(RTAvllU32GetBestFit)
+# define RTAvllU32Insert                                RT_MANGLER(RTAvllU32Insert)
+# define RTAvllU32Remove                                RT_MANGLER(RTAvllU32Remove)
+# define RTAvllU32RemoveBestFit                         RT_MANGLER(RTAvllU32RemoveBestFit)
+# define RTAvllU32RemoveNode                            RT_MANGLER(RTAvllU32RemoveNode)
+# define RTAvloGCPhysDestroy                            RT_MANGLER(RTAvloGCPhysDestroy)
+# define RTAvloGCPhysDoWithAll                          RT_MANGLER(RTAvloGCPhysDoWithAll)
+# define RTAvloGCPhysGet                                RT_MANGLER(RTAvloGCPhysGet)
+# define RTAvloGCPhysGetBestFit                         RT_MANGLER(RTAvloGCPhysGetBestFit)
+# define RTAvloGCPhysInsert                             RT_MANGLER(RTAvloGCPhysInsert)
+# define RTAvloGCPhysRemove                             RT_MANGLER(RTAvloGCPhysRemove)
+# define RTAvloGCPhysRemoveBestFit                      RT_MANGLER(RTAvloGCPhysRemoveBestFit)
+# define RTAvloGCPtrDestroy                             RT_MANGLER(RTAvloGCPtrDestroy)
+# define RTAvloGCPtrDoWithAll                           RT_MANGLER(RTAvloGCPtrDoWithAll)
+# define RTAvloGCPtrGet                                 RT_MANGLER(RTAvloGCPtrGet)
+# define RTAvloGCPtrGetBestFit                          RT_MANGLER(RTAvloGCPtrGetBestFit)
+# define RTAvloGCPtrInsert                              RT_MANGLER(RTAvloGCPtrInsert)
+# define RTAvloGCPtrRemove                              RT_MANGLER(RTAvloGCPtrRemove)
+# define RTAvloGCPtrRemoveBestFit                       RT_MANGLER(RTAvloGCPtrRemoveBestFit)
+# define RTAvloHCPhysDestroy                            RT_MANGLER(RTAvloHCPhysDestroy)
+# define RTAvloHCPhysDoWithAll                          RT_MANGLER(RTAvloHCPhysDoWithAll)
+# define RTAvloHCPhysGet                                RT_MANGLER(RTAvloHCPhysGet)
+# define RTAvloHCPhysGetBestFit                         RT_MANGLER(RTAvloHCPhysGetBestFit)
+# define RTAvloHCPhysInsert                             RT_MANGLER(RTAvloHCPhysInsert)
+# define RTAvloHCPhysRemove                             RT_MANGLER(RTAvloHCPhysRemove)
+# define RTAvloHCPhysRemoveBestFit                      RT_MANGLER(RTAvloHCPhysRemoveBestFit)
+# define RTAvloIOPortDestroy                            RT_MANGLER(RTAvloIOPortDestroy)
+# define RTAvloIOPortDoWithAll                          RT_MANGLER(RTAvloIOPortDoWithAll)
+# define RTAvloIOPortGet                                RT_MANGLER(RTAvloIOPortGet)
+# define RTAvloIOPortGetBestFit                         RT_MANGLER(RTAvloIOPortGetBestFit)
+# define RTAvloIOPortInsert                             RT_MANGLER(RTAvloIOPortInsert)
+# define RTAvloIOPortRemove                             RT_MANGLER(RTAvloIOPortRemove)
+# define RTAvloIOPortRemoveBestFit                      RT_MANGLER(RTAvloIOPortRemoveBestFit)
+# define RTAvloU32Destroy                               RT_MANGLER(RTAvloU32Destroy)
+# define RTAvloU32DoWithAll                             RT_MANGLER(RTAvloU32DoWithAll)
+# define RTAvloU32Get                                   RT_MANGLER(RTAvloU32Get)
+# define RTAvloU32GetBestFit                            RT_MANGLER(RTAvloU32GetBestFit)
+# define RTAvloU32Insert                                RT_MANGLER(RTAvloU32Insert)
+# define RTAvloU32Remove                                RT_MANGLER(RTAvloU32Remove)
+# define RTAvloU32RemoveBestFit                         RT_MANGLER(RTAvloU32RemoveBestFit)
+# define RTAvlPVDestroy                                 RT_MANGLER(RTAvlPVDestroy)
+# define RTAvlPVDoWithAll                               RT_MANGLER(RTAvlPVDoWithAll)
+# define RTAvlPVGet                                     RT_MANGLER(RTAvlPVGet)
+# define RTAvlPVGetBestFit                              RT_MANGLER(RTAvlPVGetBestFit)
+# define RTAvlPVInsert                                  RT_MANGLER(RTAvlPVInsert)
+# define RTAvlPVRemove                                  RT_MANGLER(RTAvlPVRemove)
+# define RTAvlPVRemoveBestFit                           RT_MANGLER(RTAvlPVRemoveBestFit)
+# define RTAvlrFileOffsetDestroy                        RT_MANGLER(RTAvlrFileOffsetDestroy)
+# define RTAvlrFileOffsetDoWithAll                      RT_MANGLER(RTAvlrFileOffsetDoWithAll)
+# define RTAvlrFileOffsetGet                            RT_MANGLER(RTAvlrFileOffsetGet)
+# define RTAvlrFileOffsetGetBestFit                     RT_MANGLER(RTAvlrFileOffsetGetBestFit)
+# define RTAvlrFileOffsetGetLeft                        RT_MANGLER(RTAvlrFileOffsetGetLeft)
+# define RTAvlrFileOffsetGetRight                       RT_MANGLER(RTAvlrFileOffsetGetRight)
+# define RTAvlrFileOffsetGetRoot                        RT_MANGLER(RTAvlrFileOffsetGetRoot)
+# define RTAvlrFileOffsetInsert                         RT_MANGLER(RTAvlrFileOffsetInsert)
+# define RTAvlrFileOffsetRangeGet                       RT_MANGLER(RTAvlrFileOffsetRangeGet)
+# define RTAvlrFileOffsetRangeRemove                    RT_MANGLER(RTAvlrFileOffsetRangeRemove)
+# define RTAvlrFileOffsetRemove                         RT_MANGLER(RTAvlrFileOffsetRemove)
+# define RTAvlrGCPtrDestroy                             RT_MANGLER(RTAvlrGCPtrDestroy)
+# define RTAvlrGCPtrDoWithAll                           RT_MANGLER(RTAvlrGCPtrDoWithAll)
+# define RTAvlrGCPtrGet                                 RT_MANGLER(RTAvlrGCPtrGet)
+# define RTAvlrGCPtrGetBestFit                          RT_MANGLER(RTAvlrGCPtrGetBestFit)
+# define RTAvlrGCPtrGetLeft                             RT_MANGLER(RTAvlrGCPtrGetLeft)
+# define RTAvlrGCPtrGetRight                            RT_MANGLER(RTAvlrGCPtrGetRight)
+# define RTAvlrGCPtrGetRoot                             RT_MANGLER(RTAvlrGCPtrGetRoot)
+# define RTAvlrGCPtrInsert                              RT_MANGLER(RTAvlrGCPtrInsert)
+# define RTAvlrGCPtrRangeGet                            RT_MANGLER(RTAvlrGCPtrRangeGet)
+# define RTAvlrGCPtrRangeRemove                         RT_MANGLER(RTAvlrGCPtrRangeRemove)
+# define RTAvlrGCPtrRemove                              RT_MANGLER(RTAvlrGCPtrRemove)
+# define RTAvlroGCPhysDestroy                           RT_MANGLER(RTAvlroGCPhysDestroy)
+# define RTAvlroGCPhysDoWithAll                         RT_MANGLER(RTAvlroGCPhysDoWithAll)
+# define RTAvlroGCPhysGet                               RT_MANGLER(RTAvlroGCPhysGet)
+# define RTAvlroGCPhysGetBestFit                        RT_MANGLER(RTAvlroGCPhysGetBestFit)
+# define RTAvlroGCPhysGetLeft                           RT_MANGLER(RTAvlroGCPhysGetLeft)
+# define RTAvlroGCPhysGetRight                          RT_MANGLER(RTAvlroGCPhysGetRight)
+# define RTAvlroGCPhysGetRoot                           RT_MANGLER(RTAvlroGCPhysGetRoot)
+# define RTAvlroGCPhysInsert                            RT_MANGLER(RTAvlroGCPhysInsert)
+# define RTAvlroGCPhysRangeGet                          RT_MANGLER(RTAvlroGCPhysRangeGet)
+# define RTAvlroGCPhysRangeRemove                       RT_MANGLER(RTAvlroGCPhysRangeRemove)
+# define RTAvlroGCPhysRemove                            RT_MANGLER(RTAvlroGCPhysRemove)
+# define RTAvlroGCPtrDestroy                            RT_MANGLER(RTAvlroGCPtrDestroy)
+# define RTAvlroGCPtrDoWithAll                          RT_MANGLER(RTAvlroGCPtrDoWithAll)
+# define RTAvlroGCPtrGet                                RT_MANGLER(RTAvlroGCPtrGet)
+# define RTAvlroGCPtrGetBestFit                         RT_MANGLER(RTAvlroGCPtrGetBestFit)
+# define RTAvlroGCPtrGetLeft                            RT_MANGLER(RTAvlroGCPtrGetLeft)
+# define RTAvlroGCPtrGetRight                           RT_MANGLER(RTAvlroGCPtrGetRight)
+# define RTAvlroGCPtrGetRoot                            RT_MANGLER(RTAvlroGCPtrGetRoot)
+# define RTAvlroGCPtrInsert                             RT_MANGLER(RTAvlroGCPtrInsert)
+# define RTAvlroGCPtrRangeGet                           RT_MANGLER(RTAvlroGCPtrRangeGet)
+# define RTAvlroGCPtrRangeRemove                        RT_MANGLER(RTAvlroGCPtrRangeRemove)
+# define RTAvlroGCPtrRemove                             RT_MANGLER(RTAvlroGCPtrRemove)
+# define RTAvlroIOPortDestroy                           RT_MANGLER(RTAvlroIOPortDestroy)
+# define RTAvlroIOPortDoWithAll                         RT_MANGLER(RTAvlroIOPortDoWithAll)
+# define RTAvlroIOPortGet                               RT_MANGLER(RTAvlroIOPortGet)
+# define RTAvlroIOPortInsert                            RT_MANGLER(RTAvlroIOPortInsert)
+# define RTAvlroIOPortRangeGet                          RT_MANGLER(RTAvlroIOPortRangeGet)
+# define RTAvlroIOPortRangeRemove                       RT_MANGLER(RTAvlroIOPortRangeRemove)
+# define RTAvlroIOPortRemove                            RT_MANGLER(RTAvlroIOPortRemove)
+# define RTAvlrooGCPtrDestroy                           RT_MANGLER(RTAvlrooGCPtrDestroy)
+# define RTAvlrooGCPtrDoWithAll                         RT_MANGLER(RTAvlrooGCPtrDoWithAll)
+# define RTAvlrooGCPtrGet                               RT_MANGLER(RTAvlrooGCPtrGet)
+# define RTAvlrooGCPtrGetBestFit                        RT_MANGLER(RTAvlrooGCPtrGetBestFit)
+# define RTAvlrooGCPtrGetLeft                           RT_MANGLER(RTAvlrooGCPtrGetLeft)
+# define RTAvlrooGCPtrGetNextEqual                      RT_MANGLER(RTAvlrooGCPtrGetNextEqual)
+# define RTAvlrooGCPtrGetRight                          RT_MANGLER(RTAvlrooGCPtrGetRight)
+# define RTAvlrooGCPtrGetRoot                           RT_MANGLER(RTAvlrooGCPtrGetRoot)
+# define RTAvlrooGCPtrInsert                            RT_MANGLER(RTAvlrooGCPtrInsert)
+# define RTAvlrooGCPtrRangeGet                          RT_MANGLER(RTAvlrooGCPtrRangeGet)
+# define RTAvlrooGCPtrRangeRemove                       RT_MANGLER(RTAvlrooGCPtrRangeRemove)
+# define RTAvlrooGCPtrRemove                            RT_MANGLER(RTAvlrooGCPtrRemove)
+# define RTAvlrPVDestroy                                RT_MANGLER(RTAvlrPVDestroy)
+# define RTAvlrPVDoWithAll                              RT_MANGLER(RTAvlrPVDoWithAll)
+# define RTAvlrPVGet                                    RT_MANGLER(RTAvlrPVGet)
+# define RTAvlrPVGetBestFit                             RT_MANGLER(RTAvlrPVGetBestFit)
+# define RTAvlrPVInsert                                 RT_MANGLER(RTAvlrPVInsert)
+# define RTAvlrPVRangeGet                               RT_MANGLER(RTAvlrPVRangeGet)
+# define RTAvlrPVRangeRemove                            RT_MANGLER(RTAvlrPVRangeRemove)
+# define RTAvlrPVRemove                                 RT_MANGLER(RTAvlrPVRemove)
+# define RTAvlrPVRemoveBestFit                          RT_MANGLER(RTAvlrPVRemoveBestFit)
+# define RTAvlrU64Destroy                               RT_MANGLER(RTAvlrU64Destroy)
+# define RTAvlrU64DoWithAll                             RT_MANGLER(RTAvlrU64DoWithAll)
+# define RTAvlrU64Get                                   RT_MANGLER(RTAvlrU64Get)
+# define RTAvlrU64GetBestFit                            RT_MANGLER(RTAvlrU64GetBestFit)
+# define RTAvlrU64Insert                                RT_MANGLER(RTAvlrU64Insert)
+# define RTAvlrU64RangeGet                              RT_MANGLER(RTAvlrU64RangeGet)
+# define RTAvlrU64RangeRemove                           RT_MANGLER(RTAvlrU64RangeRemove)
+# define RTAvlrU64Remove                                RT_MANGLER(RTAvlrU64Remove)
+# define RTAvlrU64RemoveBestFit                         RT_MANGLER(RTAvlrU64RemoveBestFit)
+# define RTAvlrUIntPtrDestroy                           RT_MANGLER(RTAvlrUIntPtrDestroy)
+# define RTAvlrUIntPtrDoWithAll                         RT_MANGLER(RTAvlrUIntPtrDoWithAll)
+# define RTAvlrUIntPtrGet                               RT_MANGLER(RTAvlrUIntPtrGet)
+# define RTAvlrUIntPtrGetBestFit                        RT_MANGLER(RTAvlrUIntPtrGetBestFit)
+# define RTAvlrUIntPtrGetLeft                           RT_MANGLER(RTAvlrUIntPtrGetLeft)
+# define RTAvlrUIntPtrGetRight                          RT_MANGLER(RTAvlrUIntPtrGetRight)
+# define RTAvlrUIntPtrGetRoot                           RT_MANGLER(RTAvlrUIntPtrGetRoot)
+# define RTAvlrUIntPtrInsert                            RT_MANGLER(RTAvlrUIntPtrInsert)
+# define RTAvlrUIntPtrRangeGet                          RT_MANGLER(RTAvlrUIntPtrRangeGet)
+# define RTAvlrUIntPtrRangeRemove                       RT_MANGLER(RTAvlrUIntPtrRangeRemove)
+# define RTAvlrUIntPtrRemove                            RT_MANGLER(RTAvlrUIntPtrRemove)
+# define RTAvlU32Destroy                                RT_MANGLER(RTAvlU32Destroy)
+# define RTAvlU32DoWithAll                              RT_MANGLER(RTAvlU32DoWithAll)
+# define RTAvlU32Get                                    RT_MANGLER(RTAvlU32Get)
+# define RTAvlU32GetBestFit                             RT_MANGLER(RTAvlU32GetBestFit)
+# define RTAvlU32Insert                                 RT_MANGLER(RTAvlU32Insert)
+# define RTAvlU32Remove                                 RT_MANGLER(RTAvlU32Remove)
+# define RTAvlU32RemoveBestFit                          RT_MANGLER(RTAvlU32RemoveBestFit)
+# define RTAvlUIntPtrDestroy                            RT_MANGLER(RTAvlUIntPtrDestroy)
+# define RTAvlUIntPtrDoWithAll                          RT_MANGLER(RTAvlUIntPtrDoWithAll)
+# define RTAvlUIntPtrGet                                RT_MANGLER(RTAvlUIntPtrGet)
+# define RTAvlUIntPtrGetBestFit                         RT_MANGLER(RTAvlUIntPtrGetBestFit)
+# define RTAvlUIntPtrGetLeft                            RT_MANGLER(RTAvlUIntPtrGetLeft)
+# define RTAvlUIntPtrGetRight                           RT_MANGLER(RTAvlUIntPtrGetRight)
+# define RTAvlUIntPtrGetRoot                            RT_MANGLER(RTAvlUIntPtrGetRoot)
+# define RTAvlUIntPtrInsert                             RT_MANGLER(RTAvlUIntPtrInsert)
+# define RTAvlUIntPtrRemove                             RT_MANGLER(RTAvlUIntPtrRemove)
+# define RTAvlULDestroy                                 RT_MANGLER(RTAvlULDestroy)
+# define RTAvlULDoWithAll                               RT_MANGLER(RTAvlULDoWithAll)
+# define RTAvlULGet                                     RT_MANGLER(RTAvlULGet)
+# define RTAvlULGetBestFit                              RT_MANGLER(RTAvlULGetBestFit)
+# define RTAvlULInsert                                  RT_MANGLER(RTAvlULInsert)
+# define RTAvlULRemove                                  RT_MANGLER(RTAvlULRemove)
+# define RTAvlULRemoveBestFit                           RT_MANGLER(RTAvlULRemoveBestFit)
+# define RTBase64Decode                                 RT_MANGLER(RTBase64Decode)
+# define RTBase64DecodeEx                               RT_MANGLER(RTBase64DecodeEx)
+# define RTBase64DecodedSize                            RT_MANGLER(RTBase64DecodedSize)
+# define RTBase64DecodedSizeEx                          RT_MANGLER(RTBase64DecodedSizeEx)
+# define RTBase64Encode                                 RT_MANGLER(RTBase64Encode)
+# define RTBase64EncodedLength                          RT_MANGLER(RTBase64EncodedLength)
+# define RTBldCfgCompiler                               RT_MANGLER(RTBldCfgCompiler)
+# define RTBldCfgRevision                               RT_MANGLER(RTBldCfgRevision)
+# define RTBldCfgRevisionStr                            RT_MANGLER(RTBldCfgRevisionStr)
+# define RTBldCfgTarget                                 RT_MANGLER(RTBldCfgTarget)
+# define RTBldCfgTargetArch                             RT_MANGLER(RTBldCfgTargetArch)
+# define RTBldCfgTargetDotArch                          RT_MANGLER(RTBldCfgTargetDotArch)
+# define RTBldCfgType                                   RT_MANGLER(RTBldCfgType)
+# define RTBldCfgVersion                                RT_MANGLER(RTBldCfgVersion)
+# define RTBldCfgVersionBuild                           RT_MANGLER(RTBldCfgVersionBuild)
+# define RTBldCfgVersionMajor                           RT_MANGLER(RTBldCfgVersionMajor)
+# define RTBldCfgVersionMinor                           RT_MANGLER(RTBldCfgVersionMinor)
+# define RTCdromOpen                                    RT_MANGLER(RTCdromOpen)
+# define RTCdromRetain                                  RT_MANGLER(RTCdromRetain)
+# define RTCdromRelease                                 RT_MANGLER(RTCdromRelease)
+# define RTCdromQueryMountPoint                         RT_MANGLER(RTCdromQueryMountPoint)
+# define RTCdromUnmount                                 RT_MANGLER(RTCdromUnmount)
+# define RTCdromEject                                   RT_MANGLER(RTCdromEject)
+# define RTCdromLock                                    RT_MANGLER(RTCdromLock)
+# define RTCdromUnlock                                  RT_MANGLER(RTCdromUnlock)
+# define RTCdromCount                                   RT_MANGLER(RTCdromCount)
+# define RTCdromOrdinalToName                           RT_MANGLER(RTCdromOrdinalToName)
+# define RTCdromOpenByOrdinal                           RT_MANGLER(RTCdromOpenByOrdinal)
+# define RTCidrStrToIPv4                                RT_MANGLER(RTCidrStrToIPv4)
+# define RTCircBufAcquireReadBlock                      RT_MANGLER(RTCircBufAcquireReadBlock)
+# define RTCircBufAcquireWriteBlock                     RT_MANGLER(RTCircBufAcquireWriteBlock)
+# define RTCircBufCreate                                RT_MANGLER(RTCircBufCreate)
+# define RTCircBufDestroy                               RT_MANGLER(RTCircBufDestroy)
+# define RTCircBufFree                                  RT_MANGLER(RTCircBufFree)
+# define RTCircBufIsReading                             RT_MANGLER(RTCircBufIsReading)
+# define RTCircBufIsWriting                             RT_MANGLER(RTCircBufIsWriting)
+# define RTCircBufOffsetRead                            RT_MANGLER(RTCircBufOffsetRead)
+# define RTCircBufOffsetWrite                           RT_MANGLER(RTCircBufOffsetWrite)
+# define RTCircBufReleaseReadBlock                      RT_MANGLER(RTCircBufReleaseReadBlock)
+# define RTCircBufReleaseWriteBlock                     RT_MANGLER(RTCircBufReleaseWriteBlock)
+# define RTCircBufReset                                 RT_MANGLER(RTCircBufReset)
+# define RTCircBufSize                                  RT_MANGLER(RTCircBufSize)
+# define RTCircBufUsed                                  RT_MANGLER(RTCircBufUsed)
+# define RTCoreDumperDisable                            RT_MANGLER(RTCoreDumperDisable)  /* solaris */
+# define RTCoreDumperSetup                              RT_MANGLER(RTCoreDumperSetup)    /* solaris */
+# define RTCoreDumperTakeDump                           RT_MANGLER(RTCoreDumperTakeDump) /* solaris */
+# define RTCrc32                                        RT_MANGLER(RTCrc32)
+# define RTCrc32Finish                                  RT_MANGLER(RTCrc32Finish)
+# define RTCrc32Process                                 RT_MANGLER(RTCrc32Process)
+# define RTCrc32Start                                   RT_MANGLER(RTCrc32Start)
+# define RTCrc32C                                       RT_MANGLER(RTCrc32C)
+# define RTCrc32CFinish                                 RT_MANGLER(RTCrc32CFinish)
+# define RTCrc32CProcess                                RT_MANGLER(RTCrc32CProcess)
+# define RTCrc32CStart                                  RT_MANGLER(RTCrc32CStart)
+# define RTCrc64                                        RT_MANGLER(RTCrc64)
+# define RTCrc64Finish                                  RT_MANGLER(RTCrc64Finish)
+# define RTCrc64Process                                 RT_MANGLER(RTCrc64Process)
+# define RTCrc64Start                                   RT_MANGLER(RTCrc64Start)
+# define RTCrcAdler32                                   RT_MANGLER(RTCrcAdler32)
+# define RTCrcAdler32Finish                             RT_MANGLER(RTCrcAdler32Finish)
+# define RTCrcAdler32Process                            RT_MANGLER(RTCrcAdler32Process)
+# define RTCrcAdler32Start                              RT_MANGLER(RTCrcAdler32Start)
+# define RTCritSectDelete                               RT_MANGLER(RTCritSectDelete)
+# define RTCritSectEnter                                RT_MANGLER(RTCritSectEnter)
+# define RTCritSectEnterDebug                           RT_MANGLER(RTCritSectEnterDebug)
+# define RTCritSectEnterMultiple                        RT_MANGLER(RTCritSectEnterMultiple)
+# define RTCritSectEnterMultipleDebug                   RT_MANGLER(RTCritSectEnterMultipleDebug)
+# define RTCritSectInit                                 RT_MANGLER(RTCritSectInit)
+# define RTCritSectInitEx                               RT_MANGLER(RTCritSectInitEx)
+# define RTCritSectLeave                                RT_MANGLER(RTCritSectLeave)
+# define RTCritSectLeaveMultiple                        RT_MANGLER(RTCritSectLeaveMultiple)
+# define RTCritSectSetSubClass                          RT_MANGLER(RTCritSectSetSubClass)
+# define RTCritSectTryEnter                             RT_MANGLER(RTCritSectTryEnter)
+# define RTCritSectTryEnterDebug                        RT_MANGLER(RTCritSectTryEnterDebug)
+# define RTCritSectRwDelete                             RT_MANGLER(RTCritSectRwDelete)
+# define RTCritSectRwEnterExcl                          RT_MANGLER(RTCritSectRwEnterExcl)
+# define RTCritSectRwEnterExclDebug                     RT_MANGLER(RTCritSectRwEnterExclDebug)
+# define RTCritSectRwEnterShared                        RT_MANGLER(RTCritSectRwEnterShared)
+# define RTCritSectRwEnterSharedDebug                   RT_MANGLER(RTCritSectRwEnterSharedDebug)
+# define RTCritSectRwGetReadCount                       RT_MANGLER(RTCritSectRwGetReadCount)
+# define RTCritSectRwGetWriteRecursion                  RT_MANGLER(RTCritSectRwGetWriteRecursion)
+# define RTCritSectRwGetWriterReadRecursion             RT_MANGLER(RTCritSectRwGetWriterReadRecursion)
+# define RTCritSectRwInit                               RT_MANGLER(RTCritSectRwInit)
+# define RTCritSectRwInitEx                             RT_MANGLER(RTCritSectRwInitEx)
+# define RTCritSectRwIsReadOwner                        RT_MANGLER(RTCritSectRwIsReadOwner)
+# define RTCritSectRwIsWriteOwner                       RT_MANGLER(RTCritSectRwIsWriteOwner)
+# define RTCritSectRwLeaveExcl                          RT_MANGLER(RTCritSectRwLeaveExcl)
+# define RTCritSectRwLeaveShared                        RT_MANGLER(RTCritSectRwLeaveShared)
+# define RTCritSectRwSetSubClass                        RT_MANGLER(RTCritSectRwSetSubClass)
+# define RTCritSectRwTryEnterExcl                       RT_MANGLER(RTCritSectRwTryEnterExcl)
+# define RTCritSectRwTryEnterExclDebug                  RT_MANGLER(RTCritSectRwTryEnterExclDebug)
+# define RTCritSectRwTryEnterShared                     RT_MANGLER(RTCritSectRwTryEnterShared)
+# define RTCritSectRwTryEnterSharedDebug                RT_MANGLER(RTCritSectRwTryEnterSharedDebug)
+# define RTDbgAsCreate                                  RT_MANGLER(RTDbgAsCreate)
+# define RTDbgAsCreateF                                 RT_MANGLER(RTDbgAsCreateF)
+# define RTDbgAsCreateV                                 RT_MANGLER(RTDbgAsCreateV)
+# define RTDbgAsFirstAddr                               RT_MANGLER(RTDbgAsFirstAddr)
+# define RTDbgAsLastAddr                                RT_MANGLER(RTDbgAsLastAddr)
+# define RTDbgAsLineAdd                                 RT_MANGLER(RTDbgAsLineAdd)
+# define RTDbgAsLineByAddr                              RT_MANGLER(RTDbgAsLineByAddr)
+# define RTDbgAsLineByAddrA                             RT_MANGLER(RTDbgAsLineByAddrA)
+# define RTDbgAsLockExcl                                RT_MANGLER(RTDbgAsLockExcl)
+# define RTDbgAsModuleByAddr                            RT_MANGLER(RTDbgAsModuleByAddr)
+# define RTDbgAsModuleByIndex                           RT_MANGLER(RTDbgAsModuleByIndex)
+# define RTDbgAsModuleByName                            RT_MANGLER(RTDbgAsModuleByName)
+# define RTDbgAsModuleCount                             RT_MANGLER(RTDbgAsModuleCount)
+# define RTDbgAsModuleLink                              RT_MANGLER(RTDbgAsModuleLink)
+# define RTDbgAsModuleLinkSeg                           RT_MANGLER(RTDbgAsModuleLinkSeg)
+# define RTDbgAsModuleQueryMapByIndex                   RT_MANGLER(RTDbgAsModuleQueryMapByIndex)
+# define RTDbgAsModuleUnlink                            RT_MANGLER(RTDbgAsModuleUnlink)
+# define RTDbgAsModuleUnlinkByAddr                      RT_MANGLER(RTDbgAsModuleUnlinkByAddr)
+# define RTDbgAsName                                    RT_MANGLER(RTDbgAsName)
+# define RTDbgAsRelease                                 RT_MANGLER(RTDbgAsRelease)
+# define RTDbgAsRetain                                  RT_MANGLER(RTDbgAsRetain)
+# define RTDbgAsSymbolAdd                               RT_MANGLER(RTDbgAsSymbolAdd)
+# define RTDbgAsSymbolByAddr                            RT_MANGLER(RTDbgAsSymbolByAddr)
+# define RTDbgAsSymbolByAddrA                           RT_MANGLER(RTDbgAsSymbolByAddrA)
+# define RTDbgAsSymbolByName                            RT_MANGLER(RTDbgAsSymbolByName)
+# define RTDbgAsSymbolByNameA                           RT_MANGLER(RTDbgAsSymbolByNameA)
+# define RTDbgAsUnlockExcl                              RT_MANGLER(RTDbgAsUnlockExcl)
+# define RTDbgCfgCreate                                 RT_MANGLER(RTDbgCfgCreate)
+# define RTDbgCfgRetain                                 RT_MANGLER(RTDbgCfgRetain)
+# define RTDbgCfgRelease                                RT_MANGLER(RTDbgCfgRelease)
+# define RTDbgCfgChangeString                           RT_MANGLER(RTDbgCfgChangeString)
+# define RTDbgCfgChangeUInt                             RT_MANGLER(RTDbgCfgChangeUInt)
+# define RTDbgCfgQueryString                            RT_MANGLER(RTDbgCfgQueryString)
+# define RTDbgCfgQueryUInt                              RT_MANGLER(RTDbgCfgQueryUInt)
+# define RTDbgCfgOpenDbg                                RT_MANGLER(RTDbgCfgOpenDbg)
+# define RTDbgCfgOpenDsymBundle                         RT_MANGLER(RTDbgCfgOpenDsymBundle)
+# define RTDbgCfgOpenMachOImage                         RT_MANGLER(RTDbgCfgOpenMachOImage)
+# define RTDbgCfgOpenDwo                                RT_MANGLER(RTDbgCfgOpenDwo)
+# define RTDbgCfgOpenPdb70                              RT_MANGLER(RTDbgCfgOpenPdb70)
+# define RTDbgCfgOpenPdb20                              RT_MANGLER(RTDbgCfgOpenPdb20)
+# define RTDbgCfgOpenPeImage                            RT_MANGLER(RTDbgCfgOpenPeImage)
+# define RTDbgCfgSetLogCallback                         RT_MANGLER(RTDbgCfgSetLogCallback)
+# define RTDbgLineAlloc                                 RT_MANGLER(RTDbgLineAlloc)
+# define RTDbgLineDup                                   RT_MANGLER(RTDbgLineDup)
+# define RTDbgLineFree                                  RT_MANGLER(RTDbgLineFree)
+# define RTDbgModCreate                                 RT_MANGLER(RTDbgModCreate)
+# define RTDbgModCreateFromDbg                          RT_MANGLER(RTDbgModCreateFromDbg)
+# define RTDbgModCreateFromDwo                          RT_MANGLER(RTDbgModCreateFromDwo)
+# define RTDbgModCreateFromImage                        RT_MANGLER(RTDbgModCreateFromImage)
+# define RTDbgModCreateFromMap                          RT_MANGLER(RTDbgModCreateFromMap)
+# define RTDbgModCreateFromPdb                          RT_MANGLER(RTDbgModCreateFromPdb)
+# define RTDbgModCreateFromPeImage                      RT_MANGLER(RTDbgModCreateFromPeImage)
+# define RTDbgModCreateFromMachOImage                   RT_MANGLER(RTDbgModCreateFromMachOImage)
+# define RTDbgModGetTag                                 RT_MANGLER(RTDbgModGetTag)
+# define RTDbgModImageSize                              RT_MANGLER(RTDbgModImageSize)
+# define RTDbgModIsDeferred                             RT_MANGLER(RTDbgModIsDeferred)
+# define RTDbgModIsExports                              RT_MANGLER(RTDbgModIsExports)
+# define RTDbgModLineAdd                                RT_MANGLER(RTDbgModLineAdd)
+# define RTDbgModLineByAddr                             RT_MANGLER(RTDbgModLineByAddr)
+# define RTDbgModLineByAddrA                            RT_MANGLER(RTDbgModLineByAddrA)
+# define RTDbgModLineByOrdinal                          RT_MANGLER(RTDbgModLineByOrdinal)
+# define RTDbgModLineByOrdinalA                         RT_MANGLER(RTDbgModLineByOrdinalA)
+# define RTDbgModLineCount                              RT_MANGLER(RTDbgModLineCount)
+# define RTDbgModName                                   RT_MANGLER(RTDbgModName)
+# define RTDbgModDebugFile                              RT_MANGLER(RTDbgModDebugFile)
+# define RTDbgModImageFile                              RT_MANGLER(RTDbgModImageFile)
+# define RTDbgModImageFileUsed                          RT_MANGLER(RTDbgModImageFileUsed)
+# define RTDbgModRelease                                RT_MANGLER(RTDbgModRelease)
+# define RTDbgModRemoveAll                              RT_MANGLER(RTDbgModRemoveAll)
+# define RTDbgModRetain                                 RT_MANGLER(RTDbgModRetain)
+# define RTDbgModRvaToSegOff                            RT_MANGLER(RTDbgModRvaToSegOff)
+# define RTDbgModSegmentAdd                             RT_MANGLER(RTDbgModSegmentAdd)
+# define RTDbgModSegmentByIndex                         RT_MANGLER(RTDbgModSegmentByIndex)
+# define RTDbgModSegmentCount                           RT_MANGLER(RTDbgModSegmentCount)
+# define RTDbgModSegmentRva                             RT_MANGLER(RTDbgModSegmentRva)
+# define RTDbgModSegmentSize                            RT_MANGLER(RTDbgModSegmentSize)
+# define RTDbgModSetTag                                 RT_MANGLER(RTDbgModSetTag)
+# define RTDbgModSymbolAdd                              RT_MANGLER(RTDbgModSymbolAdd)
+# define RTDbgModSymbolByAddr                           RT_MANGLER(RTDbgModSymbolByAddr)
+# define RTDbgModSymbolByAddrA                          RT_MANGLER(RTDbgModSymbolByAddrA)
+# define RTDbgModSymbolByName                           RT_MANGLER(RTDbgModSymbolByName)
+# define RTDbgModSymbolByNameA                          RT_MANGLER(RTDbgModSymbolByNameA)
+# define RTDbgModSymbolByOrdinal                        RT_MANGLER(RTDbgModSymbolByOrdinal)
+# define RTDbgModSymbolByOrdinalA                       RT_MANGLER(RTDbgModSymbolByOrdinalA)
+# define RTDbgModSymbolCount                            RT_MANGLER(RTDbgModSymbolCount)
+# define RTDbgSymbolAlloc                               RT_MANGLER(RTDbgSymbolAlloc)
+# define RTDbgSymbolDup                                 RT_MANGLER(RTDbgSymbolDup)
+# define RTDbgSymbolFree                                RT_MANGLER(RTDbgSymbolFree)
+# define RTDirClose                                     RT_MANGLER(RTDirClose)
+# define RTDirCreate                                    RT_MANGLER(RTDirCreate)
+# define RTDirCreateFullPath                            RT_MANGLER(RTDirCreateFullPath)
+# define RTDirCreateTemp                                RT_MANGLER(RTDirCreateTemp)
+# define RTDirCreateTempSecure                          RT_MANGLER(RTDirCreateTempSecure)
+# define RTDirCreateUniqueNumbered                      RT_MANGLER(RTDirCreateUniqueNumbered)
+# define RTDirEntryIsStdDotLink                         RT_MANGLER(RTDirEntryIsStdDotLink)
+# define RTDirEntryExIsStdDotLink                       RT_MANGLER(RTDirEntryExIsStdDotLink)
+# define RTDirExists                                    RT_MANGLER(RTDirExists)
+# define RTDirFlush                                     RT_MANGLER(RTDirFlush)
+# define RTDirFlushParent                               RT_MANGLER(RTDirFlushParent)
+# define RTDirOpen                                      RT_MANGLER(RTDirOpen)
+# define RTDirOpenFiltered                              RT_MANGLER(RTDirOpenFiltered)
+# define RTDirQueryInfo                                 RT_MANGLER(RTDirQueryInfo)
+# define RTDirQueryUnknownType                          RT_MANGLER(RTDirQueryUnknownType)
+# define RTDirQueryUnknownTypeEx                        RT_MANGLER(RTDirQueryUnknownTypeEx)
+# define RTDirRead                                      RT_MANGLER(RTDirRead)
+# define RTDirReadEx                                    RT_MANGLER(RTDirReadEx)
+# define RTDirRemove                                    RT_MANGLER(RTDirRemove)
+# define RTDirRemoveRecursive                           RT_MANGLER(RTDirRemoveRecursive)
+# define RTDirRename                                    RT_MANGLER(RTDirRename)
+# define RTDirSetTimes                                  RT_MANGLER(RTDirSetTimes)
+# define RTDvmCreate                                    RT_MANGLER(RTDvmCreate)
+# define RTDvmRetain                                    RT_MANGLER(RTDvmRetain)
+# define RTDvmRelease                                   RT_MANGLER(RTDvmRelease)
+# define RTDvmMapOpen                                   RT_MANGLER(RTDvmMapOpen)
+# define RTDvmMapInitialize                             RT_MANGLER(RTDvmMapInitialize)
+# define RTDvmMapGetFormat                              RT_MANGLER(RTDvmMapGetFormat)
+# define RTDvmMapGetValidVolumes                        RT_MANGLER(RTDvmMapGetValidVolumes)
+# define RTDvmMapGetMaxVolumes                          RT_MANGLER(RTDvmMapGetMaxVolumes)
+# define RTDvmMapQueryBlockStatus                       RT_MANGLER(RTDvmMapQueryBlockStatus)
+# define RTDvmMapQueryFirstVolume                       RT_MANGLER(RTDvmMapQueryFirstVolume)
+# define RTDvmMapQueryNextVolume                        RT_MANGLER(RTDvmMapQueryNextVolume)
+# define RTDvmVolumeRetain                              RT_MANGLER(RTDvmVolumeRetain)
+# define RTDvmVolumeRelease                             RT_MANGLER(RTDvmVolumeRelease)
+# define RTDvmVolumeGetSize                             RT_MANGLER(RTDvmVolumeGetSize)
+# define RTDvmVolumeQueryName                           RT_MANGLER(RTDvmVolumeQueryName)
+# define RTDvmVolumeGetType                             RT_MANGLER(RTDvmVolumeGetType)
+# define RTDvmVolumeGetFlags                            RT_MANGLER(RTDvmVolumeGetFlags)
+# define RTDvmVolumeRead                                RT_MANGLER(RTDvmVolumeRead)
+# define RTDvmVolumeWrite                               RT_MANGLER(RTDvmVolumeWrite)
+# define RTDvmVolumeSetQueryBlockStatusCallback         RT_MANGLER(RTDvmVolumeSetQueryBlockStatusCallback)
+# define RTDvmVolumeTypeGetDescr                        RT_MANGLER(RTDvmVolumeTypeGetDescr)
+# define RTDvmVolumeCreateVfsFile                       RT_MANGLER(RTDvmVolumeCreateVfsFile)
+# define RTEnvApplyChanges                              RT_MANGLER(RTEnvApplyChanges)
+# define RTEnvClone                                     RT_MANGLER(RTEnvClone)
+# define RTEnvCloneUtf16Block                           RT_MANGLER(RTEnvCloneUtf16Block)
+# define RTEnvCountEx                                   RT_MANGLER(RTEnvCountEx)
+# define RTEnvCreate                                    RT_MANGLER(RTEnvCreate)
+# define RTEnvCreateChangeRecord                        RT_MANGLER(RTEnvCreateChangeRecord)
+# define RTEnvDestroy                                   RT_MANGLER(RTEnvDestroy)
+# define RTEnvDupEx                                     RT_MANGLER(RTEnvDupEx)
+# define RTEnvExist                                     RT_MANGLER(RTEnvExist)
+# define RTEnvExistsBad                                 RT_MANGLER(RTEnvExistsBad)
+# define RTEnvExistsUtf8                                RT_MANGLER(RTEnvExistsUtf8)
+# define RTEnvExistEx                                   RT_MANGLER(RTEnvExistEx)
+# define RTEnvFreeUtf8Block                             RT_MANGLER(RTEnvFreeUtf8Block)
+# define RTEnvFreeUtf16Block                            RT_MANGLER(RTEnvFreeUtf16Block)
+# define RTEnvGet                                       RT_MANGLER(RTEnvGet)
+# define RTEnvGetBad                                    RT_MANGLER(RTEnvGetBad)
+# define RTEnvGetByIndexEx                              RT_MANGLER(RTEnvGetByIndexEx)
+# define RTEnvGetByIndexRawEx                           RT_MANGLER(RTEnvGetByIndexRawEx)
+# define RTEnvGetUtf8                                   RT_MANGLER(RTEnvGetUtf8)
+# define RTEnvGetEx                                     RT_MANGLER(RTEnvGetEx)
+# define RTEnvGetExecEnvP                               RT_MANGLER(RTEnvGetExecEnvP)
+# define RTEnvIsChangeRecord                            RT_MANGLER(RTEnvIsChangeRecord)
+# define RTEnvPut                                       RT_MANGLER(RTEnvPut)
+# define RTEnvPutBad                                    RT_MANGLER(RTEnvPutBad)
+# define RTEnvPutUtf8                                   RT_MANGLER(RTEnvPutUtf8)
+# define RTEnvPutEx                                     RT_MANGLER(RTEnvPutEx)
+# define RTEnvQueryUtf16Block                           RT_MANGLER(RTEnvQueryUtf16Block)
+# define RTEnvQueryUtf8Block                            RT_MANGLER(RTEnvQueryUtf8Block)
+# define RTEnvReset                                     RT_MANGLER(RTEnvReset)
+# define RTEnvSet                                       RT_MANGLER(RTEnvSet)
+# define RTEnvSetBad                                    RT_MANGLER(RTEnvSetBad)
+# define RTEnvSetUtf8                                   RT_MANGLER(RTEnvSetUtf8)
+# define RTEnvSetEx                                     RT_MANGLER(RTEnvSetEx)
+# define RTEnvUnset                                     RT_MANGLER(RTEnvUnset)
+# define RTEnvUnsetBad                                  RT_MANGLER(RTEnvUnsetBad)
+# define RTEnvUnsetUtf8                                 RT_MANGLER(RTEnvUnsetUtf8)
+# define RTEnvUnsetEx                                   RT_MANGLER(RTEnvUnsetEx)
+# define RTErrCOMGet                                    RT_MANGLER(RTErrCOMGet)
+# define RTErrConvertFromErrno                          RT_MANGLER(RTErrConvertFromErrno)
+# define RTErrConvertToErrno                            RT_MANGLER(RTErrConvertToErrno)
+# define RTErrGet                                       RT_MANGLER(RTErrGet)
+# define RTErrInfoAlloc                                 RT_MANGLER(RTErrInfoAlloc)
+# define RTErrInfoAllocEx                               RT_MANGLER(RTErrInfoAllocEx)
+# define RTErrInfoFree                                  RT_MANGLER(RTErrInfoFree)
+# define RTErrInfoSet                                   RT_MANGLER(RTErrInfoSet)
+# define RTErrInfoSetF                                  RT_MANGLER(RTErrInfoSetF)
+# define RTErrInfoSetV                                  RT_MANGLER(RTErrInfoSetV)
+# define RTErrVarsAreEqual                              RT_MANGLER(RTErrVarsAreEqual)
+# define RTErrVarsHaveChanged                           RT_MANGLER(RTErrVarsHaveChanged)
+# define RTErrVarsRestore                               RT_MANGLER(RTErrVarsRestore)
+# define RTErrVarsSave                                  RT_MANGLER(RTErrVarsSave)
+# define RTFileAioCtxAssociateWithFile                  RT_MANGLER(RTFileAioCtxAssociateWithFile)
+# define RTFileAioCtxCreate                             RT_MANGLER(RTFileAioCtxCreate)
+# define RTFileAioCtxDestroy                            RT_MANGLER(RTFileAioCtxDestroy)
+# define RTFileAioCtxGetMaxReqCount                     RT_MANGLER(RTFileAioCtxGetMaxReqCount)
+# define RTFileAioCtxSubmit                             RT_MANGLER(RTFileAioCtxSubmit)
+# define RTFileAioCtxWait                               RT_MANGLER(RTFileAioCtxWait)
+# define RTFileAioCtxWakeup                             RT_MANGLER(RTFileAioCtxWakeup)
+# define RTFileAioGetLimits                             RT_MANGLER(RTFileAioGetLimits)
+# define RTFileAioReqCancel                             RT_MANGLER(RTFileAioReqCancel)
+# define RTFileAioReqCreate                             RT_MANGLER(RTFileAioReqCreate)
+# define RTFileAioReqDestroy                            RT_MANGLER(RTFileAioReqDestroy)
+# define RTFileAioReqGetRC                              RT_MANGLER(RTFileAioReqGetRC)
+# define RTFileAioReqGetUser                            RT_MANGLER(RTFileAioReqGetUser)
+# define RTFileAioReqPrepareFlush                       RT_MANGLER(RTFileAioReqPrepareFlush)
+# define RTFileAioReqPrepareRead                        RT_MANGLER(RTFileAioReqPrepareRead)
+# define RTFileAioReqPrepareWrite                       RT_MANGLER(RTFileAioReqPrepareWrite)
+# define RTFileChangeLock                               RT_MANGLER(RTFileChangeLock)
+# define RTFileClose                                    RT_MANGLER(RTFileClose)
+# define RTFileCompare                                  RT_MANGLER(RTFileCompare)
+# define RTFileCompareByHandles                         RT_MANGLER(RTFileCompareByHandles)
+# define RTFileCompareByHandlesEx                       RT_MANGLER(RTFileCompareByHandlesEx)
+# define RTFileCompareEx                                RT_MANGLER(RTFileCompareEx)
+# define RTFileCopy                                     RT_MANGLER(RTFileCopy)
+# define RTFileCopyByHandles                            RT_MANGLER(RTFileCopyByHandles)
+# define RTFileCopyByHandlesEx                          RT_MANGLER(RTFileCopyByHandlesEx)
+# define RTFileCopyEx                                   RT_MANGLER(RTFileCopyEx)
+# define RTFileCreateTemp                               RT_MANGLER(RTFileCreateTemp)
+# define RTFileCreateTempSecure                         RT_MANGLER(RTFileCreateTempSecure)
+# define RTFileDelete                                   RT_MANGLER(RTFileDelete)
+# define RTFileExists                                   RT_MANGLER(RTFileExists)
+# define RTFileFlush                                    RT_MANGLER(RTFileFlush)
+# define RTFileFromNative                               RT_MANGLER(RTFileFromNative)
+# define RTFileGetMaxSize                               RT_MANGLER(RTFileGetMaxSize)
+# define RTFileGetMaxSizeEx                             RT_MANGLER(RTFileGetMaxSizeEx)
+# define RTFileGetSize                                  RT_MANGLER(RTFileGetSize)
+# define RTFileIoCtl                                    RT_MANGLER(RTFileIoCtl)
+# define RTFileIsValid                                  RT_MANGLER(RTFileIsValid)
+# define RTFileLock                                     RT_MANGLER(RTFileLock)
+# define RTFileModeToFlags                              RT_MANGLER(RTFileModeToFlags)
+# define RTFileModeToFlagsEx                            RT_MANGLER(RTFileModeToFlagsEx)
+# define RTFileMove                                     RT_MANGLER(RTFileMove)
+# define RTFileOpen                                     RT_MANGLER(RTFileOpen)
+# define RTFileOpenBitBucket                            RT_MANGLER(RTFileOpenBitBucket)
+# define RTFileOpenF                                    RT_MANGLER(RTFileOpenF)
+# define RTFileOpenV                                    RT_MANGLER(RTFileOpenV)
+# define RTFileOpenTemp                                 RT_MANGLER(RTFileOpenTemp)
+# define RTFileQueryFsSizes                             RT_MANGLER(RTFileQueryFsSizes)
+# define RTFileQueryInfo                                RT_MANGLER(RTFileQueryInfo)
+# define RTFileQuerySize                                RT_MANGLER(RTFileQuerySize)
+# define RTFileRead                                     RT_MANGLER(RTFileRead)
+# define RTFileReadAll                                  RT_MANGLER(RTFileReadAll)
+# define RTFileReadAllByHandle                          RT_MANGLER(RTFileReadAllByHandle)
+# define RTFileReadAllByHandleEx                        RT_MANGLER(RTFileReadAllByHandleEx)
+# define RTFileReadAllEx                                RT_MANGLER(RTFileReadAllEx)
+# define RTFileReadAllFree                              RT_MANGLER(RTFileReadAllFree)
+# define RTFileReadAt                                   RT_MANGLER(RTFileReadAt)
+# define RTFileRename                                   RT_MANGLER(RTFileRename)
+# define RTFileSeek                                     RT_MANGLER(RTFileSeek)
+# define RTFileSetAllocationSize                        RT_MANGLER(RTFileSetAllocationSize)
+# define RTFileSetForceFlags                            RT_MANGLER(RTFileSetForceFlags)
+# define RTFileSetMode                                  RT_MANGLER(RTFileSetMode)
+# define RTFileSetOwner                                 RT_MANGLER(RTFileSetOwner)
+# define RTFileSetSize                                  RT_MANGLER(RTFileSetSize)
+# define RTFileSetTimes                                 RT_MANGLER(RTFileSetTimes)
+# define RTFileSgReadAt                                 RT_MANGLER(RTFileSgReadAt)
+# define RTFileSgWriteAt                                RT_MANGLER(RTFileSgWriteAt)
+# define RTFileTell                                     RT_MANGLER(RTFileTell)
+# define RTFileToNative                                 RT_MANGLER(RTFileToNative)
+# define RTFileUnlock                                   RT_MANGLER(RTFileUnlock)
+# define RTFileWrite                                    RT_MANGLER(RTFileWrite)
+# define RTFileWriteAt                                  RT_MANGLER(RTFileWriteAt)
+# define RTFilesystemVfsFromFile                        RT_MANGLER(RTFilesystemVfsFromFile)
+# define RTFsIsCaseSensitive                            RT_MANGLER(RTFsIsCaseSensitive)
+# define RTFsQueryProperties                            RT_MANGLER(RTFsQueryProperties)
+# define RTFsQuerySerial                                RT_MANGLER(RTFsQuerySerial)
+# define RTFsQuerySizes                                 RT_MANGLER(RTFsQuerySizes)
+# define RTFsQueryType                                  RT_MANGLER(RTFsQueryType)
+# define RTFsTypeName                                   RT_MANGLER(RTFsTypeName)
+# define RTGetOpt                                       RT_MANGLER(RTGetOpt)
+# define RTGetOptArgvFree                               RT_MANGLER(RTGetOptArgvFree)
+# define RTGetOptArgvFromString                         RT_MANGLER(RTGetOptArgvFromString)
+# define RTGetOptArgvToString                           RT_MANGLER(RTGetOptArgvToString)
+# define RTGetOptArgvToUtf16String                      RT_MANGLER(RTGetOptArgvToUtf16String)
+# define RTGetOptFetchValue                             RT_MANGLER(RTGetOptFetchValue)
+# define RTGetOptInit                                   RT_MANGLER(RTGetOptInit)
+# define RTGetOptPrintError                             RT_MANGLER(RTGetOptPrintError)
+# define RTHandleClose                                  RT_MANGLER(RTHandleClose)
+# define RTHandleGetStandard                            RT_MANGLER(RTHandleGetStandard)
+# define RTHandleTableAlloc                             RT_MANGLER(RTHandleTableAlloc)
+# define RTHandleTableAllocWithCtx                      RT_MANGLER(RTHandleTableAllocWithCtx)
+# define RTHandleTableCreate                            RT_MANGLER(RTHandleTableCreate)
+# define RTHandleTableCreateEx                          RT_MANGLER(RTHandleTableCreateEx)
+# define RTHandleTableDestroy                           RT_MANGLER(RTHandleTableDestroy)
+# define RTHandleTableFree                              RT_MANGLER(RTHandleTableFree)
+# define RTHandleTableFreeWithCtx                       RT_MANGLER(RTHandleTableFreeWithCtx)
+# define RTHandleTableLookup                            RT_MANGLER(RTHandleTableLookup)
+# define RTHandleTableLookupWithCtx                     RT_MANGLER(RTHandleTableLookupWithCtx)
+# define RTHeapOffsetAlloc                              RT_MANGLER(RTHeapOffsetAlloc)
+# define RTHeapOffsetAllocZ                             RT_MANGLER(RTHeapOffsetAllocZ)
+# define RTHeapOffsetDump                               RT_MANGLER(RTHeapOffsetDump)
+# define RTHeapOffsetFree                               RT_MANGLER(RTHeapOffsetFree)
+# define RTHeapOffsetGetFreeSize                        RT_MANGLER(RTHeapOffsetGetFreeSize)
+# define RTHeapOffsetGetHeapSize                        RT_MANGLER(RTHeapOffsetGetHeapSize)
+# define RTHeapOffsetInit                               RT_MANGLER(RTHeapOffsetInit)
+# define RTHeapOffsetSize                               RT_MANGLER(RTHeapOffsetSize)
+# define RTHeapSimpleAlloc                              RT_MANGLER(RTHeapSimpleAlloc)
+# define RTHeapSimpleAllocZ                             RT_MANGLER(RTHeapSimpleAllocZ)
+# define RTHeapSimpleDump                               RT_MANGLER(RTHeapSimpleDump)
+# define RTHeapSimpleFree                               RT_MANGLER(RTHeapSimpleFree)
+# define RTHeapSimpleGetFreeSize                        RT_MANGLER(RTHeapSimpleGetFreeSize)
+# define RTHeapSimpleGetHeapSize                        RT_MANGLER(RTHeapSimpleGetHeapSize)
+# define RTHeapSimpleInit                               RT_MANGLER(RTHeapSimpleInit)
+# define RTHeapSimpleRelocate                           RT_MANGLER(RTHeapSimpleRelocate)
+# define RTHeapSimpleSize                               RT_MANGLER(RTHeapSimpleSize)
+# define RTHttpGetFile                                  RT_MANGLER(RTHttpGetFile)
+# define RTHttpUseSystemProxySettings                   RT_MANGLER(RTHttpUseSystemProxySettings)
+# define RTIsoFsClose                                   RT_MANGLER(RTIsoFsClose)
+# define RTIsoFsExtractFile                             RT_MANGLER(RTIsoFsExtractFile)
+# define RTIsoFsGetFileInfo                             RT_MANGLER(RTIsoFsGetFileInfo)
+# define RTIsoFsOpen                                    RT_MANGLER(RTIsoFsOpen)
+# define RTJsonIteratorBegin                            RT_MANGLER(RTJsonIteratorBegin)
+# define RTJsonIteratorFree                             RT_MANGLER(RTJsonIteratorFree)
+# define RTJsonIteratorNext                             RT_MANGLER(RTJsonIteratorNext)
+# define RTJsonIteratorQueryValue                       RT_MANGLER(RTJsonIteratorQueryValue)
+# define RTJsonParseFromBuf                             RT_MANGLER(RTJsonParseFromBuf)
+# define RTJsonParseFromFile                            RT_MANGLER(RTJsonParseFromFile)
+# define RTJsonParseFromString                          RT_MANGLER(RTJsonParseFromString)
+# define RTJsonValueGetArraySize                        RT_MANGLER(RTJsonValueGetArraySize)
+# define RTJsonValueGetString                           RT_MANGLER(RTJsonValueGetString)
+# define RTJsonValueGetType                             RT_MANGLER(RTJsonValueGetType)
+# define RTJsonValueQueryArraySizeEx                    RT_MANGLER(RTJsonValueQueryArraySize)
+# define RTJsonValueQueryBooleanByName                  RT_MANGLER(RTJsonValueQueryBooleanByName)
+# define RTJsonValueQueryByIndex                        RT_MANGLER(RTJsonValueQueryByIndex)
+# define RTJsonValueQueryByName                         RT_MANGLER(RTJsonValueQueryByName)
+# define RTJsonValueQueryInteger                        RT_MANGLER(RTJsonValueQueryInteger)
+# define RTJsonValueQueryIntegerByName                  RT_MANGLER(RTJsonValueQueryIntegerByName)
+# define RTJsonValueQueryString                         RT_MANGLER(RTJsonValueQueryString)
+# define RTJsonValueQueryStringByName                   RT_MANGLER(RTJsonValueQueryStringByName)
+# define RTJsonValueRelease                             RT_MANGLER(RTJsonValueRelease)
+# define RTJsonValueRetain                              RT_MANGLER(RTJsonValueRetain)
+# define RTLatin1CalcUtf16Len                           RT_MANGLER(RTLatin1CalcUtf16Len)
+# define RTLatin1CalcUtf16LenEx                         RT_MANGLER(RTLatin1CalcUtf16LenEx)
+# define RTLatin1CalcUtf8Len                            RT_MANGLER(RTLatin1CalcUtf8Len)
+# define RTLatin1CalcUtf8LenEx                          RT_MANGLER(RTLatin1CalcUtf8LenEx)
+# define RTLatin1ToUtf16ExTag                           RT_MANGLER(RTLatin1ToUtf16ExTag)
+# define RTLatin1ToUtf16Tag                             RT_MANGLER(RTLatin1ToUtf16Tag)
+# define RTLatin1ToUtf8ExTag                            RT_MANGLER(RTLatin1ToUtf8ExTag)
+# define RTLatin1ToUtf8Tag                              RT_MANGLER(RTLatin1ToUtf8Tag)
+# define RTLdrClose                                     RT_MANGLER(RTLdrClose)
+# define RTLdrEnumDbgInfo                               RT_MANGLER(RTLdrEnumDbgInfo)
+# define RTLdrEnumSegments                              RT_MANGLER(RTLdrEnumSegments)
+# define RTLdrEnumSymbols                               RT_MANGLER(RTLdrEnumSymbols)
+# define RTLdrGetArch                                   RT_MANGLER(RTLdrGetArch)
+# define RTLdrGetBits                                   RT_MANGLER(RTLdrGetBits)
+# define RTLdrGetEndian                                 RT_MANGLER(RTLdrGetEndian)
+# define RTLdrGetFormat                                 RT_MANGLER(RTLdrGetFormat)
+# define RTLdrGetFunction                               RT_MANGLER(RTLdrGetFunction)
+# define RTLdrGetNativeHandle                           RT_MANGLER(RTLdrGetNativeHandle)
+# define RTLdrGetSuff                                   RT_MANGLER(RTLdrGetSuff)
+# define RTLdrGetSymbol                                 RT_MANGLER(RTLdrGetSymbol)
+# define RTLdrGetSymbolEx                               RT_MANGLER(RTLdrGetSymbolEx)
+# define RTLdrGetSystemSymbol                           RT_MANGLER(RTLdrGetSystemSymbol)
+# define RTLdrGetType                                   RT_MANGLER(RTLdrGetType)
+# define RTLdrIsLoadable                                RT_MANGLER(RTLdrIsLoadable)
+# define RTLdrLinkAddressToRva                          RT_MANGLER(RTLdrLinkAddressToRva)
+# define RTLdrLinkAddressToSegOffset                    RT_MANGLER(RTLdrLinkAddressToSegOffset)
+# define RTLdrLoad                                      RT_MANGLER(RTLdrLoad)
+# define RTLdrLoadAppPriv                               RT_MANGLER(RTLdrLoadAppPriv)
+# define RTLdrLoadEx                                    RT_MANGLER(RTLdrLoadEx)
+# define RTLdrLoadSystem                                RT_MANGLER(RTLdrLoadSystem)
+# define RTLdrOpen                                      RT_MANGLER(RTLdrOpen)
+# define RTLdrOpenEx                                    RT_MANGLER(RTLdrOpenEx)
+# define RTLdrOpenInMemory                              RT_MANGLER(RTLdrOpenInMemory)
+# define RTLdrOpenkLdr                                  RT_MANGLER(RTLdrOpenkLdr)
+# define RTLdrRelocate                                  RT_MANGLER(RTLdrRelocate)
+# define RTLdrRvaToSegOffset                            RT_MANGLER(RTLdrRvaToSegOffset)
+# define RTLdrQueryForwarderInfo                        RT_MANGLER(RTLdrQueryForwarderInfo)
+# define RTLdrQueryProp                                 RT_MANGLER(RTLdrQueryProp)
+# define RTLdrSegOffsetToRva                            RT_MANGLER(RTLdrSegOffsetToRva)
+# define RTLdrSize                                      RT_MANGLER(RTLdrSize)
+# define RTLinuxCheckDevicePath                         RT_MANGLER(RTLinuxCheckDevicePath)
+# define RTLinuxCheckDevicePathV                        RT_MANGLER(RTLinuxCheckDevicePathV)
+# define RTLinuxSysFsClose                              RT_MANGLER(RTLinuxSysFsClose)
+# define RTLinuxSysFsExists                             RT_MANGLER(RTLinuxSysFsExists)
+# define RTLinuxSysFsExistsEx                           RT_MANGLER(RTLinuxSysFsExistsEx)
+# define RTLinuxSysFsExistsExV                          RT_MANGLER(RTLinuxSysFsExistsExV)
+# define RTLinuxSysFsExistsV                            RT_MANGLER(RTLinuxSysFsExistsV)
+# define RTLinuxSysFsGetLinkDest                        RT_MANGLER(RTLinuxSysFsGetLinkDest)
+# define RTLinuxSysFsGetLinkDestV                       RT_MANGLER(RTLinuxSysFsGetLinkDestV)
+# define RTLinuxSysFsOpen                               RT_MANGLER(RTLinuxSysFsOpen)
+# define RTLinuxSysFsOpenEx                             RT_MANGLER(RTLinuxSysFsOpenEx)
+# define RTLinuxSysFsOpenExV                            RT_MANGLER(RTLinuxSysFsOpenExV)
+# define RTLinuxSysFsOpenV                              RT_MANGLER(RTLinuxSysFsOpenV)
+# define RTLinuxSysFsReadDevNumFile                     RT_MANGLER(RTLinuxSysFsReadDevNumFile)
+# define RTLinuxSysFsReadDevNumFileV                    RT_MANGLER(RTLinuxSysFsReadDevNumFileV)
+# define RTLinuxSysFsReadFile                           RT_MANGLER(RTLinuxSysFsReadFile)
+# define RTLinuxSysFsReadIntFile                        RT_MANGLER(RTLinuxSysFsReadIntFile)
+# define RTLinuxSysFsReadIntFileV                       RT_MANGLER(RTLinuxSysFsReadIntFileV)
+# define RTLinuxSysFsReadStr                            RT_MANGLER(RTLinuxSysFsReadStr)
+# define RTLinuxSysFsReadStrFile                        RT_MANGLER(RTLinuxSysFsReadStrFile)
+# define RTLinuxSysFsReadStrFileV                       RT_MANGLER(RTLinuxSysFsReadStrFileV)
+# define RTLinuxSysFsWriteFile                          RT_MANGLER(RTLinuxSysFsWriteFile)
+# define RTLinuxSysFsWriteStr                           RT_MANGLER(RTLinuxSysFsWriteStr)
+# define RTLinuxSysFsWriteStrFile                       RT_MANGLER(RTLinuxSysFsWriteStrFile)
+# define RTLinuxSysFsWriteStrFileV                      RT_MANGLER(RTLinuxSysFsWriteStrFileV)
+# define RTLinuxSysFsWriteU8File                        RT_MANGLER(RTLinuxSysFsWriteU8File)
+# define RTLinuxSysFsWriteU8FileV                       RT_MANGLER(RTLinuxSysFsWriteU8FileV)
+# define RTLinuxSysFsWriteU16File                       RT_MANGLER(RTLinuxSysFsWriteU16File)
+# define RTLinuxSysFsWriteU16FileV                      RT_MANGLER(RTLinuxSysFsWriteU16FileV)
+# define RTLinuxSysFsWriteU32File                       RT_MANGLER(RTLinuxSysFsWriteU32File)
+# define RTLinuxSysFsWriteU32FileV                      RT_MANGLER(RTLinuxSysFsWriteU32FileV)
+# define RTLinuxSysFsWriteU64File                       RT_MANGLER(RTLinuxSysFsWriteU64File)
+# define RTLinuxSysFsWriteU64FileV                      RT_MANGLER(RTLinuxSysFsWriteU64FileV)
+# define RTLocalIpcServerCreate                         RT_MANGLER(RTLocalIpcServerCreate)
+# define RTLocalIpcServerDestroy                        RT_MANGLER(RTLocalIpcServerDestroy)
+# define RTLocalIpcServerCancel                         RT_MANGLER(RTLocalIpcServerCancel)
+# define RTLocalIpcServerListen                         RT_MANGLER(RTLocalIpcServerListen)
+# define RTLocalIpcSessionConnect                       RT_MANGLER(RTLocalIpcSessionConnect)
+# define RTLocalIpcSessionClose                         RT_MANGLER(RTLocalIpcSessionClose)
+# define RTLocalIpcSessionCancel                        RT_MANGLER(RTLocalIpcSessionCancel)
+# define RTLocalIpcSessionRead                          RT_MANGLER(RTLocalIpcSessionRead)
+# define RTLocalIpcSessionReadNB                        RT_MANGLER(RTLocalIpcSessionReadNB)
+# define RTLocalIpcSessionRetain                        RT_MANGLER(RTLocalIpcSessionRetain)
+# define RTLocalIpcSessionRelease                       RT_MANGLER(RTLocalIpcSessionRelease)
+# define RTLocalIpcSessionWrite                         RT_MANGLER(RTLocalIpcSessionWrite)
+# define RTLocalIpcSessionFlush                         RT_MANGLER(RTLocalIpcSessionFlush)
+# define RTLocalIpcSessionWaitForData                   RT_MANGLER(RTLocalIpcSessionWaitForData)
+# define RTLocalIpcSessionQueryProcess                  RT_MANGLER(RTLocalIpcSessionQueryProcess)
+# define RTLocalIpcSessionQueryUserId                   RT_MANGLER(RTLocalIpcSessionQueryUserId)
+# define RTLocalIpcSessionQueryGroupId                  RT_MANGLER(RTLocalIpcSessionQueryGroupId)
+# define RTLockValidatorClassAddPriorClass              RT_MANGLER(RTLockValidatorClassAddPriorClass)
+# define RTLockValidatorClassCreate                     RT_MANGLER(RTLockValidatorClassCreate)
+# define RTLockValidatorClassCreateEx                   RT_MANGLER(RTLockValidatorClassCreateEx)
+# define RTLockValidatorClassCreateExV                  RT_MANGLER(RTLockValidatorClassCreateExV)
+# define RTLockValidatorClassCreateUnique               RT_MANGLER(RTLockValidatorClassCreateUnique)
+# define RTLockValidatorClassEnforceStrictReleaseOrder  RT_MANGLER(RTLockValidatorClassEnforceStrictReleaseOrder)
+# define RTLockValidatorClassFindForSrcPos              RT_MANGLER(RTLockValidatorClassFindForSrcPos)
+# define RTLockValidatorClassForSrcPos                  RT_MANGLER(RTLockValidatorClassForSrcPos)
+# define RTLockValidatorClassRelease                    RT_MANGLER(RTLockValidatorClassRelease)
+# define RTLockValidatorClassRetain                     RT_MANGLER(RTLockValidatorClassRetain)
+# define RTLockValidatorHoldsLocksInClass               RT_MANGLER(RTLockValidatorHoldsLocksInClass)
+# define RTLockValidatorHoldsLocksInSubClass            RT_MANGLER(RTLockValidatorHoldsLocksInSubClass)
+# define RTLockValidatorIsBlockedThreadInValidator      RT_MANGLER(RTLockValidatorIsBlockedThreadInValidator)
+# define RTLockValidatorIsEnabled                       RT_MANGLER(RTLockValidatorIsEnabled)
+# define RTLockValidatorIsQuiet                         RT_MANGLER(RTLockValidatorIsQuiet)
+# define RTLockValidatorMayPanic                        RT_MANGLER(RTLockValidatorMayPanic)
+# define RTLockValidatorQueryBlocking                   RT_MANGLER(RTLockValidatorQueryBlocking)
+# define RTLockValidatorReadLockDec                     RT_MANGLER(RTLockValidatorReadLockDec)
+# define RTLockValidatorReadLockGetCount                RT_MANGLER(RTLockValidatorReadLockGetCount)
+# define RTLockValidatorReadLockInc                     RT_MANGLER(RTLockValidatorReadLockInc)
+# define RTLockValidatorRecExclCheckBlocking            RT_MANGLER(RTLockValidatorRecExclCheckBlocking)
+# define RTLockValidatorRecExclCheckOrder               RT_MANGLER(RTLockValidatorRecExclCheckOrder)
+# define RTLockValidatorRecExclCheckOrderAndBlocking    RT_MANGLER(RTLockValidatorRecExclCheckOrderAndBlocking)
+# define RTLockValidatorRecExclCreate                   RT_MANGLER(RTLockValidatorRecExclCreate)
+# define RTLockValidatorRecExclCreateV                  RT_MANGLER(RTLockValidatorRecExclCreateV)
+# define RTLockValidatorRecExclDelete                   RT_MANGLER(RTLockValidatorRecExclDelete)
+# define RTLockValidatorRecExclDestroy                  RT_MANGLER(RTLockValidatorRecExclDestroy)
+# define RTLockValidatorRecExclInit                     RT_MANGLER(RTLockValidatorRecExclInit)
+# define RTLockValidatorRecExclInitV                    RT_MANGLER(RTLockValidatorRecExclInitV)
+# define RTLockValidatorRecExclRecursion                RT_MANGLER(RTLockValidatorRecExclRecursion)
+# define RTLockValidatorRecExclRecursionMixed           RT_MANGLER(RTLockValidatorRecExclRecursionMixed)
+# define RTLockValidatorRecExclReleaseOwner             RT_MANGLER(RTLockValidatorRecExclReleaseOwner)
+# define RTLockValidatorRecExclReleaseOwnerUnchecked    RT_MANGLER(RTLockValidatorRecExclReleaseOwnerUnchecked)
+# define RTLockValidatorRecExclSetOwner                 RT_MANGLER(RTLockValidatorRecExclSetOwner)
+# define RTLockValidatorRecExclSetSubClass              RT_MANGLER(RTLockValidatorRecExclSetSubClass)
+# define RTLockValidatorRecExclUnwind                   RT_MANGLER(RTLockValidatorRecExclUnwind)
+# define RTLockValidatorRecExclUnwindMixed              RT_MANGLER(RTLockValidatorRecExclUnwindMixed)
+# define RTLockValidatorRecMakeSiblings                 RT_MANGLER(RTLockValidatorRecMakeSiblings)
+# define RTLockValidatorRecSharedAddOwner               RT_MANGLER(RTLockValidatorRecSharedAddOwner)
+# define RTLockValidatorRecSharedCheckAndRelease        RT_MANGLER(RTLockValidatorRecSharedCheckAndRelease)
+# define RTLockValidatorRecSharedCheckBlocking          RT_MANGLER(RTLockValidatorRecSharedCheckBlocking)
+# define RTLockValidatorRecSharedCheckOrder             RT_MANGLER(RTLockValidatorRecSharedCheckOrder)
+# define RTLockValidatorRecSharedCheckOrderAndBlocking  RT_MANGLER(RTLockValidatorRecSharedCheckOrderAndBlocking)
+# define RTLockValidatorRecSharedCheckSignaller         RT_MANGLER(RTLockValidatorRecSharedCheckSignaller)
+# define RTLockValidatorRecSharedCreate                 RT_MANGLER(RTLockValidatorRecSharedCreate)
+# define RTLockValidatorRecSharedCreateV                RT_MANGLER(RTLockValidatorRecSharedCreateV)
+# define RTLockValidatorRecSharedDelete                 RT_MANGLER(RTLockValidatorRecSharedDelete)
+# define RTLockValidatorRecSharedDestroy                RT_MANGLER(RTLockValidatorRecSharedDestroy)
+# define RTLockValidatorRecSharedInit                   RT_MANGLER(RTLockValidatorRecSharedInit)
+# define RTLockValidatorRecSharedInitV                  RT_MANGLER(RTLockValidatorRecSharedInitV)
+# define RTLockValidatorRecSharedIsOwner                RT_MANGLER(RTLockValidatorRecSharedIsOwner)
+# define RTLockValidatorRecSharedRemoveOwner            RT_MANGLER(RTLockValidatorRecSharedRemoveOwner)
+# define RTLockValidatorRecSharedResetOwner             RT_MANGLER(RTLockValidatorRecSharedResetOwner)
+# define RTLockValidatorRecSharedSetSubClass            RT_MANGLER(RTLockValidatorRecSharedSetSubClass)
+# define RTLockValidatorSetEnabled                      RT_MANGLER(RTLockValidatorSetEnabled)
+# define RTLockValidatorSetMayPanic                     RT_MANGLER(RTLockValidatorSetMayPanic)
+# define RTLockValidatorSetQuiet                        RT_MANGLER(RTLockValidatorSetQuiet)
+# define RTLockValidatorWriteLockDec                    RT_MANGLER(RTLockValidatorWriteLockDec)
+# define RTLockValidatorWriteLockGetCount               RT_MANGLER(RTLockValidatorWriteLockGetCount)
+# define RTLockValidatorWriteLockInc                    RT_MANGLER(RTLockValidatorWriteLockInc)
+# define RTLogBackdoorPrintf                            RT_MANGLER(RTLogBackdoorPrintf) /* r0drv-guest */
+# define RTLogBackdoorPrintfV                           RT_MANGLER(RTLogBackdoorPrintfV) /* r0drv-guest */
+# define RTLogCalcSizeForR0                             RT_MANGLER(RTLogCalcSizeForR0)
+# define RTLogCloneRC                                   RT_MANGLER(RTLogCloneRC)
+# define RTLogComPrintf                                 RT_MANGLER(RTLogComPrintf)
+# define RTLogComPrintfV                                RT_MANGLER(RTLogComPrintfV)
+# define RTLogCopyGroupsAndFlagsForR0                   RT_MANGLER(RTLogCopyGroupsAndFlagsForR0)
+# define RTLogCreate                                    RT_MANGLER(RTLogCreate)
+# define RTLogCreateEx                                  RT_MANGLER(RTLogCreateEx)
+# define RTLogCreateExV                                 RT_MANGLER(RTLogCreateExV)
+# define RTLogCreateForR0                               RT_MANGLER(RTLogCreateForR0)
+# define RTLogDefaultInit                               RT_MANGLER(RTLogDefaultInit)
+# define RTLogDefaultInstance                           RT_MANGLER(RTLogDefaultInstance)
+# define RTLogDefaultInstanceEx                         RT_MANGLER(RTLogDefaultInstanceEx)
+# define RTLogDestinations                              RT_MANGLER(RTLogDestinations)
+# define RTLogDestroy                                   RT_MANGLER(RTLogDestroy)
+# define RTLogFlags                                     RT_MANGLER(RTLogFlags)
+# define RTLogFlush                                     RT_MANGLER(RTLogFlush)
+# define RTLogFlushRC                                   RT_MANGLER(RTLogFlushRC)
+# define RTLogFlushR0                                   RT_MANGLER(RTLogFlushR0)
+# define RTLogFlushToLogger                             RT_MANGLER(RTLogFlushToLogger)
+# define RTLogFormatV                                   RT_MANGLER(RTLogFormatV)
+# define RTLogGetDefaultInstance                        RT_MANGLER(RTLogGetDefaultInstance)
+# define RTLogGetDefaultInstanceEx                      RT_MANGLER(RTLogGetDefaultInstanceEx)
+# define RTLogGetDestinations                           RT_MANGLER(RTLogGetDestinations)
+# define RTLogGetFlags                                  RT_MANGLER(RTLogGetFlags)
+# define RTLogGetGroupSettings                          RT_MANGLER(RTLogGetGroupSettings)
+# define RTLogGroupSettings                             RT_MANGLER(RTLogGroupSettings)
+# define RTLogLogger                                    RT_MANGLER(RTLogLogger)
+# define RTLogLoggerEx                                  RT_MANGLER(RTLogLoggerEx)
+# define RTLogLoggerExV                                 RT_MANGLER(RTLogLoggerExV)
+# define RTLogLoggerV                                   RT_MANGLER(RTLogLoggerV)
+# define RTLogPrintf                                    RT_MANGLER(RTLogPrintf)
+# define RTLogPrintfV                                   RT_MANGLER(RTLogPrintfV)
+# define RTLogDumpPrintfV                               RT_MANGLER(RTLogDumpPrintfV)
+# define RTLogRelGetDefaultInstance                     RT_MANGLER(RTLogRelGetDefaultInstance)
+# define RTLogRelGetDefaultInstanceEx                   RT_MANGLER(RTLogRelGetDefaultInstanceEx)
+# define RTLogRelLogger                                 RT_MANGLER(RTLogRelLogger)
+# define RTLogRelLoggerV                                RT_MANGLER(RTLogRelLoggerV)
+# define RTLogRelPrintf                                 RT_MANGLER(RTLogRelPrintf)
+# define RTLogRelPrintfV                                RT_MANGLER(RTLogRelPrintfV)
+# define RTLogRelSetBuffering                           RT_MANGLER(RTLogRelSetBuffering)
+# define RTLogRelSetDefaultInstance                     RT_MANGLER(RTLogRelSetDefaultInstance)
+# define RTLogSetBuffering                              RT_MANGLER(RTLogSetBuffering)
+# define RTLogSetCustomPrefixCallback                   RT_MANGLER(RTLogSetCustomPrefixCallback)
+# define RTLogSetCustomPrefixCallbackForR0              RT_MANGLER(RTLogSetCustomPrefixCallbackForR0)
+# define RTLogSetDefaultInstance                        RT_MANGLER(RTLogSetDefaultInstance)
+# define RTLogSetDefaultInstanceThread                  RT_MANGLER(RTLogSetDefaultInstanceThread) /* r0drv */
+# define RTLogSetGroupLimit                             RT_MANGLER(RTLogSetGroupLimit)
+# define RTLogWriteCom                                  RT_MANGLER(RTLogWriteCom)
+# define RTLogWriteCom                                  RT_MANGLER(RTLogWriteCom)
+# define RTLogWriteDebugger                             RT_MANGLER(RTLogWriteDebugger)
+# define RTLogWriteStdErr                               RT_MANGLER(RTLogWriteStdErr)
+# define RTLogWriteStdOut                               RT_MANGLER(RTLogWriteStdOut)
+# define RTLogWriteUser                                 RT_MANGLER(RTLogWriteUser)
+# define RTManifestCreate                               RT_MANGLER(RTManifestCreate)
+# define RTManifestDup                                  RT_MANGLER(RTManifestDup)
+# define RTManifestEntryAdd                             RT_MANGLER(RTManifestEntryAdd)
+# define RTManifestEntryAddIoStream                     RT_MANGLER(RTManifestEntryAddIoStream)
+# define RTManifestEntryAddPassthruIoStream             RT_MANGLER(RTManifestEntryAddPassthruIoStream)
+# define RTManifestEntryExists                          RT_MANGLER(RTManifestEntryExists)
+# define RTManifestEntryRemove                          RT_MANGLER(RTManifestEntryRemove)
+# define RTManifestEntryQueryAttr                       RT_MANGLER(RTManifestEntryQueryAttr)
+# define RTManifestEntrySetAttr                         RT_MANGLER(RTManifestEntrySetAttr)
+# define RTManifestEntryUnsetAttr                       RT_MANGLER(RTManifestEntryUnsetAttr)
+# define RTManifestEquals                               RT_MANGLER(RTManifestEquals)
+# define RTManifestEqualsEx                             RT_MANGLER(RTManifestEqualsEx)
+# define RTManifestPtIosAddEntryNow                     RT_MANGLER(RTManifestPtIosAddEntryNow)
+# define RTManifestPtIosIsInstanceOf                    RT_MANGLER(RTManifestPtIosIsInstanceOf)
+# define RTManifestQueryAllAttrTypes                    RT_MANGLER(RTManifestQueryAllAttrTypes)
+# define RTManifestQueryAttr                            RT_MANGLER(RTManifestQueryAttr)
+# define RTManifestReadStandard                         RT_MANGLER(RTManifestReadStandard)
+# define RTManifestReadStandardEx                       RT_MANGLER(RTManifestReadStandardEx)
+# define RTManifestReadStandardFromFile                 RT_MANGLER(RTManifestReadStandardFromFile)
+# define RTManifestRelease                              RT_MANGLER(RTManifestRelease)
+# define RTManifestRetain                               RT_MANGLER(RTManifestRetain)
+# define RTManifestSetAttr                              RT_MANGLER(RTManifestSetAttr)
+# define RTManifestUnsetAttr                            RT_MANGLER(RTManifestUnsetAttr)
+# define RTManifestVerify                               RT_MANGLER(RTManifestVerify)
+# define RTManifestVerifyDigestType                     RT_MANGLER(RTManifestVerifyDigestType)
+# define RTManifestVerifyFiles                          RT_MANGLER(RTManifestVerifyFiles)
+# define RTManifestVerifyFilesBuf                       RT_MANGLER(RTManifestVerifyFilesBuf)
+# define RTManifestWriteFiles                           RT_MANGLER(RTManifestWriteFiles)
+# define RTManifestWriteFilesBuf                        RT_MANGLER(RTManifestWriteFilesBuf)
+# define RTManifestWriteStandard                        RT_MANGLER(RTManifestWriteStandard)
+# define RTManifestWriteStandardToFile                  RT_MANGLER(RTManifestWriteStandardToFile)
+# define RTMd5                                          RT_MANGLER(RTMd5)
+# define RTMd5Final                                     RT_MANGLER(RTMd5Final)
+# define RTMd5FromString                                RT_MANGLER(RTMd5FromString)
+# define RTMd5Init                                      RT_MANGLER(RTMd5Init)
+# define RTMd5ToString                                  RT_MANGLER(RTMd5ToString)
+# define RTMd5Update                                    RT_MANGLER(RTMd5Update)
+# define RTMemAllocExTag                                RT_MANGLER(RTMemAllocExTag)
+# define RTMemAllocTag                                  RT_MANGLER(RTMemAllocTag)
+# define RTMemAllocVarTag                               RT_MANGLER(RTMemAllocVarTag)
+# define RTMemAllocZTag                                 RT_MANGLER(RTMemAllocZTag)
+# define RTMemAllocZVarTag                              RT_MANGLER(RTMemAllocZVarTag)
+# define RTMemCacheAlloc                                RT_MANGLER(RTMemCacheAlloc)
+# define RTMemCacheAllocEx                              RT_MANGLER(RTMemCacheAllocEx)
+# define RTMemCacheCreate                               RT_MANGLER(RTMemCacheCreate)
+# define RTMemCacheDestroy                              RT_MANGLER(RTMemCacheDestroy)
+# define RTMemCacheFree                                 RT_MANGLER(RTMemCacheFree)
+# define RTMemContAlloc                                 RT_MANGLER(RTMemContAlloc) /* r0drv */
+# define RTMemContFree                                  RT_MANGLER(RTMemContFree) /* r0drv */
+# define RTMemDump                                      RT_MANGLER(RTMemDump)
+# define RTMemDupExTag                                  RT_MANGLER(RTMemDupExTag)
+# define RTMemDupTag                                    RT_MANGLER(RTMemDupTag)
+# define RTMemEfAlloc                                   RT_MANGLER(RTMemEfAlloc)
+# define RTMemEfAllocNP                                 RT_MANGLER(RTMemEfAllocNP)
+# define RTMemEfAllocVar                                RT_MANGLER(RTMemEfAllocVar)
+# define RTMemEfAllocVarNP                              RT_MANGLER(RTMemEfAllocVarNP)
+# define RTMemEfAllocZ                                  RT_MANGLER(RTMemEfAllocZ)
+# define RTMemEfAllocZNP                                RT_MANGLER(RTMemEfAllocZNP)
+# define RTMemEfAllocZVar                               RT_MANGLER(RTMemEfAllocZVar)
+# define RTMemEfAllocZVarNP                             RT_MANGLER(RTMemEfAllocZVarNP)
+# define RTMemEfDup                                     RT_MANGLER(RTMemEfDup)
+# define RTMemEfDupEx                                   RT_MANGLER(RTMemEfDupEx)
+# define RTMemEfDupExNP                                 RT_MANGLER(RTMemEfDupExNP)
+# define RTMemEfDupNP                                   RT_MANGLER(RTMemEfDupNP)
+# define RTMemEfFree                                    RT_MANGLER(RTMemEfFree)
+# define RTMemEfFreeNP                                  RT_MANGLER(RTMemEfFreeNP)
+# define RTMemEfRealloc                                 RT_MANGLER(RTMemEfRealloc)
+# define RTMemEfReallocNP                               RT_MANGLER(RTMemEfReallocNP)
+# define RTMemEfTmpAlloc                                RT_MANGLER(RTMemEfTmpAlloc)
+# define RTMemEfTmpAllocNP                              RT_MANGLER(RTMemEfTmpAllocNP)
+# define RTMemEfTmpAllocZ                               RT_MANGLER(RTMemEfTmpAllocZ)
+# define RTMemEfTmpAllocZNP                             RT_MANGLER(RTMemEfTmpAllocZNP)
+# define RTMemEfTmpFree                                 RT_MANGLER(RTMemEfTmpFree)
+# define RTMemEfTmpFreeNP                               RT_MANGLER(RTMemEfTmpFreeNP)
+# define RTMemExecAllocTag                              RT_MANGLER(RTMemExecAllocTag)
+# define RTMemExecFree                                  RT_MANGLER(RTMemExecFree)
+# define RTMemFree                                      RT_MANGLER(RTMemFree)
+# define RTMemFreeEx                                    RT_MANGLER(RTMemFreeEx)
+# define RTMemLockedAllocExTag                          RT_MANGLER(RTMemLockedAllocExTag)
+# define RTMemLockedAllocZExTag                         RT_MANGLER(RTMemLockedAllocZExTag)
+# define RTMemLockedAllocTag                            RT_MANGLER(RTMemLockedAllocTag)
+# define RTMemLockedAllocZTag                           RT_MANGLER(RTMemLockedAllocZTag)
+# define RTMemLockedFree                                RT_MANGLER(RTMemLockedFree)
+# define RTMemPageAllocTag                              RT_MANGLER(RTMemPageAllocTag)
+# define RTMemPageAllocZTag                             RT_MANGLER(RTMemPageAllocZTag)
+# define RTMemPageFree                                  RT_MANGLER(RTMemPageFree)
+# define RTMemPoolAlloc                                 RT_MANGLER(RTMemPoolAlloc)
+# define RTMemPoolAllocZ                                RT_MANGLER(RTMemPoolAllocZ)
+# define RTMemPoolCreate                                RT_MANGLER(RTMemPoolCreate)
+# define RTMemPoolDestroy                               RT_MANGLER(RTMemPoolDestroy)
+# define RTMemPoolDup                                   RT_MANGLER(RTMemPoolDup)
+# define RTMemPoolDupEx                                 RT_MANGLER(RTMemPoolDupEx)
+# define RTMemPoolFree                                  RT_MANGLER(RTMemPoolFree)
+# define RTMemPoolRealloc                               RT_MANGLER(RTMemPoolRealloc)
+# define RTMemPoolRefCount                              RT_MANGLER(RTMemPoolRefCount)
+# define RTMemPoolRelease                               RT_MANGLER(RTMemPoolRelease)
+# define RTMemPoolRetain                                RT_MANGLER(RTMemPoolRetain)
+# define RTMemProtect                                   RT_MANGLER(RTMemProtect)
+# define RTMemReallocTag                                RT_MANGLER(RTMemReallocTag)
+# define RTMemTmpAllocTag                               RT_MANGLER(RTMemTmpAllocTag)
+# define RTMemTmpAllocZTag                              RT_MANGLER(RTMemTmpAllocZTag)
+# define RTMemTmpFree                                   RT_MANGLER(RTMemTmpFree)
+# define RTMemTrackerDumpAllToFile                      RT_MANGLER(RTMemTrackerDumpAllToFile)
+# define RTMemTrackerDumpAllToLog                       RT_MANGLER(RTMemTrackerDumpAllToLog)
+# define RTMemTrackerDumpAllToLogRel                    RT_MANGLER(RTMemTrackerDumpAllToLogRel)
+# define RTMemTrackerDumpAllToStdErr                    RT_MANGLER(RTMemTrackerDumpAllToStdErr)
+# define RTMemTrackerDumpAllToStdOut                    RT_MANGLER(RTMemTrackerDumpAllToStdOut)
+# define RTMemTrackerDumpStatsToFile                    RT_MANGLER(RTMemTrackerDumpStatsToFile)
+# define RTMemTrackerDumpStatsToLog                     RT_MANGLER(RTMemTrackerDumpStatsToLog)
+# define RTMemTrackerDumpStatsToLogRel                  RT_MANGLER(RTMemTrackerDumpStatsToLogRel)
+# define RTMemTrackerDumpStatsToStdErr                  RT_MANGLER(RTMemTrackerDumpStatsToStdErr)
+# define RTMemTrackerDumpStatsToStdOut                  RT_MANGLER(RTMemTrackerDumpStatsToStdOut)
+# define RTMemTrackerHdrAlloc                           RT_MANGLER(RTMemTrackerHdrAlloc)
+# define RTMemTrackerHdrFree                            RT_MANGLER(RTMemTrackerHdrFree)
+# define RTMemTrackerHdrReallocDone                     RT_MANGLER(RTMemTrackerHdrReallocDone)
+# define RTMemTrackerHdrReallocPrep                     RT_MANGLER(RTMemTrackerHdrReallocPrep)
+# define RTMemWipeThoroughly                            RT_MANGLER(RTMemWipeThoroughly)
+# define RTMpCpuId                                      RT_MANGLER(RTMpCpuId)
+# define RTMpCpuIdFromSetIndex                          RT_MANGLER(RTMpCpuIdFromSetIndex)
+# define RTMpCpuIdToSetIndex                            RT_MANGLER(RTMpCpuIdToSetIndex)
+# define RTMpCurSetIndex                                RT_MANGLER(RTMpCurSetIndex)
+# define RTMpCurSetIndexAndId                           RT_MANGLER(RTMpCurSetIndexAndId)
+# define RTMpGetArraySize                               RT_MANGLER(RTMpGetArraySize)
+# define RTMpGetCount                                   RT_MANGLER(RTMpGetCount)
+# define RTMpGetCurFrequency                            RT_MANGLER(RTMpGetCurFrequency)
+# define RTMpGetDescription                             RT_MANGLER(RTMpGetDescription)
+# define RTMpGetCpuGroupCounts                          RT_MANGLER(RTMpGetCpuGroupCounts)
+# define RTMpGetMaxCpuGroupCount                        RT_MANGLER(RTMpGetMaxCpuGroupCount)
+# define RTMpGetMaxCpuId                                RT_MANGLER(RTMpGetMaxCpuId)
+# define RTMpGetMaxFrequency                            RT_MANGLER(RTMpGetMaxFrequency)
+# define RTMpGetOnlineCount                             RT_MANGLER(RTMpGetOnlineCount)
+# define RTMpGetOnlineCoreCount                         RT_MANGLER(RTMpGetOnlineCoreCount)
+# define RTMpGetOnlineSet                               RT_MANGLER(RTMpGetOnlineSet)
+# define RTMpGetPresentCount                            RT_MANGLER(RTMpGetPresentCount)
+# define RTMpGetPresentCoreCount                        RT_MANGLER(RTMpGetPresentCoreCount)
+# define RTMpGetPresentSet                              RT_MANGLER(RTMpGetPresentSet)
+# define RTMpGetSet                                     RT_MANGLER(RTMpGetSet)
+# define RTMpGetCoreCount                               RT_MANGLER(RTMpGetCoreCount)
+# define RTMpIsCpuOnline                                RT_MANGLER(RTMpIsCpuOnline)
+# define RTMpIsCpuPossible                              RT_MANGLER(RTMpIsCpuPossible) /* r0drv */
+# define RTMpIsCpuPresent                               RT_MANGLER(RTMpIsCpuPresent)
+# define RTMpIsCpuWorkPending                           RT_MANGLER(RTMpIsCpuWorkPending)
+# define RTMpNotificationDeregister                     RT_MANGLER(RTMpNotificationDeregister) /* r0drv */
+# define RTMpNotificationRegister                       RT_MANGLER(RTMpNotificationRegister)   /* r0drv */
+# define RTMpOnAll                                      RT_MANGLER(RTMpOnAll)                  /* r0drv */
+# define RTMpOnAllIsConcurrentSafe                      RT_MANGLER(RTMpOnAllIsConcurrentSafe)  /* r0drv */
+# define RTMpOnOthers                                   RT_MANGLER(RTMpOnOthers)               /* r0drv */
+# define RTMpOnPair                                     RT_MANGLER(RTMpOnPair)                 /* r0drv */
+# define RTMpOnPairIsConcurrentExecSupported            RT_MANGLER(RTMpOnPairIsConcurrentExecSupported) /* r0drv */
+# define RTMpOnSpecific                                 RT_MANGLER(RTMpOnSpecific)             /* r0drv */
+# define RTMpPokeCpu                                    RT_MANGLER(RTMpPokeCpu)                /* r0drv */
+# define RTMpSetIndexFromCpuGroupMember                 RT_MANGLER(RTMpSetIndexFromCpuGroupMember)
+# define RTMsgError                                     RT_MANGLER(RTMsgError)
+# define RTMsgErrorExit                                 RT_MANGLER(RTMsgErrorExit)
+# define RTMsgErrorExitV                                RT_MANGLER(RTMsgErrorExitV)
+# define RTMsgErrorRc                                   RT_MANGLER(RTMsgErrorRc)
+# define RTMsgErrorRcV                                  RT_MANGLER(RTMsgErrorRcV)
+# define RTMsgErrorV                                    RT_MANGLER(RTMsgErrorV)
+# define RTMsgInfo                                      RT_MANGLER(RTMsgInfo)
+# define RTMsgInfoV                                     RT_MANGLER(RTMsgInfoV)
+# define RTMsgInitFailure                               RT_MANGLER(RTMsgInitFailure)
+# define RTMsgSetProgName                               RT_MANGLER(RTMsgSetProgName)
+# define RTMsgWarning                                   RT_MANGLER(RTMsgWarning)
+# define RTMsgWarningV                                  RT_MANGLER(RTMsgWarningV)
+# define RTNetIPv4AddDataChecksum                       RT_MANGLER(RTNetIPv4AddDataChecksum)
+# define RTNetIPv4AddTCPChecksum                        RT_MANGLER(RTNetIPv4AddTCPChecksum)
+# define RTNetIPv4AddUDPChecksum                        RT_MANGLER(RTNetIPv4AddUDPChecksum)
+# define RTNetIPv4FinalizeChecksum                      RT_MANGLER(RTNetIPv4FinalizeChecksum)
+# define RTNetIPv4HdrChecksum                           RT_MANGLER(RTNetIPv4HdrChecksum)
+# define RTNetIPv4IsDHCPValid                           RT_MANGLER(RTNetIPv4IsDHCPValid)
+# define RTNetIPv4IsHdrValid                            RT_MANGLER(RTNetIPv4IsHdrValid)
+# define RTNetIPv4IsTCPSizeValid                        RT_MANGLER(RTNetIPv4IsTCPSizeValid)
+# define RTNetIPv4IsTCPValid                            RT_MANGLER(RTNetIPv4IsTCPValid)
+# define RTNetIPv4IsUDPSizeValid                        RT_MANGLER(RTNetIPv4IsUDPSizeValid)
+# define RTNetIPv4IsUDPValid                            RT_MANGLER(RTNetIPv4IsUDPValid)
+# define RTNetIPv4PseudoChecksum                        RT_MANGLER(RTNetIPv4PseudoChecksum)
+# define RTNetIPv4PseudoChecksumBits                    RT_MANGLER(RTNetIPv4PseudoChecksumBits)
+# define RTNetIPv4TCPChecksum                           RT_MANGLER(RTNetIPv4TCPChecksum)
+# define RTNetIPv4UDPChecksum                           RT_MANGLER(RTNetIPv4UDPChecksum)
+# define RTNetIPv6PseudoChecksum                        RT_MANGLER(RTNetIPv6PseudoChecksum)
+# define RTNetIPv6PseudoChecksumBits                    RT_MANGLER(RTNetIPv6PseudoChecksumBits)
+# define RTNetIPv6PseudoChecksumEx                      RT_MANGLER(RTNetIPv6PseudoChecksumEx)
+# define RTNetMaskToPrefixIPv4                          RT_MANGLER(RTNetMaskToPrefixIPv4)
+# define RTNetPrefixToMaskIPv4                          RT_MANGLER(RTNetPrefixToMaskIPv4)
+# define RTNetTCPChecksum                               RT_MANGLER(RTNetTCPChecksum)
+# define RTNetUDPChecksum                               RT_MANGLER(RTNetUDPChecksum)
+# define RTNetStrToMacAddr                              RT_MANGLER(RTNetStrToMacAddr)
+# define RTNetIsIPv4AddrStr                             RT_MANGLER(RTNetIsIPv4AddrStr)
+# define RTNetStrIsIPv4AddrAny                          RT_MANGLER(RTNetStrIsIPv4AddrAny)
+# define RTNetStrToIPv4AddrEx                           RT_MANGLER(RTNetStrToIPv4AddrEx)
+# define RTNetStrToIPv4Addr                             RT_MANGLER(RTNetStrToIPv4Addr)
+# define RTNetIsIPv6AddrStr                             RT_MANGLER(RTNetIsIPv6AddrStr)
+# define RTNetStrIsIPv6AddrAny                          RT_MANGLER(RTNetStrIsIPv6AddrAny)
+# define RTNetStrToIPv6AddrEx                           RT_MANGLER(RTNetStrToIPv6AddrEx)
+# define RTNetStrToIPv6Addr                             RT_MANGLER(RTNetStrToIPv6Addr)
+# define RTNetMaskToPrefixIPv6                          RT_MANGLER(RTNetMaskToPrefixIPv6)
+# define RTNetPrefixToMaskIPv6                          RT_MANGLER(RTNetPrefixToMaskIPv6)
+# define RTOnceSlow                                     RT_MANGLER(RTOnceSlow)
+# define RTOnceReset                                    RT_MANGLER(RTOnceReset)
+# define RTPathAbs                                      RT_MANGLER(RTPathAbs)
+# define RTPathAbsDup                                   RT_MANGLER(RTPathAbsDup)
+# define RTPathAbsEx                                    RT_MANGLER(RTPathAbsEx)
+# define RTPathAbsExDup                                 RT_MANGLER(RTPathAbsExDup)
+# define RTPathAppDocs                                  RT_MANGLER(RTPathAppDocs)
+# define RTPathAppend                                   RT_MANGLER(RTPathAppend)
+# define RTPathAppendEx                                 RT_MANGLER(RTPathAppendEx)
+# define RTPathAppPrivateArch                           RT_MANGLER(RTPathAppPrivateArch)
+# define RTPathAppPrivateArchTop                        RT_MANGLER(RTPathAppPrivateArchTop)
+# define RTPathAppPrivateNoArch                         RT_MANGLER(RTPathAppPrivateNoArch)
+# define RTPathCalcRelative                             RT_MANGLER(RTPathCalcRelative)
+# define RTPathChangeToDosSlashes                       RT_MANGLER(RTPathChangeToDosSlashes)
+# define RTPathChangeToUnixSlashes                      RT_MANGLER(RTPathChangeToUnixSlashes)
+# define RTPathCompare                                  RT_MANGLER(RTPathCompare)
+# define RTPathCopyComponents                           RT_MANGLER(RTPathCopyComponents)
+# define RTPathCountComponents                          RT_MANGLER(RTPathCountComponents)
+# define RTPathEnsureTrailingSeparator                  RT_MANGLER(RTPathEnsureTrailingSeparator)
+# define RTPathExecDir                                  RT_MANGLER(RTPathExecDir)
+# define RTPathExists                                   RT_MANGLER(RTPathExists)
+# define RTPathExistsEx                                 RT_MANGLER(RTPathExistsEx)
+# define RTPathSuffix                                   RT_MANGLER(RTPathSuffix)
+# define RTPathFilename                                 RT_MANGLER(RTPathFilename)
+# define RTPathFilenameEx                               RT_MANGLER(RTPathFilenameEx)
+# define RTPathGetCurrent                               RT_MANGLER(RTPathGetCurrent)
+# define RTPathGetCurrentDrive                          RT_MANGLER(RTPathGetCurrentDrive)
+# define RTPathGetCurrentOnDrive                        RT_MANGLER(RTPathGetCurrentOnDrive)
+# define RTPathGetMode                                  RT_MANGLER(RTPathGetMode)
+# define RTPathGlob                                     RT_MANGLER(RTPathGlob)
+# define RTPathGlobFree                                 RT_MANGLER(RTPathGlobFree)
+# define RTPathHasSuffix                                RT_MANGLER(RTPathHasSuffix)
+# define RTPathHasPath                                  RT_MANGLER(RTPathHasPath)
+# define RTPathIsSame                                   RT_MANGLER(RTPathIsSame)
+# define RTPathJoin                                     RT_MANGLER(RTPathJoin)
+# define RTPathJoinA                                    RT_MANGLER(RTPathJoinA)
+# define RTPathJoinEx                                   RT_MANGLER(RTPathJoinEx)
+# define RTPathParse                                    RT_MANGLER(RTPathParse)
+# define RTPathParsedReassemble                         RT_MANGLER(RTPathParsedReassemble)
+# define RTPathParseSimple                              RT_MANGLER(RTPathParseSimple)
+# define RTPathQueryInfo                                RT_MANGLER(RTPathQueryInfo)
+# define RTPathQueryInfoEx                              RT_MANGLER(RTPathQueryInfoEx)
+# define RTPathReal                                     RT_MANGLER(RTPathReal)
+# define RTPathRealDup                                  RT_MANGLER(RTPathRealDup)
+# define RTPathRename                                   RT_MANGLER(RTPathRename)
+# define RTPathRmCmd                                    RT_MANGLER(RTPathRmCmd)
+# define RTPathSetCurrent                               RT_MANGLER(RTPathSetCurrent)
+# define RTPathSetMode                                  RT_MANGLER(RTPathSetMode)                   /* not-win */
+# define RTPathSetOwner                                 RT_MANGLER(RTPathSetOwner)                  /* not-win */
+# define RTPathSetOwnerEx                               RT_MANGLER(RTPathSetOwnerEx)                /* not-win */
+# define RTPathSetTimes                                 RT_MANGLER(RTPathSetTimes)
+# define RTPathSetTimesEx                               RT_MANGLER(RTPathSetTimesEx)
+# define RTPathSharedLibs                               RT_MANGLER(RTPathSharedLibs)
+# define RTPathSplit                                    RT_MANGLER(RTPathSplit)
+# define RTPathSplitATag                                RT_MANGLER(RTPathSplitATag)
+# define RTPathSplitFree                                RT_MANGLER(RTPathSplitFree)
+# define RTPathSplitReassemble                          RT_MANGLER(RTPathSplitReassemble)
+# define RTPathStartsWith                               RT_MANGLER(RTPathStartsWith)
+# define RTPathStartsWithRoot                           RT_MANGLER(RTPathStartsWithRoot)
+# define RTPathStripSuffix                              RT_MANGLER(RTPathStripSuffix)
+# define RTPathStripFilename                            RT_MANGLER(RTPathStripFilename)
+# define RTPathStripTrailingSlash                       RT_MANGLER(RTPathStripTrailingSlash)
+# define RTPathTemp                                     RT_MANGLER(RTPathTemp)
+# define RTPathTraverseList                             RT_MANGLER(RTPathTraverseList)
+# define RTPathUnlink                                   RT_MANGLER(RTPathUnlink)
+# define RTPathUserDocuments                            RT_MANGLER(RTPathUserDocuments)
+# define RTPathUserHome                                 RT_MANGLER(RTPathUserHome)
+# define RTPipeClose                                    RT_MANGLER(RTPipeClose)
+# define RTPipeCreate                                   RT_MANGLER(RTPipeCreate)
+# define RTPipeFlush                                    RT_MANGLER(RTPipeFlush)
+# define RTPipeFromNative                               RT_MANGLER(RTPipeFromNative)
+# define RTPipeQueryInfo                                RT_MANGLER(RTPipeQueryInfo)
+# define RTPipeQueryReadable                            RT_MANGLER(RTPipeQueryReadable)
+# define RTPipeRead                                     RT_MANGLER(RTPipeRead)
+# define RTPipeReadBlocking                             RT_MANGLER(RTPipeReadBlocking)
+# define RTPipeSelectOne                                RT_MANGLER(RTPipeSelectOne)
+# define RTPipeToNative                                 RT_MANGLER(RTPipeToNative)
+# define RTPipeWrite                                    RT_MANGLER(RTPipeWrite)
+# define RTPipeWriteBlocking                            RT_MANGLER(RTPipeWriteBlocking)
+# define RTPoll                                         RT_MANGLER(RTPoll)
+# define RTPollNoResume                                 RT_MANGLER(RTPollNoResume)
+# define RTPollSetAdd                                   RT_MANGLER(RTPollSetAdd)
+# define RTPollSetCreate                                RT_MANGLER(RTPollSetCreate)
+# define RTPollSetDestroy                               RT_MANGLER(RTPollSetDestroy)
+# define RTPollSetEventsChange                          RT_MANGLER(RTPollSetEventsChange)
+# define RTPollSetGetCount                              RT_MANGLER(RTPollSetGetCount)
+# define RTPollSetQueryHandle                           RT_MANGLER(RTPollSetQueryHandle)
+# define RTPollSetRemove                                RT_MANGLER(RTPollSetRemove)
+# define RTPowerNotificationDeregister                  RT_MANGLER(RTPowerNotificationDeregister) /* r0drv */
+# define RTPowerNotificationRegister                    RT_MANGLER(RTPowerNotificationRegister) /* r0drv */
+# define RTPowerSignalEvent                             RT_MANGLER(RTPowerSignalEvent)         /* r0drv */
+# define RTPrintf                                       RT_MANGLER(RTPrintf)
+# define RTPrintfV                                      RT_MANGLER(RTPrintfV)
+# define RTProcCreate                                   RT_MANGLER(RTProcCreate)
+# define RTProcCreateEx                                 RT_MANGLER(RTProcCreateEx)
+# define RTProcDaemonize                                RT_MANGLER(RTProcDaemonize)
+# define RTProcDaemonizeUsingFork                       RT_MANGLER(RTProcDaemonizeUsingFork)
+# define RTProcGetAffinityMask                          RT_MANGLER(RTProcGetAffinityMask)
+# define RTProcGetExecutablePath                        RT_MANGLER(RTProcGetExecutablePath)
+# define RTProcGetPriority                              RT_MANGLER(RTProcGetPriority)
+# define RTProcIsRunningByName                          RT_MANGLER(RTProcIsRunningByName)
+# define RTProcQueryParent                              RT_MANGLER(RTProcQueryParent)
+# define RTProcQueryUsername                            RT_MANGLER(RTProcQueryUsername)
+# define RTProcQueryUsernameA                           RT_MANGLER(RTProcQueryUsernameA)
+# define RTProcSelf                                     RT_MANGLER(RTProcSelf)
+# define RTProcSetPriority                              RT_MANGLER(RTProcSetPriority)
+# define RTProcShortName                                RT_MANGLER(RTProcShortName)
+# define RTProcTerminate                                RT_MANGLER(RTProcTerminate)
+# define RTProcWait                                     RT_MANGLER(RTProcWait)
+# define RTProcWaitNoResume                             RT_MANGLER(RTProcWaitNoResume)
+# define RTR0AssertPanicSystem                          RT_MANGLER(RTR0AssertPanicSystem)      /* r0drv */
+# define RTR0DbgKrnlInfoOpen                            RT_MANGLER(RTR0DbgKrnlInfoOpen)        /* r0drv */
+# define RTR0DbgKrnlInfoQueryMember                     RT_MANGLER(RTR0DbgKrnlInfoQueryMember) /* r0drv */
+# define RTR0DbgKrnlInfoQuerySize                       RT_MANGLER(RTR0DbgKrnlInfoQuerySize)   /* r0drv */
+# define RTR0DbgKrnlInfoQuerySymbol                     RT_MANGLER(RTR0DbgKrnlInfoQuerySymbol) /* r0drv */
+# define RTR0DbgKrnlInfoRelease                         RT_MANGLER(RTR0DbgKrnlInfoRelease)     /* r0drv */
+# define RTR0DbgKrnlInfoRetain                          RT_MANGLER(RTR0DbgKrnlInfoRetain)      /* r0drv */
+# define RTR0Init                                       RT_MANGLER(RTR0Init)                   /* r0drv */
+# define RTR0MemAreKrnlAndUsrDifferent                  RT_MANGLER(RTR0MemAreKrnlAndUsrDifferent) /* r0drv */
+# define RTR0MemExecDonate                              RT_MANGLER(RTR0MemExecDonate)          /* r0drv */
+# define RTR0MemKernelIsValidAddr                       RT_MANGLER(RTR0MemKernelIsValidAddr)   /* r0drv */
+# define RTR0MemObjAddress                              RT_MANGLER(RTR0MemObjAddress)          /* r0drv */
+# define RTR0MemObjAddressR3                            RT_MANGLER(RTR0MemObjAddressR3)        /* r0drv */
+# define RTR0MemKernelCopyFrom                          RT_MANGLER(RTR0MemKernelCopyFrom)      /* r0drv */
+# define RTR0MemKernelCopyTo                            RT_MANGLER(RTR0MemKernelCopyTo)        /* r0drv */
+# define RTR0MemObjAllocContTag                         RT_MANGLER(RTR0MemObjAllocContTag)     /* r0drv */
+# define RTR0MemObjAllocLowTag                          RT_MANGLER(RTR0MemObjAllocLowTag)      /* r0drv */
+# define RTR0MemObjAllocPageTag                         RT_MANGLER(RTR0MemObjAllocPageTag)     /* r0drv */
+# define RTR0MemObjAllocPhysExTag                       RT_MANGLER(RTR0MemObjAllocPhysExTag)   /* r0drv */
+# define RTR0MemObjAllocPhysNCTag                       RT_MANGLER(RTR0MemObjAllocPhysNCTag)   /* r0drv */
+# define RTR0MemObjAllocPhysTag                         RT_MANGLER(RTR0MemObjAllocPhysTag)     /* r0drv */
+# define RTR0MemObjEnterPhysTag                         RT_MANGLER(RTR0MemObjEnterPhysTag)     /* r0drv */
+# define RTR0MemObjFree                                 RT_MANGLER(RTR0MemObjFree)             /* r0drv */
+# define RTR0MemObjGetPagePhysAddr                      RT_MANGLER(RTR0MemObjGetPagePhysAddr)  /* r0drv */
+# define RTR0MemObjIsMapping                            RT_MANGLER(RTR0MemObjIsMapping)        /* r0drv */
+# define RTR0MemObjLockKernelTag                        RT_MANGLER(RTR0MemObjLockKernelTag)    /* r0drv */
+# define RTR0MemObjLockUserTag                          RT_MANGLER(RTR0MemObjLockUserTag)      /* r0drv */
+# define RTR0MemObjMapKernelExTag                       RT_MANGLER(RTR0MemObjMapKernelExTag)   /* r0drv */
+# define RTR0MemObjMapKernelTag                         RT_MANGLER(RTR0MemObjMapKernelTag)     /* r0drv */
+# define RTR0MemObjMapUserTag                           RT_MANGLER(RTR0MemObjMapUserTag)       /* r0drv */
+# define RTR0MemObjProtect                              RT_MANGLER(RTR0MemObjProtect)          /* r0drv */
+# define RTR0MemObjReserveKernelTag                     RT_MANGLER(RTR0MemObjReserveKernelTag) /* r0drv */
+# define RTR0MemObjReserveUserTag                       RT_MANGLER(RTR0MemObjReserveUserTag)   /* r0drv */
+# define RTR0MemObjSize                                 RT_MANGLER(RTR0MemObjSize)             /* r0drv */
+# define RTR0MemUserCopyFrom                            RT_MANGLER(RTR0MemUserCopyFrom)        /* r0drv */
+# define RTR0MemUserCopyTo                              RT_MANGLER(RTR0MemUserCopyTo)          /* r0drv */
+# define RTR0MemUserIsValidAddr                         RT_MANGLER(RTR0MemUserIsValidAddr)     /* r0drv */
+# define RTR0ProcHandleSelf                             RT_MANGLER(RTR0ProcHandleSelf)         /* r0drv */
+# define RTR0Term                                       RT_MANGLER(RTR0Term)                   /* r0drv */
+# define RTR0TermForced                                 RT_MANGLER(RTR0TermForced)             /* r0drv */
+# define RTR3InitDll                                    RT_MANGLER(RTR3InitDll)
+# define RTR3InitExe                                    RT_MANGLER(RTR3InitExe)
+# define RTR3InitExeNoArguments                         RT_MANGLER(RTR3InitExeNoArguments)
+# define RTR3InitEx                                     RT_MANGLER(RTR3InitEx)
+# define RTR3InitIsInitialized                          RT_MANGLER(RTR3InitIsInitialized)
+# define RTR3InitIsUnobtrusive                          RT_MANGLER(RTR3InitIsUnobtrusive)
+# define rtR3MemAlloc                                   RT_MANGLER(rtR3MemAlloc)
+# define rtR3MemFree                                    RT_MANGLER(rtR3MemFree)
+# define rtR3MemRealloc                                 RT_MANGLER(rtR3MemRealloc)
+# define RTRCInit                                       RT_MANGLER(RTRCInit)
+# define RTRCTerm                                       RT_MANGLER(RTRCTerm)
+# define RTRandAdvBytes                                 RT_MANGLER(RTRandAdvBytes)
+# define RTRandAdvCreateParkMiller                      RT_MANGLER(RTRandAdvCreateParkMiller)
+# define RTRandAdvCreateSystemFaster                    RT_MANGLER(RTRandAdvCreateSystemFaster)
+# define RTRandAdvCreateSystemTruer                     RT_MANGLER(RTRandAdvCreateSystemTruer)
+# define RTRandAdvDestroy                               RT_MANGLER(RTRandAdvDestroy)
+# define RTRandAdvRestoreState                          RT_MANGLER(RTRandAdvRestoreState)
+# define RTRandAdvS32                                   RT_MANGLER(RTRandAdvS32)
+# define RTRandAdvS32Ex                                 RT_MANGLER(RTRandAdvS32Ex)
+# define RTRandAdvS64                                   RT_MANGLER(RTRandAdvS64)
+# define RTRandAdvS64Ex                                 RT_MANGLER(RTRandAdvS64Ex)
+# define RTRandAdvSaveState                             RT_MANGLER(RTRandAdvSaveState)
+# define RTRandAdvSeed                                  RT_MANGLER(RTRandAdvSeed)
+# define RTRandAdvU32                                   RT_MANGLER(RTRandAdvU32)
+# define RTRandAdvU32Ex                                 RT_MANGLER(RTRandAdvU32Ex)
+# define RTRandAdvU64                                   RT_MANGLER(RTRandAdvU64)
+# define RTRandAdvU64Ex                                 RT_MANGLER(RTRandAdvU64Ex)
+# define RTRandBytes                                    RT_MANGLER(RTRandBytes)
+# define RTRandS32                                      RT_MANGLER(RTRandS32)
+# define RTRandS32Ex                                    RT_MANGLER(RTRandS32Ex)
+# define RTRandS64                                      RT_MANGLER(RTRandS64)
+# define RTRandS64Ex                                    RT_MANGLER(RTRandS64Ex)
+# define RTRandU32                                      RT_MANGLER(RTRandU32)
+# define RTRandU32Ex                                    RT_MANGLER(RTRandU32Ex)
+# define RTRandU64                                      RT_MANGLER(RTRandU64)
+# define RTRandU64Ex                                    RT_MANGLER(RTRandU64Ex)
+# define RTReqPoolAlloc                                 RT_MANGLER(RTReqPoolAlloc)
+# define RTReqPoolCallEx                                RT_MANGLER(RTReqPoolCallEx)
+# define RTReqPoolCallExV                               RT_MANGLER(RTReqPoolCallExV)
+# define RTReqPoolCallWait                              RT_MANGLER(RTReqPoolCallWait)
+# define RTReqPoolCallNoWait                            RT_MANGLER(RTReqPoolCallNoWait)
+# define RTReqPoolCallVoidWait                          RT_MANGLER(RTReqPoolCallVoidWait)
+# define RTReqPoolCallVoidNoWait                        RT_MANGLER(RTReqPoolCallVoidNoWait)
+# define RTReqPoolCreate                                RT_MANGLER(RTReqPoolCreate)
+# define RTReqPoolGetCfgVar                             RT_MANGLER(RTReqPoolGetCfgVar)
+# define RTReqPoolGetStat                               RT_MANGLER(RTReqPoolGetStat)
+# define RTReqPoolRetain                                RT_MANGLER(RTReqPoolRetain)
+# define RTReqPoolRelease                               RT_MANGLER(RTReqPoolRelease)
+# define RTReqPoolSetCfgVar                             RT_MANGLER(RTReqPoolSetCfgVar)
+# define RTReqQueueAlloc                                RT_MANGLER(RTReqQueueAlloc)
+# define RTReqQueueCall                                 RT_MANGLER(RTReqQueueCall)
+# define RTReqQueueCallEx                               RT_MANGLER(RTReqQueueCallEx)
+# define RTReqQueueCallV                                RT_MANGLER(RTReqQueueCallV)
+# define RTReqQueueCallVoid                             RT_MANGLER(RTReqQueueCallVoid)
+# define RTReqQueueCreate                               RT_MANGLER(RTReqQueueCreate)
+# define RTReqQueueDestroy                              RT_MANGLER(RTReqQueueDestroy)
+# define RTReqQueueIsBusy                               RT_MANGLER(RTReqQueueIsBusy)
+# define RTReqQueueProcess                              RT_MANGLER(RTReqQueueProcess)
+# define RTReqSubmit                                    RT_MANGLER(RTReqSubmit)
+# define RTReqRelease                                   RT_MANGLER(RTReqRelease)
+# define RTReqRetain                                    RT_MANGLER(RTReqRetain)
+# define RTReqWait                                      RT_MANGLER(RTReqWait)
+# define RTReqGetStatus                                 RT_MANGLER(RTReqGetStatus)
+# define RTS3BucketsDestroy                             RT_MANGLER(RTS3BucketsDestroy)
+# define RTS3Create                                     RT_MANGLER(RTS3Create)
+# define RTS3CreateBucket                               RT_MANGLER(RTS3CreateBucket)
+# define RTS3DeleteBucket                               RT_MANGLER(RTS3DeleteBucket)
+# define RTS3DeleteKey                                  RT_MANGLER(RTS3DeleteKey)
+# define RTS3Destroy                                    RT_MANGLER(RTS3Destroy)
+# define RTS3GetBucketKeys                              RT_MANGLER(RTS3GetBucketKeys)
+# define RTS3GetBuckets                                 RT_MANGLER(RTS3GetBuckets)
+# define RTS3GetKey                                     RT_MANGLER(RTS3GetKey)
+# define RTS3KeysDestroy                                RT_MANGLER(RTS3KeysDestroy)
+# define RTS3PutKey                                     RT_MANGLER(RTS3PutKey)
+# define RTS3SetProgressCallback                        RT_MANGLER(RTS3SetProgressCallback)
+# define RTSemEventAddSignaller                         RT_MANGLER(RTSemEventAddSignaller)
+# define RTSemEventCreate                               RT_MANGLER(RTSemEventCreate)
+# define RTSemEventCreateEx                             RT_MANGLER(RTSemEventCreateEx)
+# define RTSemEventDestroy                              RT_MANGLER(RTSemEventDestroy)
+# define RTSemEventGetResolution                        RT_MANGLER(RTSemEventGetResolution)    /* r0drv */
+# define RTSemEventMultiAddSignaller                    RT_MANGLER(RTSemEventMultiAddSignaller)
+# define RTSemEventMultiCreate                          RT_MANGLER(RTSemEventMultiCreate)
+# define RTSemEventMultiCreateEx                        RT_MANGLER(RTSemEventMultiCreateEx)
+# define RTSemEventMultiDestroy                         RT_MANGLER(RTSemEventMultiDestroy)
+# define RTSemEventMultiGetResolution                   RT_MANGLER(RTSemEventMultiGetResolution) /* r0drv */
+# define RTSemEventMultiRemoveSignaller                 RT_MANGLER(RTSemEventMultiRemoveSignaller)
+# define RTSemEventMultiReset                           RT_MANGLER(RTSemEventMultiReset)
+# define RTSemEventMultiSetSignaller                    RT_MANGLER(RTSemEventMultiSetSignaller)
+# define RTSemEventMultiSignal                          RT_MANGLER(RTSemEventMultiSignal)
+# define RTSemEventMultiWait                            RT_MANGLER(RTSemEventMultiWait)
+# define RTSemEventMultiWaitEx                          RT_MANGLER(RTSemEventMultiWaitEx)
+# define RTSemEventMultiWaitEx                          RT_MANGLER(RTSemEventMultiWaitEx)      /* r0drv */
+# define RTSemEventMultiWaitExDebug                     RT_MANGLER(RTSemEventMultiWaitExDebug)
+# define RTSemEventMultiWaitExDebug                     RT_MANGLER(RTSemEventMultiWaitExDebug) /* r0drv */
+# define RTSemEventMultiWaitNoResume                    RT_MANGLER(RTSemEventMultiWaitNoResume)
+# define RTSemEventRemoveSignaller                      RT_MANGLER(RTSemEventRemoveSignaller)
+# define RTSemEventSetSignaller                         RT_MANGLER(RTSemEventSetSignaller)
+# define RTSemEventSignal                               RT_MANGLER(RTSemEventSignal)
+# define RTSemEventWait                                 RT_MANGLER(RTSemEventWait)
+# define RTSemEventWaitEx                               RT_MANGLER(RTSemEventWaitEx)           /* r0drv */
+# define RTSemEventWaitExDebug                          RT_MANGLER(RTSemEventWaitExDebug)      /* r0drv */
+# define RTSemEventWaitNoResume                         RT_MANGLER(RTSemEventWaitNoResume)
+# define RTSemFastMutexCreate                           RT_MANGLER(RTSemFastMutexCreate)
+# define RTSemFastMutexDestroy                          RT_MANGLER(RTSemFastMutexDestroy)
+# define RTSemFastMutexRelease                          RT_MANGLER(RTSemFastMutexRelease)
+# define RTSemFastMutexRequest                          RT_MANGLER(RTSemFastMutexRequest)
+# define RTSemMutexCreate                               RT_MANGLER(RTSemMutexCreate)
+# define RTSemMutexCreateEx                             RT_MANGLER(RTSemMutexCreateEx)
+# define RTSemMutexDestroy                              RT_MANGLER(RTSemMutexDestroy)
+# define RTSemMutexIsOwned                              RT_MANGLER(RTSemMutexIsOwned)
+# define RTSemMutexRelease                              RT_MANGLER(RTSemMutexRelease)
+# define RTSemMutexRequest                              RT_MANGLER(RTSemMutexRequest)
+# define RTSemMutexRequestDebug                         RT_MANGLER(RTSemMutexRequestDebug)
+# define RTSemMutexRequestNoResume                      RT_MANGLER(RTSemMutexRequestNoResume)
+# define RTSemMutexRequestNoResumeDebug                 RT_MANGLER(RTSemMutexRequestNoResumeDebug)
+# define RTSemMutexSetSubClass                          RT_MANGLER(RTSemMutexSetSubClass)
+# define RTSemPing                                      RT_MANGLER(RTSemPing)
+# define RTSemPingPongDelete                            RT_MANGLER(RTSemPingPongDelete)
+# define RTSemPingPongInit                              RT_MANGLER(RTSemPingPongInit)
+# define RTSemPingWait                                  RT_MANGLER(RTSemPingWait)
+# define RTSemPong                                      RT_MANGLER(RTSemPong)
+# define RTSemPongWait                                  RT_MANGLER(RTSemPongWait)
+# define RTSemRWCreate                                  RT_MANGLER(RTSemRWCreate)
+# define RTSemRWCreateEx                                RT_MANGLER(RTSemRWCreateEx)
+# define RTSemRWDestroy                                 RT_MANGLER(RTSemRWDestroy)
+# define RTSemRWGetReadCount                            RT_MANGLER(RTSemRWGetReadCount)
+# define RTSemRWGetWriteRecursion                       RT_MANGLER(RTSemRWGetWriteRecursion)
+# define RTSemRWGetWriterReadRecursion                  RT_MANGLER(RTSemRWGetWriterReadRecursion)
+# define RTSemRWIsReadOwner                             RT_MANGLER(RTSemRWIsReadOwner)
+# define RTSemRWIsWriteOwner                            RT_MANGLER(RTSemRWIsWriteOwner)
+# define RTSemRWReleaseRead                             RT_MANGLER(RTSemRWReleaseRead)
+# define RTSemRWReleaseWrite                            RT_MANGLER(RTSemRWReleaseWrite)
+# define RTSemRWRequestRead                             RT_MANGLER(RTSemRWRequestRead)
+# define RTSemRWRequestReadDebug                        RT_MANGLER(RTSemRWRequestReadDebug)
+# define RTSemRWRequestReadNoResume                     RT_MANGLER(RTSemRWRequestReadNoResume)
+# define RTSemRWRequestReadNoResumeDebug                RT_MANGLER(RTSemRWRequestReadNoResumeDebug)
+# define RTSemRWRequestWrite                            RT_MANGLER(RTSemRWRequestWrite)
+# define RTSemRWRequestWriteDebug                       RT_MANGLER(RTSemRWRequestWriteDebug)
+# define RTSemRWRequestWriteNoResume                    RT_MANGLER(RTSemRWRequestWriteNoResume)
+# define RTSemRWRequestWriteNoResumeDebug               RT_MANGLER(RTSemRWRequestWriteNoResumeDebug)
+# define RTSemRWSetSubClass                             RT_MANGLER(RTSemRWSetSubClass)
+# define RTSemSpinMutexCreate                           RT_MANGLER(RTSemSpinMutexCreate)
+# define RTSemSpinMutexDestroy                          RT_MANGLER(RTSemSpinMutexDestroy)
+# define RTSemSpinMutexRelease                          RT_MANGLER(RTSemSpinMutexRelease)
+# define RTSemSpinMutexRequest                          RT_MANGLER(RTSemSpinMutexRequest)
+# define RTSemSpinMutexTryRequest                       RT_MANGLER(RTSemSpinMutexTryRequest)
+# define RTSemXRoadsCreate                              RT_MANGLER(RTSemXRoadsCreate)
+# define RTSemXRoadsDestroy                             RT_MANGLER(RTSemXRoadsDestroy)
+# define RTSemXRoadsEWEnter                             RT_MANGLER(RTSemXRoadsEWEnter)
+# define RTSemXRoadsEWLeave                             RT_MANGLER(RTSemXRoadsEWLeave)
+# define RTSemXRoadsNSEnter                             RT_MANGLER(RTSemXRoadsNSEnter)
+# define RTSemXRoadsNSLeave                             RT_MANGLER(RTSemXRoadsNSLeave)
+# define RTSgBufAdvance                                 RT_MANGLER(RTSgBufAdvance)
+# define RTSgBufClone                                   RT_MANGLER(RTSgBufClone)
+# define RTSgBufCmp                                     RT_MANGLER(RTSgBufCmp)
+# define RTSgBufCmpEx                                   RT_MANGLER(RTSgBufCmpEx)
+# define RTSgBufCopy                                    RT_MANGLER(RTSgBufCopy)
+# define RTSgBufCopyFromBuf                             RT_MANGLER(RTSgBufCopyFromBuf)
+# define RTSgBufCopyToBuf                               RT_MANGLER(RTSgBufCopyToBuf)
+# define RTSgBufInit                                    RT_MANGLER(RTSgBufInit)
+# define RTSgBufIsZero                                  RT_MANGLER(RTSgBufIsZero)
+# define RTSgBufReset                                   RT_MANGLER(RTSgBufReset)
+# define RTSgBufSegArrayCreate                          RT_MANGLER(RTSgBufSegArrayCreate)
+# define RTSgBufSet                                     RT_MANGLER(RTSgBufSet)
+# define RTSgBufGetNextSegment                          RT_MANGLER(RTSgBufGetNextSegment)
+# define RTSha1                                         RT_MANGLER(RTSha1)
+# define RTSha1Check                                    RT_MANGLER(RTSha1Check)
+# define RTSha1Digest                                   RT_MANGLER(RTSha1Digest)
+# define RTSha1DigestFromFile                           RT_MANGLER(RTSha1DigestFromFile)
+# define RTSha1Final                                    RT_MANGLER(RTSha1Final)
+# define RTSha1FromString                               RT_MANGLER(RTSha1FromString)
+# define RTSha1Init                                     RT_MANGLER(RTSha1Init)
+# define RTSha1ToString                                 RT_MANGLER(RTSha1ToString)
+# define RTSha1Update                                   RT_MANGLER(RTSha1Update)
+# define RTSha224                                       RT_MANGLER(RTSha224)
+# define RTSha224Check                                  RT_MANGLER(RTSha224Check)
+# define RTSha224Final                                  RT_MANGLER(RTSha224Final)
+# define RTSha224FromString                             RT_MANGLER(RTSha224FromString)
+# define RTSha224Init                                   RT_MANGLER(RTSha224Init)
+# define RTSha224ToString                               RT_MANGLER(RTSha224ToString)
+# define RTSha224Update                                 RT_MANGLER(RTSha224Update)
+# define RTSha224Digest                                 RT_MANGLER(RTSha224Digest)
+# define RTSha224DigestFromFile                         RT_MANGLER(RTSha224DigestFromFile)
+# define RTSha256                                       RT_MANGLER(RTSha256)
+# define RTSha256Check                                  RT_MANGLER(RTSha256Check)
+# define RTSha256Final                                  RT_MANGLER(RTSha256Final)
+# define RTSha256FromString                             RT_MANGLER(RTSha256FromString)
+# define RTSha256Init                                   RT_MANGLER(RTSha256Init)
+# define RTSha256ToString                               RT_MANGLER(RTSha256ToString)
+# define RTSha256Update                                 RT_MANGLER(RTSha256Update)
+# define RTSha256Digest                                 RT_MANGLER(RTSha256Digest)
+# define RTSha256DigestFromFile                         RT_MANGLER(RTSha256DigestFromFile)
+# define RTSha384                                       RT_MANGLER(RTSha384)
+# define RTSha384Check                                  RT_MANGLER(RTSha384Check)
+# define RTSha384Final                                  RT_MANGLER(RTSha384Final)
+# define RTSha384FromString                             RT_MANGLER(RTSha384FromString)
+# define RTSha384Init                                   RT_MANGLER(RTSha384Init)
+# define RTSha384ToString                               RT_MANGLER(RTSha384ToString)
+# define RTSha384Update                                 RT_MANGLER(RTSha384Update)
+# define RTSha512                                       RT_MANGLER(RTSha512)
+# define RTSha512Check                                  RT_MANGLER(RTSha512Check)
+# define RTSha512Final                                  RT_MANGLER(RTSha512Final)
+# define RTSha512FromString                             RT_MANGLER(RTSha512FromString)
+# define RTSha512Init                                   RT_MANGLER(RTSha512Init)
+# define RTSha512ToString                               RT_MANGLER(RTSha512ToString)
+# define RTSha512Update                                 RT_MANGLER(RTSha512Update)
+# define RTSha512t224                                   RT_MANGLER(RTSha512t224)
+# define RTSha512t224Check                              RT_MANGLER(RTSha512t224Check)
+# define RTSha512t224Final                              RT_MANGLER(RTSha512t224Final)
+# define RTSha512t224FromString                         RT_MANGLER(RTSha512t224FromString)
+# define RTSha512t224Init                               RT_MANGLER(RTSha512t224Init)
+# define RTSha512t224ToString                           RT_MANGLER(RTSha512t224ToString)
+# define RTSha512t224Update                             RT_MANGLER(RTSha512t224Update)
+# define RTSha512t256                                   RT_MANGLER(RTSha512t256)
+# define RTSha512t256Check                              RT_MANGLER(RTSha512t256Check)
+# define RTSha512t256Final                              RT_MANGLER(RTSha512t256Final)
+# define RTSha512t256FromString                         RT_MANGLER(RTSha512t256FromString)
+# define RTSha512t256Init                               RT_MANGLER(RTSha512t256Init)
+# define RTSha512t256ToString                           RT_MANGLER(RTSha512t256ToString)
+# define RTSha512t256Update                             RT_MANGLER(RTSha512t256Update)
+# define RTSocketClose                                  RT_MANGLER(RTSocketClose)
+# define RTSocketFromNative                             RT_MANGLER(RTSocketFromNative)
+# define RTSocketQueryAddressStr                        RT_MANGLER(RTSocketQueryAddressStr)
+# define RTSocketGetLocalAddress                        RT_MANGLER(RTSocketGetLocalAddress)
+# define RTSocketGetPeerAddress                         RT_MANGLER(RTSocketGetPeerAddress)
+# define RTSocketParseInetAddress                       RT_MANGLER(RTSocketParseInetAddress)
+# define RTSocketRead                                   RT_MANGLER(RTSocketRead)
+# define RTSocketReadFrom                               RT_MANGLER(RTSocketReadFrom)
+# define RTSocketReadNB                                 RT_MANGLER(RTSocketReadNB)
+# define RTSocketRelease                                RT_MANGLER(RTSocketRelease)
+# define RTSocketRetain                                 RT_MANGLER(RTSocketRetain)
+# define RTSocketSelectOne                              RT_MANGLER(RTSocketSelectOne)
+# define RTSocketSelectOneEx                            RT_MANGLER(RTSocketSelectOneEx)
+# define RTSocketSetInheritance                         RT_MANGLER(RTSocketSetInheritance)
+# define RTSocketSgWrite                                RT_MANGLER(RTSocketSgWrite)
+# define RTSocketSgWriteL                               RT_MANGLER(RTSocketSgWriteL)
+# define RTSocketSgWriteLNB                             RT_MANGLER(RTSocketSgWriteLNB)
+# define RTSocketSgWriteLV                              RT_MANGLER(RTSocketSgWriteLV)
+# define RTSocketSgWriteLVNB                            RT_MANGLER(RTSocketSgWriteLVNB)
+# define RTSocketSgWriteNB                              RT_MANGLER(RTSocketSgWriteNB)
+# define RTSocketShutdown                               RT_MANGLER(RTSocketShutdown)
+# define RTSocketToNative                               RT_MANGLER(RTSocketToNative)
+# define RTSocketWrite                                  RT_MANGLER(RTSocketWrite)
+# define RTSocketWriteNB                                RT_MANGLER(RTSocketWriteNB)
+# define RTSocketWriteTo                                RT_MANGLER(RTSocketWriteTo)
+# define RTSocketWriteToNB                              RT_MANGLER(RTSocketWriteToNB)
+# define RTSortApvIsSorted                              RT_MANGLER(RTSortApvIsSorted)
+# define RTSortApvShell                                 RT_MANGLER(RTSortApvShell)
+# define RTSortIsSorted                                 RT_MANGLER(RTSortIsSorted)
+# define RTSortShell                                    RT_MANGLER(RTSortShell)
+# define RTSpinlockAcquire                              RT_MANGLER(RTSpinlockAcquire)
+# define RTSpinlockAcquireNoInts                        RT_MANGLER(RTSpinlockAcquireNoInts)
+# define RTSpinlockCreate                               RT_MANGLER(RTSpinlockCreate)
+# define RTSpinlockDestroy                              RT_MANGLER(RTSpinlockDestroy)
+# define RTSpinlockRelease                              RT_MANGLER(RTSpinlockRelease)
+# define RTStrAAppendExNVTag                            RT_MANGLER(RTStrAAppendExNVTag)
+# define RTStrAAppendNTag                               RT_MANGLER(RTStrAAppendNTag)
+# define RTStrAAppendTag                                RT_MANGLER(RTStrAAppendTag)
+# define RTStrAllocExTag                                RT_MANGLER(RTStrAllocExTag)
+# define RTStrAllocTag                                  RT_MANGLER(RTStrAllocTag)
+# define RTStrAPrintf2VTag                              RT_MANGLER(RTStrAPrintf2VTag)
+# define RTStrAPrintfVTag                               RT_MANGLER(RTStrAPrintfVTag)
+# define RTStrATruncateTag                              RT_MANGLER(RTStrATruncateTag)
+# define RTStrCacheCreate                               RT_MANGLER(RTStrCacheCreate)
+# define RTStrCacheDestroy                              RT_MANGLER(RTStrCacheDestroy)
+# define RTStrCacheEnter                                RT_MANGLER(RTStrCacheEnter)
+# define RTStrCacheEnterLower                           RT_MANGLER(RTStrCacheEnterLower)
+# define RTStrCacheEnterLowerN                          RT_MANGLER(RTStrCacheEnterLowerN)
+# define RTStrCacheEnterN                               RT_MANGLER(RTStrCacheEnterN)
+# define RTStrCacheGetStats                             RT_MANGLER(RTStrCacheGetStats)
+# define RTStrCacheIsRealImpl                           RT_MANGLER(RTStrCacheIsRealImpl)
+# define RTStrCacheLength                               RT_MANGLER(RTStrCacheLength)
+# define RTStrCacheRelease                              RT_MANGLER(RTStrCacheRelease)
+# define RTStrCacheRetain                               RT_MANGLER(RTStrCacheRetain)
+# define RTStrCalcLatin1Len                             RT_MANGLER(RTStrCalcLatin1Len)
+# define RTStrCalcLatin1LenEx                           RT_MANGLER(RTStrCalcLatin1LenEx)
+# define RTStrCalcUtf16Len                              RT_MANGLER(RTStrCalcUtf16Len)
+# define RTStrCalcUtf16LenEx                            RT_MANGLER(RTStrCalcUtf16LenEx)
+# define RTStrCat                                       RT_MANGLER(RTStrCat)
+# define RTStrCatEx                                     RT_MANGLER(RTStrCatEx)
+# define RTStrCatP                                      RT_MANGLER(RTStrCatP)
+# define RTStrCatPEx                                    RT_MANGLER(RTStrCatPEx)
+# define RTStrCmp                                       RT_MANGLER(RTStrCmp)
+# define RTStrConvertHexBytes                           RT_MANGLER(RTStrConvertHexBytes)
+# define RTStrCopy                                      RT_MANGLER(RTStrCopy)
+# define RTStrCopyEx                                    RT_MANGLER(RTStrCopyEx)
+# define RTStrCopyP                                     RT_MANGLER(RTStrCopyP)
+# define RTStrCopyPEx                                   RT_MANGLER(RTStrCopyPEx)
+# define RTStrCurrentCPToUtf8Tag                        RT_MANGLER(RTStrCurrentCPToUtf8Tag)
+# define RTStrDupExTag                                  RT_MANGLER(RTStrDupExTag)
+# define RTStrDupNTag                                   RT_MANGLER(RTStrDupNTag)
+# define RTStrDupTag                                    RT_MANGLER(RTStrDupTag)
+# define RTStrFormat                                    RT_MANGLER(RTStrFormat)
+# define RTStrFormatNumber                              RT_MANGLER(RTStrFormatNumber)
+# define RTStrFormatR80                                 RT_MANGLER(RTStrFormatR80)
+# define RTStrFormatR80u2                               RT_MANGLER(RTStrFormatR80u2)
+# define RTStrFormatTypeDeregister                      RT_MANGLER(RTStrFormatTypeDeregister)
+# define RTStrFormatTypeRegister                        RT_MANGLER(RTStrFormatTypeRegister)
+# define RTStrFormatTypeSetUser                         RT_MANGLER(RTStrFormatTypeSetUser)
+# define RTStrFormatU128                                RT_MANGLER(RTStrFormatU128)
+# define RTStrFormatU256                                RT_MANGLER(RTStrFormatU256)
+# define RTStrFormatU512                                RT_MANGLER(RTStrFormatU512)
+# define RTStrFormatU16                                 RT_MANGLER(RTStrFormatU16)
+# define RTStrFormatU32                                 RT_MANGLER(RTStrFormatU32)
+# define RTStrFormatU64                                 RT_MANGLER(RTStrFormatU64)
+# define RTStrFormatU8                                  RT_MANGLER(RTStrFormatU8)
+# define RTStrFormatV                                   RT_MANGLER(RTStrFormatV)
+# define RTStrFree                                      RT_MANGLER(RTStrFree)
+# define RTStrGetCpExInternal                           RT_MANGLER(RTStrGetCpExInternal)
+# define RTStrGetCpInternal                             RT_MANGLER(RTStrGetCpInternal)
+# define RTStrGetCpNExInternal                          RT_MANGLER(RTStrGetCpNExInternal)
+# define RTStrHash1                                     RT_MANGLER(RTStrHash1)
+# define RTStrHash1ExN                                  RT_MANGLER(RTStrHash1ExN)
+# define RTStrHash1ExNV                                 RT_MANGLER(RTStrHash1ExNV)
+# define RTStrHash1N                                    RT_MANGLER(RTStrHash1N)
+# define RTStrICmp                                      RT_MANGLER(RTStrICmp)
+# define RTStrICmpAscii                                 RT_MANGLER(RTStrICmpAscii)
+# define RTStrIStartsWith                               RT_MANGLER(RTStrIStartsWith)
+# define RTStrIStr                                      RT_MANGLER(RTStrIStr)
+# define RTStrIsCaseFoldable                            RT_MANGLER(RTStrIsCaseFoldable)
+# define RTStrIsLowerCased                              RT_MANGLER(RTStrIsLowerCased)
+# define RTStrIsUpperCased                              RT_MANGLER(RTStrIsUpperCased)
+# define RTStrIsValidEncoding                           RT_MANGLER(RTStrIsValidEncoding)
+# define RTStrmClearError                               RT_MANGLER(RTStrmClearError)
+# define RTStrmClose                                    RT_MANGLER(RTStrmClose)
+# define RTStrmError                                    RT_MANGLER(RTStrmError)
+# define RTStrmFlush                                    RT_MANGLER(RTStrmFlush)
+# define RTStrmGetCh                                    RT_MANGLER(RTStrmGetCh)
+# define RTStrmInputGetEchoChars                        RT_MANGLER(RTStrmInputGetEchoChars)
+# define RTStrmGetLine                                  RT_MANGLER(RTStrmGetLine)
+# define RTStrmOpen                                     RT_MANGLER(RTStrmOpen)
+# define RTStrmOpenF                                    RT_MANGLER(RTStrmOpenF)
+# define RTStrmOpenFV                                   RT_MANGLER(RTStrmOpenFV)
+# define RTStrmPrintf                                   RT_MANGLER(RTStrmPrintf)
+# define RTStrmPrintfV                                  RT_MANGLER(RTStrmPrintfV)
+# define RTStrmDumpPrintfV                              RT_MANGLER(RTStrmDumpPrintfV)
+# define RTStrmPutCh                                    RT_MANGLER(RTStrmPutCh)
+# define RTStrmPutStr                                   RT_MANGLER(RTStrmPutStr)
+# define RTStrmReadEx                                   RT_MANGLER(RTStrmReadEx)
+# define RTStrmRewind                                   RT_MANGLER(RTStrmRewind)
+# define RTStrmInputSetEchoChars                        RT_MANGLER(RTStrmInputSetEchoChars)
+# define RTStrmSetMode                                  RT_MANGLER(RTStrmSetMode)
+# define RTStrmWriteEx                                  RT_MANGLER(RTStrmWriteEx)
+# define RTStrNCmp                                      RT_MANGLER(RTStrNCmp)
+# define RTStrNICmp                                     RT_MANGLER(RTStrNICmp)
+# define RTStrNLen                                      RT_MANGLER(RTStrNLen)
+# define RTStrNLenEx                                    RT_MANGLER(RTStrNLenEx)
+# define RTStrPrevCp                                    RT_MANGLER(RTStrPrevCp)
+# define RTStrPrintf                                    RT_MANGLER(RTStrPrintf)
+# define RTStrPrintfEx                                  RT_MANGLER(RTStrPrintfEx)
+# define RTStrPrintfExV                                 RT_MANGLER(RTStrPrintfExV)
+# define RTStrPrintfV                                   RT_MANGLER(RTStrPrintfV)
+# define RTStrPrintHexBytes                             RT_MANGLER(RTStrPrintHexBytes)
+# define RTStrPurgeEncoding                             RT_MANGLER(RTStrPurgeEncoding)
+# define RTStrPurgeComplementSet                        RT_MANGLER(RTStrPurgeComplementSet)
+# define RTStrPutCpInternal                             RT_MANGLER(RTStrPutCpInternal)
+# define RTStrReallocTag                                RT_MANGLER(RTStrReallocTag)
+# define RTStrSimplePatternMatch                        RT_MANGLER(RTStrSimplePatternMatch)
+# define RTStrSimplePatternMultiMatch                   RT_MANGLER(RTStrSimplePatternMultiMatch)
+# define RTStrSimplePatternNMatch                       RT_MANGLER(RTStrSimplePatternNMatch)
+# define RTStrSpaceDestroy                              RT_MANGLER(RTStrSpaceDestroy)
+# define RTStrSpaceEnumerate                            RT_MANGLER(RTStrSpaceEnumerate)
+# define RTStrSpaceGet                                  RT_MANGLER(RTStrSpaceGet)
+# define RTStrSpaceGetN                                 RT_MANGLER(RTStrSpaceGetN)
+# define RTStrSpaceInsert                               RT_MANGLER(RTStrSpaceInsert)
+# define RTStrSpaceRemove                               RT_MANGLER(RTStrSpaceRemove)
+# define RTStrStartsWith                                RT_MANGLER(RTStrStartsWith)
+# define RTStrStr                                       RT_MANGLER(RTStrStr)
+# define RTStrStrip                                     RT_MANGLER(RTStrStrip)
+# define RTStrStripL                                    RT_MANGLER(RTStrStripL)
+# define RTStrStripR                                    RT_MANGLER(RTStrStripR)
+# define RTStrToInt16                                   RT_MANGLER(RTStrToInt16)
+# define RTStrToInt16Ex                                 RT_MANGLER(RTStrToInt16Ex)
+# define RTStrToInt16Full                               RT_MANGLER(RTStrToInt16Full)
+# define RTStrToInt32                                   RT_MANGLER(RTStrToInt32)
+# define RTStrToInt32Ex                                 RT_MANGLER(RTStrToInt32Ex)
+# define RTStrToInt32Full                               RT_MANGLER(RTStrToInt32Full)
+# define RTStrToInt64                                   RT_MANGLER(RTStrToInt64)
+# define RTStrToInt64Ex                                 RT_MANGLER(RTStrToInt64Ex)
+# define RTStrToInt64Full                               RT_MANGLER(RTStrToInt64Full)
+# define RTStrToInt8                                    RT_MANGLER(RTStrToInt8)
+# define RTStrToInt8Ex                                  RT_MANGLER(RTStrToInt8Ex)
+# define RTStrToInt8Full                                RT_MANGLER(RTStrToInt8Full)
+# define RTStrToLatin1ExTag                             RT_MANGLER(RTStrToLatin1ExTag)
+# define RTStrToLatin1Tag                               RT_MANGLER(RTStrToLatin1Tag)
+# define RTStrToLower                                   RT_MANGLER(RTStrToLower)
+# define RTStrToUInt16                                  RT_MANGLER(RTStrToUInt16)
+# define RTStrToUInt16Ex                                RT_MANGLER(RTStrToUInt16Ex)
+# define RTStrToUInt16Full                              RT_MANGLER(RTStrToUInt16Full)
+# define RTStrToUInt32                                  RT_MANGLER(RTStrToUInt32)
+# define RTStrToUInt32Ex                                RT_MANGLER(RTStrToUInt32Ex)
+# define RTStrToUInt32Full                              RT_MANGLER(RTStrToUInt32Full)
+# define RTStrToUInt64                                  RT_MANGLER(RTStrToUInt64)
+# define RTStrToUInt64Ex                                RT_MANGLER(RTStrToUInt64Ex)
+# define RTStrToUInt64Full                              RT_MANGLER(RTStrToUInt64Full)
+# define RTStrToUInt8                                   RT_MANGLER(RTStrToUInt8)
+# define RTStrToUInt8Ex                                 RT_MANGLER(RTStrToUInt8Ex)
+# define RTStrToUInt8Full                               RT_MANGLER(RTStrToUInt8Full)
+# define RTStrToUni                                     RT_MANGLER(RTStrToUni)
+# define RTStrToUniEx                                   RT_MANGLER(RTStrToUniEx)
+# define RTStrToUpper                                   RT_MANGLER(RTStrToUpper)
+# define RTStrToUtf16ExTag                              RT_MANGLER(RTStrToUtf16ExTag)
+# define RTStrToUtf16Tag                                RT_MANGLER(RTStrToUtf16Tag)
+# define RTStrUniLen                                    RT_MANGLER(RTStrUniLen)
+# define RTStrUniLenEx                                  RT_MANGLER(RTStrUniLenEx)
+# define RTStrUtf8ToCurrentCPTag                        RT_MANGLER(RTStrUtf8ToCurrentCPTag)
+# define RTStrValidateEncoding                          RT_MANGLER(RTStrValidateEncoding)
+# define RTStrValidateEncodingEx                        RT_MANGLER(RTStrValidateEncodingEx)
+# define RTStrVersionCompare                            RT_MANGLER(RTStrVersionCompare)
+# define RTSymlinkCreate                                RT_MANGLER(RTSymlinkCreate)
+# define RTSymlinkDelete                                RT_MANGLER(RTSymlinkDelete)
+# define RTSymlinkExists                                RT_MANGLER(RTSymlinkExists)
+# define RTSymlinkIsDangling                            RT_MANGLER(RTSymlinkIsDangling)
+# define RTSymlinkRead                                  RT_MANGLER(RTSymlinkRead)
+# define RTSymlinkReadA                                 RT_MANGLER(RTSymlinkReadA)
+# define RTSystemIsInsideVM                             RT_MANGLER(RTSystemIsInsideVM)
+# define RTSystemQueryAvailableRam                      RT_MANGLER(RTSystemQueryAvailableRam)
+# define RTSystemQueryDmiString                         RT_MANGLER(RTSystemQueryDmiString)
+# define RTSystemQueryOSInfo                            RT_MANGLER(RTSystemQueryOSInfo)
+# define RTSystemQueryTotalRam                          RT_MANGLER(RTSystemQueryTotalRam)
+# define RTSystemShutdown                               RT_MANGLER(RTSystemShutdown)
+# define RTTarClose                                     RT_MANGLER(RTTarClose)
+# define RTTarFileClose                                 RT_MANGLER(RTTarFileClose)
+# define RTTarFileGetSize                               RT_MANGLER(RTTarFileGetSize)
+# define RTTarFileOpen                                  RT_MANGLER(RTTarFileOpen)
+# define RTTarFileReadAt                                RT_MANGLER(RTTarFileReadAt)
+# define RTTarFileSetSize                               RT_MANGLER(RTTarFileSetSize)
+# define RTTarFileWriteAt                               RT_MANGLER(RTTarFileWriteAt)
+# define RTTarOpen                                      RT_MANGLER(RTTarOpen)
+# define RTTcpClientCancelConnect                       RT_MANGLER(RTTcpClientCancelConnect)
+# define RTTcpClientClose                               RT_MANGLER(RTTcpClientClose)
+# define RTTcpClientCloseEx                             RT_MANGLER(RTTcpClientCloseEx)
+# define RTTcpClientConnect                             RT_MANGLER(RTTcpClientConnect)
+# define RTTcpClientConnectEx                           RT_MANGLER(RTTcpClientConnectEx)
+# define RTTcpFlush                                     RT_MANGLER(RTTcpFlush)
+# define RTTcpGetLocalAddress                           RT_MANGLER(RTTcpGetLocalAddress)
+# define RTTcpGetPeerAddress                            RT_MANGLER(RTTcpGetPeerAddress)
+# define RTTcpRead                                      RT_MANGLER(RTTcpRead)
+# define RTTcpReadNB                                    RT_MANGLER(RTTcpReadNB)
+# define RTTcpSelectOne                                 RT_MANGLER(RTTcpSelectOne)
+# define RTTcpSelectOneEx                               RT_MANGLER(RTTcpSelectOneEx)
+# define RTTcpServerCreate                              RT_MANGLER(RTTcpServerCreate)
+# define RTTcpServerCreateEx                            RT_MANGLER(RTTcpServerCreateEx)
+# define RTTcpServerDestroy                             RT_MANGLER(RTTcpServerDestroy)
+# define RTTcpServerDisconnectClient                    RT_MANGLER(RTTcpServerDisconnectClient)
+# define RTTcpServerDisconnectClient2                   RT_MANGLER(RTTcpServerDisconnectClient2)
+# define RTTcpServerListen                              RT_MANGLER(RTTcpServerListen)
+# define RTTcpServerListen2                             RT_MANGLER(RTTcpServerListen2)
+# define RTTcpServerShutdown                            RT_MANGLER(RTTcpServerShutdown)
+# define RTTcpSetSendCoalescing                         RT_MANGLER(RTTcpSetSendCoalescing)
+# define RTTcpSgWrite                                   RT_MANGLER(RTTcpSgWrite)
+# define RTTcpSgWriteL                                  RT_MANGLER(RTTcpSgWriteL)
+# define RTTcpSgWriteLNB                                RT_MANGLER(RTTcpSgWriteLNB)
+# define RTTcpSgWriteLV                                 RT_MANGLER(RTTcpSgWriteLV)
+# define RTTcpSgWriteLVNB                               RT_MANGLER(RTTcpSgWriteLVNB)
+# define RTTcpSgWriteNB                                 RT_MANGLER(RTTcpSgWriteNB)
+# define RTTcpWrite                                     RT_MANGLER(RTTcpWrite)
+# define RTTcpWriteNB                                   RT_MANGLER(RTTcpWriteNB)
+# define RTTermDeregisterCallback                       RT_MANGLER(RTTermDeregisterCallback)
+# define RTTermRegisterCallback                         RT_MANGLER(RTTermRegisterCallback)
+# define RTTermRunCallbacks                             RT_MANGLER(RTTermRunCallbacks)
+# define RTTestBanner                                   RT_MANGLER(RTTestBanner)
+# define RTTestChangeName                               RT_MANGLER(RTTestChangeName)
+# define RTTestCreate                                   RT_MANGLER(RTTestCreate)
+# define RTTestCreateChild                              RT_MANGLER(RTTestCreateChild)
+# define RTTestCreateEx                                 RT_MANGLER(RTTestCreateEx)
+# define RTTestDestroy                                  RT_MANGLER(RTTestDestroy)
+# define RTTestDisableAssertions                        RT_MANGLER(RTTestDisableAssertions)
+# define RTTestErrorCount                               RT_MANGLER(RTTestErrorCount)
+# define RTTestErrorInc                                 RT_MANGLER(RTTestErrorInc)
+# define RTTestFailed                                   RT_MANGLER(RTTestFailed)
+# define RTTestFailedV                                  RT_MANGLER(RTTestFailedV)
+# define RTTestFailureDetails                           RT_MANGLER(RTTestFailureDetails)
+# define RTTestFailureDetailsV                          RT_MANGLER(RTTestFailureDetailsV)
+# define RTTestGuardedAlloc                             RT_MANGLER(RTTestGuardedAlloc)
+# define RTTestGuardedAllocHead                         RT_MANGLER(RTTestGuardedAllocHead)
+# define RTTestGuardedAllocTail                         RT_MANGLER(RTTestGuardedAllocTail)
+# define RTTestGuardedFree                              RT_MANGLER(RTTestGuardedFree)
+# define RTTestIDisableAssertions                       RT_MANGLER(RTTestIDisableAssertions)
+# define RTTestIErrorCount                              RT_MANGLER(RTTestIErrorCount)
+# define RTTestIErrorInc                                RT_MANGLER(RTTestIErrorInc)
+# define RTTestIFailed                                  RT_MANGLER(RTTestIFailed)
+# define RTTestIFailedRc                                RT_MANGLER(RTTestIFailedRc)
+# define RTTestIFailedRcV                               RT_MANGLER(RTTestIFailedRcV)
+# define RTTestIFailedV                                 RT_MANGLER(RTTestIFailedV)
+# define RTTestIFailureDetails                          RT_MANGLER(RTTestIFailureDetails)
+# define RTTestIFailureDetailsV                         RT_MANGLER(RTTestIFailureDetailsV)
+# define RTTestInitAndCreate                            RT_MANGLER(RTTestInitAndCreate)
+# define RTTestInitExAndCreate                          RT_MANGLER(RTTestInitExAndCreate)
+# define RTTestIPassed                                  RT_MANGLER(RTTestIPassed)
+# define RTTestIPassedV                                 RT_MANGLER(RTTestIPassedV)
+# define RTTestIPrintf                                  RT_MANGLER(RTTestIPrintf)
+# define RTTestIPrintfV                                 RT_MANGLER(RTTestIPrintfV)
+# define RTTestIRestoreAssertions                       RT_MANGLER(RTTestIRestoreAssertions)
+# define RTTestISub                                     RT_MANGLER(RTTestISub)
+# define RTTestISubDone                                 RT_MANGLER(RTTestISubDone)
+# define RTTestISubF                                    RT_MANGLER(RTTestISubF)
+# define RTTestISubV                                    RT_MANGLER(RTTestISubV)
+# define RTTestIValue                                   RT_MANGLER(RTTestIValue)
+# define RTTestIValueF                                  RT_MANGLER(RTTestIValueF)
+# define RTTestIValueV                                  RT_MANGLER(RTTestIValueV)
+# define RTTestPassed                                   RT_MANGLER(RTTestPassed)
+# define RTTestPassedV                                  RT_MANGLER(RTTestPassedV)
+# define RTTestPrintf                                   RT_MANGLER(RTTestPrintf)
+# define RTTestPrintfNl                                 RT_MANGLER(RTTestPrintfNl)
+# define RTTestPrintfNlV                                RT_MANGLER(RTTestPrintfNlV)
+# define RTTestPrintfV                                  RT_MANGLER(RTTestPrintfV)
+# define RTTestRestoreAssertions                        RT_MANGLER(RTTestRestoreAssertions)
+# define RTTestSetDefault                               RT_MANGLER(RTTestSetDefault)
+# define RTTestSkipAndDestroy                           RT_MANGLER(RTTestSkipAndDestroy)
+# define RTTestSkipAndDestroyV                          RT_MANGLER(RTTestSkipAndDestroyV)
+# define RTTestSkipped                                  RT_MANGLER(RTTestSkipped)
+# define RTTestSkippedV                                 RT_MANGLER(RTTestSkippedV)
+# define RTTestSub                                      RT_MANGLER(RTTestSub)
+# define RTTestSubDone                                  RT_MANGLER(RTTestSubDone)
+# define RTTestSubErrorCount                            RT_MANGLER(RTTestSubErrorCount)
+# define RTTestSubF                                     RT_MANGLER(RTTestSubF)
+# define RTTestSubV                                     RT_MANGLER(RTTestSubV)
+# define RTTestSummaryAndDestroy                        RT_MANGLER(RTTestSummaryAndDestroy)
+# define RTTestValue                                    RT_MANGLER(RTTestValue)
+# define RTTestValueF                                   RT_MANGLER(RTTestValueF)
+# define RTTestValueV                                   RT_MANGLER(RTTestValueV)
+# define RTThreadAdopt                                  RT_MANGLER(RTThreadAdopt)
+# define RTThreadBlocking                               RT_MANGLER(RTThreadBlocking)
+# define RTThreadCreate                                 RT_MANGLER(RTThreadCreate)
+# define RTThreadCreateF                                RT_MANGLER(RTThreadCreateF)
+# define RTThreadCreateV                                RT_MANGLER(RTThreadCreateV)
+# define RTThreadCtxHookIsEnabled                       RT_MANGLER(RTThreadCtxHookIsEnabled)    /* r0drv */
+# define RTThreadCtxHookCreate                          RT_MANGLER(RTThreadCtxHookCreate)       /* r0drv */
+# define RTThreadCtxHookDestroy                         RT_MANGLER(RTThreadCtxHookDestroy)      /* r0drv */
+# define RTThreadCtxHookDisable                         RT_MANGLER(RTThreadCtxHookDisable)      /* r0drv */
+# define RTThreadCtxHookEnable                          RT_MANGLER(RTThreadCtxHookEnable)       /* r0drv */
+# define RTThreadFromNative                             RT_MANGLER(RTThreadFromNative)
+# define RTThreadGetAffinity                            RT_MANGLER(RTThreadGetAffinity)
+# define RTThreadGetExecutionTimeMilli                  RT_MANGLER(RTThreadGetExecutionTimeMilli)
+# define RTThreadGetName                                RT_MANGLER(RTThreadGetName)
+# define RTThreadGetNative                              RT_MANGLER(RTThreadGetNative)
+# define RTThreadGetNativeState                         RT_MANGLER(RTThreadGetNativeState)
+# define RTThreadGetReallySleeping                      RT_MANGLER(RTThreadGetReallySleeping)
+# define RTThreadGetState                               RT_MANGLER(RTThreadGetState)
+# define RTThreadGetType                                RT_MANGLER(RTThreadGetType)
+# define RTThreadIsInInterrupt                          RT_MANGLER(RTThreadIsInInterrupt)      /* r0drv */
+# define RTThreadIsInitialized                          RT_MANGLER(RTThreadIsInitialized)
+# define RTThreadIsMain                                 RT_MANGLER(RTThreadIsMain)
+# define RTThreadIsSelfAlive                            RT_MANGLER(RTThreadIsSelfAlive)
+# define RTThreadIsSelfKnown                            RT_MANGLER(RTThreadIsSelfKnown)
+# define RTThreadNativeSelf                             RT_MANGLER(RTThreadNativeSelf)
+# define RTThreadPoke                                   RT_MANGLER(RTThreadPoke) /* not-win not-os2 */
+# define RTThreadPreemptDisable                         RT_MANGLER(RTThreadPreemptDisable)     /* r0drv */
+# define RTThreadPreemptIsEnabled                       RT_MANGLER(RTThreadPreemptIsEnabled)   /* r0drv */
+# define RTThreadPreemptIsPending                       RT_MANGLER(RTThreadPreemptIsPending)   /* r0drv */
+# define RTThreadPreemptIsPendingTrusty                 RT_MANGLER(RTThreadPreemptIsPendingTrusty) /* r0drv */
+# define RTThreadPreemptIsPossible                      RT_MANGLER(RTThreadPreemptIsPossible)  /* r0drv */
+# define RTThreadPreemptRestore                         RT_MANGLER(RTThreadPreemptRestore)     /* r0drv */
+# define RTThreadSelf                                   RT_MANGLER(RTThreadSelf)
+# define RTThreadSelfAutoAdopt                          RT_MANGLER(RTThreadSelfAutoAdopt)
+# define RTThreadSelfName                               RT_MANGLER(RTThreadSelfName)
+# define RTThreadSetAffinity                            RT_MANGLER(RTThreadSetAffinity)
+# define RTThreadSetAffinityToCpu                       RT_MANGLER(RTThreadSetAffinityToCpu)
+# define RTThreadSetName                                RT_MANGLER(RTThreadSetName)
+# define RTThreadSetType                                RT_MANGLER(RTThreadSetType)
+# define RTThreadSleep                                  RT_MANGLER(RTThreadSleep)
+# define RTThreadSleepNoLog                             RT_MANGLER(RTThreadSleepNoLog)
+# define RTThreadStateName                              RT_MANGLER(RTThreadStateName)
+# define RTThreadUnblocked                              RT_MANGLER(RTThreadUnblocked)
+# define RTThreadUserReset                              RT_MANGLER(RTThreadUserReset)
+# define RTThreadUserSignal                             RT_MANGLER(RTThreadUserSignal)
+# define RTThreadUserWait                               RT_MANGLER(RTThreadUserWait)
+# define RTThreadUserWaitNoResume                       RT_MANGLER(RTThreadUserWaitNoResume)
+# define RTThreadWait                                   RT_MANGLER(RTThreadWait)
+# define RTThreadWaitNoResume                           RT_MANGLER(RTThreadWaitNoResume)
+# define RTThreadYield                                  RT_MANGLER(RTThreadYield)
+# define RTTimeDbgBad                                   RT_MANGLER(RTTimeDbgBad)
+# define RTTimeDbgExpired                               RT_MANGLER(RTTimeDbgExpired)
+# define RTTimeDbgRaces                                 RT_MANGLER(RTTimeDbgRaces)
+# define RTTimeDbgSteps                                 RT_MANGLER(RTTimeDbgSteps)
+# define RTTimeExplode                                  RT_MANGLER(RTTimeExplode)
+# define RTTimeImplode                                  RT_MANGLER(RTTimeImplode)
+# define RTTimeIsLeapYear                               RT_MANGLER(RTTimeIsLeapYear)
+# define RTTimeLocalDeltaNano                           RT_MANGLER(RTTimeLocalDeltaNano)
+# define RTTimeLocalExplode                             RT_MANGLER(RTTimeLocalExplode)
+# define RTTimeLocalNow                                 RT_MANGLER(RTTimeLocalNow)
+# define RTTimeMilliTS                                  RT_MANGLER(RTTimeMilliTS)
+# define RTTimeNanoTS                                   RT_MANGLER(RTTimeNanoTS)
+# define RTTimeNanoTSLegacyAsync                                RT_MANGLER(RTTimeNanoTSLegacyAsync)
+# define RTTimeNanoTSLegacyAsync_EndProc                        RT_MANGLER(RTTimeNanoTSLegacyAsync_EndProc)
+# define RTTimeNanoTSLegacyAsyncUseApicId                       RT_MANGLER(RTTimeNanoTSLegacyAsyncUseApicId)
+# define RTTimeNanoTSLegacyAsyncUseApicId_EndProc               RT_MANGLER(RTTimeNanoTSLegacyAsyncUseApicId_EndProc)
+# define RTTimeNanoTSLegacyAsyncUseRdtscp                       RT_MANGLER(RTTimeNanoTSLegacyAsyncUseRdtscp)
+# define RTTimeNanoTSLegacyAsyncUseRdtscp_EndProc               RT_MANGLER(RTTimeNanoTSLegacyAsyncUseRdtscp_EndProc)
+# define RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl           RT_MANGLER(RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl)
+# define RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl_EndProc   RT_MANGLER(RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl_EndProc)
+# define RTTimeNanoTSLegacyAsyncUseIdtrLim                      RT_MANGLER(RTTimeNanoTSLegacyAsyncUseIdtrLim)
+# define RTTimeNanoTSLegacyAsyncUseIdtrLim_EndProc              RT_MANGLER(RTTimeNanoTSLegacyAsyncUseIdtrLim_EndProc)
+# define RTTimeNanoTSLegacySyncInvarNoDelta                     RT_MANGLER(RTTimeNanoTSLegacySyncInvarNoDelta)
+# define RTTimeNanoTSLegacySyncInvarNoDelta_EndProc             RT_MANGLER(RTTimeNanoTSLegacySyncInvarNoDelta_EndProc)
+# define RTTimeNanoTSLegacySyncInvarWithDelta                   RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDelta)
+# define RTTimeNanoTSLegacySyncInvarWithDelta_EndProc           RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDelta_EndProc)
+# define RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId          RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId)
+# define RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId_EndProc  RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId_EndProc)
+# define RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp          RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp)
+# define RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp_EndProc  RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp_EndProc)
+# define RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim         RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim)
+# define RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim_EndProc RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim_EndProc)
+# define RTTimeNanoTSLFenceAsync                                RT_MANGLER(RTTimeNanoTSLFenceAsync)
+# define RTTimeNanoTSLFenceAsync_EndProc                        RT_MANGLER(RTTimeNanoTSLFenceAsync_EndProc)
+# define RTTimeNanoTSLFenceAsyncUseApicId                       RT_MANGLER(RTTimeNanoTSLFenceAsyncUseApicId)
+# define RTTimeNanoTSLFenceAsyncUseApicId_EndProc               RT_MANGLER(RTTimeNanoTSLFenceAsyncUseApicId_EndProc)
+# define RTTimeNanoTSLFenceAsyncUseRdtscp                       RT_MANGLER(RTTimeNanoTSLFenceAsyncUseRdtscp)
+# define RTTimeNanoTSLFenceAsyncUseRdtscp_EndProc               RT_MANGLER(RTTimeNanoTSLFenceAsyncUseRdtscp_EndProc)
+# define RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl           RT_MANGLER(RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl)
+# define RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl_EndProc   RT_MANGLER(RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl_EndProc)
+# define RTTimeNanoTSLFenceAsyncUseIdtrLim                      RT_MANGLER(RTTimeNanoTSLFenceAsyncUseIdtrLim)
+# define RTTimeNanoTSLFenceAsyncUseIdtrLim_EndProc              RT_MANGLER(RTTimeNanoTSLFenceAsyncUseIdtrLim_EndProc)
+# define RTTimeNanoTSLFenceSyncInvarNoDelta                     RT_MANGLER(RTTimeNanoTSLFenceSyncInvarNoDelta)
+# define RTTimeNanoTSLFenceSyncInvarNoDelta_EndProc             RT_MANGLER(RTTimeNanoTSLFenceSyncInvarNoDelta_EndProc)
+# define RTTimeNanoTSLFenceSyncInvarWithDelta                   RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDelta)
+# define RTTimeNanoTSLFenceSyncInvarWithDelta_EndProc           RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDelta_EndProc)
+# define RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId          RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId)
+# define RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId_EndProc  RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId_EndProc)
+# define RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp          RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp)
+# define RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp_EndProc  RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp_EndProc)
+# define RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim         RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim)
+# define RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim_EndProc RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim_EndProc)
+# define RTTimeNormalize                                RT_MANGLER(RTTimeNormalize)
+# define RTTimeNow                                      RT_MANGLER(RTTimeNow)
+# define RTTimeProgramMicroTS                           RT_MANGLER(RTTimeProgramMicroTS)
+# define RTTimeProgramMilliTS                           RT_MANGLER(RTTimeProgramMilliTS)
+# define RTTimeProgramNanoTS                            RT_MANGLER(RTTimeProgramNanoTS)
+# define RTTimeProgramSecTS                             RT_MANGLER(RTTimeProgramSecTS)
+# define RTTimeProgramStartNanoTS                       RT_MANGLER(RTTimeProgramStartNanoTS)
+# define RTTimerCanDoHighResolution                     RT_MANGLER(RTTimerCanDoHighResolution)
+# define RTTimerChangeInterval                          RT_MANGLER(RTTimerChangeInterval)
+# define RTTimerCreate                                  RT_MANGLER(RTTimerCreate)
+# define RTTimerCreateEx                                RT_MANGLER(RTTimerCreateEx)
+# define RTTimerDestroy                                 RT_MANGLER(RTTimerDestroy)
+# define RTTimerGetSystemGranularity                    RT_MANGLER(RTTimerGetSystemGranularity) /* r0drv */
+# define RTTimerLRCreate                                RT_MANGLER(RTTimerLRCreate)
+# define RTTimerLRCreateEx                              RT_MANGLER(RTTimerLRCreateEx)
+# define RTTimerLRDestroy                               RT_MANGLER(RTTimerLRDestroy)
+# define RTTimerLRStart                                 RT_MANGLER(RTTimerLRStart)
+# define RTTimerLRStop                                  RT_MANGLER(RTTimerLRStop)
+# define RTTimerLRChangeInterval                        RT_MANGLER(RTTimerLRChangeInterval)
+# define RTTimerReleaseSystemGranularity                RT_MANGLER(RTTimerReleaseSystemGranularity) /* r0drv */
+# define RTTimerRequestSystemGranularity                RT_MANGLER(RTTimerRequestSystemGranularity) /* r0drv */
+# define RTTimerStart                                   RT_MANGLER(RTTimerStart)
+# define RTTimerStop                                    RT_MANGLER(RTTimerStop)
+# define RTTimeSet                                      RT_MANGLER(RTTimeSet)
+# define RTTimeSpecFromString                           RT_MANGLER(RTTimeSpecFromString)
+# define RTTimeSpecToString                             RT_MANGLER(RTTimeSpecToString)
+# define RTTimeSystemMilliTS                            RT_MANGLER(RTTimeSystemMilliTS)
+# define RTTimeSystemNanoTS                             RT_MANGLER(RTTimeSystemNanoTS)
+# define RTTimeFromString                               RT_MANGLER(RTTimeFromString)
+# define RTTimeToString                                 RT_MANGLER(RTTimeToString)
+# define RTTlsAlloc                                     RT_MANGLER(RTTlsAlloc)
+# define RTTlsAllocEx                                   RT_MANGLER(RTTlsAllocEx)
+# define RTTlsFree                                      RT_MANGLER(RTTlsFree)
+# define RTTlsGet                                       RT_MANGLER(RTTlsGet)
+# define RTTlsGetEx                                     RT_MANGLER(RTTlsGetEx)
+# define RTTlsSet                                       RT_MANGLER(RTTlsSet)
+# define RTTraceBufAddMsg                               RT_MANGLER(RTTraceBufAddMsg)
+# define RTTraceBufAddMsgEx                             RT_MANGLER(RTTraceBufAddMsgEx)
+# define RTTraceBufAddMsgF                              RT_MANGLER(RTTraceBufAddMsgF)
+# define RTTraceBufAddMsgV                              RT_MANGLER(RTTraceBufAddMsgV)
+# define RTTraceBufAddPos                               RT_MANGLER(RTTraceBufAddPos)
+# define RTTraceBufAddPosMsg                            RT_MANGLER(RTTraceBufAddPosMsg)
+# define RTTraceBufAddPosMsgEx                          RT_MANGLER(RTTraceBufAddPosMsgEx)
+# define RTTraceBufAddPosMsgF                           RT_MANGLER(RTTraceBufAddPosMsgF)
+# define RTTraceBufAddPosMsgV                           RT_MANGLER(RTTraceBufAddPosMsgV)
+# define RTTraceBufCarve                                RT_MANGLER(RTTraceBufCarve)
+# define RTTraceBufCreate                               RT_MANGLER(RTTraceBufCreate)
+# define RTTraceBufDisable                              RT_MANGLER(RTTraceBufDisable)
+# define RTTraceBufDumpToAssert                         RT_MANGLER(RTTraceBufDumpToAssert)
+# define RTTraceBufDumpToLog                            RT_MANGLER(RTTraceBufDumpToLog)
+# define RTTraceBufEnable                               RT_MANGLER(RTTraceBufEnable)
+# define RTTraceBufEnumEntries                          RT_MANGLER(RTTraceBufEnumEntries)
+# define RTTraceBufGetEntryCount                        RT_MANGLER(RTTraceBufGetEntryCount)
+# define RTTraceBufGetEntrySize                         RT_MANGLER(RTTraceBufGetEntrySize)
+# define RTTraceBufRelease                              RT_MANGLER(RTTraceBufRelease)
+# define RTTraceBufRetain                               RT_MANGLER(RTTraceBufRetain)
+# define RTTraceGetDefaultBuf                           RT_MANGLER(RTTraceGetDefaultBuf)
+# define RTTraceSetDefaultBuf                           RT_MANGLER(RTTraceSetDefaultBuf)
+# define RTUdpCreateClientSocket                        RT_MANGLER(RTUdpCreateClientSocket)
+# define RTUdpRead                                      RT_MANGLER(RTUdpRead)
+# define RTUdpServerCreate                              RT_MANGLER(RTUdpServerCreate)
+# define RTUdpServerCreateEx                            RT_MANGLER(RTUdpServerCreateEx)
+# define RTUdpServerDestroy                             RT_MANGLER(RTUdpServerDestroy)
+# define RTUdpServerListen                              RT_MANGLER(RTUdpServerListen)
+# define RTUdpServerShutdown                            RT_MANGLER(RTUdpServerShutdown)
+# define RTUdpWrite                                     RT_MANGLER(RTUdpWrite)
+# define RTUniFree                                      RT_MANGLER(RTUniFree)
+# define RTUriCreate                                    RT_MANGLER(RTUriCreate)
+# define RTUriFileCreate                                RT_MANGLER(RTUriFileCreate)
+# define RTUriFileCreateEx                              RT_MANGLER(RTUriFileCreateEx)
+# define RTUriFilePath                                  RT_MANGLER(RTUriFilePath)
+# define RTUriFilePathEx                                RT_MANGLER(RTUriFilePathEx)
+# define RTUriParse                                     RT_MANGLER(RTUriParse)
+# define RTUriParsedAuthority                           RT_MANGLER(RTUriParsedAuthority)
+# define RTUriParsedAuthorityHost                       RT_MANGLER(RTUriParsedAuthorityHost)
+# define RTUriParsedAuthorityPassword                   RT_MANGLER(RTUriParsedAuthorityPassword)
+# define RTUriParsedAuthorityPort                       RT_MANGLER(RTUriParsedAuthorityPort)
+# define RTUriParsedAuthorityUsername                   RT_MANGLER(RTUriParsedAuthorityUsername)
+# define RTUriParsedFragment                            RT_MANGLER(RTUriParsedFragment)
+# define RTUriParsedPath                                RT_MANGLER(RTUriParsedPath)
+# define RTUriParsedScheme                              RT_MANGLER(RTUriParsedScheme)
+# define RTUriParsedQuery                               RT_MANGLER(RTUriParsedQuery)
+# define RTUriIsSchemeMatch                             RT_MANGLER(RTUriIsSchemeMatch)
+# define RTUtf16AllocTag                                RT_MANGLER(RTUtf16AllocTag)
+# define RTUtf16ReallocTag                              RT_MANGLER(RTUtf16ReallocTag)
+# define RTUtf16CalcLatin1Len                           RT_MANGLER(RTUtf16CalcLatin1Len)
+# define RTUtf16CalcLatin1LenEx                         RT_MANGLER(RTUtf16CalcLatin1LenEx)
+# define RTUtf16CalcUtf8Len                             RT_MANGLER(RTUtf16CalcUtf8Len)
+# define RTUtf16CalcUtf8LenEx                           RT_MANGLER(RTUtf16CalcUtf8LenEx)
+# define RTUtf16Cmp                                     RT_MANGLER(RTUtf16Cmp)
+# define RTUtf16CmpAscii                                RT_MANGLER(RTUtf16CmpAscii)
+# define RTUtf16CmpUtf8                                 RT_MANGLER(RTUtf16CmpUtf8)
+# define RTUtf16DupExTag                                RT_MANGLER(RTUtf16DupExTag)
+# define RTUtf16DupTag                                  RT_MANGLER(RTUtf16DupTag)
+# define RTUtf16Free                                    RT_MANGLER(RTUtf16Free)
+# define RTUtf16GetCpExInternal                         RT_MANGLER(RTUtf16GetCpExInternal)
+# define RTUtf16GetCpInternal                           RT_MANGLER(RTUtf16GetCpInternal)
+# define RTUtf16ICmp                                    RT_MANGLER(RTUtf16ICmp)
+# define RTUtf16ICmpUtf8                                RT_MANGLER(RTUtf16ICmpUtf8)
+# define RTUtf16IsValidEncoding                         RT_MANGLER(RTUtf16IsValidEncoding)
+# define RTUtf16Len                                     RT_MANGLER(RTUtf16Len)
+# define RTUtf16LocaleICmp                              RT_MANGLER(RTUtf16LocaleICmp)
+# define RTUtf16PutCpInternal                           RT_MANGLER(RTUtf16PutCpInternal)
+# define RTUtf16ToLatin1ExTag                           RT_MANGLER(RTUtf16ToLatin1ExTag)
+# define RTUtf16ToLatin1Tag                             RT_MANGLER(RTUtf16ToLatin1Tag)
+# define RTUtf16ToLower                                 RT_MANGLER(RTUtf16ToLower)
+# define RTUtf16ToUpper                                 RT_MANGLER(RTUtf16ToUpper)
+# define RTUtf16PurgeComplementSet                      RT_MANGLER(RTUtf16PurgeComplementSet)
+# define RTUtf16ToUtf8ExTag                             RT_MANGLER(RTUtf16ToUtf8ExTag)
+# define RTUtf16ToUtf8Tag                               RT_MANGLER(RTUtf16ToUtf8Tag)
+# define RTUtf16ValidateEncoding                        RT_MANGLER(RTUtf16ValidateEncoding)
+# define RTUtf16ValidateEncodingEx                      RT_MANGLER(RTUtf16ValidateEncodingEx)
+# define RTUuidClear                                    RT_MANGLER(RTUuidClear)
+# define RTUuidCompare                                  RT_MANGLER(RTUuidCompare)
+# define RTUuidCompare2Strs                             RT_MANGLER(RTUuidCompare2Strs)
+# define RTUuidCompareStr                               RT_MANGLER(RTUuidCompareStr)
+# define RTUuidCreate                                   RT_MANGLER(RTUuidCreate)
+# define RTUuidFromStr                                  RT_MANGLER(RTUuidFromStr)
+# define RTUuidFromUtf16                                RT_MANGLER(RTUuidFromUtf16)
+# define RTUuidIsNull                                   RT_MANGLER(RTUuidIsNull)
+# define RTUuidToStr                                    RT_MANGLER(RTUuidToStr)
+# define RTUuidToUtf16                                  RT_MANGLER(RTUuidToUtf16)
+# define RTVfsChainElementDeregisterProvider            RT_MANGLER(RTVfsChainElementDeregisterProvider)
+# define RTVfsChainElementRegisterProvider              RT_MANGLER(RTVfsChainElementRegisterProvider)
+# define RTVfsChainIsSpec                               RT_MANGLER(RTVfsChainIsSpec)
+# define RTVfsChainOpenFile                             RT_MANGLER(RTVfsChainOpenFile)
+# define RTVfsChainOpenIoStream                         RT_MANGLER(RTVfsChainOpenIoStream)
+# define RTVfsChainSpecFree                             RT_MANGLER(RTVfsChainSpecFree)
+# define RTVfsChainSpecParse                            RT_MANGLER(RTVfsChainSpecParse)
+# define RTVfsDirRelease                                RT_MANGLER(RTVfsDirRelease)
+# define RTVfsDirRetain                                 RT_MANGLER(RTVfsDirRetain)
+# define RTVfsFileFlush                                 RT_MANGLER(RTVfsFileFlush)
+# define RTVfsFileFromBuffer                            RT_MANGLER(RTVfsFileFromBuffer)
+# define RTVfsFileFromRTFile                            RT_MANGLER(RTVfsFileFromRTFile)
+# define RTVfsFileGetSize                               RT_MANGLER(RTVfsFileGetSize)
+# define RTVfsFileOpen                                  RT_MANGLER(RTVfsFileOpen)
+# define RTVfsFileOpenNormal                            RT_MANGLER(RTVfsFileOpenNormal)
+# define RTVfsFilePoll                                  RT_MANGLER(RTVfsFilePoll)
+# define RTVfsFileQueryInfo                             RT_MANGLER(RTVfsFileQueryInfo)
+# define RTVfsFileRead                                  RT_MANGLER(RTVfsFileRead)
+# define RTVfsFileReadAt                                RT_MANGLER(RTVfsFileReadAt)
+# define RTVfsFileRelease                               RT_MANGLER(RTVfsFileRelease)
+# define RTVfsFileRetain                                RT_MANGLER(RTVfsFileRetain)
+# define RTVfsFileSeek                                  RT_MANGLER(RTVfsFileSeek)
+# define RTVfsFileTell                                  RT_MANGLER(RTVfsFileTell)
+# define RTVfsFileToIoStream                            RT_MANGLER(RTVfsFileToIoStream)
+# define RTVfsFileWrite                                 RT_MANGLER(RTVfsFileWrite)
+# define RTVfsFileWriteAt                               RT_MANGLER(RTVfsFileWriteAt)
+# define RTVfsFsStrmNext                                RT_MANGLER(RTVfsFsStrmNext)
+# define RTVfsFsStrmQueryInfo                           RT_MANGLER(RTVfsFsStrmQueryInfo)
+# define RTVfsFsStrmRelease                             RT_MANGLER(RTVfsFsStrmRelease)
+# define RTVfsFsStrmRetain                              RT_MANGLER(RTVfsFsStrmRetain)
+# define RTVfsIoStreamToPrivate                         RT_MANGLER(RTVfsIoStreamToPrivate)
+# define RTVfsIoStrmFlush                               RT_MANGLER(RTVfsIoStrmFlush)
+# define RTVfsIoStrmFromBuffer                          RT_MANGLER(RTVfsIoStrmFromBuffer)
+# define RTVfsIoStrmFromRTFile                          RT_MANGLER(RTVfsIoStrmFromRTFile)
+# define RTVfsIoStrmFromRTPipe                          RT_MANGLER(RTVfsIoStrmFromRTPipe)
+# define RTVfsIoStrmFromStdHandle                       RT_MANGLER(RTVfsIoStrmFromStdHandle)
+# define RTVfsIoStrmIsAtEnd                             RT_MANGLER(RTVfsIoStrmIsAtEnd)
+# define RTVfsIoStrmOpenNormal                          RT_MANGLER(RTVfsIoStrmOpenNormal)
+# define RTVfsIoStrmPoll                                RT_MANGLER(RTVfsIoStrmPoll)
+# define RTVfsIoStrmQueryInfo                           RT_MANGLER(RTVfsIoStrmQueryInfo)
+# define RTVfsIoStrmRead                                RT_MANGLER(RTVfsIoStrmRead)
+# define RTVfsIoStrmReadAt                              RT_MANGLER(RTVfsIoStrmReadAt)
+# define RTVfsIoStrmReadAll                             RT_MANGLER(RTVfsIoStrmReadAll)
+# define RTVfsIoStrmReadAllFree                         RT_MANGLER(RTVfsIoStrmReadAllFree)
+# define RTVfsIoStrmRelease                             RT_MANGLER(RTVfsIoStrmRelease)
+# define RTVfsIoStrmRetain                              RT_MANGLER(RTVfsIoStrmRetain)
+# define RTVfsIoStrmSgRead                              RT_MANGLER(RTVfsIoStrmSgRead)
+# define RTVfsIoStrmSgWrite                             RT_MANGLER(RTVfsIoStrmSgWrite)
+# define RTVfsIoStrmSkip                                RT_MANGLER(RTVfsIoStrmSkip)
+# define RTVfsIoStrmTell                                RT_MANGLER(RTVfsIoStrmTell)
+# define RTVfsIoStrmToFile                              RT_MANGLER(RTVfsIoStrmToFile)
+# define RTVfsIoStrmValidateUtf8Encoding                RT_MANGLER(RTVfsIoStrmValidateUtf8Encoding)
+# define RTVfsIoStrmWrite                               RT_MANGLER(RTVfsIoStrmWrite)
+# define RTVfsIoStrmWriteAt                             RT_MANGLER(RTVfsIoStrmWriteAt)
+# define RTVfsIoStrmZeroFill                            RT_MANGLER(RTVfsIoStrmZeroFill)
+# define RTVfsIsRangeInUse                              RT_MANGLER(RTVfsIsRangeInUse)
+# define RTVfsLockAcquireReadSlow                       RT_MANGLER(RTVfsLockAcquireReadSlow)
+# define RTVfsLockAcquireWriteSlow                      RT_MANGLER(RTVfsLockAcquireWriteSlow)
+# define RTVfsLockRelease                               RT_MANGLER(RTVfsLockRelease)
+# define RTVfsLockReleaseReadSlow                       RT_MANGLER(RTVfsLockReleaseReadSlow)
+# define RTVfsLockReleaseWriteSlow                      RT_MANGLER(RTVfsLockReleaseWriteSlow)
+# define RTVfsLockRetain                                RT_MANGLER(RTVfsLockRetain)
+# define RTVfsMemFileCreate                             RT_MANGLER(RTVfsMemFileCreate)
+# define RTVfsMemorizeIoStreamAsFile                    RT_MANGLER(RTVfsMemorizeIoStreamAsFile)
+# define RTVfsNew                                       RT_MANGLER(RTVfsNew)
+# define RTVfsNewBaseObj                                RT_MANGLER(RTVfsNewBaseObj)
+# define RTVfsNewFile                                   RT_MANGLER(RTVfsNewFile)
+# define RTVfsNewFsStream                               RT_MANGLER(RTVfsNewFsStream)
+# define RTVfsNewIoStream                               RT_MANGLER(RTVfsNewIoStream)
+# define RTVfsNewSymlink                                RT_MANGLER(RTVfsNewSymlink)
+# define RTVfsObjFromDir                                RT_MANGLER(RTVfsObjFromDir)
+# define RTVfsObjFromFile                               RT_MANGLER(RTVfsObjFromFile)
+# define RTVfsObjFromFsStream                           RT_MANGLER(RTVfsObjFromFsStream)
+# define RTVfsObjFromIoStream                           RT_MANGLER(RTVfsObjFromIoStream)
+# define RTVfsObjFromSymlink                            RT_MANGLER(RTVfsObjFromSymlink)
+# define RTVfsObjFromVfs                                RT_MANGLER(RTVfsObjFromVfs)
+# define RTVfsObjQueryInfo                              RT_MANGLER(RTVfsObjQueryInfo)
+# define RTVfsObjRelease                                RT_MANGLER(RTVfsObjRelease)
+# define RTVfsObjRetain                                 RT_MANGLER(RTVfsObjRetain)
+# define RTVfsObjToDir                                  RT_MANGLER(RTVfsObjToDir)
+# define RTVfsObjToFile                                 RT_MANGLER(RTVfsObjToFile)
+# define RTVfsObjToFsStream                             RT_MANGLER(RTVfsObjToFsStream)
+# define RTVfsObjToIoStream                             RT_MANGLER(RTVfsObjToIoStream)
+# define RTVfsObjToSymlink                              RT_MANGLER(RTVfsObjToSymlink)
+# define RTVfsObjToVfs                                  RT_MANGLER(RTVfsObjToVfs)
+# define RTVfsParsePath                                 RT_MANGLER(RTVfsParsePath)
+# define RTVfsParsePathA                                RT_MANGLER(RTVfsParsePathA)
+# define RTVfsParsePathAppend                           RT_MANGLER(RTVfsParsePathAppend)
+# define RTVfsParsePathFree                             RT_MANGLER(RTVfsParsePathFree)
+# define RTVfsRelease                                   RT_MANGLER(RTVfsRelease)
+# define RTVfsRetain                                    RT_MANGLER(RTVfsRetain)
+# define RTVfsSymlinkQueryInfo                          RT_MANGLER(RTVfsSymlinkQueryInfo)
+# define RTVfsSymlinkRead                               RT_MANGLER(RTVfsSymlinkRead)
+# define RTVfsSymlinkRelease                            RT_MANGLER(RTVfsSymlinkRelease)
+# define RTVfsSymlinkRetain                             RT_MANGLER(RTVfsSymlinkRetain)
+# define RTVfsSymlinkSetMode                            RT_MANGLER(RTVfsSymlinkSetMode)
+# define RTVfsSymlinkSetOwner                           RT_MANGLER(RTVfsSymlinkSetOwner)
+# define RTVfsSymlinkSetTimes                           RT_MANGLER(RTVfsSymlinkSetTimes)
+# define RTVfsUtilDummyPollOne                          RT_MANGLER(RTVfsUtilDummyPollOne)
+# define RTVfsUtilPumpIoStreams                         RT_MANGLER(RTVfsUtilPumpIoStreams)
+# define RTVfsCreateReadAheadForFile                    RT_MANGLER(RTVfsCreateReadAheadForFile)
+# define RTVfsCreateReadAheadForIoStream                RT_MANGLER(RTVfsCreateReadAheadForIoStream)
+# define RTZipBlockCompress                             RT_MANGLER(RTZipBlockCompress)
+# define RTZipBlockDecompress                           RT_MANGLER(RTZipBlockDecompress)
+# define RTZipCompCreate                                RT_MANGLER(RTZipCompCreate)
+# define RTZipCompDestroy                               RT_MANGLER(RTZipCompDestroy)
+# define RTZipCompFinish                                RT_MANGLER(RTZipCompFinish)
+# define RTZipCompress                                  RT_MANGLER(RTZipCompress)
+# define RTZipDecompCreate                              RT_MANGLER(RTZipDecompCreate)
+# define RTZipDecompDestroy                             RT_MANGLER(RTZipDecompDestroy)
+# define RTZipDecompress                                RT_MANGLER(RTZipDecompress)
+# define RTZipGzipCompressIoStream                      RT_MANGLER(RTZipGzipCompressIoStream)
+# define RTZipGzipDecompressIoStream                    RT_MANGLER(RTZipGzipDecompressIoStream)
+# define RTZipPkzipFsStreamFromIoStream                 RT_MANGLER(RTZipPkzipFsStreamFromIoStream)
+# define RTZipPkzipMemDecompress                        RT_MANGLER(RTZipPkzipMemDecompress)
+# define RTZipTarCmd                                    RT_MANGLER(RTZipTarCmd)
+# define RTZipUnzipCmd                                  RT_MANGLER(RTZipUnzipCmd)
+# define RTZipTarFsStreamFromIoStream                   RT_MANGLER(RTZipTarFsStreamFromIoStream)
+# define RTZipXarFsStreamFromIoStream                   RT_MANGLER(RTZipXarFsStreamFromIoStream)
+
+/* sort/merge into the above later: */
+# define RTAsn1ContentAllocZ                            RT_MANGLER(RTAsn1ContentAllocZ)
+# define RTAsn1ContentDup                               RT_MANGLER(RTAsn1ContentDup)
+# define RTAsn1ContentFree                              RT_MANGLER(RTAsn1ContentFree)
+# define RTAsn1ContentReallocZ                          RT_MANGLER(RTAsn1ContentReallocZ)
+# define RTAsn1ContextTagN_Clone                        RT_MANGLER(RTAsn1ContextTagN_Clone)
+# define RTAsn1ContextTagN_Init                         RT_MANGLER(RTAsn1ContextTagN_Init)
+# define RTAsn1Dummy_InitEx                             RT_MANGLER(RTAsn1Dummy_InitEx)
+# define RTAsn1MemAllocZ                                RT_MANGLER(RTAsn1MemAllocZ)
+# define RTAsn1MemDup                                   RT_MANGLER(RTAsn1MemDup)
+# define RTAsn1MemFree                                  RT_MANGLER(RTAsn1MemFree)
+# define RTAsn1MemFreeArray                             RT_MANGLER(RTAsn1MemFreeArray)
+# define RTAsn1MemResizeArray                           RT_MANGLER(RTAsn1MemResizeArray)
+# define RTAsn1MemInitAllocation                        RT_MANGLER(RTAsn1MemInitAllocation)
+# define RTAsn1MemInitArrayAllocation                   RT_MANGLER(RTAsn1MemInitArrayAllocation)
+# define RTAsn1SeqOfCore_Clone                          RT_MANGLER(RTAsn1SeqOfCore_Clone)
+# define RTAsn1SeqOfCore_Init                           RT_MANGLER(RTAsn1SeqOfCore_Init)
+# define RTAsn1SequenceCore_Clone                       RT_MANGLER(RTAsn1SequenceCore_Clone)
+# define RTAsn1SequenceCore_Init                        RT_MANGLER(RTAsn1SequenceCore_Init)
+# define RTAsn1SetCore_Clone                            RT_MANGLER(RTAsn1SetCore_Clone)
+# define RTAsn1SetCore_Init                             RT_MANGLER(RTAsn1SetCore_Init)
+# define RTAsn1SetOfCore_Clone                          RT_MANGLER(RTAsn1SetOfCore_Clone)
+# define RTAsn1SetOfCore_Init                           RT_MANGLER(RTAsn1SetOfCore_Init)
+# define RTAsn1VtCheckSanity                            RT_MANGLER(RTAsn1VtCheckSanity)
+# define RTAsn1VtClone                                  RT_MANGLER(RTAsn1VtClone)
+# define RTAsn1VtCompare                                RT_MANGLER(RTAsn1VtCompare)
+# define RTAsn1VtDeepEnum                               RT_MANGLER(RTAsn1VtDeepEnum)
+# define RTAsn1VtDelete                                 RT_MANGLER(RTAsn1VtDelete)
+# define RTAsn1CursorCheckEnd                           RT_MANGLER(RTAsn1CursorCheckEnd)
+# define RTAsn1CursorGetBitString                       RT_MANGLER(RTAsn1CursorGetBitString)
+# define RTAsn1CursorGetBitStringEx                     RT_MANGLER(RTAsn1CursorGetBitStringEx)
+# define RTAsn1CursorGetBmpString                       RT_MANGLER(RTAsn1CursorGetBmpString)
+# define RTAsn1CursorGetBoolean                         RT_MANGLER(RTAsn1CursorGetBoolean)
+# define RTAsn1CursorGetContextTagNCursor               RT_MANGLER(RTAsn1CursorGetContextTagNCursor)
+# define RTAsn1CursorGetCore                            RT_MANGLER(RTAsn1CursorGetCore)
+# define RTAsn1CursorGetDynType                         RT_MANGLER(RTAsn1CursorGetDynType)
+# define RTAsn1CursorGetIa5String                       RT_MANGLER(RTAsn1CursorGetIa5String)
+# define RTAsn1CursorGetInteger                         RT_MANGLER(RTAsn1CursorGetInteger)
+# define RTAsn1CursorGetNull                            RT_MANGLER(RTAsn1CursorGetNull)
+# define RTAsn1CursorGetObjId                           RT_MANGLER(RTAsn1CursorGetObjId)
+# define RTAsn1CursorGetOctetString                     RT_MANGLER(RTAsn1CursorGetOctetString)
+# define RTAsn1CursorGetSequenceCursor                  RT_MANGLER(RTAsn1CursorGetSequenceCursor)
+# define RTAsn1CursorGetSetCursor                       RT_MANGLER(RTAsn1CursorGetSetCursor)
+# define RTAsn1CursorGetString                          RT_MANGLER(RTAsn1CursorGetString)
+# define RTAsn1CursorGetTime                            RT_MANGLER(RTAsn1CursorGetTime)
+# define RTAsn1CursorGetUtf8String                      RT_MANGLER(RTAsn1CursorGetUtf8String)
+# define RTAsn1CursorInitAllocation                     RT_MANGLER(RTAsn1CursorInitAllocation)
+# define RTAsn1CursorInitArrayAllocation                RT_MANGLER(RTAsn1CursorInitArrayAllocation)
+# define RTAsn1CursorInitPrimary                        RT_MANGLER(RTAsn1CursorInitPrimary)
+# define RTAsn1CursorInitSubFromCore                    RT_MANGLER(RTAsn1CursorInitSubFromCore)
+# define RTAsn1CursorIsNextEx                           RT_MANGLER(RTAsn1CursorIsNextEx)
+# define RTAsn1CursorMatchTagClassFlagsEx               RT_MANGLER(RTAsn1CursorMatchTagClassFlagsEx)
+# define RTAsn1CursorPeek                               RT_MANGLER(RTAsn1CursorPeek)
+# define RTAsn1CursorReadHdr                            RT_MANGLER(RTAsn1CursorReadHdr)
+# define RTAsn1CursorSetInfo                            RT_MANGLER(RTAsn1CursorSetInfo)
+# define RTAsn1CursorSetInfoV                           RT_MANGLER(RTAsn1CursorSetInfoV)
+# define RTAsn1Dump                                     RT_MANGLER(RTAsn1Dump)
+# define RTAsn1QueryObjIdName                           RT_MANGLER(RTAsn1QueryObjIdName)
+# define RTAsn1EncodePrepare                            RT_MANGLER(RTAsn1EncodePrepare)
+# define RTAsn1EncodeRecalcHdrSize                      RT_MANGLER(RTAsn1EncodeRecalcHdrSize)
+# define RTAsn1EncodeToBuffer                           RT_MANGLER(RTAsn1EncodeToBuffer)
+# define RTAsn1EncodeWrite                              RT_MANGLER(RTAsn1EncodeWrite)
+# define RTAsn1EncodeWriteHeader                        RT_MANGLER(RTAsn1EncodeWriteHeader)
+# define RTAsn1BitString_CheckSanity                    RT_MANGLER(RTAsn1BitString_CheckSanity)
+# define RTAsn1BitString_Clone                          RT_MANGLER(RTAsn1BitString_Clone)
+# define RTAsn1BitString_Compare                        RT_MANGLER(RTAsn1BitString_Compare)
+# define RTAsn1BitString_Delete                         RT_MANGLER(RTAsn1BitString_Delete)
+# define RTAsn1BitString_Enum                           RT_MANGLER(RTAsn1BitString_Enum)
+# define RTAsn1BitString_GetAsUInt64                    RT_MANGLER(RTAsn1BitString_GetAsUInt64)
+# define RTAsn1BitString_Init                           RT_MANGLER(RTAsn1BitString_Init)
+# define RTAsn1SeqOfBitStrings_CheckSanity              RT_MANGLER(RTAsn1SeqOfBitStrings_CheckSanity)
+# define RTAsn1SeqOfBitStrings_Clone                    RT_MANGLER(RTAsn1SeqOfBitStrings_Clone)
+# define RTAsn1SeqOfBitStrings_Compare                  RT_MANGLER(RTAsn1SeqOfBitStrings_Compare)
+# define RTAsn1SeqOfBitStrings_Delete                   RT_MANGLER(RTAsn1SeqOfBitStrings_Delete)
+# define RTAsn1SeqOfBitStrings_Enum                     RT_MANGLER(RTAsn1SeqOfBitStrings_Enum)
+# define RTAsn1SeqOfBitStrings_Init                     RT_MANGLER(RTAsn1SeqOfBitStrings_Init)
+# define RTAsn1SetOfBitStrings_CheckSanity              RT_MANGLER(RTAsn1SetOfBitStrings_CheckSanity)
+# define RTAsn1SetOfBitStrings_Clone                    RT_MANGLER(RTAsn1SetOfBitStrings_Clone)
+# define RTAsn1SetOfBitStrings_Compare                  RT_MANGLER(RTAsn1SetOfBitStrings_Compare)
+# define RTAsn1SetOfBitStrings_Delete                   RT_MANGLER(RTAsn1SetOfBitStrings_Delete)
+# define RTAsn1SetOfBitStrings_Enum                     RT_MANGLER(RTAsn1SetOfBitStrings_Enum)
+# define RTAsn1SetOfBitStrings_Init                     RT_MANGLER(RTAsn1SetOfBitStrings_Init)
+# define RTAsn1BitString_DecodeAsn1                     RT_MANGLER(RTAsn1BitString_DecodeAsn1)
+# define RTAsn1BitString_DecodeAsn1Ex                   RT_MANGLER(RTAsn1BitString_DecodeAsn1Ex)
+# define RTAsn1SeqOfBitStrings_DecodeAsn1               RT_MANGLER(RTAsn1SeqOfBitStrings_DecodeAsn1)
+# define RTAsn1SetOfBitStrings_DecodeAsn1               RT_MANGLER(RTAsn1SetOfBitStrings_DecodeAsn1)
+# define RTAsn1Boolean_CheckSanity                      RT_MANGLER(RTAsn1Boolean_CheckSanity)
+# define RTAsn1Boolean_Clone                            RT_MANGLER(RTAsn1Boolean_Clone)
+# define RTAsn1Boolean_Compare                          RT_MANGLER(RTAsn1Boolean_Compare)
+# define RTAsn1Boolean_Delete                           RT_MANGLER(RTAsn1Boolean_Delete)
+# define RTAsn1Boolean_Enum                             RT_MANGLER(RTAsn1Boolean_Enum)
+# define RTAsn1Boolean_Init                             RT_MANGLER(RTAsn1Boolean_Init)
+# define RTAsn1Boolean_InitDefault                      RT_MANGLER(RTAsn1Boolean_InitDefault)
+# define RTAsn1Boolean_Set                              RT_MANGLER(RTAsn1Boolean_Set)
+# define RTAsn1SeqOfBooleans_CheckSanity                RT_MANGLER(RTAsn1SeqOfBooleans_CheckSanity)
+# define RTAsn1SeqOfBooleans_Clone                      RT_MANGLER(RTAsn1SeqOfBooleans_Clone)
+# define RTAsn1SeqOfBooleans_Compare                    RT_MANGLER(RTAsn1SeqOfBooleans_Compare)
+# define RTAsn1SeqOfBooleans_Delete                     RT_MANGLER(RTAsn1SeqOfBooleans_Delete)
+# define RTAsn1SeqOfBooleans_Enum                       RT_MANGLER(RTAsn1SeqOfBooleans_Enum)
+# define RTAsn1SeqOfBooleans_Init                       RT_MANGLER(RTAsn1SeqOfBooleans_Init)
+# define RTAsn1SetOfBooleans_CheckSanity                RT_MANGLER(RTAsn1SetOfBooleans_CheckSanity)
+# define RTAsn1SetOfBooleans_Clone                      RT_MANGLER(RTAsn1SetOfBooleans_Clone)
+# define RTAsn1SetOfBooleans_Compare                    RT_MANGLER(RTAsn1SetOfBooleans_Compare)
+# define RTAsn1SetOfBooleans_Delete                     RT_MANGLER(RTAsn1SetOfBooleans_Delete)
+# define RTAsn1SetOfBooleans_Enum                       RT_MANGLER(RTAsn1SetOfBooleans_Enum)
+# define RTAsn1SetOfBooleans_Init                       RT_MANGLER(RTAsn1SetOfBooleans_Init)
+# define RTAsn1Boolean_DecodeAsn1                       RT_MANGLER(RTAsn1Boolean_DecodeAsn1)
+# define RTAsn1SeqOfBooleans_DecodeAsn1                 RT_MANGLER(RTAsn1SeqOfBooleans_DecodeAsn1)
+# define RTAsn1SetOfBooleans_DecodeAsn1                 RT_MANGLER(RTAsn1SetOfBooleans_DecodeAsn1)
+# define RTAsn1Core_ChangeTag                           RT_MANGLER(RTAsn1Core_ChangeTag)
+# define RTAsn1Core_CheckSanity                         RT_MANGLER(RTAsn1Core_CheckSanity)
+# define RTAsn1Core_Clone                               RT_MANGLER(RTAsn1Core_Clone)
+# define RTAsn1Core_CloneContent                        RT_MANGLER(RTAsn1Core_CloneContent)
+# define RTAsn1Core_CloneNoContent                      RT_MANGLER(RTAsn1Core_CloneNoContent)
+# define RTAsn1Core_Compare                             RT_MANGLER(RTAsn1Core_Compare)
+# define RTAsn1Core_CompareEx                           RT_MANGLER(RTAsn1Core_CompareEx)
+# define RTAsn1Core_Delete                              RT_MANGLER(RTAsn1Core_Delete)
+# define RTAsn1Core_Enum                                RT_MANGLER(RTAsn1Core_Enum)
+# define RTAsn1Core_Init                                RT_MANGLER(RTAsn1Core_Init)
+# define RTAsn1Core_InitDefault                         RT_MANGLER(RTAsn1Core_InitDefault)
+# define RTAsn1Core_InitEx                              RT_MANGLER(RTAsn1Core_InitEx)
+# define RTAsn1Core_ResetImplict                        RT_MANGLER(RTAsn1Core_ResetImplict)
+# define RTAsn1Core_SetTagAndFlags                      RT_MANGLER(RTAsn1Core_SetTagAndFlags)
+# define RTAsn1SeqOfCores_CheckSanity                   RT_MANGLER(RTAsn1SeqOfCores_CheckSanity)
+# define RTAsn1SeqOfCores_Clone                         RT_MANGLER(RTAsn1SeqOfCores_Clone)
+# define RTAsn1SeqOfCores_Compare                       RT_MANGLER(RTAsn1SeqOfCores_Compare)
+# define RTAsn1SeqOfCores_Delete                        RT_MANGLER(RTAsn1SeqOfCores_Delete)
+# define RTAsn1SeqOfCores_Enum                          RT_MANGLER(RTAsn1SeqOfCores_Enum)
+# define RTAsn1SeqOfCores_Init                          RT_MANGLER(RTAsn1SeqOfCores_Init)
+# define RTAsn1SetOfCores_CheckSanity                   RT_MANGLER(RTAsn1SetOfCores_CheckSanity)
+# define RTAsn1SetOfCores_Clone                         RT_MANGLER(RTAsn1SetOfCores_Clone)
+# define RTAsn1SetOfCores_Compare                       RT_MANGLER(RTAsn1SetOfCores_Compare)
+# define RTAsn1SetOfCores_Delete                        RT_MANGLER(RTAsn1SetOfCores_Delete)
+# define RTAsn1SetOfCores_Enum                          RT_MANGLER(RTAsn1SetOfCores_Enum)
+# define RTAsn1SetOfCores_Init                          RT_MANGLER(RTAsn1SetOfCores_Init)
+# define RTAsn1Core_DecodeAsn1                          RT_MANGLER(RTAsn1Core_DecodeAsn1)
+# define RTAsn1SeqOfCores_DecodeAsn1                    RT_MANGLER(RTAsn1SeqOfCores_DecodeAsn1)
+# define RTAsn1SetOfCores_DecodeAsn1                    RT_MANGLER(RTAsn1SetOfCores_DecodeAsn1)
+# define RTAsn1DynType_CheckSanity                      RT_MANGLER(RTAsn1DynType_CheckSanity)
+# define RTAsn1DynType_Clone                            RT_MANGLER(RTAsn1DynType_Clone)
+# define RTAsn1DynType_Compare                          RT_MANGLER(RTAsn1DynType_Compare)
+# define RTAsn1DynType_Delete                           RT_MANGLER(RTAsn1DynType_Delete)
+# define RTAsn1DynType_Enum                             RT_MANGLER(RTAsn1DynType_Enum)
+# define RTAsn1DynType_Init                             RT_MANGLER(RTAsn1DynType_Init)
+# define RTAsn1DynType_DecodeAsn1                       RT_MANGLER(RTAsn1DynType_DecodeAsn1)
+# define RTAsn1Integer_CheckSanity                      RT_MANGLER(RTAsn1Integer_CheckSanity)
+# define RTAsn1Integer_Clone                            RT_MANGLER(RTAsn1Integer_Clone)
+# define RTAsn1Integer_Compare                          RT_MANGLER(RTAsn1Integer_Compare)
+# define RTAsn1Integer_Delete                           RT_MANGLER(RTAsn1Integer_Delete)
+# define RTAsn1Integer_Enum                             RT_MANGLER(RTAsn1Integer_Enum)
+# define RTAsn1Integer_FromBigNum                       RT_MANGLER(RTAsn1Integer_FromBigNum)
+# define RTAsn1Integer_Init                             RT_MANGLER(RTAsn1Integer_Init)
+# define RTAsn1Integer_InitDefault                      RT_MANGLER(RTAsn1Integer_InitDefault)
+# define RTAsn1Integer_InitU64                          RT_MANGLER(RTAsn1Integer_InitU64)
+# define RTAsn1Integer_ToBigNum                         RT_MANGLER(RTAsn1Integer_ToBigNum)
+# define RTAsn1Integer_ToString                         RT_MANGLER(RTAsn1Integer_ToString)
+# define RTAsn1Integer_UnsignedCompare                  RT_MANGLER(RTAsn1Integer_UnsignedCompare)
+# define RTAsn1Integer_UnsignedCompareWithU32           RT_MANGLER(RTAsn1Integer_UnsignedCompareWithU32)
+# define RTAsn1Integer_UnsignedCompareWithU64           RT_MANGLER(RTAsn1Integer_UnsignedCompareWithU64)
+# define RTAsn1Integer_UnsignedLastBit                  RT_MANGLER(RTAsn1Integer_UnsignedLastBit)
+# define RTAsn1SeqOfIntegers_CheckSanity                RT_MANGLER(RTAsn1SeqOfIntegers_CheckSanity)
+# define RTAsn1SeqOfIntegers_Clone                      RT_MANGLER(RTAsn1SeqOfIntegers_Clone)
+# define RTAsn1SeqOfIntegers_Compare                    RT_MANGLER(RTAsn1SeqOfIntegers_Compare)
+# define RTAsn1SeqOfIntegers_Delete                     RT_MANGLER(RTAsn1SeqOfIntegers_Delete)
+# define RTAsn1SeqOfIntegers_Enum                       RT_MANGLER(RTAsn1SeqOfIntegers_Enum)
+# define RTAsn1SeqOfIntegers_Init                       RT_MANGLER(RTAsn1SeqOfIntegers_Init)
+# define RTAsn1SetOfIntegers_CheckSanity                RT_MANGLER(RTAsn1SetOfIntegers_CheckSanity)
+# define RTAsn1SetOfIntegers_Clone                      RT_MANGLER(RTAsn1SetOfIntegers_Clone)
+# define RTAsn1SetOfIntegers_Compare                    RT_MANGLER(RTAsn1SetOfIntegers_Compare)
+# define RTAsn1SetOfIntegers_Delete                     RT_MANGLER(RTAsn1SetOfIntegers_Delete)
+# define RTAsn1SetOfIntegers_Enum                       RT_MANGLER(RTAsn1SetOfIntegers_Enum)
+# define RTAsn1SetOfIntegers_Init                       RT_MANGLER(RTAsn1SetOfIntegers_Init)
+# define RTAsn1Integer_DecodeAsn1                       RT_MANGLER(RTAsn1Integer_DecodeAsn1)
+# define RTAsn1SeqOfIntegers_DecodeAsn1                 RT_MANGLER(RTAsn1SeqOfIntegers_DecodeAsn1)
+# define RTAsn1SetOfIntegers_DecodeAsn1                 RT_MANGLER(RTAsn1SetOfIntegers_DecodeAsn1)
+# define RTAsn1Null_CheckSanity                         RT_MANGLER(RTAsn1Null_CheckSanity)
+# define RTAsn1Null_Clone                               RT_MANGLER(RTAsn1Null_Clone)
+# define RTAsn1Null_Compare                             RT_MANGLER(RTAsn1Null_Compare)
+# define RTAsn1Null_Delete                              RT_MANGLER(RTAsn1Null_Delete)
+# define RTAsn1Null_Enum                                RT_MANGLER(RTAsn1Null_Enum)
+# define RTAsn1Null_Init                                RT_MANGLER(RTAsn1Null_Init)
+# define RTAsn1Null_DecodeAsn1                          RT_MANGLER(RTAsn1Null_DecodeAsn1)
+# define RTAsn1ObjIdCountComponents                     RT_MANGLER(RTAsn1ObjIdCountComponents)
+# define RTAsn1ObjIdGetComponentsAsUInt32               RT_MANGLER(RTAsn1ObjIdGetComponentsAsUInt32)
+# define RTAsn1ObjIdGetLastComponentsAsUInt32           RT_MANGLER(RTAsn1ObjIdGetLastComponentsAsUInt32)
+# define RTAsn1ObjId_CheckSanity                        RT_MANGLER(RTAsn1ObjId_CheckSanity)
+# define RTAsn1ObjId_Clone                              RT_MANGLER(RTAsn1ObjId_Clone)
+# define RTAsn1ObjId_Compare                            RT_MANGLER(RTAsn1ObjId_Compare)
+# define RTAsn1ObjId_CompareWithString                  RT_MANGLER(RTAsn1ObjId_CompareWithString)
+# define RTAsn1ObjId_Delete                             RT_MANGLER(RTAsn1ObjId_Delete)
+# define RTAsn1ObjId_Enum                               RT_MANGLER(RTAsn1ObjId_Enum)
+# define RTAsn1ObjId_Init                               RT_MANGLER(RTAsn1ObjId_Init)
+# define RTAsn1ObjId_InitFromString                     RT_MANGLER(RTAsn1ObjId_InitFromString)
+# define RTAsn1ObjId_StartsWith                         RT_MANGLER(RTAsn1ObjId_StartsWith)
+# define RTAsn1SeqOfObjIds_CheckSanity                  RT_MANGLER(RTAsn1SeqOfObjIds_CheckSanity)
+# define RTAsn1SeqOfObjIds_Clone                        RT_MANGLER(RTAsn1SeqOfObjIds_Clone)
+# define RTAsn1SeqOfObjIds_Compare                      RT_MANGLER(RTAsn1SeqOfObjIds_Compare)
+# define RTAsn1SeqOfObjIds_Delete                       RT_MANGLER(RTAsn1SeqOfObjIds_Delete)
+# define RTAsn1SeqOfObjIds_Enum                         RT_MANGLER(RTAsn1SeqOfObjIds_Enum)
+# define RTAsn1SeqOfObjIds_Init                         RT_MANGLER(RTAsn1SeqOfObjIds_Init)
+# define RTAsn1SetOfObjIds_CheckSanity                  RT_MANGLER(RTAsn1SetOfObjIds_CheckSanity)
+# define RTAsn1SetOfObjIds_Clone                        RT_MANGLER(RTAsn1SetOfObjIds_Clone)
+# define RTAsn1SetOfObjIds_Compare                      RT_MANGLER(RTAsn1SetOfObjIds_Compare)
+# define RTAsn1SetOfObjIds_Delete                       RT_MANGLER(RTAsn1SetOfObjIds_Delete)
+# define RTAsn1SetOfObjIds_Enum                         RT_MANGLER(RTAsn1SetOfObjIds_Enum)
+# define RTAsn1SetOfObjIds_Init                         RT_MANGLER(RTAsn1SetOfObjIds_Init)
+# define RTAsn1SeqOfObjIdSeqs_CheckSanity               RT_MANGLER(RTAsn1SeqOfObjIdSeqs_CheckSanity)
+# define RTAsn1SeqOfObjIdSeqs_Clone                     RT_MANGLER(RTAsn1SeqOfObjIdSeqs_Clone)
+# define RTAsn1SeqOfObjIdSeqs_Compare                   RT_MANGLER(RTAsn1SeqOfObjIdSeqs_Compare)
+# define RTAsn1SetOfObjIdSeqs_DecodeAsn1                RT_MANGLER(RTAsn1SetOfObjIdSeqs_DecodeAsn1)
+# define RTAsn1SeqOfObjIdSeqs_Delete                    RT_MANGLER(RTAsn1SeqOfObjIdSeqs_Delete)
+# define RTAsn1SeqOfObjIdSeqs_Enum                      RT_MANGLER(RTAsn1SeqOfObjIdSeqs_Enum)
+# define RTAsn1SeqOfObjIdSeqs_Init                      RT_MANGLER(RTAsn1SeqOfObjIdSeqs_Init)
+# define RTAsn1SetOfObjIdSeqs_CheckSanity               RT_MANGLER(RTAsn1SetOfObjIdSeqs_CheckSanity)
+# define RTAsn1SetOfObjIdSeqs_Clone                     RT_MANGLER(RTAsn1SetOfObjIdSeqs_Clone)
+# define RTAsn1SetOfObjIdSeqs_Compare                   RT_MANGLER(RTAsn1SetOfObjIdSeqs_Compare)
+# define RTAsn1SetOfObjIdSeqs_Delete                    RT_MANGLER(RTAsn1SetOfObjIdSeqs_Delete)
+# define RTAsn1SetOfObjIdSeqs_Enum                      RT_MANGLER(RTAsn1SetOfObjIdSeqs_Enum)
+# define RTAsn1SetOfObjIdSeqs_Init                      RT_MANGLER(RTAsn1SetOfObjIdSeqs_Init)
+# define RTAsn1ObjId_DecodeAsn1                         RT_MANGLER(RTAsn1ObjId_DecodeAsn1)
+# define RTAsn1SeqOfObjIds_DecodeAsn1                   RT_MANGLER(RTAsn1SeqOfObjIds_DecodeAsn1)
+# define RTAsn1SetOfObjIds_DecodeAsn1                   RT_MANGLER(RTAsn1SetOfObjIds_DecodeAsn1)
+# define RTAsn1OctetString_CheckSanity                  RT_MANGLER(RTAsn1OctetString_CheckSanity)
+# define RTAsn1OctetString_Clone                        RT_MANGLER(RTAsn1OctetString_Clone)
+# define RTAsn1OctetString_Compare                      RT_MANGLER(RTAsn1OctetString_Compare)
+# define RTAsn1OctetString_Delete                       RT_MANGLER(RTAsn1OctetString_Delete)
+# define RTAsn1OctetString_Enum                         RT_MANGLER(RTAsn1OctetString_Enum)
+# define RTAsn1OctetString_Init                         RT_MANGLER(RTAsn1OctetString_Init)
+# define RTAsn1SeqOfOctetStrings_CheckSanity            RT_MANGLER(RTAsn1SeqOfOctetStrings_CheckSanity)
+# define RTAsn1SeqOfOctetStrings_Clone                  RT_MANGLER(RTAsn1SeqOfOctetStrings_Clone)
+# define RTAsn1SeqOfOctetStrings_Compare                RT_MANGLER(RTAsn1SeqOfOctetStrings_Compare)
+# define RTAsn1SeqOfOctetStrings_Delete                 RT_MANGLER(RTAsn1SeqOfOctetStrings_Delete)
+# define RTAsn1SeqOfOctetStrings_Enum                   RT_MANGLER(RTAsn1SeqOfOctetStrings_Enum)
+# define RTAsn1SeqOfOctetStrings_Init                   RT_MANGLER(RTAsn1SeqOfOctetStrings_Init)
+# define RTAsn1SetOfOctetStrings_CheckSanity            RT_MANGLER(RTAsn1SetOfOctetStrings_CheckSanity)
+# define RTAsn1SetOfOctetStrings_Clone                  RT_MANGLER(RTAsn1SetOfOctetStrings_Clone)
+# define RTAsn1SetOfOctetStrings_Compare                RT_MANGLER(RTAsn1SetOfOctetStrings_Compare)
+# define RTAsn1SetOfOctetStrings_Delete                 RT_MANGLER(RTAsn1SetOfOctetStrings_Delete)
+# define RTAsn1SetOfOctetStrings_Enum                   RT_MANGLER(RTAsn1SetOfOctetStrings_Enum)
+# define RTAsn1SetOfOctetStrings_Init                   RT_MANGLER(RTAsn1SetOfOctetStrings_Init)
+# define RTAsn1OctetString_DecodeAsn1                   RT_MANGLER(RTAsn1OctetString_DecodeAsn1)
+# define RTAsn1SeqOfOctetStrings_DecodeAsn1             RT_MANGLER(RTAsn1SeqOfOctetStrings_DecodeAsn1)
+# define RTAsn1SetOfOctetStrings_DecodeAsn1             RT_MANGLER(RTAsn1SetOfOctetStrings_DecodeAsn1)
+# define RTAsn1BmpString_CheckSanity                    RT_MANGLER(RTAsn1BmpString_CheckSanity)
+# define RTAsn1BmpString_Clone                          RT_MANGLER(RTAsn1BmpString_Clone)
+# define RTAsn1BmpString_Compare                        RT_MANGLER(RTAsn1BmpString_Compare)
+# define RTAsn1BmpString_Delete                         RT_MANGLER(RTAsn1BmpString_Delete)
+# define RTAsn1BmpString_Enum                           RT_MANGLER(RTAsn1BmpString_Enum)
+# define RTAsn1BmpString_Init                           RT_MANGLER(RTAsn1BmpString_Init)
+# define RTAsn1GeneralString_CheckSanity                RT_MANGLER(RTAsn1GeneralString_CheckSanity)
+# define RTAsn1GeneralString_Clone                      RT_MANGLER(RTAsn1GeneralString_Clone)
+# define RTAsn1GeneralString_Compare                    RT_MANGLER(RTAsn1GeneralString_Compare)
+# define RTAsn1GeneralString_Delete                     RT_MANGLER(RTAsn1GeneralString_Delete)
+# define RTAsn1GeneralString_Enum                       RT_MANGLER(RTAsn1GeneralString_Enum)
+# define RTAsn1GeneralString_Init                       RT_MANGLER(RTAsn1GeneralString_Init)
+# define RTAsn1GraphicString_CheckSanity                RT_MANGLER(RTAsn1GraphicString_CheckSanity)
+# define RTAsn1GraphicString_Clone                      RT_MANGLER(RTAsn1GraphicString_Clone)
+# define RTAsn1GraphicString_Compare                    RT_MANGLER(RTAsn1GraphicString_Compare)
+# define RTAsn1GraphicString_Delete                     RT_MANGLER(RTAsn1GraphicString_Delete)
+# define RTAsn1GraphicString_Enum                       RT_MANGLER(RTAsn1GraphicString_Enum)
+# define RTAsn1GraphicString_Init                       RT_MANGLER(RTAsn1GraphicString_Init)
+# define RTAsn1Ia5String_CheckSanity                    RT_MANGLER(RTAsn1Ia5String_CheckSanity)
+# define RTAsn1Ia5String_Clone                          RT_MANGLER(RTAsn1Ia5String_Clone)
+# define RTAsn1Ia5String_Compare                        RT_MANGLER(RTAsn1Ia5String_Compare)
+# define RTAsn1Ia5String_Delete                         RT_MANGLER(RTAsn1Ia5String_Delete)
+# define RTAsn1Ia5String_Enum                           RT_MANGLER(RTAsn1Ia5String_Enum)
+# define RTAsn1Ia5String_Init                           RT_MANGLER(RTAsn1Ia5String_Init)
+# define RTAsn1NumericString_CheckSanity                RT_MANGLER(RTAsn1NumericString_CheckSanity)
+# define RTAsn1NumericString_Clone                      RT_MANGLER(RTAsn1NumericString_Clone)
+# define RTAsn1NumericString_Compare                    RT_MANGLER(RTAsn1NumericString_Compare)
+# define RTAsn1NumericString_Delete                     RT_MANGLER(RTAsn1NumericString_Delete)
+# define RTAsn1NumericString_Enum                       RT_MANGLER(RTAsn1NumericString_Enum)
+# define RTAsn1NumericString_Init                       RT_MANGLER(RTAsn1NumericString_Init)
+# define RTAsn1PrintableString_CheckSanity              RT_MANGLER(RTAsn1PrintableString_CheckSanity)
+# define RTAsn1PrintableString_Clone                    RT_MANGLER(RTAsn1PrintableString_Clone)
+# define RTAsn1PrintableString_Compare                  RT_MANGLER(RTAsn1PrintableString_Compare)
+# define RTAsn1PrintableString_Delete                   RT_MANGLER(RTAsn1PrintableString_Delete)
+# define RTAsn1PrintableString_Enum                     RT_MANGLER(RTAsn1PrintableString_Enum)
+# define RTAsn1PrintableString_Init                     RT_MANGLER(RTAsn1PrintableString_Init)
+# define RTAsn1SeqOfStrings_CheckSanity                 RT_MANGLER(RTAsn1SeqOfStrings_CheckSanity)
+# define RTAsn1SeqOfStrings_Clone                       RT_MANGLER(RTAsn1SeqOfStrings_Clone)
+# define RTAsn1SeqOfStrings_Compare                     RT_MANGLER(RTAsn1SeqOfStrings_Compare)
+# define RTAsn1SeqOfStrings_Delete                      RT_MANGLER(RTAsn1SeqOfStrings_Delete)
+# define RTAsn1SeqOfStrings_Enum                        RT_MANGLER(RTAsn1SeqOfStrings_Enum)
+# define RTAsn1SeqOfStrings_Init                        RT_MANGLER(RTAsn1SeqOfStrings_Init)
+# define RTAsn1SetOfStrings_CheckSanity                 RT_MANGLER(RTAsn1SetOfStrings_CheckSanity)
+# define RTAsn1SetOfStrings_Clone                       RT_MANGLER(RTAsn1SetOfStrings_Clone)
+# define RTAsn1SetOfStrings_Compare                     RT_MANGLER(RTAsn1SetOfStrings_Compare)
+# define RTAsn1SetOfStrings_Delete                      RT_MANGLER(RTAsn1SetOfStrings_Delete)
+# define RTAsn1SetOfStrings_Enum                        RT_MANGLER(RTAsn1SetOfStrings_Enum)
+# define RTAsn1SetOfStrings_Init                        RT_MANGLER(RTAsn1SetOfStrings_Init)
+# define RTAsn1String_CheckSanity                       RT_MANGLER(RTAsn1String_CheckSanity)
+# define RTAsn1String_Clone                             RT_MANGLER(RTAsn1String_Clone)
+# define RTAsn1String_Compare                           RT_MANGLER(RTAsn1String_Compare)
+# define RTAsn1String_CompareEx                         RT_MANGLER(RTAsn1String_CompareEx)
+# define RTAsn1String_CompareWithString                 RT_MANGLER(RTAsn1String_CompareWithString)
+# define RTAsn1String_Delete                            RT_MANGLER(RTAsn1String_Delete)
+# define RTAsn1String_Enum                              RT_MANGLER(RTAsn1String_Enum)
+# define RTAsn1String_Init                              RT_MANGLER(RTAsn1String_Init)
+# define RTAsn1String_InitEx                            RT_MANGLER(RTAsn1String_InitEx)
+# define RTAsn1String_InitWithValue                     RT_MANGLER(RTAsn1String_InitWithValue)
+# define RTAsn1String_QueryUtf8                         RT_MANGLER(RTAsn1String_QueryUtf8)
+# define RTAsn1String_QueryUtf8Len                      RT_MANGLER(RTAsn1String_QueryUtf8Len)
+# define RTAsn1String_RecodeAsUtf8                      RT_MANGLER(RTAsn1String_RecodeAsUtf8)
+# define RTAsn1T61String_CheckSanity                    RT_MANGLER(RTAsn1T61String_CheckSanity)
+# define RTAsn1T61String_Clone                          RT_MANGLER(RTAsn1T61String_Clone)
+# define RTAsn1T61String_Compare                        RT_MANGLER(RTAsn1T61String_Compare)
+# define RTAsn1T61String_Delete                         RT_MANGLER(RTAsn1T61String_Delete)
+# define RTAsn1T61String_Enum                           RT_MANGLER(RTAsn1T61String_Enum)
+# define RTAsn1T61String_Init                           RT_MANGLER(RTAsn1T61String_Init)
+# define RTAsn1UniversalString_CheckSanity              RT_MANGLER(RTAsn1UniversalString_CheckSanity)
+# define RTAsn1UniversalString_Clone                    RT_MANGLER(RTAsn1UniversalString_Clone)
+# define RTAsn1UniversalString_Compare                  RT_MANGLER(RTAsn1UniversalString_Compare)
+# define RTAsn1UniversalString_Delete                   RT_MANGLER(RTAsn1UniversalString_Delete)
+# define RTAsn1UniversalString_Enum                     RT_MANGLER(RTAsn1UniversalString_Enum)
+# define RTAsn1UniversalString_Init                     RT_MANGLER(RTAsn1UniversalString_Init)
+# define RTAsn1Utf8String_CheckSanity                   RT_MANGLER(RTAsn1Utf8String_CheckSanity)
+# define RTAsn1Utf8String_Clone                         RT_MANGLER(RTAsn1Utf8String_Clone)
+# define RTAsn1Utf8String_Compare                       RT_MANGLER(RTAsn1Utf8String_Compare)
+# define RTAsn1Utf8String_Delete                        RT_MANGLER(RTAsn1Utf8String_Delete)
+# define RTAsn1Utf8String_Enum                          RT_MANGLER(RTAsn1Utf8String_Enum)
+# define RTAsn1Utf8String_Init                          RT_MANGLER(RTAsn1Utf8String_Init)
+# define RTAsn1VisibleString_CheckSanity                RT_MANGLER(RTAsn1VisibleString_CheckSanity)
+# define RTAsn1VisibleString_Clone                      RT_MANGLER(RTAsn1VisibleString_Clone)
+# define RTAsn1VisibleString_Compare                    RT_MANGLER(RTAsn1VisibleString_Compare)
+# define RTAsn1VisibleString_Delete                     RT_MANGLER(RTAsn1VisibleString_Delete)
+# define RTAsn1VisibleString_Enum                       RT_MANGLER(RTAsn1VisibleString_Enum)
+# define RTAsn1VisibleString_Init                       RT_MANGLER(RTAsn1VisibleString_Init)
+# define RTAsn1BmpString_DecodeAsn1                     RT_MANGLER(RTAsn1BmpString_DecodeAsn1)
+# define RTAsn1GeneralString_DecodeAsn1                 RT_MANGLER(RTAsn1GeneralString_DecodeAsn1)
+# define RTAsn1GraphicString_DecodeAsn1                 RT_MANGLER(RTAsn1GraphicString_DecodeAsn1)
+# define RTAsn1Ia5String_DecodeAsn1                     RT_MANGLER(RTAsn1Ia5String_DecodeAsn1)
+# define RTAsn1NumericString_DecodeAsn1                 RT_MANGLER(RTAsn1NumericString_DecodeAsn1)
+# define RTAsn1PrintableString_DecodeAsn1               RT_MANGLER(RTAsn1PrintableString_DecodeAsn1)
+# define RTAsn1SeqOfStrings_DecodeAsn1                  RT_MANGLER(RTAsn1SeqOfStrings_DecodeAsn1)
+# define RTAsn1SetOfStrings_DecodeAsn1                  RT_MANGLER(RTAsn1SetOfStrings_DecodeAsn1)
+# define RTAsn1String_DecodeAsn1                        RT_MANGLER(RTAsn1String_DecodeAsn1)
+# define RTAsn1T61String_DecodeAsn1                     RT_MANGLER(RTAsn1T61String_DecodeAsn1)
+# define RTAsn1UniversalString_DecodeAsn1               RT_MANGLER(RTAsn1UniversalString_DecodeAsn1)
+# define RTAsn1Utf8String_DecodeAsn1                    RT_MANGLER(RTAsn1Utf8String_DecodeAsn1)
+# define RTAsn1VisibleString_DecodeAsn1                 RT_MANGLER(RTAsn1VisibleString_DecodeAsn1)
+# define RTAsn1GeneralizedTime_CheckSanity              RT_MANGLER(RTAsn1GeneralizedTime_CheckSanity)
+# define RTAsn1GeneralizedTime_Clone                    RT_MANGLER(RTAsn1GeneralizedTime_Clone)
+# define RTAsn1GeneralizedTime_Compare                  RT_MANGLER(RTAsn1GeneralizedTime_Compare)
+# define RTAsn1GeneralizedTime_Delete                   RT_MANGLER(RTAsn1GeneralizedTime_Delete)
+# define RTAsn1GeneralizedTime_Enum                     RT_MANGLER(RTAsn1GeneralizedTime_Enum)
+# define RTAsn1GeneralizedTime_Init                     RT_MANGLER(RTAsn1GeneralizedTime_Init)
+# define RTAsn1SeqOfTimes_CheckSanity                   RT_MANGLER(RTAsn1SeqOfTimes_CheckSanity)
+# define RTAsn1SeqOfTimes_Clone                         RT_MANGLER(RTAsn1SeqOfTimes_Clone)
+# define RTAsn1SeqOfTimes_Compare                       RT_MANGLER(RTAsn1SeqOfTimes_Compare)
+# define RTAsn1SeqOfTimes_Delete                        RT_MANGLER(RTAsn1SeqOfTimes_Delete)
+# define RTAsn1SeqOfTimes_Enum                          RT_MANGLER(RTAsn1SeqOfTimes_Enum)
+# define RTAsn1SeqOfTimes_Init                          RT_MANGLER(RTAsn1SeqOfTimes_Init)
+# define RTAsn1SetOfTimes_CheckSanity                   RT_MANGLER(RTAsn1SetOfTimes_CheckSanity)
+# define RTAsn1SetOfTimes_Clone                         RT_MANGLER(RTAsn1SetOfTimes_Clone)
+# define RTAsn1SetOfTimes_Compare                       RT_MANGLER(RTAsn1SetOfTimes_Compare)
+# define RTAsn1SetOfTimes_Delete                        RT_MANGLER(RTAsn1SetOfTimes_Delete)
+# define RTAsn1SetOfTimes_Enum                          RT_MANGLER(RTAsn1SetOfTimes_Enum)
+# define RTAsn1SetOfTimes_Init                          RT_MANGLER(RTAsn1SetOfTimes_Init)
+# define RTAsn1Time_CheckSanity                         RT_MANGLER(RTAsn1Time_CheckSanity)
+# define RTAsn1Time_Clone                               RT_MANGLER(RTAsn1Time_Clone)
+# define RTAsn1Time_Compare                             RT_MANGLER(RTAsn1Time_Compare)
+# define RTAsn1Time_CompareWithTimeSpec                 RT_MANGLER(RTAsn1Time_CompareWithTimeSpec)
+# define RTAsn1Time_Delete                              RT_MANGLER(RTAsn1Time_Delete)
+# define RTAsn1Time_Enum                                RT_MANGLER(RTAsn1Time_Enum)
+# define RTAsn1Time_Init                                RT_MANGLER(RTAsn1Time_Init)
+# define RTAsn1UtcTime_CheckSanity                      RT_MANGLER(RTAsn1UtcTime_CheckSanity)
+# define RTAsn1UtcTime_Clone                            RT_MANGLER(RTAsn1UtcTime_Clone)
+# define RTAsn1UtcTime_Compare                          RT_MANGLER(RTAsn1UtcTime_Compare)
+# define RTAsn1UtcTime_Delete                           RT_MANGLER(RTAsn1UtcTime_Delete)
+# define RTAsn1UtcTime_Enum                             RT_MANGLER(RTAsn1UtcTime_Enum)
+# define RTAsn1UtcTime_Init                             RT_MANGLER(RTAsn1UtcTime_Init)
+# define RTAsn1GeneralizedTime_DecodeAsn1               RT_MANGLER(RTAsn1GeneralizedTime_DecodeAsn1)
+# define RTAsn1SeqOfTimes_DecodeAsn1                    RT_MANGLER(RTAsn1SeqOfTimes_DecodeAsn1)
+# define RTAsn1SetOfTimes_DecodeAsn1                    RT_MANGLER(RTAsn1SetOfTimes_DecodeAsn1)
+# define RTAsn1Time_DecodeAsn1                          RT_MANGLER(RTAsn1Time_DecodeAsn1)
+# define RTAsn1UtcTime_DecodeAsn1                       RT_MANGLER(RTAsn1UtcTime_DecodeAsn1)
+# define RTMd2                                          RT_MANGLER(RTMd2)
+# define RTMd2Final                                     RT_MANGLER(RTMd2Final)
+# define RTMd2Init                                      RT_MANGLER(RTMd2Init)
+# define RTMd2Update                                    RT_MANGLER(RTMd2Update)
+# define RTMd2FromString                                RT_MANGLER(RTMd2FromString)
+# define RTMd2ToString                                  RT_MANGLER(RTMd2ToString)
+# define RTCrDigestClone                                RT_MANGLER(RTCrDigestClone)
+# define RTCrDigestCreate                               RT_MANGLER(RTCrDigestCreate)
+# define RTCrDigestFinal                                RT_MANGLER(RTCrDigestFinal)
+# define RTCrDigestGetConsumedSize                      RT_MANGLER(RTCrDigestGetConsumedSize)
+# define RTCrDigestGetHash                              RT_MANGLER(RTCrDigestGetHash)
+# define RTCrDigestGetHashSize                          RT_MANGLER(RTCrDigestGetHashSize)
+# define RTCrDigestGetType                              RT_MANGLER(RTCrDigestGetType)
+# define RTCrDigestGetAlgorithmOid                      RT_MANGLER(RTCrDigestGetAlgorithmOid)
+# define RTCrDigestIsFinalized                          RT_MANGLER(RTCrDigestIsFinalized)
+# define RTCrDigestMatch                                RT_MANGLER(RTCrDigestMatch)
+# define RTCrDigestRelease                              RT_MANGLER(RTCrDigestRelease)
+# define RTCrDigestReset                                RT_MANGLER(RTCrDigestReset)
+# define RTCrDigestRetain                               RT_MANGLER(RTCrDigestRetain)
+# define RTCrDigestUpdate                               RT_MANGLER(RTCrDigestUpdate)
+# define RTCrDigestUpdateFromVfsFile                    RT_MANGLER(RTCrDigestUpdateFromVfsFile)
+# define RTCrDigestCreateByObjId                        RT_MANGLER(RTCrDigestCreateByObjId)
+# define RTCrDigestCreateByObjIdString                  RT_MANGLER(RTCrDigestCreateByObjIdString)
+# define RTCrDigestCreateByType                         RT_MANGLER(RTCrDigestCreateByType)
+# define RTCrDigestFindByObjId                          RT_MANGLER(RTCrDigestFindByObjId)
+# define RTCrDigestFindByObjIdString                    RT_MANGLER(RTCrDigestFindByObjIdString)
+# define RTCrDigestFindByType                           RT_MANGLER(RTCrDigestFindByType)
+# define RTCrDigestTypeToAlgorithmOid                   RT_MANGLER(RTCrDigestTypeToAlgorithmOid)
+# define RTCrDigestTypeToName                           RT_MANGLER(RTCrDigestTypeToName)
+# define RTCrDigestTypeToHashSize                       RT_MANGLER(RTCrDigestTypeToHashSize)
+# define RTCrRsaDigestInfo_DecodeAsn1                   RT_MANGLER(RTCrRsaDigestInfo_DecodeAsn1)
+# define RTCrRsaOtherPrimeInfo_DecodeAsn1               RT_MANGLER(RTCrRsaOtherPrimeInfo_DecodeAsn1)
+# define RTCrRsaOtherPrimeInfos_DecodeAsn1              RT_MANGLER(RTCrRsaOtherPrimeInfos_DecodeAsn1)
+# define RTCrRsaPrivateKey_DecodeAsn1                   RT_MANGLER(RTCrRsaPrivateKey_DecodeAsn1)
+# define RTCrRsaPublicKey_DecodeAsn1                    RT_MANGLER(RTCrRsaPublicKey_DecodeAsn1)
+# define RTCrRsaDigestInfo_Compare                      RT_MANGLER(RTCrRsaDigestInfo_Compare)
+# define RTCrRsaDigestInfo_Delete                       RT_MANGLER(RTCrRsaDigestInfo_Delete)
+# define RTCrRsaDigestInfo_Enum                         RT_MANGLER(RTCrRsaDigestInfo_Enum)
+# define RTCrRsaOtherPrimeInfo_Compare                  RT_MANGLER(RTCrRsaOtherPrimeInfo_Compare)
+# define RTCrRsaOtherPrimeInfo_Delete                   RT_MANGLER(RTCrRsaOtherPrimeInfo_Delete)
+# define RTCrRsaOtherPrimeInfo_Enum                     RT_MANGLER(RTCrRsaOtherPrimeInfo_Enum)
+# define RTCrRsaOtherPrimeInfos_Compare                 RT_MANGLER(RTCrRsaOtherPrimeInfos_Compare)
+# define RTCrRsaOtherPrimeInfos_Delete                  RT_MANGLER(RTCrRsaOtherPrimeInfos_Delete)
+# define RTCrRsaOtherPrimeInfos_Enum                    RT_MANGLER(RTCrRsaOtherPrimeInfos_Enum)
+# define RTCrRsaPrivateKey_Compare                      RT_MANGLER(RTCrRsaPrivateKey_Compare)
+# define RTCrRsaPrivateKey_Delete                       RT_MANGLER(RTCrRsaPrivateKey_Delete)
+# define RTCrRsaPrivateKey_Enum                         RT_MANGLER(RTCrRsaPrivateKey_Enum)
+# define RTCrRsaPublicKey_Compare                       RT_MANGLER(RTCrRsaPublicKey_Compare)
+# define RTCrRsaPublicKey_Delete                        RT_MANGLER(RTCrRsaPublicKey_Delete)
+# define RTCrRsaPublicKey_Enum                          RT_MANGLER(RTCrRsaPublicKey_Enum)
+# define RTCrRsaDigestInfo_Clone                        RT_MANGLER(RTCrRsaDigestInfo_Clone)
+# define RTCrRsaDigestInfo_Init                         RT_MANGLER(RTCrRsaDigestInfo_Init)
+# define RTCrRsaOtherPrimeInfo_Clone                    RT_MANGLER(RTCrRsaOtherPrimeInfo_Clone)
+# define RTCrRsaOtherPrimeInfo_Init                     RT_MANGLER(RTCrRsaOtherPrimeInfo_Init)
+# define RTCrRsaOtherPrimeInfos_Clone                   RT_MANGLER(RTCrRsaOtherPrimeInfos_Clone)
+# define RTCrRsaOtherPrimeInfos_Init                    RT_MANGLER(RTCrRsaOtherPrimeInfos_Init)
+# define RTCrRsaPrivateKey_Clone                        RT_MANGLER(RTCrRsaPrivateKey_Clone)
+# define RTCrRsaPrivateKey_Init                         RT_MANGLER(RTCrRsaPrivateKey_Init)
+# define RTCrRsaPublicKey_Clone                         RT_MANGLER(RTCrRsaPublicKey_Clone)
+# define RTCrRsaPublicKey_Init                          RT_MANGLER(RTCrRsaPublicKey_Init)
+# define RTCrRsaDigestInfo_CheckSanity                  RT_MANGLER(RTCrRsaDigestInfo_CheckSanity)
+# define RTCrRsaOtherPrimeInfo_CheckSanity              RT_MANGLER(RTCrRsaOtherPrimeInfo_CheckSanity)
+# define RTCrRsaOtherPrimeInfos_CheckSanity             RT_MANGLER(RTCrRsaOtherPrimeInfos_CheckSanity)
+# define RTCrRsaPrivateKey_CheckSanity                  RT_MANGLER(RTCrRsaPrivateKey_CheckSanity)
+# define RTCrRsaPublicKey_CheckSanity                   RT_MANGLER(RTCrRsaPublicKey_CheckSanity)
+# define RTCrPemFindFirstSectionInContent               RT_MANGLER(RTCrPemFindFirstSectionInContent)
+# define RTCrPemFreeSections                            RT_MANGLER(RTCrPemFreeSections)
+# define RTCrPemParseContent                            RT_MANGLER(RTCrPemParseContent)
+# define RTCrPemReadFile                                RT_MANGLER(RTCrPemReadFile)
+# define RTCrPkcs7Attribute_DecodeAsn1                  RT_MANGLER(RTCrPkcs7Attribute_DecodeAsn1)
+# define RTCrPkcs7Attributes_DecodeAsn1                 RT_MANGLER(RTCrPkcs7Attributes_DecodeAsn1)
+# define RTCrPkcs7ContentInfo_DecodeAsn1                RT_MANGLER(RTCrPkcs7ContentInfo_DecodeAsn1)
+# define RTCrPkcs7DigestInfo_DecodeAsn1                 RT_MANGLER(RTCrPkcs7DigestInfo_DecodeAsn1)
+# define RTCrPkcs7IssuerAndSerialNumber_DecodeAsn1      RT_MANGLER(RTCrPkcs7IssuerAndSerialNumber_DecodeAsn1)
+# define RTCrPkcs7SignedData_DecodeAsn1                 RT_MANGLER(RTCrPkcs7SignedData_DecodeAsn1)
+# define RTCrPkcs7SignerInfo_DecodeAsn1                 RT_MANGLER(RTCrPkcs7SignerInfo_DecodeAsn1)
+# define RTCrPkcs7SignerInfos_DecodeAsn1                RT_MANGLER(RTCrPkcs7SignerInfos_DecodeAsn1)
+# define RTCrPkcs7Attribute_Compare                     RT_MANGLER(RTCrPkcs7Attribute_Compare)
+# define RTCrPkcs7Attribute_Delete                      RT_MANGLER(RTCrPkcs7Attribute_Delete)
+# define RTCrPkcs7Attribute_Enum                        RT_MANGLER(RTCrPkcs7Attribute_Enum)
+# define RTCrPkcs7Attributes_Compare                    RT_MANGLER(RTCrPkcs7Attributes_Compare)
+# define RTCrPkcs7Attributes_Delete                     RT_MANGLER(RTCrPkcs7Attributes_Delete)
+# define RTCrPkcs7Attributes_Enum                       RT_MANGLER(RTCrPkcs7Attributes_Enum)
+# define RTCrPkcs7ContentInfo_Compare                   RT_MANGLER(RTCrPkcs7ContentInfo_Compare)
+# define RTCrPkcs7ContentInfo_Delete                    RT_MANGLER(RTCrPkcs7ContentInfo_Delete)
+# define RTCrPkcs7ContentInfo_Enum                      RT_MANGLER(RTCrPkcs7ContentInfo_Enum)
+# define RTCrPkcs7ContentInfo_IsSignedData              RT_MANGLER(RTCrPkcs7ContentInfo_IsSignedData)
+# define RTCrPkcs7DigestInfo_Compare                    RT_MANGLER(RTCrPkcs7DigestInfo_Compare)
+# define RTCrPkcs7DigestInfo_Delete                     RT_MANGLER(RTCrPkcs7DigestInfo_Delete)
+# define RTCrPkcs7DigestInfo_Enum                       RT_MANGLER(RTCrPkcs7DigestInfo_Enum)
+# define RTCrPkcs7IssuerAndSerialNumber_Compare         RT_MANGLER(RTCrPkcs7IssuerAndSerialNumber_Compare)
+# define RTCrPkcs7IssuerAndSerialNumber_Delete          RT_MANGLER(RTCrPkcs7IssuerAndSerialNumber_Delete)
+# define RTCrPkcs7IssuerAndSerialNumber_Enum            RT_MANGLER(RTCrPkcs7IssuerAndSerialNumber_Enum)
+# define RTCrPkcs7SignedData_Compare                    RT_MANGLER(RTCrPkcs7SignedData_Compare)
+# define RTCrPkcs7SignedData_Delete                     RT_MANGLER(RTCrPkcs7SignedData_Delete)
+# define RTCrPkcs7SignedData_Enum                       RT_MANGLER(RTCrPkcs7SignedData_Enum)
+# define RTCrPkcs7SignerInfo_Compare                    RT_MANGLER(RTCrPkcs7SignerInfo_Compare)
+# define RTCrPkcs7SignerInfo_Delete                     RT_MANGLER(RTCrPkcs7SignerInfo_Delete)
+# define RTCrPkcs7SignerInfo_Enum                       RT_MANGLER(RTCrPkcs7SignerInfo_Enum)
+# define RTCrPkcs7SignerInfo_GetSigningTime             RT_MANGLER(RTCrPkcs7SignerInfo_GetSigningTime)
+# define RTCrPkcs7SignerInfo_GetMsTimestamp             RT_MANGLER(RTCrPkcs7SignerInfo_GetMsTimestamp)
+# define RTCrPkcs7SignerInfos_Compare                   RT_MANGLER(RTCrPkcs7SignerInfos_Compare)
+# define RTCrPkcs7SignerInfos_Delete                    RT_MANGLER(RTCrPkcs7SignerInfos_Delete)
+# define RTCrPkcs7SignerInfos_Enum                      RT_MANGLER(RTCrPkcs7SignerInfos_Enum)
+# define RTCrPkcs7Attribute_Clone                       RT_MANGLER(RTCrPkcs7Attribute_Clone)
+# define RTCrPkcs7Attribute_Init                        RT_MANGLER(RTCrPkcs7Attribute_Init)
+# define RTCrPkcs7Attributes_Clone                      RT_MANGLER(RTCrPkcs7Attributes_Clone)
+# define RTCrPkcs7Attributes_Init                       RT_MANGLER(RTCrPkcs7Attributes_Init)
+# define RTCrPkcs7ContentInfo_Clone                     RT_MANGLER(RTCrPkcs7ContentInfo_Clone)
+# define RTCrPkcs7ContentInfo_Init                      RT_MANGLER(RTCrPkcs7ContentInfo_Init)
+# define RTCrPkcs7DigestInfo_Clone                      RT_MANGLER(RTCrPkcs7DigestInfo_Clone)
+# define RTCrPkcs7DigestInfo_Init                       RT_MANGLER(RTCrPkcs7DigestInfo_Init)
+# define RTCrPkcs7IssuerAndSerialNumber_Clone           RT_MANGLER(RTCrPkcs7IssuerAndSerialNumber_Clone)
+# define RTCrPkcs7IssuerAndSerialNumber_Init            RT_MANGLER(RTCrPkcs7IssuerAndSerialNumber_Init)
+# define RTCrPkcs7SignedData_Clone                      RT_MANGLER(RTCrPkcs7SignedData_Clone)
+# define RTCrPkcs7SignedData_Init                       RT_MANGLER(RTCrPkcs7SignedData_Init)
+# define RTCrPkcs7SignerInfo_Clone                      RT_MANGLER(RTCrPkcs7SignerInfo_Clone)
+# define RTCrPkcs7SignerInfo_Init                       RT_MANGLER(RTCrPkcs7SignerInfo_Init)
+# define RTCrPkcs7SignerInfos_Clone                     RT_MANGLER(RTCrPkcs7SignerInfos_Clone)
+# define RTCrPkcs7SignerInfos_Init                      RT_MANGLER(RTCrPkcs7SignerInfos_Init)
+# define RTCrPkcs7Attribute_CheckSanity                 RT_MANGLER(RTCrPkcs7Attribute_CheckSanity)
+# define RTCrPkcs7Attributes_CheckSanity                RT_MANGLER(RTCrPkcs7Attributes_CheckSanity)
+# define RTCrPkcs7ContentInfo_CheckSanity               RT_MANGLER(RTCrPkcs7ContentInfo_CheckSanity)
+# define RTCrPkcs7DigestInfo_CheckSanity                RT_MANGLER(RTCrPkcs7DigestInfo_CheckSanity)
+# define RTCrPkcs7IssuerAndSerialNumber_CheckSanity     RT_MANGLER(RTCrPkcs7IssuerAndSerialNumber_CheckSanity)
+# define RTCrPkcs7SignedData_CheckSanity                RT_MANGLER(RTCrPkcs7SignedData_CheckSanity)
+# define RTCrPkcs7SignerInfo_CheckSanity                RT_MANGLER(RTCrPkcs7SignerInfo_CheckSanity)
+# define RTCrPkcs7SignerInfos_CheckSanity               RT_MANGLER(RTCrPkcs7SignerInfos_CheckSanity)
+# define RTCrPkcs7VerifyCertCallbackCodeSigning         RT_MANGLER(RTCrPkcs7VerifyCertCallbackCodeSigning)
+# define RTCrPkcs7VerifyCertCallbackDefault             RT_MANGLER(RTCrPkcs7VerifyCertCallbackDefault)
+# define RTCrPkcs7VerifySignedData                      RT_MANGLER(RTCrPkcs7VerifySignedData)
+# define RTCrPkcs7Cert_CheckSanity                      RT_MANGLER(RTCrPkcs7Cert_CheckSanity)
+# define RTCrPkcs7Cert_Clone                            RT_MANGLER(RTCrPkcs7Cert_Clone)
+# define RTCrPkcs7Cert_Compare                          RT_MANGLER(RTCrPkcs7Cert_Compare)
+# define RTCrPkcs7Cert_DecodeAsn1                       RT_MANGLER(RTCrPkcs7Cert_DecodeAsn1)
+# define RTCrPkcs7Cert_Delete                           RT_MANGLER(RTCrPkcs7Cert_Delete)
+# define RTCrPkcs7Cert_Enum                             RT_MANGLER(RTCrPkcs7Cert_Enum)
+# define RTCrPkcs7Cert_Init                             RT_MANGLER(RTCrPkcs7Cert_Init)
+# define RTCrPkcs7SetOfCerts_CheckSanity                RT_MANGLER(RTCrPkcs7SetOfCerts_CheckSanity)
+# define RTCrPkcs7SetOfCerts_Clone                      RT_MANGLER(RTCrPkcs7SetOfCerts_Clone)
+# define RTCrPkcs7SetOfCerts_Compare                    RT_MANGLER(RTCrPkcs7SetOfCerts_Compare)
+# define RTCrPkcs7SetOfCerts_DecodeAsn1                 RT_MANGLER(RTCrPkcs7SetOfCerts_DecodeAsn1)
+# define RTCrPkcs7SetOfCerts_Delete                     RT_MANGLER(RTCrPkcs7SetOfCerts_Delete)
+# define RTCrPkcs7SetOfCerts_Enum                       RT_MANGLER(RTCrPkcs7SetOfCerts_Enum)
+# define RTCrPkcs7SetOfCerts_Init                       RT_MANGLER(RTCrPkcs7SetOfCerts_Init)
+# define RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber RT_MANGLER(RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber)
+# define RTCrPkcs7SetOfContentInfos_CheckSanity         RT_MANGLER(RTCrPkcs7SetOfContentInfos_CheckSanity)
+# define RTCrPkcs7SetOfContentInfos_Clone               RT_MANGLER(RTCrPkcs7SetOfContentInfos_Clone)
+# define RTCrPkcs7SetOfContentInfos_Compare             RT_MANGLER(RTCrPkcs7SetOfContentInfos_Compare)
+# define RTCrPkcs7SetOfContentInfos_DecodeAsn1          RT_MANGLER(RTCrPkcs7SetOfContentInfos_DecodeAsn1)
+# define RTCrPkcs7SetOfContentInfos_Delete              RT_MANGLER(RTCrPkcs7SetOfContentInfos_Delete)
+# define RTCrPkcs7SetOfContentInfos_Enum                RT_MANGLER(RTCrPkcs7SetOfContentInfos_Enum)
+# define RTCrPkcs7SetOfContentInfos_Init                RT_MANGLER(RTCrPkcs7SetOfContentInfos_Init)
+# define RTCrPkcs7SetOfSignedData_CheckSanity           RT_MANGLER(RTCrPkcs7SetOfSignedData_CheckSanity)
+# define RTCrPkcs7SetOfSignedData_Clone                 RT_MANGLER(RTCrPkcs7SetOfSignedData_Clone)
+# define RTCrPkcs7SetOfSignedData_Compare               RT_MANGLER(RTCrPkcs7SetOfSignedData_Compare)
+# define RTCrPkcs7SetOfSignedData_DecodeAsn1            RT_MANGLER(RTCrPkcs7SetOfSignedData_DecodeAsn1)
+# define RTCrPkcs7SetOfSignedData_Delete                RT_MANGLER(RTCrPkcs7SetOfSignedData_Delete)
+# define RTCrPkcs7SetOfSignedData_Enum                  RT_MANGLER(RTCrPkcs7SetOfSignedData_Enum)
+# define RTCrPkcs7SetOfSignedData_Init                  RT_MANGLER(RTCrPkcs7SetOfSignedData_Init)
+# define RTCrPkixSignatureCreateByObjId                 RT_MANGLER(RTCrPkixSignatureCreateByObjId)
+# define RTCrPkixSignatureCreateByObjIdString           RT_MANGLER(RTCrPkixSignatureCreateByObjIdString)
+# define RTCrPkixSignatureCreate                        RT_MANGLER(RTCrPkixSignatureCreate)
+# define RTCrPkixSignatureRelease                       RT_MANGLER(RTCrPkixSignatureRelease)
+# define RTCrPkixSignatureRetain                        RT_MANGLER(RTCrPkixSignatureRetain)
+# define RTCrPkixSignatureSign                          RT_MANGLER(RTCrPkixSignatureSign)
+# define RTCrPkixSignatureVerify                        RT_MANGLER(RTCrPkixSignatureVerify)
+# define RTCrPkixSignatureVerifyBitString               RT_MANGLER(RTCrPkixSignatureVerifyBitString)
+# define RTCrPkixSignatureVerifyOctetString             RT_MANGLER(RTCrPkixSignatureVerifyOctetString)
+# define RTCrPkixGetCiperOidFromSignatureAlgorithm      RT_MANGLER(RTCrPkixGetCiperOidFromSignatureAlgorithm)
+# define RTCrPkixPubKeyVerifySignature                  RT_MANGLER(RTCrPkixPubKeyVerifySignature)
+# define RTCrPkixPubKeyVerifySignedDigest               RT_MANGLER(RTCrPkixPubKeyVerifySignedDigest)
+# define RTCrSpcAttributeTypeAndOptionalValue_DecodeAsn1 RT_MANGLER(RTCrSpcAttributeTypeAndOptionalValue_DecodeAsn1)
+# define RTCrSpcIndirectDataContent_DecodeAsn1          RT_MANGLER(RTCrSpcIndirectDataContent_DecodeAsn1)
+# define RTCrSpcLink_DecodeAsn1                         RT_MANGLER(RTCrSpcLink_DecodeAsn1)
+# define RTCrSpcPeImageData_DecodeAsn1                  RT_MANGLER(RTCrSpcPeImageData_DecodeAsn1)
+# define RTCrSpcSerializedObjectAttribute_DecodeAsn1    RT_MANGLER(RTCrSpcSerializedObjectAttribute_DecodeAsn1)
+# define RTCrSpcSerializedObjectAttributes_DecodeAsn1   RT_MANGLER(RTCrSpcSerializedObjectAttributes_DecodeAsn1)
+# define RTCrSpcSerializedObject_DecodeAsn1             RT_MANGLER(RTCrSpcSerializedObject_DecodeAsn1)
+# define RTCrSpcSerializedPageHashes_DecodeAsn1         RT_MANGLER(RTCrSpcSerializedPageHashes_DecodeAsn1)
+# define RTCrSpcString_DecodeAsn1                       RT_MANGLER(RTCrSpcString_DecodeAsn1)
+# define RTCrSpcAttributeTypeAndOptionalValue_Compare   RT_MANGLER(RTCrSpcAttributeTypeAndOptionalValue_Compare)
+# define RTCrSpcAttributeTypeAndOptionalValue_Delete    RT_MANGLER(RTCrSpcAttributeTypeAndOptionalValue_Delete)
+# define RTCrSpcAttributeTypeAndOptionalValue_Enum      RT_MANGLER(RTCrSpcAttributeTypeAndOptionalValue_Enum)
+# define RTCrSpcIndirectDataContent_Compare             RT_MANGLER(RTCrSpcIndirectDataContent_Compare)
+# define RTCrSpcIndirectDataContent_Delete              RT_MANGLER(RTCrSpcIndirectDataContent_Delete)
+# define RTCrSpcIndirectDataContent_Enum                RT_MANGLER(RTCrSpcIndirectDataContent_Enum)
+# define RTCrSpcIndirectDataContent_GetPeImageObjAttrib RT_MANGLER(RTCrSpcIndirectDataContent_GetPeImageObjAttrib)
+# define RTCrSpcLink_Compare                            RT_MANGLER(RTCrSpcLink_Compare)
+# define RTCrSpcLink_Delete                             RT_MANGLER(RTCrSpcLink_Delete)
+# define RTCrSpcLink_Enum                               RT_MANGLER(RTCrSpcLink_Enum)
+# define RTCrSpcPeImageData_Compare                     RT_MANGLER(RTCrSpcPeImageData_Compare)
+# define RTCrSpcPeImageData_Delete                      RT_MANGLER(RTCrSpcPeImageData_Delete)
+# define RTCrSpcPeImageData_Enum                        RT_MANGLER(RTCrSpcPeImageData_Enum)
+# define RTCrSpcSerializedObjectAttribute_Compare       RT_MANGLER(RTCrSpcSerializedObjectAttribute_Compare)
+# define RTCrSpcSerializedObjectAttribute_Delete        RT_MANGLER(RTCrSpcSerializedObjectAttribute_Delete)
+# define RTCrSpcSerializedObjectAttribute_Enum          RT_MANGLER(RTCrSpcSerializedObjectAttribute_Enum)
+# define RTCrSpcSerializedObjectAttributes_Compare      RT_MANGLER(RTCrSpcSerializedObjectAttributes_Compare)
+# define RTCrSpcSerializedObjectAttributes_Delete       RT_MANGLER(RTCrSpcSerializedObjectAttributes_Delete)
+# define RTCrSpcSerializedObjectAttributes_Enum         RT_MANGLER(RTCrSpcSerializedObjectAttributes_Enum)
+# define RTCrSpcSerializedObject_Compare                RT_MANGLER(RTCrSpcSerializedObject_Compare)
+# define RTCrSpcSerializedObject_Delete                 RT_MANGLER(RTCrSpcSerializedObject_Delete)
+# define RTCrSpcSerializedObject_Enum                   RT_MANGLER(RTCrSpcSerializedObject_Enum)
+# define RTCrSpcSerializedPageHashes_Compare            RT_MANGLER(RTCrSpcSerializedPageHashes_Compare)
+# define RTCrSpcSerializedPageHashes_Delete             RT_MANGLER(RTCrSpcSerializedPageHashes_Delete)
+# define RTCrSpcSerializedPageHashes_Enum               RT_MANGLER(RTCrSpcSerializedPageHashes_Enum)
+# define RTCrSpcSerializedPageHashes_UpdateDerivedData  RT_MANGLER(RTCrSpcSerializedPageHashes_UpdateDerivedData)
+# define RTCrSpcString_Compare                          RT_MANGLER(RTCrSpcString_Compare)
+# define RTCrSpcString_Delete                           RT_MANGLER(RTCrSpcString_Delete)
+# define RTCrSpcString_Enum                             RT_MANGLER(RTCrSpcString_Enum)
+# define RTCrSpcAttributeTypeAndOptionalValue_Clone     RT_MANGLER(RTCrSpcAttributeTypeAndOptionalValue_Clone)
+# define RTCrSpcAttributeTypeAndOptionalValue_Init      RT_MANGLER(RTCrSpcAttributeTypeAndOptionalValue_Init)
+# define RTCrSpcIndirectDataContent_Clone               RT_MANGLER(RTCrSpcIndirectDataContent_Clone)
+# define RTCrSpcIndirectDataContent_Init                RT_MANGLER(RTCrSpcIndirectDataContent_Init)
+# define RTCrSpcLink_Clone                              RT_MANGLER(RTCrSpcLink_Clone)
+# define RTCrSpcLink_Init                               RT_MANGLER(RTCrSpcLink_Init)
+# define RTCrSpcPeImageData_Clone                       RT_MANGLER(RTCrSpcPeImageData_Clone)
+# define RTCrSpcPeImageData_Init                        RT_MANGLER(RTCrSpcPeImageData_Init)
+# define RTCrSpcSerializedObjectAttribute_Clone         RT_MANGLER(RTCrSpcSerializedObjectAttribute_Clone)
+# define RTCrSpcSerializedObjectAttribute_Init          RT_MANGLER(RTCrSpcSerializedObjectAttribute_Init)
+# define RTCrSpcSerializedObjectAttributes_Clone        RT_MANGLER(RTCrSpcSerializedObjectAttributes_Clone)
+# define RTCrSpcSerializedObjectAttributes_Init         RT_MANGLER(RTCrSpcSerializedObjectAttributes_Init)
+# define RTCrSpcSerializedObject_Clone                  RT_MANGLER(RTCrSpcSerializedObject_Clone)
+# define RTCrSpcSerializedObject_Init                   RT_MANGLER(RTCrSpcSerializedObject_Init)
+# define RTCrSpcSerializedPageHashes_Clone              RT_MANGLER(RTCrSpcSerializedPageHashes_Clone)
+# define RTCrSpcSerializedPageHashes_Init               RT_MANGLER(RTCrSpcSerializedPageHashes_Init)
+# define RTCrSpcString_Clone                            RT_MANGLER(RTCrSpcString_Clone)
+# define RTCrSpcString_Init                             RT_MANGLER(RTCrSpcString_Init)
+# define RTCrSpcAttributeTypeAndOptionalValue_CheckSanity RT_MANGLER(RTCrSpcAttributeTypeAndOptionalValue_CheckSanity)
+# define RTCrSpcIndirectDataContent_CheckSanity         RT_MANGLER(RTCrSpcIndirectDataContent_CheckSanity)
+# define RTCrSpcIndirectDataContent_CheckSanityEx       RT_MANGLER(RTCrSpcIndirectDataContent_CheckSanityEx)
+# define RTCrSpcLink_CheckSanity                        RT_MANGLER(RTCrSpcLink_CheckSanity)
+# define RTCrSpcPeImageData_CheckSanity                 RT_MANGLER(RTCrSpcPeImageData_CheckSanity)
+# define RTCrSpcSerializedObjectAttribute_CheckSanity   RT_MANGLER(RTCrSpcSerializedObjectAttribute_CheckSanity)
+# define RTCrSpcSerializedObjectAttributes_CheckSanity  RT_MANGLER(RTCrSpcSerializedObjectAttributes_CheckSanity)
+# define RTCrSpcSerializedObject_CheckSanity            RT_MANGLER(RTCrSpcSerializedObject_CheckSanity)
+# define RTCrSpcSerializedPageHashes_CheckSanity        RT_MANGLER(RTCrSpcSerializedPageHashes_CheckSanity)
+# define RTCrSpcString_CheckSanity                      RT_MANGLER(RTCrSpcString_CheckSanity)
+# define RTCrX509AlgorithmIdentifier_DecodeAsn1         RT_MANGLER(RTCrX509AlgorithmIdentifier_DecodeAsn1)
+# define RTCrX509AlgorithmIdentifiers_DecodeAsn1        RT_MANGLER(RTCrX509AlgorithmIdentifiers_DecodeAsn1)
+# define RTCrX509AttributeTypeAndValue_DecodeAsn1       RT_MANGLER(RTCrX509AttributeTypeAndValue_DecodeAsn1)
+# define RTCrX509AttributeTypeAndValues_DecodeAsn1      RT_MANGLER(RTCrX509AttributeTypeAndValues_DecodeAsn1)
+# define RTCrX509AuthorityKeyIdentifier_DecodeAsn1      RT_MANGLER(RTCrX509AuthorityKeyIdentifier_DecodeAsn1)
+# define RTCrX509BasicConstraints_DecodeAsn1            RT_MANGLER(RTCrX509BasicConstraints_DecodeAsn1)
+# define RTCrX509CertificatePolicies_DecodeAsn1         RT_MANGLER(RTCrX509CertificatePolicies_DecodeAsn1)
+# define RTCrX509Certificate_DecodeAsn1                 RT_MANGLER(RTCrX509Certificate_DecodeAsn1)
+# define RTCrX509Certificates_DecodeAsn1                RT_MANGLER(RTCrX509Certificates_DecodeAsn1)
+# define RTCrX509Extension_DecodeAsn1                   RT_MANGLER(RTCrX509Extension_DecodeAsn1)
+# define RTCrX509Extension_ExtnValue_DecodeAsn1         RT_MANGLER(RTCrX509Extension_ExtnValue_DecodeAsn1)
+# define RTCrX509Extensions_DecodeAsn1                  RT_MANGLER(RTCrX509Extensions_DecodeAsn1)
+# define RTCrX509GeneralName_DecodeAsn1                 RT_MANGLER(RTCrX509GeneralName_DecodeAsn1)
+# define RTCrX509GeneralNames_DecodeAsn1                RT_MANGLER(RTCrX509GeneralNames_DecodeAsn1)
+# define RTCrX509GeneralSubtree_DecodeAsn1              RT_MANGLER(RTCrX509GeneralSubtree_DecodeAsn1)
+# define RTCrX509GeneralSubtrees_DecodeAsn1             RT_MANGLER(RTCrX509GeneralSubtrees_DecodeAsn1)
+# define RTCrX509NameConstraints_DecodeAsn1             RT_MANGLER(RTCrX509NameConstraints_DecodeAsn1)
+# define RTCrX509Name_DecodeAsn1                        RT_MANGLER(RTCrX509Name_DecodeAsn1)
+# define RTCrX509OldAuthorityKeyIdentifier_DecodeAsn1   RT_MANGLER(RTCrX509OldAuthorityKeyIdentifier_DecodeAsn1)
+# define RTCrX509OtherName_DecodeAsn1                   RT_MANGLER(RTCrX509OtherName_DecodeAsn1)
+# define RTCrX509PolicyConstraints_DecodeAsn1           RT_MANGLER(RTCrX509PolicyConstraints_DecodeAsn1)
+# define RTCrX509PolicyInformation_DecodeAsn1           RT_MANGLER(RTCrX509PolicyInformation_DecodeAsn1)
+# define RTCrX509PolicyMapping_DecodeAsn1               RT_MANGLER(RTCrX509PolicyMapping_DecodeAsn1)
+# define RTCrX509PolicyMappings_DecodeAsn1              RT_MANGLER(RTCrX509PolicyMappings_DecodeAsn1)
+# define RTCrX509PolicyQualifierInfo_DecodeAsn1         RT_MANGLER(RTCrX509PolicyQualifierInfo_DecodeAsn1)
+# define RTCrX509PolicyQualifierInfos_DecodeAsn1        RT_MANGLER(RTCrX509PolicyQualifierInfos_DecodeAsn1)
+# define RTCrX509SubjectPublicKeyInfo_DecodeAsn1        RT_MANGLER(RTCrX509SubjectPublicKeyInfo_DecodeAsn1)
+# define RTCrX509TbsCertificate_DecodeAsn1              RT_MANGLER(RTCrX509TbsCertificate_DecodeAsn1)
+# define RTCrX509Validity_DecodeAsn1                    RT_MANGLER(RTCrX509Validity_DecodeAsn1)
+# define RTCrX509CertPathsBuild                         RT_MANGLER(RTCrX509CertPathsBuild)
+# define RTCrX509CertPathsCreate                        RT_MANGLER(RTCrX509CertPathsCreate)
+# define RTCrX509CertPathsCreateEx                      RT_MANGLER(RTCrX509CertPathsCreateEx)
+# define RTCrX509CertPathsDumpAll                       RT_MANGLER(RTCrX509CertPathsDumpAll)
+# define RTCrX509CertPathsDumpOne                       RT_MANGLER(RTCrX509CertPathsDumpOne)
+# define RTCrX509CertPathsGetPathCount                  RT_MANGLER(RTCrX509CertPathsGetPathCount)
+# define RTCrX509CertPathsGetPathLength                 RT_MANGLER(RTCrX509CertPathsGetPathLength)
+# define RTCrX509CertPathsGetPathNodeCert               RT_MANGLER(RTCrX509CertPathsGetPathNodeCert)
+# define RTCrX509CertPathsGetPathVerifyResult           RT_MANGLER(RTCrX509CertPathsGetPathVerifyResult)
+# define RTCrX509CertPathsQueryPathInfo                 RT_MANGLER(RTCrX509CertPathsQueryPathInfo)
+# define RTCrX509CertPathsRelease                       RT_MANGLER(RTCrX509CertPathsRelease)
+# define RTCrX509CertPathsRetain                        RT_MANGLER(RTCrX509CertPathsRetain)
+# define RTCrX509CertPathsSetTrustedStore               RT_MANGLER(RTCrX509CertPathsSetTrustedStore)
+# define RTCrX509CertPathsSetUntrustedArray             RT_MANGLER(RTCrX509CertPathsSetUntrustedArray)
+# define RTCrX509CertPathsSetUntrustedSet               RT_MANGLER(RTCrX509CertPathsSetUntrustedSet)
+# define RTCrX509CertPathsSetUntrustedStore             RT_MANGLER(RTCrX509CertPathsSetUntrustedStore)
+# define RTCrX509CertPathsSetValidTime                  RT_MANGLER(RTCrX509CertPathsSetValidTime)
+# define RTCrX509CertPathsSetValidTimeSpec              RT_MANGLER(RTCrX509CertPathsSetValidTimeSpec)
+# define RTCrX509CertPathsValidateAll                   RT_MANGLER(RTCrX509CertPathsValidateAll)
+# define RTCrX509CertPathsValidateOne                   RT_MANGLER(RTCrX509CertPathsValidateOne)
+# define RTCrX509AlgorithmIdentifier_CombineEncryptionAndDigest             RT_MANGLER(RTCrX509AlgorithmIdentifier_CombineEncryptionAndDigest)
+# define RTCrX509AlgorithmIdentifier_CombineEncryptionOidAndDigestOid       RT_MANGLER(RTCrX509AlgorithmIdentifier_CombineEncryptionOidAndDigestOid)
+# define RTCrX509AlgorithmIdentifier_Compare                                RT_MANGLER(RTCrX509AlgorithmIdentifier_Compare)
+# define RTCrX509AlgorithmIdentifier_CompareDigestAndEncryptedDigest        RT_MANGLER(RTCrX509AlgorithmIdentifier_CompareDigestAndEncryptedDigest)
+# define RTCrX509AlgorithmIdentifier_CompareDigestOidAndEncryptedDigestOid  RT_MANGLER(RTCrX509AlgorithmIdentifier_CompareDigestOidAndEncryptedDigestOid)
+# define RTCrX509AlgorithmIdentifier_CompareWithString  RT_MANGLER(RTCrX509AlgorithmIdentifier_CompareWithString)
+# define RTCrX509AlgorithmIdentifier_Delete             RT_MANGLER(RTCrX509AlgorithmIdentifier_Delete)
+# define RTCrX509AlgorithmIdentifier_Enum               RT_MANGLER(RTCrX509AlgorithmIdentifier_Enum)
+# define RTCrX509AlgorithmIdentifier_QueryDigestSize    RT_MANGLER(RTCrX509AlgorithmIdentifier_QueryDigestSize)
+# define RTCrX509AlgorithmIdentifier_QueryDigestType    RT_MANGLER(RTCrX509AlgorithmIdentifier_QueryDigestType)
+# define RTCrX509AlgorithmIdentifiers_Compare           RT_MANGLER(RTCrX509AlgorithmIdentifiers_Compare)
+# define RTCrX509AlgorithmIdentifiers_Delete            RT_MANGLER(RTCrX509AlgorithmIdentifiers_Delete)
+# define RTCrX509AlgorithmIdentifiers_Enum              RT_MANGLER(RTCrX509AlgorithmIdentifiers_Enum)
+# define RTCrX509AttributeTypeAndValue_Compare          RT_MANGLER(RTCrX509AttributeTypeAndValue_Compare)
+# define RTCrX509AttributeTypeAndValue_Delete           RT_MANGLER(RTCrX509AttributeTypeAndValue_Delete)
+# define RTCrX509AttributeTypeAndValue_Enum             RT_MANGLER(RTCrX509AttributeTypeAndValue_Enum)
+# define RTCrX509AttributeTypeAndValues_Compare         RT_MANGLER(RTCrX509AttributeTypeAndValues_Compare)
+# define RTCrX509AttributeTypeAndValues_Delete          RT_MANGLER(RTCrX509AttributeTypeAndValues_Delete)
+# define RTCrX509AttributeTypeAndValues_Enum            RT_MANGLER(RTCrX509AttributeTypeAndValues_Enum)
+# define RTCrX509AuthorityKeyIdentifier_Compare         RT_MANGLER(RTCrX509AuthorityKeyIdentifier_Compare)
+# define RTCrX509AuthorityKeyIdentifier_Delete          RT_MANGLER(RTCrX509AuthorityKeyIdentifier_Delete)
+# define RTCrX509AuthorityKeyIdentifier_Enum            RT_MANGLER(RTCrX509AuthorityKeyIdentifier_Enum)
+# define RTCrX509BasicConstraints_Compare               RT_MANGLER(RTCrX509BasicConstraints_Compare)
+# define RTCrX509BasicConstraints_Delete                RT_MANGLER(RTCrX509BasicConstraints_Delete)
+# define RTCrX509BasicConstraints_Enum                  RT_MANGLER(RTCrX509BasicConstraints_Enum)
+# define RTCrX509CertificatePolicies_Compare            RT_MANGLER(RTCrX509CertificatePolicies_Compare)
+# define RTCrX509CertificatePolicies_Delete             RT_MANGLER(RTCrX509CertificatePolicies_Delete)
+# define RTCrX509CertificatePolicies_Enum               RT_MANGLER(RTCrX509CertificatePolicies_Enum)
+# define RTCrX509Certificate_Compare                    RT_MANGLER(RTCrX509Certificate_Compare)
+# define RTCrX509Certificate_Delete                     RT_MANGLER(RTCrX509Certificate_Delete)
+# define RTCrX509Certificate_Enum                       RT_MANGLER(RTCrX509Certificate_Enum)
+# define RTCrX509Certificate_IsSelfSigned               RT_MANGLER(RTCrX509Certificate_IsSelfSigned)
+# define RTCrX509Certificate_MatchIssuerAndSerialNumber RT_MANGLER(RTCrX509Certificate_MatchIssuerAndSerialNumber)
+# define RTCrX509Certificate_MatchSubjectOrAltSubjectByRfc5280 RT_MANGLER(RTCrX509Certificate_MatchSubjectOrAltSubjectByRfc5280)
+# define RTCrX509Certificates_Compare                   RT_MANGLER(RTCrX509Certificates_Compare)
+# define RTCrX509Certificates_Delete                    RT_MANGLER(RTCrX509Certificates_Delete)
+# define RTCrX509Certificates_Enum                      RT_MANGLER(RTCrX509Certificates_Enum)
+# define RTCrX509Certificates_FindByIssuerAndSerialNumber RT_MANGLER(RTCrX509Certificates_FindByIssuerAndSerialNumber)
+# define RTCrX509Extension_Compare                      RT_MANGLER(RTCrX509Extension_Compare)
+# define RTCrX509Extension_Delete                       RT_MANGLER(RTCrX509Extension_Delete)
+# define RTCrX509Extension_Enum                         RT_MANGLER(RTCrX509Extension_Enum)
+# define RTCrX509Extensions_Compare                     RT_MANGLER(RTCrX509Extensions_Compare)
+# define RTCrX509Extensions_Delete                      RT_MANGLER(RTCrX509Extensions_Delete)
+# define RTCrX509Extensions_Enum                        RT_MANGLER(RTCrX509Extensions_Enum)
+# define RTCrX509GeneralName_Compare                    RT_MANGLER(RTCrX509GeneralName_Compare)
+# define RTCrX509GeneralName_ConstraintMatch            RT_MANGLER(RTCrX509GeneralName_ConstraintMatch)
+# define RTCrX509GeneralName_Delete                     RT_MANGLER(RTCrX509GeneralName_Delete)
+# define RTCrX509GeneralName_Enum                       RT_MANGLER(RTCrX509GeneralName_Enum)
+# define RTCrX509GeneralNames_Compare                   RT_MANGLER(RTCrX509GeneralNames_Compare)
+# define RTCrX509GeneralNames_Delete                    RT_MANGLER(RTCrX509GeneralNames_Delete)
+# define RTCrX509GeneralNames_Enum                      RT_MANGLER(RTCrX509GeneralNames_Enum)
+# define RTCrX509GeneralSubtree_Compare                 RT_MANGLER(RTCrX509GeneralSubtree_Compare)
+# define RTCrX509GeneralSubtree_ConstraintMatch         RT_MANGLER(RTCrX509GeneralSubtree_ConstraintMatch)
+# define RTCrX509GeneralSubtree_Delete                  RT_MANGLER(RTCrX509GeneralSubtree_Delete)
+# define RTCrX509GeneralSubtree_Enum                    RT_MANGLER(RTCrX509GeneralSubtree_Enum)
+# define RTCrX509GeneralSubtrees_Compare                RT_MANGLER(RTCrX509GeneralSubtrees_Compare)
+# define RTCrX509GeneralSubtrees_Delete                 RT_MANGLER(RTCrX509GeneralSubtrees_Delete)
+# define RTCrX509GeneralSubtrees_Enum                   RT_MANGLER(RTCrX509GeneralSubtrees_Enum)
+# define RTCrX509NameConstraints_Compare                RT_MANGLER(RTCrX509NameConstraints_Compare)
+# define RTCrX509NameConstraints_Delete                 RT_MANGLER(RTCrX509NameConstraints_Delete)
+# define RTCrX509NameConstraints_Enum                   RT_MANGLER(RTCrX509NameConstraints_Enum)
+# define RTCrX509Name_Compare                           RT_MANGLER(RTCrX509Name_Compare)
+# define RTCrX509Name_ConstraintMatch                   RT_MANGLER(RTCrX509Name_ConstraintMatch)
+# define RTCrX509Name_Delete                            RT_MANGLER(RTCrX509Name_Delete)
+# define RTCrX509Name_Enum                              RT_MANGLER(RTCrX509Name_Enum)
+# define RTCrX509Name_FormatAsString                    RT_MANGLER(RTCrX509Name_FormatAsString)
+# define RTCrX509Name_MatchByRfc5280                    RT_MANGLER(RTCrX509Name_MatchByRfc5280)
+# define RTCrX509Name_MatchWithString                   RT_MANGLER(RTCrX509Name_MatchWithString)
+# define RTCrX509Name_GetShortRdn                       RT_MANGLER(RTCrX509Name_GetShortRdn)
+# define RTCrX509OldAuthorityKeyIdentifier_Compare      RT_MANGLER(RTCrX509OldAuthorityKeyIdentifier_Compare)
+# define RTCrX509OldAuthorityKeyIdentifier_Delete       RT_MANGLER(RTCrX509OldAuthorityKeyIdentifier_Delete)
+# define RTCrX509OldAuthorityKeyIdentifier_Enum         RT_MANGLER(RTCrX509OldAuthorityKeyIdentifier_Enum)
+# define RTCrX509OtherName_Compare                      RT_MANGLER(RTCrX509OtherName_Compare)
+# define RTCrX509OtherName_Delete                       RT_MANGLER(RTCrX509OtherName_Delete)
+# define RTCrX509OtherName_Enum                         RT_MANGLER(RTCrX509OtherName_Enum)
+# define RTCrX509PolicyConstraints_Compare              RT_MANGLER(RTCrX509PolicyConstraints_Compare)
+# define RTCrX509PolicyConstraints_Delete               RT_MANGLER(RTCrX509PolicyConstraints_Delete)
+# define RTCrX509PolicyConstraints_Enum                 RT_MANGLER(RTCrX509PolicyConstraints_Enum)
+# define RTCrX509PolicyInformation_Compare              RT_MANGLER(RTCrX509PolicyInformation_Compare)
+# define RTCrX509PolicyInformation_Delete               RT_MANGLER(RTCrX509PolicyInformation_Delete)
+# define RTCrX509PolicyInformation_Enum                 RT_MANGLER(RTCrX509PolicyInformation_Enum)
+# define RTCrX509PolicyMapping_Compare                  RT_MANGLER(RTCrX509PolicyMapping_Compare)
+# define RTCrX509PolicyMapping_Delete                   RT_MANGLER(RTCrX509PolicyMapping_Delete)
+# define RTCrX509PolicyMapping_Enum                     RT_MANGLER(RTCrX509PolicyMapping_Enum)
+# define RTCrX509PolicyMappings_Compare                 RT_MANGLER(RTCrX509PolicyMappings_Compare)
+# define RTCrX509PolicyMappings_Delete                  RT_MANGLER(RTCrX509PolicyMappings_Delete)
+# define RTCrX509PolicyMappings_Enum                    RT_MANGLER(RTCrX509PolicyMappings_Enum)
+# define RTCrX509PolicyQualifierInfo_Compare            RT_MANGLER(RTCrX509PolicyQualifierInfo_Compare)
+# define RTCrX509PolicyQualifierInfo_Delete             RT_MANGLER(RTCrX509PolicyQualifierInfo_Delete)
+# define RTCrX509PolicyQualifierInfo_Enum               RT_MANGLER(RTCrX509PolicyQualifierInfo_Enum)
+# define RTCrX509PolicyQualifierInfos_Compare           RT_MANGLER(RTCrX509PolicyQualifierInfos_Compare)
+# define RTCrX509PolicyQualifierInfos_Delete            RT_MANGLER(RTCrX509PolicyQualifierInfos_Delete)
+# define RTCrX509PolicyQualifierInfos_Enum              RT_MANGLER(RTCrX509PolicyQualifierInfos_Enum)
+# define RTCrX509SubjectPublicKeyInfo_Compare           RT_MANGLER(RTCrX509SubjectPublicKeyInfo_Compare)
+# define RTCrX509SubjectPublicKeyInfo_Delete            RT_MANGLER(RTCrX509SubjectPublicKeyInfo_Delete)
+# define RTCrX509SubjectPublicKeyInfo_Enum              RT_MANGLER(RTCrX509SubjectPublicKeyInfo_Enum)
+# define RTCrX509TbsCertificate_Compare                 RT_MANGLER(RTCrX509TbsCertificate_Compare)
+# define RTCrX509TbsCertificate_Delete                  RT_MANGLER(RTCrX509TbsCertificate_Delete)
+# define RTCrX509TbsCertificate_Enum                    RT_MANGLER(RTCrX509TbsCertificate_Enum)
+# define RTCrX509TbsCertificate_ReprocessExtensions     RT_MANGLER(RTCrX509TbsCertificate_ReprocessExtensions)
+# define RTCrX509Validity_Compare                       RT_MANGLER(RTCrX509Validity_Compare)
+# define RTCrX509Validity_Delete                        RT_MANGLER(RTCrX509Validity_Delete)
+# define RTCrX509Validity_Enum                          RT_MANGLER(RTCrX509Validity_Enum)
+# define RTCrX509Validity_IsValidAtTimeSpec             RT_MANGLER(RTCrX509Validity_IsValidAtTimeSpec)
+# define RTCrX509Certificate_ReadFromFile               RT_MANGLER(RTCrX509Certificate_ReadFromFile)
+# define RTCrX509Certificate_ReadFromBuffer             RT_MANGLER(RTCrX509Certificate_ReadFromBuffer)
+# define RTCrX509AlgorithmIdentifier_Clone              RT_MANGLER(RTCrX509AlgorithmIdentifier_Clone)
+# define RTCrX509AlgorithmIdentifier_Init               RT_MANGLER(RTCrX509AlgorithmIdentifier_Init)
+# define RTCrX509AlgorithmIdentifiers_Clone             RT_MANGLER(RTCrX509AlgorithmIdentifiers_Clone)
+# define RTCrX509AlgorithmIdentifiers_Init              RT_MANGLER(RTCrX509AlgorithmIdentifiers_Init)
+# define RTCrX509AttributeTypeAndValue_Clone            RT_MANGLER(RTCrX509AttributeTypeAndValue_Clone)
+# define RTCrX509AttributeTypeAndValue_Init             RT_MANGLER(RTCrX509AttributeTypeAndValue_Init)
+# define RTCrX509AttributeTypeAndValues_Clone           RT_MANGLER(RTCrX509AttributeTypeAndValues_Clone)
+# define RTCrX509AttributeTypeAndValues_Init            RT_MANGLER(RTCrX509AttributeTypeAndValues_Init)
+# define RTCrX509AuthorityKeyIdentifier_Clone           RT_MANGLER(RTCrX509AuthorityKeyIdentifier_Clone)
+# define RTCrX509AuthorityKeyIdentifier_Init            RT_MANGLER(RTCrX509AuthorityKeyIdentifier_Init)
+# define RTCrX509BasicConstraints_Clone                 RT_MANGLER(RTCrX509BasicConstraints_Clone)
+# define RTCrX509BasicConstraints_Init                  RT_MANGLER(RTCrX509BasicConstraints_Init)
+# define RTCrX509CertificatePolicies_Clone              RT_MANGLER(RTCrX509CertificatePolicies_Clone)
+# define RTCrX509CertificatePolicies_Init               RT_MANGLER(RTCrX509CertificatePolicies_Init)
+# define RTCrX509Certificate_Clone                      RT_MANGLER(RTCrX509Certificate_Clone)
+# define RTCrX509Certificate_Init                       RT_MANGLER(RTCrX509Certificate_Init)
+# define RTCrX509Certificates_Clone                     RT_MANGLER(RTCrX509Certificates_Clone)
+# define RTCrX509Certificates_Init                      RT_MANGLER(RTCrX509Certificates_Init)
+# define RTCrX509Extension_Clone                        RT_MANGLER(RTCrX509Extension_Clone)
+# define RTCrX509Extension_Init                         RT_MANGLER(RTCrX509Extension_Init)
+# define RTCrX509Extensions_Clone                       RT_MANGLER(RTCrX509Extensions_Clone)
+# define RTCrX509Extensions_Init                        RT_MANGLER(RTCrX509Extensions_Init)
+# define RTCrX509GeneralName_Clone                      RT_MANGLER(RTCrX509GeneralName_Clone)
+# define RTCrX509GeneralName_Init                       RT_MANGLER(RTCrX509GeneralName_Init)
+# define RTCrX509GeneralNames_Clone                     RT_MANGLER(RTCrX509GeneralNames_Clone)
+# define RTCrX509GeneralNames_Init                      RT_MANGLER(RTCrX509GeneralNames_Init)
+# define RTCrX509GeneralSubtree_Clone                   RT_MANGLER(RTCrX509GeneralSubtree_Clone)
+# define RTCrX509GeneralSubtree_Init                    RT_MANGLER(RTCrX509GeneralSubtree_Init)
+# define RTCrX509GeneralSubtrees_Clone                  RT_MANGLER(RTCrX509GeneralSubtrees_Clone)
+# define RTCrX509GeneralSubtrees_Init                   RT_MANGLER(RTCrX509GeneralSubtrees_Init)
+# define RTCrX509NameConstraints_Clone                  RT_MANGLER(RTCrX509NameConstraints_Clone)
+# define RTCrX509NameConstraints_Init                   RT_MANGLER(RTCrX509NameConstraints_Init)
+# define RTCrX509Name_Clone                             RT_MANGLER(RTCrX509Name_Clone)
+# define RTCrX509Name_Init                              RT_MANGLER(RTCrX509Name_Init)
+# define RTCrX509Name_RecodeAsUtf8                      RT_MANGLER(RTCrX509Name_RecodeAsUtf8)
+# define RTCrX509OldAuthorityKeyIdentifier_Clone        RT_MANGLER(RTCrX509OldAuthorityKeyIdentifier_Clone)
+# define RTCrX509OldAuthorityKeyIdentifier_Init         RT_MANGLER(RTCrX509OldAuthorityKeyIdentifier_Init)
+# define RTCrX509OtherName_Clone                        RT_MANGLER(RTCrX509OtherName_Clone)
+# define RTCrX509OtherName_Init                         RT_MANGLER(RTCrX509OtherName_Init)
+# define RTCrX509PolicyConstraints_Clone                RT_MANGLER(RTCrX509PolicyConstraints_Clone)
+# define RTCrX509PolicyConstraints_Init                 RT_MANGLER(RTCrX509PolicyConstraints_Init)
+# define RTCrX509PolicyInformation_Clone                RT_MANGLER(RTCrX509PolicyInformation_Clone)
+# define RTCrX509PolicyInformation_Init                 RT_MANGLER(RTCrX509PolicyInformation_Init)
+# define RTCrX509PolicyMapping_Clone                    RT_MANGLER(RTCrX509PolicyMapping_Clone)
+# define RTCrX509PolicyMapping_Init                     RT_MANGLER(RTCrX509PolicyMapping_Init)
+# define RTCrX509PolicyMappings_Clone                   RT_MANGLER(RTCrX509PolicyMappings_Clone)
+# define RTCrX509PolicyMappings_Init                    RT_MANGLER(RTCrX509PolicyMappings_Init)
+# define RTCrX509PolicyQualifierInfo_Clone              RT_MANGLER(RTCrX509PolicyQualifierInfo_Clone)
+# define RTCrX509PolicyQualifierInfo_Init               RT_MANGLER(RTCrX509PolicyQualifierInfo_Init)
+# define RTCrX509PolicyQualifierInfos_Clone             RT_MANGLER(RTCrX509PolicyQualifierInfos_Clone)
+# define RTCrX509PolicyQualifierInfos_Init              RT_MANGLER(RTCrX509PolicyQualifierInfos_Init)
+# define RTCrX509SubjectPublicKeyInfo_Clone             RT_MANGLER(RTCrX509SubjectPublicKeyInfo_Clone)
+# define RTCrX509SubjectPublicKeyInfo_Init              RT_MANGLER(RTCrX509SubjectPublicKeyInfo_Init)
+# define RTCrX509TbsCertificate_Clone                   RT_MANGLER(RTCrX509TbsCertificate_Clone)
+# define RTCrX509TbsCertificate_Init                    RT_MANGLER(RTCrX509TbsCertificate_Init)
+# define RTCrX509Validity_Clone                         RT_MANGLER(RTCrX509Validity_Clone)
+# define RTCrX509Validity_Init                          RT_MANGLER(RTCrX509Validity_Init)
+# define RTCrX509AlgorithmIdentifier_CheckSanity        RT_MANGLER(RTCrX509AlgorithmIdentifier_CheckSanity)
+# define RTCrX509AlgorithmIdentifiers_CheckSanity       RT_MANGLER(RTCrX509AlgorithmIdentifiers_CheckSanity)
+# define RTCrX509AttributeTypeAndValue_CheckSanity      RT_MANGLER(RTCrX509AttributeTypeAndValue_CheckSanity)
+# define RTCrX509AttributeTypeAndValues_CheckSanity     RT_MANGLER(RTCrX509AttributeTypeAndValues_CheckSanity)
+# define RTCrX509AuthorityKeyIdentifier_CheckSanity     RT_MANGLER(RTCrX509AuthorityKeyIdentifier_CheckSanity)
+# define RTCrX509BasicConstraints_CheckSanity           RT_MANGLER(RTCrX509BasicConstraints_CheckSanity)
+# define RTCrX509CertificatePolicies_CheckSanity        RT_MANGLER(RTCrX509CertificatePolicies_CheckSanity)
+# define RTCrX509Certificate_CheckSanity                RT_MANGLER(RTCrX509Certificate_CheckSanity)
+# define RTCrX509Certificates_CheckSanity               RT_MANGLER(RTCrX509Certificates_CheckSanity)
+# define RTCrX509Extension_CheckSanity                  RT_MANGLER(RTCrX509Extension_CheckSanity)
+# define RTCrX509Extensions_CheckSanity                 RT_MANGLER(RTCrX509Extensions_CheckSanity)
+# define RTCrX509GeneralName_CheckSanity                RT_MANGLER(RTCrX509GeneralName_CheckSanity)
+# define RTCrX509GeneralNames_CheckSanity               RT_MANGLER(RTCrX509GeneralNames_CheckSanity)
+# define RTCrX509GeneralSubtree_CheckSanity             RT_MANGLER(RTCrX509GeneralSubtree_CheckSanity)
+# define RTCrX509GeneralSubtrees_CheckSanity            RT_MANGLER(RTCrX509GeneralSubtrees_CheckSanity)
+# define RTCrX509NameConstraints_CheckSanity            RT_MANGLER(RTCrX509NameConstraints_CheckSanity)
+# define RTCrX509Name_CheckSanity                       RT_MANGLER(RTCrX509Name_CheckSanity)
+# define RTCrX509OldAuthorityKeyIdentifier_CheckSanity  RT_MANGLER(RTCrX509OldAuthorityKeyIdentifier_CheckSanity)
+# define RTCrX509OtherName_CheckSanity                  RT_MANGLER(RTCrX509OtherName_CheckSanity)
+# define RTCrX509PolicyConstraints_CheckSanity          RT_MANGLER(RTCrX509PolicyConstraints_CheckSanity)
+# define RTCrX509PolicyInformation_CheckSanity          RT_MANGLER(RTCrX509PolicyInformation_CheckSanity)
+# define RTCrX509PolicyMapping_CheckSanity              RT_MANGLER(RTCrX509PolicyMapping_CheckSanity)
+# define RTCrX509PolicyMappings_CheckSanity             RT_MANGLER(RTCrX509PolicyMappings_CheckSanity)
+# define RTCrX509PolicyQualifierInfo_CheckSanity        RT_MANGLER(RTCrX509PolicyQualifierInfo_CheckSanity)
+# define RTCrX509PolicyQualifierInfos_CheckSanity       RT_MANGLER(RTCrX509PolicyQualifierInfos_CheckSanity)
+# define RTCrX509SubjectPublicKeyInfo_CheckSanity       RT_MANGLER(RTCrX509SubjectPublicKeyInfo_CheckSanity)
+# define RTCrX509TbsCertificate_CheckSanity             RT_MANGLER(RTCrX509TbsCertificate_CheckSanity)
+# define RTCrX509Validity_CheckSanity                   RT_MANGLER(RTCrX509Validity_CheckSanity)
+# define RTCrX509Certificate_VerifySignature            RT_MANGLER(RTCrX509Certificate_VerifySignature)
+# define RTCrX509Certificate_VerifySignatureSelfSigned  RT_MANGLER(RTCrX509Certificate_VerifySignatureSelfSigned)
+# define RTCrTafCertPathControls_DecodeAsn1             RT_MANGLER(RTCrTafCertPathControls_DecodeAsn1)
+# define RTCrTafTrustAnchorChoice_DecodeAsn1            RT_MANGLER(RTCrTafTrustAnchorChoice_DecodeAsn1)
+# define RTCrTafTrustAnchorInfo_DecodeAsn1              RT_MANGLER(RTCrTafTrustAnchorInfo_DecodeAsn1)
+# define RTCrTafTrustAnchorList_DecodeAsn1              RT_MANGLER(RTCrTafTrustAnchorList_DecodeAsn1)
+# define RTCrTafCertPathControls_Compare                RT_MANGLER(RTCrTafCertPathControls_Compare)
+# define RTCrTafCertPathControls_Delete                 RT_MANGLER(RTCrTafCertPathControls_Delete)
+# define RTCrTafCertPathControls_Enum                   RT_MANGLER(RTCrTafCertPathControls_Enum)
+# define RTCrTafTrustAnchorChoice_Compare               RT_MANGLER(RTCrTafTrustAnchorChoice_Compare)
+# define RTCrTafTrustAnchorChoice_Delete                RT_MANGLER(RTCrTafTrustAnchorChoice_Delete)
+# define RTCrTafTrustAnchorChoice_Enum                  RT_MANGLER(RTCrTafTrustAnchorChoice_Enum)
+# define RTCrTafTrustAnchorInfo_Compare                 RT_MANGLER(RTCrTafTrustAnchorInfo_Compare)
+# define RTCrTafTrustAnchorInfo_Delete                  RT_MANGLER(RTCrTafTrustAnchorInfo_Delete)
+# define RTCrTafTrustAnchorInfo_Enum                    RT_MANGLER(RTCrTafTrustAnchorInfo_Enum)
+# define RTCrTafTrustAnchorList_Compare                 RT_MANGLER(RTCrTafTrustAnchorList_Compare)
+# define RTCrTafTrustAnchorList_Delete                  RT_MANGLER(RTCrTafTrustAnchorList_Delete)
+# define RTCrTafTrustAnchorList_Enum                    RT_MANGLER(RTCrTafTrustAnchorList_Enum)
+# define RTCrTafCertPathControls_Clone                  RT_MANGLER(RTCrTafCertPathControls_Clone)
+# define RTCrTafCertPathControls_Init                   RT_MANGLER(RTCrTafCertPathControls_Init)
+# define RTCrTafTrustAnchorChoice_Clone                 RT_MANGLER(RTCrTafTrustAnchorChoice_Clone)
+# define RTCrTafTrustAnchorChoice_Init                  RT_MANGLER(RTCrTafTrustAnchorChoice_Init)
+# define RTCrTafTrustAnchorInfo_Clone                   RT_MANGLER(RTCrTafTrustAnchorInfo_Clone)
+# define RTCrTafTrustAnchorInfo_Init                    RT_MANGLER(RTCrTafTrustAnchorInfo_Init)
+# define RTCrTafTrustAnchorList_Clone                   RT_MANGLER(RTCrTafTrustAnchorList_Clone)
+# define RTCrTafTrustAnchorList_Init                    RT_MANGLER(RTCrTafTrustAnchorList_Init)
+# define RTCrTafCertPathControls_CheckSanity            RT_MANGLER(RTCrTafCertPathControls_CheckSanity)
+# define RTCrTafTrustAnchorChoice_CheckSanity           RT_MANGLER(RTCrTafTrustAnchorChoice_CheckSanity)
+# define RTCrTafTrustAnchorInfo_CheckSanity             RT_MANGLER(RTCrTafTrustAnchorInfo_CheckSanity)
+# define RTCrTafTrustAnchorList_CheckSanity             RT_MANGLER(RTCrTafTrustAnchorList_CheckSanity)
+# define RTCrTspAccuracy_CheckSanity                    RT_MANGLER(RTCrTspAccuracy_CheckSanity)
+# define RTCrTspAccuracy_Clone                          RT_MANGLER(RTCrTspAccuracy_Clone)
+# define RTCrTspAccuracy_Compare                        RT_MANGLER(RTCrTspAccuracy_Compare)
+# define RTCrTspAccuracy_DecodeAsn1                     RT_MANGLER(RTCrTspAccuracy_DecodeAsn1)
+# define RTCrTspAccuracy_Delete                         RT_MANGLER(RTCrTspAccuracy_Delete)
+# define RTCrTspAccuracy_Enum                           RT_MANGLER(RTCrTspAccuracy_Enum)
+# define RTCrTspAccuracy_Init                           RT_MANGLER(RTCrTspAccuracy_Init)
+# define RTCrTspMessageImprint_CheckSanity              RT_MANGLER(RTCrTspMessageImprint_CheckSanity)
+# define RTCrTspMessageImprint_Clone                    RT_MANGLER(RTCrTspMessageImprint_Clone)
+# define RTCrTspMessageImprint_Compare                  RT_MANGLER(RTCrTspMessageImprint_Compare)
+# define RTCrTspMessageImprint_DecodeAsn1               RT_MANGLER(RTCrTspMessageImprint_DecodeAsn1)
+# define RTCrTspMessageImprint_Delete                   RT_MANGLER(RTCrTspMessageImprint_Delete)
+# define RTCrTspMessageImprint_Enum                     RT_MANGLER(RTCrTspMessageImprint_Enum)
+# define RTCrTspMessageImprint_Init                     RT_MANGLER(RTCrTspMessageImprint_Init)
+# define RTCrTspTstInfo_CheckSanity                     RT_MANGLER(RTCrTspTstInfo_CheckSanity)
+# define RTCrTspTstInfo_Clone                           RT_MANGLER(RTCrTspTstInfo_Clone)
+# define RTCrTspTstInfo_Compare                         RT_MANGLER(RTCrTspTstInfo_Compare)
+# define RTCrTspTstInfo_DecodeAsn1                      RT_MANGLER(RTCrTspTstInfo_DecodeAsn1)
+# define RTCrTspTstInfo_Delete                          RT_MANGLER(RTCrTspTstInfo_Delete)
+# define RTCrTspTstInfo_Enum                            RT_MANGLER(RTCrTspTstInfo_Enum)
+# define RTCrTspTstInfo_Init                            RT_MANGLER(RTCrTspTstInfo_Init)
+# define RTCrCertCtxRelease                             RT_MANGLER(RTCrCertCtxRelease)
+# define RTCrCertCtxRetain                              RT_MANGLER(RTCrCertCtxRetain)
+# define RTCrStoreCertAddEncoded                        RT_MANGLER(RTCrStoreCertAddEncoded)
+# define RTCrStoreCertByIssuerAndSerialNo               RT_MANGLER(RTCrStoreCertByIssuerAndSerialNo)
+# define RTCrStoreCertCount                             RT_MANGLER(RTCrStoreCertCount)
+# define RTCrStoreCertFindAll                           RT_MANGLER(RTCrStoreCertFindAll)
+# define RTCrStoreCertFindBySubjectOrAltSubjectByRfc5280 RT_MANGLER(RTCrStoreCertFindBySubjectOrAltSubjectByRfc5280)
+# define RTCrStoreCertSearchDestroy                     RT_MANGLER(RTCrStoreCertSearchDestroy)
+# define RTCrStoreCertSearchNext                        RT_MANGLER(RTCrStoreCertSearchNext)
+# define RTCrStoreConvertToOpenSslCertStack             RT_MANGLER(RTCrStoreConvertToOpenSslCertStack)
+# define RTCrStoreConvertToOpenSslCertStore             RT_MANGLER(RTCrStoreConvertToOpenSslCertStore)
+# define RTCrStoreRelease                               RT_MANGLER(RTCrStoreRelease)
+# define RTCrStoreRetain                                RT_MANGLER(RTCrStoreRetain)
+# define RTCrStoreCreateInMem                           RT_MANGLER(RTCrStoreCreateInMem)
+# define RTCrStoreCreateSnapshotById                    RT_MANGLER(RTCrStoreCreateSnapshotById)
+# define RTCrStoreCreateSnapshotOfUserAndSystemTrustedCAsAndCerts RT_MANGLER(RTCrStoreCreateSnapshotOfUserAndSystemTrustedCAsAndCerts)
+# define RTCrStoreCertAddFromDir                        RT_MANGLER(RTCrStoreCertAddFromDir)
+# define RTCrStoreCertAddFromFile                       RT_MANGLER(RTCrStoreCertAddFromFile)
+# define RTCrStoreCertAddFromJavaKeyStore               RT_MANGLER(RTCrStoreCertAddFromJavaKeyStore)
+# define RTCrStoreCertAddFromJavaKeyStoreInMem          RT_MANGLER(RTCrStoreCertAddFromJavaKeyStoreInMem)
+# define RTCrStoreCertAddFromStore                      RT_MANGLER(RTCrStoreCertAddFromStore)
+# define RTCrStoreCertAddWantedFromDir                  RT_MANGLER(RTCrStoreCertAddWantedFromDir)
+# define RTCrStoreCertAddWantedFromFile                 RT_MANGLER(RTCrStoreCertAddWantedFromFile)
+# define RTCrStoreCertAddWantedFromStore                RT_MANGLER(RTCrStoreCertAddWantedFromStore)
+# define RTCrStoreCertAddWantedFromFishingExpedition    RT_MANGLER(RTCrStoreCertAddWantedFromFishingExpedition)
+# define RTCrStoreCertCheckWanted                       RT_MANGLER(RTCrStoreCertCheckWanted)
+# define RTCrStoreCertExportAsPem                       RT_MANGLER(RTCrStoreCertExportAsPem)
+# define RTErrInfoAdd                                   RT_MANGLER(RTErrInfoAdd)
+# define RTErrInfoAddF                                  RT_MANGLER(RTErrInfoAddF)
+# define RTErrInfoAddV                                  RT_MANGLER(RTErrInfoAddV)
+# define RTLdrHashImage                                 RT_MANGLER(RTLdrHashImage)
+# define RTLdrOpenWithReader                            RT_MANGLER(RTLdrOpenWithReader)
+# define RTLdrQueryPropEx                               RT_MANGLER(RTLdrQueryPropEx)
+# define RTLdrVerifySignature                           RT_MANGLER(RTLdrVerifySignature)
+# define RTBigNumAdd                                    RT_MANGLER(RTBigNumAdd)
+# define RTBigNumAssign                                 RT_MANGLER(RTBigNumAssign)
+# define RTBigNumBitWidth                               RT_MANGLER(RTBigNumBitWidth)
+# define RTBigNumByteWidth                              RT_MANGLER(RTBigNumByteWidth)
+# define RTBigNumClone                                  RT_MANGLER(RTBigNumClone)
+# define RTBigNumCompare                                RT_MANGLER(RTBigNumCompare)
+# define RTBigNumCompareWithS64                         RT_MANGLER(RTBigNumCompareWithS64)
+# define RTBigNumCompareWithU64                         RT_MANGLER(RTBigNumCompareWithU64)
+# define RTBigNumDestroy                                RT_MANGLER(RTBigNumDestroy)
+# define RTBigNumDivide                                 RT_MANGLER(RTBigNumDivide)
+# define RTBigNumDivideKnuth                            RT_MANGLER(RTBigNumDivideKnuth)
+# define RTBigNumDivideLong                             RT_MANGLER(RTBigNumDivideLong)
+# define RTBigNumExponentiate                           RT_MANGLER(RTBigNumExponentiate)
+# define RTBigNumInit                                   RT_MANGLER(RTBigNumInit)
+# define RTBigNumInitZero                               RT_MANGLER(RTBigNumInitZero)
+# define RTBigNumModExp                                 RT_MANGLER(RTBigNumModExp)
+# define RTBigNumModulo                                 RT_MANGLER(RTBigNumModulo)
+# define RTBigNumMultiply                               RT_MANGLER(RTBigNumMultiply)
+# define RTBigNumNegate                                 RT_MANGLER(RTBigNumNegate)
+# define RTBigNumNegateThis                             RT_MANGLER(RTBigNumNegateThis)
+# define RTBigNumShiftLeft                              RT_MANGLER(RTBigNumShiftLeft)
+# define RTBigNumShiftRight                             RT_MANGLER(RTBigNumShiftRight)
+# define RTBigNumSubtract                               RT_MANGLER(RTBigNumSubtract)
+# define RTBigNumToBytesBigEndian                       RT_MANGLER(RTBigNumToBytesBigEndian)
+# define RTUInt128MulByU64                              RT_MANGLER(RTUInt128MulByU64)
+# define RTUInt128MulByU64_EndProc                      RT_MANGLER(RTUInt128MulByU64_EndProc)
+# define RTUtf16Copy                                    RT_MANGLER(RTUtf16Copy)
+# define RTUtf16CopyAscii                               RT_MANGLER(RTUtf16CopyAscii)
+# define RTUtf16Cat                                     RT_MANGLER(RTUtf16Cat)
+# define RTUtf16CatAscii                                RT_MANGLER(RTUtf16CatAscii)
+# define RTUtf16End                                     RT_MANGLER(RTUtf16End)
+# define RTUtf16ICmpAscii                               RT_MANGLER(RTUtf16ICmpAscii)
+# define RTUtf16NICmpAscii                              RT_MANGLER(RTUtf16NICmpAscii)
+# define RTUtf16NLen                                    RT_MANGLER(RTUtf16NLen)
+# define RTUtf16NLenEx                                  RT_MANGLER(RTUtf16NLenEx)
+# define RTUtf16PrintHexBytes                           RT_MANGLER(RTUtf16PrintHexBytes)
+# define RTMemSaferAllocZExTag                          RT_MANGLER(RTMemSaferAllocZExTag)
+# define RTMemSaferAllocZTag                            RT_MANGLER(RTMemSaferAllocZTag)
+# define RTMemSaferFree                                 RT_MANGLER(RTMemSaferFree)
+# define RTMemSaferReallocZExTag                        RT_MANGLER(RTMemSaferReallocZExTag)
+# define RTMemSaferReallocZTag                          RT_MANGLER(RTMemSaferReallocZTag)
+# define RTMemSaferScramble                             RT_MANGLER(RTMemSaferScramble)
+# define RTMemSaferUnscramble                           RT_MANGLER(RTMemSaferUnscramble)
+# define RTErrConvertFromDarwin                         RT_MANGLER(RTErrConvertFromDarwin)
+# define RTErrConvertFromDarwinCOM                      RT_MANGLER(RTErrConvertFromDarwinCOM)
+# define RTErrConvertFromDarwinIO                       RT_MANGLER(RTErrConvertFromDarwinIO)
+# define RTErrConvertFromDarwinKern                     RT_MANGLER(RTErrConvertFromDarwinKern)
+# define RTErrConvertFromDarwin                         RT_MANGLER(RTErrConvertFromDarwin)
+# define RTErrConvertFromDarwinIO                       RT_MANGLER(RTErrConvertFromDarwinIO)
+# define RTErrConvertFromDarwinKern                     RT_MANGLER(RTErrConvertFromDarwinKern)
+
+# define RTAsn1SeqOfBitStrings_Erase                    RT_MANGLER(RTAsn1SeqOfBitStrings_Erase)
+# define RTAsn1SeqOfBitStrings_InsertEx                 RT_MANGLER(RTAsn1SeqOfBitStrings_InsertEx)
+# define RTAsn1SeqOfBooleans_Erase                      RT_MANGLER(RTAsn1SeqOfBooleans_Erase)
+# define RTAsn1SeqOfBooleans_InsertEx                   RT_MANGLER(RTAsn1SeqOfBooleans_InsertEx)
+# define RTAsn1SeqOfCores_Erase                         RT_MANGLER(RTAsn1SeqOfCores_Erase)
+# define RTAsn1SeqOfCores_InsertEx                      RT_MANGLER(RTAsn1SeqOfCores_InsertEx)
+# define RTAsn1SeqOfIntegers_Erase                      RT_MANGLER(RTAsn1SeqOfIntegers_Erase)
+# define RTAsn1SeqOfIntegers_InsertEx                   RT_MANGLER(RTAsn1SeqOfIntegers_InsertEx)
+# define RTAsn1SeqOfObjIds_Erase                        RT_MANGLER(RTAsn1SeqOfObjIds_Erase)
+# define RTAsn1SeqOfObjIds_InsertEx                     RT_MANGLER(RTAsn1SeqOfObjIds_InsertEx)
+# define RTAsn1SeqOfOctetStrings_Erase                  RT_MANGLER(RTAsn1SeqOfOctetStrings_Erase)
+# define RTAsn1SeqOfOctetStrings_InsertEx               RT_MANGLER(RTAsn1SeqOfOctetStrings_InsertEx)
+# define RTAsn1SeqOfStrings_Erase                       RT_MANGLER(RTAsn1SeqOfStrings_Erase)
+# define RTAsn1SeqOfStrings_InsertEx                    RT_MANGLER(RTAsn1SeqOfStrings_InsertEx)
+# define RTAsn1SeqOfTimes_Erase                         RT_MANGLER(RTAsn1SeqOfTimes_Erase)
+# define RTAsn1SeqOfTimes_InsertEx                      RT_MANGLER(RTAsn1SeqOfTimes_InsertEx)
+# define RTAsn1SetOfBitStrings_Erase                    RT_MANGLER(RTAsn1SetOfBitStrings_Erase)
+# define RTAsn1SetOfBitStrings_InsertEx                 RT_MANGLER(RTAsn1SetOfBitStrings_InsertEx)
+# define RTAsn1SetOfBooleans_Erase                      RT_MANGLER(RTAsn1SetOfBooleans_Erase)
+# define RTAsn1SetOfBooleans_InsertEx                   RT_MANGLER(RTAsn1SetOfBooleans_InsertEx)
+# define RTAsn1SetOfCores_Erase                         RT_MANGLER(RTAsn1SetOfCores_Erase)
+# define RTAsn1SetOfCores_InsertEx                      RT_MANGLER(RTAsn1SetOfCores_InsertEx)
+# define RTAsn1SetOfIntegers_Erase                      RT_MANGLER(RTAsn1SetOfIntegers_Erase)
+# define RTAsn1SetOfIntegers_InsertEx                   RT_MANGLER(RTAsn1SetOfIntegers_InsertEx)
+# define RTAsn1SetOfObjIds_Erase                        RT_MANGLER(RTAsn1SetOfObjIds_Erase)
+# define RTAsn1SetOfObjIds_InsertEx                     RT_MANGLER(RTAsn1SetOfObjIds_InsertEx)
+# define RTAsn1SetOfObjIdSeqs_Erase                     RT_MANGLER(RTAsn1SetOfObjIdSeqs_Erase)
+# define RTAsn1SetOfObjIdSeqs_InsertEx                  RT_MANGLER(RTAsn1SetOfObjIdSeqs_InsertEx)
+# define RTAsn1SetOfOctetStrings_Erase                  RT_MANGLER(RTAsn1SetOfOctetStrings_Erase)
+# define RTAsn1SetOfOctetStrings_InsertEx               RT_MANGLER(RTAsn1SetOfOctetStrings_InsertEx)
+# define RTAsn1SetOfStrings_Erase                       RT_MANGLER(RTAsn1SetOfStrings_Erase)
+# define RTAsn1SetOfStrings_InsertEx                    RT_MANGLER(RTAsn1SetOfStrings_InsertEx)
+# define RTAsn1SetOfTimes_Erase                         RT_MANGLER(RTAsn1SetOfTimes_Erase)
+# define RTAsn1SetOfTimes_InsertEx                      RT_MANGLER(RTAsn1SetOfTimes_InsertEx)
+# define RTCrPkcs7Attributes_Erase                      RT_MANGLER(RTCrPkcs7Attributes_Erase)
+# define RTCrPkcs7Attributes_InsertEx                   RT_MANGLER(RTCrPkcs7Attributes_InsertEx)
+# define RTCrPkcs7SetOfCerts_Erase                      RT_MANGLER(RTCrPkcs7SetOfCerts_Erase)
+# define RTCrPkcs7SetOfCerts_InsertEx                   RT_MANGLER(RTCrPkcs7SetOfCerts_InsertEx)
+# define RTCrPkcs7SetOfContentInfos_Erase               RT_MANGLER(RTCrPkcs7SetOfContentInfos_Erase)
+# define RTCrPkcs7SetOfContentInfos_InsertEx            RT_MANGLER(RTCrPkcs7SetOfContentInfos_InsertEx)
+# define RTCrPkcs7SetOfSignedData_Erase                 RT_MANGLER(RTCrPkcs7SetOfSignedData_Erase)
+# define RTCrPkcs7SetOfSignedData_InsertEx              RT_MANGLER(RTCrPkcs7SetOfSignedData_InsertEx)
+# define RTCrPkcs7SignerInfos_Erase                     RT_MANGLER(RTCrPkcs7SignerInfos_Erase)
+# define RTCrPkcs7SignerInfos_InsertEx                  RT_MANGLER(RTCrPkcs7SignerInfos_InsertEx)
+# define RTCrRsaOtherPrimeInfos_Erase                   RT_MANGLER(RTCrRsaOtherPrimeInfos_Erase)
+# define RTCrRsaOtherPrimeInfos_InsertEx                RT_MANGLER(RTCrRsaOtherPrimeInfos_InsertEx)
+# define RTCrSpcSerializedObjectAttributes_Erase        RT_MANGLER(RTCrSpcSerializedObjectAttributes_Erase)
+# define RTCrSpcSerializedObjectAttributes_InsertEx     RT_MANGLER(RTCrSpcSerializedObjectAttributes_InsertEx)
+# define RTCrTafTrustAnchorList_Erase                   RT_MANGLER(RTCrTafTrustAnchorList_Erase)
+# define RTCrTafTrustAnchorList_InsertEx                RT_MANGLER(RTCrTafTrustAnchorList_InsertEx)
+# define RTCrX509AlgorithmIdentifiers_Erase             RT_MANGLER(RTCrX509AlgorithmIdentifiers_Erase)
+# define RTCrX509AlgorithmIdentifiers_InsertEx          RT_MANGLER(RTCrX509AlgorithmIdentifiers_InsertEx)
+# define RTCrX509AttributeTypeAndValues_Erase           RT_MANGLER(RTCrX509AttributeTypeAndValues_Erase)
+# define RTCrX509AttributeTypeAndValues_InsertEx        RT_MANGLER(RTCrX509AttributeTypeAndValues_InsertEx)
+# define RTCrX509CertificatePolicies_Erase              RT_MANGLER(RTCrX509CertificatePolicies_Erase)
+# define RTCrX509CertificatePolicies_InsertEx           RT_MANGLER(RTCrX509CertificatePolicies_InsertEx)
+# define RTCrX509Certificates_Erase                     RT_MANGLER(RTCrX509Certificates_Erase)
+# define RTCrX509Certificates_InsertEx                  RT_MANGLER(RTCrX509Certificates_InsertEx)
+# define RTCrX509Extensions_Erase                       RT_MANGLER(RTCrX509Extensions_Erase)
+# define RTCrX509Extensions_InsertEx                    RT_MANGLER(RTCrX509Extensions_InsertEx)
+# define RTCrX509GeneralNames_Erase                     RT_MANGLER(RTCrX509GeneralNames_Erase)
+# define RTCrX509GeneralNames_InsertEx                  RT_MANGLER(RTCrX509GeneralNames_InsertEx)
+# define RTCrX509GeneralSubtrees_Erase                  RT_MANGLER(RTCrX509GeneralSubtrees_Erase)
+# define RTCrX509GeneralSubtrees_InsertEx               RT_MANGLER(RTCrX509GeneralSubtrees_InsertEx)
+# define RTCrX509Name_Erase                             RT_MANGLER(RTCrX509Name_Erase)
+# define RTCrX509Name_InsertEx                          RT_MANGLER(RTCrX509Name_InsertEx)
+# define RTCrX509PolicyMappings_Erase                   RT_MANGLER(RTCrX509PolicyMappings_Erase)
+# define RTCrX509PolicyMappings_InsertEx                RT_MANGLER(RTCrX509PolicyMappings_InsertEx)
+# define RTCrX509PolicyQualifierInfos_Erase             RT_MANGLER(RTCrX509PolicyQualifierInfos_Erase)
+# define RTCrX509PolicyQualifierInfos_InsertEx          RT_MANGLER(RTCrX509PolicyQualifierInfos_InsertEx)
+
+
+/*
+ * Stable variables (alphabetical order):
+ */
+# define g_apfnRTZlibDeps                               RT_MANGLER(g_apfnRTZlibDeps) /* os2 win solaris */
+# define g_aRTUniFlagsRanges                            RT_MANGLER(g_aRTUniFlagsRanges)
+# define g_aRTUniLowerRanges                            RT_MANGLER(g_aRTUniLowerRanges)
+# define g_aRTUniUpperRanges                            RT_MANGLER(g_aRTUniUpperRanges)
+# define g_fRTAlignmentChecks                           RT_MANGLER(g_fRTAlignmentChecks)
+# define g_hKrnlDbgInfo                                 RT_MANGLER(g_hKrnlDbgInfo) /* solaris */
+# define g_pStdErr                                      RT_MANGLER(g_pStdErr)
+# define g_pStdIn                                       RT_MANGLER(g_pStdIn)
+# define g_pStdOut                                      RT_MANGLER(g_pStdOut)
+# define g_pszRTAssertExpr                              RT_MANGLER(g_pszRTAssertExpr)
+# define g_pszRTAssertFile                              RT_MANGLER(g_pszRTAssertFile)
+# define g_pszRTAssertFunction                          RT_MANGLER(g_pszRTAssertFunction)
+# define g_szRTAssertMsg1                               RT_MANGLER(g_szRTAssertMsg1)
+# define g_szRTAssertMsg2                               RT_MANGLER(g_szRTAssertMsg2)
+# define g_u32RTAssertLine                              RT_MANGLER(g_u32RTAssertLine)
+
+/* sort/merge into the above later: */
+# define g_RTAsn1Time_Vtable                            RT_MANGLER(g_RTAsn1Time_Vtable)
+# define g_RTAsn1String_Vtable                          RT_MANGLER(g_RTAsn1String_Vtable)
+# define g_RTAsn1OctetString_Vtable                     RT_MANGLER(g_RTAsn1OctetString_Vtable)
+# define g_RTAsn1ObjId_Vtable                           RT_MANGLER(g_RTAsn1ObjId_Vtable)
+# define g_RTAsn1Null_Vtable                            RT_MANGLER(g_RTAsn1Null_Vtable)
+# define g_RTAsn1Integer_Vtable                         RT_MANGLER(g_RTAsn1Integer_Vtable)
+# define g_RTAsn1Core_Vtable                            RT_MANGLER(g_RTAsn1Core_Vtable)
+# define g_RTAsn1Boolean_Vtable                         RT_MANGLER(g_RTAsn1Boolean_Vtable)
+# define g_RTAsn1BitString_Vtable                       RT_MANGLER(g_RTAsn1BitString_Vtable)
+# define g_RTAsn1DefaultAllocator                       RT_MANGLER(g_RTAsn1DefaultAllocator)
+# define g_RTAsn1EFenceAllocator                        RT_MANGLER(g_RTAsn1EFenceAllocator)
+# define g_aRTCrX509CertificateMarkers                  RT_MANGLER(g_aRTCrX509CertificateMarkers)
+# define g_cRTCrX509CertificateMarkers                  RT_MANGLER(g_cRTCrX509CertificateMarkers)
+
+#if 0 /* Disabled for now as I'm not sure the assmbler supports mangling yet. */
+# define g_abRTZeroPage                                 RT_MANGLER(g_abRTZeroPage)
+# define g_abRTZero4K                                   RT_MANGLER(g_abRTZero4K)
+# define g_abRTZero8K                                   RT_MANGLER(g_abRTZero8K)
+# define g_abRTZero16K                                  RT_MANGLER(g_abRTZero16K)
+# define g_abRTZero32K                                  RT_MANGLER(g_abRTZero32K)
+# define g_abRTZero64K                                  RT_MANGLER(g_abRTZero64K)
+#endif
+
+
+/*
+ * Unstable functions (alphabetical order):
+ */
+/** @todo the list is incomplete! See the .def files + libraries. */
+
+
+/*
+ * Unstable variables (alphabetical order):
+ */
+/* none */
+
+#endif /* !DOXYGEN_RUNNING */
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/mem.h b/ubuntu/vbox/include/iprt/mem.h
new file mode 100644 (file)
index 0000000..2f51c97
--- /dev/null
@@ -0,0 +1,987 @@
+/** @file
+ * IPRT - Memory Management and Manipulation.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_mem_h
+#define ___iprt_mem_h
+
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+
+#ifdef IN_RC
+# error "There are no RTMem APIs available Guest Context!"
+#endif
+
+
+/** @defgroup grp_rt_mem    RTMem - Memory Management and Manipulation
+ * @ingroup grp_rt
+ * @{
+ */
+
+RT_C_DECLS_BEGIN
+
+/** @def RTMEM_ALIGNMENT
+ * The alignment of the memory blocks returned by RTMemAlloc(), RTMemAllocZ(),
+ * RTMemRealloc(), RTMemTmpAlloc() and RTMemTmpAllocZ() for allocations greater
+ * than RTMEM_ALIGNMENT.
+ *
+ * @note This alignment is not forced if the electric fence is active!
+ */
+#if defined(RT_OS_OS2)
+# define RTMEM_ALIGNMENT    4
+#else
+# define RTMEM_ALIGNMENT    8
+#endif
+
+/** @def RTMEM_TAG
+ * The default allocation tag used by the RTMem allocation APIs.
+ *
+ * When not defined before the inclusion of iprt/mem.h or iprt/memobj.h, this
+ * will default to the pointer to the current file name.  The memory API will
+ * make of use of this as pointer to a volatile but read-only string.
+ * The alternative tag includes the line number for a more-detailed analysis.
+ */
+#ifndef RTMEM_TAG
+# if 0
+#  define RTMEM_TAG   (__FILE__ ":" RT_XSTR(__LINE__))
+# else
+#  define RTMEM_TAG   (__FILE__)
+# endif
+#endif
+
+
+/** @name Allocate temporary memory.
+ * @{ */
+/**
+ * Allocates temporary memory with default tag.
+ *
+ * Temporary memory blocks are used for not too large memory blocks which
+ * are believed not to stick around for too long. Using this API instead
+ * of RTMemAlloc() not only gives the heap manager room for optimization
+ * but makes the code easier to read.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure, assertion raised in strict builds.
+ * @param   cb      Size in bytes of the memory block to allocated.
+ */
+#define RTMemTmpAlloc(cb)               RTMemTmpAllocTag((cb), RTMEM_TAG)
+
+/**
+ * Allocates temporary memory with custom tag.
+ *
+ * Temporary memory blocks are used for not too large memory blocks which
+ * are believed not to stick around for too long. Using this API instead
+ * of RTMemAlloc() not only gives the heap manager room for optimization
+ * but makes the code easier to read.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure, assertion raised in strict builds.
+ * @param   cb      Size in bytes of the memory block to allocated.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ */
+RTDECL(void *)  RTMemTmpAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Allocates zero'd temporary memory with default tag.
+ *
+ * Same as RTMemTmpAlloc() but the memory will be zero'd.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure, assertion raised in strict builds.
+ * @param   cb      Size in bytes of the memory block to allocated.
+ */
+#define RTMemTmpAllocZ(cb)              RTMemTmpAllocZTag((cb), RTMEM_TAG)
+
+/**
+ * Allocates zero'd temporary memory with custom tag.
+ *
+ * Same as RTMemTmpAlloc() but the memory will be zero'd.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure, assertion raised in strict builds.
+ * @param   cb      Size in bytes of the memory block to allocated.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ */
+RTDECL(void *)  RTMemTmpAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Free temporary memory.
+ *
+ * @param   pv      Pointer to memory block.
+ */
+RTDECL(void)    RTMemTmpFree(void *pv) RT_NO_THROW_PROTO;
+
+/** @}  */
+
+
+/**
+ * Allocates memory with default tag.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure, assertion raised in strict builds.
+ * @param   cb      Size in bytes of the memory block to allocated.
+ */
+#define RTMemAlloc(cb)                  RTMemAllocTag((cb), RTMEM_TAG)
+
+/**
+ * Allocates memory with custom tag.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure, assertion raised in strict builds.
+ * @param   cb      Size in bytes of the memory block to allocated.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ */
+RTDECL(void *)  RTMemAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Allocates zero'd memory with default tag.
+ *
+ * Instead of memset(pv, 0, sizeof()) use this when you want zero'd
+ * memory. This keeps the code smaller and the heap can skip the memset
+ * in about 0.42% of calls :-).
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ * @param   cb      Size in bytes of the memory block to allocated.
+ */
+#define RTMemAllocZ(cb)                 RTMemAllocZTag((cb), RTMEM_TAG)
+
+/**
+ * Allocates zero'd memory with custom tag.
+ *
+ * Instead of memset(pv, 0, sizeof()) use this when you want zero'd
+ * memory. This keeps the code smaller and the heap can skip the memset
+ * in about 0.42% of calls :-).
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ * @param   cb      Size in bytes of the memory block to allocated.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ */
+RTDECL(void *)  RTMemAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Wrapper around RTMemAlloc for automatically aligning variable sized
+ * allocations so that the various electric fence heaps works correctly.
+ *
+ * @returns See RTMemAlloc.
+ * @param   cbUnaligned         The unaligned size.
+ */
+#define RTMemAllocVar(cbUnaligned)      RTMemAllocVarTag((cbUnaligned), RTMEM_TAG)
+
+/**
+ * Wrapper around RTMemAllocTag for automatically aligning variable sized
+ * allocations so that the various electric fence heaps works correctly.
+ *
+ * @returns See RTMemAlloc.
+ * @param   cbUnaligned         The unaligned size.
+ * @param   pszTag              Allocation tag used for statistics and such.
+ */
+RTDECL(void *) RTMemAllocVarTag(size_t cbUnaligned, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Wrapper around RTMemAllocZ for automatically aligning variable sized
+ * allocations so that the various electric fence heaps works correctly.
+ *
+ * @returns See RTMemAllocZ.
+ * @param   cbUnaligned         The unaligned size.
+ */
+#define RTMemAllocZVar(cbUnaligned)     RTMemAllocZVarTag((cbUnaligned), RTMEM_TAG)
+
+/**
+ * Wrapper around RTMemAllocZTag for automatically aligning variable sized
+ * allocations so that the various electric fence heaps works correctly.
+ *
+ * @returns See RTMemAllocZ.
+ * @param   cbUnaligned         The unaligned size.
+ * @param   pszTag              Allocation tag used for statistics and such.
+ */
+RTDECL(void *) RTMemAllocZVarTag(size_t cbUnaligned, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Duplicates a chunk of memory into a new heap block (default tag).
+ *
+ * @returns New heap block with the duplicate data.
+ * @returns NULL if we're out of memory.
+ * @param   pvSrc   The memory to duplicate.
+ * @param   cb      The amount of memory to duplicate.
+ */
+#define RTMemDup(pvSrc, cb)             RTMemDupTag((pvSrc), (cb), RTMEM_TAG)
+
+/**
+ * Duplicates a chunk of memory into a new heap block (custom tag).
+ *
+ * @returns New heap block with the duplicate data.
+ * @returns NULL if we're out of memory.
+ * @param   pvSrc   The memory to duplicate.
+ * @param   cb      The amount of memory to duplicate.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ */
+RTDECL(void *) RTMemDupTag(const void *pvSrc, size_t cb, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Duplicates a chunk of memory into a new heap block with some additional
+ * zeroed memory (default tag).
+ *
+ * @returns New heap block with the duplicate data.
+ * @returns NULL if we're out of memory.
+ * @param   pvSrc   The memory to duplicate.
+ * @param   cbSrc   The amount of memory to duplicate.
+ * @param   cbExtra The amount of extra memory to allocate and zero.
+ */
+#define RTMemDupEx(pvSrc, cbSrc, cbExtra)   RTMemDupExTag((pvSrc), (cbSrc), (cbExtra), RTMEM_TAG)
+
+/**
+ * Duplicates a chunk of memory into a new heap block with some additional
+ * zeroed memory (default tag).
+ *
+ * @returns New heap block with the duplicate data.
+ * @returns NULL if we're out of memory.
+ * @param   pvSrc   The memory to duplicate.
+ * @param   cbSrc   The amount of memory to duplicate.
+ * @param   cbExtra The amount of extra memory to allocate and zero.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ */
+RTDECL(void *) RTMemDupExTag(const void *pvSrc, size_t cbSrc, size_t cbExtra, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Reallocates memory with default tag.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ * @param   pvOld   The memory block to reallocate.
+ * @param   cbNew   The new block size (in bytes).
+ */
+#define RTMemRealloc(pvOld, cbNew)          RTMemReallocTag((pvOld), (cbNew), RTMEM_TAG)
+
+/**
+ * Reallocates memory with custom tag.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ * @param   pvOld   The memory block to reallocate.
+ * @param   cbNew   The new block size (in bytes).
+ * @param   pszTag  Allocation tag used for statistics and such.
+ */
+RTDECL(void *)  RTMemReallocTag(void *pvOld, size_t cbNew, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Frees memory.
+ *
+ * @param   pv      Pointer to memory block.
+ */
+RTDECL(void)    RTMemFree(void *pv) RT_NO_THROW_PROTO;
+
+
+
+/** @name RTR0MemAllocEx and RTR0MemAllocExTag flags.
+ * @{ */
+/** The returned memory should be zeroed. */
+#define RTMEMALLOCEX_FLAGS_ZEROED           RT_BIT(0)
+/** It must be load code into the returned memory block and execute it. */
+#define RTMEMALLOCEX_FLAGS_EXEC             RT_BIT(1)
+/** Allocation from any context.
+ * Will return VERR_NOT_SUPPORTED if not supported.  */
+#define RTMEMALLOCEX_FLAGS_ANY_CTX_ALLOC    RT_BIT(2)
+/** Allocate the memory such that it can be freed from any context.
+ * Will return VERR_NOT_SUPPORTED if not supported. */
+#define RTMEMALLOCEX_FLAGS_ANY_CTX_FREE     RT_BIT(3)
+/** Allocate and free from any context.
+ * Will return VERR_NOT_SUPPORTED if not supported. */
+#define RTMEMALLOCEX_FLAGS_ANY_CTX          (RTMEMALLOCEX_FLAGS_ANY_CTX_ALLOC | RTMEMALLOCEX_FLAGS_ANY_CTX_FREE)
+/** Reachable by 16-bit address.
+ * Will return VERR_NOT_SUPPORTED if not supported.  */
+#define RTMEMALLOCEX_FLAGS_16BIT_REACH      RT_BIT(4)
+/** Reachable by 32-bit address.
+ * Will return VERR_NOT_SUPPORTED if not supported.  */
+#define RTMEMALLOCEX_FLAGS_32BIT_REACH      RT_BIT(5)
+/** Mask of valid flags. */
+#define RTMEMALLOCEX_FLAGS_VALID_MASK       UINT32_C(0x0000003f)
+/** Mask of valid flags for ring-0. */
+#define RTMEMALLOCEX_FLAGS_VALID_MASK_R0    UINT32_C(0x0000000f)
+/** @}  */
+
+/**
+ * Extended heap allocation API, default tag.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NO_MEMORY if we're out of memory.
+ * @retval  VERR_NO_EXEC_MEMORY if we're out of executable memory.
+ * @retval  VERR_NOT_SUPPORTED if any of the specified flags are unsupported.
+ *
+ * @param   cb                  The amount of memory to allocate.
+ * @param   cbAlignment         The alignment requirements.  Use 0 to indicate
+ *                              default alignment.
+ * @param   fFlags              A combination of the RTMEMALLOCEX_FLAGS_XXX
+ *                              defines.
+ * @param   ppv                 Where to return the memory.
+ */
+#define RTMemAllocEx(cb, cbAlignment, fFlags, ppv) RTMemAllocExTag((cb), (cbAlignment), (fFlags), RTMEM_TAG, (ppv))
+
+/**
+ * Extended heap allocation API, custom tag.
+ *
+ * Depending on the implementation, using this function may add extra overhead,
+ * so use the simpler APIs where ever possible.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NO_MEMORY if we're out of memory.
+ * @retval  VERR_NO_EXEC_MEMORY if we're out of executable memory.
+ * @retval  VERR_NOT_SUPPORTED if any of the specified flags are unsupported.
+ *
+ * @param   cb                  The amount of memory to allocate.
+ * @param   cbAlignment         The alignment requirements.  Use 0 to indicate
+ *                              default alignment.
+ * @param   fFlags              A combination of the RTMEMALLOCEX_FLAGS_XXX
+ *                              defines.
+ * @param   pszTag              The tag.
+ * @param   ppv                 Where to return the memory.
+ */
+RTDECL(int) RTMemAllocExTag(size_t cb, size_t cbAlignment, uint32_t fFlags, const char *pszTag, void **ppv) RT_NO_THROW_PROTO;
+
+/**
+ * For freeing memory allocated by RTMemAllocEx or RTMemAllocExTag.
+ *
+ * @param   pv                  What to free, NULL is fine.
+ * @param   cb                  The amount of allocated memory.
+ */
+RTDECL(void) RTMemFreeEx(void *pv, size_t cb) RT_NO_THROW_PROTO;
+
+
+
+/**
+ * Allocates memory which may contain code (default tag).
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ * @param   cb      Size in bytes of the memory block to allocate.
+ */
+#define RTMemExecAlloc(cb)              RTMemExecAllocTag((cb), RTMEM_TAG)
+
+/**
+ * Allocates memory which may contain code (custom tag).
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ * @param   cb      Size in bytes of the memory block to allocate.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ */
+RTDECL(void *)  RTMemExecAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Free executable/read/write memory allocated by RTMemExecAlloc().
+ *
+ * @param   pv      Pointer to memory block.
+ * @param   cb      The allocation size.
+ */
+RTDECL(void)    RTMemExecFree(void *pv, size_t cb) RT_NO_THROW_PROTO;
+
+#if defined(IN_RING0) && defined(RT_ARCH_AMD64) && defined(RT_OS_LINUX)
+/**
+ * Donate read+write+execute memory to the exec heap.
+ *
+ * This API is specific to AMD64 and Linux/GNU. A kernel module that desires to
+ * use RTMemExecAlloc on AMD64 Linux/GNU will have to donate some statically
+ * allocated memory in the module if it wishes for GCC generated code to work.
+ * GCC can only generate modules that work in the address range ~2GB to ~0
+ * currently.
+ *
+ * The API only accept one single donation.
+ *
+ * @returns IPRT status code.
+ * @param   pvMemory    Pointer to the memory block.
+ * @param   cb          The size of the memory block.
+ */
+RTR0DECL(int) RTR0MemExecDonate(void *pvMemory, size_t cb) RT_NO_THROW_PROTO;
+#endif /* R0+AMD64+LINUX */
+
+/**
+ * Allocate page aligned memory with default tag.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL if we're out of memory.
+ * @param   cb  Size of the memory block. Will be rounded up to page size.
+ */
+#define RTMemPageAlloc(cb)              RTMemPageAllocTag((cb), RTMEM_TAG)
+
+/**
+ * Allocate page aligned memory with custom tag.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL if we're out of memory.
+ * @param   cb  Size of the memory block. Will be rounded up to page size.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ */
+RTDECL(void *) RTMemPageAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Allocate zero'd page aligned memory with default tag.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL if we're out of memory.
+ * @param   cb  Size of the memory block. Will be rounded up to page size.
+ */
+#define RTMemPageAllocZ(cb)             RTMemPageAllocZTag((cb), RTMEM_TAG)
+
+/**
+ * Allocate zero'd page aligned memory with custom tag.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL if we're out of memory.
+ * @param   cb  Size of the memory block. Will be rounded up to page size.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ */
+RTDECL(void *) RTMemPageAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Free a memory block allocated with RTMemPageAlloc() or RTMemPageAllocZ().
+ *
+ * @param   pv      Pointer to the block as it was returned by the allocation function.
+ *                  NULL will be ignored.
+ * @param   cb      The allocation size.  Will be rounded up to page size.
+ *                  Ignored if @a pv is NULL.
+ */
+RTDECL(void) RTMemPageFree(void *pv, size_t cb) RT_NO_THROW_PROTO;
+
+/** Page level protection flags for RTMemProtect().
+ * @{
+ */
+/** No access at all. */
+#define RTMEM_PROT_NONE   0
+/** Read access. */
+#define RTMEM_PROT_READ   1
+/** Write access. */
+#define RTMEM_PROT_WRITE  2
+/** Execute access. */
+#define RTMEM_PROT_EXEC   4
+/** @} */
+
+/**
+ * Change the page level protection of a memory region.
+ *
+ * @returns iprt status code.
+ * @param   pv          Start of the region. Will be rounded down to nearest page boundary.
+ * @param   cb          Size of the region. Will be rounded up to the nearest page boundary.
+ * @param   fProtect    The new protection, a combination of the RTMEM_PROT_* defines.
+ */
+RTDECL(int) RTMemProtect(void *pv, size_t cb, unsigned fProtect) RT_NO_THROW_PROTO;
+
+/**
+ * Goes thru some pains to make sure the specified memory block is thoroughly
+ * scrambled.
+ *
+ * @param   pv          The start of the memory block.
+ * @param   cb          The size of the memory block.
+ * @param   cMinPasses  The minimum number of passes to make.
+ */
+RTDECL(void) RTMemWipeThoroughly(void *pv, size_t cb, size_t cMinPasses) RT_NO_THROW_PROTO;
+
+#ifdef IN_RING0
+
+/**
+ * Allocates physical contiguous memory (below 4GB).
+ * The allocation is page aligned and the content is undefined.
+ *
+ * @returns Pointer to the memory block. This is page aligned.
+ * @param   pPhys   Where to store the physical address.
+ * @param   cb      The allocation size in bytes. This is always
+ *                  rounded up to PAGE_SIZE.
+ */
+RTR0DECL(void *) RTMemContAlloc(PRTCCPHYS pPhys, size_t cb) RT_NO_THROW_PROTO;
+
+/**
+ * Frees memory allocated ysing RTMemContAlloc().
+ *
+ * @param   pv      Pointer to return from RTMemContAlloc().
+ * @param   cb      The cb parameter passed to RTMemContAlloc().
+ */
+RTR0DECL(void) RTMemContFree(void *pv, size_t cb) RT_NO_THROW_PROTO;
+
+/**
+ * Copy memory from an user mode buffer into a kernel buffer.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_ACCESS_DENIED on error.
+ *
+ * @param   pvDst       The kernel mode destination address.
+ * @param   R3PtrSrc    The user mode source address.
+ * @param   cb          The number of bytes to copy.
+ */
+RTR0DECL(int) RTR0MemUserCopyFrom(void *pvDst, RTR3PTR R3PtrSrc, size_t cb);
+
+/**
+ * Copy memory from a kernel buffer into a user mode one.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_ACCESS_DENIED on error.
+ *
+ * @param   R3PtrDst    The user mode destination address.
+ * @param   pvSrc       The kernel mode source address.
+ * @param   cb          The number of bytes to copy.
+ */
+RTR0DECL(int) RTR0MemUserCopyTo(RTR3PTR R3PtrDst, void const *pvSrc, size_t cb);
+
+/**
+ * Tests if the specified address is in the user addressable range.
+ *
+ * This function does not check whether the memory at that address is accessible
+ * or anything of that sort, only if the address it self is in the user mode
+ * range.
+ *
+ * @returns true if it's in the user addressable range. false if not.
+ * @param   R3Ptr       The user mode pointer to test.
+ *
+ * @remarks Some systems may have overlapping kernel and user address ranges.
+ *          One prominent example of this is the x86 version of Mac OS X. Use
+ *          RTR0MemAreKrnlAndUsrDifferent() to check.
+ */
+RTR0DECL(bool) RTR0MemUserIsValidAddr(RTR3PTR R3Ptr);
+
+/**
+ * Tests if the specified address is in the kernel mode range.
+ *
+ * This function does not check whether the memory at that address is accessible
+ * or anything of that sort, only if the address it self is in the kernel mode
+ * range.
+ *
+ * @returns true if it's in the kernel range. false if not.
+ * @param   pv          The alleged kernel mode pointer.
+ *
+ * @remarks Some systems may have overlapping kernel and user address ranges.
+ *          One prominent example of this is the x86 version of Mac OS X. Use
+ *          RTR0MemAreKrnlAndUsrDifferent() to check.
+ */
+RTR0DECL(bool) RTR0MemKernelIsValidAddr(void *pv);
+
+/**
+ * Are user mode and kernel mode address ranges distinctly different.
+ *
+ * This determines whether RTR0MemKernelIsValidAddr and RTR0MemUserIsValidAddr
+ * can be used for deciding whether some arbitrary address is a user mode or a
+ * kernel mode one.
+ *
+ * @returns true if they are, false if not.
+ */
+RTR0DECL(bool) RTR0MemAreKrnlAndUsrDifferent(void);
+
+/**
+ * Copy memory from an potentially unsafe kernel mode location and into a safe
+ * (kernel) buffer.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_ACCESS_DENIED on error.
+ * @retval  VERR_NOT_SUPPORTED if not (yet) supported.
+ *
+ * @param   pvDst       The destination address (safe).
+ * @param   pvSrc       The source address (potentially unsafe).
+ * @param   cb          The number of bytes to copy.
+ */
+RTR0DECL(int) RTR0MemKernelCopyFrom(void *pvDst, void const *pvSrc, size_t cb);
+
+/**
+ * Copy from a safe (kernel) buffer and to a potentially unsafe kenrel mode
+ * location.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_ACCESS_DENIED on error.
+ * @retval  VERR_NOT_SUPPORTED if not (yet) supported.
+ *
+ * @param   pvDst       The destination address (potentially unsafe).
+ * @param   pvSrc       The source address (safe).
+ * @param   cb          The number of bytes to copy.
+ */
+RTR0DECL(int) RTR0MemKernelCopyTo(void *pvDst, void const *pvSrc, size_t cb);
+
+#endif /* IN_RING0 */
+
+
+/** @name Electrical Fence Version of some APIs.
+ * @{
+ */
+
+/**
+ * Same as RTMemTmpAllocTag() except that it's fenced.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ * @param   cb      Size in bytes of the memory block to allocate.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ * @param   SRC_POS The source position where call is being made from.
+ *                  Use RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(void *)  RTMemEfTmpAlloc(size_t cb, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW_PROTO;
+
+/**
+ * Same as RTMemTmpAllocZTag() except that it's fenced.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ * @param   cb      Size in bytes of the memory block to allocate.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ * @param   SRC_POS The source position where call is being made from.  Use
+ *                  RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(void *)  RTMemEfTmpAllocZ(size_t cb, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW_PROTO;
+
+/**
+ * Same as RTMemTmpFree() except that it's for fenced memory.
+ *
+ * @param   pv      Pointer to memory block.
+ * @param   SRC_POS The source position where call is being made from.  Use
+ *                  RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(void)    RTMemEfTmpFree(void *pv, RT_SRC_POS_DECL) RT_NO_THROW_PROTO;
+
+/**
+ * Same as RTMemAllocTag() except that it's fenced.
+ *
+ * @returns Pointer to the allocated memory. Free with RTMemEfFree().
+ * @returns NULL on failure.
+ * @param   cb      Size in bytes of the memory block to allocate.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ * @param   SRC_POS The source position where call is being made from.  Use
+ *                  RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(void *)  RTMemEfAlloc(size_t cb, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW_PROTO;
+
+/**
+ * Same as RTMemAllocZTag() except that it's fenced.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ * @param   cb      Size in bytes of the memory block to allocate.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ * @param   SRC_POS The source position where call is being made from.  Use
+ *                  RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(void *)  RTMemEfAllocZ(size_t cb, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW_PROTO;
+
+/**
+ * Same as RTMemAllocVarTag() except that it's fenced.
+ *
+ * @returns Pointer to the allocated memory. Free with RTMemEfFree().
+ * @returns NULL on failure.
+ * @param   cbUnaligned Size in bytes of the memory block to allocate.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ * @param   SRC_POS The source position where call is being made from.  Use
+ *                  RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(void *)  RTMemEfAllocVar(size_t cbUnaligned, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW_PROTO;
+
+/**
+ * Same as RTMemAllocZVarTag() except that it's fenced.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ * @param   cbUnaligned Size in bytes of the memory block to allocate.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ * @param   SRC_POS The source position where call is being made from.  Use
+ *                  RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(void *)  RTMemEfAllocZVar(size_t cbUnaligned, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW_PROTO;
+
+/**
+ * Same as RTMemReallocTag() except that it's fenced.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ * @param   pvOld   The memory block to reallocate.
+ * @param   cbNew   The new block size (in bytes).
+ * @param   pszTag  Allocation tag used for statistics and such.
+ * @param   SRC_POS The source position where call is being made from.  Use
+ *                  RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(void *)  RTMemEfRealloc(void *pvOld, size_t cbNew, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW_PROTO;
+
+/**
+ * Free memory allocated by any of the RTMemEf* allocators.
+ *
+ * @param   pv      Pointer to memory block.
+ * @param   SRC_POS The source position where call is being made from.  Use
+ *                  RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(void)    RTMemEfFree(void *pv, RT_SRC_POS_DECL) RT_NO_THROW_PROTO;
+
+/**
+ * Same as RTMemDupTag() except that it's fenced.
+ *
+ * @returns New heap block with the duplicate data.
+ * @returns NULL if we're out of memory.
+ * @param   pvSrc   The memory to duplicate.
+ * @param   cb      The amount of memory to duplicate.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ * @param   SRC_POS The source position where call is being made from.  Use
+ *                  RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(void *) RTMemEfDup(const void *pvSrc, size_t cb, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW_PROTO;
+
+/**
+ * Same as RTMemEfDupExTag except that it's fenced.
+ *
+ * @returns New heap block with the duplicate data.
+ * @returns NULL if we're out of memory.
+ * @param   pvSrc   The memory to duplicate.
+ * @param   cbSrc   The amount of memory to duplicate.
+ * @param   cbExtra The amount of extra memory to allocate and zero.
+ * @param   pszTag  Allocation tag used for statistics and such.
+ * @param   SRC_POS The source position where call is being made from.  Use
+ *                  RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(void *) RTMemEfDupEx(const void *pvSrc, size_t cbSrc, size_t cbExtra, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW_PROTO;
+
+/** @def RTMEM_WRAP_SOME_NEW_AND_DELETE_TO_EF
+ * Define RTMEM_WRAP_SOME_NEW_AND_DELETE_TO_EF to enable electric fence new and
+ * delete operators for classes which uses the RTMEMEF_NEW_AND_DELETE_OPERATORS
+ * macro.
+ */
+/** @def RTMEMEF_NEW_AND_DELETE_OPERATORS
+ * Defines the electric fence new and delete operators for a class when
+ * RTMEM_WRAP_SOME_NEW_AND_DELETE_TO_EF is define.
+ */
+/** @def RTR0MEMEF_NEW_AND_DELETE_OPERATORS_IOKIT
+ * Defines the electric fence new and delete operators for an IOKit class when
+ * RTMEM_WRAP_SOME_NEW_AND_DELETE_TO_EF is define.
+ *
+ * This differs from RTMEMEF_NEW_AND_DELETE_OPERATORS in that the memory we
+ * allocate is initialized to zero.  It is also assuming we don't have nothrow
+ * variants and exceptions, so fewer variations.
+ */
+#if defined(RTMEM_WRAP_SOME_NEW_AND_DELETE_TO_EF) && !defined(RTMEM_NO_WRAP_SOME_NEW_AND_DELETE_TO_EF)
+# if defined(RT_EXCEPTIONS_ENABLED)
+#  define RTMEMEF_NEW_AND_DELETE_OPERATORS() \
+        void *operator new(size_t cb) RT_THROW(std::bad_alloc) \
+        { \
+            void *pv = RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \
+            if (RT_LIKELY(pv)) \
+                return pv; \
+            throw std::bad_alloc(); \
+        } \
+        void *operator new(size_t cb, const std::nothrow_t &nothrow_constant) RT_NO_THROW_DEF \
+        { \
+            NOREF(nothrow_constant); \
+            return RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \
+        } \
+        void *operator new[](size_t cb) RT_THROW(std::bad_alloc) \
+        { \
+            void *pv = RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \
+            if (RT_LIKELY(pv)) \
+                return pv; \
+            throw std::bad_alloc(); \
+        } \
+        void *operator new[](size_t cb, const std::nothrow_t &nothrow_constant) RT_NO_THROW_DEF \
+        { \
+            NOREF(nothrow_constant); \
+            return RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \
+        } \
+        \
+        void operator delete(void *pv) RT_NO_THROW_DEF \
+        { \
+            RTMemEfFree(pv, RT_SRC_POS); \
+        } \
+        void operator delete(void *pv, const std::nothrow_t &nothrow_constant) RT_NO_THROW_DEF \
+        { \
+            NOREF(nothrow_constant); \
+            RTMemEfFree(pv, RT_SRC_POS); \
+        } \
+        void operator delete[](void *pv) RT_NO_THROW_DEF \
+        { \
+            RTMemEfFree(pv, RT_SRC_POS); \
+        } \
+        void operator delete[](void *pv, const std::nothrow_t &nothrow_constant) RT_NO_THROW_DEF \
+        { \
+            NOREF(nothrow_constant); \
+            RTMemEfFree(pv, RT_SRC_POS); \
+        } \
+        \
+        typedef int UsingElectricNewAndDeleteOperators
+# else
+#  define RTMEMEF_NEW_AND_DELETE_OPERATORS() \
+        void *operator new(size_t cb) \
+        { \
+            return RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \
+        } \
+        void *operator new(size_t cb, const std::nothrow_t &nothrow_constant) \
+        { \
+            NOREF(nothrow_constant); \
+            return RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \
+        } \
+        void *operator new[](size_t cb) \
+        { \
+            return RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \
+        } \
+        void *operator new[](size_t cb, const std::nothrow_t &nothrow_constant) \
+        { \
+            NOREF(nothrow_constant); \
+            return RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \
+        } \
+        \
+        void operator delete(void *pv) \
+        { \
+            RTMemEfFree(pv, RT_SRC_POS); \
+        } \
+        void operator delete(void *pv, const std::nothrow_t &nothrow_constant) \
+        { \
+            NOREF(nothrow_constant); \
+            RTMemEfFree(pv, RT_SRC_POS); \
+        } \
+        void operator delete[](void *pv) \
+        { \
+            RTMemEfFree(pv, RT_SRC_POS); \
+        } \
+        void operator delete[](void *pv, const std::nothrow_t &nothrow_constant) \
+        { \
+            NOREF(nothrow_constant); \
+            RTMemEfFree(pv, RT_SRC_POS); \
+        } \
+        \
+        typedef int UsingElectricNewAndDeleteOperators
+# endif
+# define RTR0MEMEF_NEW_AND_DELETE_OPERATORS_IOKIT() \
+    void *operator new(size_t cb) \
+    { \
+        return RTMemEfAllocZ(cb, RTMEM_TAG, RT_SRC_POS); \
+    } \
+    void *operator new[](size_t cb) \
+    { \
+        return RTMemEfAllocZ(cb, RTMEM_TAG, RT_SRC_POS); \
+    } \
+    \
+    void operator delete(void *pv) \
+    { \
+        RTMemEfFree(pv, RT_SRC_POS); \
+    } \
+    void operator delete[](void *pv) \
+    { \
+        RTMemEfFree(pv, RT_SRC_POS); \
+    } \
+    \
+    typedef int UsingElectricNewAndDeleteOperators
+#else
+# define RTMEMEF_NEW_AND_DELETE_OPERATORS() \
+        typedef int UsingDefaultNewAndDeleteOperators
+# define RTR0MEMEF_NEW_AND_DELETE_OPERATORS_IOKIT() \
+        typedef int UsingDefaultNewAndDeleteOperators
+#endif
+#ifdef DOXYGEN_RUNNING
+# define RTMEM_WRAP_SOME_NEW_AND_DELETE_TO_EF
+#endif
+
+/** @def RTMEM_WRAP_TO_EF_APIS
+ * Define RTMEM_WRAP_TO_EF_APIS to wrap RTMem APIs to RTMemEf APIs.
+ */
+#if defined(RTMEM_WRAP_TO_EF_APIS) && !defined(RTMEM_NO_WRAP_TO_EF_APIS) \
+ && ( defined(IN_RING3) || ( defined(IN_RING0) && !defined(IN_RING0_AGNOSTIC) && (defined(RT_OS_DARWIN) || 0) ) )
+# define RTMemTmpAllocTag(cb, pszTag)                   RTMemEfTmpAlloc((cb), (pszTag), RT_SRC_POS)
+# define RTMemTmpAllocZTag(cb, pszTag)                  RTMemEfTmpAllocZ((cb), (pszTag), RT_SRC_POS)
+# define RTMemTmpFree(pv)                               RTMemEfTmpFree((pv), RT_SRC_POS)
+# define RTMemAllocTag(cb, pszTag)                      RTMemEfAlloc((cb), (pszTag), RT_SRC_POS)
+# define RTMemAllocZTag(cb, pszTag)                     RTMemEfAllocZ((cb), (pszTag), RT_SRC_POS)
+# define RTMemAllocVarTag(cbUnaligned, pszTag)          RTMemEfAllocVar((cbUnaligned), (pszTag), RT_SRC_POS)
+# define RTMemAllocZVarTag(cbUnaligned, pszTag)         RTMemEfAllocZVar((cbUnaligned), (pszTag), RT_SRC_POS)
+# define RTMemReallocTag(pvOld, cbNew, pszTag)          RTMemEfRealloc((pvOld), (cbNew), (pszTag), RT_SRC_POS)
+# define RTMemFree(pv)                                  RTMemEfFree((pv), RT_SRC_POS)
+# define RTMemDupTag(pvSrc, cb, pszTag)                 RTMemEfDup((pvSrc), (cb), (pszTag), RT_SRC_POS)
+# define RTMemDupExTag(pvSrc, cbSrc, cbExtra, pszTag)   RTMemEfDupEx((pvSrc), (cbSrc), (cbExtra), (pszTag), RT_SRC_POS)
+#endif
+#ifdef DOXYGEN_RUNNING
+# define RTMEM_WRAP_TO_EF_APIS
+#endif
+
+/**
+ * Fenced drop-in replacement for RTMemTmpAllocTag.
+ * @copydoc RTMemTmpAllocTag
+ */
+RTDECL(void *)  RTMemEfTmpAllocNP(size_t cb, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Fenced drop-in replacement for RTMemTmpAllocZTag.
+ * @copydoc RTMemTmpAllocZTag
+ */
+RTDECL(void *)  RTMemEfTmpAllocZNP(size_t cb, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Fenced drop-in replacement for RTMemTmpFreeTag.
+ * @copydoc RTMemTmpFree
+ */
+RTDECL(void)    RTMemEfTmpFreeNP(void *pv) RT_NO_THROW_PROTO;
+
+/**
+ * Fenced drop-in replacement for RTMemAllocTag.
+ * @copydoc RTMemAllocTag
+ */
+RTDECL(void *)  RTMemEfAllocNP(size_t cb, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Fenced drop-in replacement for RTMemAllocZTag.
+ * @copydoc RTMemAllocZTag
+ */
+RTDECL(void *)  RTMemEfAllocZNP(size_t cb, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Fenced drop-in replacement for RTMemAllocVarTag
+ * @copydoc RTMemAllocVarTag
+ */
+RTDECL(void *)  RTMemEfAllocVarNP(size_t cbUnaligned, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Fenced drop-in replacement for RTMemAllocZVarTag.
+ * @copydoc RTMemAllocZVarTag
+ */
+RTDECL(void *)  RTMemEfAllocZVarNP(size_t cbUnaligned, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Fenced drop-in replacement for RTMemReallocTag.
+ * @copydoc RTMemReallocTag
+ */
+RTDECL(void *)  RTMemEfReallocNP(void *pvOld, size_t cbNew, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Fenced drop-in replacement for RTMemFree.
+ * @copydoc RTMemFree
+ */
+RTDECL(void)    RTMemEfFreeNP(void *pv) RT_NO_THROW_PROTO;
+
+/**
+ * Fenced drop-in replacement for RTMemDupExTag.
+ * @copydoc RTMemDupTag
+ */
+RTDECL(void *) RTMemEfDupNP(const void *pvSrc, size_t cb, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Fenced drop-in replacement for RTMemDupExTag.
+ * @copydoc RTMemDupExTag
+ */
+RTDECL(void *) RTMemEfDupExNP(const void *pvSrc, size_t cbSrc, size_t cbExtra, const char *pszTag) RT_NO_THROW_PROTO;
+
+/** @} */
+
+RT_C_DECLS_END
+
+/** @} */
+
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/memobj.h b/ubuntu/vbox/include/iprt/memobj.h
new file mode 100644 (file)
index 0000000..08f2387
--- /dev/null
@@ -0,0 +1,629 @@
+/** @file
+ * IPRT - Memory Objects (Ring-0).
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_memobj_h
+#define ___iprt_memobj_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_memobj     RTMemObj - Memory Object Manipulation (Ring-0)
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** @def RTMEM_TAG
+ * The default allocation tag used by the RTMem allocation APIs.
+ *
+ * When not defined before the inclusion of iprt/memobj.h or iprt/mem.h, this
+ * will default to the pointer to the current file name.  The memory API will
+ * make of use of this as pointer to a volatile but read-only string.
+ */
+#ifndef RTMEM_TAG
+# define RTMEM_TAG   (__FILE__)
+#endif
+
+#ifdef IN_RING0
+
+/**
+ * Checks if this is mapping or not.
+ *
+ * @returns true if it's a mapping, otherwise false.
+ * @param   MemObj  The ring-0 memory object handle.
+ */
+RTR0DECL(bool) RTR0MemObjIsMapping(RTR0MEMOBJ MemObj);
+
+/**
+ * Gets the address of a ring-0 memory object.
+ *
+ * @returns The address of the memory object.
+ * @returns NULL if the handle is invalid (asserts in strict builds) or if there isn't any mapping.
+ * @param   MemObj  The ring-0 memory object handle.
+ */
+RTR0DECL(void *) RTR0MemObjAddress(RTR0MEMOBJ MemObj);
+
+/**
+ * Gets the ring-3 address of a ring-0 memory object.
+ *
+ * This only applies to ring-0 memory object with ring-3 mappings of some kind, i.e.
+ * locked user memory, reserved user address space and user mappings. This API should
+ * not be used on any other objects.
+ *
+ * @returns The address of the memory object.
+ * @returns NIL_RTR3PTR if the handle is invalid or if it's not an object with a ring-3 mapping.
+ *          Strict builds will assert in both cases.
+ * @param   MemObj  The ring-0 memory object handle.
+ */
+RTR0DECL(RTR3PTR) RTR0MemObjAddressR3(RTR0MEMOBJ MemObj);
+
+/**
+ * Gets the size of a ring-0 memory object.
+ *
+ * The returned value may differ from the one specified to the API creating the
+ * object because of alignment adjustments.  The minimal alignment currently
+ * employed by any API is PAGE_SIZE, so the result can safely be shifted by
+ * PAGE_SHIFT to calculate a page count.
+ *
+ * @returns The object size.
+ * @returns 0 if the handle is invalid (asserts in strict builds) or if there isn't any mapping.
+ * @param   MemObj  The ring-0 memory object handle.
+ */
+RTR0DECL(size_t) RTR0MemObjSize(RTR0MEMOBJ MemObj);
+
+/**
+ * Get the physical address of an page in the memory object.
+ *
+ * @returns The physical address.
+ * @returns NIL_RTHCPHYS if the object doesn't contain fixed physical pages.
+ * @returns NIL_RTHCPHYS if the iPage is out of range.
+ * @returns NIL_RTHCPHYS if the object handle isn't valid.
+ * @param   MemObj  The ring-0 memory object handle.
+ * @param   iPage   The page number within the object.
+ */
+RTR0DECL(RTHCPHYS) RTR0MemObjGetPagePhysAddr(RTR0MEMOBJ MemObj, size_t iPage);
+
+/**
+ * Frees a ring-0 memory object.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_HANDLE if
+ * @param   MemObj          The ring-0 memory object to be freed. NULL is accepted.
+ * @param   fFreeMappings   Whether or not to free mappings of the object.
+ */
+RTR0DECL(int) RTR0MemObjFree(RTR0MEMOBJ MemObj, bool fFreeMappings);
+
+/**
+ * Allocates page aligned virtual kernel memory (default tag).
+ *
+ * The memory is taken from a non paged (= fixed physical memory backing) pool.
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate. This is rounded up to nearest page.
+ * @param   fExecutable     Flag indicating whether it should be permitted to executed code in the memory object.
+ */
+#define RTR0MemObjAllocPage(pMemObj, cb, fExecutable) \
+    RTR0MemObjAllocPageTag((pMemObj), (cb), (fExecutable), RTMEM_TAG)
+
+/**
+ * Allocates page aligned virtual kernel memory (custom tag).
+ *
+ * The memory is taken from a non paged (= fixed physical memory backing) pool.
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate. This is rounded up to nearest page.
+ * @param   fExecutable     Flag indicating whether it should be permitted to executed code in the memory object.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTR0DECL(int) RTR0MemObjAllocPageTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag);
+
+/**
+ * Allocates page aligned virtual kernel memory with physical backing below 4GB
+ * (default tag).
+ *
+ * The physical memory backing the allocation is fixed.
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate. This is rounded up to nearest page.
+ * @param   fExecutable     Flag indicating whether it should be permitted to executed code in the memory object.
+ */
+#define RTR0MemObjAllocLow(pMemObj, cb, fExecutable) \
+    RTR0MemObjAllocLowTag((pMemObj), (cb), (fExecutable), RTMEM_TAG)
+
+/**
+ * Allocates page aligned virtual kernel memory with physical backing below 4GB
+ * (custom tag).
+ *
+ * The physical memory backing the allocation is fixed.
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate. This is rounded up to nearest page.
+ * @param   fExecutable     Flag indicating whether it should be permitted to executed code in the memory object.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTR0DECL(int) RTR0MemObjAllocLowTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag);
+
+/**
+ * Allocates page aligned virtual kernel memory with contiguous physical backing
+ * below 4GB (default tag).
+ *
+ * The physical memory backing the allocation is fixed.
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate. This is rounded up to nearest page.
+ * @param   fExecutable     Flag indicating whether it should be permitted to executed code in the memory object.
+ */
+#define RTR0MemObjAllocCont(pMemObj, cb, fExecutable) \
+    RTR0MemObjAllocContTag((pMemObj), (cb), (fExecutable), RTMEM_TAG)
+
+/**
+ * Allocates page aligned virtual kernel memory with contiguous physical backing
+ * below 4GB (custom tag).
+ *
+ * The physical memory backing the allocation is fixed.
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate. This is rounded up to nearest page.
+ * @param   fExecutable     Flag indicating whether it should be permitted to executed code in the memory object.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTR0DECL(int) RTR0MemObjAllocContTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag);
+
+/**
+ * Locks a range of user virtual memory (default tag).
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   R3Ptr           User virtual address. This is rounded down to a page
+ *                          boundary.
+ * @param   cb              Number of bytes to lock. This is rounded up to
+ *                          nearest page boundary.
+ * @param   fAccess         The desired access, a combination of RTMEM_PROT_READ
+ *                          and RTMEM_PROT_WRITE.
+ * @param   R0Process       The process to lock pages in. NIL_R0PROCESS is an
+ *                          alias for the current one.
+ *
+ * @remarks RTR0MemGetAddressR3() and RTR0MemGetAddress() will return therounded
+ *          down address.
+ *
+ * @remarks Linux: This API requires that the memory begin locked is in a memory
+ *          mapping that is not required in any forked off child process. This
+ *          is not intented as permanent restriction, feel free to help out
+ *          lifting it.
+ */
+#define RTR0MemObjLockUser(pMemObj, R3Ptr, cb, fAccess, R0Process) \
+    RTR0MemObjLockUserTag((pMemObj), (R3Ptr), (cb), (fAccess), (R0Process), RTMEM_TAG)
+
+/**
+ * Locks a range of user virtual memory (custom tag).
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   R3Ptr           User virtual address. This is rounded down to a page
+ *                          boundary.
+ * @param   cb              Number of bytes to lock. This is rounded up to
+ *                          nearest page boundary.
+ * @param   fAccess         The desired access, a combination of RTMEM_PROT_READ
+ *                          and RTMEM_PROT_WRITE.
+ * @param   R0Process       The process to lock pages in. NIL_R0PROCESS is an
+ *                          alias for the current one.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ *
+ * @remarks RTR0MemGetAddressR3() and RTR0MemGetAddress() will return therounded
+ *          down address.
+ *
+ * @remarks Linux: This API requires that the memory begin locked is in a memory
+ *          mapping that is not required in any forked off child process. This
+ *          is not intented as permanent restriction, feel free to help out
+ *          lifting it.
+ */
+RTR0DECL(int) RTR0MemObjLockUserTag(PRTR0MEMOBJ pMemObj, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess,
+                                    RTR0PROCESS R0Process, const char *pszTag);
+
+/**
+ * Locks a range of kernel virtual memory (default tag).
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   pv              Kernel virtual address. This is rounded down to a page boundary.
+ * @param   cb              Number of bytes to lock. This is rounded up to nearest page boundary.
+ * @param   fAccess         The desired access, a combination of RTMEM_PROT_READ
+ *                          and RTMEM_PROT_WRITE.
+ *
+ * @remark  RTR0MemGetAddress() will return the rounded down address.
+ */
+#define RTR0MemObjLockKernel(pMemObj, pv, cb, fAccess) \
+    RTR0MemObjLockKernelTag((pMemObj), (pv), (cb), (fAccess), RTMEM_TAG)
+
+/**
+ * Locks a range of kernel virtual memory (custom tag).
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   pv              Kernel virtual address. This is rounded down to a page boundary.
+ * @param   cb              Number of bytes to lock. This is rounded up to nearest page boundary.
+ * @param   fAccess         The desired access, a combination of RTMEM_PROT_READ
+ *                          and RTMEM_PROT_WRITE.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ *
+ * @remark  RTR0MemGetAddress() will return the rounded down address.
+ */
+RTR0DECL(int) RTR0MemObjLockKernelTag(PRTR0MEMOBJ pMemObj, void *pv, size_t cb, uint32_t fAccess, const char *pszTag);
+
+/**
+ * Allocates contiguous page aligned physical memory without (necessarily) any
+ * kernel mapping (default tag).
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate. This is rounded up to nearest page.
+ * @param   PhysHighest     The highest permitable address (inclusive).
+ *                          Pass NIL_RTHCPHYS if any address is acceptable.
+ */
+#define RTR0MemObjAllocPhys(pMemObj, cb, PhysHighest) \
+    RTR0MemObjAllocPhysTag((pMemObj), (cb), (PhysHighest), RTMEM_TAG)
+
+/**
+ * Allocates contiguous page aligned physical memory without (necessarily) any
+ * kernel mapping (custom tag).
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate. This is rounded up to nearest page.
+ * @param   PhysHighest     The highest permitable address (inclusive).
+ *                          Pass NIL_RTHCPHYS if any address is acceptable.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTR0DECL(int) RTR0MemObjAllocPhysTag(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest, const char *pszTag);
+
+/**
+ * Allocates contiguous physical memory without (necessarily) any kernel mapping
+ * (default tag).
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate. This is rounded up to nearest page.
+ * @param   PhysHighest     The highest permitable address (inclusive).
+ *                          Pass NIL_RTHCPHYS if any address is acceptable.
+ * @param   uAlignment      The alignment of the reserved memory.
+ *                          Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M, _4M and _1G.
+ */
+#define RTR0MemObjAllocPhysEx(pMemObj, cb, PhysHighest, uAlignment) \
+    RTR0MemObjAllocPhysExTag((pMemObj), (cb), (PhysHighest), (uAlignment), RTMEM_TAG)
+
+/**
+ * Allocates contiguous physical memory without (necessarily) any kernel mapping
+ * (custom tag).
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate. This is rounded up to nearest page.
+ * @param   PhysHighest     The highest permitable address (inclusive).
+ *                          Pass NIL_RTHCPHYS if any address is acceptable.
+ * @param   uAlignment      The alignment of the reserved memory.
+ *                          Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M, _4M and _1G.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTR0DECL(int) RTR0MemObjAllocPhysExTag(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment, const char *pszTag);
+
+/**
+ * Allocates non-contiguous page aligned physical memory without (necessarily)
+ * any kernel mapping (default tag).
+ *
+ * This API is for allocating huge amounts of pages and will return
+ * VERR_NOT_SUPPORTED if this cannot be implemented in a satisfactory
+ * manner.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NOT_SUPPORTED if it's not possible to allocated unmapped
+ *          physical memory on this platform. The caller should expect
+ *          this error and have a fallback strategy for it.
+ *
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate. This is rounded up to nearest page.
+ * @param   PhysHighest     The highest permitable address (inclusive).
+ *                          Pass NIL_RTHCPHYS if any address is acceptable.
+ */
+#define RTR0MemObjAllocPhysNC(pMemObj, cb, PhysHighest) \
+    RTR0MemObjAllocPhysNCTag((pMemObj), (cb), (PhysHighest), RTMEM_TAG)
+
+/**
+ * Allocates non-contiguous page aligned physical memory without (necessarily)
+ * any kernel mapping (custom tag).
+ *
+ * This API is for allocating huge amounts of pages and will return
+ * VERR_NOT_SUPPORTED if this cannot be implemented in a satisfactory
+ * manner.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NOT_SUPPORTED if it's not possible to allocated unmapped
+ *          physical memory on this platform. The caller should expect
+ *          this error and have a fallback strategy for it.
+ *
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   cb              Number of bytes to allocate. This is rounded up to nearest page.
+ * @param   PhysHighest     The highest permitable address (inclusive).
+ *                          Pass NIL_RTHCPHYS if any address is acceptable.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTR0DECL(int) RTR0MemObjAllocPhysNCTag(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest, const char *pszTag);
+
+/** Memory cache policy for RTR0MemObjEnterPhys.
+ * @{
+ */
+/** Default caching policy -- don't care. */
+#define RTMEM_CACHE_POLICY_DONT_CARE    UINT32_C(0)
+/** MMIO caching policy -- uncachable. */
+#define RTMEM_CACHE_POLICY_MMIO         UINT32_C(1)
+/** @} */
+
+/**
+ * Creates a page aligned, contiguous, physical memory object (default tag).
+ *
+ * No physical memory is allocated, we trust you do know what you're doing.
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   Phys            The physical address to start at. This is rounded down to the
+ *                          nearest page boundary.
+ * @param   cb              The size of the object in bytes. This is rounded up to nearest page boundary.
+ * @param   uCachePolicy    One of the RTMEM_CACHE_XXX modes.
+ */
+#define RTR0MemObjEnterPhys(pMemObj, Phys, cb, uCachePolicy) \
+    RTR0MemObjEnterPhysTag((pMemObj), (Phys), (cb), (uCachePolicy), RTMEM_TAG)
+
+/**
+ * Creates a page aligned, contiguous, physical memory object (custom tag).
+ *
+ * No physical memory is allocated, we trust you do know what you're doing.
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   Phys            The physical address to start at. This is rounded down to the
+ *                          nearest page boundary.
+ * @param   cb              The size of the object in bytes. This is rounded up to nearest page boundary.
+ * @param   uCachePolicy    One of the RTMEM_CACHE_XXX modes.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTR0DECL(int) RTR0MemObjEnterPhysTag(PRTR0MEMOBJ pMemObj, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy, const char *pszTag);
+
+/**
+ * Reserves kernel virtual address space (default tag).
+ *
+ * If this function fails with VERR_NOT_SUPPORTED, the idea is that you
+ * can use RTR0MemObjEnterPhys() + RTR0MemObjMapKernel() as a fallback if
+ * you have a safe physical address range to make use of...
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   pvFixed         Requested address. (void *)-1 means any address. This must match the alignment.
+ * @param   cb              The number of bytes to reserve. This is rounded up to nearest page.
+ * @param   uAlignment      The alignment of the reserved memory.
+ *                          Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
+ */
+#define RTR0MemObjReserveKernel(pMemObj, pvFixed, cb, uAlignment) \
+    RTR0MemObjReserveKernelTag((pMemObj), (pvFixed), (cb), (uAlignment), RTMEM_TAG)
+
+/**
+ * Reserves kernel virtual address space (custom tag).
+ *
+ * If this function fails with VERR_NOT_SUPPORTED, the idea is that you
+ * can use RTR0MemObjEnterPhys() + RTR0MemObjMapKernel() as a fallback if
+ * you have a safe physical address range to make use of...
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   pvFixed         Requested address. (void *)-1 means any address. This must match the alignment.
+ * @param   cb              The number of bytes to reserve. This is rounded up to nearest page.
+ * @param   uAlignment      The alignment of the reserved memory.
+ *                          Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTR0DECL(int) RTR0MemObjReserveKernelTag(PRTR0MEMOBJ pMemObj, void *pvFixed, size_t cb, size_t uAlignment, const char *pszTag);
+
+/**
+ * Reserves user virtual address space in the current process (default tag).
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   R3PtrFixed      Requested address. (RTR3PTR)-1 means any address. This must match the alignment.
+ * @param   cb              The number of bytes to reserve. This is rounded up to nearest PAGE_SIZE.
+ * @param   uAlignment      The alignment of the reserved memory.
+ *                          Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
+ * @param   R0Process       The process to reserve the memory in. NIL_R0PROCESS is an alias for the current one.
+ */
+#define RTR0MemObjReserveUser(pMemObj, R3PtrFixed, cb, uAlignment, R0Process) \
+    RTR0MemObjReserveUserTag((pMemObj), (R3PtrFixed), (cb), (uAlignment), (R0Process), RTMEM_TAG)
+
+/**
+ * Reserves user virtual address space in the current process (custom tag).
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle.
+ * @param   R3PtrFixed      Requested address. (RTR3PTR)-1 means any address. This must match the alignment.
+ * @param   cb              The number of bytes to reserve. This is rounded up to nearest PAGE_SIZE.
+ * @param   uAlignment      The alignment of the reserved memory.
+ *                          Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
+ * @param   R0Process       The process to reserve the memory in. NIL_R0PROCESS is an alias for the current one.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTR0DECL(int) RTR0MemObjReserveUserTag(PRTR0MEMOBJ pMemObj, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment,
+                                       RTR0PROCESS R0Process, const char *pszTag);
+
+/**
+ * Maps a memory object into kernel virtual address space (default tag).
+ *
+ * This is the same as calling RTR0MemObjMapKernelEx with cbSub and offSub set
+ * to zero.
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle of the mapping object.
+ * @param   MemObjToMap     The object to be map.
+ * @param   pvFixed         Requested address. (void *)-1 means any address. This must match the alignment.
+ * @param   uAlignment      The alignment of the reserved memory.
+ *                          Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
+ * @param   fProt           Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE).
+ */
+#define RTR0MemObjMapKernel(pMemObj, MemObjToMap, pvFixed, uAlignment, fProt) \
+    RTR0MemObjMapKernelTag((pMemObj), (MemObjToMap), (pvFixed), (uAlignment), (fProt), RTMEM_TAG)
+
+/**
+ * Maps a memory object into kernel virtual address space (custom tag).
+ *
+ * This is the same as calling RTR0MemObjMapKernelEx with cbSub and offSub set
+ * to zero.
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle of the mapping object.
+ * @param   MemObjToMap     The object to be map.
+ * @param   pvFixed         Requested address. (void *)-1 means any address. This must match the alignment.
+ * @param   uAlignment      The alignment of the reserved memory.
+ *                          Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
+ * @param   fProt           Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE).
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTR0DECL(int) RTR0MemObjMapKernelTag(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, void *pvFixed,
+                                     size_t uAlignment, unsigned fProt, const char *pszTag);
+
+/**
+ * Maps a memory object into kernel virtual address space (default tag).
+ *
+ * The ability to map subsections of the object into kernel space is currently
+ * not implemented on all platforms. All/Most of platforms supports mapping the
+ * whole object into  kernel space.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NOT_SUPPORTED if it's not possible to map a subsection of a
+ *          memory object on this platform. When you hit this, try implement it.
+ *
+ * @param   pMemObj         Where to store the ring-0 memory object handle of the mapping object.
+ * @param   MemObjToMap     The object to be map.
+ * @param   pvFixed         Requested address. (void *)-1 means any address. This must match the alignment.
+ * @param   uAlignment      The alignment of the reserved memory.
+ *                          Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
+ * @param   fProt           Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE).
+ * @param   offSub          Where in the object to start mapping. If non-zero
+ *                          the value must be page aligned and cbSub must be
+ *                          non-zero as well.
+ * @param   cbSub           The size of the part of the object to be mapped. If
+ *                          zero the entire object is mapped. The value must be
+ *                          page aligned.
+ */
+#define RTR0MemObjMapKernelEx(pMemObj, MemObjToMap, pvFixed, uAlignment, fProt, offSub, cbSub) \
+    RTR0MemObjMapKernelExTag((pMemObj), (MemObjToMap), (pvFixed), (uAlignment), (fProt), (offSub), (cbSub), RTMEM_TAG)
+
+/**
+ * Maps a memory object into kernel virtual address space (custom tag).
+ *
+ * The ability to map subsections of the object into kernel space is currently
+ * not implemented on all platforms. All/Most of platforms supports mapping the
+ * whole object into  kernel space.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NOT_SUPPORTED if it's not possible to map a subsection of a
+ *          memory object on this platform. When you hit this, try implement it.
+ *
+ * @param   pMemObj         Where to store the ring-0 memory object handle of the mapping object.
+ * @param   MemObjToMap     The object to be map.
+ * @param   pvFixed         Requested address. (void *)-1 means any address. This must match the alignment.
+ * @param   uAlignment      The alignment of the reserved memory.
+ *                          Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
+ * @param   fProt           Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE).
+ * @param   offSub          Where in the object to start mapping. If non-zero
+ *                          the value must be page aligned and cbSub must be
+ *                          non-zero as well.
+ * @param   cbSub           The size of the part of the object to be mapped. If
+ *                          zero the entire object is mapped. The value must be
+ *                          page aligned.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTR0DECL(int) RTR0MemObjMapKernelExTag(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, void *pvFixed, size_t uAlignment,
+                                       unsigned fProt, size_t offSub, size_t cbSub, const char *pszTag);
+
+/**
+ * Maps a memory object into user virtual address space in the current process
+ * (default tag).
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle of the mapping object.
+ * @param   MemObjToMap     The object to be map.
+ * @param   R3PtrFixed      Requested address. (RTR3PTR)-1 means any address. This must match the alignment.
+ * @param   uAlignment      The alignment of the reserved memory.
+ *                          Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
+ * @param   fProt           Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE).
+ * @param   R0Process       The process to map the memory into. NIL_R0PROCESS is an alias for the current one.
+ */
+#define RTR0MemObjMapUser(pMemObj, MemObjToMap, R3PtrFixed, uAlignment, fProt, R0Process) \
+    RTR0MemObjMapUserTag((pMemObj), (MemObjToMap), (R3PtrFixed), (uAlignment), (fProt), (R0Process), RTMEM_TAG)
+
+/**
+ * Maps a memory object into user virtual address space in the current process
+ * (custom tag).
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle of the mapping object.
+ * @param   MemObjToMap     The object to be map.
+ * @param   R3PtrFixed      Requested address. (RTR3PTR)-1 means any address. This must match the alignment.
+ * @param   uAlignment      The alignment of the reserved memory.
+ *                          Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
+ * @param   fProt           Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE).
+ * @param   R0Process       The process to map the memory into. NIL_R0PROCESS is an alias for the current one.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTR0DECL(int) RTR0MemObjMapUserTag(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, RTR3PTR R3PtrFixed,
+                                   size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process, const char *pszTag);
+
+/**
+ * Change the page level protection of one or more pages in a memory object.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NOT_SUPPORTED if the OS doesn't provide any way to manipulate
+ *          page level protection. The caller must handle this status code
+ *          gracefully. (Note that it may also occur if the implementation is
+ *          missing, in which case just go ahead and implement it.)
+ *
+ * @param   hMemObj         Memory object handle.
+ * @param   offSub          Offset into the memory object. Must be page aligned.
+ * @param   cbSub           Number of bytes to change the protection of. Must be
+ *                          page aligned.
+ * @param   fProt           Combination of RTMEM_PROT_* flags.
+ */
+RTR0DECL(int) RTR0MemObjProtect(RTR0MEMOBJ hMemObj, size_t offSub, size_t cbSub, uint32_t fProt);
+
+#endif /* IN_RING0 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/mp.h b/ubuntu/vbox/include/iprt/mp.h
new file mode 100644 (file)
index 0000000..ad7d3e2
--- /dev/null
@@ -0,0 +1,508 @@
+/** @file
+ * IPRT - Multiprocessor.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+#ifndef ___iprt_mp_h
+#define ___iprt_mp_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_mp RTMp - Multiprocessor
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Gets the identifier of the CPU executing the call.
+ *
+ * When called from a system mode where scheduling is active, like ring-3 or
+ * kernel mode with interrupts enabled on some systems, no assumptions should
+ * be made about the current CPU when the call returns.
+ *
+ * @returns CPU Id.
+ */
+RTDECL(RTCPUID) RTMpCpuId(void);
+
+/**
+ * Get the CPU set index of the CPU executing the call.
+ *
+ * Same scheduling warnings as for RTMpCpuId().
+ *
+ * @returns CPU set index.
+ */
+RTDECL(int) RTMpCurSetIndex(void);
+
+/**
+ * Get the CPU set index and identifier of the CPU executing the call.
+ *
+ * Same scheduling warnings as for RTMpCpuId().
+ *
+ * @returns CPU set index.
+ * @param   pidCpu      Where to return the CPU identifier. (not optional)
+ */
+RTDECL(int) RTMpCurSetIndexAndId(PRTCPUID pidCpu);
+
+/**
+ * Converts a CPU identifier to a CPU set index.
+ *
+ * This may or may not validate the presence of the CPU.
+ *
+ * @returns The CPU set index on success, -1 on failure.
+ * @param   idCpu       The identifier of the CPU.
+ */
+RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu);
+
+/**
+ * Converts a CPU set index to a a CPU identifier.
+ *
+ * This may or may not validate the presence of the CPU, so, use
+ * RTMpIsCpuPossible for that.
+ *
+ * @returns The corresponding CPU identifier, NIL_RTCPUID on failure.
+ * @param   iCpu    The CPU set index.
+ */
+RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu);
+
+/**
+ * Translates an NT process group member to a CPU set index.
+ *
+ * @returns CPU set index, -1 if not valid.
+ * @param   idxGroup        The CPU group.
+ * @param   idxMember       The CPU group member number.
+ *
+ * @remarks Only available on Windows.
+ */
+RTDECL(int) RTMpSetIndexFromCpuGroupMember(uint32_t idxGroup, uint32_t idxMember);
+
+/**
+ * Gets the member numbers for a CPU group.
+ *
+ * @returns Maximum number of group members.
+ * @param   idxGroup        The CPU group.
+ * @param   pcActive        Where to return the number of active members.
+ *
+ * @remarks Only available on Windows.
+ */
+RTDECL(uint32_t) RTMpGetCpuGroupCounts(uint32_t idxGroup, uint32_t *pcActive);
+
+/**
+ * Get the maximum number of CPU groups.
+ *
+ * @returns Maximum number of CPU groups.
+ *
+ * @remarks Only available on Windows.
+ */
+RTDECL(uint32_t) RTMpGetMaxCpuGroupCount(void);
+
+/**
+ * Gets the max CPU identifier (inclusive).
+ *
+ * Intended for brute force enumerations, but use with
+ * care as it may be expensive.
+ *
+ * @returns The current higest CPU identifier value.
+ */
+RTDECL(RTCPUID) RTMpGetMaxCpuId(void);
+
+/**
+ * Gets the size of a CPU array that is indexed by CPU set index.
+ *
+ * This takes both online, offline and hot-plugged cpus into account.
+ *
+ * @returns Number of elements.
+ *
+ * @remarks Use RTMpCpuIdToSetIndex to convert a RTCPUID into an array index.
+ */
+RTDECL(uint32_t) RTMpGetArraySize(void);
+
+/**
+ * Checks if a CPU exists in the system or may possibly be hotplugged later.
+ *
+ * @returns true/false accordingly.
+ * @param   idCpu       The identifier of the CPU.
+ */
+RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu);
+
+/**
+ * Gets set of the CPUs present in the system plus any that may
+ * possibly be hotplugged later.
+ *
+ * @returns pSet.
+ * @param   pSet    Where to put the set.
+ */
+RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet);
+
+/**
+ * Get the count of CPUs present in the system plus any that may
+ * possibly be hotplugged later.
+ *
+ * @returns The count.
+ * @remarks Don't use this for CPU array sizing, use RTMpGetArraySize instead.
+ */
+RTDECL(RTCPUID) RTMpGetCount(void);
+
+/**
+ * Get the count of physical CPU cores present in the system plus any that may
+ * possibly be hotplugged later.
+ *
+ * @returns The number of cores.
+ */
+RTDECL(RTCPUID) RTMpGetCoreCount(void);
+
+/**
+ * Gets set of the CPUs present that are currently online.
+ *
+ * @returns pSet.
+ * @param   pSet    Where to put the set.
+ */
+RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet);
+
+/**
+ * Get the count of CPUs that are currently online.
+ *
+ * @return The count.
+ */
+RTDECL(RTCPUID) RTMpGetOnlineCount(void);
+
+/**
+ * Get the count of physical CPU cores in the system with one or more online
+ * threads.
+ *
+ * @returns The number of online cores.
+ */
+RTDECL(RTCPUID) RTMpGetOnlineCoreCount(void);
+
+/**
+ * Checks if a CPU is online or not.
+ *
+ * @returns true/false accordingly.
+ * @param   idCpu       The identifier of the CPU.
+ */
+RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu);
+
+
+/**
+ * Gets set of the CPUs present in the system.
+ *
+ * @returns pSet.
+ * @param   pSet    Where to put the set.
+ */
+RTDECL(PRTCPUSET) RTMpGetPresentSet(PRTCPUSET pSet);
+
+/**
+ * Get the count of CPUs that are present in the system.
+ *
+ * @return The count.
+ */
+RTDECL(RTCPUID) RTMpGetPresentCount(void);
+
+/**
+ * Get the count of physical CPU cores present in the system.
+ *
+ * @returns The number of cores.
+ */
+RTDECL(RTCPUID) RTMpGetPresentCoreCount(void);
+
+/**
+ * Checks if a CPU is present in the system.
+ *
+ * @returns true/false accordingly.
+ * @param   idCpu       The identifier of the CPU.
+ */
+RTDECL(bool) RTMpIsCpuPresent(RTCPUID idCpu);
+
+
+/**
+ * Get the current frequency of a CPU.
+ *
+ * The CPU must be online.
+ *
+ * @returns The frequency as MHz. 0 if the CPU is offline
+ *          or the information is not available.
+ * @param   idCpu       The identifier of the CPU.
+ */
+RTDECL(uint32_t) RTMpGetCurFrequency(RTCPUID idCpu);
+
+/**
+ * Get the maximum frequency of a CPU.
+ *
+ * The CPU must be online.
+ *
+ * @returns The frequency as MHz. 0 if the CPU is offline
+ *          or the information is not available.
+ * @param   idCpu       The identifier of the CPU.
+ */
+RTDECL(uint32_t) RTMpGetMaxFrequency(RTCPUID idCpu);
+
+/**
+ * Get the CPU description string.
+ *
+ * The CPU must be online.
+ *
+ * @returns IPRT status code.
+ * @param   idCpu       The identifier of the CPU.  NIL_RTCPUID can be used to
+ *                      indicate the current CPU.
+ * @param   pszBuf      The output buffer.
+ * @param   cbBuf       The size of the output buffer.
+ */
+RTDECL(int) RTMpGetDescription(RTCPUID idCpu, char *pszBuf, size_t cbBuf);
+
+
+#ifdef IN_RING0
+
+/**
+ * Check if there's work (DPCs on Windows) pending on the current CPU.
+ *
+ * @return true if there's pending work on the current CPU, false otherwise.
+ */
+RTDECL(bool) RTMpIsCpuWorkPending(void);
+
+
+/**
+ * Worker function passed to RTMpOnAll, RTMpOnOthers and RTMpOnSpecific that
+ * is to be called on the target cpus.
+ *
+ * @param   idCpu       The identifier for the CPU the function is called on.
+ * @param   pvUser1     The 1st user argument.
+ * @param   pvUser2     The 2nd user argument.
+ */
+typedef DECLCALLBACK(void) FNRTMPWORKER(RTCPUID idCpu, void *pvUser1, void *pvUser2);
+/** Pointer to a FNRTMPWORKER. */
+typedef FNRTMPWORKER *PFNRTMPWORKER;
+
+/** @name RTMPON_F_XXX - RTMpOn flags.
+ * @{ */
+/** Caller doesn't care if pfnWorker is executed at the same time on the
+ *  specified CPUs or not, as long as it gets executed. */
+#define RTMPON_F_WHATEVER_EXEC      0
+/** The caller insists on pfnWorker being executed more or less concurrently
+ * on the specified CPUs. */
+#define RTMPON_F_CONCURRENT_EXEC    RT_BIT_32(1)
+/** Mask of valid bits. */
+#define RTMPON_F_VALID_MASK         UINT32_C(0x00000001)
+/** @}*/
+
+/**
+ * Checks if the RTMpOnAll() is safe with regards to all threads executing
+ * concurrently.
+ *
+ * If for instance, the RTMpOnAll() is implemented in a way where the threads
+ * might cause a classic deadlock, it is considered -not- concurrent safe.
+ * Windows currently is one such platform where it isn't safe.
+ *
+ * @returns true if RTMpOnAll() is concurrent safe, false otherwise.
+ */
+RTDECL(bool) RTMpOnAllIsConcurrentSafe(void);
+
+/**
+ * Executes a function on each (online) CPU in the system.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_NOT_SUPPORTED if this kind of operation isn't supported by the system.
+ *
+ * @param   pfnWorker       The worker function.
+ * @param   pvUser1         The first user argument for the worker.
+ * @param   pvUser2         The second user argument for the worker.
+ *
+ * @remarks The execution isn't in any way guaranteed to be simultaneous,
+ *          it might even be serial (cpu by cpu).
+ */
+RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2);
+
+/**
+ * Executes a function on a all other (online) CPUs in the system.
+ *
+ * The caller must disable preemption prior to calling this API if the outcome
+ * is to make any sense. But do *not* disable interrupts.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_NOT_SUPPORTED if this kind of operation isn't supported by the system.
+ *
+ * @param   pfnWorker       The worker function.
+ * @param   pvUser1         The first user argument for the worker.
+ * @param   pvUser2         The second user argument for the worker.
+ *
+ * @remarks The execution isn't in any way guaranteed to be simultaneous,
+ *          it might even be serial (cpu by cpu).
+ */
+RTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2);
+
+/**
+ * Executes a function on a specific CPU in the system.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_NOT_SUPPORTED if this kind of operation isn't supported by the system.
+ * @retval  VERR_CPU_OFFLINE if the CPU is offline.
+ * @retval  VERR_CPU_NOT_FOUND if the CPU wasn't found.
+ *
+ * @param   idCpu           The id of the CPU.
+ * @param   pfnWorker       The worker function.
+ * @param   pvUser1         The first user argument for the worker.
+ * @param   pvUser2         The second user argument for the worker.
+ */
+RTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2);
+
+/**
+ * Executes a function on two specific CPUs in the system.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_NOT_SUPPORTED if this kind of operation isn't supported by the
+ *          system or if the specified modifier flag isn't supported.
+ * @retval  VERR_CPU_OFFLINE if one or more of the CPUs are offline (see
+ *          remarks).
+ * @retval  VERR_CPU_NOT_FOUND if on or both of the CPUs weren't found.
+ * @retval  VERR_NOT_ALL_CPUS_SHOWED if one of the CPUs didn't show.
+ *
+ * @param   idCpu1          The id of the first CPU.
+ * @param   idCpu2          The id of the second CPU.
+ * @param   fFlags          Combination of RTMPON_F_XXX flags.
+ * @param   pfnWorker       The worker function.
+ * @param   pvUser1         The first user argument for the worker.
+ * @param   pvUser2         The second user argument for the worker.
+ *
+ * @remarks There is a possible race between one (or both) of the CPUs going
+ *          offline while setting up the call.  The worker function must take
+ *          this into account.
+ */
+RTDECL(int) RTMpOnPair(RTCPUID idCpu1, RTCPUID idCpu2, uint32_t fFlags, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2);
+
+/**
+ * Indicates whether RTMpOnPair supports running the pfnWorker concurrently on
+ * both CPUs using RTMPON_F_CONCURRENT_EXEC.
+ *
+ * @returns true if supported, false if not.
+ */
+RTDECL(bool) RTMpOnPairIsConcurrentExecSupported(void);
+
+
+/**
+ * Pokes the specified CPU.
+ *
+ * This should cause the execution on the CPU to be interrupted and forcing it
+ * to enter kernel context. It is optimized version of a RTMpOnSpecific call
+ * with a worker which returns immediately.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NOT_SUPPORTED if this kind of operation isn't supported by the
+ *          system. The caller must not automatically assume that this API works
+ *          when any of the RTMpOn* APIs works. This is because not all systems
+ *          supports unicast MP events and this API will not be implemented as a
+ *          broadcast.
+ * @retval  VERR_CPU_OFFLINE if the CPU is offline.
+ * @retval  VERR_CPU_NOT_FOUND if the CPU wasn't found.
+ *
+ * @param   idCpu           The id of the CPU to poke.
+ */
+RTDECL(int) RTMpPokeCpu(RTCPUID idCpu);
+
+
+/**
+ * MP event, see FNRTMPNOTIFICATION.
+ */
+typedef enum RTMPEVENT
+{
+    /** The CPU goes online. */
+    RTMPEVENT_ONLINE = 1,
+    /** The CPU goes offline. */
+    RTMPEVENT_OFFLINE
+} RTMPEVENT;
+
+/**
+ * Notification callback.
+ *
+ * The context this is called in differs a bit from platform to platform, so be
+ * careful while in here.
+ *
+ * On Windows we're running with IRQL=PASSIVE_LEVEL (reschedulable) according to
+ * the KeRegisterProcessorChangeCallback documentation - unrestricted API
+ * access. Probably not being called on the onlined/offlined CPU...
+ *
+ * On Solaris we're holding the cpu_lock, IPL/SPL/PIL is not yet known, however
+ * we will most likely -not- be firing on the CPU going offline/online.
+ *
+ * On Linux it looks like we're called with preemption enabled on any CPU and
+ * not necessarily on the CPU going offline/online.
+ *
+ * There is no callbacks for darwin at the moment, due to lack of suitable KPI.
+ *
+ * @param   idCpu       The CPU this applies to.
+ * @param   enmEvent    The event.
+ * @param   pvUser      The user argument.
+ */
+typedef DECLCALLBACK(void) FNRTMPNOTIFICATION(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvUser);
+/** Pointer to a FNRTMPNOTIFICATION(). */
+typedef FNRTMPNOTIFICATION *PFNRTMPNOTIFICATION;
+
+/**
+ * Registers a notification callback for cpu events.
+ *
+ * On platforms which doesn't do cpu offline/online events this API
+ * will just be a no-op that pretends to work.
+ *
+ * @todo We'll be adding a flag to this soon to indicate whether the callback should be called on all
+ *       CPUs that are currently online while it's being registered. This is to help avoid some race
+ *       conditions (we'll hopefully be able to implement this on linux, solaris/win is no issue).
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_NO_MEMORY if a registration record cannot be allocated.
+ * @retval  VERR_ALREADY_EXISTS if the pfnCallback and pvUser already exist
+ *          in the callback list.
+ *
+ * @param   pfnCallback     The callback.
+ * @param   pvUser          The user argument to the callback function.
+ */
+RTDECL(int) RTMpNotificationRegister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser);
+
+/**
+ * This deregisters a notification callback registered via RTMpNotificationRegister().
+ *
+ * The pfnCallback and pvUser arguments must be identical to the registration call
+ * of we won't find the right entry.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_NOT_FOUND if no matching entry was found.
+ *
+ * @param   pfnCallback     The callback.
+ * @param   pvUser          The user argument to the callback function.
+ */
+RTDECL(int) RTMpNotificationDeregister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser);
+
+#endif /* IN_RING0 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/net.h b/ubuntu/vbox/include/iprt/net.h
new file mode 100644 (file)
index 0000000..3f43a9c
--- /dev/null
@@ -0,0 +1,1010 @@
+/** @file
+ * IPRT - Network Protocols.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+#ifndef ___iprt_net_h
+#define ___iprt_net_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/assert.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_net     RTNet - Network Protocols
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Converts an stringified Ethernet MAC address into the RTMAC representation.
+ *
+ * @todo This should be move to some generic part of the runtime.
+ *
+ * @returns VINF_SUCCESS on success, VERR_GETOPT_INVALID_ARGUMENT_FORMAT on
+ *          failure.
+ *
+ * @param   pszAddr         The address string to convert.
+ * @param   pMacAddr        Where to store the result.
+ */
+RTDECL(int) RTNetStrToMacAddr(const char *pszAddr, PRTMAC pMacAddr);
+
+/**
+ * IPv4 address.
+ */
+typedef RTUINT32U RTNETADDRIPV4;
+AssertCompileSize(RTNETADDRIPV4, 4);
+/** Pointer to a IPv4 address. */
+typedef RTNETADDRIPV4 *PRTNETADDRIPV4;
+/** Pointer to a const IPv4 address. */
+typedef RTNETADDRIPV4 const *PCRTNETADDRIPV4;
+
+/**
+ * Tests if the given string is an IPv4 address.
+ *
+ * @returns boolean.
+ * @param   pcszAddr        String which may be an IPv4 address.
+ */
+RTDECL(bool) RTNetIsIPv4AddrStr(const char *pcszAddr);
+
+/**
+ * Tests if the given string is a wildcard IPv4 address.
+ *
+ * @returns boolean.
+ * @param   pcszAddr        String which may be an IPv4 address.
+ */
+RTDECL(bool) RTNetStrIsIPv4AddrAny(const char *pcszAddr);
+
+/**
+ * Parses dotted-decimal IPv4 address into RTNETADDRIPV4 representation.
+ *
+ * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on
+ *          failure.
+ *
+ * @param   pcszAddr        The value to convert.
+ * @param   ppszNext        Where to store the pointer to the first char
+ *                            following the address. (Optional)
+ * @param   pAddr           Where to store the result.
+ */
+RTDECL(int) RTNetStrToIPv4AddrEx(const char *pcszAddr, PRTNETADDRIPV4 pAddr, char **ppszNext);
+
+/**
+ * Parses dotted-decimal IPv4 address into RTNETADDRIPV4 representation.
+ * Leading and trailing whitespace is ignored.
+ *
+ * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on
+ *          failure.
+ *
+ * @param   pcszAddr        The value to convert.
+ * @param   pAddr           Where to store the result.
+ */
+RTDECL(int) RTNetStrToIPv4Addr(const char *pcszAddr, PRTNETADDRIPV4 pAddr);
+
+/**
+ * Verifies that RTNETADDRIPV4 is a valid contiguous netmask and
+ * computes its prefix length.
+ *
+ * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on
+ *          failure.
+ *
+ * @param   pMask           The netmask to verify and convert.
+ * @param   piPrefix        Where to store the prefix length. (Optional)
+ */
+RTDECL(int) RTNetMaskToPrefixIPv4(PCRTNETADDRIPV4 pMask, int *piPrefix);
+
+/**
+ * Computes netmask corresponding to the prefix length.
+ *
+ * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on
+ *          failure.
+ *
+ * @param   iPrefix         The prefix to convert.
+ * @param   pMask           Where to store the netmask.
+ */
+RTDECL(int) RTNetPrefixToMaskIPv4(int iPrefix, PRTNETADDRIPV4 pMask);
+
+
+/**
+ * IPv6 address.
+ */
+typedef RTUINT128U RTNETADDRIPV6;
+AssertCompileSize(RTNETADDRIPV6, 16);
+/** Pointer to a IPv6 address. */
+typedef RTNETADDRIPV6 *PRTNETADDRIPV6;
+/** Pointer to a const IPv6 address. */
+typedef RTNETADDRIPV6 const *PCRTNETADDRIPV6;
+
+/**
+ * Tests if the given string is a valid IPv6 address.
+ *
+ * @returns @c true if it is, @c false if not.
+ * @param   pszAddress          String which may be an IPv6 address.
+ */
+RTDECL(bool) RTNetIsIPv6AddrStr(const char *pszAddress);
+
+/**
+ * Tests if the given string is a wildcard IPv6 address.
+ *
+ * @returns @c true if it is, @c false if not.
+ * @param   pszAddress          String which may be an IPv6 address.
+ */
+RTDECL(bool) RTNetStrIsIPv6AddrAny(const char *pszAddress);
+
+/**
+ * Parses IPv6 address into RTNETADDRIPV6 representation.
+ *
+ * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on
+ *          failure.
+ *
+ * @param   pcszAddr        The value to convert.
+ * @param   ppszNext        Where to store the pointer to the first char
+ *                            following the address. (Optional)
+ * @param   pAddr           Where to store the result.
+ */
+RTDECL(int) RTNetStrToIPv6AddrEx(const char *pcszAddr, PRTNETADDRIPV6 pAddr, char **ppszNext);
+
+/**
+ * Parses IPv6 address into RTNETADDRIPV6 representation.
+ * Leading and trailing whitespace is ignored.
+ *
+ * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on
+ *          failure.
+ *
+ * @param   pcszAddr        The value to convert.
+ * @param   ppszZone        Where to store the pointer to the first char
+ *                            of the zone id.  NULL is stored if there is
+ *                            no zone id.
+ * @param   pAddr           Where to store the result.
+ */
+RTDECL(int) RTNetStrToIPv6Addr(const char *pcszAddr, PRTNETADDRIPV6 pAddr, char **ppszZone);
+
+/**
+ * Verifies that RTNETADDRIPV6 is a valid contiguous netmask and
+ * computes its prefix length.
+ *
+ * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on
+ *          failure.
+ *
+ * @param   pMask           The netmask to verify and convert.
+ * @param   piPrefix        Where to store the prefix length. (Optional)
+ */
+RTDECL(int) RTNetMaskToPrefixIPv6(PCRTNETADDRIPV6 pMask, int *piPrefix);
+
+/**
+ * Computes netmask corresponding to the prefix length.
+ *
+ * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on
+ *          failure.
+ *
+ * @param   iPrefix         The prefix to convert.
+ * @param   pMask           Where to store the netmask.
+ */
+RTDECL(int) RTNetPrefixToMaskIPv6(int iPrefix, PRTNETADDRIPV6 pMask);
+
+
+/**
+ * IPX address.
+ */
+#pragma pack(1)
+typedef struct RTNETADDRIPX
+{
+    /** The network ID. */
+    uint32_t Network;
+    /** The node ID. (Defaults to the MAC address apparently.) */
+    RTMAC Node;
+} RTNETADDRIPX;
+#pragma pack()
+AssertCompileSize(RTNETADDRIPX, 4+6);
+/** Pointer to an IPX address. */
+typedef RTNETADDRIPX *PRTNETADDRIPX;
+/** Pointer to a const IPX address. */
+typedef RTNETADDRIPX const *PCRTNETADDRIPX;
+
+/**
+ * Network address union.
+ *
+ * @remarks The size of this structure may change in the future.
+ */
+typedef union RTNETADDRU
+{
+    /** 64-bit view. */
+    uint64_t au64[2];
+    /** 32-bit view. */
+    uint32_t au32[4];
+    /** 16-bit view. */
+    uint16_t au16[8];
+    /** 8-bit view. */
+    uint8_t  au8[16];
+    /** IPv4 view. */
+    RTNETADDRIPV4 IPv4;
+#ifndef IPv6 /* Work around X11 and RDP defining IPv6 to 1. */
+    /** IPv6 view. */
+    RTNETADDRIPV6 IPv6;
+#endif
+    /** IPX view. */
+    RTNETADDRIPX Ipx;
+    /** MAC address view. */
+    RTMAC Mac;
+} RTNETADDRU;
+AssertCompileSize(RTNETADDRU, 16);
+/** Pointer to an address union. */
+typedef RTNETADDRU *PRTNETADDRU;
+/** Pointer to a const address union. */
+typedef RTNETADDRU const *PCRTNETADDRU;
+
+/**
+ * Network address type.
+ *
+ * @remarks The value assignments may change in the future.
+ */
+typedef enum RTNETADDRTYPE
+{
+    /** The invalid 0 entry. */
+    RTNETADDRTYPE_INVALID = 0,
+    /** IP version 4. */
+    RTNETADDRTYPE_IPV4,
+    /** IP version 6. */
+    RTNETADDRTYPE_IPV6,
+    /** IPX. */
+    RTNETADDRTYPE_IPX,
+    /** MAC address. */
+    RTNETADDRTYPE_MAC,
+    /** The end of the valid values. */
+    RTNETADDRTYPE_END,
+    /** The usual 32-bit hack. */
+    RTNETADDRTYPE_32_BIT_HACK = 0x7fffffff
+} RTNETADDRTYPE;
+/** Pointer to a network address type. */
+typedef RTNETADDRTYPE *PRTNETADDRTYPE;
+/** Pointer to a const network address type. */
+typedef RTNETADDRTYPE const  *PCRTNETADDRTYPE;
+
+/**
+ * Network address.
+ *
+ * @remarks The size and type values may change.
+ */
+typedef struct RTNETADDR
+{
+    /** The address union. */
+    RTNETADDRU      uAddr;
+    /** Indicates which view of @a u that is valid. */
+    RTNETADDRTYPE   enmType;
+    /** The port number for IPv4 and IPv6 addresses.  This is set to
+     *  RTNETADDR_NA_PORT if not applicable. */
+    uint32_t        uPort;
+} RTNETADDR;
+/** Pointer to a network address. */
+typedef RTNETADDR *PRTNETADDR;
+/** Pointer to a const network address. */
+typedef RTNETADDR const *PCRTNETADDR;
+
+/** The not applicable value of  RTNETADDR::uPort value use to inid. */
+#define RTNETADDR_PORT_NA       UINT32_MAX
+
+/**
+ * Ethernet header.
+ */
+#pragma pack(1)
+typedef struct RTNETETHERHDR
+{
+    RTMAC       DstMac;
+    RTMAC       SrcMac;
+    /** Ethernet frame type or frame size, depending on the kind of ethernet.
+     * This is big endian on the wire. */
+    uint16_t    EtherType;
+} RTNETETHERHDR;
+#pragma pack()
+AssertCompileSize(RTNETETHERHDR, 14);
+/** Pointer to an ethernet header. */
+typedef RTNETETHERHDR *PRTNETETHERHDR;
+/** Pointer to a const ethernet header. */
+typedef RTNETETHERHDR const *PCRTNETETHERHDR;
+
+/** @name EtherType (RTNETETHERHDR::EtherType)
+ * @{ */
+#define RTNET_ETHERTYPE_IPV4    UINT16_C(0x0800)
+#define RTNET_ETHERTYPE_ARP     UINT16_C(0x0806)
+#define RTNET_ETHERTYPE_IPV6    UINT16_C(0x86dd)
+#define RTNET_ETHERTYPE_VLAN    UINT16_C(0x8100)
+#define RTNET_ETHERTYPE_IPX_1   UINT16_C(0x8037)
+#define RTNET_ETHERTYPE_IPX_2   UINT16_C(0x8137)
+#define RTNET_ETHERTYPE_IPX_3   UINT16_C(0x8138)
+/** @} */
+
+
+/**
+ * IPv4 header.
+ * All is bigendian on the wire.
+ */
+#pragma pack(1)
+typedef struct RTNETIPV4
+{
+#ifdef RT_BIG_ENDIAN
+    unsigned int    ip_v : 4;
+    unsigned int    ip_hl : 4;
+    unsigned int    ip_tos : 8;
+    unsigned int    ip_len : 16;
+#else
+    /** 00:0 - Header length given as a 32-bit word count. */
+    unsigned int    ip_hl : 4;
+    /** 00:4 - Header version. */
+    unsigned int    ip_v : 4;
+    /** 01 - Type of service. */
+    unsigned int    ip_tos : 8;
+    /** 02 - Total length (header + data). */
+    unsigned int    ip_len : 16;
+#endif
+    /** 04 - Packet idenficiation. */
+    uint16_t        ip_id;
+    /** 06 - Offset if fragmented. */
+    uint16_t        ip_off;
+    /** 08 - Time to live. */
+    uint8_t         ip_ttl;
+    /** 09 - Protocol. */
+    uint8_t         ip_p;
+    /** 0a - Header check sum. */
+    uint16_t        ip_sum;
+    /** 0c - Source address. */
+    RTNETADDRIPV4   ip_src;
+    /** 10 - Destination address. */
+    RTNETADDRIPV4   ip_dst;
+    /** 14 - Options (optional). */
+    uint32_t        ip_options[1];
+} RTNETIPV4;
+#pragma pack()
+AssertCompileSize(RTNETIPV4, 6 * 4);
+/** Pointer to a IPv4 header. */
+typedef RTNETIPV4 *PRTNETIPV4;
+/** Pointer to a const IPv4 header. */
+typedef RTNETIPV4 const *PCRTNETIPV4;
+
+/** The minimum IPv4 header length (in bytes).
+ * Up to and including RTNETIPV4::ip_dst. */
+#define RTNETIPV4_MIN_LEN   (20)
+
+
+/** @name IPv4 Protocol Numbers
+ * @{ */
+/** IPv4: ICMP */
+#define RTNETIPV4_PROT_ICMP     (1)
+/** IPv4: TCP */
+#define RTNETIPV4_PROT_TCP      (6)
+/** IPv4: UDP */
+#define RTNETIPV4_PROT_UDP      (17)
+/** @} */
+
+/** @name Common IPv4 Port Assignments
+ * @{
+ */
+/** Boostrap Protocol / DHCP) Server. */
+#define RTNETIPV4_PORT_BOOTPS   (67)
+/** Boostrap Protocol / DHCP) Client. */
+#define RTNETIPV4_PORT_BOOTPC   (68)
+/** @} */
+
+/** @name IPv4 Flags
+ * @{ */
+/** IPv4: Don't fragment */
+#define RTNETIPV4_FLAGS_DF      (0x4000)
+/** IPv4: More fragments */
+#define RTNETIPV4_FLAGS_MF      (0x2000)
+/** @} */
+
+RTDECL(uint16_t) RTNetIPv4HdrChecksum(PCRTNETIPV4 pIpHdr);
+RTDECL(bool)     RTNetIPv4IsHdrValid(PCRTNETIPV4 pIpHdr, size_t cbHdrMax, size_t cbPktMax, bool fChecksum);
+RTDECL(uint32_t) RTNetIPv4PseudoChecksum(PCRTNETIPV4 pIpHdr);
+RTDECL(uint32_t) RTNetIPv4PseudoChecksumBits(RTNETADDRIPV4 SrcAddr, RTNETADDRIPV4 DstAddr, uint8_t bProtocol, uint16_t cbPkt);
+RTDECL(uint32_t) RTNetIPv4AddDataChecksum(void const *pvData, size_t cbData, uint32_t u32Sum, bool *pfOdd);
+RTDECL(uint16_t) RTNetIPv4FinalizeChecksum(uint32_t u32Sum);
+
+
+/**
+ * IPv6 header.
+ * All is bigendian on the wire.
+ */
+#pragma pack(1)
+typedef struct RTNETIPV6
+{
+    /** Version (4 bits), Traffic Class (8 bits) and Flow Lable (20 bits).
+     * @todo this is probably mislabeled - ip6_flow vs. ip6_vfc, fix later. */
+    uint32_t        ip6_vfc;
+    /** 04 - Payload length, including extension headers. */
+    uint16_t        ip6_plen;
+    /** 06 - Next header type (RTNETIPV4_PROT_XXX). */
+    uint8_t         ip6_nxt;
+    /** 07 - Hop limit. */
+    uint8_t         ip6_hlim;
+    /** xx - Source address. */
+    RTNETADDRIPV6   ip6_src;
+    /** xx - Destination address. */
+    RTNETADDRIPV6   ip6_dst;
+} RTNETIPV6;
+#pragma pack()
+AssertCompileSize(RTNETIPV6, 8 + 16 + 16);
+/** Pointer to a IPv6 header. */
+typedef RTNETIPV6 *PRTNETIPV6;
+/** Pointer to a const IPv6 header. */
+typedef RTNETIPV6 const *PCRTNETIPV6;
+
+/** The minimum IPv6 header length (in bytes).
+ * Up to and including RTNETIPV6::ip6_dst. */
+#define RTNETIPV6_MIN_LEN                           (40)
+#define RTNETIPV6_ICMPV6_ND_WITH_LLA_OPT_MIN_LEN    (32)
+
+RTDECL(uint32_t) RTNetIPv6PseudoChecksum(PCRTNETIPV6 pIpHdr);
+RTDECL(uint32_t) RTNetIPv6PseudoChecksumEx(PCRTNETIPV6 pIpHdr, uint8_t bProtocol, uint16_t cbPkt);
+RTDECL(uint32_t) RTNetIPv6PseudoChecksumBits(PCRTNETADDRIPV6 pSrcAddr, PCRTNETADDRIPV6 pDstAddr,
+                                             uint8_t bProtocol, uint16_t cbPkt);
+
+
+/**
+ * UDP header.
+ */
+#pragma pack(1)
+typedef struct RTNETUDP
+{
+    /** The source port. */
+    uint16_t    uh_sport;
+    /** The destination port. */
+    uint16_t    uh_dport;
+    /** The length of the UDP header and associated data. */
+    uint16_t    uh_ulen;
+    /** The checksum of the pseudo header, the UDP header and the data. */
+    uint16_t    uh_sum;
+} RTNETUDP;
+#pragma pack()
+AssertCompileSize(RTNETUDP, 8);
+/** Pointer to an UDP header. */
+typedef RTNETUDP *PRTNETUDP;
+/** Pointer to a const UDP header. */
+typedef RTNETUDP const *PCRTNETUDP;
+
+/** The minimum UDP packet length (in bytes). (RTNETUDP::uh_ulen) */
+#define RTNETUDP_MIN_LEN   (8)
+
+RTDECL(uint16_t) RTNetUDPChecksum(uint32_t u32Sum, PCRTNETUDP pUdpHdr);
+RTDECL(uint32_t) RTNetIPv4AddUDPChecksum(PCRTNETUDP pUdpHdr, uint32_t u32Sum);
+RTDECL(uint16_t) RTNetIPv4UDPChecksum(PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, void const *pvData);
+RTDECL(bool)     RTNetIPv4IsUDPSizeValid(PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, size_t cbPktMax);
+RTDECL(bool)     RTNetIPv4IsUDPValid(PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, void const *pvData, size_t cbPktMax, bool fChecksum);
+
+
+/**
+ * IPv4 BOOTP / DHCP packet.
+ */
+#pragma pack(1)
+typedef struct RTNETBOOTP
+{
+    /** 00 - The packet opcode (RTNETBOOTP_OP_*). */
+    uint8_t         bp_op;
+    /** 01 - Hardware address type. Same as RTNETARPHDR::ar_htype.  */
+    uint8_t         bp_htype;
+    /** 02 - Hardware address length. */
+    uint8_t         bp_hlen;
+    /** 03 - Gateway hops. */
+    uint8_t         bp_hops;
+    /** 04 - Transaction ID. */
+    uint32_t        bp_xid;
+    /** 08 - Seconds since boot started. */
+    uint16_t        bp_secs;
+    /** 0a - Unused (BOOTP) / Flags (DHCP) (RTNET_DHCP_FLAGS_*).  */
+    uint16_t        bp_flags;
+    /** 0c - Client IPv4 address. */
+    RTNETADDRIPV4   bp_ciaddr;
+    /** 10 - Your IPv4 address. */
+    RTNETADDRIPV4   bp_yiaddr;
+    /** 14 - Server IPv4 address. */
+    RTNETADDRIPV4   bp_siaddr;
+    /** 18 - Gateway IPv4 address. */
+    RTNETADDRIPV4   bp_giaddr;
+    /** 1c - Client hardware address. */
+    union
+    {
+        uint8_t     au8[16];
+        RTMAC       Mac;
+    }               bp_chaddr;
+    /** 2c - Server name. */
+    uint8_t         bp_sname[64];
+    /** 6c - File name / more DHCP options. */
+    uint8_t         bp_file[128];
+    /** ec - Vendor specific area (BOOTP) / Options (DHCP).
+     * @remark This is really 312 bytes in the DHCP version. */
+    union
+    {
+        uint8_t         au8[128];
+        struct DHCP
+        {
+            /** ec - The DHCP cookie (RTNET_DHCP_COOKIE). */
+            uint32_t    dhcp_cookie;
+            /** f0 - The DHCP options. */
+            uint8_t     dhcp_opts[124];
+        }           Dhcp;
+    }               bp_vend;
+
+} RTNETBOOTP;
+#pragma pack()
+AssertCompileSize(RTNETBOOTP, 0xec + 128);
+/** Pointer to a BOOTP / DHCP packet. */
+typedef RTNETBOOTP *PRTNETBOOTP;
+/** Pointer to a const BOOTP / DHCP packet. */
+typedef RTNETBOOTP const *PCRTNETBOOTP;
+
+/** Minimum BOOTP packet length. For quick validation, no standard thing really. */
+#define RTNETBOOTP_MIN_LEN          0xec
+/** Minimum DHCP packet length. For quick validation, no standard thing really. */
+#define RTNETBOOTP_DHCP_MIN_LEN     0xf1
+
+/** The normal size of the a DHCP packet (i.e. a RTNETBOOTP).
+ * Same as RTNET_DHCP_OPT_SIZE, just expressed differently.  */
+#define RTNET_DHCP_NORMAL_SIZE      (0xec + 4 + RTNET_DHCP_OPT_SIZE)
+/** The normal size of RTNETBOOTP::bp_vend::Dhcp::dhcp_opts.  */
+#define RTNET_DHCP_OPT_SIZE         (312 - 4)
+
+/** @name BOOTP packet opcode values
+ * @{ */
+#define RTNETBOOTP_OP_REQUEST       1
+#define RTNETBOOTP_OP_REPLY         2
+/** @} */
+
+/** @name DHCP flags (RTNETBOOTP::bp_flags)
+ * @{ */
+#define RTNET_DHCP_FLAGS_NO_BROADCAST   UINT16_C(0x8000) /** @todo check test!!! */
+/** @} */
+
+/** The DHCP cookie (network endian). */
+#define RTNET_DHCP_COOKIE           UINT32_C(0x63825363)
+
+/**
+ * An IPv4 DHCP option header.
+ */
+typedef struct RTNETDHCPOPT
+{
+    /** 00 - The DHCP option. */
+    uint8_t     dhcp_opt;
+    /** 01 - The data length (excluding this header). */
+    uint8_t     dhcp_len;
+    /*  02 - The option data follows here, optional and of variable length. */
+} RTNETDHCPOPT;
+AssertCompileSize(RTNETDHCPOPT, 2);
+/** Pointer to a DHCP option header. */
+typedef RTNETDHCPOPT *PRTNETDHCPOPT;
+/** Pointer to a const DHCP option header. */
+typedef RTNETDHCPOPT const *PCRTNETDHCPOPT;
+
+/** @name DHCP options
+ * @{ */
+/** 1 byte padding, this has no dhcp_len field. */
+#define RTNET_DHCP_OPT_PAD                  0
+
+/** The subnet mask. */
+#define RTNET_DHCP_OPT_SUBNET_MASK          1
+/** The time offset. */
+#define RTNET_DHCP_OPT_TIME_OFFSET          2
+/** The routers for the subnet. */
+#define RTNET_DHCP_OPT_ROUTERS              3
+/** Domain Name Server. */
+#define RTNET_DHCP_OPT_DNS                  6
+/** Host name. */
+#define RTNET_DHCP_OPT_HOST_NAME            12
+/** Domain name. */
+#define RTNET_DHCP_OPT_DOMAIN_NAME          15
+
+/** The requested address. */
+#define RTNET_DHCP_OPT_REQ_ADDR             50
+/** The lease time in seconds. */
+#define RTNET_DHCP_OPT_LEASE_TIME           51
+/** Option overload.
+ *  Indicates that the bp_file and/or bp_sname holds contains DHCP options. */
+#define RTNET_DHCP_OPT_OPTION_OVERLOAD      52
+/** Have a 8-bit message type value as data, see RTNET_DHCP_MT_*. */
+#define RTNET_DHCP_OPT_MSG_TYPE             53
+/** Server ID. */
+#define RTNET_DHCP_OPT_SERVER_ID            54
+/** Parameter request list. */
+#define RTNET_DHCP_OPT_PARAM_REQ_LIST       55
+/** The maximum DHCP message size a client is willing to accept. */
+#define RTNET_DHCP_OPT_MAX_DHCP_MSG_SIZE    57
+/** Client ID. */
+#define RTNET_DHCP_OPT_CLIENT_ID            61
+/** TFTP server name. */
+#define RTNET_DHCP_OPT_TFTP_SERVER_NAME     66
+/** Bootfile name. */
+#define RTNET_DHCP_OPT_BOOTFILE_NAME        67
+
+/** Marks the end of the DHCP options, this has no dhcp_len field. */
+#define RTNET_DHCP_OPT_END                  255
+/** @} */
+
+/** @name DHCP Message Types (option 53)
+ * @{ */
+#define RTNET_DHCP_MT_DISCOVER      1
+#define RTNET_DHCP_MT_OFFER         2
+#define RTNET_DHCP_MT_REQUEST       3
+#define RTNET_DHCP_MT_DECLINE       4
+#define RTNET_DHCP_MT_ACK           5
+#define RTNET_DHCP_MT_NAC           6
+#define RTNET_DHCP_MT_RELEASE       7
+#define RTNET_DHCP_MT_INFORM        8
+/** @} */
+
+/** @name DHCP Flags
+ * @{ */
+#define RTNET_DHCP_FLAG_BROADCAST   0x8000
+/** @} */
+
+RTDECL(bool) RTNetIPv4IsDHCPValid(PCRTNETUDP pUdpHdr, PCRTNETBOOTP pDhcp, size_t cbDhcp, uint8_t *pMsgType);
+
+
+/**
+ * IPv4 DHCP packet.
+ * @deprecated Use RTNETBOOTP.
+ */
+#pragma pack(1)
+typedef struct RTNETDHCP
+{
+    /** 00 - The packet opcode. */
+    uint8_t         Op;
+    /** Hardware address type. */
+    uint8_t         HType;
+    /** Hardware address length. */
+    uint8_t         HLen;
+    uint8_t         Hops;
+    uint32_t        XID;
+    uint16_t        Secs;
+    uint16_t        Flags;
+    /** Client IPv4 address. */
+    RTNETADDRIPV4   CIAddr;
+    /** Your IPv4 address. */
+    RTNETADDRIPV4   YIAddr;
+    /** Server IPv4 address. */
+    RTNETADDRIPV4   SIAddr;
+    /** Gateway IPv4 address. */
+    RTNETADDRIPV4   GIAddr;
+    /** Client hardware address. */
+    uint8_t         CHAddr[16];
+    /** Server name. */
+    uint8_t         SName[64];
+    uint8_t         File[128];
+    uint8_t         abMagic[4];
+    uint8_t         DhcpOpt;
+    uint8_t         DhcpLen; /* 1 */
+    uint8_t         DhcpReq;
+    uint8_t         abOptions[57];
+} RTNETDHCP;
+#pragma pack()
+/** @todo AssertCompileSize(RTNETDHCP, ); */
+/** Pointer to a DHCP packet. */
+typedef RTNETDHCP *PRTNETDHCP;
+/** Pointer to a const DHCP packet. */
+typedef RTNETDHCP const *PCRTNETDHCP;
+
+
+/**
+ * TCP packet.
+ */
+#pragma pack(1)
+typedef struct RTNETTCP
+{
+    /** 00 - The source port. */
+    uint16_t        th_sport;
+    /** 02 - The destination port. */
+    uint16_t        th_dport;
+    /** 04 - The sequence number. */
+    uint32_t        th_seq;
+    /** 08 - The acknowledgement number. */
+    uint32_t        th_ack;
+#ifdef RT_BIG_ENDIAN
+    unsigned int    th_win : 16;
+    unsigned int    th_flags : 8;
+    unsigned int    th_off : 4;
+    unsigned int    th_x2 : 4;
+#else
+    /** 0c:0 - Reserved. */
+    unsigned int    th_x2 : 4;
+    /** 0c:4 - The data offset given as a dword count from the start of this header. */
+    unsigned int    th_off : 4;
+    /** 0d - flags. */
+    unsigned int    th_flags : 8;
+    /** 0e - The window. */
+    unsigned int    th_win : 16;
+#endif
+    /** 10 - The checksum of the pseudo header, the TCP header and the data. */
+    uint16_t        th_sum;
+    /** 12 - The urgent pointer. */
+    uint16_t        th_urp;
+    /* (options follows here and then the data (aka text).) */
+} RTNETTCP;
+#pragma pack()
+AssertCompileSize(RTNETTCP, 20);
+/** Pointer to a TCP packet. */
+typedef RTNETTCP *PRTNETTCP;
+/** Pointer to a const TCP packet. */
+typedef RTNETTCP const *PCRTNETTCP;
+
+/** The minimum TCP header length (in bytes). (RTNETTCP::th_off * 4) */
+#define RTNETTCP_MIN_LEN    (20)
+
+/** @name TCP flags (RTNETTCP::th_flags)
+ * @{ */
+#define RTNETTCP_F_FIN      0x01
+#define RTNETTCP_F_SYN      0x02
+#define RTNETTCP_F_RST      0x04
+#define RTNETTCP_F_PSH      0x08
+#define RTNETTCP_F_ACK      0x10
+#define RTNETTCP_F_URG      0x20
+#define RTNETTCP_F_ECE      0x40
+#define RTNETTCP_F_CWR      0x80
+/** @} */
+
+RTDECL(uint16_t) RTNetTCPChecksum(uint32_t u32Sum, PCRTNETTCP pTcpHdr, void const *pvData, size_t cbData);
+RTDECL(uint32_t) RTNetIPv4AddTCPChecksum(PCRTNETTCP pTcpHdr, uint32_t u32Sum);
+RTDECL(uint16_t) RTNetIPv4TCPChecksum(PCRTNETIPV4 pIpHdr, PCRTNETTCP pTcpHdr, void const *pvData);
+RTDECL(bool)     RTNetIPv4IsTCPSizeValid(PCRTNETIPV4 pIpHdr, PCRTNETTCP pTcpHdr, size_t cbHdrMax, size_t cbPktMax);
+RTDECL(bool)     RTNetIPv4IsTCPValid(PCRTNETIPV4 pIpHdr, PCRTNETTCP pTcpHdr, size_t cbHdrMax, void const *pvData,
+                                     size_t cbPktMax, bool fChecksum);
+
+
+/**
+ * IPv4 ICMP packet header.
+ */
+#pragma pack(1)
+typedef struct RTNETICMPV4HDR
+{
+    /** 00 - The ICMP message type. */
+    uint8_t         icmp_type;
+    /** 01 - Type specific code that further qualifies the message. */
+    uint8_t         icmp_code;
+    /** 02 - Checksum of the ICMP message. */
+    uint16_t        icmp_cksum;
+} RTNETICMPV4HDR;
+#pragma pack()
+AssertCompileSize(RTNETICMPV4HDR, 4);
+/** Pointer to an ICMP packet header. */
+typedef RTNETICMPV4HDR *PRTNETICMPV4HDR;
+/** Pointer to a const ICMP packet header. */
+typedef RTNETICMPV4HDR const *PCRTNETICMPV4HDR;
+
+/** @name ICMP (v4) message types.
+ * @{  */
+#define RTNETICMPV4_TYPE_ECHO_REPLY     0
+#define RTNETICMPV4_TYPE_ECHO_REQUEST   8
+#define RTNETICMPV4_TYPE_TRACEROUTE     30
+/** @} */
+
+/**
+ * IPv4 ICMP ECHO Reply & Request packet.
+ */
+#pragma pack(1)
+typedef struct RTNETICMPV4ECHO
+{
+    /** 00 - The ICMP header. */
+    RTNETICMPV4HDR  Hdr;
+    /** 04 - The identifier to help the requestor match up the reply.
+     *       Can be 0. Typically fixed value. */
+    uint16_t        icmp_id;
+    /** 06 - The sequence number to help the requestor match up the reply.
+     *       Can be 0. Typically incrementing between requests. */
+    uint16_t        icmp_seq;
+    /** 08 - Variable length data that is to be returned unmodified in the reply. */
+    uint8_t         icmp_data[1];
+} RTNETICMPV4ECHO;
+#pragma pack()
+AssertCompileSize(RTNETICMPV4ECHO, 9);
+/** Pointer to an ICMP ECHO packet. */
+typedef RTNETICMPV4ECHO *PRTNETICMPV4ECHO;
+/** Pointer to a const ICMP ECHO packet. */
+typedef RTNETICMPV4ECHO const *PCRTNETICMPV4ECHO;
+
+/**
+ * IPv4 ICMP TRACEROUTE packet.
+ * This is an reply to an IP packet with the traceroute option set.
+ */
+#pragma pack(1)
+typedef struct RTNETICMPV4TRACEROUTE
+{
+    /** 00 - The ICMP header. */
+    RTNETICMPV4HDR  Hdr;
+    /** 04 - Identifier copied from the traceroute option's ID number. */
+    uint16_t        icmp_id;
+    /** 06 - Unused. (Possibly an icmp_seq?) */
+    uint16_t        icmp_void;
+    /** 08 - Outbound hop count. From the IP packet causing this message. */
+    uint16_t        icmp_ohc;
+    /** 0a - Return hop count. From the IP packet causing this message. */
+    uint16_t        icmp_rhc;
+    /** 0c - Output link speed, 0 if not known. */
+    uint32_t        icmp_speed;
+    /** 10 - Output link MTU, 0 if not known. */
+    uint32_t        icmp_mtu;
+} RTNETICMPV4TRACEROUTE;
+#pragma pack()
+AssertCompileSize(RTNETICMPV4TRACEROUTE, 20);
+/** Pointer to an ICMP TRACEROUTE packet. */
+typedef RTNETICMPV4TRACEROUTE *PRTNETICMPV4TRACEROUTE;
+/** Pointer to a const ICMP TRACEROUTE packet. */
+typedef RTNETICMPV4TRACEROUTE const *PCRTNETICMPV4TRACEROUTE;
+
+/** @todo add more ICMPv4 as needed. */
+
+/**
+ * IPv4 ICMP union packet.
+ */
+typedef union RTNETICMPV4
+{
+    RTNETICMPV4HDR Hdr;
+    RTNETICMPV4ECHO Echo;
+    RTNETICMPV4TRACEROUTE Traceroute;
+} RTNETICMPV4;
+/** Pointer to an ICMP union packet. */
+typedef RTNETICMPV4 *PRTNETICMPV4;
+/** Pointer to a const ICMP union packet. */
+typedef RTNETICMPV4 const *PCRTNETICMPV4;
+
+
+/**
+ * IPv6 ICMP packet header.
+ */
+#pragma pack(1)
+typedef struct RTNETICMPV6HDR
+{
+    /** 00 - The ICMPv6 message type. */
+    uint8_t         icmp6_type;
+    /** 01 - Type specific code that further qualifies the message. */
+    uint8_t         icmp6_code;
+    /** 02 - Checksum of the ICMPv6 message. */
+    uint16_t        icmp6_cksum;
+} RTNETICMPV6HDR;
+#pragma pack()
+AssertCompileSize(RTNETICMPV6HDR, 4);
+/** Pointer to an ICMPv6 packet header. */
+typedef RTNETICMPV6HDR *PRTNETICMPV6HDR;
+/** Pointer to a const ICMP packet header. */
+typedef RTNETICMPV6HDR const *PCRTNETICMPV6HDR;
+
+#define RTNETIPV6_PROT_ICMPV6       (58)
+
+/** @name Internet Control Message Protocol version 6 (ICMPv6) message types.
+ * @{ */
+#define RTNETIPV6_ICMP_TYPE_RS      133
+#define RTNETIPV6_ICMP_TYPE_RA      134
+#define RTNETIPV6_ICMP_TYPE_NS      135
+#define RTNETIPV6_ICMP_TYPE_NA      136
+#define RTNETIPV6_ICMP_TYPE_RDR     137
+/** @} */
+
+/** @name Neighbor Discovery option types
+ * @{ */
+#define RTNETIPV6_ICMP_ND_SLLA_OPT  (1)
+#define RTNETIPV6_ICMP_ND_TLLA_OPT  (2)
+/** @} */
+
+/** ICMPv6 ND Source/Target Link Layer Address option */
+#pragma pack(1)
+typedef struct RTNETNDP_LLA_OPT
+{
+    uint8_t type;
+    uint8_t len;
+    RTMAC lla;
+} RTNETNDP_LLA_OPT;
+#pragma pack()
+
+AssertCompileSize(RTNETNDP_LLA_OPT, 1+1+6);
+
+typedef RTNETNDP_LLA_OPT *PRTNETNDP_LLA_OPT;
+typedef RTNETNDP_LLA_OPT const *PCRTNETNDP_LLA_OPT;
+
+/** ICMPv6 ND Neighbor Sollicitation */
+#pragma pack(1)
+typedef struct RTNETNDP
+{
+    /** 00 - The ICMPv6 header. */
+    RTNETICMPV6HDR Hdr;
+    /** 04 - reserved */
+    uint32_t reserved;
+    /** 08 - target address */
+    RTNETADDRIPV6 target_address;
+} RTNETNDP;
+#pragma pack()
+AssertCompileSize(RTNETNDP, 4+4+16);
+/** Pointer to a NDP ND packet. */
+typedef RTNETNDP *PRTNETNDP;
+/** Pointer to a const NDP NS packet. */
+typedef RTNETNDP const *PCRTNETNDP;
+
+
+/**
+ * Ethernet ARP header.
+ */
+#pragma pack(1)
+typedef struct RTNETARPHDR
+{
+    /** The hardware type. */
+    uint16_t    ar_htype;
+    /** The protocol type (ethertype). */
+    uint16_t    ar_ptype;
+    /** The hardware address length. */
+    uint8_t     ar_hlen;
+    /** The protocol address length. */
+    uint8_t     ar_plen;
+    /** The operation. */
+    uint16_t    ar_oper;
+} RTNETARPHDR;
+#pragma pack()
+AssertCompileSize(RTNETARPHDR, 8);
+/** Pointer to an ethernet ARP header. */
+typedef RTNETARPHDR *PRTNETARPHDR;
+/** Pointer to a const ethernet ARP header. */
+typedef RTNETARPHDR const *PCRTNETARPHDR;
+
+/** ARP hardware type - ethernet. */
+#define RTNET_ARP_ETHER            UINT16_C(1)
+
+/** @name ARP operations
+ * @{ */
+#define RTNET_ARPOP_REQUEST        UINT16_C(1) /**< Request hardware address given a protocol address (ARP). */
+#define RTNET_ARPOP_REPLY          UINT16_C(2)
+#define RTNET_ARPOP_REVREQUEST     UINT16_C(3) /**< Request protocol address given a hardware address (RARP). */
+#define RTNET_ARPOP_REVREPLY       UINT16_C(4)
+#define RTNET_ARPOP_INVREQUEST     UINT16_C(8) /**< Inverse ARP.  */
+#define RTNET_ARPOP_INVREPLY       UINT16_C(9)
+/** Check if an ARP operation is a request or not. */
+#define RTNET_ARPOP_IS_REQUEST(Op) ((Op) & 1)
+/** Check if an ARP operation is a reply or not. */
+#define RTNET_ARPOP_IS_REPLY(Op)   (!RTNET_ARPOP_IS_REQUEST(Op))
+/** @} */
+
+
+/**
+ * Ethernet IPv4 + 6-byte MAC ARP request packet.
+ */
+#pragma pack(1)
+typedef struct RTNETARPIPV4
+{
+    /** ARP header. */
+    RTNETARPHDR     Hdr;
+    /** The sender hardware address. */
+    RTMAC           ar_sha;
+    /** The sender protocol address. */
+    RTNETADDRIPV4   ar_spa;
+    /** The target hardware address. */
+    RTMAC           ar_tha;
+    /** The target protocol address. */
+    RTNETADDRIPV4   ar_tpa;
+} RTNETARPIPV4;
+#pragma pack()
+AssertCompileSize(RTNETARPIPV4, 8+6+4+6+4);
+/** Pointer to an ethernet IPv4+MAC ARP request packet. */
+typedef RTNETARPIPV4 *PRTNETARPIPV4;
+/** Pointer to a const ethernet IPv4+MAC ARP request packet. */
+typedef RTNETARPIPV4 const *PCRTNETARPIPV4;
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/nocrt/limits.h b/ubuntu/vbox/include/iprt/nocrt/limits.h
new file mode 100644 (file)
index 0000000..b91b1c7
--- /dev/null
@@ -0,0 +1,86 @@
+/** @file
+ * IPRT / No-CRT - Our own limits header.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_nocrt_limits_h
+#define ___iprt_nocrt_limits_h
+
+#include <iprt/types.h>
+
+#define CHAR_BIT        8
+#define SCHAR_MAX       0x7f
+#define SCHAR_MIN       (-0x7f - 1)
+#define UCHAR_MAX       0xff
+#if 1 /* ASSUMES: signed char */
+# define CHAR_MAX       SCHAR_MAX
+# define CHAR_MIN       SCHAR_MIN
+#else
+# define CHAR_MAX       UCHAR_MAX
+# define CHAR_MIN       0
+#endif
+
+#define WORD_BIT        16
+#define USHRT_MAX       0xffff
+#define SHRT_MAX        0x7fff
+#define SHRT_MIN        (-0x7fff - 1)
+
+/* ASSUMES 32-bit int */
+#define UINT_MAX        0xffffffffU
+#define INT_MAX         0x7fffffff
+#define INT_MIN         (-0x7fffffff - 1)
+
+#if defined(RT_ARCH_X86) || defined(RT_OS_WINDOWS) || defined(RT_ARCH_SPARC)
+# define LONG_BIT       32
+# define ULONG_MAX      0xffffffffU
+# define LONG_MAX       0x7fffffff
+# define LONG_MIN       (-0x7fffffff - 1)
+#elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_SPARC64)
+# define LONG_BIT       64
+# define ULONG_MAX      UINT64_C(0xffffffffffffffff)
+# define LONG_MAX       INT64_C(0x7fffffffffffffff)
+# define LONG_MIN       (INT64_C(-0x7fffffffffffffff) - 1)
+#else
+# error "PORTME"
+#endif
+
+#define LLONG_BIT       64
+#define ULLONG_MAX      UINT64_C(0xffffffffffffffff)
+#define LLONG_MAX       INT64_C(0x7fffffffffffffff)
+#define LLONG_MIN       (INT64_C(-0x7fffffffffffffff) - 1)
+
+#if ARCH_BITS == 32
+# define SIZE_T_MAX     0xffffffffU
+# define SSIZE_MAX      0x7fffffff
+#elif ARCH_BITS == 64
+# define SIZE_T_MAX     UINT64_C(0xffffffffffffffff)
+# define SSIZE_MAX      INT64_C(0x7fffffffffffffff)
+#else
+# error "huh?"
+#endif
+
+/*#define OFF_MAX         __OFF_MAX
+#define OFF_MIN         __OFF_MIN*/
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/param.h b/ubuntu/vbox/include/iprt/param.h
new file mode 100644 (file)
index 0000000..cfd489d
--- /dev/null
@@ -0,0 +1,131 @@
+/** @file
+ * IPRT - Parameter 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.
+ */
+
+#ifndef ___iprt_param_h
+#define ___iprt_param_h
+
+/** @todo Much of the PAGE_* stuff here is obsolete and highly risky to have around.
+ * As for component configs (MM_*), either we gather all in here or we move those bits away! */
+
+/** @defgroup   grp_rt_param    System Parameter Definitions
+ * @ingroup grp_rt_cdefs
+ * @{
+ */
+
+/* Undefine PAGE_SIZE and PAGE_SHIFT to avoid unnecessary noice when clashing
+ * with system headers. Include system headers before / after iprt depending
+ * on which you wish to take precedence. */
+#undef PAGE_SIZE
+#undef PAGE_SHIFT
+
+/* Undefine PAGE_OFFSET_MASK to avoid the conflict with the-linux-kernel.h */
+#undef PAGE_OFFSET_MASK
+
+/**
+ * i386 Page size.
+ */
+#if defined(RT_ARCH_SPARC64)
+# define PAGE_SIZE          8192
+#else
+# define PAGE_SIZE          4096
+#endif
+
+/**
+ * i386 Page shift.
+ * This is used to convert between size (in bytes) and page count.
+ */
+#if defined(RT_ARCH_SPARC64)
+# define PAGE_SHIFT         13
+#else
+# define PAGE_SHIFT         12
+#endif
+
+/**
+ * i386 Page offset mask.
+ *
+ * Do NOT one-complement this for whatever purpose. You may get a 32-bit const when you want a 64-bit one.
+ * Use PAGE_BASE_MASK, PAGE_BASE_GC_MASK, PAGE_BASE_HC_MASK, PAGE_ADDRESS() or X86_PTE_PAE_PG_MASK.
+ */
+#if defined(RT_ARCH_SPARC64)
+# define PAGE_OFFSET_MASK    0x1fff
+#else
+# define PAGE_OFFSET_MASK    0xfff
+#endif
+
+/**
+ * Page address mask for the guest context POINTERS.
+ * @remark  Physical addresses are always masked using X86_PTE_PAE_PG_MASK!
+ */
+#define PAGE_BASE_GC_MASK   (~(RTGCUINTPTR)PAGE_OFFSET_MASK)
+
+/**
+ * Page address mask for the host context POINTERS.
+ * @remark  Physical addresses are always masked using X86_PTE_PAE_PG_MASK!
+ */
+#define PAGE_BASE_HC_MASK   (~(RTHCUINTPTR)PAGE_OFFSET_MASK)
+
+/**
+ * Page address mask for the both context POINTERS.
+ *
+ * Be careful when using this since it may be a size too big!
+ * @remark  Physical addresses are always masked using X86_PTE_PAE_PG_MASK!
+ */
+#define PAGE_BASE_MASK      (~(RTUINTPTR)PAGE_OFFSET_MASK)
+
+/**
+ * Get the page aligned address of a POINTER in the CURRENT context.
+ *
+ * @returns Page aligned address (it's an uintptr_t).
+ * @param   pv      The virtual address to align.
+ *
+ * @remarks Physical addresses are always masked using X86_PTE_PAE_PG_MASK!
+ * @remarks This only works with POINTERS in the current context.
+ *          Do NOT use on guest address or physical address!
+ */
+#define PAGE_ADDRESS(pv)    ((uintptr_t)(pv) & ~(uintptr_t)PAGE_OFFSET_MASK)
+
+/**
+ * Get the page aligned address of a physical address
+ *
+ * @returns Page aligned address (it's an RTHCPHYS or RTGCPHYS).
+ * @param   Phys    The physical address to align.
+ */
+#define PHYS_PAGE_ADDRESS(Phys) ((Phys) & X86_PTE_PAE_PG_MASK)
+
+/**
+ * Host max path (the reasonable value).
+ * @remarks defined both by iprt/param.h and iprt/path.h.
+ */
+#if !defined(___iprt_path_h) || defined(DOXYGEN_RUNNING)
+# define RTPATH_MAX         (4096 + 4)    /* (PATH_MAX + 1) on linux w/ some alignment */
+#endif
+
+/** @} */
+
+
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/path.h b/ubuntu/vbox/include/iprt/path.h
new file mode 100644 (file)
index 0000000..8bd42bc
--- /dev/null
@@ -0,0 +1,1478 @@
+/** @file
+ * IPRT - Path Manipulation.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_path_h
+#define ___iprt_path_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#ifdef IN_RING3
+# include <iprt/fs.h>
+#endif
+
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_path   RTPath - Path Manipulation
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Host max path (the reasonable value).
+ * @remarks defined both by iprt/param.h and iprt/path.h.
+ */
+#if !defined(___iprt_param_h) || defined(DOXYGEN_RUNNING)
+# define RTPATH_MAX         (4096 + 4)    /* (PATH_MAX + 1) on linux w/ some alignment */
+#endif
+
+/** @def RTPATH_TAG
+ * The default allocation tag used by the RTPath allocation APIs.
+ *
+ * When not defined before the inclusion of iprt/string.h, this will default to
+ * the pointer to the current file name.  The string API will make of use of
+ * this as pointer to a volatile but read-only string.
+ */
+#ifndef RTPATH_TAG
+# define RTPATH_TAG     (__FILE__)
+#endif
+
+
+/** @name RTPATH_F_XXX - Generic flags for APIs working on the file system.
+ * @{ */
+/** Last component: Work on the link. */
+#define RTPATH_F_ON_LINK          RT_BIT_32(0)
+/** Last component: Follow if link. */
+#define RTPATH_F_FOLLOW_LINK      RT_BIT_32(1)
+/** Don't allow symbolic links as part of the path.
+ * @remarks this flag is currently not implemented and will be ignored. */
+#define RTPATH_F_NO_SYMLINKS      RT_BIT_32(2)
+/** @} */
+
+/** Validates a flags parameter containing RTPATH_F_*.
+ * @remarks The parameters will be referenced multiple times. */
+#define RTPATH_F_IS_VALID(a_fFlags, a_fIgnore) \
+    (    ((a_fFlags) & ~(uint32_t)((a_fIgnore) | RTPATH_F_NO_SYMLINKS)) == RTPATH_F_ON_LINK \
+      || ((a_fFlags) & ~(uint32_t)((a_fIgnore) | RTPATH_F_NO_SYMLINKS)) == RTPATH_F_FOLLOW_LINK )
+
+
+/** @name RTPATH_STR_F_XXX - Generic flags for APIs working with path strings.
+ * @{
+ */
+/** Host OS path style (default 0 value). */
+#define RTPATH_STR_F_STYLE_HOST         UINT32_C(0x00000000)
+/** DOS, OS/2 and Windows path style. */
+#define RTPATH_STR_F_STYLE_DOS          UINT32_C(0x00000001)
+/** Unix path style. */
+#define RTPATH_STR_F_STYLE_UNIX         UINT32_C(0x00000002)
+/** Reserved path style. */
+#define RTPATH_STR_F_STYLE_RESERVED     UINT32_C(0x00000003)
+/** The path style mask. */
+#define RTPATH_STR_F_STYLE_MASK         UINT32_C(0x00000003)
+/** Partial path - no start.
+ * This causes the API to skip the root specification parsing.  */
+#define RTPATH_STR_F_NO_START           UINT32_C(0x00000010)
+/** Partial path - no end.
+ * This causes the API to skip the filename and dir-slash parsing.  */
+#define RTPATH_STR_F_NO_END             UINT32_C(0x00000020)
+/** Partial path - no start and no end. */
+#define RTPATH_STR_F_MIDDLE             (RTPATH_STR_F_NO_START | RTPATH_STR_F_NO_END)
+
+/** Reserved for future use. */
+#define RTPATH_STR_F_RESERVED_MASK      UINT32_C(0x0000ffcc)
+/** @} */
+
+/** Validates a flags parameter containing RTPATH_FSTR_.
+ * @remarks The parameters will be references multiple times.  */
+#define RTPATH_STR_F_IS_VALID(a_fFlags, a_fIgnore) \
+      (   ((a_fFlags) & ~((uint32_t)(a_fIgnore) | RTPATH_STR_F_STYLE_MASK | RTPATH_STR_F_MIDDLE)) == 0 \
+       && ((a_fFlags) & RTPATH_STR_F_STYLE_MASK) != RTPATH_STR_F_STYLE_RESERVED \
+       && ((a_fFlags) & RTPATH_STR_F_RESERVED_MASK) == 0 )
+
+
+/** @def RTPATH_STYLE
+ * The host path style. This is set to RTPATH_STR_F_STYLE_DOS,
+ * RTPATH_STR_F_STYLE_UNIX, or other future styles. */
+#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
+# define RTPATH_STYLE       RTPATH_STR_F_STYLE_DOS
+#else
+# define RTPATH_STYLE       RTPATH_STR_F_STYLE_UNIX
+#endif
+
+
+/** @def RTPATH_SLASH
+ * The preferred slash character.
+ *
+ * @remark IPRT will always accept unix slashes. So, normally you would
+ *         never have to use this define.
+ */
+#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS
+# define RTPATH_SLASH       '\\'
+#elif RTPATH_STYLE == RTPATH_STR_F_STYLE_UNIX
+# define RTPATH_SLASH       '/'
+#else
+# error "Unsupported RTPATH_STYLE value."
+#endif
+
+/** @deprecated Use '/'! */
+#define RTPATH_DELIMITER    RTPATH_SLASH
+
+
+/** @def RTPATH_SLASH_STR
+ * The preferred slash character as a string, handy for concatenations
+ * with other strings.
+ *
+ * @remark IPRT will always accept unix slashes. So, normally you would
+ *         never have to use this define.
+ */
+#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS
+# define RTPATH_SLASH_STR   "\\"
+#elif RTPATH_STYLE == RTPATH_STR_F_STYLE_UNIX
+# define RTPATH_SLASH_STR   "/"
+#else
+# error "Unsupported RTPATH_STYLE value."
+#endif
+
+
+/** @def RTPATH_IS_SLASH
+ * Checks if a character is a slash.
+ *
+ * @returns true if it's a slash and false if not.
+ * @returns @param      a_ch    Char to check.
+ */
+#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS
+# define RTPATH_IS_SLASH(a_ch)      ( (a_ch) == '\\' || (a_ch) == '/' )
+#elif RTPATH_STYLE == RTPATH_STR_F_STYLE_UNIX
+# define RTPATH_IS_SLASH(a_ch)      ( (a_ch) == '/' )
+#else
+# error "Unsupported RTPATH_STYLE value."
+#endif
+
+
+/** @def RTPATH_IS_VOLSEP
+ * Checks if a character marks the end of the volume specification.
+ *
+ * @remark  This is sufficient for the drive letter concept on PC.
+ *          However it might be insufficient on other platforms
+ *          and even on PC a UNC volume spec won't be detected this way.
+ *          Use the RTPath@<too be created@>() instead.
+ *
+ * @returns true if it is and false if it isn't.
+ * @returns @param      a_ch    Char to check.
+ */
+#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS
+# define RTPATH_IS_VOLSEP(a_ch)   ( (a_ch) == ':' )
+#elif RTPATH_STYLE == RTPATH_STR_F_STYLE_UNIX
+# define RTPATH_IS_VOLSEP(a_ch)   (false)
+#else
+# error "Unsupported RTPATH_STYLE value."
+#endif
+
+
+/** @def RTPATH_IS_SEP
+ * Checks if a character is path component separator
+ *
+ * @returns true if it is and false if it isn't.
+ * @returns @param      a_ch    Char to check.
+ * @
+ */
+#define RTPATH_IS_SEP(a_ch)     ( RTPATH_IS_SLASH(a_ch) || RTPATH_IS_VOLSEP(a_ch) )
+
+
+/**
+ * Checks if the path exists.
+ *
+ * Symbolic links will all be attempted resolved and broken links means false.
+ *
+ * @returns true if it exists and false if it doesn't.
+ * @param   pszPath     The path to check.
+ */
+RTDECL(bool) RTPathExists(const char *pszPath);
+
+/**
+ * Checks if the path exists.
+ *
+ * @returns true if it exists and false if it doesn't.
+ * @param   pszPath     The path to check.
+ * @param   fFlags      RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK.
+ */
+RTDECL(bool) RTPathExistsEx(const char *pszPath, uint32_t fFlags);
+
+/**
+ * Sets the current working directory of the process.
+ *
+ * @returns IPRT status code.
+ * @param   pszPath         The path to the new working directory.
+ */
+RTDECL(int)  RTPathSetCurrent(const char *pszPath);
+
+/**
+ * Gets the current working directory of the process.
+ *
+ * @returns IPRT status code.
+ * @param   pszPath         Where to store the path.
+ * @param   cchPath         The size of the buffer pszPath points to.
+ */
+RTDECL(int)  RTPathGetCurrent(char *pszPath, size_t cchPath);
+
+/**
+ * Gets the current working directory on the specified drive.
+ *
+ * On systems without drive letters, the root slash will be returned.
+ *
+ * @returns IPRT status code.
+ * @param   chDrive         The drive we're querying the driver letter on.
+ * @param   pszPath         Where to store the working directroy path.
+ * @param   cbPath          The size of the buffer pszPath points to.
+ */
+RTDECL(int) RTPathGetCurrentOnDrive(char chDrive, char *pszPath, size_t cbPath);
+
+/**
+ * Gets the current working drive of the process.
+ *
+ * Normally drive letter and colon will be returned, never trailing a root
+ * slash.  If the current directory is on a UNC share, the root of the share
+ * will be returned.  On systems without drive letters, an empty string is
+ * returned for consistency.
+ *
+ * @returns IPRT status code.
+ * @param   pszPath         Where to store the working drive or UNC root.
+ * @param   cbPath          The size of the buffer pszPath points to.
+ */
+RTDECL(int) RTPathGetCurrentDrive(char *pszPath, size_t cbPath);
+
+/**
+ * Get the real path (no symlinks, no . or .. components), must exist.
+ *
+ * @returns iprt status code.
+ * @param   pszPath         The path to resolve.
+ * @param   pszRealPath     Where to store the real path.
+ * @param   cchRealPath     Size of the buffer.
+ */
+RTDECL(int) RTPathReal(const char *pszPath, char *pszRealPath, size_t cchRealPath);
+
+/**
+ * Same as RTPathReal only the result is RTStrDup()'ed.
+ *
+ * @returns Pointer to real path. Use RTStrFree() to free this string.
+ * @returns NULL if RTPathReal() or RTStrDup() fails.
+ * @param   pszPath         The path to resolve.
+ */
+RTDECL(char *) RTPathRealDup(const char *pszPath);
+
+/**
+ * Get the absolute path (starts from root, no . or .. components), doesn't have
+ * to exist. Note that this method is designed to never perform actual file
+ * system access, therefore symlinks are not resolved.
+ *
+ * @returns iprt status code.
+ * @param   pszPath         The path to resolve.
+ * @param   pszAbsPath      Where to store the absolute path.
+ * @param   cchAbsPath      Size of the buffer.
+ */
+RTDECL(int) RTPathAbs(const char *pszPath, char *pszAbsPath, size_t cchAbsPath);
+
+/**
+ * Same as RTPathAbs only the result is RTStrDup()'ed.
+ *
+ * @returns Pointer to the absolute path. Use RTStrFree() to free this string.
+ * @returns NULL if RTPathAbs() or RTStrDup() fails.
+ * @param   pszPath         The path to resolve.
+ */
+RTDECL(char *) RTPathAbsDup(const char *pszPath);
+
+/**
+ * Get the absolute path (no symlinks, no . or .. components), assuming the
+ * given base path as the current directory. The resulting path doesn't have
+ * to exist.
+ *
+ * @returns iprt status code.
+ * @param   pszBase         The base path to act like a current directory.
+ *                          When NULL, the actual cwd is used (i.e. the call
+ *                          is equivalent to RTPathAbs(pszPath, ...).
+ * @param   pszPath         The path to resolve.
+ * @param   pszAbsPath      Where to store the absolute path.
+ * @param   cchAbsPath      Size of the buffer.
+ */
+RTDECL(int) RTPathAbsEx(const char *pszBase, const char *pszPath, char *pszAbsPath, size_t cchAbsPath);
+
+/**
+ * Same as RTPathAbsEx only the result is RTStrDup()'ed.
+ *
+ * @returns Pointer to the absolute path. Use RTStrFree() to free this string.
+ * @returns NULL if RTPathAbsEx() or RTStrDup() fails.
+ * @param   pszBase         The base path to act like a current directory.
+ *                          When NULL, the actual cwd is used (i.e. the call
+ *                          is equivalent to RTPathAbs(pszPath, ...).
+ * @param   pszPath         The path to resolve.
+ */
+RTDECL(char *) RTPathAbsExDup(const char *pszBase, const char *pszPath);
+
+/**
+ * Strips the filename from a path. Truncates the given string in-place by overwriting the
+ * last path separator character with a null byte in a platform-neutral way.
+ *
+ * @param   pszPath     Path from which filename should be extracted, will be truncated.
+ *                      If the string contains no path separator, it will be changed to a "." string.
+ */
+RTDECL(void) RTPathStripFilename(char *pszPath);
+
+/**
+ * Strips the last suffix from a path.
+ *
+ * @param   pszPath     Path which suffix should be stripped.
+ */
+RTDECL(void) RTPathStripSuffix(char *pszPath);
+
+/**
+ * Strips the trailing slashes of a path name.
+ *
+ * Won't strip root slashes.
+ *
+ * @returns The new length of pszPath.
+ * @param   pszPath     Path to strip.
+ */
+RTDECL(size_t) RTPathStripTrailingSlash(char *pszPath);
+
+/**
+ * Ensures that the path has a trailing path separator such that file names can
+ * be appended without further work.
+ *
+ * This can be helpful when preparing for efficiently combining a directory path
+ * with the filenames returned by RTDirRead.  The return value gives you the
+ * position at which you copy the RTDIRENTRY::szName to construct a valid path
+ * to it.
+ *
+ * @returns The length of the path, 0 on buffer overflow.
+ * @param   pszPath     The path.
+ * @param   cbPath      The length of the path buffer @a pszPath points to.
+ */
+RTDECL(size_t) RTPathEnsureTrailingSeparator(char *pszPath, size_t cbPath);
+
+/**
+ * Changes all the slashes in the specified path to DOS style.
+ *
+ * Unless @a fForce is set, nothing will be done when on a UNIX flavored system
+ * since paths wont work with DOS style slashes there.
+ *
+ * @returns @a pszPath.
+ * @param   pszPath             The path to modify.
+ * @param   fForce              Whether to force the conversion on non-DOS OSes.
+ */
+RTDECL(char *) RTPathChangeToDosSlashes(char *pszPath, bool fForce);
+
+/**
+ * Changes all the slashes in the specified path to unix style.
+ *
+ * Unless @a fForce is set, nothing will be done when on a UNIX flavored system
+ * since paths wont work with DOS style slashes there.
+ *
+ * @returns @a pszPath.
+ * @param   pszPath             The path to modify.
+ * @param   fForce              Whether to force the conversion on non-DOS OSes.
+ */
+RTDECL(char *) RTPathChangeToUnixSlashes(char *pszPath, bool fForce);
+
+/**
+ * Simple parsing of the a path.
+ *
+ * It figures the length of the directory component, the offset of
+ * the file name and the location of the suffix dot.
+ *
+ * @returns The path length.
+ *
+ * @param   pszPath     Path to find filename in.
+ * @param   pcchDir     Where to put the length of the directory component. If
+ *                      no directory, this will be 0. Optional.
+ * @param   poffName    Where to store the filename offset.
+ *                      If empty string or if it's ending with a slash this
+ *                      will be set to -1. Optional.
+ * @param   poffSuff    Where to store the suffix offset (the last dot).
+ *                      If empty string or if it's ending with a slash this
+ *                      will be set to -1. Optional.
+ */
+RTDECL(size_t) RTPathParseSimple(const char *pszPath, size_t *pcchDir, ssize_t *poffName, ssize_t *poffSuff);
+
+/**
+ * Finds the filename in a path.
+ *
+ * @returns Pointer to filename within pszPath.
+ * @returns NULL if no filename (i.e. empty string or ends with a slash).
+ * @param   pszPath     Path to find filename in.
+ */
+RTDECL(char *) RTPathFilename(const char *pszPath);
+
+/**
+ * Finds the filename in a path, extended version.
+ *
+ * @returns Pointer to filename within pszPath.
+ * @returns NULL if no filename (i.e. empty string or ends with a slash).
+ * @param   pszPath     Path to find filename in.
+ * @param   fFlags      RTPATH_STR_F_STYLE_XXX. Other RTPATH_STR_F_XXX flags
+ *                      will be ignored.
+ */
+RTDECL(char *) RTPathFilenameEx(const char *pszPath, uint32_t fFlags);
+
+/**
+ * Finds the suffix part of in a path (last dot and onwards).
+ *
+ * @returns Pointer to suffix within pszPath.
+ * @returns NULL if no suffix
+ * @param   pszPath     Path to find suffix in.
+ *
+ * @remarks IPRT terminology: A suffix includes the dot, the extension starts
+ *          after the dot. For instance suffix '.txt' and extension 'txt'.
+ */
+RTDECL(char *) RTPathSuffix(const char *pszPath);
+
+/**
+ * Checks if a path has an extension / suffix.
+ *
+ * @returns true if extension / suffix present.
+ * @returns false if no extension / suffix.
+ * @param   pszPath     Path to check.
+ */
+RTDECL(bool) RTPathHasSuffix(const char *pszPath);
+/** Same thing, different name.  */
+#define RTPathHasExt RTPathHasSuffix
+
+/**
+ * Checks if a path includes more than a filename.
+ *
+ * @returns true if path present.
+ * @returns false if no path.
+ * @param   pszPath     Path to check.
+ */
+RTDECL(bool) RTPathHasPath(const char *pszPath);
+/** Misspelled, don't use.  */
+#define RTPathHavePath  RTPathHasPath
+
+/**
+ * Checks if the path starts with a root specifier or not.
+ *
+ * @returns @c true if it starts with root, @c false if not.
+ *
+ * @param   pszPath     Path to check.
+ */
+RTDECL(bool) RTPathStartsWithRoot(const char *pszPath);
+
+/**
+ * Counts the components in the specified path.
+ *
+ * An empty string has zero components.  A lone root slash is considered have
+ * one.  The paths "/init" and "/bin/" are considered having two components.  An
+ * UNC share specifier like "\\myserver\share" will be considered as one single
+ * component.
+ *
+ * @returns The number of path components.
+ * @param   pszPath     The path to parse.
+ */
+RTDECL(size_t) RTPathCountComponents(const char *pszPath);
+
+/**
+ * Copies the specified number of path components from @a pszSrc and into @a
+ * pszDst.
+ *
+ * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.  In the latter case the buffer
+ *          is not touched.
+ *
+ * @param   pszDst      The destination buffer.
+ * @param   cbDst       The size of the destination buffer.
+ * @param   pszSrc      The source path.
+ * @param   cComponents The number of components to copy from @a pszSrc.
+ */
+RTDECL(int) RTPathCopyComponents(char *pszDst, size_t cbDst, const char *pszSrc, size_t cComponents);
+
+/** @name Path properties returned by RTPathParse and RTPathSplit.
+ * @{ */
+
+/** Indicates that there is a filename.
+ * If not set, either a lone root spec was given (RTPATH_PROP_UNC,
+ * RTPATH_PROP_ROOT_SLASH, or RTPATH_PROP_VOLUME) or the final component had a
+ * trailing slash (RTPATH_PROP_DIR_SLASH). */
+#define RTPATH_PROP_FILENAME        UINT16_C(0x0001)
+/** Indicates that a directory was specified using a trailing slash.
+ * @note This is not set for lone root specifications (RTPATH_PROP_UNC,
+ *       RTPATH_PROP_ROOT_SLASH, or RTPATH_PROP_VOLUME).
+ * @note The slash is not counted into the last component. However, it is
+ *       counted into cchPath. */
+#define RTPATH_PROP_DIR_SLASH       UINT16_C(0x0002)
+
+/** The filename has a suffix (extension). */
+#define RTPATH_PROP_SUFFIX          UINT16_C(0x0004)
+/** Indicates that this is an UNC path (Windows and OS/2 only).
+ *
+ * UNC = Universal Naming Convention.  It is on the form '//Computer/',
+ * '//Namespace/', '//ComputerName/Resource' and '//Namespace/Resource'.
+ * RTPathParse, RTPathSplit and friends does not consider the 'Resource'  as
+ * part of the UNC root specifier.  Thus the root specs for the above examples
+ * would be '//ComputerName/' or '//Namespace/'.
+ *
+ * Please note that  '//something' is not a UNC path, there must be a slash
+ * following the computer or namespace.
+ */
+#define RTPATH_PROP_UNC             UINT16_C(0x0010)
+/** A root slash was specified (unix style root).
+ * (While the path must relative if not set, this being set doesn't make it
+ * absolute.)
+ *
+ * This will be set in the following examples: '/', '/bin', 'C:/', 'C:/Windows',
+ * '//./', '//./PhysicalDisk0', '//example.org/', and '//example.org/share'.
+ *
+ * It will not be set for the following examples: '.', 'bin/ls', 'C:', and
+ * 'C:Windows'.
+ */
+#define RTPATH_PROP_ROOT_SLASH      UINT16_C(0x0020)
+/** A volume is specified (Windows, DOS and OS/2).
+ * For examples: 'C:', 'C:/', and 'A:/AutoExec.bat'. */
+#define RTPATH_PROP_VOLUME          UINT16_C(0x0040)
+/** The path is absolute, i.e. has a root specifier (root-slash,
+ * volume or UNC) and contains no winding '..' bits, though it may contain
+ * unnecessary slashes (RTPATH_PROP_EXTRA_SLASHES) and '.' components
+ * (RTPATH_PROP_DOT_REFS).
+ *
+ * On systems without volumes and UNC (unix style) it will be set for '/',
+ * '/bin/ls', and '/bin//./ls', but not for 'bin/ls', /bin/../usr/bin/env',
+ * '/./bin/ls' or '/.'.
+ *
+ * On systems with volumes, it will be set for 'C:/', C:/Windows', and
+ * 'C:/./Windows//', but not for 'C:', 'C:Windows', or 'C:/Windows/../boot.ini'.
+ *
+ * On systems with UNC paths, it will be set for '//localhost/',
+ * '//localhost/C$', '//localhost/C$/Windows/System32', '//localhost/.', and
+ * '//localhost/C$//./AutoExec.bat', but not for
+ * '//localhost/C$/Windows/../AutoExec.bat'.
+ *
+ * @note For the RTPathAbs definition, this flag needs to be set while both
+ *       RTPATH_PROP_EXTRA_SLASHES and RTPATH_PROP_DOT_REFS must be cleared.
+ */
+#define RTPATH_PROP_ABSOLUTE        UINT16_C(0x0100)
+/** Relative path. Inverse of RTPATH_PROP_ABSOLUTE. */
+#define RTPATH_PROP_RELATIVE        UINT16_C(0x0200)
+/** The path contains unnecessary slashes. Meaning, that if  */
+#define RTPATH_PROP_EXTRA_SLASHES   UINT16_C(0x0400)
+/** The path contains references to the special '.' (dot) directory link. */
+#define RTPATH_PROP_DOT_REFS        UINT16_C(0x0800)
+/** The path contains references to the special '..' (dot) directory link.
+ * RTPATH_PROP_RELATIVE will always be set together with this.  */
+#define RTPATH_PROP_DOTDOT_REFS     UINT16_C(0x1000)
+
+
+/** Macro to determin whether to insert a slash after the first component when
+ * joining it with something else.
+ * (All other components in a split or parsed path requies slashes added.) */
+#define RTPATH_PROP_FIRST_NEEDS_NO_SLASH(a_fProps) \
+    RT_BOOL( (a_fProps) & (RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_VOLUME | RTPATH_PROP_UNC) )
+
+/** Macro to determin whether there is a root specification of any kind
+ * (unix, volumes, unc). */
+#define RTPATH_PROP_HAS_ROOT_SPEC(a_fProps) \
+    RT_BOOL( (a_fProps) & (RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_VOLUME | RTPATH_PROP_UNC) )
+
+/** @} */
+
+
+/**
+ * Parsed path.
+ *
+ * The first component is the root, volume or UNC specifier, if present.  Use
+ * RTPATH_PROP_HAS_ROOT_SPEC() on RTPATHPARSED::fProps to determine its
+ * presence.
+ *
+ * Other than the root component, no component will include directory separators
+ * (slashes).
+ */
+typedef struct RTPATHPARSED
+{
+    /** Number of path components.
+     * This will always be set on VERR_BUFFER_OVERFLOW returns from RTPathParsed
+     * so the caller can calculate the required buffer size. */
+    uint16_t    cComps;
+    /** Path property flags, RTPATH_PROP_XXX */
+    uint16_t    fProps;
+    /** On success this is the length of the described path, i.e. sum of all
+     * component lengths and necessary separators.
+     * Do NOT use this to index in the source path in case it contains
+     * unnecessary slashes that RTPathParsed has ignored here. */
+    uint16_t    cchPath;
+    /** Reserved for future use. */
+    uint16_t    u16Reserved;
+    /** The offset of the filename suffix, offset of the NUL char if none. */
+    uint16_t    offSuffix;
+    /** The lenght of the suffix. */
+    uint16_t    cchSuffix;
+    /** Array of component descriptors (variable size).
+     * @note Don't try figure the end of the input path by adding up off and cch
+     *       of the last component.  If RTPATH_PROP_DIR_SLASH is set, there may
+     *       be one or more trailing slashes that are unaccounted for! */
+    struct
+    {
+        /** The offset of the component. */
+        uint16_t    off;
+        /** The length of the component. */
+        uint16_t    cch;
+    } aComps[1];
+} RTPATHPARSED;
+/** Pointer to to a parsed path result. */
+typedef RTPATHPARSED *PRTPATHPARSED;
+/** Pointer to to a const parsed path result. */
+typedef RTPATHPARSED *PCRTPATHPARSED;
+
+
+/**
+ * Parses the path.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_POINTER if pParsed or pszPath is an invalid pointer.
+ * @retval  VERR_INVALID_PARAMETER if cbOutput is less than the RTPATHPARSED
+ *          strucuture. No output. (asserted)
+ * @retval  VERR_BUFFER_OVERFLOW there are more components in the path than
+ *          there is space in aComps. The required amount of space can be
+ *          determined from the pParsed->cComps:
+ *          @code
+ *              RT_OFFSETOF(RTPATHPARSED, aComps[pParsed->cComps])
+ *          @endcode
+ * @retval  VERR_PATH_ZERO_LENGTH if the path is empty.
+ *
+ * @param   pszPath             The path to parse.
+ * @param   pParsed             Where to store the details of the parsed path.
+ * @param   cbParsed            The size of the buffer. Must be at least the
+ *                              size of RTPATHPARSED.
+ * @param   fFlags              Combination of RTPATH_STR_F_XXX flags.
+ *                              Most users will pass 0.
+ * @sa      RTPathSplit, RTPathSplitA.
+ */
+RTDECL(int) RTPathParse(const char *pszPath, PRTPATHPARSED pParsed, size_t cbParsed, uint32_t fFlags);
+
+/**
+ * Reassembles a path parsed by RTPathParse.
+ *
+ * This will be more useful as more APIs manipulating the RTPATHPARSED output
+ * are added.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_BUFFER_OVERFLOW if @a cbDstPath is less than or equal to
+ *          RTPATHPARSED::cchPath.
+ *
+ * @param   pszSrcPath          The source path.
+ * @param   pParsed             The parser output for @a pszSrcPath.
+ * @param   fFlags              Combination of RTPATH_STR_F_STYLE_XXX.
+ *                              Most users will pass 0.
+ * @param   pszDstPath          Pointer to the buffer where the path is to be
+ *                              reassembled.
+ * @param   cbDstPath           The size of the output buffer.
+ */
+RTDECL(int) RTPathParsedReassemble(const char *pszSrcPath, PRTPATHPARSED pParsed, uint32_t fFlags,
+                                   char *pszDstPath, size_t cbDstPath);
+
+
+/**
+ * Output buffer for RTPathSplit and RTPathSplitA.
+ */
+typedef struct RTPATHSPLIT
+{
+    /** Number of path components.
+     * This will always be set on VERR_BUFFER_OVERFLOW returns from RTPathParsed
+     * so the caller can calculate the required buffer size. */
+    uint16_t    cComps;
+    /** Path property flags, RTPATH_PROP_XXX */
+    uint16_t    fProps;
+    /** On success this is the length of the described path, i.e. sum of all
+     * component lengths and necessary separators.
+     * Do NOT use this to index in the source path in case it contains
+     * unnecessary slashes that RTPathSplit has ignored here. */
+    uint16_t    cchPath;
+    /** Reserved (internal use).  */
+    uint16_t    u16Reserved;
+    /** The amount of memory used (on success) or required (on
+     *  VERR_BUFFER_OVERFLOW) of this structure and it's strings. */
+    uint32_t    cbNeeded;
+    /** Pointer to the filename suffix (the dot), if any. Points to the NUL
+     * character of the last component if none or if RTPATH_PROP_DIR_SLASH is
+     * present. */
+    const char *pszSuffix;
+    /** Array of component strings (variable size). */
+    char       *apszComps[1];
+} RTPATHSPLIT;
+/** Pointer to a split path buffer. */
+typedef RTPATHSPLIT *PRTPATHSPLIT;
+/** Pointer to a const split path buffer. */
+typedef RTPATHSPLIT const *PCRTPATHSPLIT;
+
+/**
+ * Splits the path into individual component strings, carved from user supplied
+ * the given buffer block.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_POINTER if pParsed or pszPath is an invalid pointer.
+ * @retval  VERR_INVALID_PARAMETER if cbOutput is less than the RTPATHSPLIT
+ *          strucuture. No output. (asserted)
+ * @retval  VERR_BUFFER_OVERFLOW there are more components in the path than
+ *          there is space in aComps. The required amount of space can be
+ *          determined from the pParsed->cComps:
+ *          @code
+ *              RT_OFFSETOF(RTPATHPARSED, aComps[pParsed->cComps])
+ *          @endcode
+ * @retval  VERR_PATH_ZERO_LENGTH if the path is empty.
+ * @retval  VERR_FILENAME_TOO_LONG if the filename is too long (close to 64 KB).
+ *
+ * @param   pszPath             The path to parse.
+ * @param   pSplit              Where to store the details of the parsed path.
+ * @param   cbSplit             The size of the buffer pointed to by @a pSplit
+ *                              (variable sized array at the end).  Must be at
+ *                              least the size of RTPATHSPLIT.
+ * @param   fFlags              Combination of RTPATH_STR_F_XXX flags.
+ *                              Most users will pass 0.
+ *
+ * @sa      RTPathSplitA, RTPathParse.
+ */
+RTDECL(int) RTPathSplit(const char *pszPath, PRTPATHSPLIT pSplit, size_t cbSplit, uint32_t fFlags);
+
+/**
+ * Splits the path into individual component strings, allocating the buffer on
+ * the default thread heap.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_POINTER if pParsed or pszPath is an invalid pointer.
+ * @retval  VERR_PATH_ZERO_LENGTH if the path is empty.
+ *
+ * @param   pszPath             The path to parse.
+ * @param   ppSplit             Where to return the pointer to the output on
+ *                              success.  This must be freed by calling
+ *                              RTPathSplitFree().
+ * @param   fFlags              Combination of RTPATH_STR_F_XXX flags.
+ *                              Most users will pass 0.
+ * @sa      RTPathSplitFree, RTPathSplit, RTPathParse.
+ */
+#define RTPathSplitA(pszPath, ppSplit, fFlags)      RTPathSplitATag(pszPath, ppSplit, fFlags, RTPATH_TAG)
+
+/**
+ * Splits the path into individual component strings, allocating the buffer on
+ * the default thread heap.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_POINTER if pParsed or pszPath is an invalid pointer.
+ * @retval  VERR_PATH_ZERO_LENGTH if the path is empty.
+ *
+ * @param   pszPath             The path to parse.
+ * @param   ppSplit             Where to return the pointer to the output on
+ *                              success.  This must be freed by calling
+ *                              RTPathSplitFree().
+ * @param   fFlags              Combination of RTPATH_STR_F_XXX flags.
+ *                              Most users will pass 0.
+ * @param   pszTag              Allocation tag used for statistics and such.
+ * @sa      RTPathSplitFree, RTPathSplit, RTPathParse.
+ */
+RTDECL(int) RTPathSplitATag(const char *pszPath, PRTPATHSPLIT *ppSplit, uint32_t fFlags, const char *pszTag);
+
+/**
+ * Frees buffer returned by RTPathSplitA.
+ *
+ * @param   pSplit              What RTPathSplitA returned.
+ * @sa      RTPathSplitA
+ */
+RTDECL(void) RTPathSplitFree(PRTPATHSPLIT pSplit);
+
+/**
+ * Reassembles a path parsed by RTPathSplit.
+ *
+ * This will be more useful as more APIs manipulating the RTPATHSPLIT output are
+ * added.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_BUFFER_OVERFLOW if @a cbDstPath is less than or equal to
+ *          RTPATHSPLIT::cchPath.
+ *
+ * @param   pSplit              A split path (see RTPathSplit, RTPathSplitA).
+ * @param   fFlags              Combination of RTPATH_STR_F_STYLE_XXX.
+ *                              Most users will pass 0.
+ * @param   pszDstPath          Pointer to the buffer where the path is to be
+ *                              reassembled.
+ * @param   cbDstPath           The size of the output buffer.
+ */
+RTDECL(int) RTPathSplitReassemble(PRTPATHSPLIT pSplit, uint32_t fFlags, char *pszDstPath, size_t cbDstPath);
+
+/**
+ * Checks if the two paths leads to the file system object.
+ *
+ * If the objects exist, we'll query attributes for them.  If that's not
+ * conclusive (some OSes) or one of them doesn't exist, we'll use a combination
+ * of RTPathAbs and RTPathCompare to determine the result.
+ *
+ * @returns true, false, or VERR_FILENAME_TOO_LONG.
+ * @param   pszPath1            The first path.
+ * @param   pszPath2            The seoncd path.
+ */
+RTDECL(int) RTPathIsSame(const char *pszPath1, const char *pszPath2);
+
+
+/**
+ * Compares two paths.
+ *
+ * The comparison takes platform-dependent details into account,
+ * such as:
+ * <ul>
+ * <li>On DOS-like platforms, both separator chars (|\| and |/|) are considered
+ *     to be equal.
+ * <li>On platforms with case-insensitive file systems, mismatching characters
+ *     are uppercased and compared again.
+ * </ul>
+ *
+ * @returns @< 0 if the first path less than the second path.
+ * @returns 0 if the first path identical to the second path.
+ * @returns @> 0 if the first path greater than the second path.
+ *
+ * @param   pszPath1    Path to compare (must be an absolute path).
+ * @param   pszPath2    Path to compare (must be an absolute path).
+ *
+ * @remarks File system details are currently ignored. This means that you won't
+ *          get case-insensitive compares on unix systems when a path goes into a
+ *          case-insensitive filesystem like FAT, HPFS, HFS, NTFS, JFS, or
+ *          similar. For NT, OS/2 and similar you'll won't get case-sensitive
+ *          compares on a case-sensitive file system.
+ */
+RTDECL(int) RTPathCompare(const char *pszPath1, const char *pszPath2);
+
+/**
+ * Checks if a path starts with the given parent path.
+ *
+ * This means that either the path and the parent path matches completely, or
+ * that the path is to some file or directory residing in the tree given by the
+ * parent directory.
+ *
+ * The path comparison takes platform-dependent details into account,
+ * see RTPathCompare() for details.
+ *
+ * @returns |true| when \a pszPath starts with \a pszParentPath (or when they
+ *          are identical), or |false| otherwise.
+ *
+ * @param   pszPath         Path to check, must be an absolute path.
+ * @param   pszParentPath   Parent path, must be an absolute path.
+ *                          No trailing directory slash!
+ *
+ * @remarks This API doesn't currently handle root directory compares in a
+ *          manner consistent with the other APIs. RTPathStartsWith(pszSomePath,
+ *          "/") will not work if pszSomePath isn't "/".
+ */
+RTDECL(bool) RTPathStartsWith(const char *pszPath, const char *pszParentPath);
+
+/**
+ * Appends one partial path to another.
+ *
+ * The main purpose of this function is to deal correctly with the slashes when
+ * concatenating the two partial paths.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the result is too big to fit within
+ *          cbPathDst bytes. No changes has been made.
+ * @retval  VERR_INVALID_PARAMETER if the string pointed to by pszPath is longer
+ *          than cbPathDst-1 bytes (failed to find terminator). Asserted.
+ *
+ * @param   pszPath         The path to append pszAppend to. This serves as both
+ *                          input and output. This can be empty, in which case
+ *                          pszAppend is just copied over.
+ * @param   cbPathDst       The size of the buffer pszPath points to, terminator
+ *                          included. This should NOT be strlen(pszPath).
+ * @param   pszAppend       The partial path to append to pszPath. This can be
+ *                          NULL, in which case nothing is done.
+ *
+ * @remarks See the RTPathAppendEx remarks.
+ */
+RTDECL(int) RTPathAppend(char *pszPath, size_t cbPathDst, const char *pszAppend);
+
+/**
+ * Appends one partial path to another.
+ *
+ * The main purpose of this function is to deal correctly with the slashes when
+ * concatenating the two partial paths.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the result is too big to fit within
+ *          cbPathDst bytes. No changes has been made.
+ * @retval  VERR_INVALID_PARAMETER if the string pointed to by pszPath is longer
+ *          than cbPathDst-1 bytes (failed to find terminator). Asserted.
+ *
+ * @param   pszPath         The path to append pszAppend to. This serves as both
+ *                          input and output. This can be empty, in which case
+ *                          pszAppend is just copied over.
+ * @param   cbPathDst       The size of the buffer pszPath points to, terminator
+ *                          included. This should NOT be strlen(pszPath).
+ * @param   pszAppend       The partial path to append to pszPath. This can be
+ *                          NULL, in which case nothing is done.
+ * @param   cchAppendMax    The maximum number or characters to take from @a
+ *                          pszAppend.  RTSTR_MAX is fine.
+ *
+ * @remarks On OS/2, Window and similar systems, concatenating a drive letter
+ *          specifier with a slash prefixed path will result in an absolute
+ *          path. Meaning, RTPathAppend(strcpy(szBuf, "C:"), sizeof(szBuf),
+ *          "/bar") will result in "C:/bar". (This follows directly from the
+ *          behavior when pszPath is empty.)
+ *
+ *          On the other hand, when joining a drive letter specifier with a
+ *          partial path that does not start with a slash, the result is not an
+ *          absolute path. Meaning, RTPathAppend(strcpy(szBuf, "C:"),
+ *          sizeof(szBuf), "bar") will result in "C:bar".
+ */
+RTDECL(int) RTPathAppendEx(char *pszPath, size_t cbPathDst, const char *pszAppend, size_t cchAppendMax);
+
+/**
+ * Like RTPathAppend, but with the base path as a separate argument instead of
+ * in the path buffer.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the result is too big to fit within
+ *          cbPathDst bytes.
+ * @retval  VERR_INVALID_PARAMETER if the string pointed to by pszPath is longer
+ *          than cbPathDst-1 bytes (failed to find terminator). Asserted.
+ *
+ * @param   pszPathDst      Where to store the resulting path.
+ * @param   cbPathDst       The size of the buffer pszPathDst points to,
+ *                          terminator included.
+ * @param   pszPathSrc      The base path to copy into @a pszPathDst before
+ *                          appending @a pszAppend.
+ * @param   pszAppend       The partial path to append to pszPathSrc. This can
+ *                          be NULL, in which case nothing is done.
+ *
+ */
+RTDECL(int) RTPathJoin(char *pszPathDst, size_t cbPathDst, const char *pszPathSrc,
+                       const char *pszAppend);
+
+/**
+ * Same as RTPathJoin, except that the output buffer is allocated.
+ *
+ * @returns Buffer containing the joined up path, call RTStrFree to free.  NULL
+ *          on allocation failure.
+ * @param   pszPathSrc      The base path to copy into @a pszPathDst before
+ *                          appending @a pszAppend.
+ * @param   pszAppend       The partial path to append to pszPathSrc. This can
+ *                          be NULL, in which case nothing is done.
+ *
+ */
+RTDECL(char *) RTPathJoinA(const char *pszPathSrc, const char *pszAppend);
+
+/**
+ * Extended version of RTPathJoin, both inputs can be specified as substrings.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the result is too big to fit within
+ *          cbPathDst bytes.
+ * @retval  VERR_INVALID_PARAMETER if the string pointed to by pszPath is longer
+ *          than cbPathDst-1 bytes (failed to find terminator). Asserted.
+ *
+ * @param   pszPathDst      Where to store the resulting path.
+ * @param   cbPathDst       The size of the buffer pszPathDst points to,
+ *                          terminator included.
+ * @param   pszPathSrc      The base path to copy into @a pszPathDst before
+ *                          appending @a pszAppend.
+ * @param   cchPathSrcMax   The maximum number of bytes to copy from @a
+ *                          pszPathSrc.  RTSTR_MAX is find.
+ * @param   pszAppend       The partial path to append to pszPathSrc. This can
+ *                          be NULL, in which case nothing is done.
+ * @param   cchAppendMax    The maximum number of bytes to copy from @a
+ *                          pszAppend.  RTSTR_MAX is find.
+ *
+ */
+RTDECL(int) RTPathJoinEx(char *pszPathDst, size_t cbPathDst,
+                         const char *pszPathSrc, size_t cchPathSrcMax,
+                         const char *pszAppend, size_t cchAppendMax);
+
+/**
+ * Callback for RTPathTraverseList that's called for each element.
+ *
+ * @returns IPRT style status code. Return VERR_TRY_AGAIN to continue, any other
+ *          value will abort the traversing and be returned to the caller.
+ *
+ * @param   pchPath         Pointer to the start of the current path. This is
+ *                          not null terminated.
+ * @param   cchPath         The length of the path.
+ * @param   pvUser1         The first user parameter.
+ * @param   pvUser2         The second user parameter.
+ */
+typedef DECLCALLBACK(int) FNRTPATHTRAVERSER(char const *pchPath, size_t cchPath, void *pvUser1, void *pvUser2);
+/** Pointer to a FNRTPATHTRAVERSER. */
+typedef FNRTPATHTRAVERSER *PFNRTPATHTRAVERSER;
+
+/**
+ * Traverses a string that can contain multiple paths separated by a special
+ * character.
+ *
+ * @returns IPRT style status code from the callback or VERR_END_OF_STRING if
+ *          the callback returned VERR_TRY_AGAIN for all paths in the string.
+ *
+ * @param   pszPathList     The string to traverse.
+ * @param   chSep           The separator character.  Using the null terminator
+ *                          is fine, but the result will simply be that there
+ *                          will only be one callback for the entire string
+ *                          (save any leading white space).
+ * @param   pfnCallback     The callback.
+ * @param   pvUser1         First user argument for the callback.
+ * @param   pvUser2         Second user argument for the callback.
+ */
+RTDECL(int) RTPathTraverseList(const char *pszPathList, char chSep, PFNRTPATHTRAVERSER pfnCallback, void *pvUser1, void *pvUser2);
+
+
+/**
+ * Calculate a relative path between the two given paths.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the result is too big to fit within
+ *          cbPathDst bytes.
+ * @retval  VERR_NOT_SUPPORTED if both paths start with different volume specifiers.
+ * @param   pszPathDst      Where to store the resulting path.
+ * @param   cbPathDst       The size of the buffer pszPathDst points to,
+ *                          terminator included.
+ * @param   pszPathFrom     The path to start from creating the relative path.
+ * @param   pszPathTo       The path to reach with the created relative path.
+ */
+RTDECL(int) RTPathCalcRelative(char *pszPathDst, size_t cbPathDst,
+                               const char *pszPathFrom,
+                               const char *pszPathTo);
+
+#ifdef IN_RING3
+
+/**
+ * Gets the path to the directory containing the executable.
+ *
+ * @returns iprt status code.
+ * @param   pszPath     Buffer where to store the path.
+ * @param   cchPath     Buffer size in bytes.
+ */
+RTDECL(int) RTPathExecDir(char *pszPath, size_t cchPath);
+
+/**
+ * Gets the user home directory.
+ *
+ * @returns iprt status code.
+ * @param   pszPath     Buffer where to store the path.
+ * @param   cchPath     Buffer size in bytes.
+ */
+RTDECL(int) RTPathUserHome(char *pszPath, size_t cchPath);
+
+/**
+ * Gets the user documents directory.
+ *
+ * The returned path isn't guaranteed to exist.
+ *
+ * @returns iprt status code.
+ * @param   pszPath     Buffer where to store the path.
+ * @param   cchPath     Buffer size in bytes.
+ */
+RTDECL(int) RTPathUserDocuments(char *pszPath, size_t cchPath);
+
+/**
+ * Gets the directory of shared libraries.
+ *
+ * This is not the same as RTPathAppPrivateArch() as Linux depends all shared
+ * libraries in a common global directory where ld.so can find them.
+ *
+ * Linux:    /usr/lib
+ * Solaris:  /opt/@<application@>/@<arch>@ or something
+ * Windows:  @<program files directory@>/@<application@>
+ * Old path: same as RTPathExecDir()
+ *
+ * @returns iprt status code.
+ * @param   pszPath     Buffer where to store the path.
+ * @param   cchPath     Buffer size in bytes.
+ */
+RTDECL(int) RTPathSharedLibs(char *pszPath, size_t cchPath);
+
+/**
+ * Gets the directory for architecture-independent application data, for
+ * example NLS files, module sources, ...
+ *
+ * Linux:    /usr/shared/@<application@>
+ * Solaris:  /opt/@<application@>
+ * Windows:  @<program files directory@>/@<application@>
+ * Old path: same as RTPathExecDir()
+ *
+ * @returns iprt status code.
+ * @param   pszPath     Buffer where to store the path.
+ * @param   cchPath     Buffer size in bytes.
+ */
+RTDECL(int) RTPathAppPrivateNoArch(char *pszPath, size_t cchPath);
+
+/**
+ * Gets the directory for architecture-dependent application data, for
+ * example modules which can be loaded at runtime.
+ *
+ * Linux:    /usr/lib/@<application@>
+ * Solaris:  /opt/@<application@>/@<arch>@ or something
+ * Windows:  @<program files directory@>/@<application@>
+ * Old path: same as RTPathExecDir()
+ *
+ * @returns iprt status code.
+ * @param   pszPath     Buffer where to store the path.
+ * @param   cchPath     Buffer size in bytes.
+ */
+RTDECL(int) RTPathAppPrivateArch(char *pszPath, size_t cchPath);
+
+/**
+ * Gets the toplevel directory for architecture-dependent application data.
+ *
+ * This differs from RTPathAppPrivateArch on Solaris only where it will work
+ * around the /opt/@<application@>/amd64 and /opt/@<application@>/i386 multi
+ * architecture installation style.
+ *
+ * Linux:    /usr/lib/@<application@>
+ * Solaris:  /opt/@<application@>
+ * Windows:  @<program files directory@>/@<application@>
+ * Old path: same as RTPathExecDir()
+ *
+ * @returns iprt status code.
+ * @param   pszPath     Buffer where to store the path.
+ * @param   cchPath     Buffer size in bytes.
+ */
+RTDECL(int) RTPathAppPrivateArchTop(char *pszPath, size_t cchPath);
+
+/**
+ * Gets the directory for documentation.
+ *
+ * Linux:    /usr/share/doc/@<application@>
+ * Solaris:  /opt/@<application@>
+ * Windows:  @<program files directory@>/@<application@>
+ * Old path: same as RTPathExecDir()
+ *
+ * @returns iprt status code.
+ * @param   pszPath     Buffer where to store the path.
+ * @param   cchPath     Buffer size in bytes.
+ */
+RTDECL(int) RTPathAppDocs(char *pszPath, size_t cchPath);
+
+/**
+ * Gets the temporary directory path.
+ *
+ * @returns iprt status code.
+ * @param   pszPath     Buffer where to store the path.
+ * @param   cchPath     Buffer size in bytes.
+ */
+RTDECL(int) RTPathTemp(char *pszPath, size_t cchPath);
+
+
+/**
+ * RTPathGlobl result entry.
+ */
+typedef struct RTPATHGLOBENTRY
+{
+    /** List entry. */
+    struct RTPATHGLOBENTRY *pNext;
+    /** RTDIRENTRYTYPE value. */
+    uint8_t                 uType;
+    /** Unused explicit padding. */
+    uint8_t                 bUnused;
+    /** The length of the path. */
+    uint16_t                cchPath;
+    /** The path to the file (variable length). */
+    char                    szPath[1];
+} RTPATHGLOBENTRY;
+/** Pointer to a GLOB result entry. */
+typedef RTPATHGLOBENTRY *PRTPATHGLOBENTRY;
+/** Pointer to a const GLOB result entry. */
+typedef RTPATHGLOBENTRY const *PCRTPATHGLOBENTRY;
+/** Pointer to a GLOB result entry pointer. */
+typedef PCRTPATHGLOBENTRY *PPCRTPATHGLOBENTRY;
+
+/**
+ * Performs wildcard expansion on a path pattern.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   pszPattern      The pattern to expand.
+ * @param   fFlags          RTPATHGLOB_F_XXX.
+ * @param   ppHead          Where to return the head of the result list.  This
+ *                          is always set to NULL on failure.
+ * @param   pcResults       Where to return the number of the result. Optional.
+ */
+RTDECL(int) RTPathGlob(const char *pszPattern, uint32_t fFlags, PPCRTPATHGLOBENTRY ppHead, uint32_t *pcResults);
+
+/** @name RTPATHGLOB_F_XXX - RTPathGlob flags
+ *  @{ */
+/** Case insensitive. */
+#define RTPATHGLOB_F_IGNORE_CASE        RT_BIT_32(0)
+/** Do not expand \${EnvOrSpecialVariable} in the pattern. */
+#define RTPATHGLOB_F_NO_VARIABLES       RT_BIT_32(1)
+/** Do not interpret a leading tilde as a home directory reference. */
+#define RTPATHGLOB_F_NO_TILDE           RT_BIT_32(2)
+/** Only return the first match. */
+#define RTPATHGLOB_F_FIRST_ONLY         RT_BIT_32(3)
+/** Only match directories (implied if pattern ends with slash). */
+#define RTPATHGLOB_F_ONLY_DIRS          RT_BIT_32(4)
+/** Do not match directories.  (Can't be used with RTPATHGLOB_F_ONLY_DIRS or
+ * patterns containing a trailing slash.) */
+#define RTPATHGLOB_F_NO_DIRS            RT_BIT_32(5)
+/** Disables the '**' wildcard pattern for matching zero or more subdirs. */
+#define RTPATHGLOB_F_NO_STARSTAR        RT_BIT_32(6)
+/** Mask of valid flags. */
+#define RTPATHGLOB_F_MASK               UINT32_C(0x0000007f)
+/** @} */
+
+/**
+ * Frees the results produced by RTPathGlob.
+ *
+ * @param   pHead           What RTPathGlob returned.  NULL ignored.
+ */
+RTDECL(void) RTPathGlobFree(PCRTPATHGLOBENTRY pHead);
+
+
+/**
+ * Query information about a file system object.
+ *
+ * This API will resolve NOT symbolic links in the last component (just like
+ * unix lstat()).
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS if the object exists, information returned.
+ * @retval  VERR_PATH_NOT_FOUND if any but the last component in the specified
+ *          path was not found or was not a directory.
+ * @retval  VERR_FILE_NOT_FOUND if the object does not exist (but path to the
+ *          parent directory exists).
+ *
+ * @param   pszPath     Path to the file system object.
+ * @param   pObjInfo    Object information structure to be filled on successful
+ *                      return.
+ * @param   enmAdditionalAttribs
+ *                      Which set of additional attributes to request.
+ *                      Use RTFSOBJATTRADD_NOTHING if this doesn't matter.
+ */
+RTR3DECL(int) RTPathQueryInfo(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs);
+
+/**
+ * Query information about a file system object.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS if the object exists, information returned.
+ * @retval  VERR_PATH_NOT_FOUND if any but the last component in the specified
+ *          path was not found or was not a directory.
+ * @retval  VERR_FILE_NOT_FOUND if the object does not exist (but path to the
+ *          parent directory exists).
+ *
+ * @param   pszPath     Path to the file system object.
+ * @param   pObjInfo    Object information structure to be filled on successful return.
+ * @param   enmAdditionalAttribs
+ *                      Which set of additional attributes to request.
+ *                      Use RTFSOBJATTRADD_NOTHING if this doesn't matter.
+ * @param   fFlags      RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK.
+ */
+RTR3DECL(int) RTPathQueryInfoEx(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags);
+
+/**
+ * Changes the mode flags of a file system object.
+ *
+ * The API requires at least one of the mode flag sets (Unix/Dos) to
+ * be set. The type is ignored.
+ *
+ * This API will resolve symbolic links in the last component since
+ * mode isn't important for symbolic links.
+ *
+ * @returns iprt status code.
+ * @param   pszPath     Path to the file system object.
+ * @param   fMode       The new file mode, see @ref grp_rt_fs for details.
+ */
+RTR3DECL(int) RTPathSetMode(const char *pszPath, RTFMODE fMode);
+
+/**
+ * Gets the mode flags of a file system object.
+ *
+ * @returns iprt status code.
+ * @param   pszPath     Path to the file system object.
+ * @param   pfMode      Where to store the file mode, see @ref grp_rt_fs for details.
+ *
+ * @remark  This is wrapper around RTPathQueryInfoEx(RTPATH_F_FOLLOW_LINK) and
+ *          exists to complement RTPathSetMode().
+ */
+RTR3DECL(int) RTPathGetMode(const char *pszPath, PRTFMODE pfMode);
+
+/**
+ * Changes one or more of the timestamps associated of file system object.
+ *
+ * This API will not resolve symbolic links in the last component (just
+ * like unix lutimes()).
+ *
+ * @returns iprt status code.
+ * @param   pszPath             Path to the file system object.
+ * @param   pAccessTime         Pointer to the new access time.
+ * @param   pModificationTime   Pointer to the new modification time.
+ * @param   pChangeTime         Pointer to the new change time. NULL if not to be changed.
+ * @param   pBirthTime          Pointer to the new time of birth. NULL if not to be changed.
+ *
+ * @remark  The file system might not implement all these time attributes,
+ *          the API will ignore the ones which aren't supported.
+ *
+ * @remark  The file system might not implement the time resolution
+ *          employed by this interface, the time will be chopped to fit.
+ *
+ * @remark  The file system may update the change time even if it's
+ *          not specified.
+ *
+ * @remark  POSIX can only set Access & Modification and will always set both.
+ */
+RTR3DECL(int) RTPathSetTimes(const char *pszPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
+                             PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime);
+
+/**
+ * Changes one or more of the timestamps associated of file system object.
+ *
+ * @returns iprt status code.
+ * @param   pszPath             Path to the file system object.
+ * @param   pAccessTime         Pointer to the new access time.
+ * @param   pModificationTime   Pointer to the new modification time.
+ * @param   pChangeTime         Pointer to the new change time. NULL if not to be changed.
+ * @param   pBirthTime          Pointer to the new time of birth. NULL if not to be changed.
+ * @param   fFlags              RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK.
+ *
+ * @remark  The file system might not implement all these time attributes,
+ *          the API will ignore the ones which aren't supported.
+ *
+ * @remark  The file system might not implement the time resolution
+ *          employed by this interface, the time will be chopped to fit.
+ *
+ * @remark  The file system may update the change time even if it's
+ *          not specified.
+ *
+ * @remark  POSIX can only set Access & Modification and will always set both.
+ */
+RTR3DECL(int) RTPathSetTimesEx(const char *pszPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
+                               PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime, uint32_t fFlags);
+
+/**
+ * Gets one or more of the timestamps associated of file system object.
+ *
+ * @returns iprt status code.
+ * @param   pszPath             Path to the file system object.
+ * @param   pAccessTime         Where to store the access time. NULL is ok.
+ * @param   pModificationTime   Where to store the modification time. NULL is ok.
+ * @param   pChangeTime         Where to store the change time. NULL is ok.
+ * @param   pBirthTime          Where to store the creation time. NULL is ok.
+ *
+ * @remark  This is wrapper around RTPathQueryInfo() and exists to complement
+ *          RTPathSetTimes().  If the last component is a symbolic link, it will
+ *          not be resolved.
+ */
+RTR3DECL(int) RTPathGetTimes(const char *pszPath, PRTTIMESPEC pAccessTime, PRTTIMESPEC pModificationTime,
+                             PRTTIMESPEC pChangeTime, PRTTIMESPEC pBirthTime);
+
+/**
+ * Changes the owner and/or group of a file system object.
+ *
+ * This API will not resolve symbolic links in the last component (just
+ * like unix lchown()).
+ *
+ * @returns iprt status code.
+ * @param   pszPath     Path to the file system object.
+ * @param   uid         The new file owner user id.  Pass NIL_RTUID to leave
+ *                      this unchanged.
+ * @param   gid         The new group id.  Pass NIL_RTGUID to leave this
+ *                      unchanged.
+ */
+RTR3DECL(int) RTPathSetOwner(const char *pszPath, uint32_t uid, uint32_t gid);
+
+/**
+ * Changes the owner and/or group of a file system object.
+ *
+ * @returns iprt status code.
+ * @param   pszPath     Path to the file system object.
+ * @param   uid         The new file owner user id.  Pass NIL_RTUID to leave
+ *                      this unchanged.
+ * @param   gid         The new group id.  Pass NIL_RTGID to leave this
+ *                      unchanged.
+ * @param   fFlags      RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK.
+ */
+RTR3DECL(int) RTPathSetOwnerEx(const char *pszPath, uint32_t uid, uint32_t gid, uint32_t fFlags);
+
+/**
+ * Gets the owner and/or group of a file system object.
+ *
+ * @returns iprt status code.
+ * @param   pszPath     Path to the file system object.
+ * @param   pUid        Where to store the owner user id. NULL is ok.
+ * @param   pGid        Where to store the group id. NULL is ok.
+ *
+ * @remark  This is wrapper around RTPathQueryInfo() and exists to complement
+ *          RTPathGetOwner().  If the last component is a symbolic link, it will
+ *          not be resolved.
+ */
+RTR3DECL(int) RTPathGetOwner(const char *pszPath, uint32_t *pUid, uint32_t *pGid);
+
+
+/** @name RTPathRename, RTDirRename & RTFileRename flags.
+ * @{ */
+/** Do not replace anything. */
+#define RTPATHRENAME_FLAGS_NO_REPLACE   UINT32_C(0)
+/** This will replace attempt any target which isn't a directory. */
+#define RTPATHRENAME_FLAGS_REPLACE      RT_BIT(0)
+/** Don't allow symbolic links as part of the path.
+ * @remarks this flag is currently not implemented and will be ignored. */
+#define RTPATHRENAME_FLAGS_NO_SYMLINKS  RT_BIT(1)
+/** @} */
+
+/**
+ * Renames a path within a filesystem.
+ *
+ * This will rename symbolic links.  If RTPATHRENAME_FLAGS_REPLACE is used and
+ * pszDst is a symbolic link, it will be replaced and not its target.
+ *
+ * @returns IPRT status code.
+ * @param   pszSrc      The source path.
+ * @param   pszDst      The destination path.
+ * @param   fRename     Rename flags, RTPATHRENAME_FLAGS_*.
+ */
+RTR3DECL(int) RTPathRename(const char *pszSrc,  const char *pszDst, unsigned fRename);
+
+/** @name RTPathUnlink flags.
+ * @{ */
+/** Don't allow symbolic links as part of the path.
+ * @remarks this flag is currently not implemented and will be ignored. */
+#define RTPATHUNLINK_FLAGS_NO_SYMLINKS  RT_BIT(0)
+/** @} */
+
+/**
+ * Removes the last component of the path.
+ *
+ * @returns IPRT status code.
+ * @param   pszPath     The path.
+ * @param   fUnlink     Unlink flags, RTPATHUNLINK_FLAGS_*.
+ */
+RTR3DECL(int) RTPathUnlink(const char *pszPath, uint32_t fUnlink);
+
+/**
+ * A /bin/rm tool.
+ *
+ * @returns Program exit code.
+ *
+ * @param   cArgs               The number of arguments.
+ * @param   papszArgs           The argument vector.  (Note that this may be
+ *                              reordered, so the memory must be writable.)
+ */
+RTDECL(RTEXITCODE) RTPathRmCmd(unsigned cArgs, char **papszArgs);
+
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/power.h b/ubuntu/vbox/include/iprt/power.h
new file mode 100644 (file)
index 0000000..bf0e241
--- /dev/null
@@ -0,0 +1,112 @@
+/** @file
+ * IPRT - Power management.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+#ifndef ___iprt_power_h
+#define ___iprt_power_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_power RTPower - Power management
+ * @ingroup grp_rt
+ * @{
+ */
+
+#ifdef IN_RING0
+
+/**
+ * MP event, see FNRTPOWERNOTIFICATION.
+ */
+typedef enum RTPOWEREVENT
+{
+    /** The system will go into suspend mode. */
+    RTPOWEREVENT_SUSPEND = 1,
+    /** The system has resumed. */
+    RTPOWEREVENT_RESUME
+} RTPOWEREVENT;
+
+/**
+ * Notification callback.
+ *
+ * The context this is called in differs a bit from platform to
+ * platform, so be careful while in here.
+ *
+ * @param   enmEvent    The event.
+ * @param   pvUser      The user argument.
+ */
+typedef DECLCALLBACK(void) FNRTPOWERNOTIFICATION(RTPOWEREVENT enmEvent, void *pvUser);
+/** Pointer to a FNRTPOWERNOTIFICATION(). */
+typedef FNRTPOWERNOTIFICATION *PFNRTPOWERNOTIFICATION;
+
+/**
+ * Registers a notification callback for power events.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_NO_MEMORY if a registration record cannot be allocated.
+ * @retval  VERR_ALREADY_EXISTS if the pfnCallback and pvUser already exist
+ *          in the callback list.
+ *
+ * @param   pfnCallback     The callback.
+ * @param   pvUser          The user argument to the callback function.
+ */
+RTDECL(int) RTPowerNotificationRegister(PFNRTPOWERNOTIFICATION pfnCallback, void *pvUser);
+
+/**
+ * This deregisters a notification callback registered via RTPowerNotificationRegister().
+ *
+ * The pfnCallback and pvUser arguments must be identical to the registration call
+ * of we won't find the right entry.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_NOT_FOUND if no matching entry was found.
+ *
+ * @param   pfnCallback     The callback.
+ * @param   pvUser          The user argument to the callback function.
+ */
+RTDECL(int) RTPowerNotificationDeregister(PFNRTPOWERNOTIFICATION pfnCallback, void *pvUser);
+
+/**
+ * This calls all registered power management callback handlers registered via RTPowerNotificationRegister().
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ *
+ * @param   enmEvent        Power Management event
+ */
+RTDECL(int) RTPowerSignalEvent(RTPOWEREVENT enmEvent);
+
+#endif /* IN_RING0 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/process.h b/ubuntu/vbox/include/iprt/process.h
new file mode 100644 (file)
index 0000000..043653e
--- /dev/null
@@ -0,0 +1,421 @@
+/** @file
+ * IPRT - Process Management.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_process_h
+#define ___iprt_process_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_process    RTProc - Process Management
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/**
+ * Process priority.
+ *
+ * The process priority is used to select how scheduling properties
+ * are assigned to the different thread types (see THREADTYPE).
+ *
+ * In addition to using the policy assigned to the process at startup (DEFAULT)
+ * it is possible to change the process priority at runtime. This allows for
+ * a GUI, resource manager or admin to adjust the general priority of a task
+ * without upsetting the fine-tuned priority of the threads within.
+ */
+typedef enum RTPROCPRIORITY
+{
+    /** Invalid priority. */
+    RTPROCPRIORITY_INVALID = 0,
+    /** Default priority.
+     * Derive the scheduling policy from the priority of the RTR3Init()
+     * and RTProcSetPriority() callers and the rights the process have
+     * to alter its own priority.
+     */
+    RTPROCPRIORITY_DEFAULT,
+    /** Flat priority.
+     * Assumes a scheduling policy which puts the process at the default priority
+     * and with all thread at the same priority.
+     */
+    RTPROCPRIORITY_FLAT,
+    /** Low priority.
+     * Assumes a scheduling policy which puts the process mostly below the
+     * default priority of the host OS.
+     */
+    RTPROCPRIORITY_LOW,
+    /** Normal priority.
+     * Assume a scheduling policy which shares the CPU resources fairly with
+     * other processes running with the default priority of the host OS.
+     */
+    RTPROCPRIORITY_NORMAL,
+    /** High priority.
+     * Assumes a scheduling policy which puts the task above the default
+     * priority of the host OS. This policy might easily cause other tasks
+     * in the system to starve.
+     */
+    RTPROCPRIORITY_HIGH,
+    /** Last priority, used for validation. */
+    RTPROCPRIORITY_LAST
+} RTPROCPRIORITY;
+
+
+/**
+ * Get the current process identifier.
+ *
+ * @returns Process identifier.
+ */
+RTDECL(RTPROCESS) RTProcSelf(void);
+
+
+#ifdef IN_RING0
+/**
+ * Get the current process handle.
+ *
+ * @returns Ring-0 process handle.
+ */
+RTR0DECL(RTR0PROCESS) RTR0ProcHandleSelf(void);
+#endif
+
+
+#ifdef IN_RING3
+
+/**
+ * Attempts to alter the priority of the current process.
+ *
+ * @returns iprt status code.
+ * @param   enmPriority     The new priority.
+ */
+RTR3DECL(int) RTProcSetPriority(RTPROCPRIORITY enmPriority);
+
+/**
+ * Gets the current priority of this process.
+ *
+ * @returns The priority (see RTPROCPRIORITY).
+ */
+RTR3DECL(RTPROCPRIORITY) RTProcGetPriority(void);
+
+/**
+ * Create a child process.
+ *
+ * @returns iprt status code.
+ * @param   pszExec     Executable image to use to create the child process.
+ * @param   papszArgs   Pointer to an array of arguments to the child. The array terminated by an entry containing NULL.
+ * @param   Env         Handle to the environment block for the child.
+ * @param   fFlags      Flags, one of the RTPROC_FLAGS_* defines.
+ * @param   pProcess    Where to store the process identifier on successful return.
+ *                      The content is not changed on failure. NULL is allowed.
+ */
+RTR3DECL(int)   RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess);
+
+
+/**
+ * Create a child process.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   pszExec     Executable image to use to create the child process.
+ * @param   papszArgs   Pointer to an array of arguments to the child.  The
+ *                      array terminated by an entry containing NULL.
+ * @param   hEnv        Handle to the environment block for the child.  Pass
+ *                      RTENV_DEFAULT to use the environment of the current
+ *                      process.
+ * @param   fFlags      Flags, one of the RTPROC_FLAGS_* defines.
+ * @param   phStdIn     The standard in handle to assign the new process. Pass
+ *                      NULL to use the same as the current process.  If the
+ *                      handle is NIL, we'll close the standard input of the
+ *                      guest.
+ * @param   phStdOut    The standard out handle to assign the new process.  Pass
+ *                      NULL to use the same as the current process.  If the
+ *                      handle is NIL, we'll close the standard output of the
+ *                      guest.
+ * @param   phStdErr    The standard error handle to assign the new process.  Pass
+ *                      NULL to use the same as the current process.  If the
+ *                      handle is NIL, we'll close the standard error of the
+ *                      guest.
+ * @param   pszAsUser   User to run the process as.  Pass NULL to use the same
+ *                      user as the current process.
+ *                      Windows: Use user\@domain (UPN, User Principal Name)
+ *                      format to specify a domain.
+ * @param   pszPassword Password to use to authenticate @a pszAsUser.  Must be
+ *                      NULL wif pszAsUser is NULL.  Whether this is actually
+ *                      used or not depends on the platform.
+ * @param   phProcess   Where to store the process handle on successful return.
+ *                      The content is not changed on failure.  NULL is allowed.
+ *
+ * @remarks The handles does not have to be created as inheritable, but it
+ *          doesn't hurt if they are as it may avoid race conditions on some
+ *          platforms.
+ *
+ * @remarks The as-user feature isn't supported/implemented on all platforms and
+ *          will cause a-yet-to-be-determined-error-status on these.
+ */
+RTR3DECL(int)   RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags,
+                               PCRTHANDLE phStdIn, PCRTHANDLE phStdOut, PCRTHANDLE phStdErr, const char *pszAsUser,
+                               const char *pszPassword, PRTPROCESS phProcess);
+
+/** @name RTProcCreate and RTProcCreateEx flags
+ * @{ */
+/** Detach the child process from the parents process tree and process group,
+ * session or/and console (depends on the platform what's done applicable).
+ *
+ * The new process will not be a direct decendent of the parent and it will not
+ * be possible to wait for it, i.e. @a phProcess shall be NULL. */
+#define RTPROC_FLAGS_DETACHED               RT_BIT(0)
+/** Don't show the started process.
+ * This is a Windows (and maybe OS/2) concept, do not use on other platforms. */
+#define RTPROC_FLAGS_HIDDEN                 RT_BIT(1)
+/** Use special code path for starting child processes from a service (daemon).
+ * This is a windows concept for dealing with the so called "Session 0"
+ * isolation which was introduced with Windows Vista. Do not use on other
+ * platforms. */
+#define RTPROC_FLAGS_SERVICE                RT_BIT(2)
+/** Suppress changing the process contract id for the child process
+ * on Solaris.  Without this flag the contract id is always changed, as that's
+ * the more frequently used case. */
+#define RTPROC_FLAGS_SAME_CONTRACT          RT_BIT(3)
+/** Load user profile data when executing a process.
+ * This redefines the meaning of RTENV_DEFAULT to the profile environment.
+ * @remarks On non-windows platforms, the resulting environment maybe very
+ *          different from what you see in your shell.  Among other reasons,
+ *          we cannot run shell profile scripts which typically sets up the
+ *          environment. */
+#define RTPROC_FLAGS_PROFILE                RT_BIT(4)
+/** Create process without a console window.
+ * This is a Windows (and OS/2) concept, do not use on other platforms. */
+#define RTPROC_FLAGS_NO_WINDOW              RT_BIT(5)
+/** Search the PATH for the executable.  */
+#define RTPROC_FLAGS_SEARCH_PATH            RT_BIT(6)
+/** Don't quote and escape arguments on Windows and similar platforms where a
+ * command line is passed to the child process instead of an argument vector,
+ * just join up argv with a space between each.  Ignored on platforms
+ * passing argument the vector. */
+#define RTPROC_FLAGS_UNQUOTED_ARGS          RT_BIT(7)
+/** Consider hEnv an environment change record to be applied to RTENV_DEFAULT.
+ * If hEnv is RTENV_DEFAULT, the flag has no effect. */
+#define RTPROC_FLAGS_ENV_CHANGE_RECORD      RT_BIT(8)
+/** Valid flag mask. */
+#define RTPROC_FLAGS_VALID_MASK             UINT32_C(0x1ff)
+/** @}  */
+
+
+/**
+ * Process exit reason.
+ */
+typedef enum RTPROCEXITREASON
+{
+    /** Normal exit. iStatus contains the exit code. */
+    RTPROCEXITREASON_NORMAL = 1,
+    /** Any abnormal exit. iStatus is undefined. */
+    RTPROCEXITREASON_ABEND,
+    /** Killed by a signal. The iStatus field contains the signal number. */
+    RTPROCEXITREASON_SIGNAL
+} RTPROCEXITREASON;
+
+/**
+ * Process exit status.
+ */
+typedef struct RTPROCSTATUS
+{
+    /** The process exit status if the exit was a normal one. */
+    int                 iStatus;
+    /** The reason the process terminated. */
+    RTPROCEXITREASON    enmReason;
+} RTPROCSTATUS;
+/** Pointer to a process exit status structure. */
+typedef RTPROCSTATUS *PRTPROCSTATUS;
+/** Pointer to a const process exit status structure. */
+typedef const RTPROCSTATUS *PCRTPROCSTATUS;
+
+
+/** Flags for RTProcWait().
+ * @{ */
+/** Block indefinitly waiting for the process to exit. */
+#define RTPROCWAIT_FLAGS_BLOCK      0
+/** Don't block, just check if the process have exited. */
+#define RTPROCWAIT_FLAGS_NOBLOCK    1
+/** @} */
+
+/**
+ * Waits for a process, resumes on interruption.
+ *
+ * @returns VINF_SUCCESS when the status code for the process was collected and
+ *          put in *pProcStatus.
+ * @returns VERR_PROCESS_NOT_FOUND if the specified process wasn't found.
+ * @returns VERR_PROCESS_RUNNING when the RTPROCWAIT_FLAGS_NOBLOCK and the
+ *          process haven't exited yet.
+ *
+ * @param   Process         The process to wait for.
+ * @param   fFlags          The wait flags, any of the RTPROCWAIT_FLAGS_ \#defines.
+ * @param   pProcStatus     Where to store the exit status on success.
+ *                          Optional.
+ */
+RTR3DECL(int) RTProcWait(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus);
+
+/**
+ * Waits for a process, returns on interruption.
+ *
+ * @returns VINF_SUCCESS when the status code for the process was collected and
+ *          put in *pProcStatus.
+ * @returns VERR_PROCESS_NOT_FOUND if the specified process wasn't found.
+ * @returns VERR_PROCESS_RUNNING when the RTPROCWAIT_FLAGS_NOBLOCK and the
+ *          process haven't exited yet.
+ * @returns VERR_INTERRUPTED when the wait was interrupted by the arrival of a
+ *          signal or other async event.
+ *
+ * @param   Process         The process to wait for.
+ * @param   fFlags          The wait flags, any of the RTPROCWAIT_FLAGS_ \#defines.
+ * @param   pProcStatus     Where to store the exit status on success.
+ *                          Optional.
+ */
+RTR3DECL(int) RTProcWaitNoResume(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus);
+
+/**
+ * Terminates (kills) a running process.
+ *
+ * @returns IPRT status code.
+ * @param   Process     The process to terminate.
+ */
+RTR3DECL(int) RTProcTerminate(RTPROCESS Process);
+
+/**
+ * Gets the processor affinity mask of the current process.
+ *
+ * @returns The affinity mask.
+ */
+RTR3DECL(uint64_t) RTProcGetAffinityMask(void);
+
+/**
+ * Gets the short process name.
+ *
+ * @returns Pointer to read-only name string.
+ */
+RTR3DECL(const char *) RTProcShortName(void);
+
+/**
+ * Gets the path to the executable image of the current process.
+ *
+ * @returns pszExecPath on success. NULL on buffer overflow or other errors.
+ *
+ * @param   pszExecPath     Where to store the path.
+ * @param   cbExecPath      The size of the buffer.
+ */
+RTR3DECL(char *) RTProcGetExecutablePath(char *pszExecPath, size_t cbExecPath);
+
+/**
+ * Daemonize the current process, making it a background process.
+ *
+ * The way this work is that it will spawn a detached / backgrounded /
+ * daemonized / call-it-what-you-want process that isn't a direct child of the
+ * current process.  The spawned will have the same arguments a the caller,
+ * except that the @a pszDaemonizedOpt is appended to prevent that the new
+ * process calls this API again.
+ *
+ * The new process will have the standard handles directed to/from the
+ * bitbucket.
+ *
+ * @returns IPRT status code.  On success it is normal for the caller to exit
+ *          the process by returning from main().
+ *
+ * @param   papszArgs           The argument vector of the calling process.
+ * @param   pszDaemonizedOpt    The daemonized option.  This is appended to the
+ *                              end of the parameter list of the daemonized process.
+ */
+RTR3DECL(int)   RTProcDaemonize(const char * const *papszArgs, const char *pszDaemonizedOpt);
+
+/**
+ * Daemonize the current process, making it a background process. The current
+ * process will exit if daemonizing is successful.
+ *
+ * @returns IPRT status code.   On success it will only return in the child
+ *          process, the parent will exit.  On failure, it will return in the
+ *          parent process and no child has been spawned.
+ *
+ * @param   fNoChDir    Pass false to change working directory to "/".
+ * @param   fNoClose    Pass false to redirect standard file streams to the null device.
+ * @param   pszPidfile  Path to a file to write the process id of the daemon
+ *                      process to. Daemonizing will fail if this file already
+ *                      exists or cannot be written. May be NULL.
+ */
+RTR3DECL(int)   RTProcDaemonizeUsingFork(bool fNoChDir, bool fNoClose, const char *pszPidfile);
+
+/**
+ * Check if the given process is running on the system.
+ *
+ * This check is case sensitive on most systems, except for Windows, OS/2 and
+ * Darwin.
+ *
+ * @returns true if the process is running & false otherwise.
+ * @param   pszName     Process name to search for. If no path is given only the
+ *                      filename part of the running process set will be
+ *                      matched. If a path is specified, the full path will be
+ *                      matched.
+ */
+RTR3DECL(bool)  RTProcIsRunningByName(const char *pszName);
+
+/**
+ * Queries the parent process ID.
+ *
+ * @returns IPRT status code
+ * @param   hProcess     The process to query the parent of.
+ * @param   phParent     Where to return the parent process ID.
+ */
+RTR3DECL(int) RTProcQueryParent(RTPROCESS hProcess, PRTPROCESS phParent);
+
+/**
+ * Query the username of the given process.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_BUFFER_OVERFLOW if the given buffer size is to small for the username.
+ * @param   hProcess     The process handle to query the username for.
+ *                       NIL_PROCESS is an alias for the current process.
+ * @param   pszUser      Where to store the user name on success.
+ * @param   cbUser       The size of the user name buffer.
+ * @param   pcbUser      Where to store the username length on success
+ *                       or the required buffer size if VERR_BUFFER_OVERFLOW
+ *                       is returned.
+ */
+RTR3DECL(int)   RTProcQueryUsername(RTPROCESS hProcess, char *pszUser, size_t cbUser, size_t *pcbUser);
+
+/**
+ * Query the username of the given process allocating the string for the username.
+ *
+ * @returns IPRT status code.
+ * @param   hProcess     The process handle to query the username for.
+ * @param   ppszUser     Where to store the pointer to the string containing
+ *                       the username on success. Free with RTStrFree().
+ */
+RTR3DECL(int)   RTProcQueryUsernameA(RTPROCESS hProcess, char **ppszUser);
+
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/semaphore.h b/ubuntu/vbox/include/iprt/semaphore.h
new file mode 100644 (file)
index 0000000..8220c13
--- /dev/null
@@ -0,0 +1,1409 @@
+/** @file
+ * IPRT - Semaphore.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_semaphore_h
+#define ___iprt_semaphore_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3)
+# include <iprt/lockvalidator.h>
+#endif
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_sems    RTSem - Semaphores
+ *
+ * This module implements all kinds of event and mutex semaphores; in addition
+ * to these, IPRT implements "critical sections", which are fast recursive
+ * mutexes (see @ref grp_rt_critsect ).  C++ users may find @ref grp_rt_cpp_lock
+ * interesting.
+ *
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/** @name Generic Semaphore Wait Flags.
+ *
+ * @remarks Exactly one of RTSEMWAIT_FLAGS_RELATIVE and
+ *          RTSEMWAIT_FLAGS_ABSOLUTE must be set, unless
+ *          RTSEMWAIT_FLAGS_INDEFINITE is used.
+ *
+ *          Exactly one of RTSEMWAIT_FLAGS_NANOSECS and
+ *          RTSEMWAIT_FLAGS_MILLISECS must be set, unless
+ *          RTSEMWAIT_FLAGS_INDEFINITE is used.
+ *
+ *          Exactly one of RTSEMWAIT_FLAGS_RESUME and RTSEMWAIT_FLAGS_NORESUME
+ *          must be set.
+ *
+ *          The interruptible vs resume stuff is ring-0 vs ring-3 semantics.
+ *
+ * @{ */
+/** The timeout is relative. */
+#define RTSEMWAIT_FLAGS_RELATIVE            RT_BIT_32(0)
+/** The timeout is absolute. */
+#define RTSEMWAIT_FLAGS_ABSOLUTE            RT_BIT_32(1)
+/** The timeout is specified in nanoseconds. */
+#define RTSEMWAIT_FLAGS_NANOSECS            RT_BIT_32(2)
+/** The timeout is specified in milliseconds. */
+#define RTSEMWAIT_FLAGS_MILLISECS           RT_BIT_32(3)
+/** Indefinite wait.
+ * The relative/absolute and nano-/millisecond flags are ignored. */
+#define RTSEMWAIT_FLAGS_INDEFINITE          RT_BIT_32(4)
+/** Mask covering the time related bits. */
+#define RTSEMWAIT_FLAGS_TIME_MASK           UINT32_C(0x0000001f)
+
+/** Interruptible wait. */
+#define RTSEMWAIT_FLAGS_INTERRUPTIBLE       RT_BIT_32(5)
+/** No automatic resume, same as interruptible. */
+#define RTSEMWAIT_FLAGS_NORESUME            RTSEMWAIT_FLAGS_INTERRUPTIBLE
+/** Uninterruptible wait. */
+#define RTSEMWAIT_FLAGS_UNINTERRUPTIBLE     RT_BIT_32(6)
+/** Resume on interrupt, same as uninterruptible. */
+#define RTSEMWAIT_FLAGS_RESUME              RTSEMWAIT_FLAGS_UNINTERRUPTIBLE
+
+/** Macro for validate the flags. */
+#define RTSEMWAIT_FLAGS_ARE_VALID(fFlags) \
+    (   !((fFlags) & UINT32_C(0xffffff80)) \
+     &&  (  ((fFlags) & RTSEMWAIT_FLAGS_INDEFINITE) \
+          ? ( (((fFlags) & UINT32_C(0x20))) ^ (((fFlags) >> 1) & UINT32_C(0x20)) ) == UINT32_C(0x20) \
+          : ( (((fFlags) & UINT32_C(0x25))) ^ (((fFlags) >> 1) & UINT32_C(0x25)) ) == UINT32_C(0x25) ))
+/** @}  */
+
+
+
+/** @defgroup grp_rt_sems_event    RTSemEvent - Single Release Event Semaphores
+ *
+ * Event semaphores can be used for inter-thread communication when one thread
+ * wants to notify another thread that something happened.  A thread can block
+ * ("wait") on an event semaphore until it is signalled by another thread; see
+ * RTSemEventCreate, RTSemEventSignal and RTSemEventWait.
+ *
+ * @{ */
+
+/**
+ * Create an event semaphore.
+ *
+ * @returns iprt status code.
+ * @param   phEventSem          Where to store the handle to the newly created
+ *                              event semaphore.
+ */
+RTDECL(int)  RTSemEventCreate(PRTSEMEVENT phEventSem);
+
+/**
+ * Create an event semaphore.
+ *
+ * @returns iprt status code.
+ * @param   phEventSem          Where to store the handle to the newly created
+ *                              event semaphore.
+ * @param   fFlags              Flags, any combination of the
+ *                              RTSEMEVENT_FLAGS_XXX \#defines.
+ * @param   hClass              The class (no reference consumed).  Since we
+ *                              don't do order checks on event semaphores, the
+ *                              use of the class is limited to controlling the
+ *                              timeout threshold for deadlock detection.
+ * @param   pszNameFmt          Name format string for the lock validator,
+ *                              optional (NULL).  Max length is 32 bytes.
+ * @param   ...                 Format string arguments.
+ */
+RTDECL(int)  RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
+                                const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(4, 5);
+
+/** @name RTSemMutexCreateEx flags
+ * @{ */
+/** Disables lock validation. */
+#define RTSEMEVENT_FLAGS_NO_LOCK_VAL    UINT32_C(0x00000001)
+/** Bootstrap hack for use with certain memory allocator locks only! */
+#define RTSEMEVENT_FLAGS_BOOTSTRAP_HACK UINT32_C(0x00000004)
+/** @} */
+
+/**
+ * Destroy an event semaphore.
+ *
+ * @returns iprt status code.
+ * @param   hEventSem           Handle of the event semaphore.  NIL_RTSEMEVENT
+ *                              is quietly ignored (VINF_SUCCESS).
+ */
+RTDECL(int)  RTSemEventDestroy(RTSEMEVENT hEventSem);
+
+/**
+ * Signal an event semaphore.
+ *
+ * The event semaphore will be signaled and automatically reset after exactly
+ * one thread have successfully returned from RTSemEventWait() after
+ * waiting/polling on that semaphore.
+ *
+ * @returns iprt status code.
+ * @param   hEventSem           The event semaphore to signal.
+ *
+ * @remarks ring-0: This works when preemption is disabled.  However it is
+ *          system specific whether it works in interrupt context or with
+ *          interrupts disabled.
+ */
+RTDECL(int)  RTSemEventSignal(RTSEMEVENT hEventSem);
+
+/**
+ * Wait for the event semaphore to be signaled, resume on interruption.
+ *
+ * This function will resume if the wait is interrupted by an async system event
+ * (like a unix signal) or similar.
+ *
+ * @returns iprt status code.
+ *          Will not return VERR_INTERRUPTED.
+ * @param   hEventSem           The event semaphore to wait on.
+ * @param   cMillies            Number of milliseconds to wait.
+ */
+RTDECL(int)  RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies);
+
+/**
+ * Wait for the event semaphore to be signaled, return on interruption.
+ *
+ * This function will not resume the wait if interrupted.
+ *
+ * @returns iprt status code.
+ * @param   hEventSem           The event semaphore to wait on.
+ * @param   cMillies            Number of milliseconds to wait.
+ */
+RTDECL(int)  RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies);
+
+/**
+ * Extended API for waiting on an event semaphore to be signaled.
+ *
+ * @returns IPRT status code.
+ * @param   hEventSem           The event semaphore to wait on.
+ * @param   fFlags              Combination of RTSEMWAIT_FLAGS_XXX.
+ * @param   uTimeout            The timeout, ignored if
+ *                              RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags.
+ *                              Whether this is absolute or relative,
+ *                              milliseconds or nanoseconds depends on the @a
+ *                              fFlags value.  Do not pass RT_INDEFINITE_WAIT
+ *                              here, use RTSEMWAIT_FLAGS_INDEFINITE instead.
+ */
+RTDECL(int)  RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout);
+
+/**
+ * Debug version of RTSemEventWaitEx that tracks the location.
+ *
+ * @returns IPRT status code, see RTSemEventWaitEx.
+ * @param   hEventSem           The event semaphore to wait on.
+ * @param   fFlags              See RTSemEventWaitEx.
+ * @param   uTimeout            See RTSemEventWaitEx.
+ * @param   uId                 Some kind of locking location ID.  Typically a
+ *                              return address up the stack.  Optional (0).
+ * @param   SRC_POS             The source position where call is being made
+ *                              from.  Use RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(int)  RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout,
+                                   RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Gets the best timeout resolution that RTSemEventWaitEx can do.
+ *
+ * @returns The resolution in nanoseconds.
+ */
+RTDECL(uint32_t) RTSemEventGetResolution(void);
+
+/**
+ * Sets the signaller thread to one specific thread.
+ *
+ * This is only used for validating usage and deadlock detection.  When used
+ * after calls to RTSemEventAddSignaller, the specified thread will be the only
+ * signalling thread.
+ *
+ * @param   hEventSem           The event semaphore.
+ * @param   hThread             The thread that will signal it.  Pass
+ *                              NIL_RTTHREAD to indicate that there is no
+ *                              special signalling thread.
+ */
+RTDECL(void) RTSemEventSetSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread);
+
+/**
+ * To add more signalling threads.
+ *
+ * First call RTSemEventSetSignaller then add further threads with this.
+ *
+ * @param   hEventSem           The event semaphore.
+ * @param   hThread             The thread that will signal it. NIL_RTTHREAD is
+ *                              not accepted.
+ */
+RTDECL(void) RTSemEventAddSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread);
+
+/**
+ * To remove a signalling thread.
+ *
+ * Reverts work done by RTSemEventAddSignaller and RTSemEventSetSignaller.
+ *
+ * @param   hEventSem           The event semaphore.
+ * @param   hThread             A previously added thread.
+ */
+RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread);
+
+/** @} */
+
+
+/** @defgroup grp_rt_sems_event_multi   RTSemEventMulti - Multiple Release Event Semaphores
+ *
+ * A variant of @ref  grp_rt_sems_event where all threads will be unblocked when
+ * signalling the semaphore.
+ *
+ * @{ */
+
+/**
+ * Creates a multiple release event semaphore.
+ *
+ * @returns iprt status code.
+ * @param   phEventMultiSem     Where to store the handle to the newly created
+ *                              multiple release event semaphore.
+ */
+RTDECL(int)  RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem);
+
+/**
+ * Creates a multiple release event semaphore.
+ *
+ * @returns iprt status code.
+ * @param   phEventMultiSem     Where to store the handle to the newly created
+ *                              multiple release event semaphore.
+ * @param   fFlags              Flags, any combination of the
+ *                              RTSEMEVENTMULTI_FLAGS_XXX \#defines.
+ * @param   hClass              The class (no reference consumed).  Since we
+ *                              don't do order checks on event semaphores, the
+ *                              use of the class is limited to controlling the
+ *                              timeout threshold for deadlock detection.
+ * @param   pszNameFmt          Name format string for the lock validator,
+ *                              optional (NULL).  Max length is 32 bytes.
+ * @param   ...                 Format string arguments.
+ */
+RTDECL(int)  RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
+                                     const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(4, 5);
+
+/** @name RTSemMutexCreateEx flags
+ * @{ */
+/** Disables lock validation. */
+#define RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL   UINT32_C(0x00000001)
+/** @} */
+
+/**
+ * Destroy an event multi semaphore.
+ *
+ * @returns iprt status code.
+ * @param   hEventMultiSem      The multiple release event semaphore.  NIL is
+ *                              quietly ignored (VINF_SUCCESS).
+ */
+RTDECL(int)  RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem);
+
+/**
+ * Signal an event multi semaphore.
+ *
+ * @returns iprt status code.
+ * @param   hEventMultiSem      The multiple release event semaphore.
+ *
+ * @remarks ring-0: This works when preemption is disabled.  However it is
+ *          system specific whether it works in interrupt context or with
+ *          interrupts disabled.
+ */
+RTDECL(int)  RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem);
+
+/**
+ * Resets an event multi semaphore to non-signaled state.
+ *
+ * @returns iprt status code.
+ * @param   hEventMultiSem      The multiple release event semaphore.
+ */
+RTDECL(int)  RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem);
+
+/**
+ * Wait for the event multi semaphore to be signaled, resume on interruption.
+ *
+ * This function will resume if the wait is interrupted by an async
+ * system event (like a unix signal) or similar.
+ *
+ * @returns iprt status code.
+ *          Will not return VERR_INTERRUPTED.
+ * @param   hEventMultiSem      The multiple release event semaphore.
+ * @param   cMillies            Number of milliseconds to wait.
+ */
+RTDECL(int)  RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies);
+
+/**
+ * Wait for the event multi semaphore to be signaled, return on interruption.
+ *
+ * This function will not resume the wait if interrupted.
+ *
+ * @returns iprt status code.
+ * @param   hEventMultiSem      The multiple release event semaphore.
+ * @param   cMillies            Number of milliseconds to wait.
+ * @todo    Rename to RTSemEventMultiWaitIntr since it is mainly for
+ *          ring-0 consumption.
+ */
+RTDECL(int)  RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies);
+
+/**
+ * Extended API for waiting on an event semaphore to be signaled.
+ *
+ * @returns IPRT status code.
+ * @param   hEventMultiSem      The multiple release event semaphore to wait
+ *                              on.
+ * @param   fFlags              Combination of the RTSEMWAIT_FLAGS_XXX.
+ * @param   uTimeout            The timeout, ignored if
+ *                              RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags.
+ *                              Whether this is absolute or relative,
+ *                              milliseconds or nanoseconds depends on the @a
+ *                              fFlags value.  Do not pass RT_INDEFINITE_WAIT
+ *                              here, use RTSEMWAIT_FLAGS_INDEFINITE instead.
+ */
+RTDECL(int)  RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout);
+
+/**
+ * Debug version of RTSemEventMultiWaitEx that tracks the location.
+
+ * @returns IPRT status code, see RTSemEventMultiWaitEx.
+ * @param   hEventMultiSem      The multiple release event semaphore handle.
+ * @param   fFlags              See RTSemEventMultiWaitEx.
+ * @param   uTimeout            See RTSemEventMultiWaitEx.
+ * @param   uId                 Some kind of locking location ID.  Typically a
+ *                              return address up the stack.  Optional (0).
+ * @param   SRC_POS             The source position where call is being made
+ *                              from.  Use RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(int)  RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
+                                        RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Gets the best timeout resolution that RTSemEventMultiWaitEx can do.
+ *
+ * @returns The resolution in nanoseconds.
+ */
+RTDECL(uint32_t) RTSemEventMultiGetResolution(void);
+
+/**
+ * Sets the signaller thread to one specific thread.
+ *
+ * This is only used for validating usage and deadlock detection.  When used
+ * after calls to RTSemEventAddSignaller, the specified thread will be the only
+ * signalling thread.
+ *
+ * @param   hEventMultiSem      The multiple release event semaphore.
+ * @param   hThread             The thread that will signal it.  Pass
+ *                              NIL_RTTHREAD to indicate that there is no
+ *                              special signalling thread.
+ */
+RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread);
+
+/**
+ * To add more signalling threads.
+ *
+ * First call RTSemEventSetSignaller then add further threads with this.
+ *
+ * @param   hEventMultiSem      The multiple release event semaphore.
+ * @param   hThread             The thread that will signal it. NIL_RTTHREAD is
+ *                              not accepted.
+ */
+RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread);
+
+/**
+ * To remove a signalling thread.
+ *
+ * Reverts work done by RTSemEventAddSignaller and RTSemEventSetSignaller.
+ *
+ * @param   hEventMultiSem      The multiple release event semaphore.
+ * @param   hThread             A previously added thread.
+ */
+RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread);
+
+/** @} */
+
+
+/** @defgroup grp_rt_sems_mutex     RTSemMutex - Mutex semaphores.
+ *
+ * Mutex semaphores protect a section of code or data to which access must be
+ * exclusive.  Only one thread can hold access to a critical section at one
+ * time.  See RTSemMutexCreate, RTSemMutexRequest and RTSemMutexRelease.
+ *
+ * @remarks These are less efficient than "fast mutexes" and "critical
+ *          sections", which IPRT implements as well; see @ref
+ *          grp_rt_sems_fast_mutex and @ref grp_rt_critsect .
+ *
+ * @{ */
+
+/**
+ * Create a mutex semaphore.
+ *
+ * @returns iprt status code.
+ * @param   phMutexSem      Where to store the mutex semaphore handle.
+ */
+RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX phMutexSem);
+
+/**
+ * Creates a read/write semaphore.
+ *
+ * @returns iprt status code.
+ * @param   phMutexSem          Where to store the handle to the newly created
+ *                              mutex semaphore.
+ * @param   fFlags              Flags, any combination of the
+ *                              RTSEMMUTEX_FLAGS_XXX \#defines.
+ * @param   hClass              The class (no reference consumed).  If NIL, no
+ *                              lock order validation will be performed on this
+ *                              lock.
+ * @param   uSubClass           The sub-class.  This is used to define lock
+ *                              order within a class.  RTLOCKVAL_SUB_CLASS_NONE
+ *                              is the recommended value here.
+ * @param   pszNameFmt          Name format string for the lock validator,
+ *                              optional (NULL).  Max length is 32 bytes.
+ * @param   ...                 Format string arguments.
+ */
+RTDECL(int) RTSemMutexCreateEx(PRTSEMMUTEX phMutexSem, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass,
+                               const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(5, 6);
+
+/** @name RTSemMutexCreateEx flags
+ * @{ */
+/** Disables lock validation. */
+#define RTSEMMUTEX_FLAGS_NO_LOCK_VAL    UINT32_C(0x00000001)
+/** @} */
+
+
+/**
+ * Destroy a mutex semaphore.
+ *
+ * @returns iprt status code.
+ * @param   hMutexSem           The mutex semaphore to destroy.  NIL is quietly
+ *                              ignored (VINF_SUCCESS).
+ */
+RTDECL(int)  RTSemMutexDestroy(RTSEMMUTEX hMutexSem);
+
+/**
+ * Changes the lock validator sub-class of the mutex semaphore.
+ *
+ * It is recommended to try make sure that nobody is using this semaphore while
+ * changing the value.
+ *
+ * @returns The old sub-class.  RTLOCKVAL_SUB_CLASS_INVALID is returns if the
+ *          lock validator isn't compiled in or either of the parameters are
+ *          invalid.
+ * @param   hMutexSem           The handle to the mutex semaphore.
+ * @param   uSubClass           The new sub-class value.
+ */
+RTDECL(uint32_t) RTSemMutexSetSubClass(RTSEMMUTEX hMutexSem, uint32_t uSubClass);
+
+/**
+ * Request ownership of a mutex semaphore, resume on interruption.
+ *
+ * This function will resume if the wait is interrupted by an async
+ * system event (like a unix signal) or similar.
+ *
+ * The same thread may request a mutex semaphore multiple times,
+ * a nested counter is kept to make sure it's released on the right
+ * RTSemMutexRelease() call.
+ *
+ * @returns iprt status code.
+ *          Will not return VERR_INTERRUPTED.
+ * @param   hMutexSem           The mutex semaphore to request ownership over.
+ * @param   cMillies            The number of milliseconds to wait.
+ */
+RTDECL(int)  RTSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies);
+
+/**
+ * Request ownership of a mutex semaphore, return on interruption.
+ *
+ * This function will not resume the wait if interrupted.
+ *
+ * The same thread may request a mutex semaphore multiple times,
+ * a nested counter is kept to make sure it's released on the right
+ * RTSemMutexRelease() call.
+ *
+ * @returns iprt status code.
+ * @param   hMutexSem           The mutex semaphore to request ownership over.
+ * @param   cMillies            The number of milliseconds to wait.
+ */
+RTDECL(int)  RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies);
+
+/**
+ * Debug version of RTSemMutexRequest that tracks the location.
+ *
+ * @returns iprt status code.
+ *          Will not return VERR_INTERRUPTED.
+ * @param   hMutexSem           The mutex semaphore to request ownership over.
+ * @param   cMillies            The number of milliseconds to wait.
+ * @param   uId                 Some kind of locking location ID.  Typically a
+ *                              return address up the stack.  Optional (0).
+ * @param   SRC_POS             The source position where call is being made
+ *                              from.  Use RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(int)  RTSemMutexRequestDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Debug version of RTSemMutexRequestNoResume that tracks the location.
+ *
+ * @returns iprt status code.
+ * @param   hMutexSem           The mutex semaphore to request ownership over.
+ * @param   cMillies            The number of milliseconds to wait.
+ * @param   uId                 Some kind of locking location ID.  Typically a
+ *                              return address up the stack.  Optional (0).
+ * @param   SRC_POS             The source position where call is being made
+ *                              from.  Use RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(int)  RTSemMutexRequestNoResumeDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Request ownership of a mutex semaphore, extended edition.
+ *
+ * The same thread may request a mutex semaphore multiple times,
+ * a nested counter is kept to make sure it's released on the right
+ * RTSemMutexRelease() call.
+ *
+ * @returns iprt status code.
+ * @param   hMutexSem           The mutex semaphore to request ownership over.
+ * @param   fFlags              Combination of the RTSEMWAIT_FLAGS_XXX.
+ * @param   uTimeout            The timeout, ignored if
+ *                              RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags.
+ *                              Whether this is absolute or relative,
+ *                              milliseconds or nanoseconds depends on the @a
+ *                              fFlags value.  Do not pass RT_INDEFINITE_WAIT
+ *                              here, use RTSEMWAIT_FLAGS_INDEFINITE instead.
+ */
+RTDECL(int)  RTSemMutexRequestEx(RTSEMMUTEX hMutexSem, uint32_t fFlags, uint64_t uTimeout);
+
+/**
+ * Debug version of RTSemMutexRequestEx that tracks the location.
+ *
+ * @returns iprt status code.
+ * @param   hMutexSem           The mutex semaphore to request ownership over.
+ * @param   fFlags              See RTSemMutexRequestEx.
+ * @param   uTimeout            See RTSemMutexRequestEx.
+ * @param   uId                 Some kind of locking location ID.  Typically a
+ *                              return address up the stack.  Optional (0).
+ * @param   SRC_POS             The source position where call is being made
+ *                              from.  Use RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(int)  RTSemMutexRequestExDebug(RTSEMMUTEX hMutexSem, uint32_t fFlags, uint64_t uTimeout,
+                                      RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Release the ownership of a mutex semaphore.
+ *
+ * @returns iprt status code.
+ * @param   hMutexSem           The mutex to release the ownership of.  It goes
+ *                              without saying the the calling thread must own
+ *                              it.
+ */
+RTDECL(int)  RTSemMutexRelease(RTSEMMUTEX hMutexSem);
+
+/**
+ * Checks if the mutex semaphore is owned or not.
+ *
+ * @returns true if owned, false if not.
+ * @param   hMutexSem           The mutex semaphore.
+ */
+RTDECL(bool) RTSemMutexIsOwned(RTSEMMUTEX hMutexSem);
+
+/* Strict build: Remap the two request calls to the debug versions. */
+#if   defined(RT_STRICT) && !defined(RTSEMMUTEX_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
+# ifdef ___iprt_asm_h
+#  define RTSemMutexRequest(hMutexSem, cMillies)            RTSemMutexRequestDebug((hMutexSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+#  define RTSemMutexRequestNoResume(hMutexSem, cMillies)    RTSemMutexRequestNoResumeDebug((hMutexSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+#  define RTSemMutexRequestEx(hMutexSem, fFlags, uTimeout)  RTSemMutexRequestExDebug((hMutexSem), (fFlags), (uTimeout), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# else
+#  define RTSemMutexRequest(hMutexSem, cMillies)            RTSemMutexRequestDebug((hMutexSem), (cMillies), 0, RT_SRC_POS)
+#  define RTSemMutexRequestNoResume(hMutexSem, cMillies)    RTSemMutexRequestNoResumeDebug((hMutexSem), (cMillies), 0, RT_SRC_POS)
+#  define RTSemMutexRequestEx(hMutexSem, fFlags, uTimeout)  RTSemMutexRequestExDebug((hMutexSem), (fFlags), (uTimeout), 0, RT_SRC_POS)
+# endif
+#endif
+
+/* Strict lock order: Automatically classify locks by init location. */
+#if   defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTSEMMUTEX_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
+# define RTSemMutexCreate(phMutexSem) \
+    RTSemMutexCreateEx((phMutexSem), 0 /*fFlags*/, \
+                       RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
+                       RTLOCKVAL_SUB_CLASS_NONE, NULL)
+#endif
+
+/** @} */
+
+
+/** @defgroup grp_rt_sems_fast_mutex    RTSemFastMutex - Fast Mutex Semaphores
+ *
+ * Fast mutexes work like regular mutexes in that they allow only a single
+ * thread access to a critical piece of code or data.  As opposed to mutexes,
+ * they require no syscall if the fast mutex is not held (like critical
+ * sections).  Unlike critical sections however, they are *not* recursive.
+ *
+ * @remarks The fast mutexes has sideeffects on IRQL on Windows hosts.  So use
+ *          with care and test on windows with driver verifier.
+ *
+ * @{ */
+
+/**
+ * Create a fast mutex semaphore.
+ *
+ * @returns iprt status code.
+ * @param   phFastMtx           Where to store the handle to the newly created
+ *                              fast mutex semaphore.
+ *
+ * @remarks Fast mutex semaphores are not recursive.
+ */
+RTDECL(int)  RTSemFastMutexCreate(PRTSEMFASTMUTEX phFastMtx);
+
+/**
+ * Destroy a fast mutex semaphore.
+ *
+ * @returns iprt status code.
+ * @param   hFastMtx            Handle to the fast mutex semaphore.  NIL is
+ *                              quietly ignored (VINF_SUCCESS).
+ */
+RTDECL(int)  RTSemFastMutexDestroy(RTSEMFASTMUTEX hFastMtx);
+
+/**
+ * Request ownership of a fast mutex semaphore.
+ *
+ * The same thread may request a mutex semaphore multiple times,
+ * a nested counter is kept to make sure it's released on the right
+ * RTSemMutexRelease() call.
+ *
+ * @returns iprt status code.
+ * @param   hFastMtx            Handle to the fast mutex semaphore.
+ */
+RTDECL(int)  RTSemFastMutexRequest(RTSEMFASTMUTEX hFastMtx);
+
+/**
+ * Release the ownership of a fast mutex semaphore.
+ *
+ * @returns iprt status code.
+ * @param   hFastMtx            Handle to the fast mutex semaphore.  It goes
+ *                              without saying the the calling thread must own
+ *                              it.
+ */
+RTDECL(int)  RTSemFastMutexRelease(RTSEMFASTMUTEX hFastMtx);
+
+/** @} */
+
+
+/** @defgroup grp_rt_sems_spin_mutex RTSemSpinMutex - Spinning Mutex Semaphores
+ *
+ * A very adaptive variant of mutex semaphore that is tailored for the ring-0
+ * logger.
+ *
+ * @{ */
+
+/**
+ * Creates a spinning mutex semaphore.
+ *
+ * @returns iprt status code.
+ * @retval  VERR_INVALID_PARAMETER on invalid flags.
+ * @retval  VERR_NO_MEMORY if out of memory for the semaphore structure and
+ *          handle.
+ *
+ * @param   phSpinMtx   Where to return the handle to the create semaphore.
+ * @param   fFlags      Flags, see RTSEMSPINMUTEX_FLAGS_XXX.
+ */
+RTDECL(int) RTSemSpinMutexCreate(PRTSEMSPINMUTEX phSpinMtx, uint32_t fFlags);
+
+/** @name RTSemSpinMutexCreate flags.
+ * @{ */
+/** Always take the semaphore in a IRQ safe way.
+ * (In plain words: always disable interrupts.) */
+#define RTSEMSPINMUTEX_FLAGS_IRQ_SAFE       RT_BIT_32(0)
+/** Mask of valid flags. */
+#define RTSEMSPINMUTEX_FLAGS_VALID_MASK     UINT32_C(0x00000001)
+/** @} */
+
+/**
+ * Destroys a spinning mutex semaphore.
+ *
+ * @returns iprt status code.
+ * @retval  VERR_INVALID_HANDLE (or crash) if the handle is invalid. (NIL will
+ *          not cause this status.)
+ *
+ * @param   hSpinMtx    The semaphore handle. NIL_RTSEMSPINMUTEX is ignored
+ *                      quietly (VINF_SUCCESS).
+ */
+RTDECL(int) RTSemSpinMutexDestroy(RTSEMSPINMUTEX hSpinMtx);
+
+/**
+ * Request the spinning mutex semaphore.
+ *
+ * This may block if the context we're called in allows this. If not it will
+ * spin. If called in an interrupt context, we will only spin if the current
+ * owner isn't interrupted. Also, on some systems it is not always possible to
+ * wake up blocking threads in all contexts, so, which will either be indicated
+ * by returning VERR_SEM_BAD_CONTEXT or by temporarily switching the semaphore
+ * into pure spinlock state.
+ *
+ * Preemption will be disabled upon return. IRQs may also be disabled.
+ *
+ * @returns iprt status code.
+ * @retval  VERR_SEM_BAD_CONTEXT if the context it's called in isn't suitable
+ *          for releasing it if someone is sleeping on it.
+ * @retval  VERR_SEM_DESTROYED if destroyed.
+ * @retval  VERR_SEM_NESTED if held by the caller. Asserted.
+ * @retval  VERR_INVALID_HANDLE if the handle is invalid. Asserted
+ *
+ * @param   hSpinMtx    The semaphore handle.
+ */
+RTDECL(int) RTSemSpinMutexRequest(RTSEMSPINMUTEX hSpinMtx);
+
+/**
+ * Like RTSemSpinMutexRequest but it won't block or spin if the semaphore is
+ * held by someone else.
+ *
+ * @returns iprt status code.
+ * @retval  VERR_SEM_BUSY if held by someone else.
+ * @retval  VERR_SEM_DESTROYED if destroyed.
+ * @retval  VERR_SEM_NESTED if held by the caller. Asserted.
+ * @retval  VERR_INVALID_HANDLE if the handle is invalid. Asserted
+ *
+ * @param   hSpinMtx    The semaphore handle.
+ */
+RTDECL(int) RTSemSpinMutexTryRequest(RTSEMSPINMUTEX hSpinMtx);
+
+/**
+ * Releases the semaphore previously acquired by RTSemSpinMutexRequest or
+ * RTSemSpinMutexTryRequest.
+ *
+ * @returns iprt status code.
+ * @retval  VERR_SEM_DESTROYED if destroyed.
+ * @retval  VERR_NOT_OWNER if not owner. Asserted.
+ * @retval  VERR_INVALID_HANDLE if the handle is invalid. Asserted.
+ *
+ * @param   hSpinMtx    The semaphore handle.
+ */
+RTDECL(int) RTSemSpinMutexRelease(RTSEMSPINMUTEX hSpinMtx);
+
+/** @} */
+
+
+/** @defgroup grp_rt_sem_rw             RTSemRW - Read / Write Semaphores
+ *
+ * Read/write semaphores are a fancier version of mutexes in that they grant
+ * read access to the protected data to several threads at the same time but
+ * allow only one writer at a time.  This can make code scale better at the
+ * expense of slightly more overhead in mutex management.
+ *
+ * @{ */
+
+/**
+ * Creates a read/write semaphore.
+ *
+ * @returns iprt status code.
+ * @param   phRWSem             Where to store the handle to the newly created
+ *                              RW semaphore.
+ */
+RTDECL(int)   RTSemRWCreate(PRTSEMRW phRWSem);
+
+/**
+ * Creates a read/write semaphore.
+ *
+ * @returns iprt status code.
+ * @param   phRWSem             Where to store the handle to the newly created
+ *                              RW semaphore.
+ * @param   fFlags              Flags, any combination of the RTSEMRW_FLAGS_XXX
+ *                              \#defines.
+ * @param   hClass              The class (no reference consumed).  If NIL, no
+ *                              lock order validation will be performed on this
+ *                              lock.
+ * @param   uSubClass           The sub-class.  This is used to define lock
+ *                              order within a class.  RTLOCKVAL_SUB_CLASS_NONE
+ *                              is the recommended value here.
+ * @param   pszNameFmt          Name format string for the lock validator,
+ *                              optional (NULL).  Max length is 32 bytes.
+ * @param   ...                 Format string arguments.
+ */
+RTDECL(int)   RTSemRWCreateEx(PRTSEMRW phRWSem, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass,
+                              const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(5, 6);
+
+/** @name RTSemRWCreateEx flags
+ * @{ */
+/** Disables lock validation. */
+#define RTSEMRW_FLAGS_NO_LOCK_VAL   UINT32_C(0x00000001)
+/** @} */
+
+/**
+ * Destroys a read/write semaphore.
+ *
+ * @returns iprt status code.
+ * @param   hRWSem              Handle to the read/write semaphore.  NIL is
+ *                              quietly ignored (VINF_SUCCESS).
+ */
+RTDECL(int)   RTSemRWDestroy(RTSEMRW hRWSem);
+
+/**
+ * Changes the lock validator sub-class of the read/write semaphore.
+ *
+ * It is recommended to try make sure that nobody is using this semaphore while
+ * changing the value.
+ *
+ * @returns The old sub-class.  RTLOCKVAL_SUB_CLASS_INVALID is returns if the
+ *          lock validator isn't compiled in or either of the parameters are
+ *          invalid.
+ * @param   hRWSem              Handle to the read/write semaphore.
+ * @param   uSubClass           The new sub-class value.
+ */
+RTDECL(uint32_t) RTSemRWSetSubClass(RTSEMRW hRWSem, uint32_t uSubClass);
+
+/**
+ * Request read access to a read/write semaphore, resume on interruption
+ *
+ * @returns iprt status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_INTERRUPT if the wait was interrupted.
+ * @retval  VERR_INVALID_HANDLE if hRWSem is invalid.
+ *
+ * @param   hRWSem              Handle to the read/write semaphore.
+ * @param   cMillies            The number of milliseconds to wait.
+ */
+RTDECL(int)   RTSemRWRequestRead(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
+
+/**
+ * Request read access to a read/write semaphore, return on interruption
+ *
+ * @returns iprt status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_INTERRUPT if the wait was interrupted.
+ * @retval  VERR_INVALID_HANDLE if hRWSem is invalid.
+ *
+ * @param   hRWSem              Handle to the read/write semaphore.
+ * @param   cMillies            The number of milliseconds to wait.
+ */
+RTDECL(int)   RTSemRWRequestReadNoResume(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
+
+/**
+ * Debug version of RTSemRWRequestRead that tracks the location.
+ *
+ * @returns iprt status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_INTERRUPT if the wait was interrupted.
+ * @retval  VERR_INVALID_HANDLE if hRWSem is invalid.
+ *
+ * @param   hRWSem              Handle to the read/write semaphore.
+ * @param   cMillies            The number of milliseconds to wait.
+ * @param   uId                 Some kind of locking location ID.  Typically a
+ *                              return address up the stack.  Optional (0).
+ * @param   SRC_POS             The source position where call is being made
+ *                              from.  Use RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(int)   RTSemRWRequestReadDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Debug version of RTSemRWRequestWriteNoResume that tracks the location.
+ *
+ * @returns iprt status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_INTERRUPT if the wait was interrupted.
+ * @retval  VERR_INVALID_HANDLE if hRWSem is invalid.
+ *
+ * @param   hRWSem              Handle to the read/write semaphore.
+ * @param   cMillies            The number of milliseconds to wait.
+ * @param   uId                 Some kind of locking location ID.  Typically a
+ *                              return address up the stack.  Optional (0).
+ * @param   SRC_POS             The source position where call is being made
+ *                              from.  Use RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(int)   RTSemRWRequestReadNoResumeDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Request read access to a read/write semaphore, extended edition.
+ *
+ * @returns iprt status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_INTERRUPT if the wait was interrupted.
+ * @retval  VERR_TIMEOUT if the wait timed out.
+ * @retval  VERR_INVALID_HANDLE if hRWSem is invalid.
+ *
+ * @param   hRWSem              Handle to the read/write semaphore.
+ * @param   fFlags              Combination of the RTSEMWAIT_FLAGS_XXX.
+ * @param   uTimeout            The timeout, ignored if
+ *                              RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags.
+ *                              Whether this is absolute or relative,
+ *                              milliseconds or nanoseconds depends on the @a
+ *                              fFlags value.  Do not pass RT_INDEFINITE_WAIT
+ *                              here, use RTSEMWAIT_FLAGS_INDEFINITE instead.
+ */
+RTDECL(int)   RTSemRWRequestReadEx(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout);
+
+
+/**
+ * Debug version of RTSemRWRequestReadEx that tracks the location.
+ *
+ * @returns iprt status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_INTERRUPT if the wait was interrupted.
+ * @retval  VERR_TIMEOUT if the wait timed out.
+ * @retval  VERR_INVALID_HANDLE if hRWSem is invalid.
+ *
+ * @param   hRWSem              Handle to the read/write semaphore.
+ * @param   fFlags              See RTSemRWRequestReadEx.
+ * @param   uTimeout            See RTSemRWRequestReadEx.
+ * @param   uId                 Some kind of locking location ID.  Typically a
+ *                              return address up the stack.  Optional (0).
+ * @param   SRC_POS             The source position where call is being made
+ *                              from.  Use RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(int)   RTSemRWRequestReadExDebug(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout,
+                                        RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Release read access to a read/write semaphore.
+ *
+ * @returns iprt status code.
+ * @param   hRWSem              Handle to the read/write semaphore.  It goes
+ *                              without saying that caller must own read
+ *                              privileges to the semaphore.
+ */
+RTDECL(int)   RTSemRWReleaseRead(RTSEMRW hRWSem);
+
+/**
+ * Request write access to a read/write semaphore, resume on interruption.
+ *
+ * @returns iprt status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_DEADLOCK if the caller owned the read lock.
+ * @retval  VERR_INVALID_HANDLE if hRWSem is invalid.
+ *
+ * @param   hRWSem              Handle to the read/write semaphore.
+ * @param   cMillies            The number of milliseconds to wait.
+ */
+RTDECL(int)   RTSemRWRequestWrite(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
+
+/**
+ * Request write access to a read/write semaphore, return on interruption.
+ *
+ * @returns iprt status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_INTERRUPT if the wait was interrupted.
+ * @retval  VERR_DEADLOCK if the caller owned the read lock.
+ * @retval  VERR_INVALID_HANDLE if hRWSem is invalid.
+ *
+ * @param   hRWSem              Handle to the read/write semaphore.
+ * @param   cMillies            The number of milliseconds to wait.
+ */
+RTDECL(int)   RTSemRWRequestWriteNoResume(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
+
+/**
+ * Debug version of RTSemRWRequestWrite that tracks the location.
+ *
+ * @returns IPRT status code, see RTSemRWRequestWrite.
+ * @param   hRWSem              Handle to the read/write semaphore.
+ * @param   cMillies            The number of milliseconds to wait.
+ * @param   uId                 Some kind of locking location ID.  Typically a
+ *                              return address up the stack.  Optional (0).
+ * @param   SRC_POS             The source position where call is being made
+ *                              from.  Use RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(int)  RTSemRWRequestWriteDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Debug version of RTSemRWRequestWriteNoResume that tracks the location.
+ *
+ * @returns IPRT status code, see RTSemRWRequestWriteNoResume.
+ * @param   hRWSem              Handle to the read/write semaphore.
+ * @param   cMillies            The number of milliseconds to wait.
+ * @param   uId                 Some kind of locking location ID.  Typically a
+ *                              return address up the stack.  Optional (0).
+ * @param   SRC_POS             The source position where call is being made
+ *                              from.  Use RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(int)  RTSemRWRequestWriteNoResumeDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Request write access to a read/write semaphore, extended edition.
+ *
+ * @returns iprt status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_INTERRUPTED if the wait was interrupted.
+ * @retval  VERR_TIMEOUT if the wait timed out.
+ * @retval  VERR_DEADLOCK if the caller owned the read lock.  Do not depend on
+ *          this as it is implementation specific.
+ * @retval  VERR_INVALID_HANDLE if hRWSem is invalid.
+ *
+ * @param   hRWSem              Handle to the read/write semaphore.
+ * @param   fFlags              Combination of the RTSEMWAIT_FLAGS_XXX.
+ * @param   uTimeout            The timeout, ignored if
+ *                              RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags.
+ *                              Whether this is absolute or relative,
+ *                              milliseconds or nanoseconds depends on the @a
+ *                              fFlags value.  Do not pass RT_INDEFINITE_WAIT
+ *                              here, use RTSEMWAIT_FLAGS_INDEFINITE instead.
+ */
+RTDECL(int)   RTSemRWRequestWriteEx(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout);
+
+/**
+ * Debug version of RTSemRWRequestWriteEx that tracks the location.
+ *
+ * @returns IPRT status code, see RTSemRWRequestWriteEx.
+ * @param   hRWSem              Handle to the read/write semaphore.
+ * @param   fFlags              See RTSemRWRequestWriteEx.
+ * @param   uTimeout            See RTSemRWRequestWriteEx.
+ * @param   uId                 Some kind of locking location ID.  Typically a
+ *                              return address up the stack.  Optional (0).
+ * @param   SRC_POS             The source position where call is being made
+ *                              from.  Use RT_SRC_POS when possible.  Optional.
+ */
+RTDECL(int)  RTSemRWRequestWriteExDebug(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout,
+                                        RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Release write access to a read/write semaphore.
+ *
+ * @returns iprt status code.
+ * @param   hRWSem              Handle to the read/write semaphore.  Goes
+ *                              without saying that caller must have write
+ *                              access to the semaphore.
+ */
+RTDECL(int)   RTSemRWReleaseWrite(RTSEMRW hRWSem);
+
+/**
+ * Checks if the caller is the exclusive semaphore owner.
+ *
+ * @returns true / false accoringly.
+ * @param   hRWSem              Handle to the read/write semaphore.
+ */
+RTDECL(bool)  RTSemRWIsWriteOwner(RTSEMRW hRWSem);
+
+/**
+ * Checks if the caller is one of the read owners of the semaphore.
+ *
+ * @note    !CAUTION!  This API doesn't work reliably if lock validation isn't
+ *          enabled. Meaning, the answer is not trustworhty unless
+ *          RT_LOCK_STRICT or RTSEMRW_STRICT was defined at build time.  Also,
+ *          make sure you do not use RTSEMRW_FLAGS_NO_LOCK_VAL when creating
+ *          the semaphore.  And finally, if you used a locking class, don't
+ *          disable deadlock detection by setting cMsMinDeadlock to
+ *          RT_INDEFINITE_WAIT.
+ *
+ *          In short, only use this for assertions.
+ *
+ * @returns true if reader, false if not.
+ * @param   hRWSem              Handle to the read/write semaphore.
+ * @param   fWannaHear          What you'd like to hear when lock validation is
+ *                              not available.  (For avoiding asserting all over
+ *                              the place.)
+ */
+RTDECL(bool)  RTSemRWIsReadOwner(RTSEMRW hRWSem, bool fWannaHear);
+
+/**
+ * Gets the write recursion count.
+ *
+ * @returns The write recursion count (0 if bad semaphore handle).
+ * @param   hRWSem              Handle to the read/write semaphore.
+ */
+RTDECL(uint32_t) RTSemRWGetWriteRecursion(RTSEMRW hRWSem);
+
+/**
+ * Gets the read recursion count of the current writer.
+ *
+ * @returns The read recursion count (0 if bad semaphore handle).
+ * @param   hRWSem              Handle to the read/write semaphore.
+ */
+RTDECL(uint32_t) RTSemRWGetWriterReadRecursion(RTSEMRW hRWSem);
+
+/**
+ * Gets the current number of reads.
+ *
+ * This includes all read recursions, so it might be higher than the number of
+ * read owners.  It does not include reads done by the current writer.
+ *
+ * @returns The read count (0 if bad semaphore handle).
+ * @param   hRWSem              Handle to the read/write semaphore.
+ */
+RTDECL(uint32_t) RTSemRWGetReadCount(RTSEMRW hRWSem);
+
+/* Strict build: Remap the four request calls to the debug versions. */
+#if defined(RT_STRICT) && !defined(RTSEMRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
+# ifdef ___iprt_asm_h
+#  define RTSemRWRequestRead(hRWSem, cMillies)              RTSemRWRequestReadDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+#  define RTSemRWRequestReadNoResume(hRWSem, cMillies)      RTSemRWRequestReadNoResumeDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+#  define RTSemRWRequestWrite(hRWSem, cMillies)             RTSemRWRequestWriteDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+#  define RTSemRWRequestWriteNoResume(hRWSem, cMillies)     RTSemRWRequestWriteNoResumeDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+#  define RTSemRWRequestWriteEx(hRWSem, fFlags, uTimeout)   RTSemRWRequestWriteExDebug((hRWSem), (fFlags), (uTimeout), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# else
+#  define RTSemRWRequestRead(hRWSem, cMillies)              RTSemRWRequestReadDebug((hRWSem), (cMillies), 0, RT_SRC_POS)
+#  define RTSemRWRequestReadNoResume(hRWSem, cMillies)      RTSemRWRequestReadNoResumeDebug((hRWSem), (cMillies), 0, RT_SRC_POS)
+#  define RTSemRWRequestWrite(hRWSem, cMillies)             RTSemRWRequestWriteDebug((hRWSem), (cMillies), 0, RT_SRC_POS)
+#  define RTSemRWRequestWriteNoResume(hRWSem, cMillies)     RTSemRWRequestWriteNoResumeDebug((hRWSem), (cMillies), 0, RT_SRC_POS)
+#  define RTSemRWRequestWriteEx(hRWSem, fFlags, uTimeout)   RTSemRWRequestWriteExDebug((hRWSem), (fFlags), (uTimeout), 0, RT_SRC_POS)
+# endif
+#endif
+
+/* Strict lock order: Automatically classify locks by init location. */
+#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTSEMRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
+# define RTSemRWCreate(phSemRW) \
+    RTSemRWCreateEx((phSemRW), 0 /*fFlags*/, \
+                    RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
+                    RTLOCKVAL_SUB_CLASS_NONE, NULL)
+#endif
+
+/** @} */
+
+
+/** @defgroup grp_rt_sems_pingpong      RTSemPingPong - Ping-Pong Construct
+ *
+ * Serialization of a two way communication.
+ *
+ * @{ */
+
+/**
+ * Ping-pong speaker
+ */
+typedef enum RTPINGPONGSPEAKER
+{
+    /** Not initialized. */
+    RTPINGPONGSPEAKER_UNINITIALIZE = 0,
+    /** Ping is speaking, Pong is waiting. */
+    RTPINGPONGSPEAKER_PING,
+    /** Pong is signaled, Ping is waiting. */
+    RTPINGPONGSPEAKER_PONG_SIGNALED,
+    /** Pong is speaking, Ping is waiting. */
+    RTPINGPONGSPEAKER_PONG,
+    /** Ping is signaled, Pong is waiting. */
+    RTPINGPONGSPEAKER_PING_SIGNALED,
+    /** Hack to ensure that it's at least 32-bits wide. */
+    RTPINGPONGSPEAKER_HACK = 0x7fffffff
+} RTPINGPONGSPEAKER;
+
+/**
+ * Ping-Pong construct.
+ *
+ * Two threads, one saying Ping and the other saying Pong. The construct
+ * makes sure they don't speak out of turn and that they can wait and poll
+ * on the conversation.
+ */
+typedef struct RTPINGPONG
+{
+    /** The semaphore the Ping thread waits on. */
+    RTSEMEVENT                  Ping;
+    /** The semaphore the Pong thread waits on. */
+    RTSEMEVENT                  Pong;
+    /** The current speaker. */
+    volatile RTPINGPONGSPEAKER  enmSpeaker;
+#if HC_ARCH_BITS == 64
+    /** Padding the structure to become a multiple of sizeof(RTHCPTR). */
+    uint32_t                    u32Padding;
+#endif
+} RTPINGPONG;
+/** Pointer to Ping-Pong construct. */
+typedef RTPINGPONG *PRTPINGPONG;
+
+/**
+ * Init a Ping-Pong construct.
+ *
+ * @returns iprt status code.
+ * @param   pPP         Pointer to the ping-pong structure which needs initialization.
+ */
+RTDECL(int) RTSemPingPongInit(PRTPINGPONG pPP);
+
+/**
+ * Deletes a Ping-Pong construct.
+ *
+ * @returns iprt status code.
+ * @param   pPP         Pointer to the ping-pong structure which is to be destroyed.
+ *                      (I.e. put into uninitialized state.)
+ */
+RTDECL(int) RTSemPingPongDelete(PRTPINGPONG pPP);
+
+/**
+ * Signals the pong thread in a ping-pong construct. (I.e. sends ping.)
+ * This is called by the ping thread.
+ *
+ * @returns iprt status code.
+ * @param   pPP         Pointer to the ping-pong structure to ping.
+ */
+RTDECL(int) RTSemPing(PRTPINGPONG pPP);
+
+/**
+ * Signals the ping thread in a ping-pong construct. (I.e. sends pong.)
+ * This is called by the pong thread.
+ *
+ * @returns iprt status code.
+ * @param   pPP         Pointer to the ping-pong structure to pong.
+ */
+RTDECL(int) RTSemPong(PRTPINGPONG pPP);
+
+/**
+ * Wait function for the ping thread.
+ *
+ * @returns iprt status code.
+ *          Will not return VERR_INTERRUPTED.
+ * @param   pPP         Pointer to the ping-pong structure to wait on.
+ * @param   cMillies    Number of milliseconds to wait.
+ */
+RTDECL(int) RTSemPingWait(PRTPINGPONG pPP, RTMSINTERVAL cMillies);
+
+/**
+ * Wait function for the pong thread.
+ *
+ * @returns iprt status code.
+ *          Will not return VERR_INTERRUPTED.
+ * @param   pPP         Pointer to the ping-pong structure to wait on.
+ * @param   cMillies    Number of milliseconds to wait.
+ */
+RTDECL(int) RTSemPongWait(PRTPINGPONG pPP, RTMSINTERVAL cMillies);
+
+
+/**
+ * Checks if the pong thread is speaking.
+ *
+ * @returns true / false.
+ * @param   pPP         Pointer to the ping-pong structure.
+ * @remark  This is NOT the same as !RTSemPongIsSpeaker().
+ */
+DECLINLINE(bool) RTSemPingIsSpeaker(PRTPINGPONG pPP)
+{
+    RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
+    return enmSpeaker == RTPINGPONGSPEAKER_PING;
+}
+
+
+/**
+ * Checks if the pong thread is speaking.
+ *
+ * @returns true / false.
+ * @param   pPP         Pointer to the ping-pong structure.
+ * @remark  This is NOT the same as !RTSemPingIsSpeaker().
+ */
+DECLINLINE(bool) RTSemPongIsSpeaker(PRTPINGPONG pPP)
+{
+    RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
+    return enmSpeaker == RTPINGPONGSPEAKER_PONG;
+}
+
+
+/**
+ * Checks whether the ping thread should wait.
+ *
+ * @returns true / false.
+ * @param   pPP         Pointer to the ping-pong structure.
+ * @remark  This is NOT the same as !RTSemPongShouldWait().
+ */
+DECLINLINE(bool) RTSemPingShouldWait(PRTPINGPONG pPP)
+{
+    RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
+    return enmSpeaker == RTPINGPONGSPEAKER_PONG
+        || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED
+        || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED;
+}
+
+
+/**
+ * Checks whether the pong thread should wait.
+ *
+ * @returns true / false.
+ * @param   pPP         Pointer to the ping-pong structure.
+ * @remark  This is NOT the same as !RTSemPingShouldWait().
+ */
+DECLINLINE(bool) RTSemPongShouldWait(PRTPINGPONG pPP)
+{
+    RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
+    return enmSpeaker == RTPINGPONGSPEAKER_PING
+        || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED
+        || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED;
+}
+
+/** @} */
+
+
+/** @defgroup grp_rt_sems_xroads    RTSemXRoads - Crossroads
+ *
+ * The crossroads semaphore is intended to prevent two classes of incompatible
+ * events from occurring simultaneously, like south/north bound traffic and
+ * west/east bound traffic at a 4-way junction.
+ *
+ * @remarks In order to simplify the implementation, the current flow is always
+ *          given priority.  So, it won't work at all well when busy!
+ *
+ * @remarks "XRoads" is used as a name because it is briefer than "crossroads"
+ *          and it slightly stresses that is a 4 way crossing to the users of
+ *          American English.
+ * @{
+ */
+
+/**
+ * Creates a crossroads semaphore.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   phXRoads            Where to return the handle to the newly created
+ *                              crossroads semaphore.
+ */
+RTDECL(int) RTSemXRoadsCreate(PRTSEMXROADS phXRoads);
+
+/**
+ * Destroys a crossroads semaphore.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   hXRoads             Handle to the crossroads semaphore that is to be
+ *                              destroyed.  NIL_RTSEMXROADS is quitetly ignored
+ *                              (VINF_SUCCESS).
+ */
+RTDECL(int) RTSemXRoadsDestroy(RTSEMXROADS hXRoads);
+
+/**
+ * Enter the crossroads from the south or north.
+ *
+ * (Coupled with RTSemXRoadsNSLeave.)
+ *
+ * @returns IPRT status code.
+ * @param   hXRoads             Handle to the crossroads semaphore.
+ */
+RTDECL(int) RTSemXRoadsNSEnter(RTSEMXROADS hXRoads);
+
+/**
+ * Leave the crossroads to the north or south.
+ *
+ * (Coupled with RTSemXRoadsNSEnter.)
+ *
+ * @returns IPRT status code.
+ * @param   hXRoads             Handle to the crossroads semaphore.
+ */
+RTDECL(int) RTSemXRoadsNSLeave(RTSEMXROADS hXRoads);
+
+/**
+ * Leave the crossroads from the east or west.
+ *
+ * (Coupled with RTSemXRoadsEWLeave.)
+ *
+ * @returns IPRT status code.
+ * @param   hXRoads             Handle to the crossroads semaphore.
+ */
+RTDECL(int) RTSemXRoadsEWEnter(RTSEMXROADS hXRoads);
+
+/**
+ * Leave the crossroads to the west or east.
+ *
+ * (Coupled with RTSemXRoadsEWEnter.)
+ *
+ * @returns IPRT status code.
+ * @param   hXRoads             Handle to the crossroads semaphore.
+ */
+RTDECL(int) RTSemXRoadsEWLeave(RTSEMXROADS hXRoads);
+
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/spinlock.h b/ubuntu/vbox/include/iprt/spinlock.h
new file mode 100644 (file)
index 0000000..56ddbe4
--- /dev/null
@@ -0,0 +1,92 @@
+/** @file
+ * IPRT - Spinlocks.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_spinlock_h
+#define ___iprt_spinlock_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup grp_rt_spinlock   RTSpinlock - Spinlocks
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Creates a spinlock.
+ *
+ * @returns iprt status code.
+ * @param   pSpinlock   Where to store the spinlock handle.
+ * @param   fFlags      Creation flags, see RTSPINLOCK_FLAGS_XXX.
+ * @param   pszName     Spinlock name, for debugging purposes.  String lifetime
+ *                      must be the same as the lock as it won't be copied.
+ */
+RTDECL(int)  RTSpinlockCreate(PRTSPINLOCK pSpinlock, uint32_t fFlags, const char *pszName);
+
+/** @name RTSPINLOCK_FLAGS_XXX
+ * @{ */
+/** Disable interrupts when taking the spinlock, making it interrupt safe
+ * (sans NMI of course).
+ *
+ * This is generally the safest option, though it isn't really required unless
+ * the data being protect is also accessed from interrupt handler context. */
+#define RTSPINLOCK_FLAGS_INTERRUPT_SAFE     RT_BIT(1)
+/** No need to disable interrupts, the protect code/data is not used by
+ * interrupt handlers. */
+#define RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE   RT_BIT(2)
+/** @}  */
+
+/**
+ * Destroys a spinlock created by RTSpinlockCreate().
+ *
+ * @returns iprt status code.
+ * @param   Spinlock    Spinlock returned by RTSpinlockCreate().
+ */
+RTDECL(int)  RTSpinlockDestroy(RTSPINLOCK Spinlock);
+
+/**
+ * Acquires the spinlock.
+ *
+ * @param   Spinlock    The spinlock to acquire.
+ */
+RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock);
+
+/**
+ * Releases the spinlock.
+ *
+ * @param   Spinlock    The spinlock to acquire.
+ */
+RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock);
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/stdarg.h b/ubuntu/vbox/include/iprt/stdarg.h
new file mode 100644 (file)
index 0000000..612ef21
--- /dev/null
@@ -0,0 +1,56 @@
+/** @file
+ * IPRT - stdarg.h wrapper.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_stdarg_h
+#define ___iprt_stdarg_h
+
+#ifdef IPRT_NO_CRT
+# include <iprt/types.h>
+# include <iprt/nocrt/compiler/compiler.h>
+#else
+# include <iprt/cdefs.h>
+# if defined(RT_OS_FREEBSD) && defined(_KERNEL)
+#  include <machine/stdarg.h>
+# elif defined(RT_OS_NETBSD) && defined(_KERNEL)
+#  include <sys/stdarg.h>
+# elif defined(RT_OS_SOLARIS) && defined(_KERNEL) && defined(__GNUC__)
+#  include <stdarg.h>
+#  if __GNUC__ >= 4 /* System headers refers to __builtin_stdarg_start. */
+#   define __builtin_stdarg_start __builtin_va_start
+#  endif
+# else
+#  include <stdarg.h>
+# endif
+#endif
+
+/*
+ * MSC doesn't implement va_copy.
+ */
+#ifndef va_copy
+# define va_copy(dst, src) do { (dst) = (src); } while (0) /** @todo check AMD64 */
+#endif
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/stdint.h b/ubuntu/vbox/include/iprt/stdint.h
new file mode 100644 (file)
index 0000000..5d267d7
--- /dev/null
@@ -0,0 +1,284 @@
+/** @file
+ * IPRT - stdint.h wrapper (for backlevel compilers like MSC).
+ */
+
+/*
+ * Copyright (C) 2009-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.
+ */
+
+#ifndef __iprt_stdint_h
+#define __iprt_stdint_h
+
+#include <iprt/cdefs.h>
+
+
+/*
+ * Use the stdint.h on systems that have one.
+ */
+#if !(defined(RT_OS_LINUX) && defined(__KERNEL__))  \
+  && !(defined(RT_OS_FREEBSD) && defined(_KERNEL)) \
+  && !(defined(RT_OS_NETBSD) && defined(_KERNEL)) \
+  && RT_MSC_PREREQ_EX(RT_MSC_VER_VS2010, 1 /*non-msc*/) \
+  && !defined(__IBMC__) \
+  && !defined(__IBMCPP__) \
+  && !defined(IPRT_NO_CRT) \
+  && !defined(IPRT_DONT_USE_SYSTEM_STDINT_H) \
+  && !defined(DOXYGEN_RUNNING)
+
+# ifndef __STDC_CONSTANT_MACROS
+#  define __STDC_CONSTANT_MACROS
+# endif
+# ifndef __STDC_LIMIT_MACROS
+#  define __STDC_LIMIT_MACROS
+# endif
+# ifdef _MSC_VER
+#  pragma warning(push)
+#  pragma warning(disable:4668)
+# endif
+# include <stdint.h>
+# ifdef _MSC_VER
+#  pragma warning(pop)
+# endif
+
+# if defined(RT_OS_DARWIN) && defined(KERNEL) && defined(RT_ARCH_AMD64)
+ /*
+  * Kludge to fix the incorrect 32-bit constant macros in
+  * Kernel.framework/Headers/stdin.h. uint32_t and int32_t are
+  * int not long as these macros use, which is significant when
+  * targeting AMD64. (10a222)
+  */
+#  undef  INT32_C
+#  define INT32_C(Value)    (Value)
+#  undef  UINT32_C
+#  define UINT32_C(Value)   (Value ## U)
+# endif /* 64-bit darwin kludge. */
+
+#elif defined(RT_OS_FREEBSD) && defined(_KERNEL)
+
+# ifndef __STDC_CONSTANT_MACROS
+#  define __STDC_CONSTANT_MACROS
+# endif
+# ifndef __STDC_LIMIT_MACROS
+#  define __STDC_LIMIT_MACROS
+# endif
+# include <sys/stdint.h>
+
+#elif defined(RT_OS_NETBSD) && defined(_KERNEL)
+
+# ifndef __STDC_CONSTANT_MACROS
+#  define __STDC_CONSTANT_MACROS
+# endif
+# ifndef __STDC_LIMIT_MACROS
+#  define __STDC_LIMIT_MACROS
+# endif
+# include <sys/stdint.h>
+
+#else /* No system stdint.h */
+
+/*
+ * Define the types we use.
+ * The linux kernel defines all these in linux/types.h, so skip it.
+ */
+# if !(defined(RT_OS_LINUX) && defined(__KERNEL__)) \
+  || defined(IPRT_NO_CRT) \
+  || defined(IPRT_DONT_USE_SYSTEM_STDINT_H) \
+  || defined(DOXGEN_RUNNING)
+
+    /* Simplify the [u]int64_t type detection mess. */
+# undef IPRT_STDINT_USE_STRUCT_FOR_64_BIT_TYPES
+# ifdef __IBMCPP__
+#  if __IBMCPP__ < 350 && (defined(__WINDOWS__) || defined(_AIX) || defined(__OS2__))
+#   define IPRT_STDINT_USE_STRUCT_FOR_64_BIT_TYPES
+#  endif
+# endif
+# ifdef __IBMC__
+#  if __IBMC__   < 350 && (defined(__WINDOWS__) || defined(_AIX) || defined(__OS2__))
+#   define IPRT_STDINT_USE_STRUCT_FOR_64_BIT_TYPES
+#  endif
+# endif
+
+    /* x-bit types */
+#  if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) || defined(RT_ARCH_SPARC) || defined(RT_ARCH_SPARC64)
+#   if !defined(_INT8_T_DECLARED)   && !defined(_INT8_T)
+typedef signed char         int8_t;
+#   endif
+#   if !defined(_UINT8_T_DECLARED)  && !defined(_UINT8_T)
+typedef unsigned char       uint8_t;
+#   endif
+#   if !defined(_INT16_T_DECLARED)  && !defined(_INT16_T)
+typedef signed short        int16_t;
+#   endif
+#   if !defined(_UINT16_T_DECLARED) && !defined(_UINT16_T)
+typedef unsigned short      uint16_t;
+#   endif
+#   if !defined(_INT32_T_DECLARED)  && !defined(_INT32_T)
+#    if ARCH_BITS != 16
+typedef signed int          int32_t;
+#    else
+typedef signed long         int32_t;
+#    endif
+#   endif
+#   if !defined(_UINT32_T_DECLARED) && !defined(_UINT32_T)
+#    if ARCH_BITS != 16
+typedef unsigned int        uint32_t;
+#    else
+typedef unsigned long       uint32_t;
+#    endif
+#   endif
+#   if defined(_MSC_VER)
+#    if !defined(_INT64_T_DECLARED)  && !defined(_INT64_T)
+typedef signed _int64       int64_t;
+#    endif
+#    if !defined(_UINT64_T_DECLARED) && !defined(_UINT64_T)
+typedef unsigned _int64     uint64_t;
+#    endif
+#   elif defined(__WATCOMC__)
+#    if !defined(_INT64_T_DECLARED)  && !defined(_INT64_T)
+typedef signed __int64      int64_t;
+#    endif
+#    if !defined(_UINT64_T_DECLARED) && !defined(_UINT64_T)
+typedef unsigned __int64    uint64_t;
+#    endif
+#   elif defined(IPRT_STDINT_USE_STRUCT_FOR_64_BIT_TYPES)
+#    if !defined(_INT64_T_DECLARED)  && !defined(_INT64_T)
+typedef struct { uint32_t lo; int32_t hi; }     int64_t;
+#    endif
+#    if !defined(_UINT64_T_DECLARED) && !defined(_UINT64_T)
+typedef struct { uint32_t lo; uint32_t hi; }    uint64_t;
+#    endif
+#   else /* Use long long for 64-bit types */
+#    if !defined(_INT64_T_DECLARED)  && !defined(_INT64_T)
+typedef signed long long    int64_t;
+#    endif
+#    if !defined(_UINT64_T_DECLARED) && !defined(_UINT64_T)
+typedef unsigned long long  uint64_t;
+#    endif
+#   endif
+
+    /* max integer types */
+#   if !defined(_INTMAX_T_DECLARED)  && !defined(_INTMAX_T)
+typedef int64_t             intmax_t;
+#   endif
+#   if !defined(_UINTMAX_T_DECLARED) && !defined(_UINTMAX_T)
+typedef uint64_t            uintmax_t;
+#   endif
+
+#  else
+#   error "PORTME: Add architecture. Don't forget to check the [U]INTx_C() and [U]INTMAX_MIN/MAX macros."
+#  endif
+
+# endif /* !linux kernel or stuff */
+
+    /* pointer <-> integer types */
+# if !defined(_MSC_VER) || defined(DOXYGEN_RUNNING)
+#  if ARCH_BITS == 32 \
+   || defined(RT_OS_LINUX) \
+   || defined(RT_OS_FREEBSD)
+#   if !defined(_INTPTR_T_DECLARED)  && !defined(_INTPTR_T)
+typedef signed long         intptr_t;
+#   endif
+#   if !defined(_UINTPTR_T_DECLARED) && !defined(_UINTPTR_T)
+typedef unsigned long       uintptr_t;
+#   endif
+#  else
+#   if !defined(_INTPTR_T_DECLARED)  && !defined(_INTPTR_T)
+typedef int64_t             intptr_t;
+#   endif
+#   if !defined(_UINTPTR_T_DECLARED) && !defined(_UINTPTR_T)
+typedef uint64_t            uintptr_t;
+#   endif
+#  endif
+# endif /* !_MSC_VER */
+
+#endif /* no system stdint.h */
+
+
+/*
+ * Make sure the [U]INTx_C(c) macros are present.
+ * For In C++ source the system stdint.h may have skipped these if it was
+ * included before we managed to define __STDC_CONSTANT_MACROS. (Kludge alert!)
+ */
+#if !defined(INT8_C) \
+ || !defined(INT16_C) \
+ || !defined(INT32_C) \
+ || !defined(INT64_C) \
+ || !defined(INTMAX_C) \
+ || !defined(UINT8_C) \
+ || !defined(UINT16_C) \
+ || !defined(UINT32_C) \
+ || !defined(UINT64_C) \
+ || !defined(UINTMAX_C)
+# define INT8_C(Value)      (Value)
+# define INT16_C(Value)     (Value)
+# define UINT8_C(Value)     (Value)
+# define UINT16_C(Value)    (Value)
+# if ARCH_BITS != 16
+#  define INT32_C(Value)    (Value)
+#  define UINT32_C(Value)   (Value ## U)
+#  define INT64_C(Value)    (Value ## LL)
+#  define UINT64_C(Value)   (Value ## ULL)
+# else
+#  define INT32_C(Value)    (Value ## L)
+#  define UINT32_C(Value)   (Value ## UL)
+#  define INT64_C(Value)    (Value ## LL)
+#  define UINT64_C(Value)   (Value ## ULL)
+# endif
+# define INTMAX_C(Value)    INT64_C(Value)
+# define UINTMAX_C(Value)   UINT64_C(Value)
+#endif
+
+
+/*
+ * Make sure the INTx_MIN and [U]INTx_MAX macros are present.
+ * For In C++ source the system stdint.h may have skipped these if it was
+ * included before we managed to define __STDC_LIMIT_MACROS. (Kludge alert!)
+ */
+#if !defined(INT8_MIN) \
+ || !defined(INT16_MIN) \
+ || !defined(INT32_MIN) \
+ || !defined(INT64_MIN) \
+ || !defined(INT8_MAX) \
+ || !defined(INT16_MAX) \
+ || !defined(INT32_MAX) \
+ || !defined(INT64_MAX) \
+ || !defined(UINT8_MAX) \
+ || !defined(UINT16_MAX) \
+ || !defined(UINT32_MAX) \
+ || !defined(UINT64_MAX)
+# 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)
+
+# define INTMAX_MIN         INT64_MIN
+# define INTMAX_MAX         INT64_MAX
+# define UINTMAX_MAX        UINT64_MAX
+#endif
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/string.h b/ubuntu/vbox/include/iprt/string.h
new file mode 100644 (file)
index 0000000..e14b803
--- /dev/null
@@ -0,0 +1,3082 @@
+/** @file
+ * IPRT - String Manipulation.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_string_h
+#define ___iprt_string_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/assert.h>
+#include <iprt/stdarg.h>
+#include <iprt/err.h> /* for VINF_SUCCESS */
+#if defined(RT_OS_LINUX) && defined(__KERNEL__)
+  /* no C++ hacks ('new' etc) here anymore! */
+# include <linux/string.h>
+
+#elif defined(IN_XF86_MODULE) && !defined(NO_ANSIC)
+  RT_C_DECLS_BEGIN
+# include "xf86_ansic.h"
+  RT_C_DECLS_END
+
+#elif defined(RT_OS_FREEBSD) && defined(_KERNEL)
+  RT_C_DECLS_BEGIN
+# include <sys/libkern.h>
+  RT_C_DECLS_END
+
+#elif defined(RT_OS_NETBSD) && defined(_KERNEL)
+  RT_C_DECLS_BEGIN
+# include <lib/libkern/libkern.h>
+  RT_C_DECLS_END
+
+#elif defined(RT_OS_SOLARIS) && defined(_KERNEL)
+  /*
+   * Same case as with FreeBSD kernel:
+   * The string.h stuff clashes with sys/system.h
+   * ffs = find first set bit.
+   */
+# define ffs ffs_string_h
+# include <string.h>
+# undef ffs
+# undef strpbrk
+
+#else
+# include <string.h>
+#endif
+
+/* For the time being: */
+#include <iprt/utf16.h>
+#include <iprt/latin1.h>
+
+/*
+ * Supply prototypes for standard string functions provided by
+ * IPRT instead of the operating environment.
+ */
+#if defined(RT_OS_DARWIN) && defined(KERNEL)
+RT_C_DECLS_BEGIN
+void *memchr(const void *pv, int ch, size_t cb);
+char *strpbrk(const char *pszStr, const char *pszChars);
+RT_C_DECLS_END
+#endif
+
+#if defined(RT_OS_FREEBSD) && defined(_KERNEL)
+RT_C_DECLS_BEGIN
+char *strpbrk(const char *pszStr, const char *pszChars);
+RT_C_DECLS_END
+#endif
+
+#if defined(RT_OS_NETBSD) && defined(_KERNEL)
+RT_C_DECLS_BEGIN
+char *strpbrk(const char *pszStr, const char *pszChars);
+RT_C_DECLS_END
+#endif
+
+#if (!defined(RT_OS_LINUX) || !defined(_GNU_SOURCE)) && !defined(RT_OS_FREEBSD) && !defined(RT_OS_NETBSD)
+RT_C_DECLS_BEGIN
+void *memrchr(const char *pv, int ch, size_t cb);
+RT_C_DECLS_END
+#endif
+
+
+/** @def RT_USE_RTC_3629
+ * When defined the UTF-8 range will stop at  0x10ffff.  If not defined, the
+ * range stops at 0x7fffffff.
+ * @remarks Must be defined both when building and using the IPRT.  */
+#ifdef DOXYGEN_RUNNING
+# define RT_USE_RTC_3629
+#endif
+
+
+/**
+ * Byte zero the specified object.
+ *
+ * This will use sizeof(Obj) to figure the size and will call memset, bzero
+ * or some compiler intrinsic to perform the actual zeroing.
+ *
+ * @param   Obj     The object to zero. Make sure to dereference pointers.
+ *
+ * @remarks Because the macro may use memset it has been placed in string.h
+ *          instead of cdefs.h to avoid build issues because someone forgot
+ *          to include this header.
+ *
+ * @ingroup grp_rt_cdefs
+ */
+#define RT_ZERO(Obj)        RT_BZERO(&(Obj), sizeof(Obj))
+
+/**
+ * Byte zero the specified memory area.
+ *
+ * This will call memset, bzero or some compiler intrinsic to clear the
+ * specified bytes of memory.
+ *
+ * @param   pv          Pointer to the memory.
+ * @param   cb          The number of bytes to clear. Please, don't pass 0.
+ *
+ * @remarks Because the macro may use memset it has been placed in string.h
+ *          instead of cdefs.h to avoid build issues because someone forgot
+ *          to include this header.
+ *
+ * @ingroup grp_rt_cdefs
+ */
+#define RT_BZERO(pv, cb)    do { memset((pv), 0, cb); } while (0)
+
+
+
+/** @defgroup grp_rt_str    RTStr - String Manipulation
+ * Mostly UTF-8 related helpers where the standard string functions won't do.
+ * @ingroup grp_rt
+ * @{
+ */
+
+RT_C_DECLS_BEGIN
+
+
+/**
+ * The maximum string length.
+ */
+#define RTSTR_MAX       (~(size_t)0)
+
+
+/** @def RTSTR_TAG
+ * The default allocation tag used by the RTStr allocation APIs.
+ *
+ * When not defined before the inclusion of iprt/string.h, this will default to
+ * the pointer to the current file name.  The string API will make of use of
+ * this as pointer to a volatile but read-only string.
+ */
+#if !defined(RTSTR_TAG) || defined(DOXYGEN_RUNNING)
+# define RTSTR_TAG      (__FILE__)
+#endif
+
+
+#ifdef IN_RING3
+
+/**
+ * Allocates tmp buffer with default tag, translates pszString from UTF8 to
+ * current codepage.
+ *
+ * @returns iprt status code.
+ * @param   ppszString      Receives pointer of allocated native CP string.
+ *                          The returned pointer must be freed using RTStrFree().
+ * @param   pszString       UTF-8 string to convert.
+ */
+#define RTStrUtf8ToCurrentCP(ppszString, pszString)     RTStrUtf8ToCurrentCPTag((ppszString), (pszString), RTSTR_TAG)
+
+/**
+ * Allocates tmp buffer with custom tag, translates pszString from UTF8 to
+ * current codepage.
+ *
+ * @returns iprt status code.
+ * @param   ppszString      Receives pointer of allocated native CP string.
+ *                          The returned pointer must be freed using
+ *                          RTStrFree()., const char *pszTag
+ * @param   pszString       UTF-8 string to convert.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTR3DECL(int)  RTStrUtf8ToCurrentCPTag(char **ppszString, const char *pszString, const char *pszTag);
+
+/**
+ * Allocates tmp buffer, translates pszString from current codepage to UTF-8.
+ *
+ * @returns iprt status code.
+ * @param   ppszString      Receives pointer of allocated UTF-8 string.
+ *                          The returned pointer must be freed using RTStrFree().
+ * @param   pszString       Native string to convert.
+ */
+#define RTStrCurrentCPToUtf8(ppszString, pszString)     RTStrCurrentCPToUtf8Tag((ppszString), (pszString), RTSTR_TAG)
+
+/**
+ * Allocates tmp buffer, translates pszString from current codepage to UTF-8.
+ *
+ * @returns iprt status code.
+ * @param   ppszString      Receives pointer of allocated UTF-8 string.
+ *                          The returned pointer must be freed using RTStrFree().
+ * @param   pszString       Native string to convert.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTR3DECL(int)  RTStrCurrentCPToUtf8Tag(char **ppszString, const char *pszString, const char *pszTag);
+
+#endif /* IN_RING3 */
+
+/**
+ * Free string allocated by any of the non-UCS-2 string functions.
+ *
+ * @returns iprt status code.
+ * @param   pszString      Pointer to buffer with string to free.
+ *                         NULL is accepted.
+ */
+RTDECL(void)  RTStrFree(char *pszString);
+
+/**
+ * Allocates a new copy of the given UTF-8 string (default tag).
+ *
+ * @returns Pointer to the allocated UTF-8 string.
+ * @param   pszString       UTF-8 string to duplicate.
+ */
+#define RTStrDup(pszString)             RTStrDupTag((pszString), RTSTR_TAG)
+
+/**
+ * Allocates a new copy of the given UTF-8 string (custom tag).
+ *
+ * @returns Pointer to the allocated UTF-8 string.
+ * @param   pszString       UTF-8 string to duplicate.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTDECL(char *) RTStrDupTag(const char *pszString, const char *pszTag);
+
+/**
+ * Allocates a new copy of the given UTF-8 string (default tag).
+ *
+ * @returns iprt status code.
+ * @param   ppszString      Receives pointer of the allocated UTF-8 string.
+ *                          The returned pointer must be freed using RTStrFree().
+ * @param   pszString       UTF-8 string to duplicate.
+ */
+#define RTStrDupEx(ppszString, pszString)   RTStrDupExTag((ppszString), (pszString), RTSTR_TAG)
+
+/**
+ * Allocates a new copy of the given UTF-8 string (custom tag).
+ *
+ * @returns iprt status code.
+ * @param   ppszString      Receives pointer of the allocated UTF-8 string.
+ *                          The returned pointer must be freed using RTStrFree().
+ * @param   pszString       UTF-8 string to duplicate.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTDECL(int)  RTStrDupExTag(char **ppszString, const char *pszString, const char *pszTag);
+
+/**
+ * Allocates a new copy of the given UTF-8 substring (default tag).
+ *
+ * @returns Pointer to the allocated UTF-8 substring.
+ * @param   pszString       UTF-8 string to duplicate.
+ * @param   cchMax          The max number of chars to duplicate, not counting
+ *                          the terminator.
+ */
+#define RTStrDupN(pszString, cchMax)        RTStrDupNTag((pszString), (cchMax), RTSTR_TAG)
+
+/**
+ * Allocates a new copy of the given UTF-8 substring (custom tag).
+ *
+ * @returns Pointer to the allocated UTF-8 substring.
+ * @param   pszString       UTF-8 string to duplicate.
+ * @param   cchMax          The max number of chars to duplicate, not counting
+ *                          the terminator.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTDECL(char *) RTStrDupNTag(const char *pszString, size_t cchMax, const char *pszTag);
+
+/**
+ * Appends a string onto an existing IPRT allocated string (default tag).
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz
+ *          remains unchanged.
+ *
+ * @param   ppsz                Pointer to the string pointer.  The string
+ *                              pointer must either be NULL or point to a string
+ *                              returned by an IPRT string API.  (In/Out)
+ * @param   pszAppend           The string to append.  NULL and empty strings
+ *                              are quietly ignored.
+ */
+#define RTStrAAppend(ppsz, pszAppend)   RTStrAAppendTag((ppsz), (pszAppend), RTSTR_TAG)
+
+/**
+ * Appends a string onto an existing IPRT allocated string (custom tag).
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz
+ *          remains unchanged.
+ *
+ * @param   ppsz                Pointer to the string pointer.  The string
+ *                              pointer must either be NULL or point to a string
+ *                              returned by an IPRT string API.  (In/Out)
+ * @param   pszAppend           The string to append.  NULL and empty strings
+ *                              are quietly ignored.
+ * @param   pszTag              Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTStrAAppendTag(char **ppsz, const char *pszAppend, const char *pszTag);
+
+/**
+ * Appends N bytes from a strings onto an existing IPRT allocated string
+ * (default tag).
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz
+ *          remains unchanged.
+ *
+ * @param   ppsz                Pointer to the string pointer.  The string
+ *                              pointer must either be NULL or point to a string
+ *                              returned by an IPRT string API.  (In/Out)
+ * @param   pszAppend           The string to append.  Can be NULL if cchAppend
+ *                              is NULL.
+ * @param   cchAppend           The number of chars (not code points) to append
+ *                              from pszAppend.   Must not be more than
+ *                              @a pszAppend contains, except for the special
+ *                              value RTSTR_MAX that can be used to indicate all
+ *                              of @a pszAppend without having to strlen it.
+ */
+#define RTStrAAppendN(ppsz, pszAppend, cchAppend)   RTStrAAppendNTag((ppsz), (pszAppend), (cchAppend), RTSTR_TAG)
+
+/**
+ * Appends N bytes from a strings onto an existing IPRT allocated string (custom
+ * tag).
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz
+ *          remains unchanged.
+ *
+ * @param   ppsz                Pointer to the string pointer.  The string
+ *                              pointer must either be NULL or point to a string
+ *                              returned by an IPRT string API.  (In/Out)
+ * @param   pszAppend           The string to append.  Can be NULL if cchAppend
+ *                              is NULL.
+ * @param   cchAppend           The number of chars (not code points) to append
+ *                              from pszAppend.   Must not be more than
+ *                              @a pszAppend contains, except for the special
+ *                              value RTSTR_MAX that can be used to indicate all
+ *                              of @a pszAppend without having to strlen it.
+ * @param   pszTag              Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTStrAAppendNTag(char **ppsz, const char *pszAppend, size_t cchAppend, const char *pszTag);
+
+/**
+ * Appends one or more strings onto an existing IPRT allocated string.
+ *
+ * This is a very flexible and efficient alternative to using RTStrAPrintf to
+ * combine several strings together.
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz
+ *          remains unchanged.
+ *
+ * @param   ppsz                Pointer to the string pointer.  The string
+ *                              pointer must either be NULL or point to a string
+ *                              returned by an IPRT string API.  (In/Out)
+ * @param   cPairs              The number of string / length pairs in the
+ *                              @a va.
+ * @param   va                  List of string (const char *) and length
+ *                              (size_t) pairs.  The strings will be appended to
+ *                              the string in the first argument.
+ */
+#define RTStrAAppendExNV(ppsz, cPairs, va)  RTStrAAppendExNVTag((ppsz), (cPairs), (va), RTSTR_TAG)
+
+/**
+ * Appends one or more strings onto an existing IPRT allocated string.
+ *
+ * This is a very flexible and efficient alternative to using RTStrAPrintf to
+ * combine several strings together.
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz
+ *          remains unchanged.
+ *
+ * @param   ppsz                Pointer to the string pointer.  The string
+ *                              pointer must either be NULL or point to a string
+ *                              returned by an IPRT string API.  (In/Out)
+ * @param   cPairs              The number of string / length pairs in the
+ *                              @a va.
+ * @param   va                  List of string (const char *) and length
+ *                              (size_t) pairs.  The strings will be appended to
+ *                              the string in the first argument.
+ * @param   pszTag              Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTStrAAppendExNVTag(char **ppsz, size_t cPairs, va_list va, const char *pszTag);
+
+/**
+ * Appends one or more strings onto an existing IPRT allocated string
+ * (untagged).
+ *
+ * This is a very flexible and efficient alternative to using RTStrAPrintf to
+ * combine several strings together.
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz
+ *          remains unchanged.
+ *
+ * @param   ppsz                Pointer to the string pointer.  The string
+ *                              pointer must either be NULL or point to a string
+ *                              returned by an IPRT string API.  (In/Out)
+ * @param   cPairs              The number of string / length pairs in the
+ *                              ellipsis.
+ * @param   ...                 List of string (const char *) and length
+ *                              (size_t) pairs.  The strings will be appended to
+ *                              the string in the first argument.
+ */
+DECLINLINE(int) RTStrAAppendExN(char **ppsz, size_t cPairs, ...)
+{
+    int     rc;
+    va_list va;
+    va_start(va, cPairs);
+    rc = RTStrAAppendExNVTag(ppsz, cPairs, va, RTSTR_TAG);
+    va_end(va);
+    return rc;
+}
+
+/**
+ * Appends one or more strings onto an existing IPRT allocated string (custom
+ * tag).
+ *
+ * This is a very flexible and efficient alternative to using RTStrAPrintf to
+ * combine several strings together.
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz
+ *          remains unchanged.
+ *
+ * @param   ppsz                Pointer to the string pointer.  The string
+ *                              pointer must either be NULL or point to a string
+ *                              returned by an IPRT string API.  (In/Out)
+ * @param   pszTag              Allocation tag used for statistics and such.
+ * @param   cPairs              The number of string / length pairs in the
+ *                              ellipsis.
+ * @param   ...                 List of string (const char *) and length
+ *                              (size_t) pairs.  The strings will be appended to
+ *                              the string in the first argument.
+ */
+DECLINLINE(int) RTStrAAppendExNTag(char **ppsz, const char *pszTag, size_t cPairs, ...)
+{
+    int     rc;
+    va_list va;
+    va_start(va, cPairs);
+    rc = RTStrAAppendExNVTag(ppsz, cPairs, va, pszTag);
+    va_end(va);
+    return rc;
+}
+
+/**
+ * Truncates an IPRT allocated string (default tag).
+ *
+ * @retval  VINF_SUCCESS.
+ * @retval  VERR_OUT_OF_RANGE if cchNew is too long.  Nothing is done.
+ *
+ * @param   ppsz                Pointer to the string pointer.  The string
+ *                              pointer can be NULL if @a cchNew is 0, no change
+ *                              is made then.  If we actually reallocate the
+ *                              string, the string pointer might be changed by
+ *                              this call.  (In/Out)
+ * @param   cchNew              The new string length (excluding the
+ *                              terminator).  The string must be at least this
+ *                              long or we'll return VERR_OUT_OF_RANGE and
+ *                              assert on you.
+ */
+#define RTStrATruncate(ppsz, cchNew)    RTStrATruncateTag((ppsz), (cchNew), RTSTR_TAG)
+
+/**
+ * Truncates an IPRT allocated string.
+ *
+ * @retval  VINF_SUCCESS.
+ * @retval  VERR_OUT_OF_RANGE if cchNew is too long.  Nothing is done.
+ *
+ * @param   ppsz                Pointer to the string pointer.  The string
+ *                              pointer can be NULL if @a cchNew is 0, no change
+ *                              is made then.  If we actually reallocate the
+ *                              string, the string pointer might be changed by
+ *                              this call.  (In/Out)
+ * @param   cchNew              The new string length (excluding the
+ *                              terminator).  The string must be at least this
+ *                              long or we'll return VERR_OUT_OF_RANGE and
+ *                              assert on you.
+ * @param   pszTag              Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTStrATruncateTag(char **ppsz, size_t cchNew, const char *pszTag);
+
+/**
+ * Allocates memory for string storage (default tag).
+ *
+ * You should normally not use this function, except if there is some very
+ * custom string handling you need doing that isn't covered by any of the other
+ * APIs.
+ *
+ * @returns Pointer to the allocated string.  The first byte is always set
+ *          to the string terminator char, the contents of the remainder of the
+ *          memory is undefined.  The string must be freed by calling RTStrFree.
+ *
+ *          NULL is returned if the allocation failed.  Please translate this to
+ *          VERR_NO_STR_MEMORY and not VERR_NO_MEMORY.  Also consider
+ *          RTStrAllocEx if an IPRT status code is required.
+ *
+ * @param   cb                  How many bytes to allocate.  If this is zero, we
+ *                              will allocate a terminator byte anyway.
+ */
+#define RTStrAlloc(cb)                  RTStrAllocTag((cb), RTSTR_TAG)
+
+/**
+ * Allocates memory for string storage (custom tag).
+ *
+ * You should normally not use this function, except if there is some very
+ * custom string handling you need doing that isn't covered by any of the other
+ * APIs.
+ *
+ * @returns Pointer to the allocated string.  The first byte is always set
+ *          to the string terminator char, the contents of the remainder of the
+ *          memory is undefined.  The string must be freed by calling RTStrFree.
+ *
+ *          NULL is returned if the allocation failed.  Please translate this to
+ *          VERR_NO_STR_MEMORY and not VERR_NO_MEMORY.  Also consider
+ *          RTStrAllocEx if an IPRT status code is required.
+ *
+ * @param   cb                  How many bytes to allocate.  If this is zero, we
+ *                              will allocate a terminator byte anyway.
+ * @param   pszTag              Allocation tag used for statistics and such.
+ */
+RTDECL(char *) RTStrAllocTag(size_t cb, const char *pszTag);
+
+/**
+ * Allocates memory for string storage, with status code (default tag).
+ *
+ * You should normally not use this function, except if there is some very
+ * custom string handling you need doing that isn't covered by any of the other
+ * APIs.
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_STR_MEMORY
+ *
+ * @param   ppsz                Where to return the allocated string.  This will
+ *                              be set to NULL on failure.  On success, the
+ *                              returned memory will always start with a
+ *                              terminator char so that it is considered a valid
+ *                              C string, the contents of rest of the memory is
+ *                              undefined.
+ * @param   cb                  How many bytes to allocate.  If this is zero, we
+ *                              will allocate a terminator byte anyway.
+ */
+#define RTStrAllocEx(ppsz, cb)      RTStrAllocExTag((ppsz), (cb), RTSTR_TAG)
+
+/**
+ * Allocates memory for string storage, with status code (custom tag).
+ *
+ * You should normally not use this function, except if there is some very
+ * custom string handling you need doing that isn't covered by any of the other
+ * APIs.
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_STR_MEMORY
+ *
+ * @param   ppsz                Where to return the allocated string.  This will
+ *                              be set to NULL on failure.  On success, the
+ *                              returned memory will always start with a
+ *                              terminator char so that it is considered a valid
+ *                              C string, the contents of rest of the memory is
+ *                              undefined.
+ * @param   cb                  How many bytes to allocate.  If this is zero, we
+ *                              will allocate a terminator byte anyway.
+ * @param   pszTag              Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTStrAllocExTag(char **ppsz, size_t cb, const char *pszTag);
+
+/**
+ * Reallocates the specified string (default tag).
+ *
+ * You should normally not have use this function, except perhaps to truncate a
+ * really long string you've got from some IPRT string API, but then you should
+ * use RTStrATruncate.
+ *
+ * @returns VINF_SUCCESS.
+ * @retval  VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz
+ *          remains unchanged.
+ *
+ * @param   ppsz                Pointer to the string variable containing the
+ *                              input and output string.
+ *
+ *                              When not freeing the string, the result will
+ *                              always have the last byte set to the terminator
+ *                              character so that when used for string
+ *                              truncation the result will be a valid C string
+ *                              (your job to keep it a valid UTF-8 string).
+ *
+ *                              When the input string is NULL and we're supposed
+ *                              to reallocate, the returned string will also
+ *                              have the first byte set to the terminator char
+ *                              so it will be a valid C string.
+ *
+ * @param   cbNew               When @a cbNew is zero, we'll behave like
+ *                              RTStrFree and @a *ppsz will be set to NULL.
+ *
+ *                              When not zero, this will be the new size of the
+ *                              memory backing the string, i.e. it includes the
+ *                              terminator char.
+ */
+#define RTStrRealloc(ppsz, cbNew)       RTStrReallocTag((ppsz), (cbNew), RTSTR_TAG)
+
+/**
+ * Reallocates the specified string (custom tag).
+ *
+ * You should normally not have use this function, except perhaps to truncate a
+ * really long string you've got from some IPRT string API, but then you should
+ * use RTStrATruncate.
+ *
+ * @returns VINF_SUCCESS.
+ * @retval  VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz
+ *          remains unchanged.
+ *
+ * @param   ppsz                Pointer to the string variable containing the
+ *                              input and output string.
+ *
+ *                              When not freeing the string, the result will
+ *                              always have the last byte set to the terminator
+ *                              character so that when used for string
+ *                              truncation the result will be a valid C string
+ *                              (your job to keep it a valid UTF-8 string).
+ *
+ *                              When the input string is NULL and we're supposed
+ *                              to reallocate, the returned string will also
+ *                              have the first byte set to the terminator char
+ *                              so it will be a valid C string.
+ *
+ * @param   cbNew               When @a cbNew is zero, we'll behave like
+ *                              RTStrFree and @a *ppsz will be set to NULL.
+ *
+ *                              When not zero, this will be the new size of the
+ *                              memory backing the string, i.e. it includes the
+ *                              terminator char.
+ * @param   pszTag              Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTStrReallocTag(char **ppsz, size_t cbNew, const char *pszTag);
+
+/**
+ * Validates the UTF-8 encoding of the string.
+ *
+ * @returns iprt status code.
+ * @param   psz         The string.
+ */
+RTDECL(int) RTStrValidateEncoding(const char *psz);
+
+/** @name Flags for RTStrValidateEncodingEx and RTUtf16ValidateEncodingEx
+ * @{
+ */
+/** Check that the string is zero terminated within the given size.
+ * VERR_BUFFER_OVERFLOW will be returned if the check fails. */
+#define RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED     RT_BIT_32(0)
+/** Check that the string is exactly the given length.
+ * If it terminates early, VERR_BUFFER_UNDERFLOW will be returned.  When used
+ * together with RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED, the given length must
+ * include the terminator or VERR_BUFFER_OVERFLOW will be returned. */
+#define RTSTR_VALIDATE_ENCODING_EXACT_LENGTH        RT_BIT_32(1)
+/** @} */
+
+/**
+ * Validates the UTF-8 encoding of the string.
+ *
+ * @returns iprt status code.
+ * @param   psz         The string.
+ * @param   cch         The max string length (/ size).  Use RTSTR_MAX to
+ *                      process the entire string.
+ * @param   fFlags      Combination of RTSTR_VALIDATE_ENCODING_XXX flags.
+ */
+RTDECL(int) RTStrValidateEncodingEx(const char *psz, size_t cch, uint32_t fFlags);
+
+/**
+ * Checks if the UTF-8 encoding is valid.
+ *
+ * @returns true / false.
+ * @param   psz         The string.
+ */
+RTDECL(bool) RTStrIsValidEncoding(const char *psz);
+
+/**
+ * Purge all bad UTF-8 encoding in the string, replacing it with '?'.
+ *
+ * @returns The number of bad characters (0 if nothing was done).
+ * @param   psz         The string to purge.
+ */
+RTDECL(size_t) RTStrPurgeEncoding(char *psz);
+
+/**
+ * Sanitizes a (valid) UTF-8 string by replacing all characters outside a white
+ * list in-place by an ASCII replacement character.
+ *
+ * Multi-byte characters will be replaced byte by byte.
+ *
+ * @returns The number of code points replaced.  In the case of an incorrectly
+ *          encoded string -1 will be returned, and the string is not completely
+ *          processed.  In the case of puszValidPairs having an odd number of
+ *          code points, -1 will be also return but without any modification to
+ *          the string.
+ * @param   psz            The string to sanitise.
+ * @param   puszValidPairs A zero-terminated array of pairs of Unicode points.
+ *                         Each pair is the start and end point of a range,
+ *                         and the union of these ranges forms the white list.
+ * @param   chReplacement  The ASCII replacement character.
+ */
+RTDECL(ssize_t) RTStrPurgeComplementSet(char *psz, PCRTUNICP puszValidPairs, char chReplacement);
+
+/**
+ * Gets the number of code points the string is made up of, excluding
+ * the terminator.
+ *
+ *
+ * @returns Number of code points (RTUNICP).
+ * @returns 0 if the string was incorrectly encoded.
+ * @param   psz         The string.
+ */
+RTDECL(size_t) RTStrUniLen(const char *psz);
+
+/**
+ * Gets the number of code points the string is made up of, excluding
+ * the terminator.
+ *
+ * This function will validate the string, and incorrectly encoded UTF-8
+ * strings will be rejected.
+ *
+ * @returns iprt status code.
+ * @param   psz         The string.
+ * @param   cch         The max string length. Use RTSTR_MAX to process the entire string.
+ * @param   pcuc        Where to store the code point count.
+ *                      This is undefined on failure.
+ */
+RTDECL(int) RTStrUniLenEx(const char *psz, size_t cch, size_t *pcuc);
+
+/**
+ * Translate a UTF-8 string into an unicode string (i.e. RTUNICPs), allocating the string buffer.
+ *
+ * @returns iprt status code.
+ * @param   pszString       UTF-8 string to convert.
+ * @param   ppUniString     Receives pointer to the allocated unicode string.
+ *                          The returned string must be freed using RTUniFree().
+ */
+RTDECL(int) RTStrToUni(const char *pszString, PRTUNICP *ppUniString);
+
+/**
+ * Translates pszString from UTF-8 to an array of code points, allocating the result
+ * array if requested.
+ *
+ * @returns iprt status code.
+ * @param   pszString       UTF-8 string to convert.
+ * @param   cchString       The maximum size in chars (the type) to convert. The conversion stop
+ *                          when it reaches cchString or the string terminator ('\\0').
+ *                          Use RTSTR_MAX to translate the entire string.
+ * @param   ppaCps          If cCps is non-zero, this must either be pointing to pointer to
+ *                          a buffer of the specified size, or pointer to a NULL pointer.
+ *                          If *ppusz is NULL or cCps is zero a buffer of at least cCps items
+ *                          will be allocated to hold the translated string.
+ *                          If a buffer was requested it must be freed using RTUtf16Free().
+ * @param   cCps            The number of code points in the unicode string. This includes the terminator.
+ * @param   pcCps           Where to store the length of the translated string,
+ *                          excluding the terminator. (Optional)
+ *
+ *                          This may be set under some error conditions,
+ *                          however, only for VERR_BUFFER_OVERFLOW and
+ *                          VERR_NO_STR_MEMORY will it contain a valid string
+ *                          length that can be used to resize the buffer.
+ */
+RTDECL(int)  RTStrToUniEx(const char *pszString, size_t cchString, PRTUNICP *ppaCps, size_t cCps, size_t *pcCps);
+
+/**
+ * Calculates the length of the string in RTUTF16 items.
+ *
+ * This function will validate the string, and incorrectly encoded UTF-8
+ * strings will be rejected. The primary purpose of this function is to
+ * help allocate buffers for RTStrToUtf16Ex of the correct size. For most
+ * other purposes RTStrCalcUtf16LenEx() should be used.
+ *
+ * @returns Number of RTUTF16 items.
+ * @returns 0 if the string was incorrectly encoded.
+ * @param   psz         The string.
+ */
+RTDECL(size_t) RTStrCalcUtf16Len(const char *psz);
+
+/**
+ * Calculates the length of the string in RTUTF16 items.
+ *
+ * This function will validate the string, and incorrectly encoded UTF-8
+ * strings will be rejected.
+ *
+ * @returns iprt status code.
+ * @param   psz         The string.
+ * @param   cch         The max string length. Use RTSTR_MAX to process the entire string.
+ * @param   pcwc        Where to store the string length. Optional.
+ *                      This is undefined on failure.
+ */
+RTDECL(int) RTStrCalcUtf16LenEx(const char *psz, size_t cch, size_t *pcwc);
+
+/**
+ * Translate a UTF-8 string into a UTF-16 allocating the result buffer (default
+ * tag).
+ *
+ * @returns iprt status code.
+ * @param   pszString       UTF-8 string to convert.
+ * @param   ppwszString     Receives pointer to the allocated UTF-16 string.
+ *                          The returned string must be freed using RTUtf16Free().
+ */
+#define RTStrToUtf16(pszString, ppwszString)    RTStrToUtf16Tag((pszString), (ppwszString), RTSTR_TAG)
+
+/**
+ * Translate a UTF-8 string into a UTF-16 allocating the result buffer (custom
+ * tag).
+ *
+ * @returns iprt status code.
+ * @param   pszString       UTF-8 string to convert.
+ * @param   ppwszString     Receives pointer to the allocated UTF-16 string.
+ *                          The returned string must be freed using RTUtf16Free().
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTStrToUtf16Tag(const char *pszString, PRTUTF16 *ppwszString, const char *pszTag);
+
+/**
+ * Translates pszString from UTF-8 to UTF-16, allocating the result buffer if requested.
+ *
+ * @returns iprt status code.
+ * @param   pszString       UTF-8 string to convert.
+ * @param   cchString       The maximum size in chars (the type) to convert. The conversion stop
+ *                          when it reaches cchString or the string terminator ('\\0').
+ *                          Use RTSTR_MAX to translate the entire string.
+ * @param   ppwsz           If cwc is non-zero, this must either be pointing to pointer to
+ *                          a buffer of the specified size, or pointer to a NULL pointer.
+ *                          If *ppwsz is NULL or cwc is zero a buffer of at least cwc items
+ *                          will be allocated to hold the translated string.
+ *                          If a buffer was requested it must be freed using RTUtf16Free().
+ * @param   cwc             The buffer size in RTUTF16s. This includes the terminator.
+ * @param   pcwc            Where to store the length of the translated string,
+ *                          excluding the terminator. (Optional)
+ *
+ *                          This may be set under some error conditions,
+ *                          however, only for VERR_BUFFER_OVERFLOW and
+ *                          VERR_NO_STR_MEMORY will it contain a valid string
+ *                          length that can be used to resize the buffer.
+ */
+#define RTStrToUtf16Ex(pszString, cchString, ppwsz, cwc, pcwc) \
+    RTStrToUtf16ExTag((pszString), (cchString), (ppwsz), (cwc), (pcwc), RTSTR_TAG)
+
+/**
+ * Translates pszString from UTF-8 to UTF-16, allocating the result buffer if
+ * requested (custom tag).
+ *
+ * @returns iprt status code.
+ * @param   pszString       UTF-8 string to convert.
+ * @param   cchString       The maximum size in chars (the type) to convert. The conversion stop
+ *                          when it reaches cchString or the string terminator ('\\0').
+ *                          Use RTSTR_MAX to translate the entire string.
+ * @param   ppwsz           If cwc is non-zero, this must either be pointing to pointer to
+ *                          a buffer of the specified size, or pointer to a NULL pointer.
+ *                          If *ppwsz is NULL or cwc is zero a buffer of at least cwc items
+ *                          will be allocated to hold the translated string.
+ *                          If a buffer was requested it must be freed using RTUtf16Free().
+ * @param   cwc             The buffer size in RTUTF16s. This includes the terminator.
+ * @param   pcwc            Where to store the length of the translated string,
+ *                          excluding the terminator. (Optional)
+ *
+ *                          This may be set under some error conditions,
+ *                          however, only for VERR_BUFFER_OVERFLOW and
+ *                          VERR_NO_STR_MEMORY will it contain a valid string
+ *                          length that can be used to resize the buffer.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTDECL(int)  RTStrToUtf16ExTag(const char *pszString, size_t cchString, PRTUTF16 *ppwsz, size_t cwc, size_t *pcwc, const char *pszTag);
+
+
+/**
+ * Calculates the length of the string in Latin-1 characters.
+ *
+ * This function will validate the string, and incorrectly encoded UTF-8
+ * strings as well as string with codepoints outside the latin-1 range will be
+ * rejected.  The primary purpose of this function is to help allocate buffers
+ * for RTStrToLatin1Ex of the correct size.  For most other purposes
+ * RTStrCalcLatin1LenEx() should be used.
+ *
+ * @returns Number of Latin-1 characters.
+ * @returns 0 if the string was incorrectly encoded.
+ * @param   psz         The string.
+ */
+RTDECL(size_t) RTStrCalcLatin1Len(const char *psz);
+
+/**
+ * Calculates the length of the string in Latin-1 characters.
+ *
+ * This function will validate the string, and incorrectly encoded UTF-8
+ * strings as well as string with codepoints outside the latin-1 range will be
+ * rejected.
+ *
+ * @returns iprt status code.
+ * @param   psz         The string.
+ * @param   cch         The max string length. Use RTSTR_MAX to process the
+ *                      entire string.
+ * @param   pcch        Where to store the string length. Optional.
+ *                      This is undefined on failure.
+ */
+RTDECL(int) RTStrCalcLatin1LenEx(const char *psz, size_t cch, size_t *pcch);
+
+/**
+ * Translate a UTF-8 string into a Latin-1 allocating the result buffer (default
+ * tag).
+ *
+ * @returns iprt status code.
+ * @param   pszString       UTF-8 string to convert.
+ * @param   ppszString      Receives pointer to the allocated Latin-1 string.
+ *                          The returned string must be freed using RTStrFree().
+ */
+#define RTStrToLatin1(pszString, ppszString)    RTStrToLatin1Tag((pszString), (ppszString), RTSTR_TAG)
+
+/**
+ * Translate a UTF-8 string into a Latin-1 allocating the result buffer (custom
+ * tag).
+ *
+ * @returns iprt status code.
+ * @param   pszString       UTF-8 string to convert.
+ * @param   ppszString      Receives pointer to the allocated Latin-1 string.
+ *                          The returned string must be freed using RTStrFree().
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTStrToLatin1Tag(const char *pszString, char **ppszString, const char *pszTag);
+
+/**
+ * Translates pszString from UTF-8 to Latin-1, allocating the result buffer if requested.
+ *
+ * @returns iprt status code.
+ * @param   pszString       UTF-8 string to convert.
+ * @param   cchString       The maximum size in chars (the type) to convert.
+ *                          The conversion stop when it reaches cchString or
+ *                          the string terminator ('\\0'). Use RTSTR_MAX to
+ *                          translate the entire string.
+ * @param   ppsz            If cch is non-zero, this must either be pointing to
+ *                          pointer to a buffer of the specified size, or
+ *                          pointer to a NULL pointer.  If *ppsz is NULL or cch
+ *                          is zero a buffer of at least cch items will be
+ *                          allocated to hold the translated string. If a
+ *                          buffer was requested it must be freed using
+ *                          RTStrFree().
+ * @param   cch             The buffer size in bytes. This includes the
+ *                          terminator.
+ * @param   pcch            Where to store the length of the translated string,
+ *                          excluding the terminator. (Optional)
+ *
+ *                          This may be set under some error conditions,
+ *                          however, only for VERR_BUFFER_OVERFLOW and
+ *                          VERR_NO_STR_MEMORY will it contain a valid string
+ *                          length that can be used to resize the buffer.
+ */
+#define RTStrToLatin1Ex(pszString, cchString, ppsz, cch, pcch) \
+    RTStrToLatin1ExTag((pszString), (cchString), (ppsz), (cch), (pcch), RTSTR_TAG)
+
+/**
+ * Translates pszString from UTF-8 to Latin1, allocating the result buffer if
+ * requested (custom tag).
+ *
+ * @returns iprt status code.
+ * @param   pszString       UTF-8 string to convert.
+ * @param   cchString       The maximum size in chars (the type) to convert.
+ *                          The conversion stop when it reaches cchString or
+ *                          the string terminator ('\\0'). Use RTSTR_MAX to
+ *                          translate the entire string.
+ * @param   ppsz            If cch is non-zero, this must either be pointing to
+ *                          pointer to a buffer of the specified size, or
+ *                          pointer to a NULL pointer.  If *ppsz is NULL or cch
+ *                          is zero a buffer of at least cch items will be
+ *                          allocated to hold the translated string. If a
+ *                          buffer was requested it must be freed using
+ *                          RTStrFree().
+ * @param   cch             The buffer size in bytes.  This includes the
+ *                          terminator.
+ * @param   pcch            Where to store the length of the translated string,
+ *                          excluding the terminator. (Optional)
+ *
+ *                          This may be set under some error conditions,
+ *                          however, only for VERR_BUFFER_OVERFLOW and
+ *                          VERR_NO_STR_MEMORY will it contain a valid string
+ *                          length that can be used to resize the buffer.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTDECL(int)  RTStrToLatin1ExTag(const char *pszString, size_t cchString, char **ppsz, size_t cch, size_t *pcch, const char *pszTag);
+
+/**
+ * Get the unicode code point at the given string position.
+ *
+ * @returns unicode code point.
+ * @returns RTUNICP_INVALID if the encoding is invalid.
+ * @param   psz         The string.
+ */
+RTDECL(RTUNICP) RTStrGetCpInternal(const char *psz);
+
+/**
+ * Get the unicode code point at the given string position.
+ *
+ * @returns iprt status code
+ * @returns VERR_INVALID_UTF8_ENCODING if the encoding is invalid.
+ * @param   ppsz        The string cursor.
+ *                      This is advanced one character forward on failure.
+ * @param   pCp         Where to store the unicode code point.
+ *                      Stores RTUNICP_INVALID if the encoding is invalid.
+ */
+RTDECL(int) RTStrGetCpExInternal(const char **ppsz, PRTUNICP pCp);
+
+/**
+ * Get the unicode code point at the given string position for a string of a
+ * given length.
+ *
+ * @returns iprt status code
+ * @retval  VERR_INVALID_UTF8_ENCODING if the encoding is invalid.
+ * @retval  VERR_END_OF_STRING if *pcch is 0. *pCp is set to RTUNICP_INVALID.
+ *
+ * @param   ppsz        The string.
+ * @param   pcch        Pointer to the length of the string.  This will be
+ *                      decremented by the size of the code point.
+ * @param   pCp         Where to store the unicode code point.
+ *                      Stores RTUNICP_INVALID if the encoding is invalid.
+ */
+RTDECL(int) RTStrGetCpNExInternal(const char **ppsz, size_t *pcch, PRTUNICP pCp);
+
+/**
+ * Put the unicode code point at the given string position
+ * and return the pointer to the char following it.
+ *
+ * This function will not consider anything at or following the
+ * buffer area pointed to by psz. It is therefore not suitable for
+ * inserting code points into a string, only appending/overwriting.
+ *
+ * @returns pointer to the char following the written code point.
+ * @param   psz         The string.
+ * @param   CodePoint   The code point to write.
+ *                      This should not be RTUNICP_INVALID or any other
+ *                      character out of the UTF-8 range.
+ *
+ * @remark  This is a worker function for RTStrPutCp().
+ *
+ */
+RTDECL(char *) RTStrPutCpInternal(char *psz, RTUNICP CodePoint);
+
+/**
+ * Get the unicode code point at the given string position.
+ *
+ * @returns unicode code point.
+ * @returns RTUNICP_INVALID if the encoding is invalid.
+ * @param   psz         The string.
+ *
+ * @remark  We optimize this operation by using an inline function for
+ *          the most frequent and simplest sequence, the rest is
+ *          handled by RTStrGetCpInternal().
+ */
+DECLINLINE(RTUNICP) RTStrGetCp(const char *psz)
+{
+    const unsigned char uch = *(const unsigned char *)psz;
+    if (!(uch & RT_BIT(7)))
+        return uch;
+    return RTStrGetCpInternal(psz);
+}
+
+/**
+ * Get the unicode code point at the given string position.
+ *
+ * @returns iprt status code.
+ * @param   ppsz        Pointer to the string pointer. This will be updated to
+ *                      point to the char following the current code point.
+ *                      This is advanced one character forward on failure.
+ * @param   pCp         Where to store the code point.
+ *                      RTUNICP_INVALID is stored here on failure.
+ *
+ * @remark  We optimize this operation by using an inline function for
+ *          the most frequent and simplest sequence, the rest is
+ *          handled by RTStrGetCpExInternal().
+ */
+DECLINLINE(int) RTStrGetCpEx(const char **ppsz, PRTUNICP pCp)
+{
+    const unsigned char uch = **(const unsigned char **)ppsz;
+    if (!(uch & RT_BIT(7)))
+    {
+        (*ppsz)++;
+        *pCp = uch;
+        return VINF_SUCCESS;
+    }
+    return RTStrGetCpExInternal(ppsz, pCp);
+}
+
+/**
+ * Get the unicode code point at the given string position for a string of a
+ * given maximum length.
+ *
+ * @returns iprt status code.
+ * @retval  VERR_INVALID_UTF8_ENCODING if the encoding is invalid.
+ * @retval  VERR_END_OF_STRING if *pcch is 0. *pCp is set to RTUNICP_INVALID.
+ *
+ * @param   ppsz        Pointer to the string pointer. This will be updated to
+ *                      point to the char following the current code point.
+ * @param   pcch        Pointer to the maximum string length.  This will be
+ *                      decremented by the size of the code point found.
+ * @param   pCp         Where to store the code point.
+ *                      RTUNICP_INVALID is stored here on failure.
+ *
+ * @remark  We optimize this operation by using an inline function for
+ *          the most frequent and simplest sequence, the rest is
+ *          handled by RTStrGetCpNExInternal().
+ */
+DECLINLINE(int) RTStrGetCpNEx(const char **ppsz, size_t *pcch, PRTUNICP pCp)
+{
+    if (RT_LIKELY(*pcch != 0))
+    {
+        const unsigned char uch = **(const unsigned char **)ppsz;
+        if (!(uch & RT_BIT(7)))
+        {
+            (*ppsz)++;
+            (*pcch)--;
+            *pCp = uch;
+            return VINF_SUCCESS;
+        }
+    }
+    return RTStrGetCpNExInternal(ppsz, pcch, pCp);
+}
+
+/**
+ * Get the UTF-8 size in characters of a given Unicode code point.
+ *
+ * The code point is expected to be a valid Unicode one, but not necessarily in
+ * the range supported by UTF-8.
+ *
+ * @returns The number of chars (bytes) required to encode the code point, or
+ *          zero if there is no UTF-8 encoding.
+ * @param   CodePoint       The unicode code point.
+ */
+DECLINLINE(size_t) RTStrCpSize(RTUNICP CodePoint)
+{
+    if (CodePoint < 0x00000080)
+        return 1;
+    if (CodePoint < 0x00000800)
+        return 2;
+    if (CodePoint < 0x00010000)
+        return 3;
+#ifdef RT_USE_RTC_3629
+    if (CodePoint < 0x00011000)
+        return 4;
+#else
+    if (CodePoint < 0x00200000)
+        return 4;
+    if (CodePoint < 0x04000000)
+        return 5;
+    if (CodePoint < 0x7fffffff)
+        return 6;
+#endif
+    return 0;
+}
+
+/**
+ * Put the unicode code point at the given string position
+ * and return the pointer to the char following it.
+ *
+ * This function will not consider anything at or following the
+ * buffer area pointed to by psz. It is therefore not suitable for
+ * inserting code points into a string, only appending/overwriting.
+ *
+ * @returns pointer to the char following the written code point.
+ * @param   psz         The string.
+ * @param   CodePoint   The code point to write.
+ *                      This should not be RTUNICP_INVALID or any other
+ *                      character out of the UTF-8 range.
+ *
+ * @remark  We optimize this operation by using an inline function for
+ *          the most frequent and simplest sequence, the rest is
+ *          handled by RTStrPutCpInternal().
+ */
+DECLINLINE(char *) RTStrPutCp(char *psz, RTUNICP CodePoint)
+{
+    if (CodePoint < 0x80)
+    {
+        *psz++ = (unsigned char)CodePoint;
+        return psz;
+    }
+    return RTStrPutCpInternal(psz, CodePoint);
+}
+
+/**
+ * Skips ahead, past the current code point.
+ *
+ * @returns Pointer to the char after the current code point.
+ * @param   psz     Pointer to the current code point.
+ * @remark  This will not move the next valid code point, only past the current one.
+ */
+DECLINLINE(char *) RTStrNextCp(const char *psz)
+{
+    RTUNICP Cp;
+    RTStrGetCpEx(&psz, &Cp);
+    return (char *)psz;
+}
+
+/**
+ * Skips back to the previous code point.
+ *
+ * @returns Pointer to the char before the current code point.
+ * @returns pszStart on failure.
+ * @param   pszStart    Pointer to the start of the string.
+ * @param   psz         Pointer to the current code point.
+ */
+RTDECL(char *) RTStrPrevCp(const char *pszStart, const char *psz);
+
+
+/** @page pg_rt_str_format  The IPRT Format Strings
+ *
+ * IPRT implements most of the commonly used format types and flags with the
+ * exception of floating point which is completely missing.  In addition IPRT
+ * provides a number of IPRT specific format types for the IPRT typedefs and
+ * other useful things.  Note that several of these extensions are similar to
+ * \%p and doesn't care much if you try add formating flags/width/precision.
+ *
+ *
+ * Group 0a, The commonly used format types:
+ *      - \%s   - Takes a pointer to a zero terminated string (UTF-8) and
+ *                prints it with the optionally adjustment (width, -) and
+ *                length restriction (precision).
+ *      - \%ls  - Same as \%s except that the input is UTF-16 (output UTF-8).
+ *      - \%Ls  - Same as \%s except that the input is UCS-32 (output UTF-8).
+ *      - \%S   - Same as \%s, used to convert to current codeset but this is
+ *                now done by the streams code.  Deprecated, use \%s.
+ *      - \%lS  - Ditto. Deprecated, use \%ls.
+ *      - \%LS  - Ditto. Deprecated, use \%Ls.
+ *      - \%c   - Takes a char and prints it.
+ *      - \%d   - Takes a signed integer and prints it as decimal. Thousand
+ *                separator (\'), zero padding (0), adjustment (-+), width,
+ *                precision
+ *      - \%i   - Same as \%d.
+ *      - \%u   - Takes an unsigned integer and prints it as decimal. Thousand
+ *                separator (\'), zero padding (0), adjustment (-+), width,
+ *                precision
+ *      - \%x   - Takes an unsigned integer and prints it as lowercased
+ *                hexadecimal.  The special hash (\#) flag causes a '0x'
+ *                prefixed to be printed. Zero padding (0), adjustment (-+),
+ *                width, precision.
+ *      - \%X   - Same as \%x except that it is uppercased.
+ *      - \%o   - Takes an unsigned (?) integer and prints it as octal. Zero
+ *                padding (0), adjustment (-+), width, precision.
+ *      - \%p   - Takes a pointer (void technically) and prints it. Zero
+ *                padding (0), adjustment (-+), width, precision.
+ *
+ * The \%d, \%i, \%u, \%x, \%X and \%o format types support the following
+ * argument type specifiers:
+ *      - \%ll  - long long (uint64_t).
+ *      - \%L   - long long (uint64_t).
+ *      - \%l   - long (uint32_t, uint64_t)
+ *      - \%h   - short (int16_t).
+ *      - \%hh  - char (int8_t).
+ *      - \%H   - char (int8_t).
+ *      - \%z   - size_t.
+ *      - \%j   - intmax_t (int64_t).
+ *      - \%t   - ptrdiff_t.
+ * The type in parentheses is typical sizes, however when printing those types
+ * you are better off using the special group 2 format types below (\%RX32 and
+ * such).
+ *
+ *
+ * Group 0b, IPRT format tricks:
+ *      - %M    - Replaces the format string, takes a string pointer.
+ *      - %N    - Nested formatting, takes a pointer to a format string
+ *                followed by the pointer to a va_list variable.  The va_list
+ *                variable will not be modified and the caller must do va_end()
+ *                on it.  Make sure the va_list variable is NOT in a parameter
+ *                list or some gcc versions/targets may get it all wrong.
+ *
+ *
+ * Group 1, the basic runtime typedefs (excluding those which obviously are
+ * pointer):
+ *      - \%RTbool          - Takes a bool value and prints 'true', 'false', or '!%d!'.
+ *      - \%RTfile          - Takes a #RTFILE value.
+ *      - \%RTfmode         - Takes a #RTFMODE value.
+ *      - \%RTfoff          - Takes a #RTFOFF value.
+ *      - \%RTfp16          - Takes a #RTFAR16 value.
+ *      - \%RTfp32          - Takes a #RTFAR32 value.
+ *      - \%RTfp64          - Takes a #RTFAR64 value.
+ *      - \%RTgid           - Takes a #RTGID value.
+ *      - \%RTino           - Takes a #RTINODE value.
+ *      - \%RTint           - Takes a #RTINT value.
+ *      - \%RTiop           - Takes a #RTIOPORT value.
+ *      - \%RTldrm          - Takes a #RTLDRMOD value.
+ *      - \%RTmac           - Takes a #PCRTMAC pointer.
+ *      - \%RTnaddr         - Takes a #PCRTNETADDR value.
+ *      - \%RTnaipv4        - Takes a #RTNETADDRIPV4 value.
+ *      - \%RTnaipv6        - Takes a #PCRTNETADDRIPV6 value.
+ *      - \%RTnthrd         - Takes a #RTNATIVETHREAD value.
+ *      - \%RTnthrd         - Takes a #RTNATIVETHREAD value.
+ *      - \%RTproc          - Takes a #RTPROCESS value.
+ *      - \%RTptr           - Takes a #RTINTPTR or #RTUINTPTR value (but not void *).
+ *      - \%RTreg           - Takes a #RTCCUINTREG value.
+ *      - \%RTsel           - Takes a #RTSEL value.
+ *      - \%RTsem           - Takes a #RTSEMEVENT, #RTSEMEVENTMULTI, #RTSEMMUTEX, #RTSEMFASTMUTEX, or #RTSEMRW value.
+ *      - \%RTsock          - Takes a #RTSOCKET value.
+ *      - \%RTthrd          - Takes a #RTTHREAD value.
+ *      - \%RTuid           - Takes a #RTUID value.
+ *      - \%RTuint          - Takes a #RTUINT value.
+ *      - \%RTunicp         - Takes a #RTUNICP value.
+ *      - \%RTutf16         - Takes a #RTUTF16 value.
+ *      - \%RTuuid          - Takes a #PCRTUUID and will print the UUID as a string.
+ *      - \%RTxuint         - Takes a #RTUINT or #RTINT value, formatting it as hex.
+ *      - \%RGi             - Takes a #RTGCINT value.
+ *      - \%RGp             - Takes a #RTGCPHYS value.
+ *      - \%RGr             - Takes a #RTGCUINTREG value.
+ *      - \%RGu             - Takes a #RTGCUINT value.
+ *      - \%RGv             - Takes a #RTGCPTR, #RTGCINTPTR or #RTGCUINTPTR value.
+ *      - \%RGx             - Takes a #RTGCUINT or #RTGCINT value, formatting it as hex.
+ *      - \%RHi             - Takes a #RTHCINT value.
+ *      - \%RHp             - Takes a #RTHCPHYS value.
+ *      - \%RHr             - Takes a #RTHCUINTREG value.
+ *      - \%RHu             - Takes a #RTHCUINT value.
+ *      - \%RHv             - Takes a #RTHCPTR, #RTHCINTPTR or #RTHCUINTPTR value.
+ *      - \%RHx             - Takes a #RTHCUINT or #RTHCINT value, formatting it as hex.
+ *      - \%RRv             - Takes a #RTRCPTR, #RTRCINTPTR or #RTRCUINTPTR value.
+ *      - \%RCi             - Takes a #RTINT value.
+ *      - \%RCp             - Takes a #RTCCPHYS value.
+ *      - \%RCr             - Takes a #RTCCUINTREG value.
+ *      - \%RCu             - Takes a #RTUINT value.
+ *      - \%RCv             - Takes a #uintptr_t, #intptr_t, void * value.
+ *      - \%RCx             - Takes a #RTUINT or #RTINT value, formatting it as hex.
+ *
+ *
+ * Group 2, the generic integer types which are prefered over relying on what
+ * bit-count a 'long', 'short',  or 'long long' has on a platform. This are
+ * highly prefered for the [u]intXX_t kind of types:
+ *      - \%RI[8|16|32|64]  - Signed integer value of the specifed bit count.
+ *      - \%RU[8|16|32|64]  - Unsigned integer value of the specifed bit count.
+ *      - \%RX[8|16|32|64]  - Hexadecimal integer value of the specifed bit count.
+ *
+ *
+ * Group 3, hex dumpers and other complex stuff which requires more than simple
+ * formatting:
+ *      - \%Rhxd            - Takes a pointer to the memory which is to be dumped in typical
+ *                            hex format. Use the precision to specify the length, and the width to
+ *                            set the number of bytes per line. Default width and precision is 16.
+ *      - \%Rhxs            - Takes a pointer to the memory to be displayed as a hex string,
+ *                            i.e. a series of space separated bytes formatted as two digit hex value.
+ *                            Use the precision to specify the length. Default length is 16 bytes.
+ *                            The width, if specified, is ignored.
+ *      - \%Rrc             - Takes an integer iprt status code as argument. Will insert the
+ *                            status code define corresponding to the iprt status code.
+ *      - \%Rrs             - Takes an integer iprt status code as argument. Will insert the
+ *                            short description of the specified status code.
+ *      - \%Rrf             - Takes an integer iprt status code as argument. Will insert the
+ *                            full description of the specified status code.
+ *      - \%Rra             - Takes an integer iprt status code as argument. Will insert the
+ *                            status code define + full description.
+ *      - \%Rwc             - Takes a long Windows error code as argument. Will insert the status
+ *                            code define corresponding to the Windows error code.
+ *      - \%Rwf             - Takes a long Windows error code as argument. Will insert the
+ *                            full description of the specified status code.
+ *      - \%Rwa             - Takes a long Windows error code as argument. Will insert the
+ *                            error code define + full description.
+ *
+ *      - \%Rhrc            - Takes a COM/XPCOM status code as argument. Will insert the status
+ *                            code define corresponding to the Windows error code.
+ *      - \%Rhrf            - Takes a COM/XPCOM status code as argument. Will insert the
+ *                            full description of the specified status code.
+ *      - \%Rhra            - Takes a COM/XPCOM error code as argument. Will insert the
+ *                            error code define + full description.
+ *
+ *      - \%Rfn             - Pretty printing of a function or method. It drops the
+ *                            return code and parameter list.
+ *      - \%Rbn             - Prints the base name.  For dropping the path in
+ *                            order to save space when printing a path name.
+ *
+ * On other platforms, \%Rw? simply prints the argument in a form of 0xXXXXXXXX.
+ *
+ *
+ * Group 4, structure dumpers:
+ *      - \%RDtimespec      - Takes a PCRTTIMESPEC.
+ *
+ *
+ * Group 5, XML / HTML escapers:
+ *      - \%RMas            - Takes a string pointer (const char *) and outputs
+ *                            it as an attribute value with the proper escaping.
+ *                            This typically ends up in double quotes.
+ *
+ *      - \%RMes            - Takes a string pointer (const char *) and outputs
+ *                            it as an element with the necessary escaping.
+ *
+ * Group 6, CPU Architecture Register dumpers:
+ *      - \%RAx86[reg]      - Takes a 64-bit register value if the register is
+ *                            64-bit or smaller.  Check the code wrt which
+ *                            registers are implemented.
+ *
+ */
+
+#ifndef DECLARED_FNRTSTROUTPUT          /* duplicated in iprt/log.h */
+# define DECLARED_FNRTSTROUTPUT
+/**
+ * Output callback.
+ *
+ * @returns number of bytes written.
+ * @param   pvArg       User argument.
+ * @param   pachChars   Pointer to an array of utf-8 characters.
+ * @param   cbChars     Number of bytes in the character array pointed to by pachChars.
+ */
+typedef DECLCALLBACK(size_t) FNRTSTROUTPUT(void *pvArg, const char *pachChars, size_t cbChars);
+/** Pointer to callback function. */
+typedef FNRTSTROUTPUT *PFNRTSTROUTPUT;
+#endif
+
+/** @name Format flag.
+ * These are used by RTStrFormat extensions and RTStrFormatNumber, mind
+ * that not all flags makes sense to both of the functions.
+ * @{ */
+#define RTSTR_F_CAPITAL         0x0001
+#define RTSTR_F_LEFT            0x0002
+#define RTSTR_F_ZEROPAD         0x0004
+#define RTSTR_F_SPECIAL         0x0008
+#define RTSTR_F_VALSIGNED       0x0010
+#define RTSTR_F_PLUS            0x0020
+#define RTSTR_F_BLANK           0x0040
+#define RTSTR_F_WIDTH           0x0080
+#define RTSTR_F_PRECISION       0x0100
+#define RTSTR_F_THOUSAND_SEP    0x0200
+#define RTSTR_F_OBFUSCATE_PTR   0x0400
+
+#define RTSTR_F_BIT_MASK        0xf800
+#define RTSTR_F_8BIT            0x0800
+#define RTSTR_F_16BIT           0x1000
+#define RTSTR_F_32BIT           0x2000
+#define RTSTR_F_64BIT           0x4000
+#define RTSTR_F_128BIT          0x8000
+/** @} */
+
+/** @def RTSTR_GET_BIT_FLAG
+ * Gets the bit flag for the specified type.
+ */
+#define RTSTR_GET_BIT_FLAG(type) \
+    ( sizeof(type) * 8 == 32  ? RTSTR_F_32BIT \
+    : sizeof(type) * 8 == 64  ? RTSTR_F_64BIT \
+    : sizeof(type) * 8 == 16  ? RTSTR_F_16BIT \
+    : sizeof(type) * 8 == 8   ? RTSTR_F_8BIT \
+    : sizeof(type) * 8 == 128 ? RTSTR_F_128BIT \
+    : 0)
+
+
+/**
+ * Callback to format non-standard format specifiers.
+ *
+ * @returns The number of bytes formatted.
+ * @param   pvArg           Formatter argument.
+ * @param   pfnOutput       Pointer to output function.
+ * @param   pvArgOutput     Argument for the output function.
+ * @param   ppszFormat      Pointer to the format string pointer. Advance this till the char
+ *                          after the format specifier.
+ * @param   pArgs           Pointer to the argument list. Use this to fetch the arguments.
+ * @param   cchWidth        Format Width. -1 if not specified.
+ * @param   cchPrecision    Format Precision. -1 if not specified.
+ * @param   fFlags          Flags (RTSTR_NTFS_*).
+ * @param   chArgSize       The argument size specifier, 'l' or 'L'.
+ */
+typedef DECLCALLBACK(size_t) FNSTRFORMAT(void *pvArg, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
+                                         const char **ppszFormat, va_list *pArgs, int cchWidth,
+                                         int cchPrecision, unsigned fFlags, char chArgSize);
+/** Pointer to a FNSTRFORMAT() function. */
+typedef FNSTRFORMAT *PFNSTRFORMAT;
+
+
+/**
+ * Partial implementation of a printf like formatter.
+ * It doesn't do everything correct, and there is no floating point support.
+ * However, it supports custom formats by the means of a format callback.
+ *
+ * @returns number of bytes formatted.
+ * @param   pfnOutput   Output worker.
+ *                      Called in two ways. Normally with a string and its length.
+ *                      For termination, it's called with NULL for string, 0 for length.
+ * @param   pvArgOutput Argument to the output worker.
+ * @param   pfnFormat   Custom format worker.
+ * @param   pvArgFormat Argument to the format worker.
+ * @param   pszFormat   Pointer to the format string, @see pg_rt_str_format.
+ * @param   InArgs      Argument list.
+ */
+RTDECL(size_t) RTStrFormatV(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, PFNSTRFORMAT pfnFormat, void *pvArgFormat,
+                            const char *pszFormat, va_list InArgs) RT_IPRT_FORMAT_ATTR(5, 0);
+
+/**
+ * Partial implementation of a printf like formatter.
+ * It doesn't do everything correct, and there is no floating point support.
+ * However, it supports custom formats by the means of a format callback.
+ *
+ * @returns number of bytes formatted.
+ * @param   pfnOutput   Output worker.
+ *                      Called in two ways. Normally with a string and its length.
+ *                      For termination, it's called with NULL for string, 0 for length.
+ * @param   pvArgOutput Argument to the output worker.
+ * @param   pfnFormat   Custom format worker.
+ * @param   pvArgFormat Argument to the format worker.
+ * @param   pszFormat   Pointer to the format string, @see pg_rt_str_format.
+ * @param   ...         Argument list.
+ */
+RTDECL(size_t) RTStrFormat(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, PFNSTRFORMAT pfnFormat, void *pvArgFormat,
+                           const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(5, 6);
+
+/**
+ * Formats an integer number according to the parameters.
+ *
+ * @returns Length of the formatted number.
+ * @param   psz             Pointer to output string buffer of sufficient size.
+ * @param   u64Value        Value to format.
+ * @param   uiBase          Number representation base.
+ * @param   cchWidth        Width.
+ * @param   cchPrecision    Precision.
+ * @param   fFlags          Flags, RTSTR_F_XXX.
+ */
+RTDECL(int) RTStrFormatNumber(char *psz, uint64_t u64Value, unsigned int uiBase, signed int cchWidth, signed int cchPrecision,
+                              unsigned int fFlags);
+
+/**
+ * Formats an unsigned 8-bit number.
+ *
+ * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW.
+ * @param   pszBuf          The output buffer.
+ * @param   cbBuf           The size of the output buffer.
+ * @param   u8Value         The value to format.
+ * @param   uiBase          Number representation base.
+ * @param   cchWidth        Width.
+ * @param   cchPrecision    Precision.
+ * @param   fFlags          Flags, RTSTR_F_XXX.
+ */
+RTDECL(ssize_t) RTStrFormatU8(char *pszBuf, size_t cbBuf, uint8_t u8Value, unsigned int uiBase,
+                              signed int cchWidth, signed int cchPrecision, uint32_t fFlags);
+
+/**
+ * Formats an unsigned 16-bit number.
+ *
+ * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW.
+ * @param   pszBuf          The output buffer.
+ * @param   cbBuf           The size of the output buffer.
+ * @param   u16Value        The value to format.
+ * @param   uiBase          Number representation base.
+ * @param   cchWidth        Width.
+ * @param   cchPrecision    Precision.
+ * @param   fFlags          Flags, RTSTR_F_XXX.
+ */
+RTDECL(ssize_t) RTStrFormatU16(char *pszBuf, size_t cbBuf, uint16_t u16Value, unsigned int uiBase,
+                               signed int cchWidth, signed int cchPrecision, uint32_t fFlags);
+
+/**
+ * Formats an unsigned 32-bit number.
+ *
+ * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW.
+ * @param   pszBuf          The output buffer.
+ * @param   cbBuf           The size of the output buffer.
+ * @param   u32Value        The value to format.
+ * @param   uiBase          Number representation base.
+ * @param   cchWidth        Width.
+ * @param   cchPrecision    Precision.
+ * @param   fFlags          Flags, RTSTR_F_XXX.
+ */
+RTDECL(ssize_t) RTStrFormatU32(char *pszBuf, size_t cbBuf, uint32_t u32Value, unsigned int uiBase,
+                               signed int cchWidth, signed int cchPrecision, uint32_t fFlags);
+
+/**
+ * Formats an unsigned 64-bit number.
+ *
+ * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW.
+ * @param   pszBuf          The output buffer.
+ * @param   cbBuf           The size of the output buffer.
+ * @param   u64Value        The value to format.
+ * @param   uiBase          Number representation base.
+ * @param   cchWidth        Width.
+ * @param   cchPrecision    Precision.
+ * @param   fFlags          Flags, RTSTR_F_XXX.
+ */
+RTDECL(ssize_t) RTStrFormatU64(char *pszBuf, size_t cbBuf, uint64_t u64Value, unsigned int uiBase,
+                               signed int cchWidth, signed int cchPrecision, uint32_t fFlags);
+
+/**
+ * Formats an unsigned 128-bit number.
+ *
+ * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW.
+ * @param   pszBuf          The output buffer.
+ * @param   cbBuf           The size of the output buffer.
+ * @param   pu128Value      The value to format.
+ * @param   uiBase          Number representation base.
+ * @param   cchWidth        Width.
+ * @param   cchPrecision    Precision.
+ * @param   fFlags          Flags, RTSTR_F_XXX.
+ * @remarks The current implementation is limited to base 16 and doesn't do
+ *          width or precision and probably ignores few flags too.
+ */
+RTDECL(ssize_t) RTStrFormatU128(char *pszBuf, size_t cbBuf, PCRTUINT128U pu128Value, unsigned int uiBase,
+                                signed int cchWidth, signed int cchPrecision, uint32_t fFlags);
+
+/**
+ * Formats an unsigned 256-bit number.
+ *
+ * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW.
+ * @param   pszBuf          The output buffer.
+ * @param   cbBuf           The size of the output buffer.
+ * @param   pu256Value      The value to format.
+ * @param   uiBase          Number representation base.
+ * @param   cchWidth        Width.
+ * @param   cchPrecision    Precision.
+ * @param   fFlags          Flags, RTSTR_F_XXX.
+ * @remarks The current implementation is limited to base 16 and doesn't do
+ *          width or precision and probably ignores few flags too.
+ */
+RTDECL(ssize_t) RTStrFormatU256(char *pszBuf, size_t cbBuf, PCRTUINT256U pu256Value, unsigned int uiBase,
+                                signed int cchWidth, signed int cchPrecision, uint32_t fFlags);
+
+/**
+ * Formats an unsigned 512-bit number.
+ *
+ * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW.
+ * @param   pszBuf          The output buffer.
+ * @param   cbBuf           The size of the output buffer.
+ * @param   pu512Value      The value to format.
+ * @param   uiBase          Number representation base.
+ * @param   cchWidth        Width.
+ * @param   cchPrecision    Precision.
+ * @param   fFlags          Flags, RTSTR_F_XXX.
+ * @remarks The current implementation is limited to base 16 and doesn't do
+ *          width or precision and probably ignores few flags too.
+ */
+RTDECL(ssize_t) RTStrFormatU512(char *pszBuf, size_t cbBuf, PCRTUINT512U pu512Value, unsigned int uiBase,
+                                signed int cchWidth, signed int cchPrecision, uint32_t fFlags);
+
+
+/**
+ * Formats an 80-bit extended floating point number.
+ *
+ * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW.
+ * @param   pszBuf          The output buffer.
+ * @param   cbBuf           The size of the output buffer.
+ * @param   pr80Value       The value to format.
+ * @param   cchWidth        Width.
+ * @param   cchPrecision    Precision.
+ * @param   fFlags          Flags, RTSTR_F_XXX.
+ */
+RTDECL(ssize_t) RTStrFormatR80(char *pszBuf, size_t cbBuf, PCRTFLOAT80U pr80Value, signed int cchWidth,
+                               signed int cchPrecision, uint32_t fFlags);
+
+/**
+ * Formats an 80-bit extended floating point number, version 2.
+ *
+ * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW.
+ * @param   pszBuf          The output buffer.
+ * @param   cbBuf           The size of the output buffer.
+ * @param   pr80Value       The value to format.
+ * @param   cchWidth        Width.
+ * @param   cchPrecision    Precision.
+ * @param   fFlags          Flags, RTSTR_F_XXX.
+ */
+RTDECL(ssize_t) RTStrFormatR80u2(char *pszBuf, size_t cbBuf, PCRTFLOAT80U2 pr80Value, signed int cchWidth,
+                                 signed int cchPrecision, uint32_t fFlags);
+
+
+
+/**
+ * Callback for formatting a type.
+ *
+ * This is registered using the RTStrFormatTypeRegister function and will
+ * be called during string formatting to handle the specified %R[type].
+ * The argument for this format type is assumed to be a pointer and it's
+ * passed in the @a pvValue argument.
+ *
+ * @returns Length of the formatted output.
+ * @param   pfnOutput       Output worker.
+ * @param   pvArgOutput     Argument to the output worker.
+ * @param   pszType         The type name.
+ * @param   pvValue         The argument value.
+ * @param   cchWidth        Width.
+ * @param   cchPrecision    Precision.
+ * @param   fFlags          Flags (NTFS_*).
+ * @param   pvUser          The user argument.
+ */
+typedef DECLCALLBACK(size_t) FNRTSTRFORMATTYPE(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
+                                               const char *pszType, void const *pvValue,
+                                               int cchWidth, int cchPrecision, unsigned fFlags,
+                                               void *pvUser);
+/** Pointer to a FNRTSTRFORMATTYPE. */
+typedef FNRTSTRFORMATTYPE *PFNRTSTRFORMATTYPE;
+
+
+/**
+ * Register a format handler for a type.
+ *
+ * The format handler is used to handle '%R[type]' format types, where the argument
+ * in the vector is a pointer value (a bit restrictive, but keeps it simple).
+ *
+ * The caller must ensure that no other thread will be making use of any of
+ * the dynamic formatting type facilities simultaneously with this call.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_ALREADY_EXISTS if the type has already been registered.
+ * @retval  VERR_TOO_MANY_OPEN_FILES if all the type slots has been allocated already.
+ *
+ * @param   pszType         The type name.
+ * @param   pfnHandler      The handler address. See FNRTSTRFORMATTYPE for details.
+ * @param   pvUser          The user argument to pass to the handler. See RTStrFormatTypeSetUser
+ *                          for how to update this later.
+ */
+RTDECL(int) RTStrFormatTypeRegister(const char *pszType, PFNRTSTRFORMATTYPE pfnHandler, void *pvUser);
+
+/**
+ * Deregisters a format type.
+ *
+ * The caller must ensure that no other thread will be making use of any of
+ * the dynamic formatting type facilities simultaneously with this call.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_FILE_NOT_FOUND if not found.
+ *
+ * @param   pszType     The type to deregister.
+ */
+RTDECL(int) RTStrFormatTypeDeregister(const char *pszType);
+
+/**
+ * Sets the user argument for a type.
+ *
+ * This can be used if a user argument needs relocating in GC.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_FILE_NOT_FOUND if not found.
+ *
+ * @param   pszType     The type to update.
+ * @param   pvUser      The new user argument value.
+ */
+RTDECL(int) RTStrFormatTypeSetUser(const char *pszType, void *pvUser);
+
+
+/**
+ * String printf.
+ *
+ * @returns The length of the returned string (in pszBuffer) excluding the
+ *          terminator.
+ * @param   pszBuffer   Output buffer.
+ * @param   cchBuffer   Size of the output buffer.
+ * @param   pszFormat   Pointer to the format string, @see pg_rt_str_format.
+ * @param   args        The format argument.
+ */
+RTDECL(size_t) RTStrPrintfV(char *pszBuffer, size_t cchBuffer, const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * String printf.
+ *
+ * @returns The length of the returned string (in pszBuffer) excluding the
+ *          terminator.
+ * @param   pszBuffer   Output buffer.
+ * @param   cchBuffer   Size of the output buffer.
+ * @param   pszFormat   Pointer to the format string, @see pg_rt_str_format.
+ * @param   ...         The format argument.
+ */
+RTDECL(size_t) RTStrPrintf(char *pszBuffer, size_t cchBuffer, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+
+/**
+ * String printf with custom formatting.
+ *
+ * @returns The length of the returned string (in pszBuffer) excluding the
+ *          terminator.
+ * @param   pfnFormat   Pointer to handler function for the custom formats.
+ * @param   pvArg       Argument to the pfnFormat function.
+ * @param   pszBuffer   Output buffer.
+ * @param   cchBuffer   Size of the output buffer.
+ * @param   pszFormat   Pointer to the format string, @see pg_rt_str_format.
+ * @param   args        The format argument.
+ */
+RTDECL(size_t) RTStrPrintfExV(PFNSTRFORMAT pfnFormat, void *pvArg, char *pszBuffer, size_t cchBuffer,
+                              const char *pszFormat, va_list args)  RT_IPRT_FORMAT_ATTR(5, 0);
+
+/**
+ * String printf with custom formatting.
+ *
+ * @returns The length of the returned string (in pszBuffer) excluding the
+ *          terminator.
+ * @param   pfnFormat   Pointer to handler function for the custom formats.
+ * @param   pvArg       Argument to the pfnFormat function.
+ * @param   pszBuffer   Output buffer.
+ * @param   cchBuffer   Size of the output buffer.
+ * @param   pszFormat   Pointer to the format string, @see pg_rt_str_format.
+ * @param   ...         The format argument.
+ */
+RTDECL(size_t) RTStrPrintfEx(PFNSTRFORMAT pfnFormat, void *pvArg, char *pszBuffer, size_t cchBuffer,
+                             const char *pszFormat, ...)  RT_IPRT_FORMAT_ATTR(5, 6);
+
+
+/**
+ * Allocating string printf (default tag).
+ *
+ * @returns The length of the string in the returned *ppszBuffer excluding the
+ *          terminator.
+ * @returns -1 on failure.
+ * @param   ppszBuffer  Where to store the pointer to the allocated output buffer.
+ *                      The buffer should be freed using RTStrFree().
+ *                      On failure *ppszBuffer will be set to NULL.
+ * @param   pszFormat   Pointer to the format string, @see pg_rt_str_format.
+ * @param   args        The format argument.
+ */
+#define RTStrAPrintfV(ppszBuffer, pszFormat, args)      RTStrAPrintfVTag((ppszBuffer), (pszFormat), (args), RTSTR_TAG)
+
+/**
+ * Allocating string printf (custom tag).
+ *
+ * @returns The length of the string in the returned *ppszBuffer excluding the
+ *          terminator.
+ * @returns -1 on failure.
+ * @param   ppszBuffer  Where to store the pointer to the allocated output buffer.
+ *                      The buffer should be freed using RTStrFree().
+ *                      On failure *ppszBuffer will be set to NULL.
+ * @param   pszFormat   Pointer to the format string, @see pg_rt_str_format.
+ * @param   args        The format argument.
+ * @param   pszTag      Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTStrAPrintfVTag(char **ppszBuffer, const char *pszFormat, va_list args, const char *pszTag) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * Allocating string printf.
+ *
+ * @returns The length of the string in the returned *ppszBuffer excluding the
+ *          terminator.
+ * @returns -1 on failure.
+ * @param   ppszBuffer  Where to store the pointer to the allocated output buffer.
+ *                      The buffer should be freed using RTStrFree().
+ *                      On failure *ppszBuffer will be set to NULL.
+ * @param   pszFormat   Pointer to the format string, @see pg_rt_str_format.
+ * @param   ...         The format argument.
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(2, 3) RTStrAPrintf(char **ppszBuffer, const char *pszFormat, ...)
+{
+    int     cbRet;
+    va_list va;
+    va_start(va, pszFormat);
+    cbRet = RTStrAPrintfVTag(ppszBuffer, pszFormat, va, RTSTR_TAG);
+    va_end(va);
+    return cbRet;
+}
+
+/**
+ * Allocating string printf (custom tag).
+ *
+ * @returns The length of the string in the returned *ppszBuffer excluding the
+ *          terminator.
+ * @returns -1 on failure.
+ * @param   ppszBuffer  Where to store the pointer to the allocated output buffer.
+ *                      The buffer should be freed using RTStrFree().
+ *                      On failure *ppszBuffer will be set to NULL.
+ * @param   pszTag      Allocation tag used for statistics and such.
+ * @param   pszFormat   Pointer to the format string, @see pg_rt_str_format.
+ * @param   ...         The format argument.
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(3, 4) RTStrAPrintfTag(char **ppszBuffer, const char *pszTag, const char *pszFormat, ...)
+{
+    int     cbRet;
+    va_list va;
+    va_start(va, pszFormat);
+    cbRet = RTStrAPrintfVTag(ppszBuffer, pszFormat, va, pszTag);
+    va_end(va);
+    return cbRet;
+}
+
+/**
+ * Allocating string printf, version 2.
+ *
+ * @returns Formatted string. Use RTStrFree() to free it. NULL when out of
+ *          memory.
+ * @param   pszFormat   Pointer to the format string, @see pg_rt_str_format.
+ * @param   args        The format argument.
+ */
+#define RTStrAPrintf2V(pszFormat, args)     RTStrAPrintf2VTag((pszFormat), (args), RTSTR_TAG)
+
+/**
+ * Allocating string printf, version 2.
+ *
+ * @returns Formatted string. Use RTStrFree() to free it. NULL when out of
+ *          memory.
+ * @param   pszFormat   Pointer to the format string, @see pg_rt_str_format.
+ * @param   args        The format argument.
+ * @param   pszTag      Allocation tag used for statistics and such.
+ */
+RTDECL(char *) RTStrAPrintf2VTag(const char *pszFormat, va_list args, const char *pszTag) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Allocating string printf, version 2 (default tag).
+ *
+ * @returns Formatted string. Use RTStrFree() to free it. NULL when out of
+ *          memory.
+ * @param   pszFormat   Pointer to the format string, @see pg_rt_str_format.
+ * @param   ...         The format argument.
+ */
+DECLINLINE(char *) RT_IPRT_FORMAT_ATTR(1, 2) RTStrAPrintf2(const char *pszFormat, ...)
+{
+    char   *pszRet;
+    va_list va;
+    va_start(va, pszFormat);
+    pszRet = RTStrAPrintf2VTag(pszFormat, va, RTSTR_TAG);
+    va_end(va);
+    return pszRet;
+}
+
+/**
+ * Allocating string printf, version 2 (custom tag).
+ *
+ * @returns Formatted string. Use RTStrFree() to free it. NULL when out of
+ *          memory.
+ * @param   pszTag      Allocation tag used for statistics and such.
+ * @param   pszFormat   Pointer to the format string, @see pg_rt_str_format.
+ * @param   ...         The format argument.
+ */
+DECLINLINE(char *) RT_IPRT_FORMAT_ATTR(2, 3) RTStrAPrintf2Tag(const char *pszTag, const char *pszFormat, ...)
+{
+    char   *pszRet;
+    va_list va;
+    va_start(va, pszFormat);
+    pszRet = RTStrAPrintf2VTag(pszFormat, va, pszTag);
+    va_end(va);
+    return pszRet;
+}
+
+/**
+ * Strips blankspaces from both ends of the string.
+ *
+ * @returns Pointer to first non-blank char in the string.
+ * @param   psz     The string to strip.
+ */
+RTDECL(char *) RTStrStrip(char *psz);
+
+/**
+ * Strips blankspaces from the start of the string.
+ *
+ * @returns Pointer to first non-blank char in the string.
+ * @param   psz     The string to strip.
+ */
+RTDECL(char *) RTStrStripL(const char *psz);
+
+/**
+ * Strips blankspaces from the end of the string.
+ *
+ * @returns psz.
+ * @param   psz     The string to strip.
+ */
+RTDECL(char *) RTStrStripR(char *psz);
+
+/**
+ * String copy with overflow handling.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the destination buffer is too small.  The
+ *          buffer will contain as much of the string as it can hold, fully
+ *          terminated.
+ *
+ * @param   pszDst              The destination buffer.
+ * @param   cbDst               The size of the destination buffer (in bytes).
+ * @param   pszSrc              The source string.  NULL is not OK.
+ */
+RTDECL(int) RTStrCopy(char *pszDst, size_t cbDst, const char *pszSrc);
+
+/**
+ * String copy with overflow handling.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the destination buffer is too small.  The
+ *          buffer will contain as much of the string as it can hold, fully
+ *          terminated.
+ *
+ * @param   pszDst              The destination buffer.
+ * @param   cbDst               The size of the destination buffer (in bytes).
+ * @param   pszSrc              The source string.  NULL is not OK.
+ * @param   cchSrcMax           The maximum number of chars (not code points) to
+ *                              copy from the source string, not counting the
+ *                              terminator as usual.
+ */
+RTDECL(int) RTStrCopyEx(char *pszDst, size_t cbDst, const char *pszSrc, size_t cchSrcMax);
+
+/**
+ * String copy with overflow handling and buffer advancing.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the destination buffer is too small.  The
+ *          buffer will contain as much of the string as it can hold, fully
+ *          terminated.
+ *
+ * @param   ppszDst             Pointer to the destination buffer pointer.
+ *                              This will be advanced to the end of the copied
+ *                              bytes (points at the terminator).  This is also
+ *                              updated on overflow.
+ * @param   pcbDst              Pointer to the destination buffer size
+ *                              variable.  This will be updated in accord with
+ *                              the buffer pointer.
+ * @param   pszSrc              The source string.  NULL is not OK.
+ */
+RTDECL(int) RTStrCopyP(char **ppszDst, size_t *pcbDst, const char *pszSrc);
+
+/**
+ * String copy with overflow handling.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the destination buffer is too small.  The
+ *          buffer will contain as much of the string as it can hold, fully
+ *          terminated.
+ *
+ * @param   ppszDst             Pointer to the destination buffer pointer.
+ *                              This will be advanced to the end of the copied
+ *                              bytes (points at the terminator).  This is also
+ *                              updated on overflow.
+ * @param   pcbDst              Pointer to the destination buffer size
+ *                              variable.  This will be updated in accord with
+ *                              the buffer pointer.
+ * @param   pszSrc              The source string.  NULL is not OK.
+ * @param   cchSrcMax           The maximum number of chars (not code points) to
+ *                              copy from the source string, not counting the
+ *                              terminator as usual.
+ */
+RTDECL(int) RTStrCopyPEx(char **ppszDst, size_t *pcbDst, const char *pszSrc, size_t cchSrcMax);
+
+/**
+ * String concatenation with overflow handling.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the destination buffer is too small.  The
+ *          buffer will contain as much of the string as it can hold, fully
+ *          terminated.
+ *
+ * @param   pszDst              The destination buffer.
+ * @param   cbDst               The size of the destination buffer (in bytes).
+ * @param   pszSrc              The source string.  NULL is not OK.
+ */
+RTDECL(int) RTStrCat(char *pszDst, size_t cbDst, const char *pszSrc);
+
+/**
+ * String concatenation with overflow handling.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the destination buffer is too small.  The
+ *          buffer will contain as much of the string as it can hold, fully
+ *          terminated.
+ *
+ * @param   pszDst              The destination buffer.
+ * @param   cbDst               The size of the destination buffer (in bytes).
+ * @param   pszSrc              The source string.  NULL is not OK.
+ * @param   cchSrcMax           The maximum number of chars (not code points) to
+ *                              copy from the source string, not counting the
+ *                              terminator as usual.
+ */
+RTDECL(int) RTStrCatEx(char *pszDst, size_t cbDst, const char *pszSrc, size_t cchSrcMax);
+
+/**
+ * String concatenation with overflow handling.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the destination buffer is too small.  The
+ *          buffer will contain as much of the string as it can hold, fully
+ *          terminated.
+ *
+ * @param   ppszDst             Pointer to the destination buffer pointer.
+ *                              This will be advanced to the end of the copied
+ *                              bytes (points at the terminator).  This is also
+ *                              updated on overflow.
+ * @param   pcbDst              Pointer to the destination buffer size
+ *                              variable.  This will be updated in accord with
+ *                              the buffer pointer.
+ * @param   pszSrc              The source string.  NULL is not OK.
+ */
+RTDECL(int) RTStrCatP(char **ppszDst, size_t *pcbDst, const char *pszSrc);
+
+/**
+ * String concatenation with overflow handling and buffer advancing.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the destination buffer is too small.  The
+ *          buffer will contain as much of the string as it can hold, fully
+ *          terminated.
+ *
+ * @param   ppszDst             Pointer to the destination buffer pointer.
+ *                              This will be advanced to the end of the copied
+ *                              bytes (points at the terminator).  This is also
+ *                              updated on overflow.
+ * @param   pcbDst              Pointer to the destination buffer size
+ *                              variable.  This will be updated in accord with
+ *                              the buffer pointer.
+ * @param   pszSrc              The source string.  NULL is not OK.
+ * @param   cchSrcMax           The maximum number of chars (not code points) to
+ *                              copy from the source string, not counting the
+ *                              terminator as usual.
+ */
+RTDECL(int) RTStrCatPEx(char **ppszDst, size_t *pcbDst, const char *pszSrc, size_t cchSrcMax);
+
+/**
+ * Performs a case sensitive string compare between two UTF-8 strings.
+ *
+ * Encoding errors are ignored by the current implementation. So, the only
+ * difference between this and the CRT strcmp function is the handling of
+ * NULL arguments.
+ *
+ * @returns < 0 if the first string less than the second string.
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ * @param   psz1        First UTF-8 string. Null is allowed.
+ * @param   psz2        Second UTF-8 string. Null is allowed.
+ */
+RTDECL(int) RTStrCmp(const char *psz1, const char *psz2);
+
+/**
+ * Performs a case sensitive string compare between two UTF-8 strings, given
+ * a maximum string length.
+ *
+ * Encoding errors are ignored by the current implementation. So, the only
+ * difference between this and the CRT strncmp function is the handling of
+ * NULL arguments.
+ *
+ * @returns < 0 if the first string less than the second string.
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ * @param   psz1        First UTF-8 string. Null is allowed.
+ * @param   psz2        Second UTF-8 string. Null is allowed.
+ * @param   cchMax      The maximum string length
+ */
+RTDECL(int) RTStrNCmp(const char *psz1, const char *psz2, size_t cchMax);
+
+/**
+ * Performs a case insensitive string compare between two UTF-8 strings.
+ *
+ * This is a simplified compare, as only the simplified lower/upper case folding
+ * specified by the unicode specs are used. It does not consider character pairs
+ * as they are used in some languages, just simple upper & lower case compares.
+ *
+ * The result is the difference between the mismatching codepoints after they
+ * both have been lower cased.
+ *
+ * If the string encoding is invalid the function will assert (strict builds)
+ * and use RTStrCmp for the remainder of the string.
+ *
+ * @returns < 0 if the first string less than the second string.
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ * @param   psz1        First UTF-8 string. Null is allowed.
+ * @param   psz2        Second UTF-8 string. Null is allowed.
+ */
+RTDECL(int) RTStrICmp(const char *psz1, const char *psz2);
+
+/**
+ * Performs a case insensitive string compare between two UTF-8 strings, given a
+ * maximum string length.
+ *
+ * This is a simplified compare, as only the simplified lower/upper case folding
+ * specified by the unicode specs are used. It does not consider character pairs
+ * as they are used in some languages, just simple upper & lower case compares.
+ *
+ * The result is the difference between the mismatching codepoints after they
+ * both have been lower cased.
+ *
+ * If the string encoding is invalid the function will assert (strict builds)
+ * and use RTStrCmp for the remainder of the string.
+ *
+ * @returns < 0 if the first string less than the second string.
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ * @param   psz1        First UTF-8 string. Null is allowed.
+ * @param   psz2        Second UTF-8 string. Null is allowed.
+ * @param   cchMax      Maximum string length
+ */
+RTDECL(int) RTStrNICmp(const char *psz1, const char *psz2, size_t cchMax);
+
+/**
+ * Performs a case insensitive string compare between a UTF-8 string and a 7-bit
+ * ASCII string.
+ *
+ * This is potentially faster than RTStrICmp and drags in less dependencies.  It
+ * is really handy for hardcoded inputs.
+ *
+ * If the string encoding is invalid the function will assert (strict builds)
+ * and use RTStrCmp for the remainder of the string.
+ *
+ * @returns < 0 if the first string less than the second string.
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ * @param   psz1        First UTF-8 string. Null is allowed.
+ * @param   psz2        Second string, 7-bit ASCII. Null is allowed.
+ * @sa      RTUtf16ICmpAscii
+ */
+RTDECL(int) RTStrICmpAscii(const char *psz1, const char *psz2);
+
+/**
+ * Checks whether @a pszString starts with @a pszStart.
+ *
+ * @returns true / false.
+ * @param   pszString   The string to check.
+ * @param   pszStart    The start string to check for.
+ */
+RTDECL(int) RTStrStartsWith(const char *pszString, const char *pszStart);
+
+/**
+ * Checks whether @a pszString starts with @a pszStart, case insensitive.
+ *
+ * @returns true / false.
+ * @param   pszString   The string to check.
+ * @param   pszStart    The start string to check for.
+ */
+RTDECL(int) RTStrIStartsWith(const char *pszString, const char *pszStart);
+
+/**
+ * Locates a case sensitive substring.
+ *
+ * If any of the two strings are NULL, then NULL is returned. If the needle is
+ * an empty string, then the haystack is returned (i.e. matches anything).
+ *
+ * @returns Pointer to the first occurrence of the substring if found, NULL if
+ *          not.
+ *
+ * @param   pszHaystack The string to search.
+ * @param   pszNeedle   The substring to search for.
+ *
+ * @remarks The difference between this and strstr is the handling of NULL
+ *          pointers.
+ */
+RTDECL(char *) RTStrStr(const char *pszHaystack, const char *pszNeedle);
+
+/**
+ * Locates a case insensitive substring.
+ *
+ * If any of the two strings are NULL, then NULL is returned. If the needle is
+ * an empty string, then the haystack is returned (i.e. matches anything).
+ *
+ * @returns Pointer to the first occurrence of the substring if found, NULL if
+ *          not.
+ *
+ * @param   pszHaystack The string to search.
+ * @param   pszNeedle   The substring to search for.
+ *
+ */
+RTDECL(char *) RTStrIStr(const char *pszHaystack, const char *pszNeedle);
+
+/**
+ * Converts the string to lower case.
+ *
+ * @returns Pointer to the converted string.
+ * @param   psz     The string to convert.
+ */
+RTDECL(char *) RTStrToLower(char *psz);
+
+/**
+ * Converts the string to upper case.
+ *
+ * @returns Pointer to the converted string.
+ * @param   psz     The string to convert.
+ */
+RTDECL(char *) RTStrToUpper(char *psz);
+
+/**
+ * Checks if the string is case foldable, i.e. whether it would change if
+ * subject to RTStrToLower or RTStrToUpper.
+ *
+ * @returns true / false
+ * @param   psz     The string in question.
+ */
+RTDECL(bool) RTStrIsCaseFoldable(const char *psz);
+
+/**
+ * Checks if the string is upper cased (no lower case chars in it).
+ *
+ * @returns true / false
+ * @param   psz     The string in question.
+ */
+RTDECL(bool) RTStrIsUpperCased(const char *psz);
+
+/**
+ * Checks if the string is lower cased (no upper case chars in it).
+ *
+ * @returns true / false
+ * @param   psz     The string in question.
+ */
+RTDECL(bool) RTStrIsLowerCased(const char *psz);
+
+/**
+ * Find the length of a zero-terminated byte string, given
+ * a max string length.
+ *
+ * See also RTStrNLenEx.
+ *
+ * @returns The string length or cbMax. The returned length does not include
+ *          the zero terminator if it was found.
+ *
+ * @param   pszString   The string.
+ * @param   cchMax      The max string length.
+ */
+RTDECL(size_t) RTStrNLen(const char *pszString, size_t cchMax);
+
+/**
+ * Find the length of a zero-terminated byte string, given
+ * a max string length.
+ *
+ * See also RTStrNLen.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS if the string has a length less than cchMax.
+ * @retval  VERR_BUFFER_OVERFLOW if the end of the string wasn't found
+ *          before cchMax was reached.
+ *
+ * @param   pszString   The string.
+ * @param   cchMax      The max string length.
+ * @param   pcch        Where to store the string length excluding the
+ *                      terminator. This is set to cchMax if the terminator
+ *                      isn't found.
+ */
+RTDECL(int) RTStrNLenEx(const char *pszString, size_t cchMax, size_t *pcch);
+
+RT_C_DECLS_END
+
+/** The maximum size argument of a memchr call. */
+#define RTSTR_MEMCHR_MAX            ((~(size_t)0 >> 1) - 15)
+
+/**
+ * Find the zero terminator in a string with a limited length.
+ *
+ * @returns Pointer to the zero terminator.
+ * @returns NULL if the zero terminator was not found.
+ *
+ * @param   pszString   The string.
+ * @param   cchMax      The max string length.  RTSTR_MAX is fine.
+ */
+#if defined(__cplusplus) && !defined(DOXYGEN_RUNNING)
+DECLINLINE(char const *) RTStrEnd(char const *pszString, size_t cchMax)
+{
+    /* Avoid potential issues with memchr seen in glibc.
+     * See sysdeps/x86_64/memchr.S in glibc versions older than 2.11 */
+    while (cchMax > RTSTR_MEMCHR_MAX)
+    {
+        char const *pszRet = (char const *)memchr(pszString, '\0', RTSTR_MEMCHR_MAX);
+        if (RT_LIKELY(pszRet))
+            return pszRet;
+        pszString += RTSTR_MEMCHR_MAX;
+        cchMax    -= RTSTR_MEMCHR_MAX;
+    }
+    return (char const *)memchr(pszString, '\0', cchMax);
+}
+
+DECLINLINE(char *) RTStrEnd(char *pszString, size_t cchMax)
+#else
+DECLINLINE(char *) RTStrEnd(const char *pszString, size_t cchMax)
+#endif
+{
+    /* Avoid potential issues with memchr seen in glibc.
+     * See sysdeps/x86_64/memchr.S in glibc versions older than 2.11 */
+    while (cchMax > RTSTR_MEMCHR_MAX)
+    {
+        char *pszRet = (char *)memchr(pszString, '\0', RTSTR_MEMCHR_MAX);
+        if (RT_LIKELY(pszRet))
+            return pszRet;
+        pszString += RTSTR_MEMCHR_MAX;
+        cchMax    -= RTSTR_MEMCHR_MAX;
+    }
+    return (char *)memchr(pszString, '\0', cchMax);
+}
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Finds the offset at which a simple character first occurs in a string.
+ *
+ * @returns The offset of the first occurence or the terminator offset.
+ * @param   pszHaystack The string to search.
+ * @param   chNeedle    The character to search for.
+ */
+DECLINLINE(size_t) RTStrOffCharOrTerm(const char *pszHaystack, char chNeedle)
+{
+    const char *psz = pszHaystack;
+    char ch;
+    while (   (ch = *psz) != chNeedle
+           && ch != '\0')
+        psz++;
+    return psz - pszHaystack;
+}
+
+
+/**
+ * Matches a simple string pattern.
+ *
+ * @returns true if the string matches the pattern, otherwise false.
+ *
+ * @param  pszPattern   The pattern. Special chars are '*' and '?', where the
+ *                      asterisk matches zero or more characters and question
+ *                      mark matches exactly one character.
+ * @param  pszString    The string to match against the pattern.
+ */
+RTDECL(bool) RTStrSimplePatternMatch(const char *pszPattern, const char *pszString);
+
+/**
+ * Matches a simple string pattern, neither which needs to be zero terminated.
+ *
+ * This is identical to RTStrSimplePatternMatch except that you can optionally
+ * specify the length of both the pattern and the string.  The function will
+ * stop when it hits a string terminator or either of the lengths.
+ *
+ * @returns true if the string matches the pattern, otherwise false.
+ *
+ * @param  pszPattern   The pattern. Special chars are '*' and '?', where the
+ *                      asterisk matches zero or more characters and question
+ *                      mark matches exactly one character.
+ * @param  cchPattern   The pattern length. Pass RTSTR_MAX if you don't know the
+ *                      length and wish to stop at the string terminator.
+ * @param  pszString    The string to match against the pattern.
+ * @param  cchString    The string length. Pass RTSTR_MAX if you don't know the
+ *                      length and wish to match up to the string terminator.
+ */
+RTDECL(bool) RTStrSimplePatternNMatch(const char *pszPattern, size_t cchPattern,
+                                      const char *pszString, size_t cchString);
+
+/**
+ * Matches multiple patterns against a string.
+ *
+ * The patterns are separated by the pipe character (|).
+ *
+ * @returns true if the string matches the pattern, otherwise false.
+ *
+ * @param   pszPatterns The patterns.
+ * @param   cchPatterns The lengths of the patterns to use. Pass RTSTR_MAX to
+ *                      stop at the terminator.
+ * @param   pszString   The string to match against the pattern.
+ * @param   cchString   The string length. Pass RTSTR_MAX stop stop at the
+ *                      terminator.
+ * @param   poffPattern Offset into the patterns string of the patttern that
+ *                      matched. If no match, this will be set to RTSTR_MAX.
+ *                      This is optional, NULL is fine.
+ */
+RTDECL(bool) RTStrSimplePatternMultiMatch(const char *pszPatterns, size_t cchPatterns,
+                                          const char *pszString, size_t cchString,
+                                          size_t *poffPattern);
+
+/**
+ * Compares two version strings RTStrICmp fashion.
+ *
+ * The version string is split up into sections at punctuation, spaces,
+ * underscores, dashes and plus signs.  The sections are then split up into
+ * numeric and string sub-sections.  Finally, the sub-sections are compared
+ * in a numeric or case insesntivie fashion depending on what they are.
+ *
+ * The following strings are considered to be equal: "1.0.0", "1.00.0", "1.0",
+ * "1".  These aren't: "1.0.0r993", "1.0", "1.0r993", "1.0_Beta3", "1.1"
+ *
+ * @returns < 0 if the first string less than the second string.
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ *
+ * @param   pszVer1     First version string to compare.
+ * @param   pszVer2     Second version string to compare first version with.
+ */
+RTDECL(int) RTStrVersionCompare(const char *pszVer1, const char *pszVer2);
+
+
+/** @defgroup rt_str_conv   String To/From Number Conversions
+ * @{ */
+
+/**
+ * Converts a string representation of a number to a 64-bit unsigned number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pu64        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt64Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint64_t *pu64);
+
+/**
+ * Converts a string representation of a number to a 64-bit unsigned number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_TRAILING_CHARS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pu64        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt64Full(const char *pszValue, unsigned uBase, uint64_t *pu64);
+
+/**
+ * Converts a string representation of a number to a 64-bit unsigned number.
+ * The base is guessed.
+ *
+ * @returns 64-bit unsigned number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(uint64_t) RTStrToUInt64(const char *pszValue);
+
+/**
+ * Converts a string representation of a number to a 32-bit unsigned number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pu32        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint32_t *pu32);
+
+/**
+ * Converts a string representation of a number to a 32-bit unsigned number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_TRAILING_CHARS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pu32        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt32Full(const char *pszValue, unsigned uBase, uint32_t *pu32);
+
+/**
+ * Converts a string representation of a number to a 64-bit unsigned number.
+ * The base is guessed.
+ *
+ * @returns 32-bit unsigned number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(uint32_t) RTStrToUInt32(const char *pszValue);
+
+/**
+ * Converts a string representation of a number to a 16-bit unsigned number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pu16        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint16_t *pu16);
+
+/**
+ * Converts a string representation of a number to a 16-bit unsigned number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_TRAILING_CHARS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pu16        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt16Full(const char *pszValue, unsigned uBase, uint16_t *pu16);
+
+/**
+ * Converts a string representation of a number to a 16-bit unsigned number.
+ * The base is guessed.
+ *
+ * @returns 16-bit unsigned number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(uint16_t) RTStrToUInt16(const char *pszValue);
+
+/**
+ * Converts a string representation of a number to a 8-bit unsigned number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pu8         Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint8_t *pu8);
+
+/**
+ * Converts a string representation of a number to a 8-bit unsigned number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_TRAILING_CHARS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pu8         Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt8Full(const char *pszValue, unsigned uBase, uint8_t *pu8);
+
+/**
+ * Converts a string representation of a number to a 8-bit unsigned number.
+ * The base is guessed.
+ *
+ * @returns 8-bit unsigned number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(uint8_t) RTStrToUInt8(const char *pszValue);
+
+/**
+ * Converts a string representation of a number to a 64-bit signed number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pi64        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt64Ex(const char *pszValue, char **ppszNext, unsigned uBase, int64_t *pi64);
+
+/**
+ * Converts a string representation of a number to a 64-bit signed number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_TRAILING_CHARS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pi64        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt64Full(const char *pszValue, unsigned uBase, int64_t *pi64);
+
+/**
+ * Converts a string representation of a number to a 64-bit signed number.
+ * The base is guessed.
+ *
+ * @returns 64-bit signed number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(int64_t) RTStrToInt64(const char *pszValue);
+
+/**
+ * Converts a string representation of a number to a 32-bit signed number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pi32        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, int32_t *pi32);
+
+/**
+ * Converts a string representation of a number to a 32-bit signed number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_TRAILING_CHARS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pi32        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt32Full(const char *pszValue, unsigned uBase, int32_t *pi32);
+
+/**
+ * Converts a string representation of a number to a 32-bit signed number.
+ * The base is guessed.
+ *
+ * @returns 32-bit signed number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(int32_t) RTStrToInt32(const char *pszValue);
+
+/**
+ * Converts a string representation of a number to a 16-bit signed number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pi16        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, int16_t *pi16);
+
+/**
+ * Converts a string representation of a number to a 16-bit signed number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_TRAILING_CHARS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pi16        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt16Full(const char *pszValue, unsigned uBase, int16_t *pi16);
+
+/**
+ * Converts a string representation of a number to a 16-bit signed number.
+ * The base is guessed.
+ *
+ * @returns 16-bit signed number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(int16_t) RTStrToInt16(const char *pszValue);
+
+/**
+ * Converts a string representation of a number to a 8-bit signed number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pi8         Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, int8_t *pi8);
+
+/**
+ * Converts a string representation of a number to a 8-bit signed number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_TRAILING_CHARS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If 0 the function will look for known prefixes before defaulting to 10.
+ * @param   pi8         Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt8Full(const char *pszValue, unsigned uBase, int8_t *pi8);
+
+/**
+ * Converts a string representation of a number to a 8-bit signed number.
+ * The base is guessed.
+ *
+ * @returns 8-bit signed number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(int8_t) RTStrToInt8(const char *pszValue);
+
+/**
+ * Formats a buffer stream as hex bytes.
+ *
+ * The default is no separating spaces or line breaks or anything.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_POINTER if any of the pointers are wrong.
+ * @retval  VERR_BUFFER_OVERFLOW if the buffer is insufficent to hold the bytes.
+ *
+ * @param   pszBuf      Output string buffer.
+ * @param   cbBuf       The size of the output buffer.
+ * @param   pv          Pointer to the bytes to stringify.
+ * @param   cb          The number of bytes to stringify.
+ * @param   fFlags      Combination of RTSTRPRINTHEXBYTES_F_XXX values.
+ * @sa      RTUtf16PrintHexBytes.
+ */
+RTDECL(int) RTStrPrintHexBytes(char *pszBuf, size_t cbBuf, void const *pv, size_t cb, uint32_t fFlags);
+/** @name RTSTRPRINTHEXBYTES_F_XXX - flags for RTStrPrintHexBytes and RTUtf16PritnHexBytes.
+ * @{ */
+/** Upper case hex digits, the default is lower case. */
+#define RTSTRPRINTHEXBYTES_F_UPPER      RT_BIT(0)
+/** Add a space between each group. */
+#define RTSTRPRINTHEXBYTES_F_SEP_SPACE  RT_BIT(1)
+/** Add a colon between each group. */
+#define RTSTRPRINTHEXBYTES_F_SEP_COLON  RT_BIT(2)
+/** @} */
+
+/**
+ * Converts a string of hex bytes back into binary data.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_POINTER if any of the pointers are wrong.
+ * @retval  VERR_BUFFER_OVERFLOW if the string contains too many hex bytes.
+ * @retval  VERR_BUFFER_UNDERFLOW if there aren't enough hex bytes to fill up
+ *          the output buffer.
+ * @retval  VERR_UNEVEN_INPUT if the input contains a half byte.
+ * @retval  VERR_NO_DIGITS
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ *
+ * @param   pszHex      The string containing the hex bytes.
+ * @param   pv          Output buffer.
+ * @param   cb          The size of the output buffer.
+ * @param   fFlags      Must be zero, reserved for future use.
+ */
+RTDECL(int) RTStrConvertHexBytes(char const *pszHex, void *pv, size_t cb, uint32_t fFlags);
+
+/** @} */
+
+
+/** @defgroup rt_str_space  Unique String Space
+ * @{
+ */
+
+/** Pointer to a string name space container node core. */
+typedef struct RTSTRSPACECORE *PRTSTRSPACECORE;
+/** Pointer to a pointer to a string name space container node core. */
+typedef PRTSTRSPACECORE *PPRTSTRSPACECORE;
+
+/**
+ * String name space container node core.
+ */
+typedef struct RTSTRSPACECORE
+{
+    /** Hash key. Don't touch. */
+    uint32_t        Key;
+    /** Pointer to the left leaf node. Don't touch. */
+    PRTSTRSPACECORE pLeft;
+    /** Pointer to the left right node. Don't touch. */
+    PRTSTRSPACECORE pRight;
+    /** Pointer to the list of string with the same key. Don't touch. */
+    PRTSTRSPACECORE pList;
+    /** Height of this tree: max(heigth(left), heigth(right)) + 1. Don't touch */
+    unsigned char   uchHeight;
+    /** The string length. Read only! */
+    size_t          cchString;
+    /** Pointer to the string. Read only! */
+    const char     *pszString;
+} RTSTRSPACECORE;
+
+/** String space. (Initialize with NULL.) */
+typedef PRTSTRSPACECORE     RTSTRSPACE;
+/** Pointer to a string space. */
+typedef PPRTSTRSPACECORE    PRTSTRSPACE;
+
+
+/**
+ * Inserts a string into a unique string space.
+ *
+ * @returns true on success.
+ * @returns false if the string collided with an existing string.
+ * @param   pStrSpace       The space to insert it into.
+ * @param   pStr            The string node.
+ */
+RTDECL(bool) RTStrSpaceInsert(PRTSTRSPACE pStrSpace, PRTSTRSPACECORE pStr);
+
+/**
+ * Removes a string from a unique string space.
+ *
+ * @returns Pointer to the removed string node.
+ * @returns NULL if the string was not found in the string space.
+ * @param   pStrSpace       The space to remove it from.
+ * @param   pszString       The string to remove.
+ */
+RTDECL(PRTSTRSPACECORE) RTStrSpaceRemove(PRTSTRSPACE pStrSpace, const char *pszString);
+
+/**
+ * Gets a string from a unique string space.
+ *
+ * @returns Pointer to the string node.
+ * @returns NULL if the string was not found in the string space.
+ * @param   pStrSpace       The space to get it from.
+ * @param   pszString       The string to get.
+ */
+RTDECL(PRTSTRSPACECORE) RTStrSpaceGet(PRTSTRSPACE pStrSpace, const char *pszString);
+
+/**
+ * Gets a string from a unique string space.
+ *
+ * @returns Pointer to the string node.
+ * @returns NULL if the string was not found in the string space.
+ * @param   pStrSpace       The space to get it from.
+ * @param   pszString       The string to get.
+ * @param   cchMax          The max string length to evaluate.  Passing
+ *                          RTSTR_MAX is ok and makes it behave just like
+ *                          RTStrSpaceGet.
+ */
+RTDECL(PRTSTRSPACECORE) RTStrSpaceGetN(PRTSTRSPACE pStrSpace, const char *pszString, size_t cchMax);
+
+/**
+ * Callback function for RTStrSpaceEnumerate() and RTStrSpaceDestroy().
+ *
+ * @returns 0 on continue.
+ * @returns Non-zero to aborts the operation.
+ * @param   pStr        The string node
+ * @param   pvUser      The user specified argument.
+ */
+typedef DECLCALLBACK(int)   FNRTSTRSPACECALLBACK(PRTSTRSPACECORE pStr, void *pvUser);
+/** Pointer to callback function for RTStrSpaceEnumerate() and RTStrSpaceDestroy(). */
+typedef FNRTSTRSPACECALLBACK *PFNRTSTRSPACECALLBACK;
+
+/**
+ * Destroys the string space.
+ *
+ * The caller supplies a callback which will be called for each of the string
+ * nodes in for freeing their memory and other resources.
+ *
+ * @returns 0 or what ever non-zero return value pfnCallback returned
+ *          when aborting the destruction.
+ * @param   pStrSpace       The space to destroy.
+ * @param   pfnCallback     The callback.
+ * @param   pvUser          The user argument.
+ */
+RTDECL(int) RTStrSpaceDestroy(PRTSTRSPACE pStrSpace, PFNRTSTRSPACECALLBACK pfnCallback, void *pvUser);
+
+/**
+ * Enumerates the string space.
+ * The caller supplies a callback which will be called for each of
+ * the string nodes.
+ *
+ * @returns 0 or what ever non-zero return value pfnCallback returned
+ *          when aborting the destruction.
+ * @param   pStrSpace       The space to enumerate.
+ * @param   pfnCallback     The callback.
+ * @param   pvUser          The user argument.
+ */
+RTDECL(int) RTStrSpaceEnumerate(PRTSTRSPACE pStrSpace, PFNRTSTRSPACECALLBACK pfnCallback, void *pvUser);
+
+/** @} */
+
+
+/** @defgroup rt_str_hash       Sting hashing
+ * @{ */
+
+/**
+ * Hashes the given string using algorithm \#1.
+ *
+ * @returns String hash.
+ * @param   pszString       The string to hash.
+ */
+RTDECL(uint32_t)    RTStrHash1(const char *pszString);
+
+/**
+ * Hashes the given string using algorithm \#1.
+ *
+ * @returns String hash.
+ * @param   pszString       The string to hash.
+ * @param   cchString       The max length to hash. Hashing will stop if the
+ *                          terminator character is encountered first. Passing
+ *                          RTSTR_MAX is fine.
+ */
+RTDECL(uint32_t)    RTStrHash1N(const char *pszString, size_t cchString);
+
+/**
+ * Hashes the given strings as if they were concatenated using algorithm \#1.
+ *
+ * @returns String hash.
+ * @param   cPairs          The number of string / length pairs in the
+ *                          ellipsis.
+ * @param   ...             List of string (const char *) and length
+ *                          (size_t) pairs.  Passing RTSTR_MAX as the size is
+ *                          fine.
+ */
+RTDECL(uint32_t)    RTStrHash1ExN(size_t cPairs, ...);
+
+/**
+ * Hashes the given strings as if they were concatenated using algorithm \#1.
+ *
+ * @returns String hash.
+ * @param   cPairs          The number of string / length pairs in the @a va.
+ * @param   va              List of string (const char *) and length
+ *                          (size_t) pairs.  Passing RTSTR_MAX as the size is
+ *                          fine.
+ */
+RTDECL(uint32_t)    RTStrHash1ExNV(size_t cPairs, va_list va);
+
+/** @}  */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/thread.h b/ubuntu/vbox/include/iprt/thread.h
new file mode 100644 (file)
index 0000000..bc0e43d
--- /dev/null
@@ -0,0 +1,943 @@
+/** @file
+ * IPRT - Threads.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_thread_h
+#define ___iprt_thread_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_thread    RTThread - Thread Management
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * The thread state.
+ */
+typedef enum RTTHREADSTATE
+{
+    /** The usual invalid 0 value. */
+    RTTHREADSTATE_INVALID = 0,
+    /** The thread is being initialized. */
+    RTTHREADSTATE_INITIALIZING,
+    /** The thread has terminated */
+    RTTHREADSTATE_TERMINATED,
+    /** Probably running. */
+    RTTHREADSTATE_RUNNING,
+
+    /** Waiting on a critical section. */
+    RTTHREADSTATE_CRITSECT,
+    /** Waiting on a event semaphore. */
+    RTTHREADSTATE_EVENT,
+    /** Waiting on a event multiple wakeup semaphore. */
+    RTTHREADSTATE_EVENT_MULTI,
+    /** Waiting on a fast mutex. */
+    RTTHREADSTATE_FAST_MUTEX,
+    /** Waiting on a mutex. */
+    RTTHREADSTATE_MUTEX,
+    /** Waiting on a read write semaphore, read (shared) access. */
+    RTTHREADSTATE_RW_READ,
+    /** Waiting on a read write semaphore, write (exclusive) access. */
+    RTTHREADSTATE_RW_WRITE,
+    /** The thread is sleeping. */
+    RTTHREADSTATE_SLEEP,
+    /** Waiting on a spin mutex. */
+    RTTHREADSTATE_SPIN_MUTEX,
+    /** End of the thread states. */
+    RTTHREADSTATE_END,
+
+    /** The usual 32-bit size hack. */
+    RTTHREADSTATE_32BIT_HACK = 0x7fffffff
+} RTTHREADSTATE;
+
+/** Checks if a thread state indicates that the thread is sleeping. */
+#define RTTHREAD_IS_SLEEPING(enmState) ((enmState) >= RTTHREADSTATE_CRITSECT)
+
+/**
+ * Thread types.
+ * Besides identifying the purpose of the thread, the thread type is
+ * used to select the scheduling properties.
+ *
+ * The types in are placed in a rough order of ascending priority.
+ */
+typedef enum RTTHREADTYPE
+{
+    /** Invalid type. */
+    RTTHREADTYPE_INVALID = 0,
+    /** Infrequent poller thread.
+     * This type of thread will sleep for the most of the time, and do
+     * infrequent polls on resources at 0.5 sec or higher intervals.
+     */
+    RTTHREADTYPE_INFREQUENT_POLLER,
+    /** Main heavy worker thread.
+     * Thread of this type is driving asynchronous tasks in the Main
+     * API which takes a long time and might involve a bit of CPU. Like
+     * for instance creating a fixed sized VDI.
+     */
+    RTTHREADTYPE_MAIN_HEAVY_WORKER,
+    /** The emulation thread type.
+     * While being a thread with very high workload it still is vital
+     * that it gets scheduled frequently. When possible all other thread
+     * types except DEFAULT and GUI should interrupt this one ASAP when
+     * they become ready.
+     */
+    RTTHREADTYPE_EMULATION,
+    /** The default thread type.
+     * Since it doesn't say much about the purpose of the thread
+     * nothing special is normally done to the scheduling. This type
+     * should be avoided.
+     * The main thread is registered with default type during RTR3Init()
+     * and that's what the default process priority is derived from.
+     */
+    RTTHREADTYPE_DEFAULT,
+    /** The GUI thread type
+     * The GUI normally have a low workload but is frequently scheduled
+     * to handle events. When possible the scheduler should not leave
+     * threads of this kind waiting for too long (~50ms).
+     */
+    RTTHREADTYPE_GUI,
+    /** Main worker thread.
+     * Thread of this type is driving asynchronous tasks in the Main API.
+     * In most cases this means little work an a lot of waiting.
+     */
+    RTTHREADTYPE_MAIN_WORKER,
+    /** VRDP I/O thread.
+     * These threads are I/O threads in the RDP server will hang around
+     * waiting for data, process it and pass it on.
+     */
+    RTTHREADTYPE_VRDP_IO,
+    /** The debugger type.
+     * Threads involved in servicing the debugger. It must remain
+     * responsive even when things are running wild in.
+     */
+    RTTHREADTYPE_DEBUGGER,
+    /** Message pump thread.
+     * Thread pumping messages from one thread/process to another
+     * thread/process. The workload is very small, most of the time
+     * it's blocked waiting for messages to be produced or processed.
+     * This type of thread will be favored after I/O threads.
+     */
+    RTTHREADTYPE_MSG_PUMP,
+    /** The I/O thread type.
+     * Doing I/O means shuffling data, waiting for request to arrive and
+     * for them to complete. The thread should be favored when competing
+     * with any other threads except timer threads.
+     */
+    RTTHREADTYPE_IO,
+    /** The timer thread type.
+     * A timer thread is mostly waiting for the timer to tick
+     * and then perform a little bit of work. Accuracy is important here,
+     * so the thread should be favoured over all threads. If premention can
+     * be configured at thread level, it could be made very short.
+     */
+    RTTHREADTYPE_TIMER,
+    /** Only used for validation. */
+    RTTHREADTYPE_END
+} RTTHREADTYPE;
+
+
+#ifndef IN_RC
+
+/**
+ * Checks if the IPRT thread component has been initialized.
+ *
+ * This is used to avoid calling into RTThread before the runtime has been
+ * initialized.
+ *
+ * @returns @c true if it's initialized, @c false if not.
+ */
+RTDECL(bool) RTThreadIsInitialized(void);
+
+/**
+ * Get the thread handle of the current thread.
+ *
+ * @returns Thread handle.
+ */
+RTDECL(RTTHREAD) RTThreadSelf(void);
+
+/**
+ * Get the native thread handle of the current thread.
+ *
+ * @returns Native thread handle.
+ */
+RTDECL(RTNATIVETHREAD) RTThreadNativeSelf(void);
+
+/**
+ * Millisecond granular sleep function.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns VERR_INTERRUPTED if a signal or other asynchronous stuff happened
+ *          which interrupt the peaceful sleep.
+ * @param   cMillies    Number of milliseconds to sleep.
+ *                      0 milliseconds means yielding the timeslice - deprecated!
+ * @remark  See RTThreadNanoSleep() for sleeping for smaller periods of time.
+ */
+RTDECL(int) RTThreadSleep(RTMSINTERVAL cMillies);
+
+/**
+ * Millisecond granular sleep function, no logger calls.
+ *
+ * Same as RTThreadSleep, except it will never call into the IPRT logger.  It
+ * can therefore safely be used in places where the logger is off limits, like
+ * at termination or init time.  The electric fence heap is one consumer of
+ * this API.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns VERR_INTERRUPTED if a signal or other asynchronous stuff happened
+ *          which interrupt the peaceful sleep.
+ * @param   cMillies    Number of milliseconds to sleep.
+ *                      0 milliseconds means yielding the timeslice - deprecated!
+ */
+RTDECL(int) RTThreadSleepNoLog(RTMSINTERVAL cMillies);
+
+/**
+ * Yields the CPU.
+ *
+ * @returns true if we yielded.
+ * @returns false if it's probable that we didn't yield.
+ */
+RTDECL(bool) RTThreadYield(void);
+
+
+
+/**
+ * Thread function.
+ *
+ * @returns 0 on success.
+ * @param   ThreadSelf  Thread handle to this thread.
+ * @param   pvUser      User argument.
+ */
+typedef DECLCALLBACK(int) FNRTTHREAD(RTTHREAD ThreadSelf, void *pvUser);
+/** Pointer to a FNRTTHREAD(). */
+typedef FNRTTHREAD *PFNRTTHREAD;
+
+/**
+ * Thread creation flags.
+ */
+typedef enum RTTHREADFLAGS
+{
+    /** This flag is used to keep the thread structure around so it can
+     * be waited on after termination.  @sa RTThreadWait and
+     * RTThreadWaitNoResume.  Not required for RTThreadUserWait and friends!
+     */
+    RTTHREADFLAGS_WAITABLE = RT_BIT(0),
+    /** The bit number corresponding to the RTTHREADFLAGS_WAITABLE mask. */
+    RTTHREADFLAGS_WAITABLE_BIT = 0,
+
+    /** Mask of valid flags, use for validation. */
+    RTTHREADFLAGS_MASK = RT_BIT(0)
+} RTTHREADFLAGS;
+
+
+/**
+ * Create a new thread.
+ *
+ * @returns iprt status code.
+ * @param   pThread     Where to store the thread handle to the new thread. (optional)
+ * @param   pfnThread   The thread function.
+ * @param   pvUser      User argument.
+ * @param   cbStack     The size of the stack for the new thread.
+ *                      Use 0 for the default stack size.
+ * @param   enmType     The thread type. Used for deciding scheduling attributes
+ *                      of the thread.
+ * @param   fFlags      Flags of the RTTHREADFLAGS type (ORed together).
+ * @param   pszName     Thread name.
+ *
+ * @remark  When called in Ring-0, this API will create a new kernel thread and not a thread in
+ *          the context of the calling process.
+ */
+RTDECL(int) RTThreadCreate(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack,
+                           RTTHREADTYPE enmType, unsigned fFlags, const char *pszName);
+#ifndef RT_OS_LINUX /* XXX crashes genksyms at least on 32-bit Linux hosts */
+/** @copydoc RTThreadCreate */
+typedef DECLCALLBACKPTR(int, PFNRTTHREADCREATE)(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack,
+                                                RTTHREADTYPE enmType, unsigned fFlags, const char *pszName);
+#endif
+
+
+/**
+ * Create a new thread.
+ *
+ * Same as RTThreadCreate except the name is given in the RTStrPrintfV form.
+ *
+ * @returns iprt status code.
+ * @param   pThread     See RTThreadCreate.
+ * @param   pfnThread   See RTThreadCreate.
+ * @param   pvUser      See RTThreadCreate.
+ * @param   cbStack     See RTThreadCreate.
+ * @param   enmType     See RTThreadCreate.
+ * @param   fFlags      See RTThreadCreate.
+ * @param   pszName     Thread name format.
+ * @param   va          Format arguments.
+ */
+RTDECL(int) RTThreadCreateV(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack,
+                            RTTHREADTYPE enmType, uint32_t fFlags, const char *pszNameFmt, va_list va) RT_IPRT_FORMAT_ATTR(7, 0);
+
+/**
+ * Create a new thread.
+ *
+ * Same as RTThreadCreate except the name is given in the RTStrPrintf form.
+ *
+ * @returns iprt status code.
+ * @param   pThread     See RTThreadCreate.
+ * @param   pfnThread   See RTThreadCreate.
+ * @param   pvUser      See RTThreadCreate.
+ * @param   cbStack     See RTThreadCreate.
+ * @param   enmType     See RTThreadCreate.
+ * @param   fFlags      See RTThreadCreate.
+ * @param   pszName     Thread name format.
+ * @param   ...         Format arguments.
+ */
+RTDECL(int) RTThreadCreateF(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack,
+                            RTTHREADTYPE enmType, uint32_t fFlags, const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR(7, 8);
+
+/**
+ * Gets the native thread id of a IPRT thread.
+ *
+ * @returns The native thread id.
+ * @param   Thread      The IPRT thread.
+ */
+RTDECL(RTNATIVETHREAD) RTThreadGetNative(RTTHREAD Thread);
+
+/**
+ * Gets the IPRT thread of a native thread.
+ *
+ * @returns The IPRT thread handle
+ * @returns NIL_RTTHREAD if not a thread known to IPRT.
+ * @param   NativeThread        The native thread handle/id.
+ */
+RTDECL(RTTHREAD) RTThreadFromNative(RTNATIVETHREAD NativeThread);
+
+/**
+ * Changes the type of the specified thread.
+ *
+ * @returns iprt status code.
+ * @param   Thread      The thread which type should be changed.
+ * @param   enmType     The new thread type.
+ * @remark  In Ring-0 it only works if Thread == RTThreadSelf().
+ */
+RTDECL(int) RTThreadSetType(RTTHREAD Thread, RTTHREADTYPE enmType);
+
+/**
+ * Wait for the thread to terminate, resume on interruption.
+ *
+ * @returns     iprt status code.
+ *              Will not return VERR_INTERRUPTED.
+ * @param       Thread          The thread to wait for.
+ * @param       cMillies        The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
+ *                              an indefinite wait.
+ * @param       prc             Where to store the return code of the thread. Optional.
+ */
+RTDECL(int) RTThreadWait(RTTHREAD Thread, RTMSINTERVAL cMillies, int *prc);
+
+/**
+ * Wait for the thread to terminate, return on interruption.
+ *
+ * @returns     iprt status code.
+ * @param       Thread          The thread to wait for.
+ * @param       cMillies        The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
+ *                              an indefinite wait.
+ * @param       prc             Where to store the return code of the thread. Optional.
+ */
+RTDECL(int) RTThreadWaitNoResume(RTTHREAD Thread, RTMSINTERVAL cMillies, int *prc);
+
+/**
+ * Gets the name of the current thread thread.
+ *
+ * @returns Pointer to readonly name string.
+ * @returns NULL on failure.
+ */
+RTDECL(const char *) RTThreadSelfName(void);
+
+/**
+ * Gets the name of a thread.
+ *
+ * @returns Pointer to readonly name string.
+ * @returns NULL on failure.
+ * @param   Thread      Thread handle of the thread to query the name of.
+ */
+RTDECL(const char *) RTThreadGetName(RTTHREAD Thread);
+
+/**
+ * Gets the type of the specified thread.
+ *
+ * @returns The thread type.
+ * @returns RTTHREADTYPE_INVALID if the thread handle is invalid.
+ * @param   Thread      The thread in question.
+ */
+RTDECL(RTTHREADTYPE) RTThreadGetType(RTTHREAD Thread);
+
+/**
+ * Sets the name of a thread.
+ *
+ * @returns iprt status code.
+ * @param   Thread      Thread handle of the thread to query the name of.
+ * @param   pszName     The thread name.
+ */
+RTDECL(int) RTThreadSetName(RTTHREAD Thread, const char *pszName);
+
+/**
+ * Checks if the specified thread is the main thread.
+ *
+ * @returns true if it is, false if it isn't.
+ *
+ * @param   hThread     The thread handle.
+ */
+RTDECL(bool) RTThreadIsMain(RTTHREAD hThread);
+
+/**
+ * Checks if the calling thread is known to IPRT.
+ *
+ * @returns @c true if it is, @c false if it isn't.
+ */
+RTDECL(bool) RTThreadIsSelfKnown(void);
+
+/**
+ * Checks if the calling thread is know to IPRT and is alive.
+ *
+ * @returns @c true if it is, @c false if it isn't.
+ */
+RTDECL(bool) RTThreadIsSelfAlive(void);
+
+/**
+ * Checks if the calling thread is known to IPRT.
+ *
+ * @returns @c true if it is, @c false if it isn't.
+ */
+RTDECL(bool) RTThreadIsOperational(void);
+
+/**
+ * Signal the user event.
+ *
+ * @returns     iprt status code.
+ */
+RTDECL(int) RTThreadUserSignal(RTTHREAD Thread);
+
+/**
+ * Wait for the user event.
+ *
+ * @returns     iprt status code.
+ * @param       Thread          The thread to wait for.
+ * @param       cMillies        The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
+ *                              an indefinite wait.
+ */
+RTDECL(int) RTThreadUserWait(RTTHREAD Thread, RTMSINTERVAL cMillies);
+
+/**
+ * Wait for the user event, return on interruption.
+ *
+ * @returns     iprt status code.
+ * @param       Thread          The thread to wait for.
+ * @param       cMillies        The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
+ *                              an indefinite wait.
+ */
+RTDECL(int) RTThreadUserWaitNoResume(RTTHREAD Thread, RTMSINTERVAL cMillies);
+
+/**
+ * Reset the user event.
+ *
+ * @returns     iprt status code.
+ * @param       Thread          The thread to reset.
+ */
+RTDECL(int) RTThreadUserReset(RTTHREAD Thread);
+
+/**
+ * Pokes the thread.
+ *
+ * This will signal the thread, attempting to interrupt whatever it's currently
+ * doing.  This is *NOT* implemented on all platforms and may cause unresolved
+ * symbols during linking or VERR_NOT_IMPLEMENTED at runtime.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   hThread             The thread to poke.  This must not be the
+ *                              calling thread.
+ */
+RTDECL(int) RTThreadPoke(RTTHREAD hThread);
+
+# ifdef IN_RING0
+
+/**
+ * Check if preemption is currently enabled or not for the current thread.
+ *
+ * @note    This may return true even on systems where preemption isn't
+ *          possible. In that case, it means no call to RTThreadPreemptDisable
+ *          has been made and interrupts are still enabled.
+ *
+ * @returns true if preemption is enabled, false if preemetion is disabled.
+ * @param   hThread             Must be NIL_RTTHREAD for now.
+ */
+RTDECL(bool) RTThreadPreemptIsEnabled(RTTHREAD hThread);
+
+/**
+ * Check if preemption is pending for the current thread.
+ *
+ * This function should be called regularly when executing larger portions of
+ * code with preemption disabled.
+ *
+ * @returns true if pending, false if not.
+ * @param       hThread         Must be NIL_RTTHREAD for now.
+ */
+RTDECL(bool) RTThreadPreemptIsPending(RTTHREAD hThread);
+
+/**
+ * Is RTThreadPreemptIsPending reliable?
+ *
+ * @returns true if reliable, false if not.
+ */
+RTDECL(bool) RTThreadPreemptIsPendingTrusty(void);
+
+/**
+ * Is preemption possible on this system.
+ *
+ * @returns true if possible, false if not.
+ */
+RTDECL(bool) RTThreadPreemptIsPossible(void);
+
+/**
+ * Preemption state saved by RTThreadPreemptDisable and used by
+ * RTThreadPreemptRestore to restore the previous state.
+ */
+typedef struct RTTHREADPREEMPTSTATE
+{
+    /** In debug builds this will be used to check for cpu migration. */
+    RTCPUID         idCpu;
+#  ifdef RT_OS_WINDOWS
+    /** The old IRQL. Don't touch! */
+    unsigned char   uchOldIrql;
+    /** Reserved, MBZ. */
+    uint8_t         bReserved1;
+    /** Reserved, MBZ. */
+    uint8_t         bReserved2;
+    /** Reserved, MBZ. */
+    uint8_t         bReserved3;
+#   define RTTHREADPREEMPTSTATE_INITIALIZER { NIL_RTCPUID, 255, 0, 0, 0 }
+#  elif defined(RT_OS_HAIKU)
+    /** The cpu_state. Don't touch! */
+    uint32_t        uOldCpuState;
+#   define RTTHREADPREEMPTSTATE_INITIALIZER { NIL_RTCPUID, 0 }
+#  elif defined(RT_OS_SOLARIS)
+    /** The Old PIL. Don't touch! */
+    uint32_t        uOldPil;
+#   define RTTHREADPREEMPTSTATE_INITIALIZER { NIL_RTCPUID, UINT32_MAX }
+#  else
+    /** Reserved, MBZ. */
+    uint32_t        u32Reserved;
+#   define RTTHREADPREEMPTSTATE_INITIALIZER { NIL_RTCPUID, 0 }
+#  endif
+} RTTHREADPREEMPTSTATE;
+/** Pointer to a preemption state. */
+typedef RTTHREADPREEMPTSTATE *PRTTHREADPREEMPTSTATE;
+
+/**
+ * Disable preemption.
+ *
+ * A call to this function must be matched by exactly one call to
+ * RTThreadPreemptRestore().
+ *
+ * @param   pState              Where to store the preemption state.
+ */
+RTDECL(void) RTThreadPreemptDisable(PRTTHREADPREEMPTSTATE pState);
+
+/**
+ * Restores the preemption state, undoing a previous call to
+ * RTThreadPreemptDisable.
+ *
+ * A call to this function must be matching a previous call to
+ * RTThreadPreemptDisable.
+ *
+ * @param  pState               The state return by RTThreadPreemptDisable.
+ */
+RTDECL(void) RTThreadPreemptRestore(PRTTHREADPREEMPTSTATE pState);
+
+/**
+ * Check if the thread is executing in interrupt context.
+ *
+ * @returns true if in interrupt context, false if not.
+ * @param       hThread         Must be NIL_RTTHREAD for now.
+ */
+RTDECL(bool) RTThreadIsInInterrupt(RTTHREAD hThread);
+
+
+/**
+ * Thread context swithcing events.
+ */
+typedef enum RTTHREADCTXEVENT
+{
+    /** This thread is being scheduled out on the current CPU (includes preemption,
+     * waiting, sleep and whatever else may trigger scheduling). */
+    RTTHREADCTXEVENT_OUT = 0,
+    /** This thread is being scheduled in on the current CPU and will resume
+     * execution. */
+    RTTHREADCTXEVENT_IN,
+    /** The usual 32-bit size hack. */
+    RTTHREADCTXEVENT_32BIT_HACK = 0x7fffffff
+} RTTHREADCTXEVENT;
+
+/**
+ * Thread context switching hook callback.
+ *
+ * This hook function is called when a thread is scheduled and preempted.  Check
+ * @a enmEvent to see which it is.  Since the function is being called from
+ * hooks inside the scheduler, it is limited what you can do from this function.
+ * Do NOT acquire locks, sleep or yield the thread for instance.  IRQ safe
+ * spinlocks are fine though.
+ *
+ * @returns IPRT status code.
+ * @param   enmEvent    The thread-context event.  Please quitely ignore unknown
+ *                      events, we may add more (thread exit, ++) later.
+ * @param   pvUser      User argument.
+ */
+typedef DECLCALLBACK(void) FNRTTHREADCTXHOOK(RTTHREADCTXEVENT enmEvent, void *pvUser);
+/** Pointer to a context switching hook. */
+typedef FNRTTHREADCTXHOOK *PFNRTTHREADCTXHOOK;
+
+/**
+ * Initializes a thread context switching hook for the current thread.
+ *
+ * The hook is created as disabled, use RTThreadCtxHookEnable to enable it.
+ *
+ * @returns IPRT status code.
+ * @param   phCtxHook       Where to store the hook handle.
+ * @param   fFlags          Reserved for future extensions, must be zero.
+ * @param   pfnCallback     Pointer to a the hook function (callback) that
+ *                          should be called for all context switching events
+ *                          involving the current thread.
+ * @param   pvUser          User argument that will be passed to @a pfnCallback.
+ * @remarks Preemption must be enabled.
+ */
+RTDECL(int) RTThreadCtxHookCreate(PRTTHREADCTXHOOK phCtxHook, uint32_t fFlags, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser);
+
+/**
+ * Destroys a thread context switching hook.
+ *
+ * Caller must make sure the hook is disabled before the final reference is
+ * released.  Recommended to call this on the owning thread, otherwise the
+ * memory backing it may on some systems only be released when the thread
+ * terminates.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   hCtxHook        The context hook handle.  NIL_RTTHREADCTXHOOK is
+ *                          ignored and the function will return VINF_SUCCESS.
+ * @remarks Preemption must be enabled.
+ * @remarks Do not call from FNRTTHREADCTXHOOK.
+ */
+RTDECL(int) RTThreadCtxHookDestroy(RTTHREADCTXHOOK hCtxHook);
+
+/**
+ * Enables the context switching hooks for the current thread.
+ *
+ * @returns IPRT status code.
+ * @param   hCtxHook        The context hook handle.
+ * @remarks Should be called with preemption disabled.
+ */
+RTDECL(int) RTThreadCtxHookEnable(RTTHREADCTXHOOK hCtxHook);
+
+/**
+ * Disables the thread context switching hook for the current thread.
+ *
+ * Will not assert or fail if called twice or with a NIL handle.
+ *
+ * @returns IPRT status code.
+ * @param   hCtxHook        The context hook handle. NIL_RTTHREADCTXHOOK is
+ *                          ignored and the function wil return VINF_SUCCESS.
+ * @remarks Should be called with preemption disabled.
+ * @remarks Do not call from FNRTTHREADCTXHOOK.
+ */
+RTDECL(int) RTThreadCtxHookDisable(RTTHREADCTXHOOK hCtxHook);
+
+/**
+ * Is the thread context switching hook enabled?
+ *
+ * @returns true if registered, false if not supported or not registered.
+ * @param   hCtxHook        The context hook handle.   NIL_RTTHREADCTXHOOK is
+ *                          ignored and the function will return false.
+ *
+ * @remarks Can be called from any thread, though is naturally subject to races
+ *          when not called from the thread associated with the hook.
+ */
+RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook);
+
+# endif /* IN_RING0 */
+
+
+# ifdef IN_RING3
+
+/**
+ * Adopts a non-IPRT thread.
+ *
+ * @returns IPRT status code.
+ * @param   enmType         The thread type.
+ * @param   fFlags          The thread flags. RTTHREADFLAGS_WAITABLE is not currently allowed.
+ * @param   pszName         The thread name. Optional
+ * @param   pThread         Where to store the thread handle. Optional.
+ */
+RTDECL(int) RTThreadAdopt(RTTHREADTYPE enmType, unsigned fFlags, const char *pszName, PRTTHREAD pThread);
+
+/**
+ * Get the thread handle of the current thread, automatically adopting alien
+ * threads.
+ *
+ * @returns Thread handle.
+ */
+RTDECL(RTTHREAD) RTThreadSelfAutoAdopt(void);
+
+/**
+ * Gets the affinity mask of the current thread.
+ *
+ * @returns IPRT status code.
+ * @param   pCpuSet         Where to return the CPU affienty set of the calling
+ *                          thread.
+ */
+RTR3DECL(int) RTThreadGetAffinity(PRTCPUSET pCpuSet);
+
+/**
+ * Sets the affinity mask of the current thread.
+ *
+ * @returns iprt status code.
+ * @param   pCpuSet         The set of CPUs this thread can run on.  NULL means
+ *                          all CPUs.
+ */
+RTR3DECL(int) RTThreadSetAffinity(PCRTCPUSET pCpuSet);
+
+/**
+ * Binds the thread to one specific CPU.
+ *
+ * @returns iprt status code.
+ * @param   idCpu           The ID of the CPU to bind this thread to.  Use
+ *                          NIL_RTCPUID to unbind it.
+ */
+RTR3DECL(int) RTThreadSetAffinityToCpu(RTCPUID idCpu);
+
+/**
+ * Unblocks a thread.
+ *
+ * This function is paired with RTThreadBlocking and RTThreadBlockingDebug.
+ *
+ * @param   hThread     The current thread.
+ * @param   enmCurState The current state, used to check for nested blocking.
+ *                      The new state will be running.
+ */
+RTDECL(void) RTThreadUnblocked(RTTHREAD hThread, RTTHREADSTATE enmCurState);
+
+/**
+ * Change the thread state to blocking.
+ *
+ * @param   hThread         The current thread.
+ * @param   enmState        The sleep state.
+ * @param   fReallySleeping Really going to sleep now.  Use false before calls
+ *                          to other IPRT synchronization methods.
+ */
+RTDECL(void) RTThreadBlocking(RTTHREAD hThread, RTTHREADSTATE enmState, bool fReallySleeping);
+
+/**
+ * Get the current thread state.
+ *
+ * A thread that is reported as sleeping may actually still be running inside
+ * the lock validator or/and in the code of some other IPRT synchronization
+ * primitive.  Use RTThreadGetReallySleeping
+ *
+ * @returns The thread state.
+ * @param   hThread         The thread.
+ */
+RTDECL(RTTHREADSTATE) RTThreadGetState(RTTHREAD hThread);
+
+/**
+ * Checks if the thread is really sleeping or not.
+ *
+ * @returns RTTHREADSTATE_RUNNING if not really sleeping, otherwise the state it
+ *          is sleeping in.
+ * @param   hThread         The thread.
+ */
+RTDECL(RTTHREADSTATE) RTThreadGetReallySleeping(RTTHREAD hThread);
+
+/**
+ * Translate a thread state into a string.
+ *
+ * @returns Pointer to a read-only string containing the state name.
+ * @param   enmState            The state.
+ */
+RTDECL(const char *) RTThreadStateName(RTTHREADSTATE enmState);
+
+
+/**
+ * Native thread states returned by RTThreadNativeState.
+ */
+typedef enum RTTHREADNATIVESTATE
+{
+    /** Invalid thread handle. */
+    RTTHREADNATIVESTATE_INVALID = 0,
+    /** Unable to determine the thread state. */
+    RTTHREADNATIVESTATE_UNKNOWN,
+    /** The thread is running. */
+    RTTHREADNATIVESTATE_RUNNING,
+    /** The thread is blocked. */
+    RTTHREADNATIVESTATE_BLOCKED,
+    /** The thread is suspended / stopped. */
+    RTTHREADNATIVESTATE_SUSPENDED,
+    /** The thread has terminated. */
+    RTTHREADNATIVESTATE_TERMINATED,
+    /** Make sure it's a 32-bit type. */
+    RTTHREADNATIVESTATE_32BIT_HACK = 0x7fffffff
+} RTTHREADNATIVESTATE;
+
+
+/**
+ * Get the native state of a thread.
+ *
+ * @returns Native state.
+ * @param   hThread             The thread handle.
+ *
+ * @remarks Not yet implemented on all systems, so have a backup plan for
+ *          RTTHREADNATIVESTATE_UNKNOWN.
+ */
+RTDECL(RTTHREADNATIVESTATE) RTThreadGetNativeState(RTTHREAD hThread);
+
+
+/**
+ * Get the execution times of the specified thread
+ *
+ * @returns IPRT status code.
+ * @param   pKernelTime         Kernel execution time in ms (out)
+ * @param   pUserTime           User execution time in ms (out)
+ *
+ */
+RTR3DECL(int) RTThreadGetExecutionTimeMilli(uint64_t *pKernelTime, uint64_t *pUserTime);
+
+/** @name Thread Local Storage
+ * @{
+ */
+/**
+ * Thread termination callback for destroying a non-zero TLS entry.
+ *
+ * @remarks It is not permitable to use any RTTls APIs at this time. Doing so
+ *          may lead to endless loops, crashes, and other bad stuff.
+ *
+ * @param   pvValue     The current value.
+ */
+typedef DECLCALLBACK(void) FNRTTLSDTOR(void *pvValue);
+/** Pointer to a FNRTTLSDTOR. */
+typedef FNRTTLSDTOR *PFNRTTLSDTOR;
+
+/**
+ * Allocates a TLS entry (index).
+ *
+ * Example code:
+ * @code
+    RTTLS g_iTls = NIL_RTTLS;
+
+    ...
+
+    // once for the process, allocate the TLS index
+    if (g_iTls == NIL_RTTLS)
+         g_iTls = RTTlsAlloc();
+
+    // set the thread-local value.
+    RTTlsSet(g_iTls, pMyData);
+
+    ...
+
+    // get the thread-local value
+    PMYDATA pMyData = (PMYDATA)RTTlsGet(g_iTls);
+
+   @endcode
+ *
+ * @returns the index of the allocated TLS entry.
+ * @returns NIL_RTTLS on failure.
+ */
+RTR3DECL(RTTLS) RTTlsAlloc(void);
+
+/**
+ * Variant of RTTlsAlloc that returns a status code.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NOT_SUPPORTED if pfnDestructor is non-NULL and the platform
+ *          doesn't support this feature.
+ *
+ * @param   piTls           Where to store the index of the allocated TLS entry.
+ *                          This is set to NIL_RTTLS on failure.
+ * @param   pfnDestructor   Optional callback function for cleaning up on
+ *                          thread termination. WARNING! This feature may not
+ *                          be implemented everywhere.
+ */
+RTR3DECL(int) RTTlsAllocEx(PRTTLS piTls, PFNRTTLSDTOR pfnDestructor);
+
+/**
+ * Frees a TLS entry.
+ *
+ * @returns IPRT status code.
+ * @param   iTls        The index of the TLS entry.
+ */
+RTR3DECL(int) RTTlsFree(RTTLS iTls);
+
+/**
+ * Get the (thread-local) value stored in a TLS entry.
+ *
+ * @returns value in given TLS entry.
+ * @retval  NULL if RTTlsSet() has not yet been called on this thread, or if the
+ *          TLS index is invalid.
+ *
+ * @param   iTls        The index of the TLS entry.
+ */
+RTR3DECL(void *) RTTlsGet(RTTLS iTls);
+
+/**
+ * Get the value stored in a TLS entry.
+ *
+ * @returns IPRT status code.
+ * @param   iTls        The index of the TLS entry.
+ * @param   ppvValue    Where to store the value.  The value will be NULL if
+ *                      RTTlsSet has not yet been called on this thread.
+ */
+RTR3DECL(int) RTTlsGetEx(RTTLS iTls, void **ppvValue);
+
+/**
+ * Set the value stored in an allocated TLS entry.
+ *
+ * @returns IPRT status.
+ * @param   iTls        The index of the TLS entry.
+ * @param   pvValue     The value to store.
+ *
+ * @remarks Note that NULL is considered a special value.
+ */
+RTR3DECL(int) RTTlsSet(RTTLS iTls, void *pvValue);
+
+/** @} */
+
+# endif /* IN_RING3 */
+# endif /* !IN_RC */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/time.h b/ubuntu/vbox/include/iprt/time.h
new file mode 100644 (file)
index 0000000..a3dcd0d
--- /dev/null
@@ -0,0 +1,1038 @@
+/** @file
+ * IPRT - Time.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_time_h
+#define ___iprt_time_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_time   RTTime - Time
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** Time Specification.
+ *
+ * Use the inline RTTimeSpecGet/Set to operate on structure this so we
+ * can easily change the representation if required later.
+ *
+ * The current representation is in nanoseconds relative to the unix epoch
+ * (1970-01-01 00:00:00 UTC). This gives us an approximate span from
+ * 1678 to 2262 without sacrificing the resolution offered by the various
+ * host OSes (BSD & LINUX 1ns, NT 100ns).
+ */
+typedef struct RTTIMESPEC
+{
+    /** Nanoseconds since epoch.
+     * The name is intentially too long to be comfortable to use because you should be
+     * using inline helpers! */
+    int64_t     i64NanosecondsRelativeToUnixEpoch;
+} RTTIMESPEC;
+
+
+/** @name RTTIMESPEC methods
+ * @{ */
+
+/**
+ * Gets the time as nanoseconds relative to the unix epoch.
+ *
+ * @returns Nanoseconds relative to unix epoch.
+ * @param   pTime       The time spec to interpret.
+ */
+DECLINLINE(int64_t) RTTimeSpecGetNano(PCRTTIMESPEC pTime)
+{
+    return pTime->i64NanosecondsRelativeToUnixEpoch;
+}
+
+
+/**
+ * Sets the time give by nanoseconds relative to the unix epoch.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   i64Nano     The new time in nanoseconds.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecSetNano(PRTTIMESPEC pTime, int64_t i64Nano)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch = i64Nano;
+    return pTime;
+}
+
+
+/**
+ * Gets the time as microseconds relative to the unix epoch.
+ *
+ * @returns microseconds relative to unix epoch.
+ * @param   pTime       The time spec to interpret.
+ */
+DECLINLINE(int64_t) RTTimeSpecGetMicro(PCRTTIMESPEC pTime)
+{
+    return pTime->i64NanosecondsRelativeToUnixEpoch / RT_NS_1US;
+}
+
+
+/**
+ * Sets the time given by microseconds relative to the unix epoch.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   i64Micro    The new time in microsecond.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecSetMicro(PRTTIMESPEC pTime, int64_t i64Micro)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch = i64Micro * RT_NS_1US;
+    return pTime;
+}
+
+
+/**
+ * Gets the time as milliseconds relative to the unix epoch.
+ *
+ * @returns milliseconds relative to unix epoch.
+ * @param   pTime       The time spec to interpret.
+ */
+DECLINLINE(int64_t) RTTimeSpecGetMilli(PCRTTIMESPEC pTime)
+{
+    return pTime->i64NanosecondsRelativeToUnixEpoch / RT_NS_1MS;
+}
+
+
+/**
+ * Sets the time given by milliseconds relative to the unix epoch.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   i64Milli    The new time in milliseconds.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecSetMilli(PRTTIMESPEC pTime, int64_t i64Milli)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch = i64Milli * RT_NS_1MS;
+    return pTime;
+}
+
+
+/**
+ * Gets the time as seconds relative to the unix epoch.
+ *
+ * @returns seconds relative to unix epoch.
+ * @param   pTime       The time spec to interpret.
+ */
+DECLINLINE(int64_t) RTTimeSpecGetSeconds(PCRTTIMESPEC pTime)
+{
+    return pTime->i64NanosecondsRelativeToUnixEpoch / RT_NS_1SEC;
+}
+
+
+/**
+ * Sets the time given by seconds relative to the unix epoch.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   i64Seconds  The new time in seconds.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecSetSeconds(PRTTIMESPEC pTime, int64_t i64Seconds)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch = i64Seconds * RT_NS_1SEC;
+    return pTime;
+}
+
+
+/**
+ * Makes the time spec absolute like abs() does (i.e. a positive value).
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecAbsolute(PRTTIMESPEC pTime)
+{
+    if (pTime->i64NanosecondsRelativeToUnixEpoch < 0)
+        pTime->i64NanosecondsRelativeToUnixEpoch = -pTime->i64NanosecondsRelativeToUnixEpoch;
+    return pTime;
+}
+
+
+/**
+ * Negates the time.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecNegate(PRTTIMESPEC pTime)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch = -pTime->i64NanosecondsRelativeToUnixEpoch;
+    return pTime;
+}
+
+
+/**
+ * Adds a time period to the time.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   pTimeAdd    The time spec to add to pTime.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecAdd(PRTTIMESPEC pTime, PCRTTIMESPEC pTimeAdd)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch += pTimeAdd->i64NanosecondsRelativeToUnixEpoch;
+    return pTime;
+}
+
+
+/**
+ * Adds a time period give as nanoseconds from the time.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   i64Nano     The time period in nanoseconds.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecAddNano(PRTTIMESPEC pTime, int64_t i64Nano)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch += i64Nano;
+    return pTime;
+}
+
+
+/**
+ * Adds a time period give as microseconds from the time.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   i64Micro    The time period in microseconds.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecAddMicro(PRTTIMESPEC pTime, int64_t i64Micro)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch += i64Micro * RT_NS_1US;
+    return pTime;
+}
+
+
+/**
+ * Adds a time period give as milliseconds from the time.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   i64Milli    The time period in milliseconds.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecAddMilli(PRTTIMESPEC pTime, int64_t i64Milli)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch += i64Milli * RT_NS_1MS;
+    return pTime;
+}
+
+
+/**
+ * Adds a time period give as seconds from the time.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   i64Seconds  The time period in seconds.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecAddSeconds(PRTTIMESPEC pTime, int64_t i64Seconds)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch += i64Seconds * RT_NS_1SEC;
+    return pTime;
+}
+
+
+/**
+ * Subtracts a time period from the time.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   pTimeSub    The time spec to subtract from pTime.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecSub(PRTTIMESPEC pTime, PCRTTIMESPEC pTimeSub)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch -= pTimeSub->i64NanosecondsRelativeToUnixEpoch;
+    return pTime;
+}
+
+
+/**
+ * Subtracts a time period give as nanoseconds from the time.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   i64Nano     The time period in nanoseconds.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecSubNano(PRTTIMESPEC pTime, int64_t i64Nano)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch -= i64Nano;
+    return pTime;
+}
+
+
+/**
+ * Subtracts a time period give as microseconds from the time.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   i64Micro    The time period in microseconds.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecSubMicro(PRTTIMESPEC pTime, int64_t i64Micro)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch -= i64Micro * RT_NS_1US;
+    return pTime;
+}
+
+
+/**
+ * Subtracts a time period give as milliseconds from the time.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   i64Milli    The time period in milliseconds.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecSubMilli(PRTTIMESPEC pTime, int64_t i64Milli)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch -= i64Milli * RT_NS_1MS;
+    return pTime;
+}
+
+
+/**
+ * Subtracts a time period give as seconds from the time.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   i64Seconds  The time period in seconds.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecSubSeconds(PRTTIMESPEC pTime, int64_t i64Seconds)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch -= i64Seconds * RT_NS_1SEC;
+    return pTime;
+}
+
+
+/**
+ * Gives the time in seconds and nanoseconds.
+ *
+ * @returns pTime.
+ * @param   pTime           The time spec to interpret.
+ * @param   *pi32Seconds    Where to store the time period in seconds.
+ * @param   *pi32Nano       Where to store the time period in nanoseconds.
+ */
+DECLINLINE(void) RTTimeSpecGetSecondsAndNano(PRTTIMESPEC pTime, int32_t *pi32Seconds, int32_t *pi32Nano)
+{
+    int64_t i64 = RTTimeSpecGetNano(pTime);
+    int32_t i32Nano = (int32_t)(i64 % RT_NS_1SEC);
+    i64 /= RT_NS_1SEC;
+    if (i32Nano < 0)
+    {
+        i32Nano += RT_NS_1SEC;
+        i64--;
+    }
+    *pi32Seconds = (int32_t)i64;
+    *pi32Nano    = i32Nano;
+}
+
+
+/* PORTME: Add struct timeval guard macro here. */
+#if defined(RTTIME_INCL_TIMEVAL) || defined(_STRUCT_TIMEVAL) || defined(_SYS__TIMEVAL_H_) || defined(_SYS_TIME_H) || defined(_TIMEVAL) || defined(_LINUX_TIME_H) \
+ || (defined(RT_OS_NETBSD) && defined(_SYS_TIME_H_))
+/**
+ * Gets the time as POSIX timeval.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to interpret.
+ * @param   pTimeval    Where to store the time as POSIX timeval.
+ */
+DECLINLINE(struct timeval *) RTTimeSpecGetTimeval(PCRTTIMESPEC pTime, struct timeval *pTimeval)
+{
+    int64_t i64 = RTTimeSpecGetMicro(pTime);
+    int32_t i32Micro = (int32_t)(i64 % RT_US_1SEC);
+    i64 /= RT_US_1SEC;
+    if (i32Micro < 0)
+    {
+        i32Micro += RT_US_1SEC;
+        i64--;
+    }
+    pTimeval->tv_sec = (time_t)i64;
+    pTimeval->tv_usec = i32Micro;
+    return pTimeval;
+}
+
+/**
+ * Sets the time as POSIX timeval.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   pTimeval    Pointer to the POSIX timeval struct with the new time.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecSetTimeval(PRTTIMESPEC pTime, const struct timeval *pTimeval)
+{
+    return RTTimeSpecAddMicro(RTTimeSpecSetSeconds(pTime, pTimeval->tv_sec), pTimeval->tv_usec);
+}
+#endif /* various ways of detecting struct timeval */
+
+
+/* PORTME: Add struct timespec guard macro here. */
+#if defined(RTTIME_INCL_TIMESPEC) || defined(_STRUCT_TIMESPEC) || defined(_SYS__TIMESPEC_H_) || defined(TIMEVAL_TO_TIMESPEC) || defined(_TIMESPEC) \
+ || (defined(RT_OS_NETBSD) && defined(_SYS_TIME_H_))
+/**
+ * Gets the time as POSIX timespec.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to interpret.
+ * @param   pTimespec   Where to store the time as POSIX timespec.
+ */
+DECLINLINE(struct timespec *) RTTimeSpecGetTimespec(PCRTTIMESPEC pTime, struct timespec *pTimespec)
+{
+    int64_t i64 = RTTimeSpecGetNano(pTime);
+    int32_t i32Nano = (int32_t)(i64 % RT_NS_1SEC);
+    i64 /= RT_NS_1SEC;
+    if (i32Nano < 0)
+    {
+        i32Nano += RT_NS_1SEC;
+        i64--;
+    }
+    pTimespec->tv_sec = (time_t)i64;
+    pTimespec->tv_nsec = i32Nano;
+    return pTimespec;
+}
+
+/**
+ * Sets the time as POSIX timespec.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   pTimespec   Pointer to the POSIX timespec struct with the new time.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecSetTimespec(PRTTIMESPEC pTime, const struct timespec *pTimespec)
+{
+    return RTTimeSpecAddNano(RTTimeSpecSetSeconds(pTime, pTimespec->tv_sec), pTimespec->tv_nsec);
+}
+#endif /* various ways of detecting struct timespec */
+
+
+
+/** The offset of the unix epoch and the base for NT time (in 100ns units).
+ * Nt time starts at 1601-01-01 00:00:00. */
+#define RTTIME_NT_TIME_OFFSET_UNIX      (116444736000000000LL)
+
+
+/**
+ * Gets the time as NT time.
+ *
+ * @returns Nt time.
+ * @param   pTime       The time spec to interpret.
+ */
+DECLINLINE(uint64_t) RTTimeSpecGetNtTime(PCRTTIMESPEC pTime)
+{
+    return pTime->i64NanosecondsRelativeToUnixEpoch / 100
+        + RTTIME_NT_TIME_OFFSET_UNIX;
+}
+
+
+/**
+ * Sets the time given by Nt time.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   u64NtTime   The new time in Nt time.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecSetNtTime(PRTTIMESPEC pTime, uint64_t u64NtTime)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch =
+        ((int64_t)u64NtTime - RTTIME_NT_TIME_OFFSET_UNIX) * 100;
+    return pTime;
+}
+
+
+#ifdef _FILETIME_
+/**
+ * Gets the time as NT file time.
+ *
+ * @returns pFileTime.
+ * @param   pTime       The time spec to interpret.
+ * @param   pFileTime   Pointer to NT filetime structure.
+ */
+DECLINLINE(PFILETIME) RTTimeSpecGetNtFileTime(PCRTTIMESPEC pTime, PFILETIME pFileTime)
+{
+    *((uint64_t *)pFileTime) = RTTimeSpecGetNtTime(pTime);
+    return pFileTime;
+}
+
+/**
+ * Sets the time as NT file time.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   pFileTime   Where to store the time as Nt file time.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecSetNtFileTime(PRTTIMESPEC pTime, const FILETIME *pFileTime)
+{
+    return RTTimeSpecSetNtTime(pTime, *(const uint64_t *)pFileTime);
+}
+#endif
+
+
+/** The offset to the start of DOS time.
+ * DOS time starts 1980-01-01 00:00:00.  */
+#define RTTIME_OFFSET_DOS_TIME          (315532800000000000LL)
+
+
+/**
+ * Gets the time as seconds relative to the start of dos time.
+ *
+ * @returns seconds relative to the start of dos time.
+ * @param   pTime       The time spec to interpret.
+ */
+DECLINLINE(int64_t) RTTimeSpecGetDosSeconds(PCRTTIMESPEC pTime)
+{
+    return (pTime->i64NanosecondsRelativeToUnixEpoch - RTTIME_OFFSET_DOS_TIME)
+        / RT_NS_1SEC;
+}
+
+
+/**
+ * Sets the time given by seconds relative to the start of dos time.
+ *
+ * @returns pTime.
+ * @param   pTime       The time spec to modify.
+ * @param   i64Seconds  The new time in seconds relative to the start of dos time.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecSetDosSeconds(PRTTIMESPEC pTime, int64_t i64Seconds)
+{
+    pTime->i64NanosecondsRelativeToUnixEpoch = i64Seconds * RT_NS_1SEC
+        + RTTIME_OFFSET_DOS_TIME;
+    return pTime;
+}
+
+
+/**
+ * Compare two time specs.
+ *
+ * @returns true they are equal.
+ * @returns false they are not equal.
+ * @param   pTime1  The 1st time spec.
+ * @param   pTime2  The 2nd time spec.
+ */
+DECLINLINE(bool) RTTimeSpecIsEqual(PCRTTIMESPEC pTime1, PCRTTIMESPEC pTime2)
+{
+    return pTime1->i64NanosecondsRelativeToUnixEpoch == pTime2->i64NanosecondsRelativeToUnixEpoch;
+}
+
+
+/**
+ * Compare two time specs.
+ *
+ * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
+ * @returns false they are not equal.
+ * @param   pLeft       The 1st time spec.
+ * @param   pRight      The 2nd time spec.
+ */
+DECLINLINE(int) RTTimeSpecCompare(PCRTTIMESPEC pLeft, PCRTTIMESPEC pRight)
+{
+    if (pLeft->i64NanosecondsRelativeToUnixEpoch == pRight->i64NanosecondsRelativeToUnixEpoch)
+        return 0;
+    return pLeft->i64NanosecondsRelativeToUnixEpoch < pRight->i64NanosecondsRelativeToUnixEpoch ? -1 : 1;
+}
+
+
+/**
+ * Converts a time spec to a ISO date string.
+ *
+ * @returns psz on success.
+ * @returns NULL on buffer underflow.
+ * @param   pTime       The time spec.
+ * @param   psz         Where to store the string.
+ * @param   cb          The size of the buffer.
+ */
+RTDECL(char *) RTTimeSpecToString(PCRTTIMESPEC pTime, char *psz, size_t cb);
+
+/**
+ * Attempts to convert an ISO date string to a time structure.
+ *
+ * We're a little forgiving with zero padding, unspecified parts, and leading
+ * and trailing spaces.
+ *
+ * @retval  pTime on success,
+ * @retval  NULL on failure.
+ * @param   pTime       The time spec.
+ * @param   pszString   The ISO date string to convert.
+ */
+RTDECL(PRTTIMESPEC) RTTimeSpecFromString(PRTTIMESPEC pTime, const char *pszString);
+
+/** @} */
+
+
+/**
+ * Exploded time.
+ */
+#pragma pack(1)
+typedef struct RTTIME
+{
+    /** The year number. */
+    int32_t     i32Year;
+    /** The month of the year (1-12). January is 1. */
+    uint8_t     u8Month;
+    /** The day of the week (0-6). Monday is 0. */
+    uint8_t     u8WeekDay;
+    /** The day of the year (1-366). January the 1st is 1. */
+    uint16_t    u16YearDay;
+    /** The day of the month (1-31). */
+    uint8_t     u8MonthDay;
+    /** Hour of the day (0-23). */
+    uint8_t     u8Hour;
+    /** The minute of the hour (0-59). */
+    uint8_t     u8Minute;
+    /** The second of the minute (0-60).
+     * (u32Nanosecond / 1000000) */
+    uint8_t     u8Second;
+    /** The nanoseconds of the second (0-999999999). */
+    uint32_t    u32Nanosecond;
+    /** Flags, of the RTTIME_FLAGS_* \#defines. */
+    uint32_t    fFlags;
+    /** UCT time offset in minutes (-840-840).
+     * @remarks The implementation of RTTimeLocal* isn't quite there yet, so this might not be 100% correct. */
+    int32_t     offUTC;
+} RTTIME;
+#pragma pack()
+/** Pointer to a exploded time structure. */
+typedef RTTIME *PRTTIME;
+/** Pointer to a const exploded time structure. */
+typedef const RTTIME *PCRTTIME;
+
+/** @name RTTIME::fFlags values.
+ * @{ */
+/** Set if the time is UTC. If clear the time local time. */
+#define RTTIME_FLAGS_TYPE_MASK      3
+/** the time is UTC time. */
+#define RTTIME_FLAGS_TYPE_UTC       2
+/** The time is local time. */
+#define RTTIME_FLAGS_TYPE_LOCAL     3
+
+/** Set if the time is local and daylight saving time is in effect.
+ * Not bit is not valid if RTTIME_FLAGS_NO_DST_DATA is set. */
+#define RTTIME_FLAGS_DST            RT_BIT(4)
+/** Set if the time is local and there is no data available on daylight saving time. */
+#define RTTIME_FLAGS_NO_DST_DATA    RT_BIT(5)
+/** Set if the year is a leap year.
+ * This is mutual exclusiv with RTTIME_FLAGS_COMMON_YEAR. */
+#define RTTIME_FLAGS_LEAP_YEAR      RT_BIT(6)
+/** Set if the year is a common year.
+ * This is mutual exclusiv with RTTIME_FLAGS_LEAP_YEAR. */
+#define RTTIME_FLAGS_COMMON_YEAR    RT_BIT(7)
+/** The mask of valid flags. */
+#define RTTIME_FLAGS_MASK           UINT32_C(0xff)
+/** @} */
+
+
+/**
+ * Gets the current system time (UTC).
+ *
+ * @returns pTime.
+ * @param   pTime       Where to store the time.
+ */
+RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime);
+
+/**
+ * Sets the system time.
+ *
+ * @returns IPRT status code
+ * @param   pTime       The new system time (UTC).
+ *
+ * @remarks This will usually fail because changing the wall time is usually
+ *          requires extra privileges.
+ */
+RTDECL(int) RTTimeSet(PCRTTIMESPEC pTime);
+
+/**
+ * Explodes a time spec (UTC).
+ *
+ * @returns pTime.
+ * @param   pTime       Where to store the exploded time.
+ * @param   pTimeSpec   The time spec to exploded.
+ */
+RTDECL(PRTTIME) RTTimeExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec);
+
+/**
+ * Implodes exploded time to a time spec (UTC).
+ *
+ * @returns pTime on success.
+ * @returns NULL if the pTime data is invalid.
+ * @param   pTimeSpec   Where to store the imploded UTC time.
+ *                      If pTime specifies a time which outside the range, maximum or
+ *                      minimum values will be returned.
+ * @param   pTime       Pointer to the exploded time to implode.
+ *                      The fields u8Month, u8WeekDay and u8MonthDay are not used,
+ *                      and all the other fields are expected to be within their
+ *                      bounds. Use RTTimeNormalize() to calculate u16YearDay and
+ *                      normalize the ranges of the fields.
+ */
+RTDECL(PRTTIMESPEC) RTTimeImplode(PRTTIMESPEC pTimeSpec, PCRTTIME pTime);
+
+/**
+ * Normalizes the fields of a time structure.
+ *
+ * It is possible to calculate year-day from month/day and vice
+ * versa. If you adjust any of of these, make sure to zero the
+ * other so you make it clear which of the fields to use. If
+ * it's ambiguous, the year-day field is used (and you get
+ * assertions in debug builds).
+ *
+ * All the time fields and the year-day or month/day fields will
+ * be adjusted for overflows. (Since all fields are unsigned, there
+ * is no underflows.) It is possible to exploit this for simple
+ * date math, though the recommended way of doing that to implode
+ * the time into a timespec and do the math on that.
+ *
+ * @returns pTime on success.
+ * @returns NULL if the data is invalid.
+ *
+ * @param   pTime       The time structure to normalize.
+ *
+ * @remarks This function doesn't work with local time, only with UTC time.
+ */
+RTDECL(PRTTIME) RTTimeNormalize(PRTTIME pTime);
+
+/**
+ * Gets the current local system time.
+ *
+ * @returns pTime.
+ * @param   pTime   Where to store the local time.
+ */
+RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime);
+
+/**
+ * Gets the delta between UTC and local time.
+ *
+ * @code
+ *      RTTIMESPEC LocalTime;
+ *      RTTimeSpecAddNano(RTTimeNow(&LocalTime), RTTimeLocalDeltaNano());
+ * @endcode
+ *
+ * @returns Returns the nanosecond delta between UTC and local time.
+ */
+RTDECL(int64_t) RTTimeLocalDeltaNano(void);
+
+/**
+ * Explodes a time spec to the localized timezone.
+ *
+ * @returns pTime.
+ * @param   pTime       Where to store the exploded time.
+ * @param   pTimeSpec   The time spec to exploded (UTC).
+ */
+RTDECL(PRTTIME) RTTimeLocalExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec);
+
+/**
+ * Normalizes the fields of a time structure containing local time.
+ *
+ * See RTTimeNormalize for details.
+ *
+ * @returns pTime on success.
+ * @returns NULL if the data is invalid.
+ * @param   pTime       The time structure to normalize.
+ */
+RTDECL(PRTTIME) RTTimeLocalNormalize(PRTTIME pTime);
+
+/**
+ * Converts a time spec to a ISO date string.
+ *
+ * @returns psz on success.
+ * @returns NULL on buffer underflow.
+ * @param   pTime       The time. Caller should've normalized this.
+ * @param   psz         Where to store the string.
+ * @param   cb          The size of the buffer.
+ */
+RTDECL(char *) RTTimeToString(PCRTTIME pTime, char *psz, size_t cb);
+
+/**
+ * Attempts to convert an ISO date string to a time structure.
+ *
+ * We're a little forgiving with zero padding, unspecified parts, and leading
+ * and trailing spaces.
+ *
+ * @retval  pTime on success,
+ * @retval  NULL on failure.
+ * @param   pTime       Where to store the time on success.
+ * @param   pszString   The ISO date string to convert.
+ */
+RTDECL(PRTTIME) RTTimeFromString(PRTTIME pTime, const char *pszString);
+
+/**
+ * Checks if a year is a leap year or not.
+ *
+ * @returns true if it's a leap year.
+ * @returns false if it's a common year.
+ * @param   i32Year     The year in question.
+ */
+RTDECL(bool) RTTimeIsLeapYear(int32_t i32Year);
+
+/**
+ * Gets the current nanosecond timestamp.
+ *
+ * @returns nanosecond timestamp.
+ */
+RTDECL(uint64_t) RTTimeNanoTS(void);
+
+/**
+ * Gets the current millisecond timestamp.
+ *
+ * @returns millisecond timestamp.
+ */
+RTDECL(uint64_t) RTTimeMilliTS(void);
+
+/**
+ * Debugging the time api.
+ *
+ * @returns the number of 1ns steps which has been applied by RTTimeNanoTS().
+ */
+RTDECL(uint32_t) RTTimeDbgSteps(void);
+
+/**
+ * Debugging the time api.
+ *
+ * @returns the number of times the TSC interval expired RTTimeNanoTS().
+ */
+RTDECL(uint32_t) RTTimeDbgExpired(void);
+
+/**
+ * Debugging the time api.
+ *
+ * @returns the number of bad previous values encountered by RTTimeNanoTS().
+ */
+RTDECL(uint32_t) RTTimeDbgBad(void);
+
+/**
+ * Debugging the time api.
+ *
+ * @returns the number of update races in RTTimeNanoTS().
+ */
+RTDECL(uint32_t) RTTimeDbgRaces(void);
+
+/** @name RTTimeNanoTS GIP worker functions, for TM.
+ * @{ */
+/** Pointer to a RTTIMENANOTSDATA structure. */
+typedef struct RTTIMENANOTSDATA *PRTTIMENANOTSDATA;
+
+/**
+ * Nanosecond timestamp data.
+ *
+ * This is used to keep track of statistics and callback so IPRT
+ * and TM (VirtualBox) can share code.
+ *
+ * @remark Keep this in sync with the assembly version in timesupA.asm.
+ */
+typedef struct RTTIMENANOTSDATA
+{
+    /** Where the previous timestamp is stored.
+     * This is maintained to ensure that time doesn't go backwards or anything. */
+    uint64_t volatile  *pu64Prev;
+
+    /**
+     * Helper function that's used by the assembly routines when something goes bust.
+     *
+     * @param   pData           Pointer to this structure.
+     * @param   u64NanoTS       The calculated nano ts.
+     * @param   u64DeltaPrev    The delta relative to the previously returned timestamp.
+     * @param   u64PrevNanoTS   The previously returned timestamp (as it was read it).
+     */
+    DECLCALLBACKMEMBER(void, pfnBad)(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS);
+
+    /**
+     * Callback for when rediscovery is required.
+     *
+     * @returns Nanosecond timestamp.
+     * @param   pData           Pointer to this structure.
+     */
+    DECLCALLBACKMEMBER(uint64_t, pfnRediscover)(PRTTIMENANOTSDATA pData);
+
+    /**
+     * Callback for when some CPU index related stuff goes wrong.
+     *
+     * @returns Nanosecond timestamp.
+     * @param   pData           Pointer to this structure.
+     * @param   idApic          The APIC ID if available, otherwise (UINT16_MAX-1).
+     * @param   iCpuSet         The CPU set index if available, otherwise
+     *                          (UINT16_MAX-1).
+     * @param   iGipCpu         The GIP CPU array index if available, otherwise
+     *                          (UINT16_MAX-1).
+     */
+    DECLCALLBACKMEMBER(uint64_t, pfnBadCpuIndex)(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu);
+
+    /** Number of 1ns steps because of overshooting the period. */
+    uint32_t            c1nsSteps;
+    /** The number of times the interval expired (overflow). */
+    uint32_t            cExpired;
+    /** Number of "bad" previous values. */
+    uint32_t            cBadPrev;
+    /** The number of update races. */
+    uint32_t            cUpdateRaces;
+} RTTIMENANOTSDATA;
+
+#ifndef IN_RING3
+/**
+ * The Ring-3 layout of the RTTIMENANOTSDATA structure.
+ */
+typedef struct RTTIMENANOTSDATAR3
+{
+    R3PTRTYPE(uint64_t volatile  *) pu64Prev;
+    DECLR3CALLBACKMEMBER(void, pfnBad,(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS));
+    DECLR3CALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData));
+    DECLR3CALLBACKMEMBER(uint64_t, pfnBadCpuIndex,(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu));
+    uint32_t            c1nsSteps;
+    uint32_t            cExpired;
+    uint32_t            cBadPrev;
+    uint32_t            cUpdateRaces;
+} RTTIMENANOTSDATAR3;
+#else
+typedef RTTIMENANOTSDATA RTTIMENANOTSDATAR3;
+#endif
+
+#ifndef IN_RING0
+/**
+ * The Ring-3 layout of the RTTIMENANOTSDATA structure.
+ */
+typedef struct RTTIMENANOTSDATAR0
+{
+    R0PTRTYPE(uint64_t volatile  *) pu64Prev;
+    DECLR0CALLBACKMEMBER(void, pfnBad,(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS));
+    DECLR0CALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData));
+    DECLR0CALLBACKMEMBER(uint64_t, pfnBadCpuIndex,(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu));
+    uint32_t            c1nsSteps;
+    uint32_t            cExpired;
+    uint32_t            cBadPrev;
+    uint32_t            cUpdateRaces;
+} RTTIMENANOTSDATAR0;
+#else
+typedef RTTIMENANOTSDATA RTTIMENANOTSDATAR0;
+#endif
+
+#ifndef IN_RC
+/**
+ * The RC layout of the RTTIMENANOTSDATA structure.
+ */
+typedef struct RTTIMENANOTSDATARC
+{
+    RCPTRTYPE(uint64_t volatile  *) pu64Prev;
+    DECLRCCALLBACKMEMBER(void, pfnBad,(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS));
+    DECLRCCALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData));
+    DECLRCCALLBACKMEMBER(uint64_t, pfnBadCpuIndex,(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu));
+    uint32_t            c1nsSteps;
+    uint32_t            cExpired;
+    uint32_t            cBadPrev;
+    uint32_t            cUpdateRaces;
+} RTTIMENANOTSDATARC;
+#else
+typedef RTTIMENANOTSDATA RTTIMENANOTSDATARC;
+#endif
+
+/** Internal RTTimeNanoTS worker (assembly). */
+typedef DECLCALLBACK(uint64_t) FNTIMENANOTSINTERNAL(PRTTIMENANOTSDATA pData);
+/** Pointer to an internal RTTimeNanoTS worker (assembly). */
+typedef FNTIMENANOTSINTERNAL *PFNTIMENANOTSINTERNAL;
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarNoDelta(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarNoDelta(PRTTIMENANOTSDATA pData);
+#ifdef IN_RING3
+RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseApicId(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseRdtscp(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseIdtrLim(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseApicId(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseRdtscp(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseIdtrLim(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim(PRTTIMENANOTSDATA pData);
+#else
+RTDECL(uint64_t) RTTimeNanoTSLegacyAsync(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDelta(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceAsync(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDelta(PRTTIMENANOTSDATA pData);
+#endif
+
+/** @} */
+
+
+/**
+ * Gets the current nanosecond timestamp.
+ *
+ * This differs from RTTimeNanoTS in that it will use system APIs and not do any
+ * resolution or performance optimizations.
+ *
+ * @returns nanosecond timestamp.
+ */
+RTDECL(uint64_t) RTTimeSystemNanoTS(void);
+
+/**
+ * Gets the current millisecond timestamp.
+ *
+ * This differs from RTTimeNanoTS in that it will use system APIs and not do any
+ * resolution or performance optimizations.
+ *
+ * @returns millisecond timestamp.
+ */
+RTDECL(uint64_t) RTTimeSystemMilliTS(void);
+
+/**
+ * Get the nanosecond timestamp relative to program startup.
+ *
+ * @returns Timestamp relative to program startup.
+ */
+RTDECL(uint64_t)  RTTimeProgramNanoTS(void);
+
+/**
+ * Get the microsecond timestamp relative to program startup.
+ *
+ * @returns Timestamp relative to program startup.
+ */
+RTDECL(uint64_t)  RTTimeProgramMicroTS(void);
+
+/**
+ * Get the millisecond timestamp relative to program startup.
+ *
+ * @returns Timestamp relative to program startup.
+ */
+RTDECL(uint64_t)  RTTimeProgramMilliTS(void);
+
+/**
+ * Get the second timestamp relative to program startup.
+ *
+ * @returns Timestamp relative to program startup.
+ */
+RTDECL(uint32_t)  RTTimeProgramSecTS(void);
+
+/**
+ * Get the RTTimeNanoTS() of when the program started.
+ *
+ * @returns Program startup timestamp.
+ */
+RTDECL(uint64_t) RTTimeProgramStartNanoTS(void);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/timer.h b/ubuntu/vbox/include/iprt/timer.h
new file mode 100644 (file)
index 0000000..920faa6
--- /dev/null
@@ -0,0 +1,387 @@
+/** @file
+ * IPRT - Timer.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_timer_h
+#define ___iprt_timer_h
+
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_timer      RTTimer - Timer
+ *
+ * The IPRT timer API provides a simple abstraction of recurring and one-shot callback timers.
+ *
+ * Because of the great variation in the native APIs and the quality of
+ * the service delivered by those native APIs, the timers are operated
+ * on at best effort basis.
+ *
+ * All the ring-3 implementations are naturally at the mercy of the scheduler,
+ * which means that the callback rate might vary quite a bit and we might skip
+ * ticks. Many systems have a restriction that a process can only have one
+ * timer. IPRT currently makes no efforts at multiplexing timers in those kind
+ * of situations and will simply fail if you try to create more than one timer.
+ *
+ * Things are generally better in ring-0. The implementations will use interrupt
+ * time callbacks wherever available, and if not, resort to a high priority
+ * kernel thread.
+ *
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/** Timer handle. */
+typedef struct RTTIMER   *PRTTIMER;
+
+/**
+ * Timer callback function.
+ *
+ * The context this call is made in varies with different platforms and
+ * kernel / user mode IPRT.
+ *
+ * In kernel mode a timer callback should not waste time, it shouldn't
+ * waste stack and it should be prepared that some APIs might not work
+ * correctly because of weird OS restrictions in this context that we
+ * haven't discovered and avoided yet. Please fix those APIs so they
+ * at least avoid panics and weird behaviour.
+ *
+ * @param   pTimer      Timer handle.
+ * @param   pvUser      User argument.
+ * @param   iTick       The current timer tick. This is always 1 on the first
+ *                      callback after the timer was started. For omni timers
+ *                      this will be 1 when a cpu comes back online.
+ */
+typedef DECLCALLBACK(void) FNRTTIMER(PRTTIMER pTimer, void *pvUser, uint64_t iTick);
+/** Pointer to FNRTTIMER() function. */
+typedef FNRTTIMER *PFNRTTIMER;
+
+
+/**
+ * Create a recurring timer.
+ *
+ * @returns iprt status code.
+ * @param   ppTimer             Where to store the timer handle.
+ * @param   uMilliesInterval    Milliseconds between the timer ticks.
+ *                              This is rounded up to the system granularity.
+ * @param   pfnTimer            Callback function which shall be scheduled for execution
+ *                              on every timer tick.
+ * @param   pvUser              User argument for the callback.
+ * @see     RTTimerCreateEx, RTTimerStart, RTTimerStop, RTTimerChangeInterval,
+ *          RTTimerDestroy, RTTimerGetSystemGranularity
+ */
+RTDECL(int) RTTimerCreate(PRTTIMER *ppTimer, unsigned uMilliesInterval, PFNRTTIMER pfnTimer, void *pvUser);
+
+/**
+ * Create a suspended timer.
+ *
+ * @returns iprt status code.
+ * @retval  VERR_NOT_SUPPORTED if an unsupported flag was specfied.
+ * @retval  VERR_CPU_NOT_FOUND if the specified CPU
+ *
+ * @param   ppTimer             Where to store the timer handle.
+ * @param   u64NanoInterval     The interval between timer ticks specified in nanoseconds if it's
+ *                              a recurring timer. This is rounded to the fit the system timer granularity.
+ *                              For one shot timers, pass 0.
+ * @param   fFlags              Timer flags.
+ * @param   pfnTimer            Callback function which shall be scheduled for execution
+ *                              on every timer tick.
+ * @param   pvUser              User argument for the callback.
+ * @see     RTTimerStart, RTTimerStop, RTTimerChangeInterval, RTTimerDestroy,
+ *          RTTimerGetSystemGranularity, RTTimerCanDoHighResolution
+ */
+RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser);
+
+/** @name RTTimerCreateEx flags
+ * @{ */
+/** Any CPU is fine. (Must be 0.) */
+#define RTTIMER_FLAGS_CPU_ANY       UINT32_C(0)
+/** One specific CPU */
+#define RTTIMER_FLAGS_CPU_SPECIFIC  RT_BIT(16)
+/** Omni timer, run on all online CPUs.
+ * @remarks The timer callback isn't necessarily running at the time same time on each CPU. */
+#define RTTIMER_FLAGS_CPU_ALL       ( RTTIMER_FLAGS_CPU_MASK | RTTIMER_FLAGS_CPU_SPECIFIC )
+/** CPU mask. */
+#define RTTIMER_FLAGS_CPU_MASK      UINT32_C(0xffff)
+/** Desire a high resolution timer that works with RTTimerChangeInterval and
+ * isn't subject to RTTimerGetSystemGranularity rounding.
+ * @remarks This is quietly ignored if the feature isn't supported. */
+#define RTTIMER_FLAGS_HIGH_RES      RT_BIT(17)
+/** Convert a CPU set index (0-based) to RTTimerCreateEx flags.
+ * This will automatically OR in the RTTIMER_FLAGS_CPU_SPECIFIC flag. */
+#define RTTIMER_FLAGS_CPU(iCpu)     ( (iCpu) | RTTIMER_FLAGS_CPU_SPECIFIC )
+/** Macro that validates the flags. */
+#define RTTIMER_FLAGS_ARE_VALID(fFlags) \
+    ( !((fFlags) & ~((fFlags) & RTTIMER_FLAGS_CPU_SPECIFIC ? UINT32_C(0x3ffff) : UINT32_C(0x30000))) )
+/** @} */
+
+/**
+ * Stops and destroys a running timer.
+ *
+ * @returns iprt status code.
+ * @retval  VERR_INVALID_CONTEXT if executing at the wrong IRQL (windows), PIL
+ *          (solaris), or similar.  Portable code does not destroy timers with
+ *          preemption (or interrupts) disabled.
+ * @param   pTimer      Timer to stop and destroy. NULL is ok.
+ */
+RTDECL(int) RTTimerDestroy(PRTTIMER pTimer);
+
+/**
+ * Starts a suspended timer.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_HANDLE if pTimer isn't valid.
+ * @retval  VERR_TIMER_ACTIVE if the timer isn't suspended.
+ * @retval  VERR_CPU_OFFLINE if the CPU the timer was created to run on is not
+ *          online (this include the case where it's not present in the
+ *          system).
+ *
+ * @param   pTimer      The timer to activate.
+ * @param   u64First    The RTTimeSystemNanoTS() for when the timer should start
+ *                      firing (relative).  If 0 is specified, the timer will
+ *                      fire ASAP.
+ * @remarks When RTTimerCanDoHighResolution returns true, this API is
+ *          callable with preemption disabled in ring-0.
+ * @see     RTTimerStop
+ */
+RTDECL(int) RTTimerStart(PRTTIMER pTimer, uint64_t u64First);
+
+/**
+ * Stops an active timer.
+ *
+ * @todo    May return while the timer callback function is being services on
+ *          some platforms (ring-0 Windows, ring-0 linux).  This needs to be
+ *          addressed at some point...
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_HANDLE if pTimer isn't valid.
+ * @retval  VERR_TIMER_SUSPENDED if the timer isn't active.
+ * @retval  VERR_NOT_SUPPORTED if the IPRT implementation doesn't support
+ *          stopping a timer.
+ *
+ * @param   pTimer  The timer to suspend.
+ * @remarks Can be called from the timer callback function to stop it.
+ * @see     RTTimerStart
+ */
+RTDECL(int) RTTimerStop(PRTTIMER pTimer);
+
+/**
+ * Changes the interval of a periodic timer.
+ *
+ * If the timer is active, it is implementation dependent whether the change
+ * takes place immediately or after the next tick.  To get defined behavior,
+ * stop the timer before calling this API.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_HANDLE if pTimer isn't valid.
+ * @retval  VERR_NOT_SUPPORTED if not supported.
+ * @retval  VERR_INVALID_STATE if not a periodic timer.
+ *
+ * @param   pTimer              The timer to activate.
+ * @param   u64NanoInterval     The interval between timer ticks specified in
+ *                              nanoseconds.  This is rounded to the fit the
+ *                              system timer granularity.
+ * @remarks Callable from the timer callback.  Callable with preemption
+ *          disabled in ring-0.
+ */
+RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval);
+
+/**
+ * Gets the (current) timer granularity of the system.
+ *
+ * @returns The timer granularity of the system in nanoseconds.
+ * @see     RTTimerRequestSystemGranularity
+ */
+RTDECL(uint32_t) RTTimerGetSystemGranularity(void);
+
+/**
+ * Requests a specific system timer granularity.
+ *
+ * Successfull calls to this API must be coupled with the exact same number of
+ * calls to RTTimerReleaseSystemGranularity() in order to undo any changes made.
+ *
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NOT_SUPPORTED if the requested value isn't supported by the host platform
+ *          or if the host platform doesn't support modifying the system timer granularity.
+ * @retval  VERR_PERMISSION_DENIED if the caller doesn't have the necessary privilege to
+ *          modify the system timer granularity.
+ *
+ * @param   u32Request      The requested system timer granularity in nanoseconds.
+ * @param   pu32Granted     Where to store the granted system granularity. This is the value
+ *                          that should be passed to  RTTimerReleaseSystemGranularity(). It
+ *                          is what RTTimerGetSystemGranularity() would return immediately
+ *                          after the change was made.
+ *
+ *                          The value differ from the request in two ways; rounding and
+ *                          scale. Meaning if your request is for 10.000.000 you might
+ *                          be granted 10.000.055 or 1.000.000.
+ * @see     RTTimerReleaseSystemGranularity, RTTimerGetSystemGranularity
+ */
+RTDECL(int) RTTimerRequestSystemGranularity(uint32_t u32Request, uint32_t *pu32Granted);
+
+/**
+ * Releases a system timer granularity grant acquired by RTTimerRequestSystemGranularity().
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NOT_SUPPORTED if the host platform doesn't have any way of modifying
+ *          the system timer granularity.
+ * @retval  VERR_WRONG_ORDER if nobody call RTTimerRequestSystemGranularity() with the
+ *          given grant value.
+ * @param   u32Granted      The granted system granularity.
+ * @see     RTTimerRequestSystemGranularity
+ */
+RTDECL(int) RTTimerReleaseSystemGranularity(uint32_t u32Granted);
+
+/**
+ * Checks if the system support high resolution timers.
+ *
+ * The kind of support we are checking for is the kind of dynamically
+ * reprogrammable timers employed by recent Solaris and Linux kernels.  It also
+ * implies that we can specify microsecond (or even better maybe) intervals
+ * without getting into trouble.
+ *
+ * @returns true if supported, false it not.
+ *
+ * @remarks Returning true also means RTTimerChangeInterval must be implemented
+ *          and RTTimerStart be callable with preemption disabled.
+ */
+RTDECL(bool) RTTimerCanDoHighResolution(void);
+
+
+/**
+ * Timer callback function for low res timers.
+ *
+ * This is identical to FNRTTIMER except for the first parameter, so
+ * see FNRTTIMER for details.
+ *
+ * @param   hTimerLR    The low resolution timer handle.
+ * @param   pvUser      User argument.
+ * @param   iTick       The current timer tick. This is always 1 on the first
+ *                      callback after the timer was started. Will jump if we've
+ *                      skipped ticks when lagging behind.
+ */
+typedef DECLCALLBACK(void) FNRTTIMERLR(RTTIMERLR hTimerLR, void *pvUser, uint64_t iTick);
+/** Pointer to FNRTTIMER() function. */
+typedef FNRTTIMERLR *PFNRTTIMERLR;
+
+
+/**
+ * Create a recurring low resolution timer.
+ *
+ * @returns iprt status code.
+ * @param   phTimerLR           Where to store the timer handle.
+ * @param   uMilliesInterval    Milliseconds between the timer ticks, at least 100 ms.
+ *                              If higher resolution is required use the other API.
+ * @param   pfnTimer            Callback function which shall be scheduled for execution
+ *                              on every timer tick.
+ * @param   pvUser              User argument for the callback.
+ * @see     RTTimerLRCreateEx, RTTimerLRDestroy, RTTimerLRStop
+ */
+RTDECL(int) RTTimerLRCreate(PRTTIMERLR phTimerLR, uint32_t uMilliesInterval, PFNRTTIMERLR pfnTimer, void *pvUser);
+
+/**
+ * Create a suspended low resolution timer.
+ *
+ * @returns iprt status code.
+ * @retval  VERR_NOT_SUPPORTED if an unsupported flag was specfied.
+ *
+ * @param   phTimerLR           Where to store the timer handle.
+ * @param   u64NanoInterval     The interval between timer ticks specified in nanoseconds if it's
+ *                              a recurring timer, the minimum for is 100000000 ns.
+ *                              For one shot timers, pass 0.
+ * @param   fFlags              Timer flags. Same as RTTimerCreateEx.
+ * @param   pfnTimer            Callback function which shall be scheduled for execution
+ *                              on every timer tick.
+ * @param   pvUser              User argument for the callback.
+ * @see     RTTimerLRStart, RTTimerLRStop, RTTimerLRDestroy
+ */
+RTDECL(int) RTTimerLRCreateEx(PRTTIMERLR phTimerLR, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMERLR pfnTimer, void *pvUser);
+
+/**
+ * Stops and destroys a running low resolution timer.
+ *
+ * @returns iprt status code.
+ * @param   hTimerLR            The low resolution timer to stop and destroy.
+ *                              NIL_RTTIMERLR is accepted.
+ */
+RTDECL(int) RTTimerLRDestroy(RTTIMERLR hTimerLR);
+
+/**
+ * Starts a low resolution timer.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_HANDLE if pTimer isn't valid.
+ * @retval  VERR_TIMER_ACTIVE if the timer isn't suspended.
+ *
+ * @param   hTimerLR            The low resolution timer to activate.
+ * @param   u64First            The RTTimeSystemNanoTS() for when the timer should start
+ *                              firing (relative), the minimum is 100000000 ns.
+ *                              If 0 is specified, the timer will fire ASAP.
+ *
+ * @see     RTTimerLRStop
+ */
+RTDECL(int) RTTimerLRStart(RTTIMERLR hTimerLR, uint64_t u64First);
+
+/**
+ * Stops an active low resolution timer.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_HANDLE if pTimer isn't valid.
+ * @retval  VERR_TIMER_SUSPENDED if the timer isn't active.
+ * @retval  VERR_NOT_SUPPORTED if the IPRT implementation doesn't support stopping a timer.
+ *
+ * @param   hTimerLR            The low resolution timer to suspend.
+ *
+ * @see     RTTimerLRStart
+ */
+RTDECL(int) RTTimerLRStop(RTTIMERLR hTimerLR);
+
+/**
+ * Changes the interval of a low resolution timer.
+ *
+ * If the timer is active, the next tick will occure immediately just like with
+ * RTTimerLRStart() when u64First parameter is zero.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_HANDLE if pTimer isn't valid.
+ * @retval  VERR_NOT_SUPPORTED if not supported.
+ *
+ * @param   hTimerLR            The low resolution timer to update.
+ * @param   u64NanoInterval     The interval between timer ticks specified in
+ *                              nanoseconds.  This is rounded to the fit the
+ *                              system timer granularity.
+ * @remarks Callable from the timer callback.
+ */
+RTDECL(int) RTTimerLRChangeInterval(RTTIMERLR hTimerLR, uint64_t u64NanoInterval);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
diff --git a/ubuntu/vbox/include/iprt/types.h b/ubuntu/vbox/include/iprt/types.h
new file mode 100644 (file)
index 0000000..fee3303
--- /dev/null
@@ -0,0 +1,3157 @@
+/** @file
+ * IPRT - Types.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_types_h
+#define ___iprt_types_h
+
+#include <iprt/cdefs.h>
+#include <iprt/stdint.h>
+#include <iprt/stdarg.h>
+
+/*
+ * Include standard C types.
+ */
+#ifndef IPRT_NO_CRT
+
+# if defined(IN_XF86_MODULE) && !defined(NO_ANSIC)
+    /*
+     * Kludge for xfree86 modules: size_t and other types are redefined.
+     */
+RT_C_DECLS_BEGIN
+#  include "xf86_ansic.h"
+#  undef NULL
+RT_C_DECLS_END
+
+# elif defined(RT_OS_DARWIN) && defined(KERNEL)
+    /*
+     * Kludge for the darwin kernel:
+     *  stddef.h is missing IIRC.
+     */
+#  ifndef _PTRDIFF_T
+#  define _PTRDIFF_T
+    typedef __darwin_ptrdiff_t ptrdiff_t;
+#  endif
+#  include <sys/types.h>
+
+# elif defined(RT_OS_FREEBSD) && defined(_KERNEL)
+    /*
+     * Kludge for the FreeBSD kernel:
+     *  stddef.h and sys/types.h have slightly different offsetof definitions
+     *  when compiling in kernel mode. This is just to make GCC shut up.
+     */
+#  ifndef _STDDEF_H_
+#   undef offsetof
+#  endif
+#  include <sys/stddef.h>
+#  ifndef _SYS_TYPES_H_
+#   undef offsetof
+#  endif
+#  include <sys/types.h>
+#  ifndef offsetof
+#   error "offsetof is not defined!"
+#  endif
+
+# elif defined(RT_OS_FREEBSD) && HC_ARCH_BITS == 64 && defined(RT_ARCH_X86)
+    /*
+     * Kludge for compiling 32-bit code on a 64-bit FreeBSD:
+     *  FreeBSD declares uint64_t and int64_t wrong (long unsigned and long int
+     *  though they need to be long long unsigned and long long int). These
+     *  defines conflict with our declaration in stdint.h. Adding the defines
+     *  below omits the definitions in the system header.
+     */
+#  include <stddef.h>
+#  define _UINT64_T_DECLARED
+#  define _INT64_T_DECLARED
+#  define _UINTPTR_T_DECLARED
+#  define _INTPTR_T_DECLARED
+#  include <sys/types.h>
+
+# elif defined(RT_OS_NETBSD) && defined(_KERNEL)
+
+#  include <sys/types.h>
+
+   /*
+    * Kludge for NetBSD-6.x where the definition of bool in
+    * <sys/types.h> does not check for C++.
+    */
+#  if defined(__cplusplus) && defined(bool)
+#   undef bool
+#   undef true
+#   undef false
+#  endif
+
+   /*
+    * Kludge for NetBSD-6.x where <sys/types.h> does not define
+    * ptrdiff_t for the kernel code.  Note that we don't worry about
+    * redefinition in <stddef.h> since that header doesn't exist for
+    * _KERNEL code.
+    */
+#  ifdef _BSD_PTRDIFF_T_
+    typedef _BSD_PTRDIFF_T_ ptrdiff_t;
+#  endif
+
+# elif defined(RT_OS_LINUX) && defined(__KERNEL__)
+    /*
+     * Kludge for the linux kernel:
+     *   1. sys/types.h doesn't mix with the kernel.
+     *   2. Starting with 2.6.19, linux/types.h typedefs bool and linux/stddef.h
+     *      declares false and true as enum values.
+     *   3. Starting with 2.6.24, linux/types.h typedefs uintptr_t.
+     * We work around these issues here and nowhere else.
+     */
+#  include <stddef.h>
+#  if defined(__cplusplus)
+    typedef bool _Bool;
+#  endif
+#  define bool linux_bool
+#  define true linux_true
+#  define false linux_false
+#  define uintptr_t linux_uintptr_t
+#  include <linux/version.h>
+#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
+#   include <generated/autoconf.h>
+#  else
+#   ifndef AUTOCONF_INCLUDED
+#    include <linux/autoconf.h>
+#   endif
+#  endif
+#  include <linux/compiler.h>
+#  if defined(__cplusplus)
+    /*
+     * Starting with 3.3, <linux/compiler-gcc.h> appends 'notrace' (which
+     * expands to __attribute__((no_instrument_function))) to inline,
+     * __inline and __inline__. Revert that.
+     */
+#   undef inline
+#   define inline inline
+#   undef __inline__
+#   define __inline__ __inline__
+#   undef __inline
+#   define __inline __inline
+#  endif
+#  include <linux/types.h>
+#  include <linux/stddef.h>
+    /*
+     * Starting with 3.4, <linux/stddef.h> defines NULL as '((void*)0)' which
+     * does not work for C++ code.
+     */
+#  undef NULL
+#  undef uintptr_t
+#  ifdef __GNUC__
+#   if !RT_GNUC_PREREQ(4, 1)
+     /*
+      * <linux/compiler-gcc{3,4}.h> does
+      *   #define __inline__  __inline__ __attribute__((always_inline))
+      * in some older Linux kernels. Forcing inlining will fail for some RTStrA*
+      * functions with gcc <= 4.0 due to passing variable argument lists.
+      */
+#    undef __inline__
+#    define __inline__ __inline__
+#   endif
+#  endif
+#  undef false
+#  undef true
+#  undef bool
+# else
+#  include <stddef.h>
+#  include <sys/types.h>
+# endif
+
+
+/* Define any types missing from sys/types.h on windows. */
+# ifdef _MSC_VER
+#  undef ssize_t
+   typedef intptr_t ssize_t;
+# endif
+
+#else  /* no crt */
+# include <iprt/nocrt/compiler/compiler.h>
+#endif /* no crt */
+
+
+
+/** @def NULL
+ * NULL pointer.
+ */
+#ifndef NULL
+# ifdef __cplusplus
+#  define NULL 0
+# else
+#  define NULL ((void*)0)
+# endif
+#endif
+
+
+
+/** @defgroup grp_rt_types  IPRT Base Types
+ * @{
+ */
+
+/* define wchar_t, we don't wanna include all the wcsstuff to get this. */
+#ifdef _MSC_VER
+# ifndef _WCHAR_T_DEFINED
+  typedef unsigned short wchar_t;
+# define _WCHAR_T_DEFINED
+# endif
+#endif
+#ifdef __GNUC__
+/** @todo wchar_t on GNUC */
+#endif
+
+/*
+ * C doesn't have bool, nor does VisualAge for C++ v3.08.
+ */
+#if !defined(__cplusplus) || (defined(__IBMCPP__) && defined(RT_OS_OS2))
+# if defined(__GNUC__)
+#  if defined(RT_OS_LINUX) && __GNUC__ < 3
+typedef uint8_t bool;
+#  elif defined(RT_OS_FREEBSD)
+#   ifndef __bool_true_false_are_defined
+typedef _Bool bool;
+#   endif
+#  elif defined(RT_OS_NETBSD)
+#   if !defined(_KERNEL)
+     /*
+      * For the kernel code <stdbool.h> is not available, but bool is
+      * provided by <sys/types.h> included above.
+      */
+#    include <stdbool.h>
+
+     /*
+      * ... but the story doesn't end here.  The C standard says that
+      * <stdbool.h> defines preprocessor macro "bool" that expands to
+      * "_Bool", but adds that a program may undefine/redefine it
+      * (this is 7.16 in C99 and 7.18 in C11).  We have to play this
+      * game here because X11 code uses "bool" as a struct member name
+      * - so undefine "bool" and provide it as a typedef instead.  We
+      * still keep #include <stdbool.h> so that any code that might
+      * include it later doesn't mess things up.
+      */
+#    undef bool
+     typedef _Bool bool;
+#   endif
+#  else
+#   if (defined(RT_OS_DARWIN) || defined(RT_OS_HAIKU)) && (defined(_STDBOOL_H) || defined(__STDBOOL_H))
+#    undef bool
+#   endif
+typedef _Bool bool;
+#  endif
+# else
+typedef unsigned char bool;
+# endif
+# ifndef true
+#  define true  (1)
+# endif
+# ifndef false
+#  define false (0)
+# endif
+#endif
+
+/**
+ * 128-bit unsigned integer.
+ */
+#if defined(__GNUC__) && defined(RT_ARCH_AMD64)
+typedef __uint128_t uint128_t;
+#else
+typedef struct uint128_s
+{
+# ifdef RT_BIG_ENDIAN
+    uint64_t    Hi;
+    uint64_t    Lo;
+# else
+    uint64_t    Lo;
+    uint64_t    Hi;
+# endif
+} uint128_t;
+#endif
+
+
+/**
+ * 128-bit signed integer.
+ */
+#if defined(__GNUC__) && defined(RT_ARCH_AMD64)
+typedef __int128_t int128_t;
+#else
+typedef struct int128_s
+{
+# ifdef RT_BIG_ENDIAN
+    int64_t     Hi;
+    uint64_t    Lo;
+# else
+    uint64_t    Lo;
+    int64_t     Hi;
+# endif
+} int128_t;
+#endif
+
+
+/**
+ * 16-bit unsigned integer union.
+ */
+typedef union RTUINT16U
+{
+    /** natural view. */
+    uint16_t    u;
+
+    /** 16-bit view. */
+    uint16_t    au16[1];
+    /** 8-bit view. */
+    uint8_t     au8[2];
+    /** 16-bit hi/lo view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint8_t    Hi;
+        uint8_t    Lo;
+#else
+        uint8_t    Lo;
+        uint8_t    Hi;
+#endif
+    } s;
+} RTUINT16U;
+/** Pointer to a 16-bit unsigned integer union. */
+typedef RTUINT16U *PRTUINT16U;
+/** Pointer to a const 32-bit unsigned integer union. */
+typedef const RTUINT16U *PCRTUINT16U;
+
+
+/**
+ * 32-bit unsigned integer union.
+ */
+typedef union RTUINT32U
+{
+    /** natural view. */
+    uint32_t    u;
+    /** Hi/Low view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint16_t    Hi;
+        uint16_t    Lo;
+#else
+        uint16_t    Lo;
+        uint16_t    Hi;
+#endif
+    } s;
+    /** Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint16_t    w1;
+        uint16_t    w0;
+#else
+        uint16_t    w0;
+        uint16_t    w1;
+#endif
+    } Words;
+
+    /** 32-bit view. */
+    uint32_t    au32[1];
+    /** 16-bit view. */
+    uint16_t    au16[2];
+    /** 8-bit view. */
+    uint8_t     au8[4];
+} RTUINT32U;
+/** Pointer to a 32-bit unsigned integer union. */
+typedef RTUINT32U *PRTUINT32U;
+/** Pointer to a const 32-bit unsigned integer union. */
+typedef const RTUINT32U *PCRTUINT32U;
+
+
+/**
+ * 64-bit unsigned integer union.
+ */
+typedef union RTUINT64U
+{
+    /** Natural view. */
+    uint64_t    u;
+    /** Hi/Low view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint32_t    Hi;
+        uint32_t    Lo;
+#else
+        uint32_t    Lo;
+        uint32_t    Hi;
+#endif
+    } s;
+    /** Double-Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint32_t    dw1;
+        uint32_t    dw0;
+#else
+        uint32_t    dw0;
+        uint32_t    dw1;
+#endif
+    } DWords;
+    /** Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint16_t    w3;
+        uint16_t    w2;
+        uint16_t    w1;
+        uint16_t    w0;
+#else
+        uint16_t    w0;
+        uint16_t    w1;
+        uint16_t    w2;
+        uint16_t    w3;
+#endif
+    } Words;
+
+    /** 64-bit view. */
+    uint64_t    au64[1];
+    /** 32-bit view. */
+    uint32_t    au32[2];
+    /** 16-bit view. */
+    uint16_t    au16[4];
+    /** 8-bit view. */
+    uint8_t     au8[8];
+} RTUINT64U;
+/** Pointer to a 64-bit unsigned integer union. */
+typedef RTUINT64U *PRTUINT64U;
+/** Pointer to a const 64-bit unsigned integer union. */
+typedef const RTUINT64U *PCRTUINT64U;
+
+
+/**
+ * 128-bit unsigned integer union.
+ */
+#pragma pack(1)
+typedef union RTUINT128U
+{
+    /** Hi/Low view.
+     * @remarks We put this first so we can have portable initializers
+     *          (RTUINT128_INIT) */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint64_t    Hi;
+        uint64_t    Lo;
+#else
+        uint64_t    Lo;
+        uint64_t    Hi;
+#endif
+    } s;
+
+    /** Natural view.
+     * WARNING! This member depends on the compiler supporting 128-bit stuff. */
+    uint128_t   u;
+
+    /** Quad-Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint64_t    qw1;
+        uint64_t    qw0;
+#else
+        uint64_t    qw0;
+        uint64_t    qw1;
+#endif
+    } QWords;
+    /** Double-Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint32_t    dw3;
+        uint32_t    dw2;
+        uint32_t    dw1;
+        uint32_t    dw0;
+#else
+        uint32_t    dw0;
+        uint32_t    dw1;
+        uint32_t    dw2;
+        uint32_t    dw3;
+#endif
+    } DWords;
+    /** Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint16_t    w7;
+        uint16_t    w6;
+        uint16_t    w5;
+        uint16_t    w4;
+        uint16_t    w3;
+        uint16_t    w2;
+        uint16_t    w1;
+        uint16_t    w0;
+#else
+        uint16_t    w0;
+        uint16_t    w1;
+        uint16_t    w2;
+        uint16_t    w3;
+        uint16_t    w4;
+        uint16_t    w5;
+        uint16_t    w6;
+        uint16_t    w7;
+#endif
+    } Words;
+
+    /** 64-bit view. */
+    uint64_t    au64[2];
+    /** 32-bit view. */
+    uint32_t    au32[4];
+    /** 16-bit view. */
+    uint16_t    au16[8];
+    /** 8-bit view. */
+    uint8_t     au8[16];
+} RTUINT128U;
+#pragma pack()
+/** Pointer to a 128-bit unsigned integer union. */
+typedef RTUINT128U *PRTUINT128U;
+/** Pointer to a const 128-bit unsigned integer union. */
+typedef const RTUINT128U *PCRTUINT128U;
+
+/** @def RTUINT128_INIT
+ * Portable RTUINT128U initializer. */
+#ifdef RT_BIG_ENDIAN
+# define RTUINT128_INIT(a_Hi, a_Lo) { { a_Hi, a_Lo } }
+#else
+# define RTUINT128_INIT(a_Hi, a_Lo) { { a_Lo, a_Hi } }
+#endif
+
+/** @def RTUINT128_INIT_C
+ * Portable RTUINT128U initializer for 64-bit constants. */
+#ifdef RT_BIG_ENDIAN
+# define RTUINT128_INIT_C(a_Hi, a_Lo) { { UINT64_C(a_Hi), UINT64_C(a_Lo) } }
+#else
+# define RTUINT128_INIT_C(a_Hi, a_Lo) { { UINT64_C(a_Lo), UINT64_C(a_Hi) } }
+#endif
+
+
+/**
+ * 256-bit unsigned integer union.
+ */
+#pragma pack(1)
+typedef union RTUINT256U
+{
+    /** Quad-Word view (first as it's used by RTUINT256_INIT). */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint64_t    qw3;
+        uint64_t    qw2;
+        uint64_t    qw1;
+        uint64_t    qw0;
+#else
+        uint64_t    qw0;
+        uint64_t    qw1;
+        uint64_t    qw2;
+        uint64_t    qw3;
+#endif
+    } QWords;
+    /** Double-Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint32_t    dw7;
+        uint32_t    dw6;
+        uint32_t    dw5;
+        uint32_t    dw4;
+        uint32_t    dw3;
+        uint32_t    dw2;
+        uint32_t    dw1;
+        uint32_t    dw0;
+#else
+        uint32_t    dw0;
+        uint32_t    dw1;
+        uint32_t    dw2;
+        uint32_t    dw3;
+        uint32_t    dw4;
+        uint32_t    dw5;
+        uint32_t    dw6;
+        uint32_t    dw7;
+#endif
+    } DWords;
+    /** Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint16_t    w15;
+        uint16_t    w14;
+        uint16_t    w13;
+        uint16_t    w12;
+        uint16_t    w11;
+        uint16_t    w10;
+        uint16_t    w9;
+        uint16_t    w8;
+        uint16_t    w7;
+        uint16_t    w6;
+        uint16_t    w5;
+        uint16_t    w4;
+        uint16_t    w3;
+        uint16_t    w2;
+        uint16_t    w1;
+        uint16_t    w0;
+#else
+        uint16_t    w0;
+        uint16_t    w1;
+        uint16_t    w2;
+        uint16_t    w3;
+        uint16_t    w4;
+        uint16_t    w5;
+        uint16_t    w6;
+        uint16_t    w7;
+        uint16_t    w8;
+        uint16_t    w9;
+        uint16_t    w10;
+        uint16_t    w11;
+        uint16_t    w12;
+        uint16_t    w13;
+        uint16_t    w14;
+        uint16_t    w15;
+#endif
+    } Words;
+
+    /** Double-Quad-Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        RTUINT128U  dqw1;
+        RTUINT128U  dqw0;
+#else
+        RTUINT128U  dqw0;
+        RTUINT128U  dqw1;
+#endif
+    } DQWords;
+
+    /** 128-bit view. */
+    RTUINT128U  au128[2];
+    /** 64-bit view. */
+    uint64_t    au64[4];
+    /** 32-bit view. */
+    uint32_t    au32[8];
+    /** 16-bit view. */
+    uint16_t    au16[16];
+    /** 8-bit view. */
+    uint8_t     au8[32];
+} RTUINT256U;
+#pragma pack()
+/** Pointer to a 256-bit unsigned integer union. */
+typedef RTUINT256U *PRTUINT256U;
+/** Pointer to a const 256-bit unsigned integer union. */
+typedef const RTUINT256U *PCRTUINT256U;
+
+/** @def RTUINT256_INIT
+ * Portable RTUINT256U initializer. */
+#ifdef RT_BIG_ENDIAN
+# define RTUINT256_INIT(a_Qw3, a_Qw2, a_Qw1, a_Qw0)   { { a_Qw3, a_Qw2, a_Qw1, a_Qw0 } }
+#else
+# define RTUINT256_INIT(a_Qw3, a_Qw2, a_Qw1, a_Qw0)   { { a_Qw0, a_Qw1, a_Qw2, a_Qw3 } }
+#endif
+
+/** @def RTUINT256_INIT_C
+ * Portable RTUINT256U initializer for 64-bit constants. */
+#define RTUINT256_INIT_C(a_Qw3, a_Qw2, a_Qw1, a_Qw0)  \
+    RTUINT256_INIT(UINT64_C(a_Qw3), UINT64_C(a_Qw2), UINT64_C(a_Qw1), UINT64_C(a_Qw0))
+
+
+/**
+ * 512-bit unsigned integer union.
+ */
+#pragma pack(1)
+typedef union RTUINT512U
+{
+    /** Quad-Word view (first as it's used by RTUINT512_INIT). */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint64_t    qw7;
+        uint64_t    qw6;
+        uint64_t    qw5;
+        uint64_t    qw4;
+        uint64_t    qw3;
+        uint64_t    qw2;
+        uint64_t    qw1;
+        uint64_t    qw0;
+#else
+        uint64_t    qw0;
+        uint64_t    qw1;
+        uint64_t    qw2;
+        uint64_t    qw3;
+        uint64_t    qw4;
+        uint64_t    qw5;
+        uint64_t    qw6;
+        uint64_t    qw7;
+#endif
+    } QWords;
+    /** Double-Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint32_t    dw15;
+        uint32_t    dw14;
+        uint32_t    dw13;
+        uint32_t    dw12;
+        uint32_t    dw11;
+        uint32_t    dw10;
+        uint32_t    dw9;
+        uint32_t    dw8;
+        uint32_t    dw7;
+        uint32_t    dw6;
+        uint32_t    dw5;
+        uint32_t    dw4;
+        uint32_t    dw3;
+        uint32_t    dw2;
+        uint32_t    dw1;
+        uint32_t    dw0;
+#else
+        uint32_t    dw0;
+        uint32_t    dw1;
+        uint32_t    dw2;
+        uint32_t    dw3;
+        uint32_t    dw4;
+        uint32_t    dw5;
+        uint32_t    dw6;
+        uint32_t    dw7;
+        uint32_t    dw8;
+        uint32_t    dw9;
+        uint32_t    dw10;
+        uint32_t    dw11;
+        uint32_t    dw12;
+        uint32_t    dw13;
+        uint32_t    dw14;
+        uint32_t    dw15;
+#endif
+    } DWords;
+    /** Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        uint16_t    w31;
+        uint16_t    w30;
+        uint16_t    w29;
+        uint16_t    w28;
+        uint16_t    w27;
+        uint16_t    w26;
+        uint16_t    w25;
+        uint16_t    w24;
+        uint16_t    w23;
+        uint16_t    w22;
+        uint16_t    w21;
+        uint16_t    w20;
+        uint16_t    w19;
+        uint16_t    w18;
+        uint16_t    w17;
+        uint16_t    w16;
+        uint16_t    w15;
+        uint16_t    w14;
+        uint16_t    w13;
+        uint16_t    w12;
+        uint16_t    w11;
+        uint16_t    w10;
+        uint16_t    w9;
+        uint16_t    w8;
+        uint16_t    w7;
+        uint16_t    w6;
+        uint16_t    w5;
+        uint16_t    w4;
+        uint16_t    w3;
+        uint16_t    w2;
+        uint16_t    w1;
+        uint16_t    w0;
+#else
+        uint16_t    w0;
+        uint16_t    w1;
+        uint16_t    w2;
+        uint16_t    w3;
+        uint16_t    w4;
+        uint16_t    w5;
+        uint16_t    w6;
+        uint16_t    w7;
+        uint16_t    w8;
+        uint16_t    w9;
+        uint16_t    w10;
+        uint16_t    w11;
+        uint16_t    w12;
+        uint16_t    w13;
+        uint16_t    w14;
+        uint16_t    w15;
+        uint16_t    w16;
+        uint16_t    w17;
+        uint16_t    w18;
+        uint16_t    w19;
+        uint16_t    w20;
+        uint16_t    w21;
+        uint16_t    w22;
+        uint16_t    w23;
+        uint16_t    w24;
+        uint16_t    w25;
+        uint16_t    w26;
+        uint16_t    w27;
+        uint16_t    w28;
+        uint16_t    w29;
+        uint16_t    w30;
+        uint16_t    w31;
+#endif
+    } Words;
+
+    /** Double-Quad-Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        RTUINT128U  dqw3;
+        RTUINT128U  dqw2;
+        RTUINT128U  dqw1;
+        RTUINT128U  dqw0;
+#else
+        RTUINT128U  dqw0;
+        RTUINT128U  dqw1;
+        RTUINT128U  dqw2;
+        RTUINT128U  dqw3;
+#endif
+    } DQWords;
+
+    /** Octo-Word view. */
+    struct
+    {
+#ifdef RT_BIG_ENDIAN
+        RTUINT256U  ow3;
+        RTUINT256U  ow2;
+        RTUINT256U  ow1;
+        RTUINT256U  ow0;
+#else
+        RTUINT256U  ow0;
+        RTUINT256U  ow1;
+        RTUINT256U  ow2;
+        RTUINT256U  ow3;
+#endif
+    } OWords;
+
+    /** 256-bit view. */
+    RTUINT256U  au256[2];
+    /** 128-bit view. */
+    RTUINT128U  au128[4];
+    /** 64-bit view. */
+    uint64_t    au64[8];
+    /** 32-bit view. */
+    uint32_t    au32[16];
+    /** 16-bit view. */
+    uint16_t    au16[32];
+    /** 8-bit view. */
+    uint8_t     au8[64];
+} RTUINT512U;
+#pragma pack()
+/** Pointer to a 512-bit unsigned integer union. */
+typedef RTUINT512U *PRTUINT512U;
+/** Pointer to a const 512-bit unsigned integer union. */
+typedef const RTUINT512U *PCRTUINT512U;
+
+/** @def RTUINT512_INIT
+ * Portable RTUINT512U initializer. */
+#ifdef RT_BIG_ENDIAN
+# define RTUINT512_INIT(a_Qw7, a_Qw6, a_Qw5, a_Qw4, a_Qw3, a_Qw2, a_Qw1, a_Qw0) \
+    { { a_Qw7, a_Qw6, a_Qw5, a_Qw4, a_Qw3, a_Qw2, a_Qw1, a_Qw0 } }
+#else
+# define RTUINT512_INIT(a_Qw7, a_Qw6, a_Qw5, a_Qw4, a_Qw3, a_Qw2, a_Qw1, a_Qw0) \
+    { { a_Qw0, a_Qw1, a_Qw2, a_Qw3, a_Qw4, a_Qw5, a_Qw6, a_Qw7 } }
+#endif
+
+/** @def RTUINT512_INIT_C
+ * Portable RTUINT512U initializer for 64-bit constants. */
+#define RTUINT512_INIT_C(a_Qw7, a_Qw6, a_Qw5, a_Qw4, a_Qw3, a_Qw2, a_Qw1, a_Qw0) \
+    RTUINT512_INIT(UINT64_C(a_Qw7), UINT64_C(a_Qw6), UINT64_C(a_Qw5), UINT64_C(a_Qw4), \
+                   UINT64_C(a_Qw3), UINT64_C(a_Qw2), UINT64_C(a_Qw1), UINT64_C(a_Qw0))
+
+
+/**
+ * Double precision floating point format (64-bit).
+ */
+typedef union RTFLOAT64U
+{
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+    /** Double view. */
+    double      rd;
+#endif
+    /** Format using regular bitfields.  */
+    struct
+    {
+# ifdef RT_BIG_ENDIAN
+        /** The sign indicator. */
+        uint32_t    fSign : 1;
+        /** The exponent (offseted by 1023). */
+        uint32_t    uExponent : 11;
+        /** The fraction, bits 32 thru 51. */
+        uint32_t    u20FractionHigh : 20;
+        /** The fraction, bits 0 thru 31. */
+        uint32_t    u32FractionLow;
+# else
+        /** The fraction, bits 0 thru 31. */
+        uint32_t    u32FractionLow;
+        /** The fraction, bits 32 thru 51. */
+        uint32_t    u20FractionHigh : 20;
+        /** The exponent (offseted by 1023). */
+        uint32_t    uExponent : 11;
+        /** The sign indicator. */
+        uint32_t    fSign : 1;
+# endif
+    } s;
+
+#ifdef RT_COMPILER_GROKS_64BIT_BITFIELDS
+    /** Format using 64-bit bitfields.  */
+    RT_GCC_EXTENSION struct
+    {
+# ifdef RT_BIG_ENDIAN
+        /** The sign indicator. */
+        RT_GCC_EXTENSION uint64_t    fSign : 1;
+        /** The exponent (offseted by 1023). */
+        RT_GCC_EXTENSION uint64_t    uExponent : 11;
+        /** The fraction. */
+        RT_GCC_EXTENSION uint64_t    uFraction : 52;
+# else
+        /** The fraction. */
+        RT_GCC_EXTENSION uint64_t    uFraction : 52;
+        /** The exponent (offseted by 1023). */
+        RT_GCC_EXTENSION uint64_t    uExponent : 11;
+        /** The sign indicator. */
+        RT_GCC_EXTENSION uint64_t    fSign : 1;
+# endif
+    } s64;
+#endif
+
+    /** 64-bit view. */
+    uint64_t    au64[1];
+    /** 32-bit view. */
+    uint32_t    au32[2];
+    /** 16-bit view. */
+    uint16_t    au16[4];
+    /** 8-bit view. */
+    uint8_t     au8[8];
+} RTFLOAT64U;
+/** Pointer to a double precision floating point format union. */
+typedef RTFLOAT64U *PRTFLOAT64U;
+/** Pointer to a const double precision floating point format union. */
+typedef const RTFLOAT64U *PCRTFLOAT64U;
+
+
+#if !defined(__IBMCPP__) && !defined(__IBMC__)
+
+/**
+ * Extended Double precision floating point format (80-bit).
+ */
+#pragma pack(1)
+typedef union RTFLOAT80U
+{
+    /** Format using bitfields.  */
+    RT_GCC_EXTENSION struct
+    {
+# ifdef RT_BIG_ENDIAN
+        /** The sign indicator. */
+        RT_GCC_EXTENSION uint16_t   fSign : 1;
+        /** The exponent (offseted by 16383). */
+        RT_GCC_EXTENSION uint16_t   uExponent : 15;
+        /** The mantissa. */
+        uint64_t                    u64Mantissa;
+# else
+        /** The mantissa. */
+        uint64_t                    u64Mantissa;
+        /** The exponent (offseted by 16383). */
+        RT_GCC_EXTENSION uint16_t   uExponent : 15;
+        /** The sign indicator. */
+        RT_GCC_EXTENSION uint16_t   fSign : 1;
+# endif
+    } s;
+
+    /** 64-bit view. */
+    uint64_t    au64[1];
+    /** 32-bit view. */
+    uint32_t    au32[2];
+    /** 16-bit view. */
+    uint16_t    au16[5];
+    /** 8-bit view. */
+    uint8_t     au8[10];
+} RTFLOAT80U;
+#pragma pack()
+/** Pointer to a extended precision floating point format union. */
+typedef RTFLOAT80U *PRTFLOAT80U;
+/** Pointer to a const extended precision floating point format union. */
+typedef const RTFLOAT80U *PCRTFLOAT80U;
+
+
+/**
+ * A variant of RTFLOAT80U that may be larger than 80-bits depending on how the
+ * compiler implements long double.
+ */
+#pragma pack(1)
+typedef union RTFLOAT80U2
+{
+#ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
+    /** Long double view. */
+    long double     lrd;
+#endif
+    /** Format using bitfields.  */
+    RT_GCC_EXTENSION struct
+    {
+#ifdef RT_BIG_ENDIAN
+        /** The sign indicator. */
+        RT_GCC_EXTENSION uint16_t   fSign : 1;
+        /** The exponent (offseted by 16383). */
+        RT_GCC_EXTENSION uint16_t   uExponent : 15;
+        /** The mantissa. */
+        uint64_t                    u64Mantissa;
+#else
+        /** The mantissa. */
+        uint64_t                    u64Mantissa;
+        /** The exponent (offseted by 16383). */
+        RT_GCC_EXTENSION uint16_t   uExponent : 15;
+        /** The sign indicator. */
+        RT_GCC_EXTENSION uint16_t   fSign : 1;
+#endif
+    } s;
+
+    /** Bitfield exposing the J bit and the fraction.  */
+    RT_GCC_EXTENSION struct
+    {
+#ifdef RT_BIG_ENDIAN
+        /** The sign indicator. */
+        RT_GCC_EXTENSION uint16_t   fSign : 1;
+        /** The exponent (offseted by 16383). */
+        RT_GCC_EXTENSION uint16_t   uExponent : 15;
+        /** The J bit, aka the integer bit. */
+        uint32_t                    fInteger;
+        /** The fraction, bits 32 thru 62. */
+        uint32_t                    u31FractionHigh : 31;
+        /** The fraction, bits 0 thru 31. */
+        uint32_t                    u32FractionLow : 32;
+#else
+        /** The fraction, bits 0 thru 31. */
+        uint32_t                    u32FractionLow : 32;
+        /** The fraction, bits 32 thru 62. */
+        uint32_t                    u31FractionHigh : 31;
+        /** The J bit, aka the integer bit. */
+        uint32_t                    fInteger;
+        /** The exponent (offseted by 16383). */
+        RT_GCC_EXTENSION uint16_t   uExponent : 15;
+        /** The sign indicator. */
+        RT_GCC_EXTENSION uint16_t   fSign : 1;
+#endif
+    } sj;
+
+#ifdef RT_COMPILER_GROKS_64BIT_BITFIELDS
+    /** 64-bit bitfields exposing the J bit and the fraction.  */
+    RT_GCC_EXTENSION struct
+    {
+# ifdef RT_BIG_ENDIAN
+        /** The sign indicator. */
+        RT_GCC_EXTENSION uint16_t   fSign : 1;
+        /** The exponent (offseted by 16383). */
+        RT_GCC_EXTENSION uint16_t   uExponent : 15;
+        /** The J bit, aka the integer bit. */
+        RT_GCC_EXTENSION uint64_t   fInteger : 1;
+        /** The fraction. */
+        RT_GCC_EXTENSION uint64_t   u63Fraction : 63;
+# else
+        /** The fraction. */
+        RT_GCC_EXTENSION uint64_t   u63Fraction : 63;
+        /** The J bit, aka the integer bit. */
+        RT_GCC_EXTENSION uint64_t   fInteger : 1;
+        /** The exponent (offseted by 16383). */
+        RT_GCC_EXTENSION uint16_t   uExponent : 15;
+        /** The sign indicator. */
+        RT_GCC_EXTENSION uint16_t   fSign : 1;
+# endif
+    } sj64;
+#endif
+
+    /** 64-bit view. */
+    uint64_t    au64[1];
+    /** 32-bit view. */
+    uint32_t    au32[2];
+    /** 16-bit view. */
+    uint16_t    au16[5];
+    /** 8-bit view. */
+    uint8_t     au8[10];
+} RTFLOAT80U2;
+#pragma pack()
+/** Pointer to a extended precision floating point format union, 2nd
+ * variant. */
+typedef RTFLOAT80U2 *PRTFLOAT80U2;
+/** Pointer to a const extended precision floating point format union, 2nd
+ * variant. */
+typedef const RTFLOAT80U2 *PCRTFLOAT80U2;
+
+#endif /* uint16_t bitfields doesn't work */
+
+
+/** Generic function type.
+ * @see PFNRT
+ */
+typedef DECLCALLBACK(void) FNRT(void);
+
+/** Generic function pointer.
+ * With -pedantic, gcc-4 complains when casting a function to a data object, for
+ * example:
+ *
+ * @code
+ *    void foo(void)
+ *    {
+ *    }
+ *
+ *    void *bar = (void *)foo;
+ * @endcode
+ *
+ * The compiler would warn with "ISO C++ forbids casting between
+ * pointer-to-function and pointer-to-object".  The purpose of this warning is
+ * not to bother the programmer but to point out that he is probably doing
+ * something dangerous, assigning a pointer to executable code to a data object.
+ */
+typedef FNRT *PFNRT;
+
+/** Millisecond interval. */
+typedef uint32_t            RTMSINTERVAL;
+/** Pointer to a millisecond interval. */
+typedef RTMSINTERVAL       *PRTMSINTERVAL;
+/** Pointer to a const millisecond interval. */
+typedef const RTMSINTERVAL *PCRTMSINTERVAL;
+
+/** Pointer to a time spec structure. */
+typedef struct RTTIMESPEC  *PRTTIMESPEC;
+/** Pointer to a const time spec structure. */
+typedef const struct RTTIMESPEC *PCRTTIMESPEC;
+
+
+
+/** @defgroup grp_rt_types_both  Common Guest and Host Context Basic Types
+ * @{
+ */
+
+/** Signed integer which can contain both GC and HC pointers. */
+#if (HC_ARCH_BITS == 32 && GC_ARCH_BITS == 32) || (HC_ARCH_BITS == 16 || GC_ARCH_BITS == 16)
+typedef int32_t         RTINTPTR;
+#elif (HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64)
+typedef int64_t         RTINTPTR;
+#else
+#  error Unsupported HC_ARCH_BITS and/or GC_ARCH_BITS values.
+#endif
+/** Pointer to signed integer which can contain both GC and HC pointers. */
+typedef RTINTPTR       *PRTINTPTR;
+/** Pointer const to signed integer which can contain both GC and HC pointers. */
+typedef const RTINTPTR *PCRTINTPTR;
+/** The maximum value the RTINTPTR type can hold. */
+#if (HC_ARCH_BITS == 32 && GC_ARCH_BITS == 32) || (HC_ARCH_BITS == 16 || GC_ARCH_BITS == 16)
+# define RTINTPTR_MAX   INT32_MAX
+#elif (HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64)
+# define RTINTPTR_MAX   INT64_MAX
+#else
+#  error Unsupported HC_ARCH_BITS and/or GC_ARCH_BITS values.
+#endif
+/** The minimum value the RTINTPTR type can hold. */
+#if (HC_ARCH_BITS == 32 && GC_ARCH_BITS == 32) || (HC_ARCH_BITS == 16 || GC_ARCH_BITS == 16)
+# define RTINTPTR_MIN   INT32_MIN
+#elif (HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64)
+# define RTINTPTR_MIN   INT64_MIN
+#else
+#  error Unsupported HC_ARCH_BITS and/or GC_ARCH_BITS values.
+#endif
+
+/** Unsigned integer which can contain both GC and HC pointers. */
+#if (HC_ARCH_BITS == 32 && GC_ARCH_BITS == 32) || (HC_ARCH_BITS == 16 || GC_ARCH_BITS == 16)
+typedef uint32_t        RTUINTPTR;
+#elif (HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64)
+typedef uint64_t        RTUINTPTR;
+#else
+#  error Unsupported HC_ARCH_BITS and/or GC_ARCH_BITS values.
+#endif
+/** Pointer to unsigned integer which can contain both GC and HC pointers. */
+typedef RTUINTPTR      *PRTUINTPTR;
+/** Pointer const to unsigned integer which can contain both GC and HC pointers. */
+typedef const RTUINTPTR *PCRTUINTPTR;
+/** The maximum value the RTUINTPTR type can hold. */
+#if (HC_ARCH_BITS == 32 && GC_ARCH_BITS == 32) || (HC_ARCH_BITS == 16 || GC_ARCH_BITS == 16)
+# define RTUINTPTR_MAX  UINT32_MAX
+#elif (HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64)
+# define RTUINTPTR_MAX  UINT64_MAX
+#else
+#  error Unsupported HC_ARCH_BITS and/or GC_ARCH_BITS values.
+#endif
+
+/** Signed integer. */
+typedef int32_t         RTINT;
+/** Pointer to signed integer. */
+typedef RTINT          *PRTINT;
+/** Pointer to const signed integer. */
+typedef const RTINT    *PCRTINT;
+
+/** Unsigned integer. */
+typedef uint32_t        RTUINT;
+/** Pointer to unsigned integer. */
+typedef RTUINT         *PRTUINT;
+/** Pointer to const unsigned integer. */
+typedef const RTUINT   *PCRTUINT;
+
+/** A file offset / size (off_t). */
+typedef int64_t         RTFOFF;
+/** Pointer to a file offset / size. */
+typedef RTFOFF         *PRTFOFF;
+/** The max value for RTFOFF. */
+#define RTFOFF_MAX      INT64_MAX
+/** The min value for RTFOFF. */
+#define RTFOFF_MIN      INT64_MIN
+
+/** File mode (see iprt/fs.h). */
+typedef uint32_t        RTFMODE;
+/** Pointer to file mode. */
+typedef RTFMODE        *PRTFMODE;
+
+/** Device unix number. */
+typedef uint32_t        RTDEV;
+/** Pointer to a device unix number. */
+typedef RTDEV          *PRTDEV;
+
+/** @name RTDEV Macros
+ * @{  */
+/**
+ * Our makedev macro.
+ * @returns RTDEV
+ * @param   uMajor          The major device number.
+ * @param   uMinor          The minor device number.
+ */
+#define RTDEV_MAKE(uMajor, uMinor)      ((RTDEV)( ((RTDEV)(uMajor) << 24) | (uMinor & UINT32_C(0x00ffffff)) ))
+/**
+ * Get the major device node number from an RTDEV type.
+ * @returns The major device number of @a uDev
+ * @param   uDev            The device number.
+ */
+#define RTDEV_MAJOR(uDev)               ((uDev) >> 24)
+/**
+ * Get the minor device node number from an RTDEV type.
+ * @returns The minor device number of @a uDev
+ * @param   uDev            The device number.
+ */
+#define RTDEV_MINOR(uDev)               ((uDev) & UINT32_C(0x00ffffff))
+/** @}  */
+
+/** i-node number. */
+typedef uint64_t        RTINODE;
+/** Pointer to a i-node number. */
+typedef RTINODE        *PRTINODE;
+
+/** User id. */
+typedef uint32_t        RTUID;
+/** Pointer to a user id. */
+typedef RTUID          *PRTUID;
+/** NIL user id.
+ * @todo check this for portability! */
+#define NIL_RTUID       (~(RTUID)0)
+
+/** Group id. */
+typedef uint32_t        RTGID;
+/** Pointer to a group id. */
+typedef RTGID          *PRTGID;
+/** NIL group id.
+ * @todo check this for portability! */
+#define NIL_RTGID       (~(RTGID)0)
+
+/** I/O Port. */
+typedef uint16_t        RTIOPORT;
+/** Pointer to I/O Port. */
+typedef RTIOPORT       *PRTIOPORT;
+/** Pointer to const I/O Port. */
+typedef const RTIOPORT *PCRTIOPORT;
+
+/** Selector. */
+typedef uint16_t        RTSEL;
+/** Pointer to selector. */
+typedef RTSEL          *PRTSEL;
+/** Pointer to const selector. */
+typedef const RTSEL    *PCRTSEL;
+/** Max selector value. */
+#define RTSEL_MAX       UINT16_MAX
+
+/** Far 16-bit pointer. */
+#pragma pack(1)
+typedef struct RTFAR16
+{
+    uint16_t        off;
+    RTSEL           sel;
+} RTFAR16;
+#pragma pack()
+/** Pointer to Far 16-bit pointer. */
+typedef RTFAR16 *PRTFAR16;
+/** Pointer to const Far 16-bit pointer. */
+typedef const RTFAR16 *PCRTFAR16;
+
+/** Far 32-bit pointer. */
+#pragma pack(1)
+typedef struct RTFAR32
+{
+    uint32_t        off;
+    RTSEL           sel;
+} RTFAR32;
+#pragma pack()
+/** Pointer to Far 32-bit pointer. */
+typedef RTFAR32 *PRTFAR32;
+/** Pointer to const Far 32-bit pointer. */
+typedef const RTFAR32 *PCRTFAR32;
+
+/** Far 64-bit pointer. */
+#pragma pack(1)
+typedef struct RTFAR64
+{
+    uint64_t        off;
+    RTSEL           sel;
+} RTFAR64;
+#pragma pack()
+/** Pointer to Far 64-bit pointer. */
+typedef RTFAR64 *PRTFAR64;
+/** Pointer to const Far 64-bit pointer. */
+typedef const RTFAR64 *PCRTFAR64;
+
+/** @} */
+
+
+/** @defgroup grp_rt_types_hc  Host Context Basic Types
+ * @{
+ */
+
+/** HC Natural signed integer.
+ * @deprecated silly type. */
+typedef int32_t             RTHCINT;
+/** Pointer to HC Natural signed integer.
+ * @deprecated silly type. */
+typedef RTHCINT            *PRTHCINT;
+/** Pointer to const HC Natural signed integer.
+ * @deprecated silly type. */
+typedef const RTHCINT      *PCRTHCINT;
+
+/** HC Natural unsigned integer.
+ * @deprecated silly type. */
+typedef uint32_t            RTHCUINT;
+/** Pointer to HC Natural unsigned integer.
+ * @deprecated silly type. */
+typedef RTHCUINT           *PRTHCUINT;
+/** Pointer to const HC Natural unsigned integer.
+ * @deprecated silly type. */
+typedef const RTHCUINT     *PCRTHCUINT;
+
+
+/** Signed integer which can contain a HC pointer. */
+#if HC_ARCH_BITS == 32
+typedef int32_t             RTHCINTPTR;
+#elif HC_ARCH_BITS == 64
+typedef int64_t             RTHCINTPTR;
+#elif HC_ARCH_BITS == 16
+typedef int16_t             RTHCINTPTR;
+#else
+# error Unsupported HC_ARCH_BITS value.
+#endif
+/** Pointer to signed integer which can contain a HC pointer. */
+typedef RTHCINTPTR         *PRTHCINTPTR;
+/** Pointer to const signed integer which can contain a HC pointer. */
+typedef const RTHCINTPTR   *PCRTHCINTPTR;
+/** Max RTHCINTPTR value. */
+#if HC_ARCH_BITS == 32
+# define RTHCINTPTR_MAX     INT32_MAX
+#elif HC_ARCH_BITS == 64
+# define RTHCINTPTR_MAX     INT64_MAX
+#else
+# define RTHCINTPTR_MAX     INT16_MAX
+#endif
+/** Min RTHCINTPTR value. */
+#if HC_ARCH_BITS == 32
+# define RTHCINTPTR_MIN     INT32_MIN
+#elif HC_ARCH_BITS == 64
+# define RTHCINTPTR_MIN     INT64_MIN
+#else
+# define RTHCINTPTR_MIN     INT16_MIN
+#endif
+
+/** Signed integer which can contain a HC ring-3 pointer. */
+#if R3_ARCH_BITS == 32
+typedef int32_t             RTR3INTPTR;
+#elif R3_ARCH_BITS == 64
+typedef int64_t             RTR3INTPTR;
+#elif R3_ARCH_BITS == 16
+typedef int16_t             RTR3INTPTR;
+#else
+#  error Unsupported R3_ARCH_BITS value.
+#endif
+/** Pointer to signed integer which can contain a HC ring-3 pointer. */
+typedef RTR3INTPTR         *PRTR3INTPTR;
+/** Pointer to const signed integer which can contain a HC ring-3 pointer. */
+typedef const RTR3INTPTR   *PCRTR3INTPTR;
+/** Max RTR3INTPTR value. */
+#if R3_ARCH_BITS == 32
+# define RTR3INTPTR_MAX     INT32_MAX
+#elif R3_ARCH_BITS == 64
+# define RTR3INTPTR_MAX     INT64_MAX
+#else
+# define RTR3INTPTR_MAX     INT16_MAX
+#endif
+/** Min RTR3INTPTR value. */
+#if R3_ARCH_BITS == 32
+# define RTR3INTPTR_MIN     INT32_MIN
+#elif R3_ARCH_BITS == 64
+# define RTR3INTPTR_MIN     INT64_MIN
+#else
+# define RTR3INTPTR_MIN     INT16_MIN
+#endif
+
+/** Signed integer which can contain a HC ring-0 pointer. */
+#if R0_ARCH_BITS == 32
+typedef int32_t             RTR0INTPTR;
+#elif R0_ARCH_BITS == 64
+typedef int64_t             RTR0INTPTR;
+#elif R0_ARCH_BITS == 16
+typedef int16_t             RTR0INTPTR;
+#else
+# error Unsupported R0_ARCH_BITS value.
+#endif
+/** Pointer to signed integer which can contain a HC ring-0 pointer. */
+typedef RTR0INTPTR         *PRTR0INTPTR;
+/** Pointer to const signed integer which can contain a HC ring-0 pointer. */
+typedef const RTR0INTPTR   *PCRTR0INTPTR;
+/** Max RTR0INTPTR value. */
+#if R0_ARCH_BITS == 32
+# define RTR0INTPTR_MAX     INT32_MAX
+#elif R0_ARCH_BITS == 64
+# define RTR0INTPTR_MAX     INT64_MAX
+#else
+# define RTR0INTPTR_MAX     INT16_MAX
+#endif
+/** Min RTHCINTPTR value. */
+#if R0_ARCH_BITS == 32
+# define RTR0INTPTR_MIN     INT32_MIN
+#elif R0_ARCH_BITS == 64
+# define RTR0INTPTR_MIN     INT64_MIN
+#else
+# define RTR0INTPTR_MIN     INT16_MIN
+#endif
+
+
+/** Unsigned integer which can contain a HC pointer. */
+#if HC_ARCH_BITS == 32
+typedef uint32_t            RTHCUINTPTR;
+#elif HC_ARCH_BITS == 64
+typedef uint64_t            RTHCUINTPTR;
+#elif HC_ARCH_BITS == 16
+typedef uint16_t            RTHCUINTPTR;
+#else
+# error Unsupported HC_ARCH_BITS value.
+#endif
+/** Pointer to unsigned integer which can contain a HC pointer. */
+typedef RTHCUINTPTR        *PRTHCUINTPTR;
+/** Pointer to unsigned integer which can contain a HC pointer. */
+typedef const RTHCUINTPTR  *PCRTHCUINTPTR;
+/** Max RTHCUINTTPR value. */
+#if HC_ARCH_BITS == 32
+# define RTHCUINTPTR_MAX    UINT32_MAX
+#elif HC_ARCH_BITS == 64
+# define RTHCUINTPTR_MAX    UINT64_MAX
+#else
+# define RTHCUINTPTR_MAX    UINT16_MAX
+#endif
+
+/** Unsigned integer which can contain a HC ring-3 pointer. */
+#if R3_ARCH_BITS == 32
+typedef uint32_t            RTR3UINTPTR;
+#elif R3_ARCH_BITS == 64
+typedef uint64_t            RTR3UINTPTR;
+#elif R3_ARCH_BITS == 16
+typedef uint16_t            RTR3UINTPTR;
+#else
+# error Unsupported R3_ARCH_BITS value.
+#endif
+/** Pointer to unsigned integer which can contain a HC ring-3 pointer. */
+typedef RTR3UINTPTR        *PRTR3UINTPTR;
+/** Pointer to unsigned integer which can contain a HC ring-3 pointer. */
+typedef const RTR3UINTPTR  *PCRTR3UINTPTR;
+/** Max RTHCUINTTPR value. */
+#if R3_ARCH_BITS == 32
+# define RTR3UINTPTR_MAX    UINT32_MAX
+#elif R3_ARCH_BITS == 64
+# define RTR3UINTPTR_MAX    UINT64_MAX
+#else
+# define RTR3UINTPTR_MAX    UINT16_MAX
+#endif
+
+/** Unsigned integer which can contain a HC ring-0 pointer. */
+#if R0_ARCH_BITS == 32
+typedef uint32_t            RTR0UINTPTR;
+#elif R0_ARCH_BITS == 64
+typedef uint64_t            RTR0UINTPTR;
+#elif R0_ARCH_BITS == 16
+typedef uint16_t            RTR0UINTPTR;
+#else
+# error Unsupported R0_ARCH_BITS value.
+#endif
+/** Pointer to unsigned integer which can contain a HC ring-0 pointer. */
+typedef RTR0UINTPTR        *PRTR0UINTPTR;
+/** Pointer to unsigned integer which can contain a HC ring-0 pointer. */
+typedef const RTR0UINTPTR  *PCRTR0UINTPTR;
+/** Max RTR0UINTTPR value. */
+#if R0_ARCH_BITS == 32
+# define RTR0UINTPTR_MAX    UINT32_MAX
+#elif R0_ARCH_BITS == 64
+# define RTR0UINTPTR_MAX    UINT64_MAX
+#else
+# define RTR0UINTPTR_MAX    UINT16_MAX
+#endif
+
+
+/** Host Physical Memory Address. */
+typedef uint64_t            RTHCPHYS;
+/** Pointer to Host Physical Memory Address. */
+typedef RTHCPHYS           *PRTHCPHYS;
+/** Pointer to const Host Physical Memory Address. */
+typedef const RTHCPHYS     *PCRTHCPHYS;
+/** @def NIL_RTHCPHYS
+ * NIL HC Physical Address.
+ * NIL_RTHCPHYS is used to signal an invalid physical address, similar
+ * to the NULL pointer.
+ */
+#define NIL_RTHCPHYS        (~(RTHCPHYS)0)
+/** Max RTHCPHYS value. */
+#define RTHCPHYS_MAX        UINT64_MAX
+
+
+/** HC pointer. */
+#ifndef IN_RC
+typedef void *              RTHCPTR;
+#else
+typedef RTHCUINTPTR         RTHCPTR;
+#endif
+/** Pointer to HC pointer. */
+typedef RTHCPTR            *PRTHCPTR;
+/** Pointer to const HC pointer. */
+typedef const RTHCPTR      *PCRTHCPTR;
+/** @def NIL_RTHCPTR
+ * NIL HC pointer.
+ */
+#define NIL_RTHCPTR         ((RTHCPTR)0)
+/** Max RTHCPTR value. */
+#define RTHCPTR_MAX         ((RTHCPTR)RTHCUINTPTR_MAX)
+
+
+/** HC ring-3 pointer. */
+#ifdef IN_RING3
+typedef void *              RTR3PTR;
+#else
+typedef RTR3UINTPTR         RTR3PTR;
+#endif
+/** Pointer to HC ring-3 pointer. */
+typedef RTR3PTR            *PRTR3PTR;
+/** Pointer to const HC ring-3 pointer. */
+typedef const RTR3PTR      *PCRTR3PTR;
+/** @def NIL_RTR3PTR
+ * NIL HC ring-3 pointer.
+ */
+#ifndef IN_RING3
+# define NIL_RTR3PTR        ((RTR3PTR)0)
+#else
+# define NIL_RTR3PTR        (NULL)
+#endif
+/** Max RTR3PTR value. */
+#define RTR3PTR_MAX         ((RTR3PTR)RTR3UINTPTR_MAX)
+
+/** HC ring-0 pointer. */
+#ifdef  IN_RING0
+typedef void *              RTR0PTR;
+#else
+typedef RTR0UINTPTR         RTR0PTR;
+#endif
+/** Pointer to HC ring-0 pointer. */
+typedef RTR0PTR            *PRTR0PTR;
+/** Pointer to const HC ring-0 pointer. */
+typedef const RTR0PTR      *PCRTR0PTR;
+/** @def NIL_RTR0PTR
+ * NIL HC ring-0 pointer.
+ */
+#ifndef IN_RING0
+# define NIL_RTR0PTR        ((RTR0PTR)0)
+#else
+# define NIL_RTR0PTR        (NULL)
+#endif
+/** Max RTR3PTR value. */
+#define RTR0PTR_MAX         ((RTR0PTR)RTR0UINTPTR_MAX)
+
+
+/** Unsigned integer register in the host context. */
+#if HC_ARCH_BITS == 32
+typedef uint32_t            RTHCUINTREG;
+#elif HC_ARCH_BITS == 64
+typedef uint64_t            RTHCUINTREG;
+#elif HC_ARCH_BITS == 16
+typedef uint16_t            RTHCUINTREG;
+#else
+# error "Unsupported HC_ARCH_BITS!"
+#endif
+/** Pointer to an unsigned integer register in the host context. */
+typedef RTHCUINTREG        *PRTHCUINTREG;
+/** Pointer to a const unsigned integer register in the host context. */
+typedef const RTHCUINTREG  *PCRTHCUINTREG;
+
+/** Unsigned integer register in the host ring-3 context. */
+#if R3_ARCH_BITS == 32
+typedef uint32_t            RTR3UINTREG;
+#elif R3_ARCH_BITS == 64
+typedef uint64_t            RTR3UINTREG;
+#elif R3_ARCH_BITS == 16
+typedef uint16_t            RTR3UINTREG;
+#else
+# error "Unsupported R3_ARCH_BITS!"
+#endif
+/** Pointer to an unsigned integer register in the host ring-3 context. */
+typedef RTR3UINTREG        *PRTR3UINTREG;
+/** Pointer to a const unsigned integer register in the host ring-3 context. */
+typedef const RTR3UINTREG  *PCRTR3UINTREG;
+
+/** Unsigned integer register in the host ring-3 context. */
+#if R0_ARCH_BITS == 32
+typedef uint32_t            RTR0UINTREG;
+#elif R0_ARCH_BITS == 64
+typedef uint64_t            RTR0UINTREG;
+#elif R0_ARCH_BITS == 16
+typedef uint16_t            RTR0UINTREG;
+#else
+# error "Unsupported R3_ARCH_BITS!"
+#endif
+/** Pointer to an unsigned integer register in the host ring-3 context. */
+typedef RTR0UINTREG        *PRTR0UINTREG;
+/** Pointer to a const unsigned integer register in the host ring-3 context. */
+typedef const RTR0UINTREG  *PCRTR0UINTREG;
+
+/** @} */
+
+
+/** @defgroup grp_rt_types_gc  Guest Context Basic Types
+ * @{
+ */
+
+/** Natural signed integer in the GC.
+ * @deprecated silly type. */
+#if GC_ARCH_BITS == 32
+typedef int32_t         RTGCINT;
+#elif GC_ARCH_BITS == 64 /** @todo this isn't right, natural int is 32-bit, see RTHCINT. */
+typedef int64_t         RTGCINT;
+#endif
+/** Pointer to natural signed integer in GC.
+ * @deprecated silly type. */
+typedef RTGCINT        *PRTGCINT;
+/** Pointer to const natural signed integer in GC.
+ * @deprecated silly type. */
+typedef const RTGCINT  *PCRTGCINT;
+
+/** Natural unsigned integer in the GC.
+ * @deprecated silly type. */
+#if GC_ARCH_BITS == 32
+typedef uint32_t        RTGCUINT;
+#elif GC_ARCH_BITS == 64 /** @todo this isn't right, natural int is 32-bit, see RTHCUINT. */
+typedef uint64_t        RTGCUINT;
+#endif
+/** Pointer to natural unsigned integer in GC.
+ * @deprecated silly type. */
+typedef RTGCUINT       *PRTGCUINT;
+/** Pointer to const natural unsigned integer in GC.
+ * @deprecated silly type. */
+typedef const RTGCUINT *PCRTGCUINT;
+
+/** Signed integer which can contain a GC pointer. */
+#if GC_ARCH_BITS == 32
+typedef int32_t         RTGCINTPTR;
+#elif GC_ARCH_BITS == 64
+typedef int64_t         RTGCINTPTR;
+#endif
+/** Pointer to signed integer which can contain a GC pointer. */
+typedef RTGCINTPTR     *PRTGCINTPTR;
+/** Pointer to const signed integer which can contain a GC pointer. */
+typedef const RTGCINTPTR *PCRTGCINTPTR;
+
+/** Unsigned integer which can contain a GC pointer. */
+#if GC_ARCH_BITS == 32
+typedef uint32_t        RTGCUINTPTR;
+#elif GC_ARCH_BITS == 64
+typedef uint64_t        RTGCUINTPTR;
+#else
+#  error Unsupported GC_ARCH_BITS value.
+#endif
+/** Pointer to unsigned integer which can contain a GC pointer. */
+typedef RTGCUINTPTR     *PRTGCUINTPTR;
+/** Pointer to unsigned integer which can contain a GC pointer. */
+typedef const RTGCUINTPTR *PCRTGCUINTPTR;
+
+/** Unsigned integer which can contain a 32 bits GC pointer. */
+typedef uint32_t        RTGCUINTPTR32;
+/** Pointer to unsigned integer which can contain a 32 bits GC pointer. */
+typedef RTGCUINTPTR32   *PRTGCUINTPTR32;
+/** Pointer to unsigned integer which can contain a 32 bits GC pointer. */
+typedef const RTGCUINTPTR32 *PCRTGCUINTPTR32;
+
+/** Unsigned integer which can contain a 64 bits GC pointer. */
+typedef uint64_t        RTGCUINTPTR64;
+/** Pointer to unsigned integer which can contain a 32 bits GC pointer. */
+typedef RTGCUINTPTR64   *PRTGCUINTPTR64;
+/** Pointer to unsigned integer which can contain a 32 bits GC pointer. */
+typedef const RTGCUINTPTR64 *PCRTGCUINTPTR64;
+
+/** Guest Physical Memory Address.*/
+typedef uint64_t            RTGCPHYS;
+/** Pointer to Guest Physical Memory Address. */
+typedef RTGCPHYS           *PRTGCPHYS;
+/** Pointer to const Guest Physical Memory Address. */
+typedef const RTGCPHYS     *PCRTGCPHYS;
+/** @def NIL_RTGCPHYS
+ * NIL GC Physical Address.
+ * NIL_RTGCPHYS is used to signal an invalid physical address, similar
+ * to the NULL pointer. Note that this value may actually be valid in
+ * some contexts.
+ */
+#define NIL_RTGCPHYS        (~(RTGCPHYS)0U)
+/** Max guest physical memory address value. */
+#define RTGCPHYS_MAX        UINT64_MAX
+
+
+/** Guest Physical Memory Address; limited to 32 bits.*/
+typedef uint32_t            RTGCPHYS32;
+/** Pointer to Guest Physical Memory Address. */
+typedef RTGCPHYS32         *PRTGCPHYS32;
+/** Pointer to const Guest Physical Memory Address. */
+typedef const RTGCPHYS32    *PCRTGCPHYS32;
+/** @def NIL_RTGCPHYS32
+ * NIL GC Physical Address.
+ * NIL_RTGCPHYS32 is used to signal an invalid physical address, similar
+ * to the NULL pointer. Note that this value may actually be valid in
+ * some contexts.
+ */
+#define NIL_RTGCPHYS32     (~(RTGCPHYS32)0)
+
+
+/** Guest Physical Memory Address; limited to 64 bits.*/
+typedef uint64_t        RTGCPHYS64;
+/** Pointer to Guest Physical Memory Address. */
+typedef RTGCPHYS64     *PRTGCPHYS64;
+/** Pointer to const Guest Physical Memory Address. */
+typedef const RTGCPHYS64 *PCRTGCPHYS64;
+/** @def NIL_RTGCPHYS64
+ * NIL GC Physical Address.
+ * NIL_RTGCPHYS64 is used to signal an invalid physical address, similar
+ * to the NULL pointer. Note that this value may actually be valid in
+ * some contexts.
+ */
+#define NIL_RTGCPHYS64     (~(RTGCPHYS64)0)
+
+/** Guest context pointer, 32 bits.
+ * Keep in mind that this type is an unsigned integer in
+ * HC and void pointer in GC.
+ */
+typedef RTGCUINTPTR32   RTGCPTR32;
+/** Pointer to a guest context pointer. */
+typedef RTGCPTR32      *PRTGCPTR32;
+/** Pointer to a const guest context pointer. */
+typedef const RTGCPTR32 *PCRTGCPTR32;
+/** @def NIL_RTGCPTR32
+ * NIL GC pointer.
+ */
+#define NIL_RTGCPTR32   ((RTGCPTR32)0)
+
+/** Guest context pointer, 64 bits.
+ */
+typedef RTGCUINTPTR64   RTGCPTR64;
+/** Pointer to a guest context pointer. */
+typedef RTGCPTR64      *PRTGCPTR64;
+/** Pointer to a const guest context pointer. */
+typedef const RTGCPTR64 *PCRTGCPTR64;
+/** @def NIL_RTGCPTR64
+ * NIL GC pointer.
+ */
+#define NIL_RTGCPTR64   ((RTGCPTR64)0)
+
+/** Guest context pointer.
+ * Keep in mind that this type is an unsigned integer in
+ * HC and void pointer in GC.
+ */
+#if GC_ARCH_BITS == 64
+typedef RTGCPTR64       RTGCPTR;
+/** Pointer to a guest context pointer. */
+typedef PRTGCPTR64      PRTGCPTR;
+/** Pointer to a const guest context pointer. */
+typedef PCRTGCPTR64     PCRTGCPTR;
+/** @def NIL_RTGCPTR
+ * NIL GC pointer.
+ */
+# define NIL_RTGCPTR    NIL_RTGCPTR64
+/** Max RTGCPTR value. */
+# define RTGCPTR_MAX    UINT64_MAX
+#elif GC_ARCH_BITS == 32
+typedef RTGCPTR32       RTGCPTR;
+/** Pointer to a guest context pointer. */
+typedef PRTGCPTR32      PRTGCPTR;
+/** Pointer to a const guest context pointer. */
+typedef PCRTGCPTR32     PCRTGCPTR;
+/** @def NIL_RTGCPTR
+ * NIL GC pointer.
+ */
+# define NIL_RTGCPTR     NIL_RTGCPTR32
+/** Max RTGCPTR value. */
+# define RTGCPTR_MAX    UINT32_MAX
+#else
+# error "Unsupported GC_ARCH_BITS!"
+#endif
+
+/** Unsigned integer register in the guest context. */
+typedef uint32_t              RTGCUINTREG32;
+/** Pointer to an unsigned integer register in the guest context. */
+typedef RTGCUINTREG32        *PRTGCUINTREG32;
+/** Pointer to a const unsigned integer register in the guest context. */
+typedef const RTGCUINTREG32  *PCRTGCUINTREG32;
+
+typedef uint64_t              RTGCUINTREG64;
+/** Pointer to an unsigned integer register in the guest context. */
+typedef RTGCUINTREG64        *PRTGCUINTREG64;
+/** Pointer to a const unsigned integer register in the guest context. */
+typedef const RTGCUINTREG64  *PCRTGCUINTREG64;
+
+#if GC_ARCH_BITS == 64
+typedef RTGCUINTREG64           RTGCUINTREG;
+#elif GC_ARCH_BITS == 32
+typedef RTGCUINTREG32           RTGCUINTREG;
+#else
+# error "Unsupported GC_ARCH_BITS!"
+#endif
+/** Pointer to an unsigned integer register in the guest context. */
+typedef RTGCUINTREG            *PRTGCUINTREG;
+/** Pointer to a const unsigned integer register in the guest context. */
+typedef const RTGCUINTREG      *PCRTGCUINTREG;
+
+/** @} */
+
+/** @defgroup grp_rt_types_rc  Raw mode Context Basic Types
+ * @{
+ */
+
+/** Raw mode context pointer; a 32 bits guest context pointer.
+ * Keep in mind that this type is an unsigned integer in
+ * HC and void pointer in RC.
+ */
+#ifdef IN_RC
+typedef void *          RTRCPTR;
+#else
+typedef uint32_t        RTRCPTR;
+#endif
+/** Pointer to a raw mode context pointer. */
+typedef RTRCPTR        *PRTRCPTR;
+/** Pointer to a const raw mode context pointer. */
+typedef const RTRCPTR  *PCRTRCPTR;
+/** @def NIL_RTGCPTR
+ * NIL RC pointer.
+ */
+#ifndef IN_RC
+# define NIL_RTRCPTR   ((RTRCPTR)0)
+#else
+# define NIL_RTRCPTR   (NULL)
+#endif
+/** @def RTRCPTR_MAX
+ * The maximum value a RTRCPTR can have. Mostly used as INVALID value.
+ */
+#define RTRCPTR_MAX    ((RTRCPTR)UINT32_MAX)
+
+/** Raw mode context pointer, unsigned integer variant. */
+typedef int32_t         RTRCINTPTR;
+/** @def RTRCUINTPTR_MAX
+ * The maximum value a RTRCUINPTR can have.
+ */
+#define RTRCUINTPTR_MAX ((RTRCUINTPTR)UINT32_MAX)
+
+/** Raw mode context pointer, signed integer variant. */
+typedef uint32_t        RTRCUINTPTR;
+/** @def RTRCINTPTR_MIN
+ * The minimum value a RTRCINPTR can have.
+ */
+#define RTRCINTPTR_MIN ((RTRCINTPTR)INT32_MIN)
+/** @def RTRCINTPTR_MAX
+ * The maximum value a RTRCINPTR can have.
+ */
+#define RTRCINTPTR_MAX ((RTRCINTPTR)INT32_MAX)
+
+/** @} */
+
+
+/** @defgroup grp_rt_types_cc  Current Context Basic Types
+ * @{
+ */
+
+/** Current Context Physical Memory Address.*/
+#ifdef IN_RC
+typedef RTGCPHYS RTCCPHYS;
+#else
+typedef RTHCPHYS RTCCPHYS;
+#endif
+/** Pointer to Current Context Physical Memory Address. */
+typedef RTCCPHYS       *PRTCCPHYS;
+/** Pointer to const Current Context Physical Memory Address. */
+typedef const RTCCPHYS *PCRTCCPHYS;
+/** @def NIL_RTCCPHYS
+ * NIL CC Physical Address.
+ * NIL_RTCCPHYS is used to signal an invalid physical address, similar
+ * to the NULL pointer.
+ */
+#ifdef IN_RC
+# define NIL_RTCCPHYS   NIL_RTGCPHYS
+#else
+# define NIL_RTCCPHYS   NIL_RTHCPHYS
+#endif
+
+/** Unsigned integer register in the current context. */
+#if ARCH_BITS == 32
+typedef uint32_t                RTCCUINTREG;
+#elif ARCH_BITS == 64
+typedef uint64_t                RTCCUINTREG;
+#elif ARCH_BITS == 16
+typedef uint16_t                RTCCUINTREG;
+#else
+# error "Unsupported ARCH_BITS!"
+#endif
+/** Pointer to an unsigned integer register in the current context. */
+typedef RTCCUINTREG            *PRTCCUINTREG;
+/** Pointer to a const unsigned integer register in the current context. */
+typedef RTCCUINTREG const      *PCRTCCUINTREG;
+
+/** Signed integer register in the current context. */
+#if ARCH_BITS == 32
+typedef int32_t                 RTCCINTREG;
+#elif ARCH_BITS == 64
+typedef int64_t                 RTCCINTREG;
+#elif ARCH_BITS == 16
+typedef int16_t                 RTCCINTREG;
+#endif
+/** Pointer to a signed integer register in the current context. */
+typedef RTCCINTREG             *PRTCCINTREG;
+/** Pointer to a const signed integer register in the current context. */
+typedef RTCCINTREG const       *PCRTCCINTREG;
+
+/** Unsigned integer register in the current context.
+ * @remarks This is for dealing with EAX in 16-bit mode. */
+#if ARCH_BITS == 16 && defined(RT_ARCH_X86)
+typedef uint32_t                RTCCUINTXREG;
+#else
+typedef RTCCUINTREG             RTCCUINTXREG;
+#endif
+/** Pointer to an unsigned integer register in the current context. */
+typedef RTCCUINTREG            *PRTCCUINTXREG;
+/** Pointer to a const unsigned integer register in the current context. */
+typedef RTCCUINTREG const      *PCRTCCUINTXREG;
+
+/** Signed integer extended register in the current context.
+ * @remarks This is for dealing with EAX in 16-bit mode. */
+#if ARCH_BITS == 16 && defined(RT_ARCH_X86)
+typedef int32_t                 RTCCINTXREG;
+#else
+typedef RTCCINTREG              RTCCINTXREG;
+#endif
+/** Pointer to a signed integer extended register in the current context. */
+typedef RTCCINTXREG            *PRTCCINTXREG;
+/** Pointer to a const signed integer extended register in the current
+ * context. */
+typedef RTCCINTXREG const      *PCRTCCINTXREG;
+
+/** @def RTCCUINTREG_C
+ * Defines a constant of RTCCUINTREG type.
+ * @param a_Value   Constant value  */
+/** @def RTCCUINTREG_MAX
+ * Max value that RTCCUINTREG can hold. */
+/** @def RTCCUINTREG_FMT
+ * Generic IPRT format specifier for RTCCUINTREG. */
+/** @def RTCCUINTREG_XFMT
+ * Generic IPRT format specifier for RTCCUINTREG, hexadecimal. */
+/** @def RTCCINTREG_C
+ * Defines a constant of RTCCINTREG type.
+ * @param a_Value   Constant value  */
+/** @def RTCCINTREG_MAX
+ * Max value that RTCCINTREG can hold. */
+/** @def RTCCINTREG_MIN
+ * Min value that RTCCINTREG can hold. */
+/** @def RTCCINTREG_XFMT
+ * Generic IPRT format specifier for RTCCINTREG, hexadecimal. */
+#if ARCH_BITS == 32
+# define RTCCUINTREG_C(a_Value)     UINT32_C(a_Value)
+# define RTCCUINTREG_MAX            UINT32_MAX
+# define RTCCUINTREG_FMT            "RU32"
+# define RTCCUINTREG_XFMT           "RX32"
+# define RTCCINTREG_C(a_Value)      INT32_C(a_Value)
+# define RTCCINTREG_MAX             INT32_MAX
+# define RTCCINTREG_MIN             INT32_MIN
+# define RTCCINTREG_FMT             "RI32"
+# define RTCCINTREG_XFMT            "RX32"
+#elif ARCH_BITS == 64
+# define RTCCUINTREG_C(a_Value)     UINT64_C(a_Value)
+# define RTCCUINTREG_MAX            UINT64_MAX
+# define RTCCUINTREG_FMT            "RU64"
+# define RTCCUINTREG_XFMT           "RX64"
+# define RTCCINTREG_C(a_Value)      INT64_C(a_Value)
+# define RTCCINTREG_MAX             INT64_MAX
+# define RTCCINTREG_MIN             INT64_MIN
+# define RTCCINTREG_FMT             "RI64"
+# define RTCCINTREG_XFMT            "RX64"
+#elif ARCH_BITS == 16
+# define RTCCUINTREG_C(a_Value)     UINT16_C(a_Value)
+# define RTCCUINTREG_MAX            UINT16_MAX
+# define RTCCUINTREG_FMT            "RU16"
+# define RTCCUINTREG_XFMT           "RX16"
+# define RTCCINTREG_C(a_Value)      INT16_C(a_Value)
+# define RTCCINTREG_MAX             INT16_MAX
+# define RTCCINTREG_MIN             INT16_MIN
+# define RTCCINTREG_FMT             "RI16"
+# define RTCCINTREG_XFMT            "RX16"
+#else
+# error "Unsupported ARCH_BITS!"
+#endif
+/** @def RTCCUINTXREG_C
+ * Defines a constant of RTCCUINTXREG type.
+ * @param a_Value   Constant value  */
+/** @def RTCCUINTXREG_MAX
+ * Max value that RTCCUINTXREG can hold. */
+/** @def RTCCUINTXREG_FMT
+ * Generic IPRT format specifier for RTCCUINTXREG. */
+/** @def RTCCUINTXREG_XFMT
+ * Generic IPRT format specifier for RTCCUINTXREG, hexadecimal. */
+/** @def RTCCINTXREG_C
+ * Defines a constant of RTCCINTXREG type.
+ * @param a_Value   Constant value  */
+/** @def RTCCINTXREG_MAX
+ * Max value that RTCCINTXREG can hold. */
+/** @def RTCCINTXREG_MIN
+ * Min value that RTCCINTXREG can hold. */
+/** @def RTCCINTXREG_FMT
+ * Generic IPRT format specifier for RTCCINTXREG. */
+/** @def RTCCINTXREG_XFMT
+ * Generic IPRT format specifier for RTCCINTXREG, hexadecimal. */
+#if ARCH_BITS == 16 && defined(RT_ARCH_X86)
+# define RTCCUINTXREG_C(a_Value)    UINT32_C(a_Value)
+# define RTCCUINTXREG_MAX           UINT32_MAX
+# define RTCCUINTXREG_FMT           "RU32"
+# define RTCCUINTXREG_XFMT          "RX32"
+# define RTCCINTXREG_C(a_Value)     INT32_C(a_Value)
+# define RTCCINTXREG_MAX            INT32_MAX
+# define RTCCINTXREG_MIN            INT32_MIN
+# define RTCCINTXREG_FMT            "RI32"
+# define RTCCINTXREG_XFMT           "RX32"
+#else
+# define RTCCUINTXREG_C(a_Value)    RTCCUINTREG_C(a_Value)
+# define RTCCUINTXREG_MAX           RTCCUINTREG_MAX
+# define RTCCUINTXREG_FMT           RTCCUINTREG_FMT
+# define RTCCUINTXREG_XFMT          RTCCUINTREG_XFMT
+# define RTCCINTXREG_C(a_Value)     RTCCINTREG_C(a_Value)
+# define RTCCINTXREG_MAX            RTCCINTREG_MAX
+# define RTCCINTXREG_MIN            RTCCINTREG_MIN
+# define RTCCINTXREG_FMT            RTCCINTREG_FMT
+# define RTCCINTXREG_XFMT           RTCCINTREG_XFMT
+#endif
+/** @} */
+
+
+
+/** Pointer to a big integer number. */
+typedef struct RTBIGNUM                            *PRTBIGNUM;
+/** Pointer to a const big integer number. */
+typedef struct RTBIGNUM const                      *PCRTBIGNUM;
+
+
+/** Pointer to a critical section. */
+typedef struct RTCRITSECT                          *PRTCRITSECT;
+/** Pointer to a const critical section. */
+typedef const struct RTCRITSECT                    *PCRTCRITSECT;
+
+/** Pointer to a read/write critical section. */
+typedef struct RTCRITSECTRW                        *PRTCRITSECTRW;
+/** Pointer to a const read/write critical section. */
+typedef const struct RTCRITSECTRW                  *PCRTCRITSECTRW;
+
+
+/** Condition variable handle. */
+typedef R3PTRTYPE(struct RTCONDVARINTERNAL *)       RTCONDVAR;
+/** Pointer to a condition variable handle. */
+typedef RTCONDVAR                                  *PRTCONDVAR;
+/** Nil condition variable handle. */
+#define NIL_RTCONDVAR                               0
+
+/** Cryptographic (certificate) store handle. */
+typedef R3R0PTRTYPE(struct RTCRSTOREINT *)          RTCRSTORE;
+/** Pointer to a Cryptographic (certificate) store handle. */
+typedef RTCRSTORE                                  *PRTCRSTORE;
+/** Nil Cryptographic (certificate) store handle. */
+#define NIL_RTCRSTORE                               0
+
+/** Pointer to a const (store) certificate context. */
+typedef struct RTCRCERTCTX const                   *PCRTCRCERTCTX;
+
+/** Cryptographic message digest handle. */
+typedef R3R0PTRTYPE(struct RTCRDIGESTINT *)         RTCRDIGEST;
+/** Pointer to a cryptographic message digest handle. */
+typedef RTCRDIGEST                                 *PRTCRDIGEST;
+/** NIL cryptographic message digest handle. */
+#define NIL_RTCRDIGEST                              (0)
+
+/** Public key encryption schema handle. */
+typedef R3R0PTRTYPE(struct RTCRPKIXENCRYPTIONINT *) RTCRPKIXENCRYPTION;
+/** Pointer to a public key encryption schema handle. */
+typedef RTCRPKIXENCRYPTION                         *PRTCRPKIXENCRYPTION;
+/** NIL public key encryption schema handle */
+#define NIL_RTCRPKIXENCRYPTION                      (0)
+
+/** Public key signature schema handle. */
+typedef R3R0PTRTYPE(struct RTCRPKIXSIGNATUREINT *)  RTCRPKIXSIGNATURE;
+/** Pointer to a public key signature schema handle. */
+typedef RTCRPKIXSIGNATURE                          *PRTCRPKIXSIGNATURE;
+/** NIL public key signature schema handle */
+#define NIL_RTCRPKIXSIGNATURE                       (0)
+
+/** X.509 certificate paths builder & validator handle. */
+typedef R3R0PTRTYPE(struct RTCRX509CERTPATHSINT *)  RTCRX509CERTPATHS;
+/** Pointer to a certificate paths builder & validator handle. */
+typedef RTCRX509CERTPATHS                          *PRTCRX509CERTPATHS;
+/** Nil certificate paths builder & validator handle. */
+#define NIL_RTCRX509CERTPATHS                       0
+
+/** File handle. */
+typedef R3R0PTRTYPE(struct RTFILEINT *)             RTFILE;
+/** Pointer to file handle. */
+typedef RTFILE                                     *PRTFILE;
+/** Nil file handle. */
+#define NIL_RTFILE                                  ((RTFILE)~(RTHCINTPTR)0)
+
+/** Async I/O request handle. */
+typedef R3PTRTYPE(struct RTFILEAIOREQINTERNAL *)    RTFILEAIOREQ;
+/** Pointer to an async I/O request handle. */
+typedef RTFILEAIOREQ                               *PRTFILEAIOREQ;
+/** Nil request handle. */
+#define NIL_RTFILEAIOREQ                            0
+
+/** Async I/O completion context handle. */
+typedef R3PTRTYPE(struct RTFILEAIOCTXINTERNAL *)    RTFILEAIOCTX;
+/** Pointer to an async I/O completion context handle. */
+typedef RTFILEAIOCTX                               *PRTFILEAIOCTX;
+/** Nil context handle. */
+#define NIL_RTFILEAIOCTX                            0
+
+/** Loader module handle. */
+typedef R3R0PTRTYPE(struct RTLDRMODINTERNAL *)      RTLDRMOD;
+/** Pointer to a loader module handle. */
+typedef RTLDRMOD                                   *PRTLDRMOD;
+/** Nil loader module handle. */
+#define NIL_RTLDRMOD                                0
+
+/** Lock validator class handle. */
+typedef R3R0PTRTYPE(struct RTLOCKVALCLASSINT *)     RTLOCKVALCLASS;
+/** Pointer to a lock validator class handle. */
+typedef RTLOCKVALCLASS                             *PRTLOCKVALCLASS;
+/** Nil lock validator class handle. */
+#define NIL_RTLOCKVALCLASS                         ((RTLOCKVALCLASS)0)
+
+/** Ring-0 memory object handle. */
+typedef R0PTRTYPE(struct RTR0MEMOBJINTERNAL *)      RTR0MEMOBJ;
+/** Pointer to a Ring-0 memory object handle. */
+typedef RTR0MEMOBJ                                 *PRTR0MEMOBJ;
+/** Nil ring-0 memory object handle. */
+#define NIL_RTR0MEMOBJ                              0
+
+/** Native thread handle. */
+typedef RTHCUINTPTR                                 RTNATIVETHREAD;
+/** Pointer to an native thread handle. */
+typedef RTNATIVETHREAD                             *PRTNATIVETHREAD;
+/** Nil native thread handle. */
+#define NIL_RTNATIVETHREAD                          (~(RTNATIVETHREAD)0)
+
+/** Pipe handle. */
+typedef R3R0PTRTYPE(struct RTPIPEINTERNAL *)        RTPIPE;
+/** Pointer to a pipe handle. */
+typedef RTPIPE                                     *PRTPIPE;
+/** Nil pipe handle.
+ * @remarks This is not 0 because of UNIX and OS/2 handle values. Take care! */
+#define NIL_RTPIPE                                 ((RTPIPE)RTHCUINTPTR_MAX)
+
+/** @typedef RTPOLLSET
+ * Poll set handle. */
+typedef R3R0PTRTYPE(struct RTPOLLSETINTERNAL *)     RTPOLLSET;
+/** Pointer to a poll set handle. */
+typedef RTPOLLSET                                  *PRTPOLLSET;
+/** Nil poll set handle handle. */
+#define NIL_RTPOLLSET                               ((RTPOLLSET)0)
+
+/** Process identifier. */
+typedef uint32_t                                    RTPROCESS;
+/** Pointer to a process identifier. */
+typedef RTPROCESS                                  *PRTPROCESS;
+/** Nil process identifier. */
+#define NIL_RTPROCESS                               (~(RTPROCESS)0)
+
+/** Process ring-0 handle. */
+typedef RTR0UINTPTR                                 RTR0PROCESS;
+/** Pointer to a ring-0 process handle. */
+typedef RTR0PROCESS                                *PRTR0PROCESS;
+/** Nil ring-0 process handle. */
+#define NIL_RTR0PROCESS                             (~(RTR0PROCESS)0)
+
+/** @typedef RTSEMEVENT
+ * Event Semaphore handle. */
+typedef R3R0PTRTYPE(struct RTSEMEVENTINTERNAL *)    RTSEMEVENT;
+/** Pointer to an event semaphore handle. */
+typedef RTSEMEVENT                                 *PRTSEMEVENT;
+/** Nil event semaphore handle. */
+#define NIL_RTSEMEVENT                              0
+
+/** @typedef RTSEMEVENTMULTI
+ * Event Multiple Release Semaphore handle. */
+typedef R3R0PTRTYPE(struct RTSEMEVENTMULTIINTERNAL *) RTSEMEVENTMULTI;
+/** Pointer to an event multiple release semaphore handle. */
+typedef RTSEMEVENTMULTI                            *PRTSEMEVENTMULTI;
+/** Nil multiple release event semaphore handle. */
+#define NIL_RTSEMEVENTMULTI                         0
+
+/** @typedef RTSEMFASTMUTEX
+ * Fast mutex Semaphore handle. */
+typedef R3R0PTRTYPE(struct RTSEMFASTMUTEXINTERNAL *) RTSEMFASTMUTEX;
+/** Pointer to a fast mutex semaphore handle. */
+typedef RTSEMFASTMUTEX                             *PRTSEMFASTMUTEX;
+/** Nil fast mutex semaphore handle. */
+#define NIL_RTSEMFASTMUTEX                          0
+
+/** @typedef RTSEMMUTEX
+ * Mutex Semaphore handle. */
+typedef R3R0PTRTYPE(struct RTSEMMUTEXINTERNAL *)    RTSEMMUTEX;
+/** Pointer to a mutex semaphore handle. */
+typedef RTSEMMUTEX                                 *PRTSEMMUTEX;
+/** Nil mutex semaphore handle. */
+#define NIL_RTSEMMUTEX                              0
+
+/** @typedef RTSEMSPINMUTEX
+ * Spinning mutex Semaphore handle. */
+typedef R3R0PTRTYPE(struct RTSEMSPINMUTEXINTERNAL *) RTSEMSPINMUTEX;
+/** Pointer to a spinning mutex semaphore handle. */
+typedef RTSEMSPINMUTEX                             *PRTSEMSPINMUTEX;
+/** Nil spinning mutex semaphore handle. */
+#define NIL_RTSEMSPINMUTEX                          0
+
+/** @typedef RTSEMRW
+ * Read/Write Semaphore handle. */
+typedef R3R0PTRTYPE(struct RTSEMRWINTERNAL *)       RTSEMRW;
+/** Pointer to a read/write semaphore handle. */
+typedef RTSEMRW                                    *PRTSEMRW;
+/** Nil read/write semaphore handle. */
+#define NIL_RTSEMRW                                 0
+
+/** @typedef RTSEMXROADS
+ * Crossroads semaphore handle. */
+typedef R3R0PTRTYPE(struct RTSEMXROADSINTERNAL *)   RTSEMXROADS;
+/** Pointer to a crossroads semaphore handle. */
+typedef RTSEMXROADS                                *PRTSEMXROADS;
+/** Nil crossroads semaphore handle. */
+#define NIL_RTSEMXROADS                             ((RTSEMXROADS)0)
+
+/** Spinlock handle. */
+typedef R3R0PTRTYPE(struct RTSPINLOCKINTERNAL *)    RTSPINLOCK;
+/** Pointer to a spinlock handle. */
+typedef RTSPINLOCK                                 *PRTSPINLOCK;
+/** Nil spinlock handle. */
+#define NIL_RTSPINLOCK                              0
+
+/** Socket handle. */
+typedef R3R0PTRTYPE(struct RTSOCKETINT *)           RTSOCKET;
+/** Pointer to socket handle. */
+typedef RTSOCKET                                   *PRTSOCKET;
+/** Nil socket handle. */
+#define NIL_RTSOCKET                                ((RTSOCKET)0)
+
+/** Pointer to a RTTCPSERVER handle. */
+typedef struct RTTCPSERVER                         *PRTTCPSERVER;
+/** Pointer to a RTTCPSERVER handle. */
+typedef PRTTCPSERVER                               *PPRTTCPSERVER;
+/** Nil RTTCPSERVER handle. */
+#define NIL_RTTCPSERVER                            ((PRTTCPSERVER)0)
+
+/** Pointer to a RTUDPSERVER handle. */
+typedef struct RTUDPSERVER                         *PRTUDPSERVER;
+/** Pointer to a RTUDPSERVER handle. */
+typedef PRTUDPSERVER                               *PPRTUDPSERVER;
+/** Nil RTUDPSERVER handle. */
+#define NIL_RTUDPSERVER                            ((PRTUDPSERVER)0)
+
+/** Thread handle.*/
+typedef R3R0PTRTYPE(struct RTTHREADINT *)           RTTHREAD;
+/** Pointer to thread handle. */
+typedef RTTHREAD                                   *PRTTHREAD;
+/** Nil thread handle. */
+#define NIL_RTTHREAD                                0
+
+/** Thread context switching hook handle.   */
+typedef R0PTRTYPE(struct RTTHREADCTXHOOKINT *)      RTTHREADCTXHOOK;
+/** Pointer to Thread context switching hook handle. */
+typedef RTTHREADCTXHOOK                            *PRTTHREADCTXHOOK;
+/** Nil Thread context switching hook handle. */
+#define NIL_RTTHREADCTXHOOK                         ((RTTHREADCTXHOOK)0)
+
+/** A TLS index. */
+typedef RTHCINTPTR                                  RTTLS;
+/** Pointer to a TLS index. */
+typedef RTTLS                                      *PRTTLS;
+/** Pointer to a const TLS index. */
+typedef RTTLS const                                *PCRTTLS;
+/** NIL TLS index value. */
+#define NIL_RTTLS                                   ((RTTLS)-1)
+
+/** Trace buffer handle.
+ * @remarks This is not a R3/R0 type like most other handles!
+ */
+typedef struct RTTRACEBUFINT                        *RTTRACEBUF;
+/** Pointer to a trace buffer handle. */
+typedef RTTRACEBUF                                  *PRTTRACEBUF;
+/** Nil trace buffer handle. */
+#define NIL_RTTRACEBUF                              ((RTTRACEBUF)0)
+/** The handle of the default trace buffer.
+ * This can be used with any of the RTTraceBufAdd APIs. */
+#define RTTRACEBUF_DEFAULT                          ((RTTRACEBUF)-2)
+
+/** Handle to a simple heap. */
+typedef R3R0PTRTYPE(struct RTHEAPSIMPLEINTERNAL *)  RTHEAPSIMPLE;
+/** Pointer to a handle to a simple heap. */
+typedef RTHEAPSIMPLE                               *PRTHEAPSIMPLE;
+/** NIL simple heap handle. */
+#define NIL_RTHEAPSIMPLE                            ((RTHEAPSIMPLE)0)
+
+/** Handle to an offset based heap. */
+typedef R3R0PTRTYPE(struct RTHEAPOFFSETINTERNAL *)  RTHEAPOFFSET;
+/** Pointer to a handle to an offset based heap. */
+typedef RTHEAPOFFSET                               *PRTHEAPOFFSET;
+/** NIL offset based heap handle. */
+#define NIL_RTHEAPOFFSET                            ((RTHEAPOFFSET)0)
+
+/** Handle to an environment block. */
+typedef R3PTRTYPE(struct RTENVINTERNAL *)           RTENV;
+/** Pointer to a handle to an environment block. */
+typedef RTENV                                      *PRTENV;
+/** NIL simple heap handle. */
+#define NIL_RTENV                                   ((RTENV)0)
+
+/** A CPU identifier.
+ * @remarks This doesn't have to correspond to the APIC ID (intel/amd). Nor
+ *          does it have to correspond to the bits in the affinity mask, at
+ *          least not until we've sorted out Windows NT. */
+typedef uint32_t                                    RTCPUID;
+/** Pointer to a CPU identifier. */
+typedef RTCPUID                                    *PRTCPUID;
+/** Pointer to a const CPU identifier. */
+typedef RTCPUID const                              *PCRTCPUID;
+/** Nil CPU Id. */
+#define NIL_RTCPUID                                 ((RTCPUID)~0)
+
+/** The maximum number of CPUs a set can contain and IPRT is able
+ * to reference. (Should be max of support arch/platforms.)
+ * @remarks Must be a multiple of 64 (see RTCPUSET).  */
+#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
+# define RTCPUSET_MAX_CPUS      256
+#elif defined(RT_ARCH_SPARC) || defined(RT_ARCH_SPARC64)
+# define RTCPUSET_MAX_CPUS      1024
+#else
+# define RTCPUSET_MAX_CPUS      64
+#endif
+/** A CPU set.
+ * @note    Treat this as an opaque type and always use RTCpuSet* for
+ *          manipulating it. */
+typedef struct RTCPUSET
+{
+    /** The bitmap.  */
+    uint64_t bmSet[RTCPUSET_MAX_CPUS / 64];
+} RTCPUSET;
+/** Pointer to a CPU set. */
+typedef RTCPUSET                                   *PRTCPUSET;
+/** Pointer to a const CPU set. */
+typedef RTCPUSET const                             *PCRTCPUSET;
+
+/** A handle table handle. */
+typedef R3R0PTRTYPE(struct RTHANDLETABLEINT *)      RTHANDLETABLE;
+/** A pointer to a handle table handle. */
+typedef RTHANDLETABLE                              *PRTHANDLETABLE;
+/** @def NIL_RTHANDLETABLE
+ * NIL handle table handle. */
+#define NIL_RTHANDLETABLE                           ((RTHANDLETABLE)0)
+
+/** A handle to a low resolution timer. */
+typedef R3R0PTRTYPE(struct RTTIMERLRINT *)          RTTIMERLR;
+/** A pointer to a low resolution timer handle. */
+typedef RTTIMERLR                                  *PRTTIMERLR;
+/** @def NIL_RTTIMERLR
+ * NIL low resolution timer handle value. */
+#define NIL_RTTIMERLR                               ((RTTIMERLR)0)
+
+/** Handle to a random number generator. */
+typedef R3R0PTRTYPE(struct RTRANDINT *)             RTRAND;
+/** Pointer to a random number generator handle. */
+typedef RTRAND                                     *PRTRAND;
+/** NIL random number generator handle value. */
+#define NIL_RTRAND                                  ((RTRAND)0)
+
+/** Debug address space handle. */
+typedef R3R0PTRTYPE(struct RTDBGASINT *)            RTDBGAS;
+/** Pointer to a debug address space handle. */
+typedef RTDBGAS                                    *PRTDBGAS;
+/** NIL debug address space handle. */
+#define NIL_RTDBGAS                                 ((RTDBGAS)0)
+
+/** Debug module handle. */
+typedef R3R0PTRTYPE(struct RTDBGMODINT *)           RTDBGMOD;
+/** Pointer to a debug module handle. */
+typedef RTDBGMOD                                   *PRTDBGMOD;
+/** NIL debug module handle. */
+#define NIL_RTDBGMOD                                ((RTDBGMOD)0)
+
+/** Manifest handle. */
+typedef struct RTMANIFESTINT                       *RTMANIFEST;
+/** Pointer to a manifest handle. */
+typedef RTMANIFEST                                 *PRTMANIFEST;
+/** NIL manifest handle. */
+#define NIL_RTMANIFEST                              ((RTMANIFEST)~(uintptr_t)0)
+
+/** Memory pool handle. */
+typedef R3R0PTRTYPE(struct RTMEMPOOLINT *)          RTMEMPOOL;
+/** Pointer to a memory pool handle. */
+typedef RTMEMPOOL                                  *PRTMEMPOOL;
+/** NIL memory pool handle. */
+#define NIL_RTMEMPOOL                               ((RTMEMPOOL)0)
+/** The default memory pool handle. */
+#define RTMEMPOOL_DEFAULT                           ((RTMEMPOOL)-2)
+
+/** String cache handle. */
+typedef R3R0PTRTYPE(struct RTSTRCACHEINT *)         RTSTRCACHE;
+/** Pointer to a string cache handle. */
+typedef RTSTRCACHE                                 *PRTSTRCACHE;
+/** NIL string cache handle. */
+#define NIL_RTSTRCACHE                              ((RTSTRCACHE)0)
+/** The default string cache handle. */
+#define RTSTRCACHE_DEFAULT                          ((RTSTRCACHE)-2)
+
+
+/** Virtual Filesystem handle. */
+typedef struct RTVFSINTERNAL                       *RTVFS;
+/** Pointer to a VFS handle. */
+typedef RTVFS                                      *PRTVFS;
+/** A NIL VFS handle. */
+#define NIL_RTVFS                                   ((RTVFS)~(uintptr_t)0)
+
+/** Virtual Filesystem base object handle. */
+typedef struct RTVFSOBJINTERNAL                    *RTVFSOBJ;
+/** Pointer to a VFS base object handle. */
+typedef RTVFSOBJ                                   *PRTVFSOBJ;
+/** A NIL VFS base object handle. */
+#define NIL_RTVFSOBJ                                ((RTVFSOBJ)~(uintptr_t)0)
+
+/** Virtual Filesystem directory handle. */
+typedef struct RTVFSDIRINTERNAL                    *RTVFSDIR;
+/** Pointer to a VFS directory handle. */
+typedef RTVFSDIR                                   *PRTVFSDIR;
+/** A NIL VFS directory handle. */
+#define NIL_RTVFSDIR                                ((RTVFSDIR)~(uintptr_t)0)
+
+/** Virtual Filesystem filesystem stream handle. */
+typedef struct RTVFSFSSTREAMINTERNAL               *RTVFSFSSTREAM;
+/** Pointer to a VFS filesystem stream handle. */
+typedef RTVFSFSSTREAM                              *PRTVFSFSSTREAM;
+/** A NIL VFS filesystem stream handle. */
+#define NIL_RTVFSFSSTREAM                           ((RTVFSFSSTREAM)~(uintptr_t)0)
+
+/** Virtual Filesystem I/O stream handle. */
+typedef struct RTVFSIOSTREAMINTERNAL               *RTVFSIOSTREAM;
+/** Pointer to a VFS I/O stream handle. */
+typedef RTVFSIOSTREAM                              *PRTVFSIOSTREAM;
+/** A NIL VFS I/O stream handle. */
+#define NIL_RTVFSIOSTREAM                           ((RTVFSIOSTREAM)~(uintptr_t)0)
+
+/** Virtual Filesystem file handle. */
+typedef struct RTVFSFILEINTERNAL                   *RTVFSFILE;
+/** Pointer to a VFS file handle. */
+typedef RTVFSFILE                                  *PRTVFSFILE;
+/** A NIL VFS file handle. */
+#define NIL_RTVFSFILE                               ((RTVFSFILE)~(uintptr_t)0)
+
+/** Virtual Filesystem symbolic link handle. */
+typedef struct RTVFSSYMLINKINTERNAL                *RTVFSSYMLINK;
+/** Pointer to a VFS symbolic link handle. */
+typedef RTVFSSYMLINK                               *PRTVFSSYMLINK;
+/** A NIL VFS symbolic link handle. */
+#define NIL_RTVFSSYMLINK                            ((RTVFSSYMLINK)~(uintptr_t)0)
+
+/** Async I/O manager handle. */
+typedef struct RTAIOMGRINT                         *RTAIOMGR;
+/** Pointer to a async I/O manager handle. */
+typedef RTAIOMGR                                   *PRTAIOMGR;
+/** A NIL async I/O manager handle. */
+#define NIL_RTAIOMGR                                ((RTAIOMGR)~(uintptr_t)0)
+
+/** Async I/O manager file handle. */
+typedef struct RTAIOMGRFILEINT                     *RTAIOMGRFILE;
+/** Pointer to a async I/O manager file handle. */
+typedef RTAIOMGRFILE                               *PRTAIOMGRFILE;
+/** A NIL async I/O manager file handle. */
+#define NIL_RTAIOMGRFILE                            ((RTAIOMGRFILE)~(uintptr_t)0)
+
+/**
+ * Handle type.
+ *
+ * This is usually used together with RTHANDLEUNION.
+ */
+typedef enum RTHANDLETYPE
+{
+    /** The invalid zero value. */
+    RTHANDLETYPE_INVALID = 0,
+    /** File handle. */
+    RTHANDLETYPE_FILE,
+    /** Pipe handle */
+    RTHANDLETYPE_PIPE,
+    /** Socket handle. */
+    RTHANDLETYPE_SOCKET,
+    /** Thread handle. */
+    RTHANDLETYPE_THREAD,
+    /** The end of the valid values. */
+    RTHANDLETYPE_END,
+    /** The 32-bit type blow up. */
+    RTHANDLETYPE_32BIT_HACK = 0x7fffffff
+} RTHANDLETYPE;
+/** Pointer to a handle type. */
+typedef RTHANDLETYPE *PRTHANDLETYPE;
+
+/**
+ * Handle union.
+ *
+ * This is usually used together with RTHANDLETYPE or as RTHANDLE.
+ */
+typedef union RTHANDLEUNION
+{
+    RTFILE          hFile;              /**< File handle. */
+    RTPIPE          hPipe;              /**< Pipe handle. */
+    RTSOCKET        hSocket;            /**< Socket handle. */
+    RTTHREAD        hThread;            /**< Thread handle. */
+    /** Generic integer handle value.
+     * Note that RTFILE is not yet pointer sized, so accessing it via this member
+     * isn't necessarily safe or fully portable. */
+    RTHCUINTPTR     uInt;
+} RTHANDLEUNION;
+/** Pointer to a handle union. */
+typedef RTHANDLEUNION *PRTHANDLEUNION;
+/** Pointer to a const handle union. */
+typedef RTHANDLEUNION const *PCRTHANDLEUNION;
+
+/**
+ * Generic handle.
+ */
+typedef struct RTHANDLE
+{
+    /** The handle type. */
+    RTHANDLETYPE    enmType;
+    /** The handle value. */
+    RTHANDLEUNION   u;
+} RTHANDLE;
+/** Pointer to a generic handle. */
+typedef RTHANDLE *PRTHANDLE;
+/** Pointer to a const generic handle. */
+typedef RTHANDLE const *PCRTHANDLE;
+
+
+/**
+ * Standard handles.
+ *
+ * @remarks These have the correct file descriptor values for unixy systems and
+ *          can be used directly in code specific to those platforms.
+ */
+typedef enum RTHANDLESTD
+{
+    /** Invalid standard handle. */
+    RTHANDLESTD_INVALID = -1,
+    /** The standard input handle. */
+    RTHANDLESTD_INPUT = 0,
+    /** The standard output handle. */
+    RTHANDLESTD_OUTPUT,
+    /** The standard error handle. */
+    RTHANDLESTD_ERROR,
+    /** The typical 32-bit type hack. */
+    RTHANDLESTD_32BIT_HACK = 0x7fffffff
+} RTHANDLESTD;
+
+
+/**
+ * Error info.
+ *
+ * See RTErrInfo*.
+ */
+typedef struct RTERRINFO
+{
+    /** Flags, see RTERRINFO_FLAGS_XXX. */
+    uint32_t    fFlags;
+    /** The status code. */
+    int32_t     rc;
+    /** The size of the message  */
+    size_t      cbMsg;
+    /** The error buffer. */
+    char       *pszMsg;
+    /** Reserved for future use. */
+    void       *apvReserved[2];
+} RTERRINFO;
+/** Pointer to an error info structure. */
+typedef RTERRINFO *PRTERRINFO;
+/** Pointer to a const error info structure. */
+typedef RTERRINFO const *PCRTERRINFO;
+
+/**
+ * Static error info structure, see RTErrInfoInitStatic.
+ */
+typedef struct RTERRINFOSTATIC
+{
+    /** The core error info. */
+    RTERRINFO   Core;
+    /** The static message buffer. */
+    char        szMsg[3072];
+} RTERRINFOSTATIC;
+/** Pointer to a error info buffer. */
+typedef RTERRINFOSTATIC *PRTERRINFOSTATIC;
+/** Pointer to a const static error info buffer. */
+typedef RTERRINFOSTATIC const *PCRTERRINFOSTATIC;
+
+
+/**
+ * UUID data type.
+ *
+ * See RTUuid*.
+ *
+ * @remarks IPRT defines that the first three integers in the @c Gen struct
+ *          interpretation are in little endian representation.  This is
+ *          different to many other UUID implementation, and requires
+ *          conversion if you need to achieve consistent results.
+ */
+typedef union RTUUID
+{
+    /** 8-bit view. */
+    uint8_t     au8[16];
+    /** 16-bit view. */
+    uint16_t    au16[8];
+    /** 32-bit view. */
+    uint32_t    au32[4];
+    /** 64-bit view. */
+    uint64_t    au64[2];
+    /** The way the UUID is declared by the DCE specification. */
+    struct
+    {
+        uint32_t    u32TimeLow;
+        uint16_t    u16TimeMid;
+        uint16_t    u16TimeHiAndVersion;
+        uint8_t     u8ClockSeqHiAndReserved;
+        uint8_t     u8ClockSeqLow;
+        uint8_t     au8Node[6];
+    } Gen;
+} RTUUID;
+/** Pointer to UUID data. */
+typedef RTUUID *PRTUUID;
+/** Pointer to readonly UUID data. */
+typedef const RTUUID *PCRTUUID;
+
+/** Initializes a RTUUID structure with all zeros (RTUuidIsNull() true). */
+#define RTUUID_INITIALIZE_NULL  { { 0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0 } }
+
+/** UUID string maximum length. */
+#define RTUUID_STR_LENGTH       37
+
+
+/** Compression handle. */
+typedef struct RTZIPCOMP   *PRTZIPCOMP;
+/** Decompressor handle. */
+typedef struct RTZIPDECOMP *PRTZIPDECOMP;
+
+
+/**
+ * Unicode Code Point.
+ */
+typedef uint32_t            RTUNICP;
+/** Pointer to an Unicode Code Point. */
+typedef RTUNICP            *PRTUNICP;
+/** Pointer to an Unicode Code Point. */
+typedef const RTUNICP      *PCRTUNICP;
+/** Max value a RTUNICP type can hold. */
+#define RTUNICP_MAX         ( ~(RTUNICP)0 )
+/** Invalid code point.
+ * This is returned when encountered invalid encodings or invalid
+ * unicode code points. */
+#define RTUNICP_INVALID     ( UINT32_C(0xfffffffe) )
+
+
+/**
+ * UTF-16 character.
+ * @remark  wchar_t is not usable since it's compiler defined.
+ * @remark  When we use the term character we're not talking about unicode code point, but
+ *          the basic unit of the string encoding. Thus cwc - count of wide chars - means
+ *          count of RTUTF16; cuc - count of unicode chars - means count of RTUNICP;
+ *          and cch means count of the typedef 'char', which is assumed to be an octet.
+ */
+typedef uint16_t        RTUTF16;
+/** Pointer to a UTF-16 character. */
+typedef RTUTF16        *PRTUTF16;
+/** Pointer to a const UTF-16 character. */
+typedef const RTUTF16  *PCRTUTF16;
+
+
+/**
+ * String tuple to go with the RT_STR_TUPLE macro.
+ */
+typedef struct RTSTRTUPLE
+{
+    /** The string. */
+    const char *psz;
+    /** The string length. */
+    size_t      cch;
+} RTSTRTUPLE;
+/** Pointer to a string tuple. */
+typedef RTSTRTUPLE *PRTSTRTUPLE;
+/** Pointer to a const string tuple. */
+typedef RTSTRTUPLE const *PCRTSTRTUPLE;
+
+/**
+ * Wait for ever if we have to.
+ */
+#define RT_INDEFINITE_WAIT      (~0U)
+
+
+/**
+ * Generic process callback.
+ *
+ * @returns VBox status code. Failure will cancel the operation.
+ * @param   uPercentage     The percentage of the operation which has been completed.
+ * @param   pvUser          The user specified argument.
+ */
+typedef DECLCALLBACK(int) FNRTPROGRESS(unsigned uPrecentage, void *pvUser);
+/** Pointer to a generic progress callback function, FNRTPROCESS(). */
+typedef FNRTPROGRESS *PFNRTPROGRESS;
+
+/**
+ * Generic vprintf-like callback function for dumpers.
+ *
+ * @param   pvUser          User argument.
+ * @param   pszFormat       The format string.
+ * @param   va              Arguments for the format string.
+ */
+typedef DECLCALLBACK(void) FNRTDUMPPRINTFV(void *pvUser, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+/** Pointer to a generic printf-like function for dumping. */
+typedef FNRTDUMPPRINTFV *PFNRTDUMPPRINTFV;
+
+
+/**
+ * A point in a two dimentional coordinate system.
+ */
+typedef struct RTPOINT
+{
+    /** X coordinate. */
+    int32_t     x;
+    /** Y coordinate. */
+    int32_t     y;
+} RTPOINT;
+/** Pointer to a point. */
+typedef RTPOINT *PRTPOINT;
+/** Pointer to a const point. */
+typedef const RTPOINT *PCRTPOINT;
+
+
+/**
+ * Rectangle data type, double point.
+ */
+typedef struct RTRECT
+{
+    /** left X coordinate. */
+    int32_t     xLeft;
+    /** top Y coordinate. */
+    int32_t     yTop;
+    /** right X coordinate. (exclusive) */
+    int32_t     xRight;
+    /** bottom Y coordinate. (exclusive) */
+    int32_t     yBottom;
+} RTRECT;
+/** Pointer to a double point rectangle. */
+typedef RTRECT *PRTRECT;
+/** Pointer to a const double point rectangle. */
+typedef const RTRECT *PCRTRECT;
+
+
+/**
+ * Rectangle data type, point + size.
+ */
+typedef struct RTRECT2
+{
+    /** X coordinate.
+     * Unless stated otherwise, this is the top left corner. */
+    int32_t     x;
+    /** Y coordinate.
+     * Unless stated otherwise, this is the top left corner.  */
+    int32_t     y;
+    /** The width.
+     * Unless stated otherwise, this is to the right of (x,y) and will not
+     * be a negative number. */
+    int32_t     cx;
+    /** The height.
+     * Unless stated otherwise, this is down from (x,y) and will not be a
+     * negative number. */
+    int32_t     cy;
+} RTRECT2;
+/** Pointer to a point + size rectangle. */
+typedef RTRECT2 *PRTRECT2;
+/** Pointer to a const point + size rectangle. */
+typedef const RTRECT2 *PCRTRECT2;
+
+
+/**
+ * The size of a rectangle.
+ */
+typedef struct RTRECTSIZE
+{
+    /** The width (along the x-axis). */
+    uint32_t    cx;
+    /** The height (along the y-axis). */
+    uint32_t    cy;
+} RTRECTSIZE;
+/** Pointer to a rectangle size. */
+typedef RTRECTSIZE *PRTRECTSIZE;
+/** Pointer to a const rectangle size. */
+typedef const RTRECTSIZE *PCRTRECTSIZE;
+
+
+/**
+ * Ethernet MAC address.
+ *
+ * The first 24 bits make up the Organisationally Unique Identifier (OUI),
+ * where the first bit (little endian) indicates multicast (set) / unicast,
+ * and the second bit indicates locally (set) / global administered. If all
+ * bits are set, it's a broadcast.
+ */
+typedef union RTMAC
+{
+    /** @todo add a bitfield view of this stuff. */
+    /** 8-bit view. */
+    uint8_t     au8[6];
+    /** 16-bit view. */
+    uint16_t    au16[3];
+} RTMAC;
+/** Pointer to a MAC address. */
+typedef RTMAC *PRTMAC;
+/** Pointer to a readonly MAC address. */
+typedef const RTMAC *PCRTMAC;
+
+
+/** Pointer to a lock validator record.
+ * The structure definition is found in iprt/lockvalidator.h.  */
+typedef struct RTLOCKVALRECEXCL        *PRTLOCKVALRECEXCL;
+/** Pointer to a record of one ownership share.
+ * The structure definition is found in iprt/lockvalidator.h.  */
+typedef struct RTLOCKVALRECSHRD        *PRTLOCKVALRECSHRD;
+/** Pointer to a lock validator source position.
+ * The structure definition is found in iprt/lockvalidator.h.  */
+typedef struct RTLOCKVALSRCPOS         *PRTLOCKVALSRCPOS;
+/** Pointer to a const lock validator source position.
+ * The structure definition is found in iprt/lockvalidator.h.  */
+typedef struct RTLOCKVALSRCPOS const   *PCRTLOCKVALSRCPOS;
+
+/** @name   Special sub-class values.
+ * The range 16..UINT32_MAX is available to the user, the range 0..15 is
+ * reserved for the lock validator.  In the user range the locks can only be
+ * taking in ascending order.
+ * @{ */
+/** Invalid value.  */
+#define RTLOCKVAL_SUB_CLASS_INVALID     UINT32_C(0)
+/** Not allowed to be taken with any other locks in the same class.
+  * This is the recommended value.  */
+#define RTLOCKVAL_SUB_CLASS_NONE        UINT32_C(1)
+/** Any order is allowed within the class. */
+#define RTLOCKVAL_SUB_CLASS_ANY         UINT32_C(2)
+/** The first user value. */
+#define RTLOCKVAL_SUB_CLASS_USER        UINT32_C(16)
+/** @} */
+
+
+/**
+ * Digest types.
+ */
+typedef enum RTDIGESTTYPE
+{
+    /** Invalid digest value.  */
+    RTDIGESTTYPE_INVALID = 0,
+    /** Unknown digest type. */
+    RTDIGESTTYPE_UNKNOWN,
+    /** CRC32 checksum. */
+    RTDIGESTTYPE_CRC32,
+    /** CRC64 checksum. */
+    RTDIGESTTYPE_CRC64,
+    /** MD2 checksum (unsafe!). */
+    RTDIGESTTYPE_MD2,
+    /** MD4 checksum (unsafe!!). */
+    RTDIGESTTYPE_MD4,
+    /** MD5 checksum (unsafe!). */
+    RTDIGESTTYPE_MD5,
+    /** SHA-1 checksum (unsafe!). */
+    RTDIGESTTYPE_SHA1,
+    /** SHA-224 checksum. */
+    RTDIGESTTYPE_SHA224,
+    /** SHA-256 checksum. */
+    RTDIGESTTYPE_SHA256,
+    /** SHA-384 checksum. */
+    RTDIGESTTYPE_SHA384,
+    /** SHA-512 checksum. */
+    RTDIGESTTYPE_SHA512,
+    /** SHA-512/224 checksum. */
+    RTDIGESTTYPE_SHA512T224,
+    /** SHA-512/256 checksum. */
+    RTDIGESTTYPE_SHA512T256,
+    /** End of valid types. */
+    RTDIGESTTYPE_END,
+    /** Usual 32-bit type blowup. */
+    RTDIGESTTYPE_32BIT_HACK = 0x7fffffff
+} RTDIGESTTYPE;
+
+/**
+ * Process exit codes.
+ */
+typedef enum RTEXITCODE
+{
+    /** Success. */
+    RTEXITCODE_SUCCESS = 0,
+    /** General failure. */
+    RTEXITCODE_FAILURE = 1,
+    /** Invalid arguments.  */
+    RTEXITCODE_SYNTAX = 2,
+    /** Initialization failure (usually IPRT, but could be used for other
+     *  components as well). */
+    RTEXITCODE_INIT = 3,
+    /** Test skipped. */
+    RTEXITCODE_SKIPPED = 4,
+    /** The end of valid exit codes. */
+    RTEXITCODE_END,
+    /** The usual 32-bit type hack. */
+    RTEXITCODE_32BIT_HACK = 0x7fffffff
+} RTEXITCODE;
+
+/**
+ * Range descriptor.
+ */
+typedef struct RTRANGE
+{
+    /** Start offset. */
+    uint64_t    offStart;
+    /** Range size. */
+    size_t      cbRange;
+} RTRANGE;
+/** Pointer to a range descriptor. */
+typedef RTRANGE *PRTRANGE;
+/** Pointer to a readonly range descriptor. */
+typedef const RTRANGE *PCRTRANGE;
+
+
+/**
+ * Generic pointer union.
+ */
+typedef union RTPTRUNION
+{
+    /** Pointer into the void. */
+    void                   *pv;
+    /** As a signed integer. */
+    intptr_t                i;
+    /** As an unsigned integer. */
+    intptr_t                u;
+    /** Pointer to char value. */
+    char                   *pch;
+    /** Pointer to char value. */
+    unsigned char          *puch;
+    /** Pointer to a int value. */
+    int                    *pi;
+    /** Pointer to a unsigned int value. */
+    unsigned int           *pu;
+    /** Pointer to a long value. */
+    long                   *pl;
+    /** Pointer to a long value. */
+    unsigned long          *pul;
+    /** Pointer to a 8-bit unsigned value. */
+    uint8_t                *pu8;
+    /** Pointer to a 16-bit unsigned value. */
+    uint16_t               *pu16;
+    /** Pointer to a 32-bit unsigned value. */
+    uint32_t               *pu32;
+    /** Pointer to a 64-bit unsigned value. */
+    uint64_t               *pu64;
+    /** Pointer to a UTF-16 character. */
+    PRTUTF16                pwc;
+    /** Pointer to a UUID character. */
+    PRTUUID                 pUuid;
+} RTPTRUNION;
+/** Pointer to a pointer union. */
+typedef RTPTRUNION *PRTPTRUNION;
+
+/**
+ * Generic const pointer union.
+ */
+typedef union RTCPTRUNION
+{
+    /** Pointer into the void. */
+    void const             *pv;
+    /** As a signed integer. */
+    intptr_t                i;
+    /** As an unsigned integer. */
+    intptr_t                u;
+    /** Pointer to char value. */
+    char const             *pch;
+    /** Pointer to char value. */
+    unsigned char const    *puch;
+    /** Pointer to a int value. */
+    int const              *pi;
+    /** Pointer to a unsigned int value. */
+    unsigned int const     *pu;
+    /** Pointer to a long value. */
+    long const             *pl;
+    /** Pointer to a long value. */
+    unsigned long const    *pul;
+    /** Pointer to a 8-bit unsigned value. */
+    uint8_t const          *pu8;
+    /** Pointer to a 16-bit unsigned value. */
+    uint16_t const         *pu16;
+    /** Pointer to a 32-bit unsigned value. */
+    uint32_t const         *pu32;
+    /** Pointer to a 64-bit unsigned value. */
+    uint64_t const         *pu64;
+    /** Pointer to a UTF-16 character. */
+    PCRTUTF16               pwc;
+    /** Pointer to a UUID character. */
+    PCRTUUID                pUuid;
+} RTCPTRUNION;
+/** Pointer to a const pointer union. */
+typedef RTCPTRUNION *PRTCPTRUNION;
+
+/**
+ * Generic volatile pointer union.
+ */
+typedef union RTVPTRUNION
+{
+    /** Pointer into the void. */
+    void volatile          *pv;
+    /** As a signed integer. */
+    intptr_t                i;
+    /** As an unsigned integer. */
+    intptr_t                u;
+    /** Pointer to char value. */
+    char volatile          *pch;
+    /** Pointer to char value. */
+    unsigned char volatile *puch;
+    /** Pointer to a int value. */
+    int volatile           *pi;
+    /** Pointer to a unsigned int value. */
+    unsigned int volatile  *pu;
+    /** Pointer to a long value. */
+    long volatile          *pl;
+    /** Pointer to a long value. */
+    unsigned long volatile *pul;
+    /** Pointer to a 8-bit unsigned value. */
+    uint8_t volatile       *pu8;
+    /** Pointer to a 16-bit unsigned value. */
+    uint16_t volatile      *pu16;
+    /** Pointer to a 32-bit unsigned value. */
+    uint32_t volatile      *pu32;
+    /** Pointer to a 64-bit unsigned value. */
+    uint64_t volatile      *pu64;
+    /** Pointer to a UTF-16 character. */
+    RTUTF16 volatile       *pwc;
+    /** Pointer to a UUID character. */
+    RTUUID volatile        *pUuid;
+} RTVPTRUNION;
+/** Pointer to a const pointer union. */
+typedef RTVPTRUNION *PRTVPTRUNION;
+
+/**
+ * Generic const volatile pointer union.
+ */
+typedef union RTCVPTRUNION
+{
+    /** Pointer into the void. */
+    void const volatile            *pv;
+    /** As a signed integer. */
+    intptr_t                        i;
+    /** As an unsigned integer. */
+    intptr_t                        u;
+    /** Pointer to char value. */
+    char const volatile            *pch;
+    /** Pointer to char value. */
+    unsigned char const volatile   *puch;
+    /** Pointer to a int value. */
+    int const volatile             *pi;
+    /** Pointer to a unsigned int value. */
+    unsigned int const volatile    *pu;
+    /** Pointer to a long value. */
+    long const volatile            *pl;
+    /** Pointer to a long value. */
+    unsigned long const volatile   *pul;
+    /** Pointer to a 8-bit unsigned value. */
+    uint8_t const volatile         *pu8;
+    /** Pointer to a 16-bit unsigned value. */
+    uint16_t const volatile        *pu16;
+    /** Pointer to a 32-bit unsigned value. */
+    uint32_t const volatile        *pu32;
+    /** Pointer to a 64-bit unsigned value. */
+    uint64_t const volatile        *pu64;
+    /** Pointer to a UTF-16 character. */
+    RTUTF16 const volatile         *pwc;
+    /** Pointer to a UUID character. */
+    RTUUID const volatile          *pUuid;
+} RTCVPTRUNION;
+/** Pointer to a const pointer union. */
+typedef RTCVPTRUNION *PRTCVPTRUNION;
+
+
+
+#ifdef __cplusplus
+/**
+ * Strict type validation helper class.
+ *
+ * See RTErrStrictType and RT_SUCCESS_NP.
+ */
+class RTErrStrictType2
+{
+protected:
+    /** The status code.  */
+    int32_t m_rc;
+
+public:
+    /**
+     * Constructor.
+     * @param   rc      IPRT style status code.
+     */
+    RTErrStrictType2(int32_t rc) : m_rc(rc)
+    {
+    }
+
+    /**
+     * Get the status code.
+     * @returns IPRT style status code.
+     */
+    int32_t getValue() const
+    {
+        return m_rc;
+    }
+};
+#endif /* __cplusplus */
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/uint64.h b/ubuntu/vbox/include/iprt/uint64.h
new file mode 100644 (file)
index 0000000..38ccbc4
--- /dev/null
@@ -0,0 +1,1330 @@
+/** @file
+ * IPRT - RTUINT64U methods for old 32-bit and 16-bit compilers.
+ */
+
+/*
+ * Copyright (C) 2011-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.
+ */
+
+#ifndef ___iprt_uint64_h
+#define ___iprt_uint64_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/asm.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_uint64 RTUInt64 - 64-bit Unsigned Integer Methods for ancient compilers
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/**
+ * Test if a 128-bit unsigned integer value is zero.
+ *
+ * @returns true if they are, false if they aren't.
+ * @param   pValue          The input and output value.
+ */
+DECLINLINE(bool) RTUInt64IsZero(PRTUINT64U pValue)
+{
+#if ARCH_BITS >= 32
+    return pValue->s.Lo == 0
+        && pValue->s.Hi == 0;
+#else
+    return pValue->Words.w0 == 0
+        && pValue->Words.w1 == 0
+        && pValue->Words.w2 == 0
+        && pValue->Words.w3 == 0;
+#endif
+}
+
+
+/**
+ * Set a 128-bit unsigned integer value to zero.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64SetZero(PRTUINT64U pResult)
+{
+#if ARCH_BITS >= 32
+    pResult->s.Hi = 0;
+    pResult->s.Lo = 0;
+#else
+    pResult->Words.w0 = 0;
+    pResult->Words.w1 = 0;
+    pResult->Words.w2 = 0;
+    pResult->Words.w3 = 0;
+#endif
+    return pResult;
+}
+
+
+/**
+ * Set a 32-bit unsigned integer value to the maximum value.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64SetMax(PRTUINT64U pResult)
+{
+#if ARCH_BITS >= 32
+    pResult->s.Hi = UINT32_MAX;
+    pResult->s.Lo = UINT32_MAX;
+#else
+    pResult->Words.w0 = UINT16_MAX;
+    pResult->Words.w1 = UINT16_MAX;
+    pResult->Words.w2 = UINT16_MAX;
+    pResult->Words.w3 = UINT16_MAX;
+#endif
+    return pResult;
+}
+
+
+
+
+/**
+ * Adds two 64-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable.
+ * @param   pValue1             The first value.
+ * @param   pValue2             The second value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64Add(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
+{
+    pResult->s.Hi = pValue1->s.Hi + pValue2->s.Hi;
+    pResult->s.Lo = pValue1->s.Lo + pValue2->s.Lo;
+    if (pResult->s.Lo < pValue1->s.Lo)
+        pResult->s.Hi++;
+    return pResult;
+}
+
+
+/**
+ * Adds a 64-bit and a 32-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable.
+ * @param   pValue1             The first value.
+ * @param   uValue2             The second value, 32-bit.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AddU32(PRTUINT64U pResult, PCRTUINT64U pValue1, uint32_t uValue2)
+{
+    pResult->s.Hi = pValue1->s.Hi;
+    pResult->s.Lo = pValue1->s.Lo + uValue2;
+    if (pResult->s.Lo < pValue1->s.Lo)
+        pResult->s.Hi++;
+    return pResult;
+}
+
+
+/**
+ * Subtracts a 64-bit unsigned integer value from another.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable.
+ * @param   pValue1             The minuend value.
+ * @param   pValue2             The subtrahend value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64Sub(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
+{
+    pResult->s.Lo = pValue1->s.Lo - pValue2->s.Lo;
+    pResult->s.Hi = pValue1->s.Hi - pValue2->s.Hi;
+    if (pResult->s.Lo > pValue1->s.Lo)
+        pResult->s.Hi--;
+    return pResult;
+}
+
+
+/**
+ * Multiplies two 64-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable.
+ * @param   pValue1             The first value.
+ * @param   pValue2             The second value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64Mul(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
+{
+    RTUINT32U uTmp;
+
+    /* multiply all words in v1 by v2.w0. */
+    pResult->s.Lo = (uint32_t)pValue1->Words.w0 * pValue2->Words.w0;
+
+    uTmp.u = (uint32_t)pValue1->Words.w1 * pValue2->Words.w0;
+    pResult->Words.w3 = 0;
+    pResult->Words.w2 = uTmp.Words.w1;
+    pResult->Words.w1 += uTmp.Words.w0;
+    if (pResult->Words.w1 < uTmp.Words.w0)
+        if (pResult->Words.w2++ == UINT16_MAX)
+            pResult->Words.w3++;
+
+    pResult->s.Hi += (uint32_t)pValue1->Words.w2 * pValue2->Words.w0;
+    pResult->Words.w3       += pValue1->Words.w3 * pValue2->Words.w0;
+
+    /* multiply w0, w1 & w2 in v1 by v2.w1. */
+    uTmp.u = (uint32_t)pValue1->Words.w0 * pValue2->Words.w1;
+    pResult->Words.w1 += uTmp.Words.w0;
+    if (pResult->Words.w1 < uTmp.Words.w0)
+        if (pResult->Words.w2++ == UINT16_MAX)
+            pResult->Words.w3++;
+
+    pResult->Words.w2 += uTmp.Words.w1;
+    if (pResult->Words.w2 < uTmp.Words.w1)
+        pResult->Words.w3++;
+
+    pResult->s.Hi += (uint32_t)pValue1->Words.w1 * pValue2->Words.w1;
+    pResult->Words.w3       += pValue1->Words.w2 * pValue2->Words.w1;
+
+    /* multiply w0 & w1 in v1 by v2.w2. */
+    pResult->s.Hi += (uint32_t)pValue1->Words.w0 * pValue2->Words.w2;
+    pResult->Words.w3       += pValue1->Words.w1 * pValue2->Words.w2;
+
+    /* multiply w0 in v1 by v2.w3. */
+    pResult->Words.w3       += pValue1->Words.w0 * pValue2->Words.w3;
+
+    return pResult;
+}
+
+
+/**
+ * Multiplies an 64-bit unsigned integer by a 32-bit unsigned integer value.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable.
+ * @param   pValue1             The first value.
+ * @param   uValue2             The second value, 32-bit.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64MulByU32(PRTUINT64U pResult, PCRTUINT64U pValue1, uint32_t uValue2)
+{
+    uint16_t const uLoValue2 = (uint16_t)uValue2;
+    uint16_t const uHiValue2 = (uint16_t)(uValue2 >> 16);
+    RTUINT32U uTmp;
+
+    /* multiply all words in v1 by uLoValue1. */
+    pResult->s.Lo = (uint32_t)pValue1->Words.w0 * uLoValue2;
+
+    uTmp.u = (uint32_t)pValue1->Words.w1 * uLoValue2;
+    pResult->Words.w3 = 0;
+    pResult->Words.w2 = uTmp.Words.w1;
+    pResult->Words.w1 += uTmp.Words.w0;
+    if (pResult->Words.w1 < uTmp.Words.w0)
+        if (pResult->Words.w2++ == UINT16_MAX)
+            pResult->Words.w3++;
+
+    pResult->s.Hi += (uint32_t)pValue1->Words.w2 * uLoValue2;
+    pResult->Words.w3       += pValue1->Words.w3 * uLoValue2;
+
+    /* multiply w0, w1 & w2 in v1 by uHiValue2. */
+    uTmp.u = (uint32_t)pValue1->Words.w0 * uHiValue2;
+    pResult->Words.w1 += uTmp.Words.w0;
+    if (pResult->Words.w1 < uTmp.Words.w0)
+        if (pResult->Words.w2++ == UINT16_MAX)
+            pResult->Words.w3++;
+
+    pResult->Words.w2 += uTmp.Words.w1;
+    if (pResult->Words.w2 < uTmp.Words.w1)
+        pResult->Words.w3++;
+
+    pResult->s.Hi += (uint32_t)pValue1->Words.w1 * uHiValue2;
+    pResult->Words.w3     += pValue1->Words.w2 * uHiValue2;
+
+    return pResult;
+}
+
+
+/**
+ * Multiplies two 32-bit unsigned integer values with 64-bit precision.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable.
+ * @param   uValue1             The first value. 32-bit.
+ * @param   uValue2             The second value, 32-bit.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64MulU32ByU32(PRTUINT64U pResult, uint32_t uValue1, uint32_t uValue2)
+{
+    uint16_t const uLoValue1 = (uint16_t)uValue1;
+    uint16_t const uHiValue1 = (uint16_t)(uValue1 >> 16);
+    uint16_t const uLoValue2 = (uint16_t)uValue2;
+    uint16_t const uHiValue2 = (uint16_t)(uValue2 >> 16);
+    RTUINT32U uTmp;
+
+    /* Multiply uLoValue1 and uHiValue1 by uLoValue1. */
+    pResult->s.Lo = (uint32_t)uLoValue1 * uLoValue2;
+
+    uTmp.u = (uint32_t)uHiValue1 * uLoValue2;
+    pResult->Words.w3 = 0;
+    pResult->Words.w2 = uTmp.Words.w1;
+    pResult->Words.w1 += uTmp.Words.w0;
+    if (pResult->Words.w1 < uTmp.Words.w0)
+        if (pResult->Words.w2++ == UINT16_MAX)
+            pResult->Words.w3++;
+
+    /* Multiply uLoValue1 and uHiValue1 by uHiValue2. */
+    uTmp.u = (uint32_t)uLoValue1 * uHiValue2;
+    pResult->Words.w1 += uTmp.Words.w0;
+    if (pResult->Words.w1 < uTmp.Words.w0)
+        if (pResult->Words.w2++ == UINT16_MAX)
+            pResult->Words.w3++;
+
+    pResult->Words.w2 += uTmp.Words.w1;
+    if (pResult->Words.w2 < uTmp.Words.w1)
+        pResult->Words.w3++;
+
+    pResult->s.Hi += (uint32_t)uHiValue1 * uHiValue2;
+    return pResult;
+}
+
+
+DECLINLINE(PRTUINT64U) RTUInt64DivRem(PRTUINT64U pQuotient, PRTUINT64U pRemainder, PCRTUINT64U pValue1, PCRTUINT64U pValue2);
+
+/**
+ * Divides a 64-bit unsigned integer value by another.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable.
+ * @param   pValue1             The dividend value.
+ * @param   pValue2             The divisor value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64Div(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
+{
+    RTUINT64U Ignored;
+    return RTUInt64DivRem(pResult, &Ignored, pValue1, pValue2);
+}
+
+
+/**
+ * Divides a 64-bit unsigned integer value by another, returning the remainder.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable (remainder).
+ * @param   pValue1             The dividend value.
+ * @param   pValue2             The divisor value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64Mod(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
+{
+    RTUINT64U Ignored;
+    RTUInt64DivRem(&Ignored, pResult, pValue1, pValue2);
+    return pResult;
+}
+
+
+/**
+ * Bitwise AND of two 64-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable.
+ * @param   pValue1             The first value.
+ * @param   pValue2             The second value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64And(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
+{
+    pResult->s.Hi = pValue1->s.Hi & pValue2->s.Hi;
+    pResult->s.Lo = pValue1->s.Lo & pValue2->s.Lo;
+    return pResult;
+}
+
+
+/**
+ * Bitwise OR of two 64-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable.
+ * @param   pValue1             The first value.
+ * @param   pValue2             The second value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64Or( PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
+{
+    pResult->s.Hi = pValue1->s.Hi | pValue2->s.Hi;
+    pResult->s.Lo = pValue1->s.Lo | pValue2->s.Lo;
+    return pResult;
+}
+
+
+/**
+ * Bitwise XOR of two 64-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable.
+ * @param   pValue1             The first value.
+ * @param   pValue2             The second value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64Xor(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
+{
+    pResult->s.Hi = pValue1->s.Hi ^ pValue2->s.Hi;
+    pResult->s.Lo = pValue1->s.Lo ^ pValue2->s.Lo;
+    return pResult;
+}
+
+
+/**
+ * Shifts a 64-bit unsigned integer value @a cBits to the left.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable.
+ * @param   pValue              The value to shift.
+ * @param   cBits               The number of bits to shift it.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64ShiftLeft(PRTUINT64U pResult, PCRTUINT64U pValue, int cBits)
+{
+    cBits &= 63;
+    if (cBits < 32)
+    {
+        pResult->s.Lo = pValue->s.Lo << cBits;
+        pResult->s.Hi = (pValue->s.Hi << cBits) | (pValue->s.Lo >> (32 - cBits));
+    }
+    else
+    {
+        pResult->s.Lo = 0;
+        pResult->s.Hi = pValue->s.Lo << (cBits - 32);
+    }
+    return pResult;
+}
+
+
+/**
+ * Shifts a 64-bit unsigned integer value @a cBits to the right.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable.
+ * @param   pValue              The value to shift.
+ * @param   cBits               The number of bits to shift it.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64ShiftRight(PRTUINT64U pResult, PCRTUINT64U pValue, int cBits)
+{
+    cBits &= 63;
+    if (cBits < 32)
+    {
+        pResult->s.Hi = pValue->s.Hi >> cBits;
+        pResult->s.Lo = (pValue->s.Lo >> cBits) | (pValue->s.Hi << (32 - cBits));
+    }
+    else
+    {
+        pResult->s.Hi = 0;
+        pResult->s.Lo = pValue->s.Hi >> (cBits - 32);
+    }
+    return pResult;
+}
+
+
+/**
+ * Boolean not (result 0 or 1).
+ *
+ * @returns pResult.
+ * @param   pResult             The result variable.
+ * @param   pValue              The value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64BooleanNot(PRTUINT64U pResult, PCRTUINT64U pValue)
+{
+    pResult->s.Lo = pValue->s.Lo || pValue->s.Hi ? 0 : 1;
+    pResult->s.Hi = 0;
+    return pResult;
+}
+
+
+/**
+ * Bitwise not (flips each bit of the 64 bits).
+ *
+ * @returns pResult.
+ * @param   pResult             The result variable.
+ * @param   pValue              The value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64BitwiseNot(PRTUINT64U pResult, PCRTUINT64U pValue)
+{
+    pResult->s.Hi = ~pValue->s.Hi;
+    pResult->s.Lo = ~pValue->s.Lo;
+    return pResult;
+}
+
+
+/**
+ * Assigns one 64-bit unsigned integer value to another.
+ *
+ * @returns pResult
+ * @param   pResult             The result variable.
+ * @param   pValue              The value to assign.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64Assign(PRTUINT64U pResult, PCRTUINT64U pValue)
+{
+#if ARCH_BITS >= 32
+    pResult->s.Hi = pValue->s.Hi;
+    pResult->s.Lo = pValue->s.Lo;
+#else
+    pResult->Words.w0 = pValue->Words.w0;
+    pResult->Words.w1 = pValue->Words.w1;
+    pResult->Words.w2 = pValue->Words.w2;
+    pResult->Words.w3 = pValue->Words.w3;
+#endif
+    return pResult;
+}
+
+
+/**
+ * Assigns a boolean value to 64-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param   pValueResult        The result variable.
+ * @param   fValue              The boolean value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignBoolean(PRTUINT64U pValueResult, bool fValue)
+{
+#if ARCH_BITS >= 32
+    pValueResult->s.Lo = fValue;
+    pValueResult->s.Hi = 0;
+#else
+    pValueResult->Words.w0 = fValue;
+    pValueResult->Words.w1 = 0;
+    pValueResult->Words.w2 = 0;
+    pValueResult->Words.w3 = 0;
+#endif
+    return pValueResult;
+}
+
+
+/**
+ * Assigns a 8-bit unsigned integer value to 64-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param   pValueResult        The result variable.
+ * @param   u8Value             The 8-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignU8(PRTUINT64U pValueResult, uint8_t u8Value)
+{
+#if ARCH_BITS >= 32
+    pValueResult->s.Lo = u8Value;
+    pValueResult->s.Hi = 0;
+#else
+    pValueResult->Words.w0 = u8Value;
+    pValueResult->Words.w1 = 0;
+    pValueResult->Words.w2 = 0;
+    pValueResult->Words.w3 = 0;
+#endif
+    return pValueResult;
+}
+
+
+/**
+ * Assigns a 16-bit unsigned integer value to 64-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param   pValueResult        The result variable.
+ * @param   u16Value            The 16-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignU16(PRTUINT64U pValueResult, uint16_t u16Value)
+{
+#if ARCH_BITS >= 32
+    pValueResult->s.Lo = u16Value;
+    pValueResult->s.Hi = 0;
+#else
+    pValueResult->Words.w0 = u16Value;
+    pValueResult->Words.w1 = 0;
+    pValueResult->Words.w2 = 0;
+    pValueResult->Words.w3 = 0;
+#endif
+    return pValueResult;
+}
+
+
+/**
+ * Assigns a 32-bit unsigned integer value to 64-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param   pValueResult        The result variable.
+ * @param   u32Value            The 32-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignU32(PRTUINT64U pValueResult, uint32_t u32Value)
+{
+#if ARCH_BITS >= 32
+    pValueResult->s.Lo = u32Value;
+    pValueResult->s.Hi = 0;
+#else
+    pValueResult->Words.w0 = (uint16_t)u32Value;
+    pValueResult->Words.w1 = u32Value >> 16;
+    pValueResult->Words.w2 = 0;
+    pValueResult->Words.w3 = 0;
+#endif
+    return pValueResult;
+}
+
+
+/**
+ * Adds two 64-bit unsigned integer values, storing the result in the first.
+ *
+ * @returns pValue1Result.
+ * @param   pValue1Result   The first value and result.
+ * @param   pValue2         The second value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignAdd(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
+{
+    uint32_t const uTmp = pValue1Result->s.Lo;
+    pValue1Result->s.Lo += pValue2->s.Lo;
+    if (pValue1Result->s.Lo < uTmp)
+        pValue1Result->s.Hi++;
+    pValue1Result->s.Hi += pValue2->s.Hi;
+    return pValue1Result;
+}
+
+
+/**
+ * Subtracts two 64-bit unsigned integer values, storing the result in the
+ * first.
+ *
+ * @returns pValue1Result.
+ * @param   pValue1Result   The minuend value and result.
+ * @param   pValue2         The subtrahend value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignSub(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
+{
+    uint32_t const uTmp = pValue1Result->s.Lo;
+    pValue1Result->s.Lo -= pValue2->s.Lo;
+    if (pValue1Result->s.Lo > uTmp)
+        pValue1Result->s.Hi--;
+    pValue1Result->s.Hi -= pValue2->s.Hi;
+    return pValue1Result;
+}
+
+
+/**
+ * Multiplies two 64-bit unsigned integer values, storing the result in the
+ * first.
+ *
+ * @returns pValue1Result.
+ * @param   pValue1Result   The first value and result.
+ * @param   pValue2         The second value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignMul(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
+{
+    RTUINT64U Result;
+    RTUInt64Mul(&Result, pValue1Result, pValue2);
+    *pValue1Result = Result;
+    return pValue1Result;
+}
+
+
+/**
+ * Divides a 64-bit unsigned integer value by another, storing the result in
+ * the first.
+ *
+ * @returns pValue1Result.
+ * @param   pValue1Result   The dividend value and result.
+ * @param   pValue2         The divisor value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignDiv(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
+{
+    RTUINT64U Result;
+    RTUINT64U Ignored;
+    RTUInt64DivRem(&Result, &Ignored, pValue1Result, pValue2);
+    *pValue1Result = Result;
+    return pValue1Result;
+}
+
+
+/**
+ * Divides a 64-bit unsigned integer value by another, storing the remainder in
+ * the first.
+ *
+ * @returns pValue1Result.
+ * @param   pValue1Result   The dividend value and result (remainder).
+ * @param   pValue2         The divisor value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignMod(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
+{
+    RTUINT64U Ignored;
+    RTUINT64U Result;
+    RTUInt64DivRem(&Ignored, &Result, pValue1Result, pValue2);
+    *pValue1Result = Result;
+    return pValue1Result;
+}
+
+
+/**
+ * Performs a bitwise AND of two 64-bit unsigned integer values and assigned
+ * the result to the first one.
+ *
+ * @returns pValue1Result.
+ * @param   pValue1Result   The first value and result.
+ * @param   pValue2         The second value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignAnd(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
+{
+#if ARCH_BITS >= 32
+    pValue1Result->s.Hi &= pValue2->s.Hi;
+    pValue1Result->s.Lo &= pValue2->s.Lo;
+#else
+    pValue1Result->Words.w0 &= pValue2->Words.w0;
+    pValue1Result->Words.w1 &= pValue2->Words.w1;
+    pValue1Result->Words.w2 &= pValue2->Words.w2;
+    pValue1Result->Words.w3 &= pValue2->Words.w3;
+#endif
+    return pValue1Result;
+}
+
+
+/**
+ * Performs a bitwise AND of a 64-bit unsigned integer value and a mask made
+ * up of the first N bits, assigning the result to the the 64-bit value.
+ *
+ * @returns pValueResult.
+ * @param   pValueResult    The value and result.
+ * @param   cBits           The number of bits to AND (counting from the first
+ *                          bit).
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignAndNFirstBits(PRTUINT64U pValueResult, unsigned cBits)
+{
+    if (cBits <= 32)
+    {
+        if (cBits != 32)
+            pValueResult->s.Lo &= (RT_BIT_32(cBits) - 1);
+        pValueResult->s.Hi = 0;
+    }
+    else if (cBits < 64)
+        pValueResult->s.Hi &= (RT_BIT_32(cBits - 32) - 1);
+    return pValueResult;
+}
+
+
+/**
+ * Performs a bitwise OR of two 64-bit unsigned integer values and assigned
+ * the result to the first one.
+ *
+ * @returns pValue1Result.
+ * @param   pValue1Result   The first value and result.
+ * @param   pValue2         The second value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignOr(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
+{
+#if ARCH_BITS >= 32
+    pValue1Result->s.Hi |= pValue2->s.Hi;
+    pValue1Result->s.Lo |= pValue2->s.Lo;
+#else
+    pValue1Result->Words.w0 |= pValue2->Words.w0;
+    pValue1Result->Words.w1 |= pValue2->Words.w1;
+    pValue1Result->Words.w2 |= pValue2->Words.w2;
+    pValue1Result->Words.w3 |= pValue2->Words.w3;
+#endif
+    return pValue1Result;
+}
+
+
+/**
+ * ORs in a bit and assign the result to the input value.
+ *
+ * @returns pValue1Result.
+ * @param   pValue1Result   The first value and result.
+ * @param   iBit            The bit to set (0 based).
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignOrBit(PRTUINT64U pValue1Result, unsigned iBit)
+{
+#if ARCH_BITS >= 32
+    if (iBit >= 32)
+        pValue1Result->s.Hi |= RT_BIT_32(iBit - 32);
+    else
+        pValue1Result->s.Lo |= RT_BIT_32(iBit);
+#else
+    if (iBit >= 32)
+    {
+        if (iBit >= 48)
+            pValue1Result->Words.w3 |= UINT16_C(1) << (iBit - 48);
+        else
+            pValue1Result->Words.w2 |= UINT16_C(1) << (iBit - 32);
+    }
+    else
+    {
+        if (iBit >= 16)
+            pValue1Result->Words.w1 |= UINT16_C(1) << (iBit - 16);
+        else
+            pValue1Result->Words.w0 |= UINT16_C(1) << (iBit);
+    }
+#endif
+    return pValue1Result;
+}
+
+
+
+/**
+ * Performs a bitwise XOR of two 64-bit unsigned integer values and assigned
+ * the result to the first one.
+ *
+ * @returns pValue1Result.
+ * @param   pValue1Result   The first value and result.
+ * @param   pValue2         The second value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignXor(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
+{
+#if ARCH_BITS >= 32
+    pValue1Result->s.Hi ^= pValue2->s.Hi;
+    pValue1Result->s.Lo ^= pValue2->s.Lo;
+#else
+    pValue1Result->Words.w0 ^= pValue2->Words.w0;
+    pValue1Result->Words.w1 ^= pValue2->Words.w1;
+    pValue1Result->Words.w2 ^= pValue2->Words.w2;
+    pValue1Result->Words.w3 ^= pValue2->Words.w3;
+#endif
+    return pValue1Result;
+}
+
+
+/**
+ * Performs a bitwise left shift on a 64-bit unsigned integer value, assigning
+ * the result to it.
+ *
+ * @returns pValueResult.
+ * @param   pValueResult    The first value and result.
+ * @param   cBits           The number of bits to shift.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignShiftLeft(PRTUINT64U pValueResult, int cBits)
+{
+    RTUINT64U const InVal = *pValueResult;
+    if (cBits > 0)
+    {
+        /* (left shift) */
+        cBits &= 31;
+        if (cBits >= 32)
+        {
+            pValueResult->s.Lo  = 0;
+            pValueResult->s.Hi  = InVal.s.Lo << (cBits - 32);
+        }
+        else
+        {
+            pValueResult->s.Hi  = InVal.s.Hi << cBits;
+            pValueResult->s.Hi |= InVal.s.Lo >> (32 - cBits);
+            pValueResult->s.Lo  = InVal.s.Lo << cBits;
+        }
+    }
+    else if (cBits < 0)
+    {
+        /* (right shift) */
+        cBits = -cBits;
+        cBits &= 31;
+        if (cBits >= 32)
+        {
+            pValueResult->s.Hi  = 0;
+            pValueResult->s.Lo  = InVal.s.Hi >> (cBits - 32);
+        }
+        else
+        {
+            pValueResult->s.Lo  = InVal.s.Lo >> cBits;
+            pValueResult->s.Lo |= InVal.s.Hi << (32 - cBits);
+            pValueResult->s.Hi  = InVal.s.Hi >> cBits;
+        }
+    }
+    return pValueResult;
+}
+
+
+/**
+ * Performs a bitwise left shift on a 64-bit unsigned integer value, assigning
+ * the result to it.
+ *
+ * @returns pValueResult.
+ * @param   pValueResult    The first value and result.
+ * @param   cBits           The number of bits to shift.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignShiftRight(PRTUINT64U pValueResult, int cBits)
+{
+    return RTUInt64AssignShiftLeft(pValueResult, -cBits);
+}
+
+
+/**
+ * Performs a bitwise NOT on a 64-bit unsigned integer value, assigning the
+ * result to it.
+ *
+ * @returns pValueResult
+ * @param   pValueResult    The value and result.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignBitwiseNot(PRTUINT64U pValueResult)
+{
+#if ARCH_BITS >= 32
+    pValueResult->s.Hi = ~pValueResult->s.Hi;
+    pValueResult->s.Lo = ~pValueResult->s.Lo;
+#else
+    pValueResult->Words.w0 = ~pValueResult->Words.w0;
+    pValueResult->Words.w1 = ~pValueResult->Words.w1;
+    pValueResult->Words.w2 = ~pValueResult->Words.w2;
+    pValueResult->Words.w3 = ~pValueResult->Words.w3;
+#endif
+    return pValueResult;
+}
+
+
+/**
+ * Performs a boolean NOT on a 64-bit unsigned integer value, assigning the
+ * result to it.
+ *
+ * @returns pValueResult
+ * @param   pValueResult    The value and result.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64AssignBooleanNot(PRTUINT64U pValueResult)
+{
+    return RTUInt64AssignBoolean(pValueResult, RTUInt64IsZero(pValueResult));
+}
+
+
+/**
+ * Compares two 64-bit unsigned integer values.
+ *
+ * @retval  0 if equal.
+ * @retval  -1 if the first value is smaller than the second.
+ * @retval  1  if the first value is larger than the second.
+ *
+ * @param   pValue1             The first value.
+ * @param   pValue2             The second value.
+ */
+DECLINLINE(int) RTUInt64Compare(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
+{
+#if ARCH_BITS >= 32
+    if (pValue1->s.Hi != pValue2->s.Hi)
+        return pValue1->s.Hi > pValue2->s.Hi ? 1 : -1;
+    if (pValue1->s.Lo != pValue2->s.Lo)
+        return pValue1->s.Lo > pValue2->s.Lo ? 1 : -1;
+    return 0;
+#else
+    if (pValue1->Words.w3 != pValue2->Words.w3)
+        return pValue1->Words.w3 > pValue2->Words.w3 ? 1 : -1;
+    if (pValue1->Words.w2 != pValue2->Words.w2)
+        return pValue1->Words.w2 > pValue2->Words.w2 ? 1 : -1;
+    if (pValue1->Words.w1 != pValue2->Words.w1)
+        return pValue1->Words.w1 > pValue2->Words.w1 ? 1 : -1;
+    if (pValue1->Words.w0 != pValue2->Words.w0)
+        return pValue1->Words.w0 > pValue2->Words.w0 ? 1 : -1;
+    return 0;
+#endif
+}
+
+
+/**
+ * Tests if a 64-bit unsigned integer value is smaller than another.
+ *
+ * @returns true if the first value is smaller, false if not.
+ * @param   pValue1             The first value.
+ * @param   pValue2             The second value.
+ */
+DECLINLINE(bool) RTUInt64IsSmaller(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
+{
+#if ARCH_BITS >= 32
+    return pValue1->s.Hi < pValue2->s.Hi
+        || (   pValue1->s.Hi == pValue2->s.Hi
+            && pValue1->s.Lo  < pValue2->s.Lo);
+#else
+    return pValue1->Words.w3 < pValue2->Words.w3
+        || (   pValue1->Words.w3 == pValue2->Words.w3
+            && (   pValue1->Words.w2  < pValue2->Words.w2
+                || (   pValue1->Words.w2 == pValue2->Words.w2
+                    && (   pValue1->Words.w1  < pValue2->Words.w1
+                        || (   pValue1->Words.w1 == pValue2->Words.w1
+                            && pValue1->Words.w0  < pValue2->Words.w0)))));
+#endif
+}
+
+
+/**
+ * Tests if a 32-bit unsigned integer value is larger than another.
+ *
+ * @returns true if the first value is larger, false if not.
+ * @param   pValue1             The first value.
+ * @param   pValue2             The second value.
+ */
+DECLINLINE(bool) RTUInt64IsLarger(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
+{
+#if ARCH_BITS >= 32
+    return pValue1->s.Hi > pValue2->s.Hi
+        || (   pValue1->s.Hi == pValue2->s.Hi
+            && pValue1->s.Lo  > pValue2->s.Lo);
+#else
+    return pValue1->Words.w3 > pValue2->Words.w3
+        || (   pValue1->Words.w3 == pValue2->Words.w3
+            && (   pValue1->Words.w2  > pValue2->Words.w2
+                || (   pValue1->Words.w2 == pValue2->Words.w2
+                    && (   pValue1->Words.w1  > pValue2->Words.w1
+                        || (   pValue1->Words.w1 == pValue2->Words.w1
+                            && pValue1->Words.w0  > pValue2->Words.w0)))));
+#endif
+}
+
+
+/**
+ * Tests if a 64-bit unsigned integer value is larger or equal than another.
+ *
+ * @returns true if the first value is larger or equal, false if not.
+ * @param   pValue1             The first value.
+ * @param   pValue2             The second value.
+ */
+DECLINLINE(bool) RTUInt64IsLargerOrEqual(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
+{
+#if ARCH_BITS >= 32
+    return pValue1->s.Hi > pValue2->s.Hi
+        || (   pValue1->s.Hi == pValue2->s.Hi
+            && pValue1->s.Lo >= pValue2->s.Lo);
+#else
+    return pValue1->Words.w3 > pValue2->Words.w3
+        || (   pValue1->Words.w3 == pValue2->Words.w3
+            && (   pValue1->Words.w2  > pValue2->Words.w2
+                || (   pValue1->Words.w2 == pValue2->Words.w2
+                    && (   pValue1->Words.w1  > pValue2->Words.w1
+                        || (   pValue1->Words.w1 == pValue2->Words.w1
+                            && pValue1->Words.w0 >= pValue2->Words.w0)))));
+#endif
+}
+
+
+/**
+ * Tests if two 64-bit unsigned integer values not equal.
+ *
+ * @returns true if equal, false if not equal.
+ * @param   pValue1             The first value.
+ * @param   pValue2             The second value.
+ */
+DECLINLINE(bool) RTUInt64IsEqual(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
+{
+#if ARCH_BITS >= 32
+    return pValue1->s.Hi == pValue2->s.Hi
+        && pValue1->s.Lo == pValue2->s.Lo;
+#else
+    return pValue1->Words.w0 == pValue2->Words.w0
+        && pValue1->Words.w1 == pValue2->Words.w1
+        && pValue1->Words.w2 == pValue2->Words.w2
+        && pValue1->Words.w3 == pValue2->Words.w3;
+#endif
+}
+
+
+/**
+ * Tests if two 64-bit unsigned integer values are not equal.
+ *
+ * @returns true if not equal, false if equal.
+ * @param   pValue1             The first value.
+ * @param   pValue2             The second value.
+ */
+DECLINLINE(bool) RTUInt64IsNotEqual(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
+{
+    return !RTUInt64IsEqual(pValue1, pValue2);
+}
+
+
+/**
+ * Sets a bit in a 64-bit unsigned integer type.
+ *
+ * @returns pValueResult.
+ * @param   pValueResult    The input and output value.
+ * @param   iBit            The bit to set.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64BitSet(PRTUINT64U pValueResult, unsigned iBit)
+{
+    if (iBit < 32)
+    {
+#if ARCH_BITS >= 32
+        pValueResult->s.Lo |= RT_BIT_32(iBit);
+#else
+        if (iBit < 16)
+            pValueResult->Words.w0 |= UINT16_C(1) << iBit;
+        else
+            pValueResult->Words.w1 |= UINT16_C(1) << (iBit - 32);
+#endif
+    }
+    else if (iBit < 64)
+    {
+#if ARCH_BITS >= 32
+        pValueResult->s.Hi |= RT_BIT_32(iBit - 32);
+#else
+        if (iBit < 48)
+            pValueResult->Words.w2 |= UINT16_C(1) << (iBit - 64);
+        else
+            pValueResult->Words.w3 |= UINT16_C(1) << (iBit - 96);
+#endif
+    }
+    return pValueResult;
+}
+
+
+/**
+ * Sets a bit in a 64-bit unsigned integer type.
+ *
+ * @returns pValueResult.
+ * @param   pValueResult    The input and output value.
+ * @param   iBit            The bit to set.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64BitClear(PRTUINT64U pValueResult, unsigned iBit)
+{
+    if (iBit < 32)
+    {
+#if ARCH_BITS >= 32
+        pValueResult->s.Lo &= ~RT_BIT_32(iBit);
+#else
+        if (iBit < 48)
+            pValueResult->Words.w0 &= ~(UINT16_C(1) << (iBit));
+        else
+            pValueResult->Words.w1 &= ~(UINT16_C(1) << (iBit - 32));
+#endif
+    }
+    else if (iBit < 64)
+    {
+#if ARCH_BITS >= 32
+        pValueResult->s.Hi &= ~RT_BIT_32(iBit - 32);
+#else
+        if (iBit < 48)
+            pValueResult->Words.w2 &= ~(UINT16_C(1) << (iBit - 64));
+        else
+            pValueResult->Words.w3 &= ~(UINT16_C(1) << (iBit - 96));
+#endif
+    }
+    return pValueResult;
+}
+
+
+/**
+ * Tests if a bit in a 64-bit unsigned integer value is set.
+ *
+ * @returns pValueResult.
+ * @param   pValueResult    The input and output value.
+ * @param   iBit            The bit to test.
+ */
+DECLINLINE(bool) RTUInt64BitTest(PRTUINT64U pValueResult, unsigned iBit)
+{
+    bool fRc;
+    if (iBit < 32)
+    {
+#if ARCH_BITS >= 32
+        fRc = RT_BOOL(pValueResult->s.Lo & RT_BIT_32(iBit));
+#else
+        if (iBit < 16)
+            fRc = RT_BOOL(pValueResult->Words.w0 & (UINT16_C(1) << (iBit)));
+        else
+            fRc = RT_BOOL(pValueResult->Words.w1 & (UINT16_C(1) << (iBit - 16)));
+#endif
+    }
+    else if (iBit < 64)
+    {
+#if ARCH_BITS >= 32
+        fRc = RT_BOOL(pValueResult->s.Hi & RT_BIT_32(iBit - 32));
+#else
+        if (iBit < 48)
+            fRc = RT_BOOL(pValueResult->Words.w2 & (UINT16_C(1) << (iBit - 32)));
+        else
+            fRc = RT_BOOL(pValueResult->Words.w3 & (UINT16_C(1) << (iBit - 48)));
+#endif
+    }
+    else
+        fRc = false;
+    return fRc;
+}
+
+
+/**
+ * Set a range of bits a 64-bit unsigned integer value.
+ *
+ * @returns pValueResult.
+ * @param   pValueResult    The input and output value.
+ * @param   iFirstBit       The first bit to test.
+ * @param   cBits           The number of bits to set.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64BitSetRange(PRTUINT64U pValueResult, unsigned iFirstBit, unsigned cBits)
+{
+    /* bounds check & fix. */
+    if (iFirstBit < 64)
+    {
+        if (iFirstBit + cBits > 64)
+            cBits = 64 - iFirstBit;
+
+#if ARCH_BITS >= 32
+        if (iFirstBit + cBits < 32)
+            pValueResult->s.Lo |= (RT_BIT_32(cBits) - 1) << iFirstBit;
+        else if (iFirstBit + cBits < 64 && iFirstBit >= 32)
+            pValueResult->s.Hi |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 32);
+        else
+#else
+        if (iFirstBit + cBits < 16)
+            pValueResult->Words.w0 |= ((UINT16_C(1) << cBits) - 1) << iFirstBit;
+        else if (iFirstBit + cBits < 32 && iFirstBit >= 16)
+            pValueResult->Words.w1 |= ((UINT16_C(1) << cBits) - 1) << (iFirstBit - 16);
+        else if (iFirstBit + cBits < 48 && iFirstBit >= 32)
+            pValueResult->Words.w2 |= ((UINT16_C(1) << cBits) - 1) << (iFirstBit - 32);
+        else if (iFirstBit + cBits < 64 && iFirstBit >= 48)
+            pValueResult->Words.w3 |= ((UINT16_C(1) << cBits) - 1) << (iFirstBit - 48);
+        else
+#endif
+            while (cBits-- > 0)
+                RTUInt64BitSet(pValueResult, iFirstBit++);
+    }
+    return pValueResult;
+}
+
+
+/**
+ * Test if all the bits of a 64-bit unsigned integer value are set.
+ *
+ * @returns true if they are, false if they aren't.
+ * @param   pValue          The input and output value.
+ */
+DECLINLINE(bool) RTUInt64BitAreAllSet(PRTUINT64U pValue)
+{
+#if ARCH_BITS >= 32
+    return pValue->s.Hi == UINT32_MAX
+        && pValue->s.Lo == UINT32_MAX;
+#else
+    return pValue->Words.w0 == UINT16_MAX
+        && pValue->Words.w1 == UINT16_MAX
+        && pValue->Words.w2 == UINT16_MAX
+        && pValue->Words.w3 == UINT16_MAX;
+#endif
+}
+
+
+/**
+ * Test if all the bits of a 64-bit unsigned integer value are clear.
+ *
+ * @returns true if they are, false if they aren't.
+ * @param   pValue          The input and output value.
+ */
+DECLINLINE(bool) RTUInt64BitAreAllClear(PRTUINT64U pValue)
+{
+    return RTUInt64IsZero(pValue);
+}
+
+
+DECLINLINE(unsigned) RTUInt64BitCount(PCRTUINT64U pValue)
+{
+    unsigned cBits;
+    if (pValue->s.Hi != 0)
+    {
+#if ARCH_BITS >= 32
+        cBits = 32 + ASMBitLastSetU32(pValue->s.Hi);
+#else
+        if (pValue->Words.w3)
+            cBits = 48 + ASMBitLastSetU16(pValue->Words.w3);
+        else
+            cBits = 32 + ASMBitLastSetU16(pValue->Words.w2);
+#endif
+    }
+    else
+    {
+#if ARCH_BITS >= 32
+        cBits = ASMBitLastSetU32(pValue->s.Lo);
+#else
+        if (pValue->Words.w1)
+            cBits = 16 + ASMBitLastSetU16(pValue->Words.w1);
+        else
+            cBits =  0 + ASMBitLastSetU16(pValue->Words.w0);
+#endif
+    }
+    return cBits;
+}
+
+
+/**
+ * Divides a 64-bit unsigned integer value by another, returning both quotient
+ * and remainder.
+ *
+ * @returns pQuotient, NULL if pValue2 is 0.
+ * @param   pQuotient           Where to return the quotient.
+ * @param   pRemainder          Where to return the remainder.
+ * @param   pValue1             The dividend value.
+ * @param   pValue2             The divisor value.
+ */
+DECLINLINE(PRTUINT64U) RTUInt64DivRem(PRTUINT64U pQuotient, PRTUINT64U pRemainder, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
+{
+    int iDiff;
+
+    /*
+     * Sort out all the special cases first.
+     */
+    /* Divide by zero or 1? */
+    if (!pValue2->s.Hi)
+    {
+        if (!pValue2->s.Lo)
+            return NULL;
+
+        if (pValue2->s.Lo == 1)
+        {
+            RTUInt64SetZero(pRemainder);
+            *pQuotient = *pValue1;
+            return pQuotient;
+        }
+        /** @todo RTUInt64DivModByU32 */
+    }
+
+    /* Dividend is smaller? */
+    iDiff = RTUInt64Compare(pValue1, pValue2);
+    if (iDiff < 0)
+    {
+        *pRemainder = *pValue1;
+        RTUInt64SetZero(pQuotient);
+    }
+
+    /* The values are equal? */
+    else if (iDiff == 0)
+    {
+        RTUInt64SetZero(pRemainder);
+        RTUInt64AssignU8(pQuotient, 1);
+    }
+    else
+    {
+        /*
+         * Prepare.
+         */
+        unsigned  iBitAdder = RTUInt64BitCount(pValue1) - RTUInt64BitCount(pValue2);
+        RTUINT64U NormDivisor = *pValue2;
+        if (iBitAdder)
+        {
+            RTUInt64ShiftLeft(&NormDivisor, pValue2, iBitAdder);
+            if (RTUInt64IsLarger(&NormDivisor, pValue1))
+            {
+                RTUInt64AssignShiftRight(&NormDivisor, 1);
+                iBitAdder--;
+            }
+        }
+        else
+            NormDivisor = *pValue2;
+
+        RTUInt64SetZero(pQuotient);
+        *pRemainder = *pValue1;
+
+        /*
+         * Do the division.
+         */
+        if (RTUInt64IsLargerOrEqual(pRemainder, pValue2))
+        {
+            for (;;)
+            {
+                if (RTUInt64IsLargerOrEqual(pRemainder, &NormDivisor))
+                {
+                    RTUInt64AssignSub(pRemainder, &NormDivisor);
+                    RTUInt64AssignOrBit(pQuotient, iBitAdder);
+                }
+                if (RTUInt64IsSmaller(pRemainder, pValue2))
+                    break;
+                RTUInt64AssignShiftRight(&NormDivisor, 1);
+                iBitAdder--;
+            }
+        }
+    }
+    return pQuotient;
+}
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/uni.h b/ubuntu/vbox/include/iprt/uni.h
new file mode 100644 (file)
index 0000000..896c9f8
--- /dev/null
@@ -0,0 +1,478 @@
+/** @file
+ * IPRT - Unicode Code Points.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_uni_h
+#define ___iprt_uni_h
+
+/** @defgroup grp_rt_uni    RTUniCp - Unicode Code Points
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** @def RTUNI_USE_WCTYPE
+ * Define RTUNI_USE_WCTYPE to not use the IPRT unicode data but the
+ * data which the C runtime library provides. */
+#ifdef DOXYGEN_RUNNING
+# define RTUNI_USE_WCTYPE
+#endif
+
+#include <iprt/types.h>
+#ifdef RTUNI_USE_WCTYPE
+# include <wctype.h>
+#endif
+
+RT_C_DECLS_BEGIN
+
+
+#ifndef RTUNI_USE_WCTYPE
+
+/**
+ * A unicode flags range.
+ * @internal
+ */
+typedef struct RTUNIFLAGSRANGE
+{
+    /** The first code point of the range. */
+    RTUNICP         BeginCP;
+    /** The last + 1 code point of the range. */
+    RTUNICP         EndCP;
+    /** Pointer to the array of case folded code points. */
+    const uint8_t  *pafFlags;
+} RTUNIFLAGSRANGE;
+/** Pointer to a flags range.
+ * @internal */
+typedef RTUNIFLAGSRANGE *PRTUNIFLAGSRANGE;
+/** Pointer to a const flags range.
+ * @internal */
+typedef const RTUNIFLAGSRANGE *PCRTUNIFLAGSRANGE;
+
+/**
+ * A unicode case folded range.
+ * @internal
+ */
+typedef struct RTUNICASERANGE
+{
+    /** The first code point of the range. */
+    RTUNICP         BeginCP;
+    /** The last + 1 code point of the range. */
+    RTUNICP         EndCP;
+    /** Pointer to the array of case folded code points. */
+    PCRTUNICP       paFoldedCPs;
+} RTUNICASERANGE;
+/** Pointer to a case folded range.
+ * @internal */
+typedef RTUNICASERANGE *PRTUNICASERANGE;
+/** Pointer to a const case folded range.
+ * @internal */
+typedef const RTUNICASERANGE *PCRTUNICASERANGE;
+
+/** @name Unicode Code Point Flags.
+ * @internal
+ * @{ */
+#define RTUNI_UPPER         RT_BIT(0)
+#define RTUNI_LOWER         RT_BIT(1)
+#define RTUNI_ALPHA         RT_BIT(2)
+#define RTUNI_XDIGIT        RT_BIT(3)
+#define RTUNI_DDIGIT        RT_BIT(4)
+#define RTUNI_WSPACE        RT_BIT(5)
+/*#define RTUNI_BSPACE RT_BIT(6) - later */
+/** When set, the codepoint requires further checking wrt NFC and NFD
+ * normalization. I.e. set when either of QC_NFD and QC_NFC are not Y. */
+#define RTUNI_QC_NFX        RT_BIT(7)
+/** @} */
+
+
+/**
+ * Array of flags ranges.
+ * @internal
+ */
+extern RTDATADECL(const RTUNIFLAGSRANGE) g_aRTUniFlagsRanges[];
+
+/**
+ * Gets the flags for a unicode code point.
+ *
+ * @returns The flag mask. (RTUNI_*)
+ * @param   CodePoint       The unicode code point.
+ * @internal
+ */
+DECLINLINE(RTUNICP) rtUniCpFlags(RTUNICP CodePoint)
+{
+    PCRTUNIFLAGSRANGE pCur = &g_aRTUniFlagsRanges[0];
+    do
+    {
+        if (pCur->EndCP > CodePoint)
+        {
+            if (pCur->BeginCP <= CodePoint)
+                return pCur->pafFlags[CodePoint - pCur->BeginCP];
+            break;
+        }
+        pCur++;
+    } while (pCur->EndCP != RTUNICP_MAX);
+    return 0;
+}
+
+
+/**
+ * Checks if a unicode code point is upper case.
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   CodePoint       The code point.
+ */
+DECLINLINE(bool) RTUniCpIsUpper(RTUNICP CodePoint)
+{
+    return (rtUniCpFlags(CodePoint) & RTUNI_UPPER) != 0;
+}
+
+
+/**
+ * Checks if a unicode code point is lower case.
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   CodePoint       The code point.
+ */
+DECLINLINE(bool) RTUniCpIsLower(RTUNICP CodePoint)
+{
+    return (rtUniCpFlags(CodePoint) & RTUNI_LOWER) != 0;
+}
+
+
+/**
+ * Checks if a unicode code point is case foldable.
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   CodePoint       The code point.
+ */
+DECLINLINE(bool) RTUniCpIsFoldable(RTUNICP CodePoint)
+{
+    /* Right enough. */
+    return (rtUniCpFlags(CodePoint) & (RTUNI_LOWER | RTUNI_UPPER)) != 0;
+}
+
+
+/**
+ * Checks if a unicode code point is alphabetic.
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   CodePoint       The code point.
+ */
+DECLINLINE(bool) RTUniCpIsAlphabetic(RTUNICP CodePoint)
+{
+    return (rtUniCpFlags(CodePoint) & RTUNI_ALPHA) != 0;
+}
+
+
+/**
+ * Checks if a unicode code point is a decimal digit.
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   CodePoint       The code point.
+ */
+DECLINLINE(bool) RTUniCpIsDecDigit(RTUNICP CodePoint)
+{
+    return (rtUniCpFlags(CodePoint) & RTUNI_DDIGIT) != 0;
+}
+
+
+/**
+ * Checks if a unicode code point is a hexadecimal digit.
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   CodePoint       The code point.
+ */
+DECLINLINE(bool) RTUniCpIsHexDigit(RTUNICP CodePoint)
+{
+    return (rtUniCpFlags(CodePoint) & RTUNI_XDIGIT) != 0;
+}
+
+
+/**
+ * Checks if a unicode code point is white space.
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   CodePoint       The code point.
+ */
+DECLINLINE(bool) RTUniCpIsSpace(RTUNICP CodePoint)
+{
+    return (rtUniCpFlags(CodePoint) & RTUNI_WSPACE) != 0;
+}
+
+
+
+/**
+ * Array of uppercase ranges.
+ * @internal
+ */
+extern RTDATADECL(const RTUNICASERANGE) g_aRTUniUpperRanges[];
+
+/**
+ * Array of lowercase ranges.
+ * @internal
+ */
+extern RTDATADECL(const RTUNICASERANGE) g_aRTUniLowerRanges[];
+
+
+/**
+ * Folds a unicode code point using the specified range array.
+ *
+ * @returns FOlded code point.
+ * @param   CodePoint       The unicode code point to fold.
+ * @param   pCur            The case folding range to use.
+ */
+DECLINLINE(RTUNICP) rtUniCpFold(RTUNICP CodePoint, PCRTUNICASERANGE pCur)
+{
+    do
+    {
+        if (pCur->EndCP > CodePoint)
+        {
+            if (pCur->BeginCP <= CodePoint)
+                CodePoint = pCur->paFoldedCPs[CodePoint - pCur->BeginCP];
+            break;
+        }
+        pCur++;
+    } while (pCur->EndCP != RTUNICP_MAX);
+    return CodePoint;
+}
+
+
+/**
+ * Folds a unicode code point to upper case.
+ *
+ * @returns Folded code point.
+ * @param   CodePoint       The unicode code point to fold.
+ */
+DECLINLINE(RTUNICP) RTUniCpToUpper(RTUNICP CodePoint)
+{
+    return rtUniCpFold(CodePoint, &g_aRTUniUpperRanges[0]);
+}
+
+
+/**
+ * Folds a unicode code point to lower case.
+ *
+ * @returns Folded code point.
+ * @param   CodePoint       The unicode code point to fold.
+ */
+DECLINLINE(RTUNICP) RTUniCpToLower(RTUNICP CodePoint)
+{
+    return rtUniCpFold(CodePoint, &g_aRTUniLowerRanges[0]);
+}
+
+
+#else /* RTUNI_USE_WCTYPE */
+
+
+/**
+ * Checks if a unicode code point is upper case.
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   CodePoint       The code point.
+ */
+DECLINLINE(bool) RTUniCpIsUpper(RTUNICP CodePoint)
+{
+    return !!iswupper(CodePoint);
+}
+
+
+/**
+ * Checks if a unicode code point is lower case.
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   CodePoint       The code point.
+ */
+DECLINLINE(bool) RTUniCpIsLower(RTUNICP CodePoint)
+{
+    return !!iswlower(CodePoint);
+}
+
+
+/**
+ * Checks if a unicode code point is case foldable.
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   CodePoint       The code point.
+ */
+DECLINLINE(bool) RTUniCpIsFoldable(RTUNICP CodePoint)
+{
+    /* Right enough. */
+    return iswupper(CodePoint) || iswlower(CodePoint);
+}
+
+
+/**
+ * Checks if a unicode code point is alphabetic.
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   CodePoint       The code point.
+ */
+DECLINLINE(bool) RTUniCpIsAlphabetic(RTUNICP CodePoint)
+{
+    return !!iswalpha(CodePoint);
+}
+
+
+/**
+ * Checks if a unicode code point is a decimal digit.
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   CodePoint       The code point.
+ */
+DECLINLINE(bool) RTUniCpIsDecDigit(RTUNICP CodePoint)
+{
+    return !!iswdigit(CodePoint);
+}
+
+
+/**
+ * Checks if a unicode code point is a hexadecimal digit.
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   CodePoint       The code point.
+ */
+DECLINLINE(bool) RTUniCpIsHexDigit(RTUNICP CodePoint)
+{
+    return !!iswxdigit(CodePoint);
+}
+
+
+/**
+ * Checks if a unicode code point is white space.
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   CodePoint       The code point.
+ */
+DECLINLINE(bool) RTUniCpIsSpace(RTUNICP CodePoint)
+{
+    return !!iswspace(CodePoint);
+}
+
+
+/**
+ * Folds a unicode code point to upper case.
+ *
+ * @returns Folded code point.
+ * @param   CodePoint       The unicode code point to fold.
+ */
+DECLINLINE(RTUNICP) RTUniCpToUpper(RTUNICP CodePoint)
+{
+    return towupper(CodePoint);
+}
+
+
+/**
+ * Folds a unicode code point to lower case.
+ *
+ * @returns Folded code point.
+ * @param   CodePoint       The unicode code point to fold.
+ */
+DECLINLINE(RTUNICP) RTUniCpToLower(RTUNICP CodePoint)
+{
+    return towlower(CodePoint);
+}
+
+
+#endif /* RTUNI_USE_WCTYPE */
+
+
+/**
+ * Frees a unicode string.
+ *
+ * @param   pusz        The string to free.
+ */
+RTDECL(void) RTUniFree(PRTUNICP pusz);
+
+
+/**
+ * Checks if a code point valid.
+ *
+ * Any code point (defined or not) within the 17 unicode planes (0 thru 16),
+ * except surrogates will be considered valid code points by this function.
+ *
+ * @returns true if in range, false if not.
+ * @param   CodePoint       The unicode code point to validate.
+ */
+DECLINLINE(bool) RTUniCpIsValid(RTUNICP CodePoint)
+{
+    return CodePoint <= 0x00d7ff
+        || (   CodePoint <= 0x10ffff
+            && CodePoint >= 0x00e000);
+}
+
+
+/**
+ * Checks if the given code point is in the BMP range.
+ *
+ * Surrogates are not considered in the BMP range by this function.
+ *
+ * @returns true if in BMP, false if not.
+ * @param   CodePoint       The unicode code point to consider.
+ */
+DECLINLINE(bool) RTUniCpIsBMP(RTUNICP CodePoint)
+{
+    return CodePoint <= 0xd7ff
+        || (   CodePoint <= 0xffff
+            && CodePoint >= 0xe000);
+}
+
+
+/**
+ * Folds a unicode code point to lower case.
+ *
+ * @returns Folded code point.
+ * @param   CodePoint       The unicode code point to fold.
+ */
+DECLINLINE(size_t) RTUniCpCalcUtf8Len(RTUNICP CodePoint)
+{
+    if (CodePoint < 0x80)
+        return 1;
+    return 2
+        + (CodePoint >= 0x00000800)
+        + (CodePoint >= 0x00010000)
+        + (CodePoint >= 0x00200000)
+        + (CodePoint >= 0x04000000)
+        + (CodePoint >= 0x80000000) /* illegal */;
+}
+
+
+
+RT_C_DECLS_END
+/** @} */
+
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/utf16.h b/ubuntu/vbox/include/iprt/utf16.h
new file mode 100644 (file)
index 0000000..f17ae55
--- /dev/null
@@ -0,0 +1,1004 @@
+/** @file
+ * IPRT - String Manipulation, UTF-16 encoding.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_utf16_h
+#define ___iprt_utf16_h
+
+#include <iprt/string.h>
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup rt_str_utf16      UTF-16 String Manipulation
+ * @ingroup grp_rt_str
+ * @{
+ */
+
+/**
+ * Allocates memory for UTF-16 string storage (default tag).
+ *
+ * You should normally not use this function, except if there is some very
+ * custom string handling you need doing that isn't covered by any of the other
+ * APIs.
+ *
+ * @returns Pointer to the allocated UTF-16 string.  The first wide char is
+ *          always set to the string terminator char, the contents of the
+ *          remainder of the memory is undefined.  The string must be freed by
+ *          calling RTUtf16Free.
+ *
+ *          NULL is returned if the allocation failed.  Please translate this to
+ *          VERR_NO_UTF16_MEMORY and not VERR_NO_MEMORY.  Also consider
+ *          RTUtf16AllocEx if an IPRT status code is required.
+ *
+ * @param   cb                  How many bytes to allocate, will be rounded up
+ *                              to a multiple of two. If this is zero, we will
+ *                              allocate a terminator wide char anyway.
+ */
+#define RTUtf16Alloc(cb)                    RTUtf16AllocTag((cb), RTSTR_TAG)
+
+/**
+ * Allocates memory for UTF-16 string storage (custom tag).
+ *
+ * You should normally not use this function, except if there is some very
+ * custom string handling you need doing that isn't covered by any of the other
+ * APIs.
+ *
+ * @returns Pointer to the allocated UTF-16 string.  The first wide char is
+ *          always set to the string terminator char, the contents of the
+ *          remainder of the memory is undefined.  The string must be freed by
+ *          calling RTUtf16Free.
+ *
+ *          NULL is returned if the allocation failed.  Please translate this to
+ *          VERR_NO_UTF16_MEMORY and not VERR_NO_MEMORY.  Also consider
+ *          RTUtf16AllocExTag if an IPRT status code is required.
+ *
+ * @param   cb                  How many bytes to allocate, will be rounded up
+ *                              to a multiple of two. If this is zero, we will
+ *                              allocate a terminator wide char anyway.
+ * @param   pszTag              Allocation tag used for statistics and such.
+ */
+RTDECL(PRTUTF16) RTUtf16AllocTag(size_t cb, const char *pszTag);
+
+/**
+ * Reallocates the specified UTF-16 string (default tag).
+ *
+ * You should normally not use this function, except if there is some very
+ * custom string handling you need doing that isn't covered by any of the other
+ * APIs.
+ *
+ * @returns VINF_SUCCESS.
+ * @retval  VERR_NO_UTF16_MEMORY if we failed to reallocate the string, @a
+ *          *ppwsz remains unchanged.
+ *
+ * @param   ppwsz               Pointer to the string variable containing the
+ *                              input and output string.
+ *
+ *                              When not freeing the string, the result will
+ *                              always have the last RTUTF16 set to the
+ *                              terminator character so that when used for
+ *                              string truncation the result will be a valid
+ *                              C-style string (your job to keep it a valid
+ *                              UTF-16 string).
+ *
+ *                              When the input string is NULL and we're supposed
+ *                              to reallocate, the returned string will also
+ *                              have the first RTUTF16 set to the terminator
+ *                              char so it will be a valid C-style string.
+ *
+ * @param   cbNew               When @a cbNew is zero, we'll behave like
+ *                              RTUtf16Free and @a *ppwsz will be set to NULL.
+ *
+ *                              When not zero, this will be rounded up to a
+ *                              multiple of two, and used as the new size of the
+ *                              memory backing the string, i.e. it includes the
+ *                              terminator (RTUTF16) char.
+ */
+#define RTUtf16Realloc(ppwsz, cbNew)    RTUtf16ReallocTag((ppwsz), (cbNew), RTSTR_TAG)
+
+/**
+ * Reallocates the specified UTF-16 string (custom tag).
+ *
+ * You should normally not use this function, except if there is some very
+ * custom string handling you need doing that isn't covered by any of the other
+ * APIs.
+ *
+ * @returns VINF_SUCCESS.
+ * @retval  VERR_NO_UTF16_MEMORY if we failed to reallocate the string, @a
+ *          *ppwsz remains unchanged.
+ *
+ * @param   ppwsz               Pointer to the string variable containing the
+ *                              input and output string.
+ *
+ *                              When not freeing the string, the result will
+ *                              always have the last RTUTF16 set to the
+ *                              terminator character so that when used for
+ *                              string truncation the result will be a valid
+ *                              C-style string (your job to keep it a valid
+ *                              UTF-16 string).
+ *
+ *                              When the input string is NULL and we're supposed
+ *                              to reallocate, the returned string will also
+ *                              have the first RTUTF16 set to the terminator
+ *                              char so it will be a valid C-style string.
+ *
+ * @param   cbNew               When @a cbNew is zero, we'll behave like
+ *                              RTUtf16Free and @a *ppwsz will be set to NULL.
+ *
+ *                              When not zero, this will be rounded up to a
+ *                              multiple of two, and used as the new size of the
+ *                              memory backing the string, i.e. it includes the
+ *                              terminator (RTUTF16) char.
+ * @param   pszTag              Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTUtf16ReallocTag(PRTUTF16 *ppwsz, size_t cbNew, const char *pszTag);
+
+/**
+ * Free a UTF-16 string allocated by RTStrToUtf16(), RTStrToUtf16Ex(),
+ * RTLatin1ToUtf16(), RTLatin1ToUtf16Ex(), RTUtf16Dup() or RTUtf16DupEx().
+ *
+ * @returns iprt status code.
+ * @param   pwszString      The UTF-16 string to free. NULL is accepted.
+ */
+RTDECL(void)  RTUtf16Free(PRTUTF16 pwszString);
+
+/**
+ * Allocates a new copy of the specified UTF-16 string (default tag).
+ *
+ * @returns Pointer to the allocated string copy. Use RTUtf16Free() to free it.
+ * @returns NULL when out of memory.
+ * @param   pwszString      UTF-16 string to duplicate.
+ * @remark  This function will not make any attempt to validate the encoding.
+ */
+#define RTUtf16Dup(pwszString)          RTUtf16DupTag((pwszString), RTSTR_TAG)
+
+/**
+ * Allocates a new copy of the specified UTF-16 string (custom tag).
+ *
+ * @returns Pointer to the allocated string copy. Use RTUtf16Free() to free it.
+ * @returns NULL when out of memory.
+ * @param   pwszString      UTF-16 string to duplicate.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ * @remark  This function will not make any attempt to validate the encoding.
+ */
+RTDECL(PRTUTF16) RTUtf16DupTag(PCRTUTF16 pwszString, const char *pszTag);
+
+/**
+ * Allocates a new copy of the specified UTF-16 string (default tag).
+ *
+ * @returns iprt status code.
+ * @param   ppwszString     Receives pointer of the allocated UTF-16 string.
+ *                          The returned pointer must be freed using RTUtf16Free().
+ * @param   pwszString      UTF-16 string to duplicate.
+ * @param   cwcExtra        Number of extra RTUTF16 items to allocate.
+ * @remark  This function will not make any attempt to validate the encoding.
+ */
+#define RTUtf16DupEx(ppwszString, pwszString, cwcExtra) \
+    RTUtf16DupExTag((ppwszString), (pwszString), (cwcExtra), RTSTR_TAG)
+
+/**
+ * Allocates a new copy of the specified UTF-16 string (custom tag).
+ *
+ * @returns iprt status code.
+ * @param   ppwszString     Receives pointer of the allocated UTF-16 string.
+ *                          The returned pointer must be freed using RTUtf16Free().
+ * @param   pwszString      UTF-16 string to duplicate.
+ * @param   cwcExtra        Number of extra RTUTF16 items to allocate.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ * @remark  This function will not make any attempt to validate the encoding.
+ */
+RTDECL(int) RTUtf16DupExTag(PRTUTF16 *ppwszString, PCRTUTF16 pwszString, size_t cwcExtra, const char *pszTag);
+
+/**
+ * Returns the length of a UTF-16 string in UTF-16 characters
+ * without trailing '\\0'.
+ *
+ * Surrogate pairs counts as two UTF-16 characters here. Use RTUtf16CpCnt()
+ * to get the exact number of code points in the string.
+ *
+ * @returns The number of RTUTF16 items in the string.
+ * @param   pwszString  Pointer the UTF-16 string.
+ * @remark  This function will not make any attempt to validate the encoding.
+ */
+RTDECL(size_t) RTUtf16Len(PCRTUTF16 pwszString);
+
+/**
+ * Find the length of a zero-terminated byte string, given a max string length.
+ *
+ * @returns The string length or cbMax. The returned length does not include
+ *          the zero terminator if it was found.
+ *
+ * @param   pwszString  The string.
+ * @param   cwcMax      The max string length in RTUTF16s.
+ * @sa      RTUtf16NLenEx, RTStrNLen.
+ */
+RTDECL(size_t) RTUtf16NLen(PCRTUTF16 pwszString, size_t cwcMax);
+
+/**
+ * Find the length of a zero-terminated byte string, given
+ * a max string length.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS if the string has a length less than cchMax.
+ * @retval  VERR_BUFFER_OVERFLOW if the end of the string wasn't found
+ *          before cwcMax was reached.
+ *
+ * @param   pwszString  The string.
+ * @param   cwcMax      The max string length in RTUTF16s.
+ * @param   pcwc        Where to store the string length excluding the
+ *                      terminator.  This is set to cwcMax if the terminator
+ *                      isn't found.
+ * @sa      RTUtf16NLen, RTStrNLenEx.
+ */
+RTDECL(int) RTUtf16NLenEx(PCRTUTF16 pwszString, size_t cwcMax, size_t *pcwc);
+
+/**
+ * Find the zero terminator in a string with a limited length.
+ *
+ * @returns Pointer to the zero terminator.
+ * @returns NULL if the zero terminator was not found.
+ *
+ * @param   pwszString  The string.
+ * @param   cwcMax      The max string length.  RTSTR_MAX is fine.
+ */
+RTDECL(PCRTUTF16) RTUtf16End(PCRTUTF16 pwszString, size_t cwcMax);
+
+/**
+ * Strips blankspaces from both ends of the string.
+ *
+ * @returns Pointer to first non-blank char in the string.
+ * @param   pwsz    The string to strip.
+ */
+RTDECL(PRTUTF16) RTUtf16Strip(PRTUTF16 pwsz);
+
+/**
+ * Strips blankspaces from the start of the string.
+ *
+ * @returns Pointer to first non-blank char in the string.
+ * @param   pwsz    The string to strip.
+ */
+RTDECL(PRTUTF16) RTUtf16StripL(PCRTUTF16 pwsz);
+
+/**
+ * Strips blankspaces from the end of the string.
+ *
+ * @returns pwsz.
+ * @param   pwsz    The string to strip.
+ */
+RTDECL(PRTUTF16) RTUtf16StripR(PRTUTF16 pwsz);
+
+/**
+ * String copy with overflow handling.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the destination buffer is too small.  The
+ *          buffer will contain as much of the string as it can hold, fully
+ *          terminated.
+ *
+ * @param   pwszDst             The destination buffer.
+ * @param   cwcDst              The size of the destination buffer in RTUTF16s.
+ * @param   pwszSrc             The source string.  NULL is not OK.
+ */
+RTDECL(int) RTUtf16Copy(PRTUTF16 pwszDst, size_t cwcDst, PCRTUTF16 pwszSrc);
+
+/**
+ * String copy with overflow handling, ASCII source.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the destination buffer is too small.  The
+ *          buffer will contain as much of the string as it can hold, fully
+ *          terminated.
+ *
+ * @param   pwszDst             The destination buffer.
+ * @param   cwcDst              The size of the destination buffer in RTUTF16s.
+ * @param   pszSrc              The source string, pure ASCII.  NULL is not OK.
+ */
+RTDECL(int) RTUtf16CopyAscii(PRTUTF16 pwszDst, size_t cwcDst, const char *pszSrc);
+
+/**
+ * String copy with overflow handling.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the destination buffer is too small.  The
+ *          buffer will contain as much of the string as it can hold, fully
+ *          terminated.
+ *
+ * @param   pwszDst             The destination buffer.
+ * @param   cwcDst              The size of the destination buffer in RTUTF16s.
+ * @param   pwszSrc             The source string.  NULL is not OK.
+ * @param   cwcSrcMax           The maximum number of chars (not code points) to
+ *                              copy from the source string, not counting the
+ *                              terminator as usual.
+ */
+RTDECL(int) RTUtf16CopyEx(PRTUTF16 pwszDst, size_t cwcDst, PCRTUTF16 pwszSrc, size_t cwcSrcMax);
+
+/**
+ * String concatenation with overflow handling.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the destination buffer is too small.  The
+ *          buffer will contain as much of the string as it can hold, fully
+ *          terminated.
+ *
+ * @param   pwszDst             The destination buffer.
+ * @param   cwcDst              The size of the destination buffer in RTUTF16s.
+ * @param   pwszSrc             The source string.  NULL is not OK.
+ */
+RTDECL(int) RTUtf16Cat(PRTUTF16 pwszDst, size_t cwcDst, PCRTUTF16 pwszSrc);
+
+/**
+ * String concatenation with overflow handling, ASCII source.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the destination buffer is too small.  The
+ *          buffer will contain as much of the string as it can hold, fully
+ *          terminated.
+ *
+ * @param   pwszDst             The destination buffer.
+ * @param   cwcDst              The size of the destination buffer in RTUTF16s.
+ * @param   pszSrc              The source string, pure ASCII.  NULL is not OK.
+ */
+RTDECL(int) RTUtf16CatAscii(PRTUTF16 pwszDst, size_t cwcDst, const char *pszSrc);
+
+/**
+ * String concatenation with overflow handling.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_BUFFER_OVERFLOW if the destination buffer is too small.  The
+ *          buffer will contain as much of the string as it can hold, fully
+ *          terminated.
+ *
+ * @param   pwszDst             The destination buffer.
+ * @param   cwcDst              The size of the destination buffer in RTUTF16s.
+ * @param   pwszSrc             The source string.  NULL is not OK.
+ * @param   cwcSrcMax           The maximum number of UTF-16 chars (not code
+ *                              points) to copy from the source string, not
+ *                              counting the terminator as usual.
+ */
+RTDECL(int) RTUtf16CatEx(PRTUTF16 pwszDst, size_t cwcDst, PCRTUTF16 pwszSrc, size_t cwcSrcMax);
+
+/**
+ * Performs a case sensitive string compare between two UTF-16 strings.
+ *
+ * @returns < 0 if the first string less than the second string.s
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ * @param   pwsz1       First UTF-16 string. Null is allowed.
+ * @param   pwsz2       Second UTF-16 string. Null is allowed.
+ * @remark  This function will not make any attempt to validate the encoding.
+ */
+RTDECL(int) RTUtf16Cmp(PCRTUTF16 pwsz1, PCRTUTF16 pwsz2);
+
+/**
+ * Performs a case sensitive string compare between an UTF-16 string and a pure
+ * ASCII string.
+ *
+ * @returns < 0 if the first string less than the second string.s
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ * @param   pwsz1       First UTF-16 string. Null is allowed.
+ * @param   psz2        Second string, pure ASCII. Null is allowed.
+ * @remark  This function will not make any attempt to validate the encoding.
+ */
+RTDECL(int) RTUtf16CmpAscii(PCRTUTF16 pwsz1, const char *psz2);
+
+/**
+ * Performs a case sensitive string compare between an UTF-16 string and a UTF-8
+ * string.
+ *
+ * @returns < 0 if the first string less than the second string.s
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ * @param   pwsz1       First UTF-16 string. Null is allowed.
+ * @param   psz2        Second string, UTF-8. Null is allowed.
+ * @remarks NULL and empty strings are treated equally.
+ */
+RTDECL(int) RTUtf16CmpUtf8(PCRTUTF16 pwsz1, const char *psz2);
+
+/**
+ * Performs a case insensitive string compare between two UTF-16 strings.
+ *
+ * This is a simplified compare, as only the simplified lower/upper case folding
+ * specified by the unicode specs are used. It does not consider character pairs
+ * as they are used in some languages, just simple upper & lower case compares.
+ *
+ * @returns < 0 if the first string less than the second string.
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ * @param   pwsz1       First UTF-16 string. Null is allowed.
+ * @param   pwsz2       Second UTF-16 string. Null is allowed.
+ */
+RTDECL(int) RTUtf16ICmp(PCRTUTF16 pwsz1, PCRTUTF16 pwsz2);
+
+/**
+ * Performs a case insensitive string compare between an UTF-16 string and a
+ * UTF-8 string.
+ *
+ * @returns < 0 if the first string less than the second string.s
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ * @param   pwsz1       First UTF-16 string. Null is allowed.
+ * @param   psz2        Second string, UTF-8. Null is allowed.
+ * @remarks NULL and empty strings are treated equally.
+ */
+RTDECL(int) RTUtf16ICmpUtf8(PCRTUTF16 pwsz1, const char *psz2);
+
+/**
+ * Performs a case insensitive string compare between an UTF-16 string and a
+ * pure ASCII string.
+ *
+ * Since this compare only takes cares about the first 128 codepoints in
+ * unicode, no tables are needed and there aren't any real complications.
+ *
+ * @returns < 0 if the first string less than the second string.
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ * @param   pwsz1       First UTF-16 string. Null is allowed.
+ * @param   psz2        Second string, pure ASCII. Null is allowed.
+ */
+RTDECL(int) RTUtf16ICmpAscii(PCRTUTF16 pwsz1, const char *psz2);
+
+/**
+ * Performs a case insensitive string compare between two UTF-16 strings
+ * using the current locale of the process (if applicable).
+ *
+ * This differs from RTUtf16ICmp() in that it will try, if a locale with the
+ * required data is available, to do a correct case-insensitive compare. It
+ * follows that it is more complex and thereby likely to be more expensive.
+ *
+ * @returns < 0 if the first string less than the second string.
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ * @param   pwsz1       First UTF-16 string. Null is allowed.
+ * @param   pwsz2       Second UTF-16 string. Null is allowed.
+ */
+RTDECL(int) RTUtf16LocaleICmp(PCRTUTF16 pwsz1, PCRTUTF16 pwsz2);
+
+/**
+ * Performs a case insensitive string compare between a UTF-16 string and a pure
+ * ASCII string, stopping after N characters.
+ *
+ * Since this compare only takes cares about the first 128 codepoints in
+ * unicode, no tables are needed and there aren't any real complications.
+ *
+ * @returns < 0 if the first string less than the second string.
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ * @param   pwsz1       The UTF-16 first string. Null is allowed.
+ * @param   psz2        The pure ASCII second string. Null is allowed.
+ * @param   cwcMax      Maximum number of UTF-16 characters to compare.
+ */
+RTDECL(int) RTUtf16NICmpAscii(PCRTUTF16 pwsz1, const char *psz2, size_t cwcMax);
+
+
+/**
+ * Folds a UTF-16 string to lowercase.
+ *
+ * This is a very simple folding; is uses the simple lowercase
+ * code point, it is not related to any locale just the most common
+ * lowercase codepoint setup by the unicode specs, and it will not
+ * create new surrogate pairs or remove existing ones.
+ *
+ * @returns Pointer to the passed in string.
+ * @param   pwsz        The string to fold.
+ */
+RTDECL(PRTUTF16) RTUtf16ToLower(PRTUTF16 pwsz);
+
+/**
+ * Folds a UTF-16 string to uppercase.
+ *
+ * This is a very simple folding; is uses the simple uppercase
+ * code point, it is not related to any locale just the most common
+ * uppercase codepoint setup by the unicode specs, and it will not
+ * create new surrogate pairs or remove existing ones.
+ *
+ * @returns Pointer to the passed in string.
+ * @param   pwsz        The string to fold.
+ */
+RTDECL(PRTUTF16) RTUtf16ToUpper(PRTUTF16 pwsz);
+
+/**
+ * Validates the UTF-16 encoding of the string.
+ *
+ * @returns iprt status code.
+ * @param   pwsz        The string.
+ */
+RTDECL(int) RTUtf16ValidateEncoding(PCRTUTF16 pwsz);
+
+/**
+ * Validates the UTF-16 encoding of the string.
+ *
+ * @returns iprt status code.
+ * @param   pwsz        The string.
+ * @param   cwc         The max string length (/ size) in UTF-16 units. Use
+ *                      RTSTR_MAX to process the entire string.
+ * @param   fFlags      Combination of RTSTR_VALIDATE_ENCODING_XXX flags.
+ */
+RTDECL(int) RTUtf16ValidateEncodingEx(PCRTUTF16 pwsz, size_t cwc, uint32_t fFlags);
+
+/**
+ * Checks if the UTF-16 encoding is valid.
+ *
+ * @returns true / false.
+ * @param   pwsz        The string.
+ */
+RTDECL(bool) RTUtf16IsValidEncoding(PCRTUTF16 pwsz);
+
+/**
+ * Sanitise a (valid) UTF-16 string by replacing all characters outside a white
+ * list in-place by an ASCII replacement character.
+ *
+ * Surrogate paris will be replaced by two chars.
+ *
+ * @returns The number of code points replaced.  In the case of an incorrectly
+ *          encoded string -1 will be returned, and the string is not completely
+ *          processed.  In the case of puszValidPairs having an odd number of
+ *          code points, -1 will be also return but without any modification to
+ *          the string.
+ * @param   pwsz           The string to sanitise.
+ * @param   puszValidPairs A zero-terminated array of pairs of Unicode points.
+ *                         Each pair is the start and end point of a range,
+ *                         and the union of these ranges forms the white list.
+ * @param   chReplacement  The ASCII replacement character.
+ * @sa      RTStrPurgeComplementSet
+ */
+RTDECL(ssize_t) RTUtf16PurgeComplementSet(PRTUTF16 pwsz, PCRTUNICP puszValidPairs, char chReplacement);
+
+/**
+ * Translate a UTF-16 string into a UTF-8 allocating the result buffer (default
+ * tag).
+ *
+ * @returns iprt status code.
+ * @param   pwszString      UTF-16 string to convert.
+ * @param   ppszString      Receives pointer of allocated UTF-8 string on
+ *                          success, and is always set to NULL on failure.
+ *                          The returned pointer must be freed using RTStrFree().
+ */
+#define RTUtf16ToUtf8(pwszString, ppszString)       RTUtf16ToUtf8Tag((pwszString), (ppszString), RTSTR_TAG)
+
+/**
+ * Translate a UTF-16 string into a UTF-8 allocating the result buffer.
+ *
+ * @returns iprt status code.
+ * @param   pwszString      UTF-16 string to convert.
+ * @param   ppszString      Receives pointer of allocated UTF-8 string on
+ *                          success, and is always set to NULL on failure.
+ *                          The returned pointer must be freed using RTStrFree().
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTDECL(int)  RTUtf16ToUtf8Tag(PCRTUTF16 pwszString, char **ppszString, const char *pszTag);
+
+/**
+ * Translates UTF-16 to UTF-8 using buffer provided by the caller or a fittingly
+ * sized buffer allocated by the function (default tag).
+ *
+ * @returns iprt status code.
+ * @param   pwszString      The UTF-16 string to convert.
+ * @param   cwcString       The number of RTUTF16 items to translate from pwszString.
+ *                          The translation will stop when reaching cwcString or the terminator ('\\0').
+ *                          Use RTSTR_MAX to translate the entire string.
+ * @param   ppsz            If cch is non-zero, this must either be pointing to a pointer to
+ *                          a buffer of the specified size, or pointer to a NULL pointer.
+ *                          If *ppsz is NULL or cch is zero a buffer of at least cch chars
+ *                          will be allocated to hold the translated string.
+ *                          If a buffer was requested it must be freed using RTStrFree().
+ * @param   cch             The buffer size in chars (the type). This includes the terminator.
+ * @param   pcch            Where to store the length of the translated string,
+ *                          excluding the terminator. (Optional)
+ *
+ *                          This may be set under some error conditions,
+ *                          however, only for VERR_BUFFER_OVERFLOW and
+ *                          VERR_NO_STR_MEMORY will it contain a valid string
+ *                          length that can be used to resize the buffer.
+ */
+#define RTUtf16ToUtf8Ex(pwszString, cwcString, ppsz, cch, pcch) \
+    RTUtf16ToUtf8ExTag((pwszString), (cwcString), (ppsz), (cch), (pcch), RTSTR_TAG)
+
+/**
+ * Translates UTF-16 to UTF-8 using buffer provided by the caller or a fittingly
+ * sized buffer allocated by the function (custom tag).
+ *
+ * @returns iprt status code.
+ * @param   pwszString      The UTF-16 string to convert.
+ * @param   cwcString       The number of RTUTF16 items to translate from pwszString.
+ *                          The translation will stop when reaching cwcString or the terminator ('\\0').
+ *                          Use RTSTR_MAX to translate the entire string.
+ * @param   ppsz            If cch is non-zero, this must either be pointing to a pointer to
+ *                          a buffer of the specified size, or pointer to a NULL pointer.
+ *                          If *ppsz is NULL or cch is zero a buffer of at least cch chars
+ *                          will be allocated to hold the translated string.
+ *                          If a buffer was requested it must be freed using RTStrFree().
+ * @param   cch             The buffer size in chars (the type). This includes the terminator.
+ * @param   pcch            Where to store the length of the translated string,
+ *                          excluding the terminator. (Optional)
+ *
+ *                          This may be set under some error conditions,
+ *                          however, only for VERR_BUFFER_OVERFLOW and
+ *                          VERR_NO_STR_MEMORY will it contain a valid string
+ *                          length that can be used to resize the buffer.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTDECL(int)  RTUtf16ToUtf8ExTag(PCRTUTF16 pwszString, size_t cwcString, char **ppsz, size_t cch, size_t *pcch, const char *pszTag);
+
+/**
+ * Calculates the length of the UTF-16 string in UTF-8 chars (bytes).
+ *
+ * This function will validate the string, and incorrectly encoded UTF-16
+ * strings will be rejected. The primary purpose of this function is to
+ * help allocate buffers for RTUtf16ToUtf8() of the correct size. For most
+ * other purposes RTUtf16ToUtf8Ex() should be used.
+ *
+ * @returns Number of char (bytes).
+ * @returns 0 if the string was incorrectly encoded.
+ * @param   pwsz        The UTF-16 string.
+ */
+RTDECL(size_t) RTUtf16CalcUtf8Len(PCRTUTF16 pwsz);
+
+/**
+ * Calculates the length of the UTF-16 string in UTF-8 chars (bytes).
+ *
+ * This function will validate the string, and incorrectly encoded UTF-16
+ * strings will be rejected.
+ *
+ * @returns iprt status code.
+ * @param   pwsz        The string.
+ * @param   cwc         The max string length. Use RTSTR_MAX to process the entire string.
+ * @param   pcch        Where to store the string length (in bytes). Optional.
+ *                      This is undefined on failure.
+ */
+RTDECL(int) RTUtf16CalcUtf8LenEx(PCRTUTF16 pwsz, size_t cwc, size_t *pcch);
+
+/**
+ * Translate a UTF-16 string into a Latin-1 (ISO-8859-1) allocating the result
+ * buffer (default tag).
+ *
+ * @returns iprt status code.
+ * @param   pwszString      UTF-16 string to convert.
+ * @param   ppszString      Receives pointer of allocated Latin1 string on
+ *                          success, and is always set to NULL on failure.
+ *                          The returned pointer must be freed using RTStrFree().
+ */
+#define RTUtf16ToLatin1(pwszString, ppszString)     RTUtf16ToLatin1Tag((pwszString), (ppszString), RTSTR_TAG)
+
+/**
+ * Translate a UTF-16 string into a Latin-1 (ISO-8859-1) allocating the result
+ * buffer (custom tag).
+ *
+ * @returns iprt status code.
+ * @param   pwszString      UTF-16 string to convert.
+ * @param   ppszString      Receives pointer of allocated Latin1 string on
+ *                          success, and is always set to NULL on failure.
+ *                          The returned pointer must be freed using RTStrFree().
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTDECL(int)  RTUtf16ToLatin1Tag(PCRTUTF16 pwszString, char **ppszString, const char *pszTag);
+
+/**
+ * Translates UTF-16 to Latin-1 (ISO-8859-1) using buffer provided by the caller
+ * or a fittingly sized buffer allocated by the function (default tag).
+ *
+ * @returns iprt status code.
+ * @param   pwszString      The UTF-16 string to convert.
+ * @param   cwcString       The number of RTUTF16 items to translate from
+ *                          pwszString. The translation will stop when reaching
+ *                          cwcString or the terminator ('\\0'). Use RTSTR_MAX
+ *                          to translate the entire string.
+ * @param   ppsz            Pointer to the pointer to the Latin-1 string. The
+ *                          buffer can optionally be preallocated by the caller.
+ *
+ *                          If cch is zero, *ppsz is undefined.
+ *
+ *                          If cch is non-zero and *ppsz is not NULL, then this
+ *                          will be used as the output buffer.
+ *                          VERR_BUFFER_OVERFLOW will be returned if this is
+ *                          insufficient.
+ *
+ *                          If cch is zero or *ppsz is NULL, then a buffer of
+ *                          sufficient size is allocated. cch can be used to
+ *                          specify a minimum size of this buffer. Use
+ *                          RTUtf16Free() to free the result.
+ *
+ * @param   cch             The buffer size in chars (the type). This includes
+ *                          the terminator.
+ * @param   pcch            Where to store the length of the translated string,
+ *                          excluding the terminator. (Optional)
+ *
+ *                          This may be set under some error conditions,
+ *                          however, only for VERR_BUFFER_OVERFLOW and
+ *                          VERR_NO_STR_MEMORY will it contain a valid string
+ *                          length that can be used to resize the buffer.
+ */
+#define RTUtf16ToLatin1Ex(pwszString, cwcString, ppsz, cch, pcch) \
+    RTUtf16ToLatin1ExTag((pwszString), (cwcString), (ppsz), (cch), (pcch), RTSTR_TAG)
+
+/**
+ * Translates UTF-16 to Latin-1 (ISO-8859-1) using buffer provided by the caller
+ * or a fittingly sized buffer allocated by the function (custom tag).
+ *
+ * @returns iprt status code.
+ * @param   pwszString      The UTF-16 string to convert.
+ * @param   cwcString       The number of RTUTF16 items to translate from
+ *                          pwszString. The translation will stop when reaching
+ *                          cwcString or the terminator ('\\0'). Use RTSTR_MAX
+ *                          to translate the entire string.
+ * @param   ppsz            Pointer to the pointer to the Latin-1 string. The
+ *                          buffer can optionally be preallocated by the caller.
+ *
+ *                          If cch is zero, *ppsz is undefined.
+ *
+ *                          If cch is non-zero and *ppsz is not NULL, then this
+ *                          will be used as the output buffer.
+ *                          VERR_BUFFER_OVERFLOW will be returned if this is
+ *                          insufficient.
+ *
+ *                          If cch is zero or *ppsz is NULL, then a buffer of
+ *                          sufficient size is allocated. cch can be used to
+ *                          specify a minimum size of this buffer. Use
+ *                          RTUtf16Free() to free the result.
+ *
+ * @param   cch             The buffer size in chars (the type). This includes
+ *                          the terminator.
+ * @param   pcch            Where to store the length of the translated string,
+ *                          excluding the terminator. (Optional)
+ *
+ *                          This may be set under some error conditions,
+ *                          however, only for VERR_BUFFER_OVERFLOW and
+ *                          VERR_NO_STR_MEMORY will it contain a valid string
+ *                          length that can be used to resize the buffer.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTDECL(int)  RTUtf16ToLatin1ExTag(PCRTUTF16 pwszString, size_t cwcString, char **ppsz, size_t cch, size_t *pcch, const char *pszTag);
+
+/**
+ * Calculates the length of the UTF-16 string in Latin-1 (ISO-8859-1) chars.
+ *
+ * This function will validate the string, and incorrectly encoded UTF-16
+ * strings will be rejected. The primary purpose of this function is to
+ * help allocate buffers for RTUtf16ToLatin1() of the correct size. For most
+ * other purposes RTUtf16ToLatin1Ex() should be used.
+ *
+ * @returns Number of char (bytes).
+ * @returns 0 if the string was incorrectly encoded.
+ * @param   pwsz        The UTF-16 string.
+ */
+RTDECL(size_t) RTUtf16CalcLatin1Len(PCRTUTF16 pwsz);
+
+/**
+ * Calculates the length of the UTF-16 string in Latin-1 (ISO-8859-1) chars.
+ *
+ * This function will validate the string, and incorrectly encoded UTF-16
+ * strings will be rejected.
+ *
+ * @returns iprt status code.
+ * @param   pwsz        The string.
+ * @param   cwc         The max string length. Use RTSTR_MAX to process the
+ *                      entire string.
+ * @param   pcch        Where to store the string length (in bytes). Optional.
+ *                      This is undefined on failure.
+ */
+RTDECL(int) RTUtf16CalcLatin1LenEx(PCRTUTF16 pwsz, size_t cwc, size_t *pcch);
+
+/**
+ * Get the unicode code point at the given string position.
+ *
+ * @returns unicode code point.
+ * @returns RTUNICP_INVALID if the encoding is invalid.
+ * @param   pwsz        The string.
+ *
+ * @remark  This is an internal worker for RTUtf16GetCp().
+ */
+RTDECL(RTUNICP) RTUtf16GetCpInternal(PCRTUTF16 pwsz);
+
+/**
+ * Get the unicode code point at the given string position.
+ *
+ * @returns iprt status code.
+ * @param   ppwsz       Pointer to the string pointer. This will be updated to
+ *                      point to the char following the current code point.
+ * @param   pCp         Where to store the code point.
+ *                      RTUNICP_INVALID is stored here on failure.
+ *
+ * @remark  This is an internal worker for RTUtf16GetCpEx().
+ */
+RTDECL(int) RTUtf16GetCpExInternal(PCRTUTF16 *ppwsz, PRTUNICP pCp);
+
+/**
+ * Put the unicode code point at the given string position
+ * and return the pointer to the char following it.
+ *
+ * This function will not consider anything at or following the
+ * buffer area pointed to by pwsz. It is therefore not suitable for
+ * inserting code points into a string, only appending/overwriting.
+ *
+ * @returns pointer to the char following the written code point.
+ * @param   pwsz        The string.
+ * @param   CodePoint   The code point to write.
+ *                      This should not be RTUNICP_INVALID or any other
+ *                      character out of the UTF-16 range.
+ *
+ * @remark  This is an internal worker for RTUtf16GetCpEx().
+ */
+RTDECL(PRTUTF16) RTUtf16PutCpInternal(PRTUTF16 pwsz, RTUNICP CodePoint);
+
+/**
+ * Get the unicode code point at the given string position.
+ *
+ * @returns unicode code point.
+ * @returns RTUNICP_INVALID if the encoding is invalid.
+ * @param   pwsz        The string.
+ *
+ * @remark  We optimize this operation by using an inline function for
+ *          everything which isn't a surrogate pair or an endian indicator.
+ */
+DECLINLINE(RTUNICP) RTUtf16GetCp(PCRTUTF16 pwsz)
+{
+    const RTUTF16 wc = *pwsz;
+    if (wc < 0xd800 || (wc > 0xdfff && wc < 0xfffe))
+        return wc;
+    return RTUtf16GetCpInternal(pwsz);
+}
+
+/**
+ * Get the unicode code point at the given string position.
+ *
+ * @returns iprt status code.
+ * @param   ppwsz       Pointer to the string pointer. This will be updated to
+ *                      point to the char following the current code point.
+ * @param   pCp         Where to store the code point.
+ *                      RTUNICP_INVALID is stored here on failure.
+ *
+ * @remark  We optimize this operation by using an inline function for
+ *          everything which isn't a surrogate pair or and endian indicator.
+ */
+DECLINLINE(int) RTUtf16GetCpEx(PCRTUTF16 *ppwsz, PRTUNICP pCp)
+{
+    const RTUTF16 wc = **ppwsz;
+    if (wc < 0xd800 || (wc > 0xdfff && wc < 0xfffe))
+    {
+        (*ppwsz)++;
+        *pCp = wc;
+        return VINF_SUCCESS;
+    }
+    return RTUtf16GetCpExInternal(ppwsz, pCp);
+}
+
+/**
+ * Put the unicode code point at the given string position
+ * and return the pointer to the char following it.
+ *
+ * This function will not consider anything at or following the
+ * buffer area pointed to by pwsz. It is therefore not suitable for
+ * inserting code points into a string, only appending/overwriting.
+ *
+ * @returns pointer to the char following the written code point.
+ * @param   pwsz        The string.
+ * @param   CodePoint   The code point to write.
+ *                      This should not be RTUNICP_INVALID or any other
+ *                      character out of the UTF-16 range.
+ *
+ * @remark  We optimize this operation by using an inline function for
+ *          everything which isn't a surrogate pair or and endian indicator.
+ */
+DECLINLINE(PRTUTF16) RTUtf16PutCp(PRTUTF16 pwsz, RTUNICP CodePoint)
+{
+    if (CodePoint < 0xd800 || (CodePoint > 0xd800 && CodePoint < 0xfffe))
+    {
+        *pwsz++ = (RTUTF16)CodePoint;
+        return pwsz;
+    }
+    return RTUtf16PutCpInternal(pwsz, CodePoint);
+}
+
+/**
+ * Skips ahead, past the current code point.
+ *
+ * @returns Pointer to the char after the current code point.
+ * @param   pwsz    Pointer to the current code point.
+ * @remark  This will not move the next valid code point, only past the current one.
+ */
+DECLINLINE(PRTUTF16) RTUtf16NextCp(PCRTUTF16 pwsz)
+{
+    RTUNICP Cp;
+    RTUtf16GetCpEx(&pwsz, &Cp);
+    return (PRTUTF16)pwsz;
+}
+
+/**
+ * Skips backwards, to the previous code point.
+ *
+ * @returns Pointer to the char after the current code point.
+ * @param   pwszStart   Pointer to the start of the string.
+ * @param   pwsz        Pointer to the current code point.
+ */
+RTDECL(PRTUTF16) RTUtf16PrevCp(PCRTUTF16 pwszStart, PCRTUTF16 pwsz);
+
+
+/**
+ * Checks if the UTF-16 char is the high surrogate char (i.e.
+ * the 1st char in the pair).
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   wc      The character to investigate.
+ */
+DECLINLINE(bool) RTUtf16IsHighSurrogate(RTUTF16 wc)
+{
+    return wc >= 0xd800 && wc <= 0xdbff;
+}
+
+/**
+ * Checks if the UTF-16 char is the low surrogate char (i.e.
+ * the 2nd char in the pair).
+ *
+ * @returns true if it is.
+ * @returns false if it isn't.
+ * @param   wc      The character to investigate.
+ */
+DECLINLINE(bool) RTUtf16IsLowSurrogate(RTUTF16 wc)
+{
+    return wc >= 0xdc00 && wc <= 0xdfff;
+}
+
+
+/**
+ * Checks if the two UTF-16 chars form a valid surrogate pair.
+ *
+ * @returns true if they do.
+ * @returns false if they doesn't.
+ * @param   wcHigh      The high (1st) character.
+ * @param   wcLow       The low (2nd) character.
+ */
+DECLINLINE(bool) RTUtf16IsSurrogatePair(RTUTF16 wcHigh, RTUTF16 wcLow)
+{
+    return RTUtf16IsHighSurrogate(wcHigh)
+        && RTUtf16IsLowSurrogate(wcLow);
+}
+
+/**
+ * Formats a buffer stream as hex bytes.
+ *
+ * The default is no separating spaces or line breaks or anything.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_POINTER if any of the pointers are wrong.
+ * @retval  VERR_BUFFER_OVERFLOW if the buffer is insufficent to hold the bytes.
+ *
+ * @param   pwszBuf     Output string buffer.
+ * @param   cwcBuf      The size of the output buffer in RTUTF16 units.
+ * @param   pv          Pointer to the bytes to stringify.
+ * @param   cb          The number of bytes to stringify.
+ * @param   fFlags      Combination of RTSTRPRINTHEXBYTES_F_XXX values.
+ * @sa      RTStrPrintHexBytes.
+ */
+RTDECL(int) RTUtf16PrintHexBytes(PRTUTF16 pwszBuf, size_t cwcBuf, void const *pv, size_t cb, uint32_t fFlags);
+
+/** @} */
+
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/iprt/x86.h b/ubuntu/vbox/include/iprt/x86.h
new file mode 100644 (file)
index 0000000..81b03c8
--- /dev/null
@@ -0,0 +1,4212 @@
+/** @file
+ * IPRT - X86 and AMD64 Structures and Definitions.
+ *
+ * @note x86.mac is generated from this file by running 'kmk incs' in the root.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___iprt_x86_h
+#define ___iprt_x86_h
+
+#ifndef VBOX_FOR_DTRACE_LIB
+# include <iprt/types.h>
+# include <iprt/assert.h>
+#else
+# pragma D depends_on library vbox-types.d
+#endif
+
+/* Workaround for Solaris sys/regset.h defining CS, DS */
+#ifdef RT_OS_SOLARIS
+# undef CS
+# undef DS
+#endif
+
+/** @defgroup grp_rt_x86   x86 Types and Definitions
+ * @ingroup grp_rt
+ * @{
+ */
+
+#ifndef VBOX_FOR_DTRACE_LIB
+/**
+ * EFLAGS Bits.
+ */
+typedef struct X86EFLAGSBITS
+{
+    /** Bit 0 - CF - Carry flag - Status flag. */
+    unsigned    u1CF : 1;
+    /** Bit 1 -  1 - Reserved flag. */
+    unsigned    u1Reserved0 : 1;
+    /** Bit 2 - PF - Parity flag - Status flag. */
+    unsigned    u1PF : 1;
+    /** Bit 3 -  0 - Reserved flag. */
+    unsigned    u1Reserved1 : 1;
+    /** Bit 4 - AF - Auxiliary carry flag - Status flag. */
+    unsigned    u1AF : 1;
+    /** Bit 5 -  0 - Reserved flag. */
+    unsigned    u1Reserved2 : 1;
+    /** Bit 6 - ZF - Zero flag - Status flag. */
+    unsigned    u1ZF : 1;
+    /** Bit 7 - SF - Signed flag - Status flag. */
+    unsigned    u1SF : 1;
+    /** Bit 8 - TF - Trap flag - System flag. */
+    unsigned    u1TF : 1;
+    /** Bit 9 - IF - Interrupt flag - System flag. */
+    unsigned    u1IF : 1;
+    /** Bit 10 - DF - Direction flag - Control flag. */
+    unsigned    u1DF : 1;
+    /** Bit 11 - OF - Overflow flag - Status flag. */
+    unsigned    u1OF : 1;
+    /** Bit 12-13 - IOPL - I/O privilege level flag - System flag. */
+    unsigned    u2IOPL : 2;
+    /** Bit 14 - NT - Nested task flag - System flag. */
+    unsigned    u1NT : 1;
+    /** Bit 15 -  0 - Reserved flag. */
+    unsigned    u1Reserved3 : 1;
+    /** Bit 16 - RF - Resume flag - System flag. */
+    unsigned    u1RF : 1;
+    /** Bit 17 - VM - Virtual 8086 mode - System flag. */
+    unsigned    u1VM : 1;
+    /** Bit 18 - AC - Alignment check flag - System flag. Works with CR0.AM. */
+    unsigned    u1AC : 1;
+    /** Bit 19 - VIF - Virtual interrupt flag - System flag. */
+    unsigned    u1VIF : 1;
+    /** Bit 20 - VIP - Virtual interrupt pending flag - System flag. */
+    unsigned    u1VIP : 1;
+    /** Bit 21 - ID - CPUID flag - System flag. If this responds to flipping CPUID is supported. */
+    unsigned    u1ID : 1;
+    /** Bit 22-31 - 0 - Reserved flag. */
+    unsigned    u10Reserved4 : 10;
+} X86EFLAGSBITS;
+/** Pointer to EFLAGS bits. */
+typedef X86EFLAGSBITS *PX86EFLAGSBITS;
+/** Pointer to const EFLAGS bits. */
+typedef const X86EFLAGSBITS *PCX86EFLAGSBITS;
+#endif /* !VBOX_FOR_DTRACE_LIB */
+
+/**
+ * EFLAGS.
+ */
+typedef union X86EFLAGS
+{
+    /** The plain unsigned view. */
+    uint32_t        u;
+#ifndef VBOX_FOR_DTRACE_LIB
+    /** The bitfield view. */
+    X86EFLAGSBITS   Bits;
+#endif
+    /** The 8-bit view. */
+    uint8_t         au8[4];
+    /** The 16-bit view. */
+    uint16_t        au16[2];
+    /** The 32-bit view. */
+    uint32_t        au32[1];
+    /** The 32-bit view. */
+    uint32_t        u32;
+} X86EFLAGS;
+/** Pointer to EFLAGS. */
+typedef X86EFLAGS *PX86EFLAGS;
+/** Pointer to const EFLAGS. */
+typedef const X86EFLAGS *PCX86EFLAGS;
+
+/**
+ * RFLAGS (32 upper bits are reserved).
+ */
+typedef union X86RFLAGS
+{
+    /** The plain unsigned view. */
+    uint64_t        u;
+#ifndef VBOX_FOR_DTRACE_LIB
+    /** The bitfield view. */
+    X86EFLAGSBITS   Bits;
+#endif
+    /** The 8-bit view. */
+    uint8_t         au8[8];
+    /** The 16-bit view. */
+    uint16_t        au16[4];
+    /** The 32-bit view. */
+    uint32_t        au32[2];
+    /** The 64-bit view. */
+    uint64_t        au64[1];
+    /** The 64-bit view. */
+    uint64_t        u64;
+} X86RFLAGS;
+/** Pointer to RFLAGS. */
+typedef X86RFLAGS *PX86RFLAGS;
+/** Pointer to const RFLAGS. */
+typedef const X86RFLAGS *PCX86RFLAGS;
+
+
+/** @name EFLAGS
+ * @{
+ */
+/** Bit 0 - CF - Carry flag - Status flag. */
+#define X86_EFL_CF          RT_BIT_32(0)
+#define X86_EFL_CF_BIT      0
+/** Bit 1 - Reserved, reads as 1. */
+#define X86_EFL_1           RT_BIT_32(1)
+/** Bit 2 - PF - Parity flag - Status flag. */
+#define X86_EFL_PF          RT_BIT_32(2)
+/** Bit 4 - AF - Auxiliary carry flag - Status flag. */
+#define X86_EFL_AF          RT_BIT_32(4)
+#define X86_EFL_AF_BIT      4
+/** Bit 6 - ZF - Zero flag - Status flag. */
+#define X86_EFL_ZF          RT_BIT_32(6)
+#define X86_EFL_ZF_BIT      6
+/** Bit 7 - SF - Signed flag - Status flag. */
+#define X86_EFL_SF          RT_BIT_32(7)
+#define X86_EFL_SF_BIT      7
+/** Bit 8 - TF - Trap flag - System flag. */
+#define X86_EFL_TF          RT_BIT_32(8)
+/** Bit 9 - IF - Interrupt flag - System flag. */
+#define X86_EFL_IF          RT_BIT_32(9)
+/** Bit 10 - DF - Direction flag - Control flag. */
+#define X86_EFL_DF          RT_BIT_32(10)
+/** Bit 11 - OF - Overflow flag - Status flag. */
+#define X86_EFL_OF          RT_BIT_32(11)
+#define X86_EFL_OF_BIT      11
+/** Bit 12-13 - IOPL - I/O privilege level flag - System flag. */
+#define X86_EFL_IOPL        (RT_BIT_32(12) | RT_BIT_32(13))
+/** Bit 14 - NT - Nested task flag - System flag. */
+#define X86_EFL_NT          RT_BIT_32(14)
+/** Bit 16 - RF - Resume flag - System flag. */
+#define X86_EFL_RF          RT_BIT_32(16)
+/** Bit 17 - VM - Virtual 8086 mode - System flag. */
+#define X86_EFL_VM          RT_BIT_32(17)
+/** Bit 18 - AC - Alignment check flag - System flag. Works with CR0.AM. */
+#define X86_EFL_AC          RT_BIT_32(18)
+/** Bit 19 - VIF - Virtual interrupt flag - System flag. */
+#define X86_EFL_VIF         RT_BIT_32(19)
+/** Bit 20 - VIP - Virtual interrupt pending flag - System flag. */
+#define X86_EFL_VIP         RT_BIT_32(20)
+/** Bit 21 - ID - CPUID flag - System flag. If this responds to flipping CPUID is supported. */
+#define X86_EFL_ID          RT_BIT_32(21)
+/** All live bits. */
+#define X86_EFL_LIVE_MASK   UINT32_C(0x003f7fd5)
+/** Read as 1 bits. */
+#define X86_EFL_RA1_MASK    RT_BIT_32(1)
+/** IOPL shift. */
+#define X86_EFL_IOPL_SHIFT  12
+/** The IOPL level from the flags. */
+#define X86_EFL_GET_IOPL(efl)   (((efl) >> X86_EFL_IOPL_SHIFT) & 3)
+/** Bits restored by popf */
+#define X86_EFL_POPF_BITS       (  X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_TF | X86_EFL_IF \
+                                 | X86_EFL_DF | X86_EFL_OF | X86_EFL_IOPL | X86_EFL_NT | X86_EFL_AC | X86_EFL_ID )
+/** Bits restored by popf */
+#define X86_EFL_POPF_BITS_386   (  X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_TF | X86_EFL_IF \
+                                 | X86_EFL_DF | X86_EFL_OF | X86_EFL_IOPL | X86_EFL_NT )
+/** The status bits commonly updated by arithmetic instructions. */
+#define X86_EFL_STATUS_BITS     ( X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF )
+/** @} */
+
+
+/** CPUID Feature information - ECX.
+ * CPUID query with EAX=1.
+ */
+#ifndef VBOX_FOR_DTRACE_LIB
+typedef struct X86CPUIDFEATECX
+{
+    /** Bit 0 - SSE3 - Supports SSE3 or not. */
+    unsigned    u1SSE3 : 1;
+    /** Bit 1 - PCLMULQDQ. */
+    unsigned    u1PCLMULQDQ : 1;
+    /** Bit 2 - DS Area 64-bit layout. */
+    unsigned    u1DTE64 : 1;
+    /** Bit 3 - MONITOR - Supports MONITOR/MWAIT. */
+    unsigned    u1Monitor : 1;
+    /** Bit 4 - CPL-DS - CPL Qualified Debug Store. */
+    unsigned    u1CPLDS : 1;
+    /** Bit 5 - VMX - Virtual Machine Technology. */
+    unsigned    u1VMX : 1;
+    /** Bit 6 - SMX: Safer Mode Extensions. */
+    unsigned    u1SMX : 1;
+    /** Bit 7 - EST - Enh. SpeedStep Tech. */
+    unsigned    u1EST : 1;
+    /** Bit 8 - TM2 - Terminal Monitor 2. */
+    unsigned    u1TM2 : 1;
+    /** Bit 9 - SSSE3 - Supplemental Streaming SIMD Extensions 3. */
+    unsigned    u1SSSE3 : 1;
+    /** Bit 10 - CNTX-ID - L1 Context ID. */
+    unsigned    u1CNTXID : 1;
+    /** Bit 11 - Reserved. */
+    unsigned    u1Reserved1 : 1;
+    /** Bit 12 - FMA. */
+    unsigned    u1FMA : 1;
+    /** Bit 13 - CX16 - CMPXCHG16B. */
+    unsigned    u1CX16 : 1;
+    /** Bit 14 - xTPR Update Control. Processor supports changing IA32_MISC_ENABLES[bit 23]. */
+    unsigned    u1TPRUpdate : 1;
+    /** Bit 15 - PDCM - Perf/Debug Capability MSR. */
+    unsigned    u1PDCM : 1;
+    /** Bit 16 - Reserved. */
+    unsigned    u1Reserved2 : 1;
+    /** Bit 17 - PCID - Process-context identifiers. */
+    unsigned    u1PCID : 1;
+    /** Bit 18 - Direct Cache Access. */
+    unsigned    u1DCA : 1;
+    /** Bit 19 - SSE4_1 - Supports SSE4_1 or not. */
+    unsigned    u1SSE4_1 : 1;
+    /** Bit 20 - SSE4_2 - Supports SSE4_2 or not. */
+    unsigned    u1SSE4_2 : 1;
+    /** Bit 21 - x2APIC. */
+    unsigned    u1x2APIC : 1;
+    /** Bit 22 - MOVBE - Supports MOVBE. */
+    unsigned    u1MOVBE : 1;
+    /** Bit 23 - POPCNT - Supports POPCNT. */
+    unsigned    u1POPCNT : 1;
+    /** Bit 24 - TSC-Deadline. */
+    unsigned    u1TSCDEADLINE : 1;
+    /** Bit 25 - AES. */
+    unsigned    u1AES : 1;
+    /** Bit 26 - XSAVE - Supports XSAVE. */
+    unsigned    u1XSAVE : 1;
+    /** Bit 27 - OSXSAVE - Supports OSXSAVE. */
+    unsigned    u1OSXSAVE : 1;
+    /** Bit 28 - AVX - Supports AVX instruction extensions. */
+    unsigned    u1AVX : 1;
+    /** Bit 29 - F16C - Supports 16-bit floating point conversion instructions. */
+    unsigned    u1F16C : 1;
+    /** Bit 30 - RDRAND - Supports RDRAND. */
+    unsigned    u1RDRAND : 1;
+    /** Bit 31 - Hypervisor present (we're a guest). */
+    unsigned    u1HVP : 1;
+} X86CPUIDFEATECX;
+#else  /* VBOX_FOR_DTRACE_LIB */
+typedef uint32_t X86CPUIDFEATECX;
+#endif /* VBOX_FOR_DTRACE_LIB */
+/** Pointer to CPUID Feature Information - ECX. */
+typedef X86CPUIDFEATECX *PX86CPUIDFEATECX;
+/** Pointer to const CPUID Feature Information - ECX. */
+typedef const X86CPUIDFEATECX *PCX86CPUIDFEATECX;
+
+
+/** CPUID Feature Information - EDX.
+ * CPUID query with EAX=1.
+ */
+#ifndef VBOX_FOR_DTRACE_LIB /* DTrace different (brain-dead from a C pov) bitfield implementation */
+typedef struct X86CPUIDFEATEDX
+{
+    /** Bit 0 - FPU - x87 FPU on Chip. */
+    unsigned    u1FPU : 1;
+    /** Bit 1 - VME - Virtual 8086 Mode Enhancements. */
+    unsigned    u1VME : 1;
+    /** Bit 2 - DE - Debugging extensions. */
+    unsigned    u1DE : 1;
+    /** Bit 3 - PSE - Page Size Extension. */
+    unsigned    u1PSE : 1;
+    /** Bit 4 - TSC - Time Stamp Counter. */
+    unsigned    u1TSC : 1;
+    /** Bit 5 - MSR - Model Specific Registers RDMSR and WRMSR Instructions. */
+    unsigned    u1MSR : 1;
+    /** Bit 6 - PAE - Physical Address Extension. */
+    unsigned    u1PAE : 1;
+    /** Bit 7 - MCE - Machine Check Exception. */
+    unsigned    u1MCE : 1;
+    /** Bit 8 - CX8 - CMPXCHG8B instruction. */
+    unsigned    u1CX8 : 1;
+    /** Bit 9 - APIC - APIC On-Chip. */
+    unsigned    u1APIC : 1;
+    /** Bit 10 - Reserved. */
+    unsigned    u1Reserved1 : 1;
+    /** Bit 11 - SEP - SYSENTER and SYSEXIT. */
+    unsigned    u1SEP : 1;
+    /** Bit 12 - MTRR - Memory Type Range Registers. */
+    unsigned    u1MTRR : 1;
+    /** Bit 13 - PGE - PTE Global Bit. */
+    unsigned    u1PGE : 1;
+    /** Bit 14 - MCA - Machine Check Architecture. */
+    unsigned    u1MCA : 1;
+    /** Bit 15 - CMOV - Conditional Move Instructions. */
+    unsigned    u1CMOV : 1;
+    /** Bit 16 - PAT - Page Attribute Table. */
+    unsigned    u1PAT : 1;
+    /** Bit 17 - PSE-36 - 36-bit Page Size Extension. */
+    unsigned    u1PSE36 : 1;
+    /** Bit 18 - PSN - Processor Serial Number. */
+    unsigned    u1PSN : 1;
+    /** Bit 19 - CLFSH - CLFLUSH Instruction. */
+    unsigned    u1CLFSH : 1;
+    /** Bit 20 - Reserved. */
+    unsigned    u1Reserved2 : 1;
+    /** Bit 21 - DS - Debug Store. */
+    unsigned    u1DS : 1;
+    /** Bit 22 - ACPI - Thermal Monitor and Software Controlled Clock Facilities. */
+    unsigned    u1ACPI : 1;
+    /** Bit 23 - MMX - Intel MMX 'Technology'. */
+    unsigned    u1MMX : 1;
+    /** Bit 24 - FXSR - FXSAVE and FXRSTOR Instructions. */
+    unsigned    u1FXSR : 1;
+    /** Bit 25 - SSE - SSE Support. */
+    unsigned    u1SSE : 1;
+    /** Bit 26 - SSE2 - SSE2 Support. */
+    unsigned    u1SSE2 : 1;
+    /** Bit 27 - SS - Self Snoop. */
+    unsigned    u1SS : 1;
+    /** Bit 28 - HTT - Hyper-Threading Technology. */
+    unsigned    u1HTT : 1;
+    /** Bit 29 - TM - Thermal Monitor. */
+    unsigned    u1TM : 1;
+    /** Bit 30 - Reserved - . */
+    unsigned    u1Reserved3 : 1;
+    /** Bit 31 - PBE - Pending Break Enabled. */
+    unsigned    u1PBE : 1;
+} X86CPUIDFEATEDX;
+#else  /* VBOX_FOR_DTRACE_LIB */
+typedef uint32_t X86CPUIDFEATEDX;
+#endif /* VBOX_FOR_DTRACE_LIB */
+/** Pointer to CPUID Feature Information - EDX. */
+typedef X86CPUIDFEATEDX *PX86CPUIDFEATEDX;
+/** Pointer to const CPUID Feature Information - EDX. */
+typedef const X86CPUIDFEATEDX *PCX86CPUIDFEATEDX;
+
+/** @name CPUID Vendor information.
+ * CPUID query with EAX=0.
+ * @{
+ */
+#define X86_CPUID_VENDOR_INTEL_EBX      0x756e6547      /* Genu */
+#define X86_CPUID_VENDOR_INTEL_ECX      0x6c65746e      /* ntel */
+#define X86_CPUID_VENDOR_INTEL_EDX      0x49656e69      /* ineI */
+
+#define X86_CPUID_VENDOR_AMD_EBX        0x68747541      /* Auth */
+#define X86_CPUID_VENDOR_AMD_ECX        0x444d4163      /* cAMD */
+#define X86_CPUID_VENDOR_AMD_EDX        0x69746e65      /* enti */
+
+#define X86_CPUID_VENDOR_VIA_EBX        0x746e6543      /* Cent */
+#define X86_CPUID_VENDOR_VIA_ECX        0x736c7561      /* auls */
+#define X86_CPUID_VENDOR_VIA_EDX        0x48727561      /* aurH */
+/** @} */
+
+
+/** @name CPUID Feature information.
+ * CPUID query with EAX=1.
+ * @{
+ */
+/** ECX Bit 0 - SSE3 - Supports SSE3 or not. */
+#define X86_CPUID_FEATURE_ECX_SSE3      RT_BIT_32(0)
+/** ECX Bit 1 - PCLMUL - PCLMULQDQ support (for AES-GCM). */
+#define X86_CPUID_FEATURE_ECX_PCLMUL    RT_BIT_32(1)
+/** ECX Bit 2 - DTES64 - DS Area 64-bit Layout. */
+#define X86_CPUID_FEATURE_ECX_DTES64    RT_BIT_32(2)
+/** ECX Bit 3 - MONITOR - Supports MONITOR/MWAIT. */
+#define X86_CPUID_FEATURE_ECX_MONITOR   RT_BIT_32(3)
+/** ECX Bit 4 - CPL-DS - CPL Qualified Debug Store. */
+#define X86_CPUID_FEATURE_ECX_CPLDS     RT_BIT_32(4)
+/** ECX Bit 5 - VMX - Virtual Machine Technology. */
+#define X86_CPUID_FEATURE_ECX_VMX       RT_BIT_32(5)
+/** ECX Bit 6 - SMX - Safer Mode Extensions. */
+#define X86_CPUID_FEATURE_ECX_SMX       RT_BIT_32(6)
+/** ECX Bit 7 - EST - Enh. SpeedStep Tech. */
+#define X86_CPUID_FEATURE_ECX_EST       RT_BIT_32(7)
+/** ECX Bit 8 - TM2 - Terminal Monitor 2. */
+#define X86_CPUID_FEATURE_ECX_TM2       RT_BIT_32(8)
+/** ECX Bit 9 - SSSE3 - Supplemental Streaming SIMD Extensions 3. */
+#define X86_CPUID_FEATURE_ECX_SSSE3     RT_BIT_32(9)
+/** ECX Bit 10 - CNTX-ID - L1 Context ID. */
+#define X86_CPUID_FEATURE_ECX_CNTXID    RT_BIT_32(10)
+/** ECX Bit 11 - SDBG - Sillicon debug interface (IA32_DEBUG_INTERFACE MSR).
+ * See figure 3-6 and table 3-10, in intel Vol. 2A. from 2015-01-01. */
+#define X86_CPUID_FEATURE_ECX_SDBG      RT_BIT_32(11)
+/** ECX Bit 12 - FMA. */
+#define X86_CPUID_FEATURE_ECX_FMA       RT_BIT_32(12)
+/** ECX Bit 13 - CX16 - CMPXCHG16B. */
+#define X86_CPUID_FEATURE_ECX_CX16      RT_BIT_32(13)
+/** ECX Bit 14 - xTPR Update Control. Processor supports changing IA32_MISC_ENABLES[bit 23]. */
+#define X86_CPUID_FEATURE_ECX_TPRUPDATE RT_BIT_32(14)
+/** ECX Bit 15 - PDCM - Perf/Debug Capability MSR. */
+#define X86_CPUID_FEATURE_ECX_PDCM      RT_BIT_32(15)
+/** ECX Bit 17 - PCID - Process-context identifiers. */
+#define X86_CPUID_FEATURE_ECX_PCID      RT_BIT_32(17)
+/** ECX Bit 18 - DCA - Direct Cache Access. */
+#define X86_CPUID_FEATURE_ECX_DCA       RT_BIT_32(18)
+/** ECX Bit 19 - SSE4_1 - Supports SSE4_1 or not. */
+#define X86_CPUID_FEATURE_ECX_SSE4_1    RT_BIT_32(19)
+/** ECX Bit 20 - SSE4_2 - Supports SSE4_2 or not. */
+#define X86_CPUID_FEATURE_ECX_SSE4_2    RT_BIT_32(20)
+/** ECX Bit 21 - x2APIC support. */
+#define X86_CPUID_FEATURE_ECX_X2APIC    RT_BIT_32(21)
+/** ECX Bit 22 - MOVBE instruction. */
+#define X86_CPUID_FEATURE_ECX_MOVBE     RT_BIT_32(22)
+/** ECX Bit 23 - POPCNT instruction. */
+#define X86_CPUID_FEATURE_ECX_POPCNT    RT_BIT_32(23)
+/** ECX Bir 24 - TSC-Deadline. */
+#define X86_CPUID_FEATURE_ECX_TSCDEADL  RT_BIT_32(24)
+/** ECX Bit 25 - AES instructions. */
+#define X86_CPUID_FEATURE_ECX_AES       RT_BIT_32(25)
+/** ECX Bit 26 - XSAVE instruction. */
+#define X86_CPUID_FEATURE_ECX_XSAVE     RT_BIT_32(26)
+/** ECX Bit 27 - Copy of CR4.OSXSAVE. */
+#define X86_CPUID_FEATURE_ECX_OSXSAVE   RT_BIT_32(27)
+/** ECX Bit 28 - AVX. */
+#define X86_CPUID_FEATURE_ECX_AVX       RT_BIT_32(28)
+/** ECX Bit 29 - F16C - Half-precision convert instruction support. */
+#define X86_CPUID_FEATURE_ECX_F16C      RT_BIT_32(29)
+/** ECX Bit 30 - RDRAND instruction. */
+#define X86_CPUID_FEATURE_ECX_RDRAND    RT_BIT_32(30)
+/** ECX Bit 31 - Hypervisor Present (software only). */
+#define X86_CPUID_FEATURE_ECX_HVP       RT_BIT_32(31)
+
+
+/** Bit 0 - FPU - x87 FPU on Chip. */
+#define X86_CPUID_FEATURE_EDX_FPU       RT_BIT_32(0)
+/** Bit 1 - VME - Virtual 8086 Mode Enhancements. */
+#define X86_CPUID_FEATURE_EDX_VME       RT_BIT_32(1)
+/** Bit 2 - DE - Debugging extensions. */
+#define X86_CPUID_FEATURE_EDX_DE        RT_BIT_32(2)
+/** Bit 3 - PSE - Page Size Extension. */
+#define X86_CPUID_FEATURE_EDX_PSE       RT_BIT_32(3)
+#define X86_CPUID_FEATURE_EDX_PSE_BIT             3     /**< Bit number for X86_CPUID_FEATURE_EDX_PSE. */
+/** Bit 4 - TSC - Time Stamp Counter. */
+#define X86_CPUID_FEATURE_EDX_TSC       RT_BIT_32(4)
+/** Bit 5 - MSR - Model Specific Registers RDMSR and WRMSR Instructions. */
+#define X86_CPUID_FEATURE_EDX_MSR       RT_BIT_32(5)
+/** Bit 6 - PAE - Physical Address Extension. */
+#define X86_CPUID_FEATURE_EDX_PAE       RT_BIT_32(6)
+#define X86_CPUID_FEATURE_EDX_PAE_BIT             6     /**< Bit number for X86_CPUID_FEATURE_EDX_PAE. */
+/** Bit 7 - MCE - Machine Check Exception. */
+#define X86_CPUID_FEATURE_EDX_MCE       RT_BIT_32(7)
+/** Bit 8 - CX8 - CMPXCHG8B instruction. */
+#define X86_CPUID_FEATURE_EDX_CX8       RT_BIT_32(8)
+/** Bit 9 - APIC - APIC On-Chip. */
+#define X86_CPUID_FEATURE_EDX_APIC      RT_BIT_32(9)
+/** Bit 11 - SEP - SYSENTER and SYSEXIT Present. */
+#define X86_CPUID_FEATURE_EDX_SEP       RT_BIT_32(11)
+/** Bit 12 - MTRR - Memory Type Range Registers. */
+#define X86_CPUID_FEATURE_EDX_MTRR      RT_BIT_32(12)
+/** Bit 13 - PGE - PTE Global Bit. */
+#define X86_CPUID_FEATURE_EDX_PGE       RT_BIT_32(13)
+/** Bit 14 - MCA - Machine Check Architecture. */
+#define X86_CPUID_FEATURE_EDX_MCA       RT_BIT_32(14)
+/** Bit 15 - CMOV - Conditional Move Instructions. */
+#define X86_CPUID_FEATURE_EDX_CMOV      RT_BIT_32(15)
+/** Bit 16 - PAT - Page Attribute Table. */
+#define X86_CPUID_FEATURE_EDX_PAT       RT_BIT_32(16)
+/** Bit 17 - PSE-36 - 36-bit Page Size Extension. */
+#define X86_CPUID_FEATURE_EDX_PSE36     RT_BIT_32(17)
+/** Bit 18 - PSN - Processor Serial Number. */
+#define X86_CPUID_FEATURE_EDX_PSN       RT_BIT_32(18)
+/** Bit 19 - CLFSH - CLFLUSH Instruction. */
+#define X86_CPUID_FEATURE_EDX_CLFSH     RT_BIT_32(19)
+/** Bit 21 - DS - Debug Store. */
+#define X86_CPUID_FEATURE_EDX_DS        RT_BIT_32(21)
+/** Bit 22 - ACPI - Thermal Monitor and Software Controlled Clock Facilities. */
+#define X86_CPUID_FEATURE_EDX_ACPI      RT_BIT_32(22)
+/** Bit 23 - MMX - Intel MMX Technology. */
+#define X86_CPUID_FEATURE_EDX_MMX       RT_BIT_32(23)
+/** Bit 24 - FXSR - FXSAVE and FXRSTOR Instructions. */
+#define X86_CPUID_FEATURE_EDX_FXSR      RT_BIT_32(24)
+/** Bit 25 - SSE - SSE Support. */
+#define X86_CPUID_FEATURE_EDX_SSE       RT_BIT_32(25)
+/** Bit 26 - SSE2 - SSE2 Support. */
+#define X86_CPUID_FEATURE_EDX_SSE2      RT_BIT_32(26)
+/** Bit 27 - SS - Self Snoop. */
+#define X86_CPUID_FEATURE_EDX_SS        RT_BIT_32(27)
+/** Bit 28 - HTT - Hyper-Threading Technology. */
+#define X86_CPUID_FEATURE_EDX_HTT       RT_BIT_32(28)
+/** Bit 29 - TM - Therm. Monitor. */
+#define X86_CPUID_FEATURE_EDX_TM        RT_BIT_32(29)
+/** Bit 31 - PBE - Pending Break Enabled. */
+#define X86_CPUID_FEATURE_EDX_PBE       RT_BIT_32(31)
+/** @} */
+
+/** @name CPUID mwait/monitor information.
+ * CPUID query with EAX=5.
+ * @{
+ */
+/** ECX Bit 0 - MWAITEXT - Supports mwait/monitor extensions or not. */
+#define X86_CPUID_MWAIT_ECX_EXT            RT_BIT_32(0)
+/** ECX Bit 1 - MWAITBREAK - Break mwait for external interrupt even if EFLAGS.IF=0. */
+#define X86_CPUID_MWAIT_ECX_BREAKIRQIF0    RT_BIT_32(1)
+/** @} */
+
+
+/** @name CPUID Structured Extended Feature information.
+ * CPUID query with EAX=7.
+ * @{
+ */
+/** EBX Bit 0 - FSGSBASE - Supports RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE. */
+#define X86_CPUID_STEXT_FEATURE_EBX_FSGSBASE          RT_BIT_32(0)
+/** EBX Bit 1 - TSCADJUST - Supports MSR_IA32_TSC_ADJUST. */
+#define X86_CPUID_STEXT_FEATURE_EBX_TSC_ADJUST        RT_BIT_32(1)
+/** EBX Bit 2 - SGX - Supports Software Guard Extensions . */
+#define X86_CPUID_STEXT_FEATURE_EBX_SGX               RT_BIT_32(2)
+/** EBX Bit 3 - BMI1 - Advanced Bit Manipulation extension 1. */
+#define X86_CPUID_STEXT_FEATURE_EBX_BMI1              RT_BIT_32(3)
+/** EBX Bit 4 - HLE - Hardware Lock Elision. */
+#define X86_CPUID_STEXT_FEATURE_EBX_HLE               RT_BIT_32(4)
+/** EBX Bit 5 - AVX2 - Advanced Vector Extensions 2. */
+#define X86_CPUID_STEXT_FEATURE_EBX_AVX2              RT_BIT_32(5)
+/** EBX Bit 6 - FDP_EXCPTN_ONLY - FPU data pointer only updated on exceptions if set. */
+#define X86_CPUID_STEXT_FEATURE_EBX_FDP_EXCPTN_ONLY   RT_BIT_32(6)
+/** EBX Bit 7 - SMEP - Supervisor Mode Execution Prevention. */
+#define X86_CPUID_STEXT_FEATURE_EBX_SMEP              RT_BIT_32(7)
+/** EBX Bit 8 - BMI2 - Advanced Bit Manipulation extension 2. */
+#define X86_CPUID_STEXT_FEATURE_EBX_BMI2              RT_BIT_32(8)
+/** EBX Bit 9 - ERMS - Supports Enhanced REP MOVSB/STOSB. */
+#define X86_CPUID_STEXT_FEATURE_EBX_ERMS              RT_BIT_32(9)
+/** EBX Bit 10 - INVPCID - Supports INVPCID. */
+#define X86_CPUID_STEXT_FEATURE_EBX_INVPCID           RT_BIT_32(10)
+/** EBX Bit 11 - RTM - Supports Restricted Transactional Memory. */
+#define X86_CPUID_STEXT_FEATURE_EBX_RTM               RT_BIT_32(11)
+/** EBX Bit 12 - PQM - Supports Platform Quality of Service Monitoring. */
+#define X86_CPUID_STEXT_FEATURE_EBX_PQM               RT_BIT_32(12)
+/** EBX Bit 13 - DEPFPU_CS_DS - Deprecates FPU CS, FPU DS values if set. */
+#define X86_CPUID_STEXT_FEATURE_EBX_DEPR_FPU_CS_DS    RT_BIT_32(13)
+/** EBX Bit 14 - MPE - Supports Intel Memory Protection Extensions. */
+#define X86_CPUID_STEXT_FEATURE_EBX_MPE               RT_BIT_32(14)
+/** EBX Bit 15 - PQE - Supports Platform Quality of Service Enforcement. */
+#define X86_CPUID_STEXT_FEATURE_EBX_PQE               RT_BIT_32(15)
+/** EBX Bit 16 - AVX512F - Supports AVX512F. */
+#define X86_CPUID_STEXT_FEATURE_EBX_AVX512F           RT_BIT_32(16)
+/** EBX Bit 18 - RDSEED - Supports RDSEED. */
+#define X86_CPUID_STEXT_FEATURE_EBX_RDSEED            RT_BIT_32(18)
+/** EBX Bit 19 - ADX - Supports ADCX/ADOX. */
+#define X86_CPUID_STEXT_FEATURE_EBX_ADX               RT_BIT_32(19)
+/** EBX Bit 20 - SMAP - Supports Supervisor Mode Access Prevention. */
+#define X86_CPUID_STEXT_FEATURE_EBX_SMAP              RT_BIT_32(20)
+/** EBX Bit 23 - CLFLUSHOPT - Supports CLFLUSHOPT (Cache Line Flush). */
+#define X86_CPUID_STEXT_FEATURE_EBX_CLFLUSHOPT        RT_BIT_32(23)
+/** EBX Bit 25 - INTEL_PT - Supports Intel Processor Trace. */
+#define X86_CPUID_STEXT_FEATURE_EBX_INTEL_PT          RT_BIT_32(25)
+/** EBX Bit 26 - AVX512PF - Supports AVX512PF. */
+#define X86_CPUID_STEXT_FEATURE_EBX_AVX512PF          RT_BIT_32(26)
+/** EBX Bit 27 - AVX512ER - Supports AVX512ER. */
+#define X86_CPUID_STEXT_FEATURE_EBX_AVX512ER          RT_BIT_32(27)
+/** EBX Bit 28 - AVX512CD - Supports AVX512CD. */
+#define X86_CPUID_STEXT_FEATURE_EBX_AVX512CD          RT_BIT_32(28)
+/** EBX Bit 29 - SHA - Supports Secure Hash Algorithm extensions. */
+#define X86_CPUID_STEXT_FEATURE_EBX_SHA               RT_BIT_32(29)
+
+/** ECX Bit 0 - PREFETCHWT1 - Supports the PREFETCHWT1 instruction. */
+#define X86_CPUID_STEXT_FEATURE_ECX_PREFETCHWT1       RT_BIT_32(0)
+/** @} */
+
+
+/** @name CPUID Extended Feature information.
+ *  CPUID query with EAX=0x80000001.
+ *  @{
+ */
+/** ECX Bit 0 - LAHF/SAHF support in 64-bit mode. */
+#define X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF     RT_BIT_32(0)
+
+/** EDX Bit 11 - SYSCALL/SYSRET. */
+#define X86_CPUID_EXT_FEATURE_EDX_SYSCALL       RT_BIT_32(11)
+/** EDX Bit 20 - No-Execute/Execute-Disable. */
+#define X86_CPUID_EXT_FEATURE_EDX_NX            RT_BIT_32(20)
+/** EDX Bit 26 - 1 GB large page. */
+#define X86_CPUID_EXT_FEATURE_EDX_PAGE1GB       RT_BIT_32(26)
+/** EDX Bit 27 - RDTSCP. */
+#define X86_CPUID_EXT_FEATURE_EDX_RDTSCP        RT_BIT_32(27)
+/** EDX Bit 29 - AMD Long Mode/Intel-64 Instructions. */
+#define X86_CPUID_EXT_FEATURE_EDX_LONG_MODE     RT_BIT_32(29)
+/** @}*/
+
+/** @name CPUID AMD Feature information.
+ * CPUID query with EAX=0x80000001.
+ * @{
+ */
+/** Bit 0 - FPU - x87 FPU on Chip. */
+#define X86_CPUID_AMD_FEATURE_EDX_FPU       RT_BIT_32(0)
+/** Bit 1 - VME - Virtual 8086 Mode Enhancements. */
+#define X86_CPUID_AMD_FEATURE_EDX_VME       RT_BIT_32(1)
+/** Bit 2 - DE - Debugging extensions. */
+#define X86_CPUID_AMD_FEATURE_EDX_DE        RT_BIT_32(2)
+/** Bit 3 - PSE - Page Size Extension. */
+#define X86_CPUID_AMD_FEATURE_EDX_PSE       RT_BIT_32(3)
+/** Bit 4 - TSC - Time Stamp Counter. */
+#define X86_CPUID_AMD_FEATURE_EDX_TSC       RT_BIT_32(4)
+/** Bit 5 - MSR - K86 Model Specific Registers RDMSR and WRMSR Instructions. */
+#define X86_CPUID_AMD_FEATURE_EDX_MSR       RT_BIT_32(5)
+/** Bit 6 - PAE - Physical Address Extension. */
+#define X86_CPUID_AMD_FEATURE_EDX_PAE       RT_BIT_32(6)
+/** Bit 7 - MCE - Machine Check Exception. */
+#define X86_CPUID_AMD_FEATURE_EDX_MCE       RT_BIT_32(7)
+/** Bit 8 - CX8 - CMPXCHG8B instruction. */
+#define X86_CPUID_AMD_FEATURE_EDX_CX8       RT_BIT_32(8)
+/** Bit 9 - APIC - APIC On-Chip. */
+#define X86_CPUID_AMD_FEATURE_EDX_APIC      RT_BIT_32(9)
+/** Bit 12 - MTRR - Memory Type Range Registers. */
+#define X86_CPUID_AMD_FEATURE_EDX_MTRR      RT_BIT_32(12)
+/** Bit 13 - PGE - PTE Global Bit. */
+#define X86_CPUID_AMD_FEATURE_EDX_PGE       RT_BIT_32(13)
+/** Bit 14 - MCA - Machine Check Architecture. */
+#define X86_CPUID_AMD_FEATURE_EDX_MCA       RT_BIT_32(14)
+/** Bit 15 - CMOV - Conditional Move Instructions. */
+#define X86_CPUID_AMD_FEATURE_EDX_CMOV      RT_BIT_32(15)
+/** Bit 16 - PAT - Page Attribute Table. */
+#define X86_CPUID_AMD_FEATURE_EDX_PAT       RT_BIT_32(16)
+/** Bit 17 - PSE-36 - 36-bit Page Size Extension. */
+#define X86_CPUID_AMD_FEATURE_EDX_PSE36     RT_BIT_32(17)
+/** Bit 22 - AXMMX - AMD Extensions to MMX Instructions. */
+#define X86_CPUID_AMD_FEATURE_EDX_AXMMX     RT_BIT_32(22)
+/** Bit 23 - MMX - Intel MMX Technology. */
+#define X86_CPUID_AMD_FEATURE_EDX_MMX       RT_BIT_32(23)
+/** Bit 24 - FXSR - FXSAVE and FXRSTOR Instructions. */
+#define X86_CPUID_AMD_FEATURE_EDX_FXSR      RT_BIT_32(24)
+/** Bit 25 - FFXSR - AMD fast FXSAVE and FXRSTOR Instructions. */
+#define X86_CPUID_AMD_FEATURE_EDX_FFXSR     RT_BIT_32(25)
+/** Bit 30 - 3DNOWEXT - AMD Extensions to 3DNow. */
+#define X86_CPUID_AMD_FEATURE_EDX_3DNOW_EX  RT_BIT_32(30)
+/** Bit 31 - 3DNOW - AMD 3DNow. */
+#define X86_CPUID_AMD_FEATURE_EDX_3DNOW     RT_BIT_32(31)
+
+/** Bit 1 - CmpLegacy - Core multi-processing legacy mode. */
+#define X86_CPUID_AMD_FEATURE_ECX_CMPL      RT_BIT_32(1)
+/** Bit 2 - SVM - AMD VM extensions. */
+#define X86_CPUID_AMD_FEATURE_ECX_SVM       RT_BIT_32(2)
+/** Bit 3 - EXTAPIC - AMD extended APIC registers starting at 0x400. */
+#define X86_CPUID_AMD_FEATURE_ECX_EXT_APIC  RT_BIT_32(3)
+/** Bit 4 - CR8L - AMD LOCK MOV CR0 means MOV CR8. */
+#define X86_CPUID_AMD_FEATURE_ECX_CR8L      RT_BIT_32(4)
+/** Bit 5 - ABM - AMD Advanced bit manipulation. LZCNT instruction support. */
+#define X86_CPUID_AMD_FEATURE_ECX_ABM       RT_BIT_32(5)
+/** Bit 6 - SSE4A - AMD EXTRQ, INSERTQ, MOVNTSS, and MOVNTSD instruction support. */
+#define X86_CPUID_AMD_FEATURE_ECX_SSE4A     RT_BIT_32(6)
+/** Bit 7 - MISALIGNSSE - AMD Misaligned SSE mode. */
+#define X86_CPUID_AMD_FEATURE_ECX_MISALNSSE RT_BIT_32(7)
+/** Bit 8 - 3DNOWPRF - AMD PREFETCH and PREFETCHW instruction support. */
+#define X86_CPUID_AMD_FEATURE_ECX_3DNOWPRF  RT_BIT_32(8)
+/** Bit 9 - OSVW - AMD OS visible workaround. */
+#define X86_CPUID_AMD_FEATURE_ECX_OSVW      RT_BIT_32(9)
+/** Bit 10 - IBS - Instruct based sampling. */
+#define X86_CPUID_AMD_FEATURE_ECX_IBS       RT_BIT_32(10)
+/** Bit 11 - XOP - Extended operation support (see APM6). */
+#define X86_CPUID_AMD_FEATURE_ECX_XOP       RT_BIT_32(11)
+/** Bit 12 - SKINIT - AMD SKINIT: SKINIT, STGI, and DEV support. */
+#define X86_CPUID_AMD_FEATURE_ECX_SKINIT    RT_BIT_32(12)
+/** Bit 13 - WDT - AMD Watchdog timer support. */
+#define X86_CPUID_AMD_FEATURE_ECX_WDT       RT_BIT_32(13)
+/** Bit 15 - LWP - Lightweight profiling support. */
+#define X86_CPUID_AMD_FEATURE_ECX_LWP       RT_BIT_32(15)
+/** Bit 16 - FMA4 - Four operand FMA instruction support. */
+#define X86_CPUID_AMD_FEATURE_ECX_FMA4      RT_BIT_32(16)
+/** Bit 19 - NodeId - Indicates support for
+ * MSR_C001_100C[NodeId,NodesPerProcessr]. */
+#define X86_CPUID_AMD_FEATURE_ECX_NODEID    RT_BIT_32(19)
+/** Bit 21 - TBM - Trailing bit manipulation instruction support. */
+#define X86_CPUID_AMD_FEATURE_ECX_TBM       RT_BIT_32(21)
+/** Bit 22 - TopologyExtensions - . */
+#define X86_CPUID_AMD_FEATURE_ECX_TOPOEXT   RT_BIT_32(22)
+/** @} */
+
+
+/** @name CPUID AMD Feature information.
+ * CPUID query with EAX=0x80000007.
+ * @{
+ */
+/** Bit 0 - TS - Temperature Sensor. */
+#define X86_CPUID_AMD_ADVPOWER_EDX_TS        RT_BIT_32(0)
+/** Bit 1 - FID - Frequency ID Control. */
+#define X86_CPUID_AMD_ADVPOWER_EDX_FID       RT_BIT_32(1)
+/** Bit 2 - VID - Voltage ID Control. */
+#define X86_CPUID_AMD_ADVPOWER_EDX_VID       RT_BIT_32(2)
+/** Bit 3 - TTP - THERMTRIP. */
+#define X86_CPUID_AMD_ADVPOWER_EDX_TTP       RT_BIT_32(3)
+/** Bit 4 - TM - Hardware Thermal Control. */
+#define X86_CPUID_AMD_ADVPOWER_EDX_TM        RT_BIT_32(4)
+/** Bit 5 - STC - Software Thermal Control. */
+#define X86_CPUID_AMD_ADVPOWER_EDX_STC       RT_BIT_32(5)
+/** Bit 6 - MC - 100 Mhz Multiplier Control. */
+#define X86_CPUID_AMD_ADVPOWER_EDX_MC        RT_BIT_32(6)
+/** Bit 7 - HWPSTATE - Hardware P-State Control. */
+#define X86_CPUID_AMD_ADVPOWER_EDX_HWPSTATE  RT_BIT_32(7)
+/** Bit 8 - TSCINVAR - TSC Invariant. */
+#define X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR  RT_BIT_32(8)
+/** Bit 9 - CPB - TSC Invariant. */
+#define X86_CPUID_AMD_ADVPOWER_EDX_CPB       RT_BIT_32(9)
+/** Bit 10 - EffFreqRO - MPERF/APERF. */
+#define X86_CPUID_AMD_ADVPOWER_EDX_EFRO      RT_BIT_32(10)
+/** Bit 11 - PFI - Processor feedback interface (see EAX). */
+#define X86_CPUID_AMD_ADVPOWER_EDX_PFI       RT_BIT_32(11)
+/** Bit 12 - PA - Processor accumulator (MSR c001_007a). */
+#define X86_CPUID_AMD_ADVPOWER_EDX_PA        RT_BIT_32(12)
+/** @} */
+
+
+/** @name CPUID AMD SVM Feature information.
+ * CPUID query with EAX=0x8000000a.
+ * @{
+ */
+/** Bit 0 - NP - Nested Paging supported. */
+#define X86_CPUID_SVM_FEATURE_EDX_NESTED_PAGING             RT_BIT(0)
+/** Bit 1 - LbrVirt - Support for saving five debug MSRs. */
+#define X86_CPUID_SVM_FEATURE_EDX_LBR_VIRT                  RT_BIT(1)
+/** Bit 2 - SVML - SVM locking bit supported. */
+#define X86_CPUID_SVM_FEATURE_EDX_SVM_LOCK                  RT_BIT(2)
+/** Bit 3 - NRIPS - Saving the next instruction pointer is supported. */
+#define X86_CPUID_SVM_FEATURE_EDX_NRIP_SAVE                 RT_BIT(3)
+/** Bit 4 - TscRateMsr - Support for MSR TSC ratio. */
+#define X86_CPUID_SVM_FEATURE_EDX_TSC_RATE_MSR              RT_BIT(4)
+/** Bit 5 - VmcbClean - Support VMCB clean bits. */
+#define X86_CPUID_SVM_FEATURE_EDX_VMCB_CLEAN                RT_BIT(5)
+/** Bit 6 - FlushByAsid - Indicate TLB flushing for current ASID only, and that
+ *  VMCB.TLB_Control is supported. */
+#define X86_CPUID_SVM_FEATURE_EDX_FLUSH_BY_ASID             RT_BIT(6)
+/** Bit 7 - DecodeAssist - Indicate decode assist is supported. */
+#define X86_CPUID_SVM_FEATURE_EDX_DECODE_ASSIST             RT_BIT(7)
+/** Bit 10 - PauseFilter - Indicates support for the PAUSE intercept filter. */
+#define X86_CPUID_SVM_FEATURE_EDX_PAUSE_FILTER              RT_BIT(10)
+/** Bit 12 - PauseFilterThreshold - Indicates support for the PAUSE
+ *  intercept filter cycle count threshold. */
+#define X86_CPUID_SVM_FEATURE_EDX_PAUSE_FILTER_THRESHOLD    RT_BIT(12)
+/** Bit 13 - AVIC - Advanced Virtual Interrupt Controller. */
+#define X86_CPUID_SVM_FEATURE_EDX_AVIC                      RT_BIT(13)
+/** @} */
+
+
+/** @name CR0
+ * @remarks The 286 (MSW), 386 and 486 ignores attempts at setting
+ *          reserved flags.
+ * @{ */
+/** Bit 0 - PE - Protection Enabled */
+#define X86_CR0_PE                          RT_BIT_32(0)
+#define X86_CR0_PROTECTION_ENABLE           RT_BIT_32(0)
+/** Bit 1 - MP - Monitor Coprocessor */
+#define X86_CR0_MP                          RT_BIT_32(1)
+#define X86_CR0_MONITOR_COPROCESSOR         RT_BIT_32(1)
+/** Bit 2 - EM - Emulation. */
+#define X86_CR0_EM                          RT_BIT_32(2)
+#define X86_CR0_EMULATE_FPU                 RT_BIT_32(2)
+/** Bit 3 - TS - Task Switch. */
+#define X86_CR0_TS                          RT_BIT_32(3)
+#define X86_CR0_TASK_SWITCH                 RT_BIT_32(3)
+/** Bit 4 - ET - Extension flag. (386, 'hardcoded' to 1 on 486+) */
+#define X86_CR0_ET                          RT_BIT_32(4)
+#define X86_CR0_EXTENSION_TYPE              RT_BIT_32(4)
+/** Bit 5 - NE - Numeric error (486+). */
+#define X86_CR0_NE                          RT_BIT_32(5)
+#define X86_CR0_NUMERIC_ERROR               RT_BIT_32(5)
+/** Bit 16 - WP - Write Protect (486+). */
+#define X86_CR0_WP                          RT_BIT_32(16)
+#define X86_CR0_WRITE_PROTECT               RT_BIT_32(16)
+/** Bit 18 - AM - Alignment Mask (486+). */
+#define X86_CR0_AM                          RT_BIT_32(18)
+#define X86_CR0_ALIGMENT_MASK               RT_BIT_32(18)
+/** Bit 29 - NW - Not Write-though (486+). */
+#define X86_CR0_NW                          RT_BIT_32(29)
+#define X86_CR0_NOT_WRITE_THROUGH           RT_BIT_32(29)
+/** Bit 30 - WP - Cache Disable (486+). */
+#define X86_CR0_CD                          RT_BIT_32(30)
+#define X86_CR0_CACHE_DISABLE               RT_BIT_32(30)
+/** Bit 31 - PG - Paging. */
+#define X86_CR0_PG                          RT_BIT_32(31)
+#define X86_CR0_PAGING                      RT_BIT_32(31)
+/** @} */
+
+
+/** @name CR3
+ * @{ */
+/** Bit 3 - PWT - Page-level Writes Transparent. */
+#define X86_CR3_PWT                         RT_BIT_32(3)
+/** Bit 4 - PCD - Page-level Cache Disable. */
+#define X86_CR3_PCD                         RT_BIT_32(4)
+/** Bits 12-31 - - Page directory page number. */
+#define X86_CR3_PAGE_MASK                   (0xfffff000)
+/** Bits  5-31 - - PAE Page directory page number. */
+#define X86_CR3_PAE_PAGE_MASK               (0xffffffe0)
+/** Bits 12-51 - - AMD64 Page directory page number. */
+#define X86_CR3_AMD64_PAGE_MASK             UINT64_C(0x000ffffffffff000)
+/** @} */
+
+
+/** @name CR4
+ * @{ */
+/** Bit 0 - VME - Virtual-8086 Mode Extensions. */
+#define X86_CR4_VME                         RT_BIT_32(0)
+/** Bit 1 - PVI - Protected-Mode Virtual Interrupts. */
+#define X86_CR4_PVI                         RT_BIT_32(1)
+/** Bit 2 - TSD - Time Stamp Disable. */
+#define X86_CR4_TSD                         RT_BIT_32(2)
+/** Bit 3 - DE - Debugging Extensions. */
+#define X86_CR4_DE                          RT_BIT_32(3)
+/** Bit 4 - PSE - Page Size Extension. */
+#define X86_CR4_PSE                         RT_BIT_32(4)
+/** Bit 5 - PAE - Physical Address Extension. */
+#define X86_CR4_PAE                         RT_BIT_32(5)
+/** Bit 6 - MCE - Machine-Check Enable. */
+#define X86_CR4_MCE                         RT_BIT_32(6)
+/** Bit 7 - PGE - Page Global Enable. */
+#define X86_CR4_PGE                         RT_BIT_32(7)
+/** Bit 8 - PCE - Performance-Monitoring Counter Enable. */
+#define X86_CR4_PCE                         RT_BIT_32(8)
+/** Bit 9 - OSFXSR - Operating System Support for FXSAVE and FXRSTORE instructions. */
+#define X86_CR4_OSFXSR                      RT_BIT_32(9)
+/** Bit 10 - OSXMMEEXCPT - Operating System Support for Unmasked SIMD Floating-Point Exceptions. */
+#define X86_CR4_OSXMMEEXCPT                 RT_BIT_32(10)
+/** Bit 13 - VMXE - VMX mode is enabled. */
+#define X86_CR4_VMXE                        RT_BIT_32(13)
+/** Bit 14 - SMXE - Safer Mode Extensions Enabled. */
+#define X86_CR4_SMXE                        RT_BIT_32(14)
+/** Bit 17 - PCIDE - Process-Context Identifiers Enabled. */
+#define X86_CR4_PCIDE                       RT_BIT_32(17)
+/** Bit 18 - OSXSAVE - Operating System Support for XSAVE and processor
+ * extended states. */
+#define X86_CR4_OSXSAVE                     RT_BIT_32(18)
+/** Bit 20 - SMEP - Supervisor-mode Execution Prevention enabled. */
+#define X86_CR4_SMEP                        RT_BIT_32(20)
+/** Bit 21 - SMAP - Supervisor-mode Access Prevention enabled. */
+#define X86_CR4_SMAP                        RT_BIT_32(21)
+/** Bit 22 - PKE - Protection Key Enable. */
+#define X86_CR4_PKE                         RT_BIT_32(22)
+/** @} */
+
+
+/** @name DR6
+ * @{ */
+/** Bit 0 - B0 - Breakpoint 0 condition detected. */
+#define X86_DR6_B0                          RT_BIT_32(0)
+/** Bit 1 - B1 - Breakpoint 1 condition detected. */
+#define X86_DR6_B1                          RT_BIT_32(1)
+/** Bit 2 - B2 - Breakpoint 2 condition detected. */
+#define X86_DR6_B2                          RT_BIT_32(2)
+/** Bit 3 - B3 - Breakpoint 3 condition detected. */
+#define X86_DR6_B3                          RT_BIT_32(3)
+/** Mask of all the Bx bits. */
+#define X86_DR6_B_MASK                      UINT64_C(0x0000000f)
+/** Bit 13 - BD - Debug register access detected. Corresponds to the X86_DR7_GD bit. */
+#define X86_DR6_BD                          RT_BIT_32(13)
+/** Bit 14 - BS - Single step */
+#define X86_DR6_BS                          RT_BIT_32(14)
+/** Bit 15 - BT - Task switch. (TSS T bit.) */
+#define X86_DR6_BT                          RT_BIT_32(15)
+/** Value of DR6 after powerup/reset. */
+#define X86_DR6_INIT_VAL                    UINT64_C(0xFFFF0FF0)
+/** Bits which must be 1s in DR6. */
+#define X86_DR6_RA1_MASK                    UINT64_C(0xffff0ff0)
+/** Bits which must be 0s in DR6. */
+#define X86_DR6_RAZ_MASK                    RT_BIT_64(12)
+/** Bits which must be 0s on writes to DR6. */
+#define X86_DR6_MBZ_MASK                    UINT64_C(0xffffffff00000000)
+/** @} */
+
+/** Get the DR6.Bx bit for a the given breakpoint. */
+#define X86_DR6_B(iBp)                      RT_BIT_64(iBp)
+
+
+/** @name DR7
+ * @{ */
+/** Bit 0 - L0 - Local breakpoint enable. Cleared on task switch. */
+#define X86_DR7_L0                          RT_BIT_32(0)
+/** Bit 1 - G0 - Global breakpoint enable. Not cleared on task switch. */
+#define X86_DR7_G0                          RT_BIT_32(1)
+/** Bit 2 - L1 - Local breakpoint enable. Cleared on task switch. */
+#define X86_DR7_L1                          RT_BIT_32(2)
+/** Bit 3 - G1 - Global breakpoint enable. Not cleared on task switch. */
+#define X86_DR7_G1                          RT_BIT_32(3)
+/** Bit 4 - L2 - Local breakpoint enable. Cleared on task switch. */
+#define X86_DR7_L2                          RT_BIT_32(4)
+/** Bit 5 - G2 - Global breakpoint enable. Not cleared on task switch. */
+#define X86_DR7_G2                          RT_BIT_32(5)
+/** Bit 6 - L3 - Local breakpoint enable. Cleared on task switch. */
+#define X86_DR7_L3                          RT_BIT_32(6)
+/** Bit 7 - G3 - Global breakpoint enable. Not cleared on task switch. */
+#define X86_DR7_G3                          RT_BIT_32(7)
+/** Bit 8 - LE - Local breakpoint exact. (Not supported (read ignored) by P6 and later.) */
+#define X86_DR7_LE                          RT_BIT_32(8)
+/** Bit 9 - GE - Local breakpoint exact. (Not supported (read ignored) by P6 and later.) */
+#define X86_DR7_GE                          RT_BIT_32(9)
+
+/** L0, L1, L2, and L3.  */
+#define X86_DR7_LE_ALL                      UINT64_C(0x0000000000000055)
+/** L0, L1, L2, and L3.  */
+#define X86_DR7_GE_ALL                      UINT64_C(0x00000000000000aa)
+
+/** Bit 12 - IR (ICE) - Interrupt redirection on Pentium.  When set, the in
+ * Circuit Emulator (ICE) will break emulation on breakpoints and stuff.
+ * May cause CPU hang if enabled without ICE attached when the ICEBP/INT1
+ * instruction is executed.
+ * @see http://www.rcollins.org/secrets/DR7.html  */
+#define X86_DR7_ICE_IR                      RT_BIT_32(12)
+/** Bit 13 - GD - General detect enable. Enables emulators to get exceptions when
+ * any DR register is accessed. */
+#define X86_DR7_GD                          RT_BIT_32(13)
+/** Bit 14 - TR1 (ICE) - Code discontinuity trace for use with ICE on
+ *  Pentium. */
+#define X86_DR7_ICE_TR1                     RT_BIT_32(14)
+/** Bit 15 - TR2 (ICE) - Controls unknown ICE trace feature of the pentium. */
+#define X86_DR7_ICE_TR2                     RT_BIT_32(15)
+/** Bit 16 & 17 - R/W0 - Read write field 0. Values X86_DR7_RW_*. */
+#define X86_DR7_RW0_MASK                    (3 << 16)
+/** Bit 18 & 19 - LEN0 - Length field 0. Values X86_DR7_LEN_*. */
+#define X86_DR7_LEN0_MASK                   (3 << 18)
+/** Bit 20 & 21 - R/W1 - Read write field 0. Values X86_DR7_RW_*. */
+#define X86_DR7_RW1_MASK                    (3 << 20)
+/** Bit 22 & 23 - LEN1 - Length field 0. Values X86_DR7_LEN_*. */
+#define X86_DR7_LEN1_MASK                   (3 << 22)
+/** Bit 24 & 25 - R/W2 - Read write field 0. Values X86_DR7_RW_*. */
+#define X86_DR7_RW2_MASK                    (3 << 24)
+/** Bit 26 & 27 - LEN2 - Length field 0. Values X86_DR7_LEN_*. */
+#define X86_DR7_LEN2_MASK                   (3 << 26)
+/** Bit 28 & 29 - R/W3 - Read write field 0. Values X86_DR7_RW_*. */
+#define X86_DR7_RW3_MASK                    (3 << 28)
+/** Bit 30 & 31 - LEN3 - Length field 0. Values X86_DR7_LEN_*. */
+#define X86_DR7_LEN3_MASK                   (3 << 30)
+
+/** Bits which reads as 1s. */
+#define X86_DR7_RA1_MASK                    RT_BIT_32(10)
+/** Bits which reads as zeros.  These are related to ICE (bits 12, 14, 15). */
+#define X86_DR7_RAZ_MASK                    UINT64_C(0x0000d800)
+/** Bits which must be 0s when writing to DR7. */
+#define X86_DR7_MBZ_MASK                    UINT64_C(0xffffffff00000000)
+
+/** Calcs the L bit of Nth breakpoint.
+ * @param   iBp     The breakpoint number [0..3].
+ */
+#define X86_DR7_L(iBp)                      ( UINT32_C(1) << (iBp * 2) )
+
+/** Calcs the G bit of Nth breakpoint.
+ * @param   iBp     The breakpoint number [0..3].
+ */
+#define X86_DR7_G(iBp)                      ( UINT32_C(1) << (iBp * 2 + 1) )
+
+/** Calcs the L and G bits of Nth breakpoint.
+ * @param   iBp     The breakpoint number [0..3].
+ */
+#define X86_DR7_L_G(iBp)                    ( UINT32_C(3) << (iBp * 2) )
+
+/** @name Read/Write values.
+ * @{ */
+/** Break on instruction fetch only. */
+#define X86_DR7_RW_EO                       0U
+/** Break on write only. */
+#define X86_DR7_RW_WO                       1U
+/** Break on I/O read/write. This is only defined if CR4.DE is set. */
+#define X86_DR7_RW_IO                       2U
+/** Break on read or write (but not instruction fetches). */
+#define X86_DR7_RW_RW                       3U
+/** @} */
+
+/** Shifts a X86_DR7_RW_* value to its right place.
+ * @param   iBp     The breakpoint number [0..3].
+ * @param   fRw     One of the X86_DR7_RW_* value.
+ */
+#define X86_DR7_RW(iBp, fRw)                ( (fRw) << ((iBp) * 4 + 16) )
+
+/** Fetch the R/Wx bits for a given breakpoint (so it can be compared with
+ * one of the X86_DR7_RW_XXX constants).
+ *
+ * @returns X86_DR7_RW_XXX
+ * @param   uDR7    DR7 value
+ * @param   iBp     The breakpoint number [0..3].
+ */
+#define X86_DR7_GET_RW(uDR7, iBp)            ( ( (uDR7) >> ((iBp) * 4 + 16) ) & UINT32_C(3) )
+
+/** R/W0, R/W1, R/W2, and R/W3. */
+#define X86_DR7_RW_ALL_MASKS                UINT32_C(0x33330000)
+
+#ifndef VBOX_FOR_DTRACE_LIB
+/** Checks if there are any I/O breakpoint types configured in the RW
+ * registers.  Does NOT check if these are enabled, sorry. */
+# define X86_DR7_ANY_RW_IO(uDR7) \
+    (   (    UINT32_C(0x22220000) & (uDR7) ) /* any candidates? */ \
+     && ( ( (UINT32_C(0x22220000) & (uDR7) ) >> 1 )  &  ~(uDR7) ) )
+AssertCompile(X86_DR7_ANY_RW_IO(UINT32_C(0x33330000)) == 0);
+AssertCompile(X86_DR7_ANY_RW_IO(UINT32_C(0x22220000)) == 1);
+AssertCompile(X86_DR7_ANY_RW_IO(UINT32_C(0x32320000)) == 1);
+AssertCompile(X86_DR7_ANY_RW_IO(UINT32_C(0x23230000)) == 1);
+AssertCompile(X86_DR7_ANY_RW_IO(UINT32_C(0x00000000)) == 0);
+AssertCompile(X86_DR7_ANY_RW_IO(UINT32_C(0x00010000)) == 0);
+AssertCompile(X86_DR7_ANY_RW_IO(UINT32_C(0x00020000)) == 1);
+AssertCompile(X86_DR7_ANY_RW_IO(UINT32_C(0x00030000)) == 0);
+AssertCompile(X86_DR7_ANY_RW_IO(UINT32_C(0x00040000)) == 0);
+#endif /* !VBOX_FOR_DTRACE_LIB */
+
+/** @name Length values.
+ * @{ */
+#define X86_DR7_LEN_BYTE                    0U
+#define X86_DR7_LEN_WORD                    1U
+#define X86_DR7_LEN_QWORD                   2U /**< AMD64 long mode only. */
+#define X86_DR7_LEN_DWORD                   3U
+/** @} */
+
+/** Shifts a X86_DR7_LEN_* value to its right place.
+ * @param   iBp     The breakpoint number [0..3].
+ * @param   cb      One of the X86_DR7_LEN_* values.
+ */
+#define X86_DR7_LEN(iBp, cb)                ( (cb) << ((iBp) * 4 + 18) )
+
+/** Fetch the breakpoint length bits from the DR7 value.
+ * @param   uDR7    DR7 value
+ * @param   iBp     The breakpoint number [0..3].
+ */
+#define X86_DR7_GET_LEN(uDR7, iBp)          ( ( (uDR7) >> ((iBp) * 4 + 18) ) & UINT32_C(0x3) )
+
+/** Mask used to check if any breakpoints are enabled. */
+#define X86_DR7_ENABLED_MASK                UINT32_C(0x000000ff)
+
+/** LEN0, LEN1, LEN2, and LEN3. */
+#define X86_DR7_LEN_ALL_MASKS               UINT32_C(0xcccc0000)
+/** R/W0, R/W1, R/W2, R/W3,LEN0, LEN1, LEN2, and LEN3. */
+#define X86_DR7_RW_LEN_ALL_MASKS            UINT32_C(0xffff0000)
+
+/** Value of DR7 after powerup/reset. */
+#define X86_DR7_INIT_VAL                    0x400
+/** @} */
+
+
+/** @name Machine Specific Registers
+ * @{
+ */
+/** Machine check address register (P5). */
+#define MSR_P5_MC_ADDR                      UINT32_C(0x00000000)
+/** Machine check type register (P5). */
+#define MSR_P5_MC_TYPE                      UINT32_C(0x00000001)
+/** Time Stamp Counter. */
+#define MSR_IA32_TSC                        0x10
+#define MSR_IA32_CESR                       UINT32_C(0x00000011)
+#define MSR_IA32_CTR0                       UINT32_C(0x00000012)
+#define MSR_IA32_CTR1                       UINT32_C(0x00000013)
+
+#define MSR_IA32_PLATFORM_ID                0x17
+
+#ifndef MSR_IA32_APICBASE /* qemu cpu.h kludge */
+# define MSR_IA32_APICBASE                  0x1b
+/** Local APIC enabled. */
+# define MSR_IA32_APICBASE_EN               RT_BIT_64(11)
+/** X2APIC enabled (requires the EN bit to be set). */
+# define MSR_IA32_APICBASE_EXTD             RT_BIT_64(10)
+/** The processor is the boot strap processor (BSP). */
+# define MSR_IA32_APICBASE_BSP              RT_BIT_64(8)
+/** Minimum base address mask, consult CPUID leaf 0x80000008 for the actual
+ *  width. */
+# define MSR_IA32_APICBASE_BASE_MIN         UINT64_C(0x0000000ffffff000)
+/** The default physical base address of the APIC. */
+# define MSR_IA32_APICBASE_ADDR             UINT64_C(0x00000000fee00000)
+/** Gets the physical base address from the MSR. */
+# define MSR_IA32_APICBASE_GET_ADDR(a_Msr)  ((a_Msr) & X86_PAGE_4K_BASE_MASK)
+#endif
+
+/** Undocumented intel MSR for reporting thread and core counts.
+ * Judging from the XNU sources, it seems to be introduced in Nehalem. The
+ * first 16 bits is the thread count. The next 16 bits the core count, except
+ * on Westmere where it seems it's only the next 4 bits for some reason. */
+#define MSR_CORE_THREAD_COUNT               0x35
+
+/** CPU Feature control. */
+#define MSR_IA32_FEATURE_CONTROL            0x3A
+#define MSR_IA32_FEATURE_CONTROL_LOCK       RT_BIT_32(0)
+#define MSR_IA32_FEATURE_CONTROL_SMX_VMXON  RT_BIT_32(1)
+#define MSR_IA32_FEATURE_CONTROL_VMXON      RT_BIT_32(2)
+
+/** Per-processor TSC adjust MSR. */
+#define MSR_IA32_TSC_ADJUST                 0x3B
+
+/** BIOS update trigger (microcode update). */
+#define MSR_IA32_BIOS_UPDT_TRIG             0x79
+
+/** BIOS update signature (microcode). */
+#define MSR_IA32_BIOS_SIGN_ID               0x8B
+
+/** SMM monitor control. */
+#define MSR_IA32_SMM_MONITOR_CTL            0x9B
+
+/** General performance counter no. 0. */
+#define MSR_IA32_PMC0                       0xC1
+/** General performance counter no. 1. */
+#define MSR_IA32_PMC1                       0xC2
+/** General performance counter no. 2. */
+#define MSR_IA32_PMC2                       0xC3
+/** General performance counter no. 3. */
+#define MSR_IA32_PMC3                       0xC4
+
+/** Nehalem power control. */
+#define MSR_IA32_PLATFORM_INFO              0xCE
+
+/** Get FSB clock status (Intel-specific). */
+#define MSR_IA32_FSB_CLOCK_STS              0xCD
+
+/** C-State configuration control. Intel specific: Nehalem, Sandy Bridge. */
+#define MSR_PKG_CST_CONFIG_CONTROL          UINT32_C(0x000000e2)
+
+/** C0 Maximum Frequency Clock Count */
+#define MSR_IA32_MPERF                      0xE7
+/** C0 Actual Frequency Clock Count */
+#define MSR_IA32_APERF                      0xE8
+
+/** MTRR Capabilities. */
+#define MSR_IA32_MTRR_CAP                   0xFE
+
+/** Cache control/info. */
+#define MSR_BBL_CR_CTL3                     UINT32_C(0x11e)
+
+#ifndef MSR_IA32_SYSENTER_CS /* qemu cpu.h kludge */
+/** SYSENTER_CS - the R0 CS, indirectly giving R0 SS, R3 CS and R3 DS.
+ * R0 SS == CS + 8
+ * R3 CS == CS + 16
+ * R3 SS == CS + 24
+ */
+#define MSR_IA32_SYSENTER_CS                0x174
+/** SYSENTER_ESP - the R0 ESP. */
+#define MSR_IA32_SYSENTER_ESP               0x175
+/** SYSENTER_EIP - the R0 EIP. */
+#define MSR_IA32_SYSENTER_EIP               0x176
+#endif
+
+/** Machine Check Global Capabilities Register. */
+#define MSR_IA32_MCG_CAP                    0x179
+/** Machine Check Global Status Register. */
+#define MSR_IA32_MCG_STATUS                 0x17A
+/** Machine Check Global Control Register. */
+#define MSR_IA32_MCG_CTRL                   0x17B
+
+/** Page Attribute Table. */
+#define MSR_IA32_CR_PAT                     0x277
+
+/** Performance counter MSRs. (Intel only) */
+#define MSR_IA32_PERFEVTSEL0                0x186
+#define MSR_IA32_PERFEVTSEL1                0x187
+/** Flexible ratio, seems to be undocumented, used by XNU (tsc.c).
+ * The 16th bit whether flex ratio is being used, in which case bits 15:8
+ * holds a ratio that Apple takes for TSC granularity.
+ *
+ * @note This MSR conflicts the P4 MSR_MCG_R12 register. */
+#define MSR_FLEX_RATIO                      0x194
+/** Performance state value and starting with Intel core more.
+ * Apple uses the >=core features to determine TSC granularity on older CPUs. */
+#define MSR_IA32_PERF_STATUS                0x198
+#define MSR_IA32_PERF_CTL                   0x199
+#define MSR_IA32_THERM_STATUS               0x19c
+
+/** Enable misc. processor features (R/W). */
+#define MSR_IA32_MISC_ENABLE                   0x1A0
+/** Enable fast-strings feature (for REP MOVS and REP STORS). */
+#define MSR_IA32_MISC_ENABLE_FAST_STRINGS      RT_BIT_64(0)
+/** Automatic Thermal Control Circuit Enable (R/W). */
+#define MSR_IA32_MISC_ENABLE_TCC               RT_BIT_64(3)
+/** Performance Monitoring Available (R). */
+#define MSR_IA32_MISC_ENABLE_PERF_MON          RT_BIT_64(7)
+/** Branch Trace Storage Unavailable (R/O). */
+#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL       RT_BIT_64(11)
+/** Precise Event Based Sampling (PEBS) Unavailable (R/O). */
+#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL      RT_BIT_64(12)
+/** Enhanced Intel SpeedStep Technology Enable (R/W). */
+#define MSR_IA32_MISC_ENABLE_SST_ENABLE        RT_BIT_64(16)
+/** If MONITOR/MWAIT is supported (R/W). */
+#define MSR_IA32_MISC_ENABLE_MONITOR           RT_BIT_64(18)
+/** Limit CPUID Maxval to 3 leafs (R/W). */
+#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID       RT_BIT_64(22)
+/** When set to 1, xTPR messages are disabled (R/W). */
+#define MSR_IA32_MISC_ENABLE_XTPR_MSG_DISABLE  RT_BIT_64(23)
+/** When set to 1, the Execute Disable Bit feature (XD Bit) is disabled (R/W). */
+#define MSR_IA32_MISC_ENABLE_XD_DISABLE        RT_BIT_64(34)
+
+/** Trace/Profile Resource Control (R/W) */
+#define MSR_IA32_DEBUGCTL                   UINT32_C(0x000001d9)
+/** The number (0..3 or 0..15) of the last branch record register on P4 and
+ * related Xeons. */
+#define MSR_P4_LASTBRANCH_TOS               UINT32_C(0x000001da)
+/** @name Last branch registers for P4 and Xeon, models 0 thru 2.
+ * @{ */
+#define MSR_P4_LASTBRANCH_0                 UINT32_C(0x000001db)
+#define MSR_P4_LASTBRANCH_1                 UINT32_C(0x000001dc)
+#define MSR_P4_LASTBRANCH_2                 UINT32_C(0x000001dd)
+#define MSR_P4_LASTBRANCH_3                 UINT32_C(0x000001de)
+/** @} */
+
+
+#define IA32_MTRR_PHYSBASE0                 0x200
+#define IA32_MTRR_PHYSMASK0                 0x201
+#define IA32_MTRR_PHYSBASE1                 0x202
+#define IA32_MTRR_PHYSMASK1                 0x203
+#define IA32_MTRR_PHYSBASE2                 0x204
+#define IA32_MTRR_PHYSMASK2                 0x205
+#define IA32_MTRR_PHYSBASE3                 0x206
+#define IA32_MTRR_PHYSMASK3                 0x207
+#define IA32_MTRR_PHYSBASE4                 0x208
+#define IA32_MTRR_PHYSMASK4                 0x209
+#define IA32_MTRR_PHYSBASE5                 0x20a
+#define IA32_MTRR_PHYSMASK5                 0x20b
+#define IA32_MTRR_PHYSBASE6                 0x20c
+#define IA32_MTRR_PHYSMASK6                 0x20d
+#define IA32_MTRR_PHYSBASE7                 0x20e
+#define IA32_MTRR_PHYSMASK7                 0x20f
+#define IA32_MTRR_PHYSBASE8                 0x210
+#define IA32_MTRR_PHYSMASK8                 0x211
+#define IA32_MTRR_PHYSBASE9                 0x212
+#define IA32_MTRR_PHYSMASK9                 0x213
+
+/** Fixed range MTRRs.
+ * @{  */
+#define IA32_MTRR_FIX64K_00000              0x250
+#define IA32_MTRR_FIX16K_80000              0x258
+#define IA32_MTRR_FIX16K_A0000              0x259
+#define IA32_MTRR_FIX4K_C0000               0x268
+#define IA32_MTRR_FIX4K_C8000               0x269
+#define IA32_MTRR_FIX4K_D0000               0x26a
+#define IA32_MTRR_FIX4K_D8000               0x26b
+#define IA32_MTRR_FIX4K_E0000               0x26c
+#define IA32_MTRR_FIX4K_E8000               0x26d
+#define IA32_MTRR_FIX4K_F0000               0x26e
+#define IA32_MTRR_FIX4K_F8000               0x26f
+/** @}  */
+
+/** MTRR Default Range. */
+#define MSR_IA32_MTRR_DEF_TYPE              0x2FF
+
+/** Global performance counter control facilities (Intel only). */
+#define MSR_IA32_PERF_GLOBAL_STATUS         0x38E
+#define MSR_IA32_PERF_GLOBAL_CTRL           0x38F
+#define MSR_IA32_PERF_GLOBAL_OVF_CTRL       0x390
+
+/** Precise Event Based sampling (Intel only). */
+#define MSR_IA32_PEBS_ENABLE                0x3F1
+
+#define MSR_IA32_MC0_CTL                    0x400
+#define MSR_IA32_MC0_STATUS                 0x401
+
+/** Basic VMX information. */
+#define MSR_IA32_VMX_BASIC_INFO             0x480
+/** Allowed settings for pin-based VM execution controls */
+#define MSR_IA32_VMX_PINBASED_CTLS          0x481
+/** Allowed settings for proc-based VM execution controls */
+#define MSR_IA32_VMX_PROCBASED_CTLS         0x482
+/** Allowed settings for the VMX exit controls. */
+#define MSR_IA32_VMX_EXIT_CTLS              0x483
+/** Allowed settings for the VMX entry controls. */
+#define MSR_IA32_VMX_ENTRY_CTLS             0x484
+/** Misc VMX info. */
+#define MSR_IA32_VMX_MISC                   0x485
+/** Fixed cleared bits in CR0. */
+#define MSR_IA32_VMX_CR0_FIXED0             0x486
+/** Fixed set bits in CR0. */
+#define MSR_IA32_VMX_CR0_FIXED1             0x487
+/** Fixed cleared bits in CR4. */
+#define MSR_IA32_VMX_CR4_FIXED0             0x488
+/** Fixed set bits in CR4. */
+#define MSR_IA32_VMX_CR4_FIXED1             0x489
+/** Information for enumerating fields in the VMCS. */
+#define MSR_IA32_VMX_VMCS_ENUM              0x48A
+/** Allowed settings for the VM-functions controls. */
+#define MSR_IA32_VMX_VMFUNC                 0x491
+/** Allowed settings for secondary proc-based VM execution controls */
+#define MSR_IA32_VMX_PROCBASED_CTLS2        0x48B
+/** EPT capabilities. */
+#define MSR_IA32_VMX_EPT_VPID_CAP           0x48C
+/** DS Save Area (R/W). */
+#define MSR_IA32_DS_AREA                    0x600
+/** Running Average Power Limit (RAPL) power units. */
+#define MSR_RAPL_POWER_UNIT                 0x606
+
+/** X2APIC MSR range start. */
+#define MSR_IA32_X2APIC_START               0x800
+/** X2APIC MSR -  APIC ID Register. */
+#define MSR_IA32_X2APIC_ID                  0x802
+/** X2APIC MSR -  APIC Version Register. */
+#define MSR_IA32_X2APIC_VERSION             0x803
+/** X2APIC MSR -  Task Priority Register. */
+#define MSR_IA32_X2APIC_TPR                 0x808
+/** X2APIC MSR -  Processor Priority register. */
+#define MSR_IA32_X2APIC_PPR                 0x80A
+/** X2APIC MSR -  End Of Interrupt register. */
+#define MSR_IA32_X2APIC_EOI                 0x80B
+/** X2APIC MSR -  Logical Destination Register. */
+#define MSR_IA32_X2APIC_LDR                 0x80D
+/** X2APIC MSR -  Spurious Interrupt Vector Register. */
+#define MSR_IA32_X2APIC_SVR                 0x80F
+/** X2APIC MSR -  In-service Register (bits 31:0). */
+#define MSR_IA32_X2APIC_ISR0                0x810
+/** X2APIC MSR -  In-service Register (bits 63:32). */
+#define MSR_IA32_X2APIC_ISR1                0x811
+/** X2APIC MSR -  In-service Register (bits 95:64). */
+#define MSR_IA32_X2APIC_ISR2                0x812
+/** X2APIC MSR -  In-service Register (bits 127:96). */
+#define MSR_IA32_X2APIC_ISR3                0x813
+/** X2APIC MSR -  In-service Register (bits 159:128). */
+#define MSR_IA32_X2APIC_ISR4                0x814
+/** X2APIC MSR -  In-service Register (bits 191:160). */
+#define MSR_IA32_X2APIC_ISR5                0x815
+/** X2APIC MSR -  In-service Register (bits 223:192). */
+#define MSR_IA32_X2APIC_ISR6                0x816
+/** X2APIC MSR -  In-service Register (bits 255:224). */
+#define MSR_IA32_X2APIC_ISR7                0x817
+/** X2APIC MSR -  Trigger Mode Register (bits 31:0). */
+#define MSR_IA32_X2APIC_TMR0                0x818
+/** X2APIC MSR -  Trigger Mode Register (bits 63:32). */
+#define MSR_IA32_X2APIC_TMR1                0x819
+/** X2APIC MSR -  Trigger Mode Register (bits 95:64). */
+#define MSR_IA32_X2APIC_TMR2                0x81A
+/** X2APIC MSR -  Trigger Mode Register (bits 127:96). */
+#define MSR_IA32_X2APIC_TMR3                0x81B
+/** X2APIC MSR -  Trigger Mode Register (bits 159:128). */
+#define MSR_IA32_X2APIC_TMR4                0x81C
+/** X2APIC MSR -  Trigger Mode Register (bits 191:160). */
+#define MSR_IA32_X2APIC_TMR5                0x81D
+/** X2APIC MSR -  Trigger Mode Register (bits 223:192). */
+#define MSR_IA32_X2APIC_TMR6                0x81E
+/** X2APIC MSR -  Trigger Mode Register (bits 255:224). */
+#define MSR_IA32_X2APIC_TMR7                0x81F
+/** X2APIC MSR -  Interrupt Request Register (bits 31:0). */
+#define MSR_IA32_X2APIC_IRR0                0x820
+/** X2APIC MSR -  Interrupt Request Register (bits 63:32). */
+#define MSR_IA32_X2APIC_IRR1                0x821
+/** X2APIC MSR -  Interrupt Request Register (bits 95:64). */
+#define MSR_IA32_X2APIC_IRR2                0x822
+/** X2APIC MSR -  Interrupt Request Register (bits 127:96). */
+#define MSR_IA32_X2APIC_IRR3                0x823
+/** X2APIC MSR -  Interrupt Request Register (bits 159:128). */
+#define MSR_IA32_X2APIC_IRR4                0x824
+/** X2APIC MSR -  Interrupt Request Register (bits 191:160). */
+#define MSR_IA32_X2APIC_IRR5                0x825
+/** X2APIC MSR -  Interrupt Request Register (bits 223:192). */
+#define MSR_IA32_X2APIC_IRR6                0x826
+/** X2APIC MSR -  Interrupt Request Register (bits 255:224). */
+#define MSR_IA32_X2APIC_IRR7                0x827
+/** X2APIC MSR -  Error Status Register. */
+#define MSR_IA32_X2APIC_ESR                 0x828
+/** X2APIC MSR - LVT CMCI Register. */
+#define MSR_IA32_X2APIC_LVT_CMCI            0x82F
+/** X2APIC MSR -  Interrupt Command Register. */
+#define MSR_IA32_X2APIC_ICR                 0x830
+/** X2APIC MSR -  LVT Timer Register. */
+#define MSR_IA32_X2APIC_LVT_TIMER           0x832
+/** X2APIC MSR -  LVT Thermal Sensor Register. */
+#define MSR_IA32_X2APIC_LVT_THERMAL         0x833
+/** X2APIC MSR -  LVT Performance Counter Register. */
+#define MSR_IA32_X2APIC_LVT_PERF            0x834
+/** X2APIC MSR -  LVT LINT0 Register. */
+#define MSR_IA32_X2APIC_LVT_LINT0           0x835
+/** X2APIC MSR -  LVT LINT1 Register. */
+#define MSR_IA32_X2APIC_LVT_LINT1           0x836
+/** X2APIC MSR -  LVT Error Register . */
+#define MSR_IA32_X2APIC_LVT_ERROR           0x837
+/** X2APIC MSR -  Timer Initial Count Register. */
+#define MSR_IA32_X2APIC_TIMER_ICR           0x838
+/** X2APIC MSR -  Timer Current Count Register. */
+#define MSR_IA32_X2APIC_TIMER_CCR           0x839
+/** X2APIC MSR -  Timer Divide Configuration Register. */
+#define MSR_IA32_X2APIC_TIMER_DCR           0x83E
+/** X2APIC MSR - Self IPI. */
+#define MSR_IA32_X2APIC_SELF_IPI            0x83F
+/** X2APIC MSR range end. */
+#define MSR_IA32_X2APIC_END                 0xBFF
+/** X2APIC MSR - LVT start range. */
+#define MSR_IA32_X2APIC_LVT_START           MSR_IA32_X2APIC_LVT_TIMER
+/** X2APIC MSR - LVT end range (inclusive). */
+#define MSR_IA32_X2APIC_LVT_END             MSR_IA32_X2APIC_LVT_ERROR
+
+/** K6 EFER - Extended Feature Enable Register. */
+#define MSR_K6_EFER                         UINT32_C(0xc0000080)
+/** @todo document EFER */
+/** Bit 0 - SCE - System call extensions (SYSCALL / SYSRET). (R/W) */
+#define  MSR_K6_EFER_SCE                     RT_BIT_32(0)
+/** Bit 8 - LME - Long mode enabled. (R/W) */
+#define  MSR_K6_EFER_LME                     RT_BIT_32(8)
+/** Bit 10 - LMA - Long mode active. (R) */
+#define  MSR_K6_EFER_LMA                     RT_BIT_32(10)
+/** Bit 11 - NXE - No-Execute Page Protection Enabled. (R/W) */
+#define  MSR_K6_EFER_NXE                     RT_BIT_32(11)
+#define  MSR_K6_EFER_BIT_NXE                 11 /**< Bit number of MSR_K6_EFER_NXE */
+/** Bit 12 - SVME - Secure VM Extension Enabled. (R/W) */
+#define  MSR_K6_EFER_SVME                    RT_BIT_32(12)
+/** Bit 13 - LMSLE - Long Mode Segment Limit Enable. (R/W?) */
+#define  MSR_K6_EFER_LMSLE                   RT_BIT_32(13)
+/** Bit 14 - FFXSR - Fast FXSAVE / FXRSTOR (skip XMM*). (R/W) */
+#define  MSR_K6_EFER_FFXSR                   RT_BIT_32(14)
+/** Bit 15 - TCE - Translation Cache Extension. (R/W) */
+#define  MSR_K6_EFER_TCE                     RT_BIT_32(15)
+/** K6 STAR - SYSCALL/RET targets. */
+#define MSR_K6_STAR                         UINT32_C(0xc0000081)
+/** Shift value for getting the SYSRET CS and SS value. */
+#define  MSR_K6_STAR_SYSRET_CS_SS_SHIFT     48
+/** Shift value for getting the SYSCALL CS and SS value. */
+#define  MSR_K6_STAR_SYSCALL_CS_SS_SHIFT    32
+/** Selector mask for use after shifting. */
+#define  MSR_K6_STAR_SEL_MASK               UINT32_C(0xffff)
+/** The mask which give the SYSCALL EIP. */
+#define  MSR_K6_STAR_SYSCALL_EIP_MASK       UINT32_C(0xffffffff)
+/** K6 WHCR - Write Handling Control Register. */
+#define MSR_K6_WHCR                         UINT32_C(0xc0000082)
+/** K6 UWCCR - UC/WC Cacheability Control Register. */
+#define MSR_K6_UWCCR                        UINT32_C(0xc0000085)
+/** K6 PSOR - Processor State Observability Register. */
+#define MSR_K6_PSOR                         UINT32_C(0xc0000087)
+/** K6 PFIR - Page Flush/Invalidate Register. */
+#define MSR_K6_PFIR                         UINT32_C(0xc0000088)
+
+/** Performance counter MSRs. (AMD only) */
+#define MSR_K7_EVNTSEL0                     UINT32_C(0xc0010000)
+#define MSR_K7_EVNTSEL1                     UINT32_C(0xc0010001)
+#define MSR_K7_EVNTSEL2                     UINT32_C(0xc0010002)
+#define MSR_K7_EVNTSEL3                     UINT32_C(0xc0010003)
+#define MSR_K7_PERFCTR0                     UINT32_C(0xc0010004)
+#define MSR_K7_PERFCTR1                     UINT32_C(0xc0010005)
+#define MSR_K7_PERFCTR2                     UINT32_C(0xc0010006)
+#define MSR_K7_PERFCTR3                     UINT32_C(0xc0010007)
+
+/** K8 LSTAR - Long mode SYSCALL target (RIP). */
+#define MSR_K8_LSTAR                        UINT32_C(0xc0000082)
+/** K8 CSTAR - Compatibility mode SYSCALL target (RIP). */
+#define MSR_K8_CSTAR                        UINT32_C(0xc0000083)
+/** K8 SF_MASK - SYSCALL flag mask. (aka SFMASK) */
+#define MSR_K8_SF_MASK                      UINT32_C(0xc0000084)
+/** K8 FS.base - The 64-bit base FS register. */
+#define MSR_K8_FS_BASE                      UINT32_C(0xc0000100)
+/** K8 GS.base - The 64-bit base GS register. */
+#define MSR_K8_GS_BASE                      UINT32_C(0xc0000101)
+/** K8 KernelGSbase - Used with SWAPGS. */
+#define MSR_K8_KERNEL_GS_BASE               UINT32_C(0xc0000102)
+/** K8 TSC_AUX - Used with RDTSCP. */
+#define MSR_K8_TSC_AUX                      UINT32_C(0xc0000103)
+#define MSR_K8_SYSCFG                       UINT32_C(0xc0010010)
+#define MSR_K8_HWCR                         UINT32_C(0xc0010015)
+#define MSR_K8_IORRBASE0                    UINT32_C(0xc0010016)
+#define MSR_K8_IORRMASK0                    UINT32_C(0xc0010017)
+#define MSR_K8_IORRBASE1                    UINT32_C(0xc0010018)
+#define MSR_K8_IORRMASK1                    UINT32_C(0xc0010019)
+#define MSR_K8_TOP_MEM1                     UINT32_C(0xc001001a)
+#define MSR_K8_TOP_MEM2                     UINT32_C(0xc001001d)
+/** North bridge config? See BIOS & Kernel dev guides for
+ * details. */
+#define MSR_K8_NB_CFG                       UINT32_C(0xc001001f)
+
+/** Hypertransport interrupt pending register.
+ * "BIOS and Kernel Developer's Guide for AMD NPT Family 0Fh Processors" */
+#define MSR_K8_INT_PENDING                  UINT32_C(0xc0010055)
+
+/** SVM Control. */
+#define MSR_K8_VM_CR                        UINT32_C(0xc0010114)
+/** Disables HDT (Hardware Debug Tool) and certain internal debug
+ *  features. */
+#define MSR_K8_VM_CR_DPD                    RT_BIT_32(0)
+/** If set, non-intercepted INIT signals are converted to \#SX
+ *  exceptions. */
+#define MSR_K8_VM_CR_R_INIT                 RT_BIT_32(1)
+/** Disables A20 masking.  */
+#define MSR_K8_VM_CR_DIS_A20M               RT_BIT_32(2)
+/** Lock bit for this MSR controlling bits 3 (LOCK) and 4 (SVMDIS). */
+#define MSR_K8_VM_CR_LOCK                   RT_BIT_32(3)
+/** SVM disable. When set, writes to EFER.SVME are treated as MBZ. When
+ *  clear, EFER.SVME can be written normally. */
+#define MSR_K8_VM_CR_SVM_DISABLE            RT_BIT_32(4)
+
+#define MSR_K8_IGNNE                        UINT32_C(0xc0010115)
+#define MSR_K8_SMM_CTL                      UINT32_C(0xc0010116)
+/** SVM - VM_HSAVE_PA - Physical address for saving and restoring
+ *                      host state during world switch. */
+#define MSR_K8_VM_HSAVE_PA                  UINT32_C(0xc0010117)
+
+/** @} */
+
+
+/** @name Page Table / Directory / Directory Pointers / L4.
+ * @{
+ */
+
+/** Page table/directory  entry as an unsigned integer. */
+typedef uint32_t X86PGUINT;
+/** Pointer to a page table/directory table entry as an unsigned integer. */
+typedef X86PGUINT *PX86PGUINT;
+/** Pointer to an const page table/directory table entry as an unsigned integer. */
+typedef X86PGUINT const *PCX86PGUINT;
+
+/** Number of entries in a 32-bit PT/PD. */
+#define X86_PG_ENTRIES                      1024
+
+
+/** PAE page table/page directory/pdpt/l4/l5 entry as an unsigned integer. */
+typedef uint64_t X86PGPAEUINT;
+/** Pointer to a PAE page table/page directory/pdpt/l4/l5 entry as an unsigned integer. */
+typedef X86PGPAEUINT *PX86PGPAEUINT;
+/** Pointer to an const PAE page table/page directory/pdpt/l4/l5 entry as an unsigned integer. */
+typedef X86PGPAEUINT const *PCX86PGPAEUINT;
+
+/** Number of entries in a PAE PT/PD. */
+#define X86_PG_PAE_ENTRIES                  512
+/** Number of entries in a PAE PDPT. */
+#define X86_PG_PAE_PDPE_ENTRIES             4
+
+/** Number of entries in an AMD64 PT/PD/PDPT/L4/L5. */
+#define X86_PG_AMD64_ENTRIES                X86_PG_PAE_ENTRIES
+/** Number of entries in an AMD64 PDPT.
+ * Just for complementing X86_PG_PAE_PDPE_ENTRIES, using X86_PG_AMD64_ENTRIES for this is fine too. */
+#define X86_PG_AMD64_PDPE_ENTRIES           X86_PG_AMD64_ENTRIES
+
+/** The size of a default page. */
+#define X86_PAGE_SIZE                       X86_PAGE_4K_SIZE
+/** The page shift of a default page. */
+#define X86_PAGE_SHIFT                      X86_PAGE_4K_SHIFT
+/** The default page offset mask. */
+#define X86_PAGE_OFFSET_MASK                X86_PAGE_4K_OFFSET_MASK
+/** The default page base mask for virtual addresses. */
+#define X86_PAGE_BASE_MASK                  X86_PAGE_4K_BASE_MASK
+/** The default page base mask for virtual addresses - 32bit version. */
+#define X86_PAGE_BASE_MASK_32               X86_PAGE_4K_BASE_MASK_32
+
+/** The size of a 4KB page. */
+#define X86_PAGE_4K_SIZE                    _4K
+/** The page shift of a 4KB page. */
+#define X86_PAGE_4K_SHIFT                   12
+/** The 4KB page offset mask. */
+#define X86_PAGE_4K_OFFSET_MASK             0xfff
+/** The 4KB page base mask for virtual addresses. */
+#define X86_PAGE_4K_BASE_MASK               0xfffffffffffff000ULL
+/** The 4KB page base mask for virtual addresses - 32bit version. */
+#define X86_PAGE_4K_BASE_MASK_32            0xfffff000U
+
+/** The size of a 2MB page. */
+#define X86_PAGE_2M_SIZE                    _2M
+/** The page shift of a 2MB page. */
+#define X86_PAGE_2M_SHIFT                   21
+/** The 2MB page offset mask. */
+#define X86_PAGE_2M_OFFSET_MASK             0x001fffff
+/** The 2MB page base mask for virtual addresses. */
+#define X86_PAGE_2M_BASE_MASK               0xffffffffffe00000ULL
+/** The 2MB page base mask for virtual addresses - 32bit version. */
+#define X86_PAGE_2M_BASE_MASK_32            0xffe00000U
+
+/** The size of a 4MB page. */
+#define X86_PAGE_4M_SIZE                    _4M
+/** The page shift of a 4MB page. */
+#define X86_PAGE_4M_SHIFT                   22
+/** The 4MB page offset mask. */
+#define X86_PAGE_4M_OFFSET_MASK             0x003fffff
+/** The 4MB page base mask for virtual addresses. */
+#define X86_PAGE_4M_BASE_MASK               0xffffffffffc00000ULL
+/** The 4MB page base mask for virtual addresses - 32bit version. */
+#define X86_PAGE_4M_BASE_MASK_32            0xffc00000U
+
+/**
+ * Check if the given address is canonical.
+ */
+#define X86_IS_CANONICAL(a_u64Addr)         ((uint64_t)(a_u64Addr) + UINT64_C(0x800000000000) < UINT64_C(0x1000000000000))
+
+
+/** @name Page Table Entry
+ * @{
+ */
+/** Bit 0 -  P  - Present bit. */
+#define X86_PTE_BIT_P                       0
+/** Bit 1 - R/W - Read (clear) / Write (set) bit. */
+#define X86_PTE_BIT_RW                      1
+/** Bit 2 - U/S - User (set) / Supervisor (clear) bit. */
+#define X86_PTE_BIT_US                      2
+/** Bit 3 - PWT - Page level write thru bit. */
+#define X86_PTE_BIT_PWT                     3
+/** Bit 4 - PCD - Page level cache disable bit. */
+#define X86_PTE_BIT_PCD                     4
+/** Bit 5 -  A  - Access bit. */
+#define X86_PTE_BIT_A                       5
+/** Bit 6 -  D  - Dirty bit. */
+#define X86_PTE_BIT_D                       6
+/** Bit 7 - PAT - Page Attribute Table index bit. Reserved and 0 if not supported. */
+#define X86_PTE_BIT_PAT                     7
+/** Bit 8 -  G  - Global flag. */
+#define X86_PTE_BIT_G                       8
+/** Bits 63 - NX - PAE/LM - No execution flag. */
+#define X86_PTE_PAE_BIT_NX                  63
+
+/** Bit 0 -  P  - Present bit mask. */
+#define X86_PTE_P                           RT_BIT_32(0)
+/** Bit 1 - R/W - Read (clear) / Write (set) bit mask. */
+#define X86_PTE_RW                          RT_BIT_32(1)
+/** Bit 2 - U/S - User (set) / Supervisor (clear) bit mask. */
+#define X86_PTE_US                          RT_BIT_32(2)
+/** Bit 3 - PWT - Page level write thru bit mask. */
+#define X86_PTE_PWT                         RT_BIT_32(3)
+/** Bit 4 - PCD - Page level cache disable bit mask. */
+#define X86_PTE_PCD                         RT_BIT_32(4)
+/** Bit 5 -  A  - Access bit mask. */
+#define X86_PTE_A                           RT_BIT_32(5)
+/** Bit 6 -  D  - Dirty bit mask. */
+#define X86_PTE_D                           RT_BIT_32(6)
+/** Bit 7 - PAT - Page Attribute Table index bit mask. Reserved and 0 if not supported. */
+#define X86_PTE_PAT                         RT_BIT_32(7)
+/** Bit 8 -  G  - Global bit mask. */
+#define X86_PTE_G                           RT_BIT_32(8)
+
+/** Bits 9-11 - - Available for use to system software. */
+#define X86_PTE_AVL_MASK                    (RT_BIT_32(9) | RT_BIT_32(10) | RT_BIT_32(11))
+/** Bits 12-31 - - Physical Page number of the next level. */
+#define X86_PTE_PG_MASK                     ( 0xfffff000 )
+
+/** Bits 12-51 - - PAE - Physical Page number of the next level. */
+#define X86_PTE_PAE_PG_MASK                 UINT64_C(0x000ffffffffff000)
+/** Bits 63 - NX - PAE/LM - No execution flag. */
+#define X86_PTE_PAE_NX                      RT_BIT_64(63)
+/** Bits 62-52 - - PAE - MBZ bits when NX is active. */
+#define X86_PTE_PAE_MBZ_MASK_NX             UINT64_C(0x7ff0000000000000)
+/** Bits 63-52 - - PAE - MBZ bits when no NX. */
+#define X86_PTE_PAE_MBZ_MASK_NO_NX          UINT64_C(0xfff0000000000000)
+/** No bits -    - LM  - MBZ bits when NX is active. */
+#define X86_PTE_LM_MBZ_MASK_NX              UINT64_C(0x0000000000000000)
+/** Bits 63 -    - LM  - MBZ bits when no NX. */
+#define X86_PTE_LM_MBZ_MASK_NO_NX           UINT64_C(0x8000000000000000)
+
+/**
+ * Page table entry.
+ */
+typedef struct X86PTEBITS
+{
+    /** Flags whether(=1) or not the page is present. */
+    uint32_t    u1Present : 1;
+    /** Read(=0) / Write(=1) flag. */
+    uint32_t    u1Write : 1;
+    /** User(=1) / Supervisor (=0) flag. */
+    uint32_t    u1User : 1;
+    /** Write Thru flag. If PAT enabled, bit 0 of the index. */
+    uint32_t    u1WriteThru : 1;
+    /** Cache disabled flag. If PAT enabled, bit 1 of the index. */
+    uint32_t    u1CacheDisable : 1;
+    /** Accessed flag.
+     * Indicates that the page have been read or written to. */
+    uint32_t    u1Accessed : 1;
+    /** Dirty flag.
+     * Indicates that the page has been written to. */
+    uint32_t    u1Dirty : 1;
+    /** Reserved / If PAT enabled, bit 2 of the index.  */
+    uint32_t    u1PAT : 1;
+    /** Global flag. (Ignored in all but final level.) */
+    uint32_t    u1Global : 1;
+    /** Available for use to system software. */
+    uint32_t    u3Available : 3;
+    /** Physical Page number of the next level. */
+    uint32_t    u20PageNo : 20;
+} X86PTEBITS;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PTEBITS, 4);
+#endif
+/** Pointer to a page table entry. */
+typedef X86PTEBITS *PX86PTEBITS;
+/** Pointer to a const page table entry. */
+typedef const X86PTEBITS *PCX86PTEBITS;
+
+/**
+ * Page table entry.
+ */
+typedef union X86PTE
+{
+    /** Unsigned integer view */
+    X86PGUINT       u;
+    /** Bit field view. */
+    X86PTEBITS      n;
+    /** 32-bit view. */
+    uint32_t        au32[1];
+    /** 16-bit view. */
+    uint16_t        au16[2];
+    /** 8-bit view. */
+    uint8_t         au8[4];
+} X86PTE;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PTE, 4);
+#endif
+/** Pointer to a page table entry. */
+typedef X86PTE *PX86PTE;
+/** Pointer to a const page table entry. */
+typedef const X86PTE *PCX86PTE;
+
+
+/**
+ * PAE page table entry.
+ */
+typedef struct X86PTEPAEBITS
+{
+    /** Flags whether(=1) or not the page is present. */
+    uint32_t    u1Present : 1;
+    /** Read(=0) / Write(=1) flag. */
+    uint32_t    u1Write : 1;
+    /** User(=1) / Supervisor(=0) flag. */
+    uint32_t    u1User : 1;
+    /** Write Thru flag. If PAT enabled, bit 0 of the index. */
+    uint32_t    u1WriteThru : 1;
+    /** Cache disabled flag. If PAT enabled, bit 1 of the index. */
+    uint32_t    u1CacheDisable : 1;
+    /** Accessed flag.
+     * Indicates that the page have been read or written to. */
+    uint32_t    u1Accessed : 1;
+    /** Dirty flag.
+     * Indicates that the page has been written to. */
+    uint32_t    u1Dirty : 1;
+    /** Reserved / If PAT enabled, bit 2 of the index.  */
+    uint32_t    u1PAT : 1;
+    /** Global flag. (Ignored in all but final level.) */
+    uint32_t    u1Global : 1;
+    /** Available for use to system software. */
+    uint32_t    u3Available : 3;
+    /** Physical Page number of the next level - Low Part. Don't use this. */
+    uint32_t    u20PageNoLow : 20;
+    /** Physical Page number of the next level - High Part. Don't use this. */
+    uint32_t    u20PageNoHigh : 20;
+    /** MBZ bits */
+    uint32_t    u11Reserved : 11;
+    /** No Execute flag. */
+    uint32_t    u1NoExecute : 1;
+} X86PTEPAEBITS;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PTEPAEBITS, 8);
+#endif
+/** Pointer to a page table entry. */
+typedef X86PTEPAEBITS *PX86PTEPAEBITS;
+/** Pointer to a page table entry. */
+typedef const X86PTEPAEBITS *PCX86PTEPAEBITS;
+
+/**
+ * PAE Page table entry.
+ */
+typedef union X86PTEPAE
+{
+    /** Unsigned integer view */
+    X86PGPAEUINT    u;
+    /** Bit field view. */
+    X86PTEPAEBITS   n;
+    /** 32-bit view. */
+    uint32_t        au32[2];
+    /** 16-bit view. */
+    uint16_t        au16[4];
+    /** 8-bit view. */
+    uint8_t         au8[8];
+} X86PTEPAE;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PTEPAE, 8);
+#endif
+/** Pointer to a PAE page table entry. */
+typedef X86PTEPAE *PX86PTEPAE;
+/** Pointer to a const PAE page table entry. */
+typedef const X86PTEPAE *PCX86PTEPAE;
+/** @} */
+
+/**
+ * Page table.
+ */
+typedef struct X86PT
+{
+    /** PTE Array. */
+    X86PTE     a[X86_PG_ENTRIES];
+} X86PT;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PT, 4096);
+#endif
+/** Pointer to a page table. */
+typedef X86PT *PX86PT;
+/** Pointer to a const page table. */
+typedef const X86PT *PCX86PT;
+
+/** The page shift to get the PT index. */
+#define X86_PT_SHIFT                        12
+/** The PT index mask (apply to a shifted page address). */
+#define X86_PT_MASK                         0x3ff
+
+
+/**
+ * Page directory.
+ */
+typedef struct X86PTPAE
+{
+    /** PTE Array. */
+    X86PTEPAE  a[X86_PG_PAE_ENTRIES];
+} X86PTPAE;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PTPAE, 4096);
+#endif
+/** Pointer to a page table. */
+typedef X86PTPAE *PX86PTPAE;
+/** Pointer to a const page table. */
+typedef const X86PTPAE *PCX86PTPAE;
+
+/** The page shift to get the PA PTE index. */
+#define X86_PT_PAE_SHIFT                    12
+/** The PAE PT index mask (apply to a shifted page address). */
+#define X86_PT_PAE_MASK                     0x1ff
+
+
+/** @name 4KB Page Directory Entry
+ * @{
+ */
+/** Bit 0 -  P  - Present bit. */
+#define X86_PDE_P                           RT_BIT_32(0)
+/** Bit 1 - R/W - Read (clear) / Write (set) bit. */
+#define X86_PDE_RW                          RT_BIT_32(1)
+/** Bit 2 - U/S - User (set) / Supervisor (clear) bit. */
+#define X86_PDE_US                          RT_BIT_32(2)
+/** Bit 3 - PWT - Page level write thru bit. */
+#define X86_PDE_PWT                         RT_BIT_32(3)
+/** Bit 4 - PCD - Page level cache disable bit. */
+#define X86_PDE_PCD                         RT_BIT_32(4)
+/** Bit 5 -  A  - Access bit. */
+#define X86_PDE_A                           RT_BIT_32(5)
+/** Bit 7 - PS  - Page size attribute.
+ * Clear mean 4KB pages, set means large pages (2/4MB). */
+#define X86_PDE_PS                          RT_BIT_32(7)
+/** Bits 9-11 - - Available for use to system software. */
+#define X86_PDE_AVL_MASK                    (RT_BIT_32(9) | RT_BIT_32(10) | RT_BIT_32(11))
+/** Bits 12-31 -  - Physical Page number of the next level. */
+#define X86_PDE_PG_MASK                     ( 0xfffff000 )
+
+/** Bits 12-51 - - PAE - Physical Page number of the next level. */
+#define X86_PDE_PAE_PG_MASK                 UINT64_C(0x000ffffffffff000)
+/** Bits 63 - NX - PAE/LM - No execution flag. */
+#define X86_PDE_PAE_NX                      RT_BIT_64(63)
+/** Bits 62-52, 7 - - PAE - MBZ bits when NX is active. */
+#define X86_PDE_PAE_MBZ_MASK_NX             UINT64_C(0x7ff0000000000080)
+/** Bits 63-52, 7 - - PAE - MBZ bits when no NX. */
+#define X86_PDE_PAE_MBZ_MASK_NO_NX          UINT64_C(0xfff0000000000080)
+/** Bit 7 -         - LM  - MBZ bits when NX is active. */
+#define X86_PDE_LM_MBZ_MASK_NX              UINT64_C(0x0000000000000080)
+/** Bits 63, 7 -    - LM  - MBZ bits when no NX. */
+#define X86_PDE_LM_MBZ_MASK_NO_NX           UINT64_C(0x8000000000000080)
+
+/**
+ * Page directory entry.
+ */
+typedef struct X86PDEBITS
+{
+    /** Flags whether(=1) or not the page is present. */
+    uint32_t    u1Present : 1;
+    /** Read(=0) / Write(=1) flag. */
+    uint32_t    u1Write : 1;
+    /** User(=1) / Supervisor (=0) flag. */
+    uint32_t    u1User : 1;
+    /** Write Thru flag. If PAT enabled, bit 0 of the index. */
+    uint32_t    u1WriteThru : 1;
+    /** Cache disabled flag. If PAT enabled, bit 1 of the index. */
+    uint32_t    u1CacheDisable : 1;
+    /** Accessed flag.
+     * Indicates that the page has been read or written to. */
+    uint32_t    u1Accessed : 1;
+    /** Reserved / Ignored (dirty bit). */
+    uint32_t    u1Reserved0 : 1;
+    /** Size bit if PSE is enabled - in any event it's 0. */
+    uint32_t    u1Size : 1;
+    /** Reserved / Ignored (global bit). */
+    uint32_t    u1Reserved1 : 1;
+    /** Available for use to system software. */
+    uint32_t    u3Available : 3;
+    /** Physical Page number of the next level. */
+    uint32_t    u20PageNo : 20;
+} X86PDEBITS;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PDEBITS, 4);
+#endif
+/** Pointer to a page directory entry. */
+typedef X86PDEBITS *PX86PDEBITS;
+/** Pointer to a const page directory entry. */
+typedef const X86PDEBITS *PCX86PDEBITS;
+
+
+/**
+ * PAE page directory entry.
+ */
+typedef struct X86PDEPAEBITS
+{
+    /** Flags whether(=1) or not the page is present. */
+    uint32_t    u1Present : 1;
+    /** Read(=0) / Write(=1) flag. */
+    uint32_t    u1Write : 1;
+    /** User(=1) / Supervisor (=0) flag. */
+    uint32_t    u1User : 1;
+    /** Write Thru flag. If PAT enabled, bit 0 of the index. */
+    uint32_t    u1WriteThru : 1;
+    /** Cache disabled flag. If PAT enabled, bit 1 of the index. */
+    uint32_t    u1CacheDisable : 1;
+    /** Accessed flag.
+     * Indicates that the page has been read or written to. */
+    uint32_t    u1Accessed : 1;
+    /** Reserved / Ignored (dirty bit). */
+    uint32_t    u1Reserved0 : 1;
+    /** Size bit if PSE is enabled - in any event it's 0. */
+    uint32_t    u1Size : 1;
+    /** Reserved / Ignored (global bit). /  */
+    uint32_t    u1Reserved1 : 1;
+    /** Available for use to system software. */
+    uint32_t    u3Available : 3;
+    /** Physical Page number of the next level - Low Part. Don't use! */
+    uint32_t    u20PageNoLow : 20;
+    /** Physical Page number of the next level - High Part. Don't use! */
+    uint32_t    u20PageNoHigh : 20;
+    /** MBZ bits */
+    uint32_t    u11Reserved : 11;
+    /** No Execute flag. */
+    uint32_t    u1NoExecute : 1;
+} X86PDEPAEBITS;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PDEPAEBITS, 8);
+#endif
+/** Pointer to a page directory entry. */
+typedef X86PDEPAEBITS *PX86PDEPAEBITS;
+/** Pointer to a const page directory entry. */
+typedef const X86PDEPAEBITS *PCX86PDEPAEBITS;
+
+/** @} */
+
+
+/** @name 2/4MB Page Directory Entry
+ * @{
+ */
+/** Bit 0 -  P  - Present bit. */
+#define X86_PDE4M_P                         RT_BIT_32(0)
+/** Bit 1 - R/W - Read (clear) / Write (set) bit. */
+#define X86_PDE4M_RW                        RT_BIT_32(1)
+/** Bit 2 - U/S - User (set) / Supervisor (clear) bit. */
+#define X86_PDE4M_US                        RT_BIT_32(2)
+/** Bit 3 - PWT - Page level write thru bit. */
+#define X86_PDE4M_PWT                       RT_BIT_32(3)
+/** Bit 4 - PCD - Page level cache disable bit. */
+#define X86_PDE4M_PCD                       RT_BIT_32(4)
+/** Bit 5 -  A  - Access bit. */
+#define X86_PDE4M_A                         RT_BIT_32(5)
+/** Bit 6 -  D  - Dirty bit. */
+#define X86_PDE4M_D                         RT_BIT_32(6)
+/** Bit 7 - PS  - Page size attribute. Clear mean 4KB pages, set means large pages (2/4MB). */
+#define X86_PDE4M_PS                        RT_BIT_32(7)
+/** Bit 8 -  G  - Global flag. */
+#define X86_PDE4M_G                         RT_BIT_32(8)
+/** Bits 9-11 - AVL - Available for use to system software. */
+#define X86_PDE4M_AVL                       (RT_BIT_32(9) | RT_BIT_32(10) | RT_BIT_32(11))
+/** Bit 12 - PAT - Page Attribute Table index bit. Reserved and 0 if not supported. */
+#define X86_PDE4M_PAT                       RT_BIT_32(12)
+/** Shift to get from X86_PTE_PAT to X86_PDE4M_PAT. */
+#define X86_PDE4M_PAT_SHIFT                 (12 - 7)
+/** Bits 22-31 - - Physical Page number. */
+#define X86_PDE4M_PG_MASK                   ( 0xffc00000 )
+/** Bits 20-13 - - Physical Page number high part (32-39 bits). AMD64 hack. */
+#define X86_PDE4M_PG_HIGH_MASK              ( 0x001fe000 )
+/** The number of bits to the high part of the page number. */
+#define X86_PDE4M_PG_HIGH_SHIFT             19
+/** Bit 21 -     - MBZ bits for AMD CPUs, no PSE36. */
+#define X86_PDE4M_MBZ_MASK                  RT_BIT_32(21)
+
+/** Bits 21-51 - - PAE/LM - Physical Page number.
+ * (Bits 40-51 (long mode) & bits 36-51 (pae legacy) are reserved according to the Intel docs; AMD allows for more.) */
+#define X86_PDE2M_PAE_PG_MASK               UINT64_C(0x000fffffffe00000)
+/** Bits 63 - NX - PAE/LM - No execution flag. */
+#define X86_PDE2M_PAE_NX                    RT_BIT_64(63)
+/** Bits 62-52, 20-13 - - PAE - MBZ bits when NX is active. */
+#define X86_PDE2M_PAE_MBZ_MASK_NX           UINT64_C(0x7ff00000001fe000)
+/** Bits 63-52, 20-13 - - PAE - MBZ bits when no NX. */
+#define X86_PDE2M_PAE_MBZ_MASK_NO_NX        UINT64_C(0xfff00000001fe000)
+/** Bits 20-13        - - LM  - MBZ bits when NX is active. */
+#define X86_PDE2M_LM_MBZ_MASK_NX            UINT64_C(0x00000000001fe000)
+/** Bits 63, 20-13    - - LM  - MBZ bits when no NX. */
+#define X86_PDE2M_LM_MBZ_MASK_NO_NX         UINT64_C(0x80000000001fe000)
+
+/**
+ * 4MB page directory entry.
+ */
+typedef struct X86PDE4MBITS
+{
+    /** Flags whether(=1) or not the page is present. */
+    uint32_t    u1Present : 1;
+    /** Read(=0) / Write(=1) flag. */
+    uint32_t    u1Write : 1;
+    /** User(=1) / Supervisor (=0) flag. */
+    uint32_t    u1User : 1;
+    /** Write Thru flag. If PAT enabled, bit 0 of the index. */
+    uint32_t    u1WriteThru : 1;
+    /** Cache disabled flag. If PAT enabled, bit 1 of the index. */
+    uint32_t    u1CacheDisable : 1;
+    /** Accessed flag.
+     * Indicates that the page have been read or written to. */
+    uint32_t    u1Accessed : 1;
+    /** Dirty flag.
+     * Indicates that the page has been written to. */
+    uint32_t    u1Dirty : 1;
+    /** Page size flag - always 1 for 4MB entries. */
+    uint32_t    u1Size : 1;
+    /** Global flag.  */
+    uint32_t    u1Global : 1;
+    /** Available for use to system software. */
+    uint32_t    u3Available : 3;
+    /** Reserved / If PAT enabled, bit 2 of the index.  */
+    uint32_t    u1PAT : 1;
+    /** Bits 32-39 of the page number on AMD64.
+     * This AMD64 hack allows accessing 40bits of physical memory without PAE. */
+    uint32_t    u8PageNoHigh : 8;
+    /** Reserved. */
+    uint32_t    u1Reserved : 1;
+    /** Physical Page number of the page. */
+    uint32_t    u10PageNo : 10;
+} X86PDE4MBITS;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PDE4MBITS, 4);
+#endif
+/** Pointer to a page table entry. */
+typedef X86PDE4MBITS *PX86PDE4MBITS;
+/** Pointer to a const page table entry. */
+typedef const X86PDE4MBITS *PCX86PDE4MBITS;
+
+
+/**
+ * 2MB PAE page directory entry.
+ */
+typedef struct X86PDE2MPAEBITS
+{
+    /** Flags whether(=1) or not the page is present. */
+    uint32_t    u1Present : 1;
+    /** Read(=0) / Write(=1) flag. */
+    uint32_t    u1Write : 1;
+    /** User(=1) / Supervisor(=0) flag. */
+    uint32_t    u1User : 1;
+    /** Write Thru flag. If PAT enabled, bit 0 of the index. */
+    uint32_t    u1WriteThru : 1;
+    /** Cache disabled flag. If PAT enabled, bit 1 of the index. */
+    uint32_t    u1CacheDisable : 1;
+    /** Accessed flag.
+     * Indicates that the page have been read or written to. */
+    uint32_t    u1Accessed : 1;
+    /** Dirty flag.
+     * Indicates that the page has been written to. */
+    uint32_t    u1Dirty : 1;
+    /** Page size flag - always 1 for 2MB entries. */
+    uint32_t    u1Size : 1;
+    /** Global flag.  */
+    uint32_t    u1Global : 1;
+    /** Available for use to system software. */
+    uint32_t    u3Available : 3;
+    /** Reserved / If PAT enabled, bit 2 of the index.  */
+    uint32_t    u1PAT : 1;
+    /** Reserved. */
+    uint32_t    u9Reserved : 9;
+    /** Physical Page number of the next level - Low part. Don't use! */
+    uint32_t    u10PageNoLow : 10;
+    /** Physical Page number of the next level - High part. Don't use! */
+    uint32_t    u20PageNoHigh : 20;
+    /** MBZ bits */
+    uint32_t    u11Reserved : 11;
+    /** No Execute flag. */
+    uint32_t    u1NoExecute : 1;
+} X86PDE2MPAEBITS;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PDE2MPAEBITS, 8);
+#endif
+/** Pointer to a 2MB PAE page table entry. */
+typedef X86PDE2MPAEBITS *PX86PDE2MPAEBITS;
+/** Pointer to a 2MB PAE page table entry. */
+typedef const X86PDE2MPAEBITS *PCX86PDE2MPAEBITS;
+
+/** @} */
+
+/**
+ * Page directory entry.
+ */
+typedef union X86PDE
+{
+    /** Unsigned integer view. */
+    X86PGUINT       u;
+    /** Normal view. */
+    X86PDEBITS      n;
+    /** 4MB view (big). */
+    X86PDE4MBITS    b;
+    /** 8 bit unsigned integer view. */
+    uint8_t         au8[4];
+    /** 16 bit unsigned integer view. */
+    uint16_t        au16[2];
+    /** 32 bit unsigned integer view. */
+    uint32_t        au32[1];
+} X86PDE;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PDE, 4);
+#endif
+/** Pointer to a page directory entry. */
+typedef X86PDE *PX86PDE;
+/** Pointer to a const page directory entry. */
+typedef const X86PDE *PCX86PDE;
+
+/**
+ * PAE page directory entry.
+ */
+typedef union X86PDEPAE
+{
+    /** Unsigned integer view. */
+    X86PGPAEUINT    u;
+    /** Normal view. */
+    X86PDEPAEBITS   n;
+    /** 2MB page view (big). */
+    X86PDE2MPAEBITS b;
+    /** 8 bit unsigned integer view. */
+    uint8_t         au8[8];
+    /** 16 bit unsigned integer view. */
+    uint16_t        au16[4];
+    /** 32 bit unsigned integer view. */
+    uint32_t        au32[2];
+} X86PDEPAE;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PDEPAE, 8);
+#endif
+/** Pointer to a page directory entry. */
+typedef X86PDEPAE *PX86PDEPAE;
+/** Pointer to a const page directory entry. */
+typedef const X86PDEPAE *PCX86PDEPAE;
+
+/**
+ * Page directory.
+ */
+typedef struct X86PD
+{
+    /** PDE Array. */
+    X86PDE      a[X86_PG_ENTRIES];
+} X86PD;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PD, 4096);
+#endif
+/** Pointer to a page directory. */
+typedef X86PD *PX86PD;
+/** Pointer to a const page directory. */
+typedef const X86PD *PCX86PD;
+
+/** The page shift to get the PD index. */
+#define X86_PD_SHIFT                        22
+/** The PD index mask (apply to a shifted page address). */
+#define X86_PD_MASK                         0x3ff
+
+
+/**
+ * PAE page directory.
+ */
+typedef struct X86PDPAE
+{
+    /** PDE Array. */
+    X86PDEPAE   a[X86_PG_PAE_ENTRIES];
+} X86PDPAE;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PDPAE, 4096);
+#endif
+/** Pointer to a PAE page directory. */
+typedef X86PDPAE *PX86PDPAE;
+/** Pointer to a const PAE page directory. */
+typedef const X86PDPAE *PCX86PDPAE;
+
+/** The page shift to get the PAE PD index. */
+#define X86_PD_PAE_SHIFT                    21
+/** The PAE PD index mask (apply to a shifted page address). */
+#define X86_PD_PAE_MASK                     0x1ff
+
+
+/** @name Page Directory Pointer Table Entry (PAE)
+ * @{
+ */
+/** Bit 0 -  P  - Present bit. */
+#define X86_PDPE_P                          RT_BIT_32(0)
+/** Bit 1 - R/W - Read (clear) / Write (set) bit. Long Mode only. */
+#define X86_PDPE_RW                         RT_BIT_32(1)
+/** Bit 2 - U/S - User (set) / Supervisor (clear) bit. Long Mode only. */
+#define X86_PDPE_US                         RT_BIT_32(2)
+/** Bit 3 - PWT - Page level write thru bit. */
+#define X86_PDPE_PWT                        RT_BIT_32(3)
+/** Bit 4 - PCD - Page level cache disable bit. */
+#define X86_PDPE_PCD                        RT_BIT_32(4)
+/** Bit 5 -  A  - Access bit. Long Mode only. */
+#define X86_PDPE_A                          RT_BIT_32(5)
+/** Bit 7 - PS  - Page size (1GB). Long Mode only. */
+#define X86_PDPE_LM_PS                      RT_BIT_32(7)
+/** Bits 9-11 - - Available for use to system software. */
+#define X86_PDPE_AVL_MASK                   (RT_BIT_32(9) | RT_BIT_32(10) | RT_BIT_32(11))
+/** Bits 12-51 - - PAE - Physical Page number of the next level. */
+#define X86_PDPE_PG_MASK                    UINT64_C(0x000ffffffffff000)
+/** Bits 63-52, 8-5, 2-1 - - PAE - MBZ bits (NX is long mode only). */
+#define X86_PDPE_PAE_MBZ_MASK               UINT64_C(0xfff00000000001e6)
+/** Bits 63 - NX - LM - No execution flag. Long Mode only. */
+#define X86_PDPE_LM_NX                      RT_BIT_64(63)
+/** Bits 8, 7 - - LM - MBZ bits when NX is active. */
+#define X86_PDPE_LM_MBZ_MASK_NX             UINT64_C(0x0000000000000180)
+/** Bits 63, 8, 7 - - LM - MBZ bits when no NX. */
+#define X86_PDPE_LM_MBZ_MASK_NO_NX          UINT64_C(0x8000000000000180)
+/** Bits 29-13 - - LM - MBZ bits for 1GB page entry when NX is active. */
+#define X86_PDPE1G_LM_MBZ_MASK_NX           UINT64_C(0x000000003fffe000)
+/** Bits 63, 29-13 - - LM - MBZ bits for 1GB page entry when no NX. */
+#define X86_PDPE1G_LM_MBZ_MASK_NO_NX        UINT64_C(0x800000003fffe000)
+
+
+/**
+ * Page directory pointer table entry.
+ */
+typedef struct X86PDPEBITS
+{
+    /** Flags whether(=1) or not the page is present. */
+    uint32_t    u1Present : 1;
+    /** Chunk of reserved bits. */
+    uint32_t    u2Reserved : 2;
+    /** Write Thru flag. If PAT enabled, bit 0 of the index. */
+    uint32_t    u1WriteThru : 1;
+    /** Cache disabled flag. If PAT enabled, bit 1 of the index. */
+    uint32_t    u1CacheDisable : 1;
+    /** Chunk of reserved bits. */
+    uint32_t    u4Reserved : 4;
+    /** Available for use to system software. */
+    uint32_t    u3Available : 3;
+    /** Physical Page number of the next level - Low Part. Don't use! */
+    uint32_t    u20PageNoLow : 20;
+    /** Physical Page number of the next level - High Part. Don't use! */
+    uint32_t    u20PageNoHigh : 20;
+    /** MBZ bits */
+    uint32_t    u12Reserved : 12;
+} X86PDPEBITS;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PDPEBITS, 8);
+#endif
+/** Pointer to a page directory pointer table entry. */
+typedef X86PDPEBITS *PX86PTPEBITS;
+/** Pointer to a const page directory pointer table entry. */
+typedef const X86PDPEBITS *PCX86PTPEBITS;
+
+/**
+ * Page directory pointer table entry. AMD64 version
+ */
+typedef struct X86PDPEAMD64BITS
+{
+    /** Flags whether(=1) or not the page is present. */
+    uint32_t    u1Present : 1;
+    /** Read(=0) / Write(=1) flag. */
+    uint32_t    u1Write : 1;
+    /** User(=1) / Supervisor (=0) flag. */
+    uint32_t    u1User : 1;
+    /** Write Thru flag. If PAT enabled, bit 0 of the index. */
+    uint32_t    u1WriteThru : 1;
+    /** Cache disabled flag. If PAT enabled, bit 1 of the index. */
+    uint32_t    u1CacheDisable : 1;
+    /** Accessed flag.
+     * Indicates that the page have been read or written to. */
+    uint32_t    u1Accessed : 1;
+    /** Chunk of reserved bits. */
+    uint32_t    u3Reserved : 3;
+    /** Available for use to system software. */
+    uint32_t    u3Available : 3;
+    /** Physical Page number of the next level - Low Part. Don't use! */
+    uint32_t    u20PageNoLow : 20;
+    /** Physical Page number of the next level - High Part. Don't use! */
+    uint32_t    u20PageNoHigh : 20;
+    /** MBZ bits */
+    uint32_t    u11Reserved : 11;
+    /** No Execute flag. */
+    uint32_t    u1NoExecute : 1;
+} X86PDPEAMD64BITS;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PDPEAMD64BITS, 8);
+#endif
+/** Pointer to a page directory pointer table entry. */
+typedef X86PDPEAMD64BITS *PX86PDPEAMD64BITS;
+/** Pointer to a const page directory pointer table entry. */
+typedef const X86PDPEAMD64BITS *PCX86PDPEAMD64BITS;
+
+/**
+ * Page directory pointer table entry for 1GB page. (AMD64 only)
+ */
+typedef struct X86PDPE1GB
+{
+    /** 0: Flags whether(=1) or not the page is present. */
+    uint32_t    u1Present : 1;
+    /** 1: Read(=0) / Write(=1) flag. */
+    uint32_t    u1Write : 1;
+    /** 2: User(=1) / Supervisor (=0) flag. */
+    uint32_t    u1User : 1;
+    /** 3: Write Thru flag. If PAT enabled, bit 0 of the index. */
+    uint32_t    u1WriteThru : 1;
+    /** 4: Cache disabled flag. If PAT enabled, bit 1 of the index. */
+    uint32_t    u1CacheDisable : 1;
+    /** 5: Accessed flag.
+     * Indicates that the page have been read or written to. */
+    uint32_t    u1Accessed : 1;
+    /** 6: Dirty flag for 1GB pages.  */
+    uint32_t    u1Dirty : 1;
+    /** 7: Indicates 1GB page if set. */
+    uint32_t    u1Size : 1;
+    /** 8: Global 1GB page. */
+    uint32_t    u1Global: 1;
+    /** 9-11: Available for use to system software. */
+    uint32_t    u3Available : 3;
+    /** 12: PAT bit for 1GB page. */
+    uint32_t    u1PAT : 1;
+    /** 13-29: MBZ bits. */
+    uint32_t    u17Reserved : 17;
+    /** 30-31: Physical page number - Low Part. Don't use! */
+    uint32_t    u2PageNoLow : 2;
+    /** 32-51: Physical Page number of the next level - High Part. Don't use! */
+    uint32_t    u20PageNoHigh : 20;
+    /** 52-62: MBZ bits */
+    uint32_t    u11Reserved : 11;
+    /** 63: No Execute flag. */
+    uint32_t    u1NoExecute : 1;
+} X86PDPE1GB;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PDPE1GB, 8);
+#endif
+/** Pointer to a page directory pointer table entry for a 1GB page. */
+typedef X86PDPE1GB *PX86PDPE1GB;
+/** Pointer to a const page directory pointer table entry for a 1GB page. */
+typedef const X86PDPE1GB *PCX86PDPE1GB;
+
+/**
+ * Page directory pointer table entry.
+ */
+typedef union X86PDPE
+{
+    /** Unsigned integer view. */
+    X86PGPAEUINT    u;
+    /** Normal view. */
+    X86PDPEBITS     n;
+    /** AMD64 view. */
+    X86PDPEAMD64BITS lm;
+    /** AMD64 big view. */
+    X86PDPE1GB      b;
+    /** 8 bit unsigned integer view. */
+    uint8_t         au8[8];
+    /** 16 bit unsigned integer view. */
+    uint16_t        au16[4];
+    /** 32 bit unsigned integer view. */
+    uint32_t        au32[2];
+} X86PDPE;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PDPE, 8);
+#endif
+/** Pointer to a page directory pointer table entry. */
+typedef X86PDPE *PX86PDPE;
+/** Pointer to a const page directory pointer table entry. */
+typedef const X86PDPE *PCX86PDPE;
+
+
+/**
+ * Page directory pointer table.
+ */
+typedef struct X86PDPT
+{
+    /** PDE Array. */
+    X86PDPE         a[X86_PG_AMD64_PDPE_ENTRIES];
+} X86PDPT;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PDPT, 4096);
+#endif
+/** Pointer to a page directory pointer table. */
+typedef X86PDPT *PX86PDPT;
+/** Pointer to a const page directory pointer table. */
+typedef const X86PDPT *PCX86PDPT;
+
+/** The page shift to get the PDPT index. */
+#define X86_PDPT_SHIFT             30
+/** The PDPT index mask (apply to a shifted page address). (32 bits PAE) */
+#define X86_PDPT_MASK_PAE          0x3
+/** The PDPT index mask (apply to a shifted page address). (64 bits PAE)*/
+#define X86_PDPT_MASK_AMD64        0x1ff
+
+/** @} */
+
+
+/** @name Page Map Level-4 Entry (Long Mode PAE)
+ * @{
+ */
+/** Bit 0 -  P  - Present bit. */
+#define X86_PML4E_P                         RT_BIT_32(0)
+/** Bit 1 - R/W - Read (clear) / Write (set) bit. */
+#define X86_PML4E_RW                        RT_BIT_32(1)
+/** Bit 2 - U/S - User (set) / Supervisor (clear) bit. */
+#define X86_PML4E_US                        RT_BIT_32(2)
+/** Bit 3 - PWT - Page level write thru bit. */
+#define X86_PML4E_PWT                       RT_BIT_32(3)
+/** Bit 4 - PCD - Page level cache disable bit. */
+#define X86_PML4E_PCD                       RT_BIT_32(4)
+/** Bit 5 -  A  - Access bit. */
+#define X86_PML4E_A                         RT_BIT_32(5)
+/** Bits 9-11 - - Available for use to system software. */
+#define X86_PML4E_AVL_MASK                  (RT_BIT_32(9) | RT_BIT_32(10) | RT_BIT_32(11))
+/** Bits 12-51 - - PAE - Physical Page number of the next level. */
+#define X86_PML4E_PG_MASK                   UINT64_C(0x000ffffffffff000)
+/** Bits 8, 7 - - MBZ bits when NX is active. */
+#define X86_PML4E_MBZ_MASK_NX               UINT64_C(0x0000000000000080)
+/** Bits 63, 7 - - MBZ bits when no NX. */
+#define X86_PML4E_MBZ_MASK_NO_NX            UINT64_C(0x8000000000000080)
+/** Bits 63 - NX - PAE - No execution flag. */
+#define X86_PML4E_NX                        RT_BIT_64(63)
+
+/**
+ * Page Map Level-4 Entry
+ */
+typedef struct X86PML4EBITS
+{
+    /** Flags whether(=1) or not the page is present. */
+    uint32_t    u1Present : 1;
+    /** Read(=0) / Write(=1) flag. */
+    uint32_t    u1Write : 1;
+    /** User(=1) / Supervisor (=0) flag. */
+    uint32_t    u1User : 1;
+    /** Write Thru flag. If PAT enabled, bit 0 of the index. */
+    uint32_t    u1WriteThru : 1;
+    /** Cache disabled flag. If PAT enabled, bit 1 of the index. */
+    uint32_t    u1CacheDisable : 1;
+    /** Accessed flag.
+     * Indicates that the page have been read or written to. */
+    uint32_t    u1Accessed : 1;
+    /** Chunk of reserved bits. */
+    uint32_t    u3Reserved : 3;
+    /** Available for use to system software. */
+    uint32_t    u3Available : 3;
+    /** Physical Page number of the next level - Low Part. Don't use! */
+    uint32_t    u20PageNoLow : 20;
+    /** Physical Page number of the next level - High Part. Don't use! */
+    uint32_t    u20PageNoHigh : 20;
+    /** MBZ bits */
+    uint32_t    u11Reserved : 11;
+    /** No Execute flag. */
+    uint32_t    u1NoExecute : 1;
+} X86PML4EBITS;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PML4EBITS, 8);
+#endif
+/** Pointer to a page map level-4 entry. */
+typedef X86PML4EBITS *PX86PML4EBITS;
+/** Pointer to a const page map level-4 entry. */
+typedef const X86PML4EBITS *PCX86PML4EBITS;
+
+/**
+ * Page Map Level-4 Entry.
+ */
+typedef union X86PML4E
+{
+    /** Unsigned integer view. */
+    X86PGPAEUINT    u;
+    /** Normal view. */
+    X86PML4EBITS    n;
+    /** 8 bit unsigned integer view. */
+    uint8_t         au8[8];
+    /** 16 bit unsigned integer view. */
+    uint16_t        au16[4];
+    /** 32 bit unsigned integer view. */
+    uint32_t        au32[2];
+} X86PML4E;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PML4E, 8);
+#endif
+/** Pointer to a page map level-4 entry. */
+typedef X86PML4E *PX86PML4E;
+/** Pointer to a const page map level-4 entry. */
+typedef const X86PML4E *PCX86PML4E;
+
+
+/**
+ * Page Map Level-4.
+ */
+typedef struct X86PML4
+{
+    /** PDE Array. */
+    X86PML4E        a[X86_PG_PAE_ENTRIES];
+} X86PML4;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86PML4, 4096);
+#endif
+/** Pointer to a page map level-4. */
+typedef X86PML4 *PX86PML4;
+/** Pointer to a const page map level-4. */
+typedef const X86PML4 *PCX86PML4;
+
+/** The page shift to get the PML4 index. */
+#define X86_PML4_SHIFT              39
+/** The PML4 index mask (apply to a shifted page address). */
+#define X86_PML4_MASK               0x1ff
+
+/** @} */
+
+/** @} */
+
+/**
+ * 32-bit protected mode FSTENV image.
+ */
+typedef struct X86FSTENV32P
+{
+    uint16_t    FCW;
+    uint16_t    padding1;
+    uint16_t    FSW;
+    uint16_t    padding2;
+    uint16_t    FTW;
+    uint16_t    padding3;
+    uint32_t    FPUIP;
+    uint16_t    FPUCS;
+    uint16_t    FOP;
+    uint32_t    FPUDP;
+    uint16_t    FPUDS;
+    uint16_t    padding4;
+} X86FSTENV32P;
+/** Pointer to a 32-bit protected mode FSTENV image. */
+typedef X86FSTENV32P *PX86FSTENV32P;
+/** Pointer to a const 32-bit protected mode FSTENV image. */
+typedef X86FSTENV32P const *PCX86FSTENV32P;
+
+
+/**
+ * 80-bit MMX/FPU register type.
+ */
+typedef struct X86FPUMMX
+{
+    uint8_t reg[10];
+} X86FPUMMX;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86FPUMMX, 10);
+#endif
+/** Pointer to a 80-bit MMX/FPU register type. */
+typedef X86FPUMMX *PX86FPUMMX;
+/** Pointer to a const 80-bit MMX/FPU register type. */
+typedef const X86FPUMMX *PCX86FPUMMX;
+
+/** FPU (x87) register. */
+typedef union X86FPUREG
+{
+    /** MMX view. */
+    uint64_t    mmx;
+    /** FPU view - todo. */
+    X86FPUMMX   fpu;
+    /** Extended precision floating point view. */
+    RTFLOAT80U  r80;
+    /** Extended precision floating point view v2 */
+    RTFLOAT80U2 r80Ex;
+    /** 8-bit view. */
+    uint8_t     au8[16];
+    /** 16-bit view. */
+    uint16_t    au16[8];
+    /** 32-bit view. */
+    uint32_t    au32[4];
+    /** 64-bit view. */
+    uint64_t    au64[2];
+    /** 128-bit view. (yeah, very helpful) */
+    uint128_t   au128[1];
+} X86FPUREG;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86FPUREG, 16);
+#endif
+/** Pointer to a FPU register. */
+typedef X86FPUREG *PX86FPUREG;
+/** Pointer to a const FPU register. */
+typedef X86FPUREG const *PCX86FPUREG;
+
+/**
+ * XMM register union.
+ */
+typedef union X86XMMREG
+{
+    /** XMM Register view. */
+    uint128_t   xmm;
+    /** 8-bit view. */
+    uint8_t     au8[16];
+    /** 16-bit view. */
+    uint16_t    au16[8];
+    /** 32-bit view. */
+    uint32_t    au32[4];
+    /** 64-bit view. */
+    uint64_t    au64[2];
+    /** 128-bit view. (yeah, very helpful) */
+    uint128_t   au128[1];
+    /** Confusing nested 128-bit union view (this is what xmm should've been). */
+    RTUINT128U  uXmm;
+} X86XMMREG;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86XMMREG, 16);
+#endif
+/** Pointer to an XMM register state. */
+typedef X86XMMREG *PX86XMMREG;
+/** Pointer to a const XMM register state. */
+typedef X86XMMREG const *PCX86XMMREG;
+
+/**
+ * YMM register union.
+ */
+typedef union X86YMMREG
+{
+    /** 8-bit view. */
+    uint8_t     au8[32];
+    /** 16-bit view. */
+    uint16_t    au16[16];
+    /** 32-bit view. */
+    uint32_t    au32[8];
+    /** 64-bit view. */
+    uint64_t    au64[4];
+    /** 128-bit view. (yeah, very helpful) */
+    uint128_t   au128[2];
+    /** XMM sub register view. */
+    X86XMMREG   aXmm[2];
+} X86YMMREG;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86YMMREG, 32);
+#endif
+/** Pointer to an YMM register state. */
+typedef X86YMMREG *PX86YMMREG;
+/** Pointer to a const YMM register state. */
+typedef X86YMMREG const *PCX86YMMREG;
+
+/**
+ * ZMM register union.
+ */
+typedef union X86ZMMREG
+{
+    /** 8-bit view. */
+    uint8_t     au8[64];
+    /** 16-bit view. */
+    uint16_t    au16[32];
+    /** 32-bit view. */
+    uint32_t    au32[16];
+    /** 64-bit view. */
+    uint64_t    au64[8];
+    /** 128-bit view. (yeah, very helpful) */
+    uint128_t   au128[4];
+    /** XMM sub register view. */
+    X86XMMREG   aXmm[4];
+    /** YMM sub register view. */
+    X86YMMREG   aYmm[2];
+} X86ZMMREG;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86ZMMREG, 64);
+#endif
+/** Pointer to an ZMM register state. */
+typedef X86ZMMREG *PX86ZMMREG;
+/** Pointer to a const ZMM register state. */
+typedef X86ZMMREG const *PCX86ZMMREG;
+
+
+/**
+ * 32-bit FPU state (aka FSAVE/FRSTOR Memory Region).
+ * @todo verify this...
+ */
+#pragma pack(1)
+typedef struct X86FPUSTATE
+{
+    /** 0x00 - Control word. */
+    uint16_t    FCW;
+    /** 0x02 - Alignment word */
+    uint16_t    Dummy1;
+    /** 0x04 - Status word. */
+    uint16_t    FSW;
+    /** 0x06 - Alignment word */
+    uint16_t    Dummy2;
+    /** 0x08 - Tag word */
+    uint16_t    FTW;
+    /** 0x0a - Alignment word */
+    uint16_t    Dummy3;
+
+    /** 0x0c - Instruction pointer. */
+    uint32_t    FPUIP;
+    /** 0x10 - Code selector. */
+    uint16_t    CS;
+    /** 0x12 - Opcode. */
+    uint16_t    FOP;
+    /** 0x14 - FOO. */
+    uint32_t    FPUOO;
+    /** 0x18 - FOS. */
+    uint32_t    FPUOS;
+    /** 0x1c - FPU register. */
+    X86FPUREG   regs[8];
+} X86FPUSTATE;
+#pragma pack()
+/** Pointer to a FPU state. */
+typedef X86FPUSTATE  *PX86FPUSTATE;
+/** Pointer to a const FPU state. */
+typedef const X86FPUSTATE  *PCX86FPUSTATE;
+
+/**
+ * FPU Extended state (aka FXSAVE/FXRSTORE Memory Region).
+ */
+#pragma pack(1)
+typedef struct X86FXSTATE
+{
+    /** 0x00 - Control word. */
+    uint16_t    FCW;
+    /** 0x02 - Status word. */
+    uint16_t    FSW;
+    /** 0x04 - Tag word. (The upper byte is always zero.) */
+    uint16_t    FTW;
+    /** 0x06 - Opcode. */
+    uint16_t    FOP;
+    /** 0x08 - Instruction pointer. */
+    uint32_t    FPUIP;
+    /** 0x0c - Code selector. */
+    uint16_t    CS;
+    uint16_t    Rsrvd1;
+    /** 0x10 - Data pointer. */
+    uint32_t    FPUDP;
+    /** 0x14 - Data segment */
+    uint16_t    DS;
+    /** 0x16 */
+    uint16_t    Rsrvd2;
+    /** 0x18 */
+    uint32_t    MXCSR;
+    /** 0x1c */
+    uint32_t    MXCSR_MASK;
+    /** 0x20 - FPU registers. */
+    X86FPUREG   aRegs[8];
+    /** 0xA0 - XMM registers - 8 registers in 32 bits mode, 16 in long mode. */
+    X86XMMREG   aXMM[16];
+    /* - offset 416 - */
+    uint32_t    au32RsrvdRest[(464 - 416) / sizeof(uint32_t)];
+    /* - offset 464 - Software usable reserved bits. */
+    uint32_t    au32RsrvdForSoftware[(512 - 464) / sizeof(uint32_t)];
+} X86FXSTATE;
+#pragma pack()
+/** Pointer to a FPU Extended state. */
+typedef X86FXSTATE *PX86FXSTATE;
+/** Pointer to a const FPU Extended state. */
+typedef const X86FXSTATE *PCX86FXSTATE;
+
+/** Offset for software usable reserved bits (464:511) where we store a 32-bit
+ *  magic. Don't forget to update x86.mac if you change this! */
+#define X86_OFF_FXSTATE_RSVD            0x1d0
+/** The 32-bit magic used to recognize if this a 32-bit FPU state. Don't
+ *  forget to update x86.mac if you change this!
+ * @todo r=bird: This has nothing what-so-ever to do here.... */
+#define X86_FXSTATE_RSVD_32BIT_MAGIC    0x32b3232b
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86FXSTATE, 512);
+AssertCompileMemberOffset(X86FXSTATE, au32RsrvdForSoftware, X86_OFF_FXSTATE_RSVD);
+#endif
+
+/** @name FPU status word flags.
+ * @{ */
+/** Exception Flag: Invalid operation.  */
+#define X86_FSW_IE          RT_BIT_32(0)
+/** Exception Flag: Denormalized operand.  */
+#define X86_FSW_DE          RT_BIT_32(1)
+/** Exception Flag: Zero divide.  */
+#define X86_FSW_ZE          RT_BIT_32(2)
+/** Exception Flag: Overflow.  */
+#define X86_FSW_OE          RT_BIT_32(3)
+/** Exception Flag: Underflow.  */
+#define X86_FSW_UE          RT_BIT_32(4)
+/** Exception Flag: Precision.  */
+#define X86_FSW_PE          RT_BIT_32(5)
+/** Stack fault. */
+#define X86_FSW_SF          RT_BIT_32(6)
+/** Error summary status. */
+#define X86_FSW_ES          RT_BIT_32(7)
+/** Mask of exceptions flags, excluding the summary bit. */
+#define X86_FSW_XCPT_MASK   UINT16_C(0x007f)
+/** Mask of exceptions flags, including the summary bit. */
+#define X86_FSW_XCPT_ES_MASK UINT16_C(0x00ff)
+/** Condition code 0. */
+#define X86_FSW_C0          RT_BIT_32(8)
+/** Condition code 1. */
+#define X86_FSW_C1          RT_BIT_32(9)
+/** Condition code 2. */
+#define X86_FSW_C2          RT_BIT_32(10)
+/** Top of the stack mask. */
+#define X86_FSW_TOP_MASK    UINT16_C(0x3800)
+/** TOP shift value. */
+#define X86_FSW_TOP_SHIFT   11
+/** Mask for getting TOP value after shifting it right. */
+#define X86_FSW_TOP_SMASK   UINT16_C(0x0007)
+/** Get the TOP value. */
+#define X86_FSW_TOP_GET(a_uFsw) (((a_uFsw) >> X86_FSW_TOP_SHIFT) & X86_FSW_TOP_SMASK)
+/** Condition code 3. */
+#define X86_FSW_C3          RT_BIT_32(14)
+/** Mask of exceptions flags, including the summary bit. */
+#define X86_FSW_C_MASK      UINT16_C(0x4700)
+/** FPU busy. */
+#define X86_FSW_B           RT_BIT_32(15)
+/** @} */
+
+
+/** @name FPU control word flags.
+ * @{ */
+/** Exception Mask: Invalid operation.  */
+#define X86_FCW_IM          RT_BIT_32(0)
+/** Exception Mask: Denormalized operand.  */
+#define X86_FCW_DM          RT_BIT_32(1)
+/** Exception Mask: Zero divide.  */
+#define X86_FCW_ZM          RT_BIT_32(2)
+/** Exception Mask: Overflow.  */
+#define X86_FCW_OM          RT_BIT_32(3)
+/** Exception Mask: Underflow.  */
+#define X86_FCW_UM          RT_BIT_32(4)
+/** Exception Mask: Precision.  */
+#define X86_FCW_PM          RT_BIT_32(5)
+/** Mask all exceptions, the value typically loaded (by for instance fninit).
+ * @remarks This includes reserved bit 6.  */
+#define X86_FCW_MASK_ALL    UINT16_C(0x007f)
+/** Mask all exceptions. Same as X86_FSW_XCPT_MASK. */
+#define X86_FCW_XCPT_MASK    UINT16_C(0x003f)
+/** Precision control mask. */
+#define X86_FCW_PC_MASK     UINT16_C(0x0300)
+/** Precision control: 24-bit. */
+#define X86_FCW_PC_24       UINT16_C(0x0000)
+/** Precision control: Reserved. */
+#define X86_FCW_PC_RSVD     UINT16_C(0x0100)
+/** Precision control: 53-bit. */
+#define X86_FCW_PC_53       UINT16_C(0x0200)
+/** Precision control: 64-bit. */
+#define X86_FCW_PC_64       UINT16_C(0x0300)
+/** Rounding control mask. */
+#define X86_FCW_RC_MASK     UINT16_C(0x0c00)
+/** Rounding control: To nearest. */
+#define X86_FCW_RC_NEAREST  UINT16_C(0x0000)
+/** Rounding control: Down. */
+#define X86_FCW_RC_DOWN     UINT16_C(0x0400)
+/** Rounding control: Up. */
+#define X86_FCW_RC_UP       UINT16_C(0x0800)
+/** Rounding control: Towards zero. */
+#define X86_FCW_RC_ZERO     UINT16_C(0x0c00)
+/** Bits which should be zero, apparently. */
+#define X86_FCW_ZERO_MASK   UINT16_C(0xf080)
+/** @} */
+
+/** @name SSE MXCSR
+ * @{ */
+/** Exception Flag: Invalid operation.  */
+#define X86_MXCSR_IE          RT_BIT_32(0)
+/** Exception Flag: Denormalized operand.  */
+#define X86_MXCSR_DE          RT_BIT_32(1)
+/** Exception Flag: Zero divide.  */
+#define X86_MXCSR_ZE          RT_BIT_32(2)
+/** Exception Flag: Overflow.  */
+#define X86_MXCSR_OE          RT_BIT_32(3)
+/** Exception Flag: Underflow.  */
+#define X86_MXCSR_UE          RT_BIT_32(4)
+/** Exception Flag: Precision.  */
+#define X86_MXCSR_PE          RT_BIT_32(5)
+
+/** Denormals are zero. */
+#define X86_MXCSR_DAZ         RT_BIT_32(6)
+
+/** Exception Mask: Invalid operation. */
+#define X86_MXCSR_IM          RT_BIT_32(7)
+/** Exception Mask: Denormalized operand. */
+#define X86_MXCSR_DM          RT_BIT_32(8)
+/** Exception Mask: Zero divide.  */
+#define X86_MXCSR_ZM          RT_BIT_32(9)
+/** Exception Mask: Overflow.  */
+#define X86_MXCSR_OM          RT_BIT_32(10)
+/** Exception Mask: Underflow.  */
+#define X86_MXCSR_UM          RT_BIT_32(11)
+/** Exception Mask: Precision.  */
+#define X86_MXCSR_PM          RT_BIT_32(12)
+
+/** Rounding control mask. */
+#define X86_MXCSR_RC_MASK     UINT16_C(0x6000)
+/** Rounding control: To nearest. */
+#define X86_MXCSR_RC_NEAREST  UINT16_C(0x0000)
+/** Rounding control: Down. */
+#define X86_MXCSR_RC_DOWN     UINT16_C(0x2000)
+/** Rounding control: Up. */
+#define X86_MXCSR_RC_UP       UINT16_C(0x4000)
+/** Rounding control: Towards zero. */
+#define X86_MXCSR_RC_ZERO     UINT16_C(0x6000)
+
+/** Flush-to-zero for masked underflow.  */
+#define X86_MXCSR_FZ          RT_BIT_32(15)
+
+/** Misaligned Exception Mask (AMD MISALIGNSSE).  */
+#define X86_MXCSR_MM          RT_BIT_32(17)
+/** @} */
+
+/**
+ * XSAVE header.
+ */
+typedef struct X86XSAVEHDR
+{
+    /** XTATE_BV - Bitmap indicating whether a component is in the state. */
+    uint64_t        bmXState;
+    /** XCOMP_BC - Bitmap used by instructions applying structure compaction. */
+    uint64_t        bmXComp;
+    /** Reserved for furture extensions, probably MBZ. */
+    uint64_t        au64Reserved[6];
+} X86XSAVEHDR;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86XSAVEHDR, 64);
+#endif
+/** Pointer to an XSAVE header. */
+typedef X86XSAVEHDR *PX86XSAVEHDR;
+/** Pointer to a const XSAVE header. */
+typedef X86XSAVEHDR const *PCX86XSAVEHDR;
+
+
+/**
+ * The high 128-bit YMM register state (XSAVE_C_YMM).
+ * (The lower 128-bits being in X86FXSTATE.)
+ */
+typedef struct X86XSAVEYMMHI
+{
+    /** 16 registers in 64-bit mode, 8 in 32-bit mode. */
+    X86XMMREG       aYmmHi[16];
+} X86XSAVEYMMHI;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86XSAVEYMMHI, 256);
+#endif
+/** Pointer to a high 128-bit YMM register state. */
+typedef X86XSAVEYMMHI *PX86XSAVEYMMHI;
+/** Pointer to a const high 128-bit YMM register state. */
+typedef X86XSAVEYMMHI const *PCX86XSAVEYMMHI;
+
+/**
+ * Intel MPX bound registers state (XSAVE_C_BNDREGS).
+ */
+typedef struct X86XSAVEBNDREGS
+{
+    /** Array of registers (BND0...BND3). */
+    struct
+    {
+        /** Lower bound. */
+        uint64_t    uLowerBound;
+        /** Upper bound. */
+        uint64_t    uUpperBound;
+    } aRegs[4];
+} X86XSAVEBNDREGS;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86XSAVEBNDREGS, 64);
+#endif
+/** Pointer to a MPX bound register state. */
+typedef X86XSAVEBNDREGS *PX86XSAVEBNDREGS;
+/** Pointer to a const MPX bound register state. */
+typedef X86XSAVEBNDREGS const *PCX86XSAVEBNDREGS;
+
+/**
+ * Intel MPX bound config and status register state (XSAVE_C_BNDCSR).
+ */
+typedef struct X86XSAVEBNDCFG
+{
+    uint64_t        fConfig;
+    uint64_t        fStatus;
+} X86XSAVEBNDCFG;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86XSAVEBNDCFG, 16);
+#endif
+/** Pointer to a MPX bound config and status register state. */
+typedef X86XSAVEBNDCFG *PX86XSAVEBNDCFG;
+/** Pointer to a const MPX bound config and status register state. */
+typedef X86XSAVEBNDCFG *PCX86XSAVEBNDCFG;
+
+/**
+ * AVX-512 opmask state (XSAVE_C_OPMASK).
+ */
+typedef struct X86XSAVEOPMASK
+{
+    /** The K0..K7 values. */
+    uint64_t    aKRegs[8];
+} X86XSAVEOPMASK;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86XSAVEOPMASK, 64);
+#endif
+/** Pointer to a AVX-512 opmask state. */
+typedef X86XSAVEOPMASK *PX86XSAVEOPMASK;
+/** Pointer to a const AVX-512 opmask state. */
+typedef X86XSAVEOPMASK const *PCX86XSAVEOPMASK;
+
+/**
+ * ZMM0-15 upper 256 bits introduced in AVX-512 (XSAVE_C_ZMM_HI256).
+ */
+typedef struct X86XSAVEZMMHI256
+{
+    /** Upper 256-bits of ZMM0-15. */
+    X86YMMREG   aHi256Regs[16];
+} X86XSAVEZMMHI256;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86XSAVEZMMHI256, 512);
+#endif
+/** Pointer to a state comprising the upper 256-bits of ZMM0-15. */
+typedef X86XSAVEZMMHI256 *PX86XSAVEZMMHI256;
+/** Pointer to a const state comprising the upper 256-bits of ZMM0-15. */
+typedef X86XSAVEZMMHI256 const *PCX86XSAVEZMMHI256;
+
+/**
+ * ZMM16-31 register state introduced in AVX-512 (XSAVE_C_ZMM_16HI).
+ */
+typedef struct X86XSAVEZMM16HI
+{
+    /** ZMM16 thru ZMM31. */
+    X86ZMMREG   aRegs[16];
+} X86XSAVEZMM16HI;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86XSAVEZMM16HI, 1024);
+#endif
+/** Pointer to a state comprising ZMM16-32. */
+typedef X86XSAVEZMM16HI *PX86XSAVEZMM16HI;
+/** Pointer to a const state comprising ZMM16-32. */
+typedef X86XSAVEZMM16HI const *PCX86XSAVEZMM16HI;
+
+/**
+ * AMD Light weight profiling state (XSAVE_C_LWP).
+ *
+ * We probably won't play with this as AMD seems to be dropping from their "zen"
+ * processor micro architecture.
+ */
+typedef struct X86XSAVELWP
+{
+    /** Details when needed. */
+    uint64_t        auLater[128/8];
+} X86XSAVELWP;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86XSAVELWP, 128);
+#endif
+
+
+/**
+ * x86 FPU/SSE/AVX/XXXX state.
+ *
+ * Please bump DBGFCORE_FMT_VERSION by 1 in dbgfcorefmt.h if you make any
+ * changes to this structure.
+ */
+typedef struct X86XSAVEAREA
+{
+    /** The x87 and SSE region (or legacy region if you like).  */
+    X86FXSTATE      x87;
+    /** The XSAVE header. */
+    X86XSAVEHDR     Hdr;
+    /** Beyond the header, there isn't really a fixed layout, but we can
+       generally assume the YMM (AVX) register extensions are present and
+       follows immediately. */
+    union
+    {
+        /** The high 128-bit AVX registers for easy access by IEM.
+         * @note This ASSUMES they will always be here...  */
+        X86XSAVEYMMHI       YmmHi;
+
+        /** This is a typical layout on intel CPUs (good for debuggers). */
+        struct
+        {
+            X86XSAVEYMMHI       YmmHi;
+            X86XSAVEBNDREGS     BndRegs;
+            X86XSAVEBNDCFG      BndCfg;
+            uint8_t             abFudgeToMatchDocs[0xB0];
+            X86XSAVEOPMASK      Opmask;
+            X86XSAVEZMMHI256    ZmmHi256;
+            X86XSAVEZMM16HI     Zmm16Hi;
+        } Intel;
+
+        /** This is a typical layout on AMD Bulldozer type CPUs (good for debuggers). */
+        struct
+        {
+            X86XSAVEYMMHI       YmmHi;
+            X86XSAVELWP         Lwp;
+        } AmdBd;
+
+        /** To enbling static deployments that have a reasonable chance of working for
+         * the next 3-6 CPU generations without running short on space, we allocate a
+         * lot of extra space here, making the structure a round 8KB in size.  This
+         * leaves us 7616 bytes for extended state.  The skylake xeons are likely to use
+         * 2112 of these, leaving us with 5504 bytes for future Intel generations. */
+        uint8_t         ab[8192 - 512 - 64];
+    } u;
+} X86XSAVEAREA;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86XSAVEAREA, 8192);
+AssertCompileMemberSize(X86XSAVEAREA, u.Intel, 0x840 /*2112 => total 0xa80 (2688) */);
+AssertCompileMemberOffset(X86XSAVEAREA, Hdr,                0x200);
+AssertCompileMemberOffset(X86XSAVEAREA, u.Intel.YmmHi,      0x240);
+AssertCompileMemberOffset(X86XSAVEAREA, u.Intel.BndRegs,    0x340);
+AssertCompileMemberOffset(X86XSAVEAREA, u.Intel.BndCfg,     0x380);
+AssertCompileMemberOffset(X86XSAVEAREA, u.Intel.Opmask,     0x440 /* 1088 */);
+AssertCompileMemberOffset(X86XSAVEAREA, u.Intel.ZmmHi256,   0x480 /* 1152 */);
+AssertCompileMemberOffset(X86XSAVEAREA, u.Intel.Zmm16Hi,    0x680 /* 1664 */);
+#endif
+/** Pointer to a XSAVE area. */
+typedef X86XSAVEAREA *PX86XSAVEAREA;
+/** Pointer to a const XSAVE area. */
+typedef X86XSAVEAREA const *PCX86XSAVEAREA;
+
+
+/** @name XSAVE_C_XXX - XSAVE State Components Bits (XCR0).
+ * @{ */
+/** Bit 0 - x87 - Legacy FPU state (bit number) */
+#define XSAVE_C_X87_BIT         0
+/** Bit 0 - x87 - Legacy FPU state. */
+#define XSAVE_C_X87             RT_BIT_64(XSAVE_C_X87_BIT)
+/** Bit 1 - SSE - 128-bit SSE state (bit number). */
+#define XSAVE_C_SSE_BIT         1
+/** Bit 1 - SSE - 128-bit SSE state. */
+#define XSAVE_C_SSE             RT_BIT_64(XSAVE_C_SSE_BIT)
+/** Bit 2 - YMM_Hi128 - Upper 128 bits of YMM0-15 (AVX) (bit number). */
+#define XSAVE_C_YMM_BIT         2
+/** Bit 2 - YMM_Hi128 - Upper 128 bits of YMM0-15 (AVX). */
+#define XSAVE_C_YMM             RT_BIT_64(XSAVE_C_YMM_BIT)
+/** Bit 3 - BNDREGS - MPX bound register state (bit number). */
+#define XSAVE_C_BNDREGS_BIT     3
+/** Bit 3 - BNDREGS - MPX bound register state. */
+#define XSAVE_C_BNDREGS         RT_BIT_64(XSAVE_C_BNDREGS_BIT)
+/** Bit 4 - BNDCSR - MPX bound config and status state (bit number). */
+#define XSAVE_C_BNDCSR_BIT      4
+/** Bit 4 - BNDCSR - MPX bound config and status state. */
+#define XSAVE_C_BNDCSR          RT_BIT_64(XSAVE_C_BNDCSR_BIT)
+/** Bit 5 - Opmask - opmask state (bit number). */
+#define XSAVE_C_OPMASK_BIT      5
+/** Bit 5 - Opmask - opmask state. */
+#define XSAVE_C_OPMASK          RT_BIT_64(XSAVE_C_OPMASK_BIT)
+/** Bit 6 - ZMM_Hi256 - Upper 256 bits of ZMM0-15 (AVX-512) (bit number). */
+#define XSAVE_C_ZMM_HI256_BIT   6
+/** Bit 6 - ZMM_Hi256 - Upper 256 bits of ZMM0-15 (AVX-512). */
+#define XSAVE_C_ZMM_HI256       RT_BIT_64(XSAVE_C_ZMM_HI256_BIT)
+/** Bit 7 - Hi16_ZMM - 512-bits ZMM16-31 state (AVX-512) (bit number). */
+#define XSAVE_C_ZMM_16HI_BIT    7
+/** Bit 7 - Hi16_ZMM - 512-bits ZMM16-31 state (AVX-512). */
+#define XSAVE_C_ZMM_16HI        RT_BIT_64(XSAVE_C_ZMM_16HI_BIT)
+/** Bit 9 - PKRU - Protection-key state (bit number). */
+#define XSAVE_C_PKRU_BIT        9
+/** Bit 9 - PKRU - Protection-key state. */
+#define XSAVE_C_PKRU            RT_BIT_64(XSAVE_C_PKRU_BIT)
+/** Bit 62 - LWP - Lightweight Profiling (AMD) (bit number). */
+#define XSAVE_C_LWP_BIT         62
+/** Bit 62 - LWP - Lightweight Profiling (AMD). */
+#define XSAVE_C_LWP             RT_BIT_64(XSAVE_C_LWP_BIT)
+/** Bit 63 - X - Reserved (MBZ) for extending XCR0 (bit number). */
+#define XSAVE_C_X_BIT           63
+/** Bit 63 - X - Reserved (MBZ) for extending XCR0 (AMD). */
+#define XSAVE_C_X               RT_BIT_64(XSAVE_C_X_BIT)
+/** @} */
+
+
+
+/** @name Selector Descriptor
+ * @{
+ */
+
+#ifndef VBOX_FOR_DTRACE_LIB
+/**
+ * Descriptor attributes (as seen by VT-x).
+ */
+typedef struct X86DESCATTRBITS
+{
+    /** 00 - Segment Type. */
+    unsigned    u4Type : 4;
+    /** 04 - Descriptor Type. System(=0) or code/data selector */
+    unsigned    u1DescType : 1;
+    /** 05 - Descriptor Privilege level. */
+    unsigned    u2Dpl : 2;
+    /** 07 - Flags selector present(=1) or not. */
+    unsigned    u1Present : 1;
+    /** 08 - Segment limit 16-19. */
+    unsigned    u4LimitHigh : 4;
+    /** 0c - Available for system software. */
+    unsigned    u1Available : 1;
+    /** 0d - 32 bits mode: Reserved - 0, long mode: Long Attribute Bit. */
+    unsigned    u1Long : 1;
+    /** 0e - This flags meaning depends on the segment type. Try make sense out
+     * of the intel manual yourself.  */
+    unsigned    u1DefBig : 1;
+    /** 0f - Granularity of the limit. If set 4KB granularity is used, if
+     * clear byte. */
+    unsigned    u1Granularity : 1;
+    /** 10 - "Unusable" selector, special Intel (VT-x only?) bit. */
+    unsigned    u1Unusable : 1;
+} X86DESCATTRBITS;
+#endif /* !VBOX_FOR_DTRACE_LIB */
+
+/** @name X86DESCATTR masks
+ * @{ */
+#define X86DESCATTR_TYPE            UINT32_C(0x0000000f)
+#define X86DESCATTR_DT              UINT32_C(0x00000010)
+#define X86DESCATTR_DPL             UINT32_C(0x00000060)
+#define X86DESCATTR_DPL_SHIFT       5 /**< Shift count for the DPL value. */
+#define X86DESCATTR_P               UINT32_C(0x00000080)
+#define X86DESCATTR_LIMIT_HIGH      UINT32_C(0x00000f00)
+#define X86DESCATTR_AVL             UINT32_C(0x00001000)
+#define X86DESCATTR_L               UINT32_C(0x00002000)
+#define X86DESCATTR_D               UINT32_C(0x00004000)
+#define X86DESCATTR_G               UINT32_C(0x00008000)
+#define X86DESCATTR_UNUSABLE        UINT32_C(0x00010000)
+/** @}  */
+
+#pragma pack(1)
+typedef union X86DESCATTR
+{
+    /** Unsigned integer view. */
+    uint32_t           u;
+#ifndef VBOX_FOR_DTRACE_LIB
+    /** Normal view. */
+    X86DESCATTRBITS    n;
+#endif
+} X86DESCATTR;
+#pragma pack()
+/** Pointer to descriptor attributes. */
+typedef X86DESCATTR *PX86DESCATTR;
+/** Pointer to const descriptor attributes. */
+typedef const X86DESCATTR *PCX86DESCATTR;
+
+#ifndef VBOX_FOR_DTRACE_LIB
+
+/**
+ * Generic descriptor table entry
+ */
+#pragma pack(1)
+typedef struct X86DESCGENERIC
+{
+    /** 00 - Limit - Low word. */
+    unsigned    u16LimitLow : 16;
+    /** 10 - Base address - low word.
+     * Don't try set this to 24 because MSC is doing stupid things then. */
+    unsigned    u16BaseLow : 16;
+    /** 20 - Base address - first 8 bits of high word. */
+    unsigned    u8BaseHigh1 : 8;
+    /** 28 - Segment Type. */
+    unsigned    u4Type : 4;
+    /** 2c - Descriptor Type. System(=0) or code/data selector */
+    unsigned    u1DescType : 1;
+    /** 2d - Descriptor Privilege level. */
+    unsigned    u2Dpl : 2;
+    /** 2f - Flags selector present(=1) or not. */
+    unsigned    u1Present : 1;
+    /** 30 - Segment limit 16-19. */
+    unsigned    u4LimitHigh : 4;
+    /** 34 - Available for system software. */
+    unsigned    u1Available : 1;
+    /** 35 - 32 bits mode: Reserved - 0, long mode: Long Attribute Bit. */
+    unsigned    u1Long : 1;
+    /** 36 - This flags meaning depends on the segment type. Try make sense out
+     * of the intel manual yourself.  */
+    unsigned    u1DefBig : 1;
+    /** 37 - Granularity of the limit. If set 4KB granularity is used, if
+     * clear byte. */
+    unsigned    u1Granularity : 1;
+    /** 38 - Base address - highest 8 bits. */
+    unsigned    u8BaseHigh2 : 8;
+} X86DESCGENERIC;
+#pragma pack()
+/** Pointer to a generic descriptor entry. */
+typedef X86DESCGENERIC *PX86DESCGENERIC;
+/** Pointer to a const generic descriptor entry. */
+typedef const X86DESCGENERIC *PCX86DESCGENERIC;
+
+/** @name Bit offsets of X86DESCGENERIC members.
+ * @{*/
+#define X86DESCGENERIC_BIT_OFF_LIMIT_LOW        (0)   /**< Bit offset of X86DESCGENERIC::u16LimitLow. */
+#define X86DESCGENERIC_BIT_OFF_BASE_LOW         (16)  /**< Bit offset of X86DESCGENERIC::u16BaseLow. */
+#define X86DESCGENERIC_BIT_OFF_BASE_HIGH1       (32)  /**< Bit offset of X86DESCGENERIC::u8BaseHigh1. */
+#define X86DESCGENERIC_BIT_OFF_TYPE             (40)  /**< Bit offset of X86DESCGENERIC::u4Type. */
+#define X86DESCGENERIC_BIT_OFF_DESC_TYPE        (44)  /**< Bit offset of X86DESCGENERIC::u1DescType. */
+#define X86DESCGENERIC_BIT_OFF_DPL              (45)  /**< Bit offset of X86DESCGENERIC::u2Dpl. */
+#define X86DESCGENERIC_BIT_OFF_PRESENT          (47)  /**< Bit offset of X86DESCGENERIC::uu1Present. */
+#define X86DESCGENERIC_BIT_OFF_LIMIT_HIGH       (48)  /**< Bit offset of X86DESCGENERIC::u4LimitHigh. */
+#define X86DESCGENERIC_BIT_OFF_AVAILABLE        (52)  /**< Bit offset of X86DESCGENERIC::u1Available. */
+#define X86DESCGENERIC_BIT_OFF_LONG             (53)  /**< Bit offset of X86DESCGENERIC::u1Long. */
+#define X86DESCGENERIC_BIT_OFF_DEF_BIG          (54)  /**< Bit offset of X86DESCGENERIC::u1DefBig. */
+#define X86DESCGENERIC_BIT_OFF_GRANULARITY      (55)  /**< Bit offset of X86DESCGENERIC::u1Granularity. */
+#define X86DESCGENERIC_BIT_OFF_BASE_HIGH2       (56)  /**< Bit offset of X86DESCGENERIC::u8BaseHigh2. */
+/** @}  */
+
+
+/** @name LAR mask
+ * @{ */
+#define X86LAR_F_TYPE            UINT16_C(    0x0f00)
+#define X86LAR_F_DT              UINT16_C(    0x1000)
+#define X86LAR_F_DPL             UINT16_C(    0x6000)
+#define X86LAR_F_DPL_SHIFT       13 /**< Shift count for the DPL value. */
+#define X86LAR_F_P               UINT16_C(    0x8000)
+#define X86LAR_F_AVL             UINT32_C(0x00100000)
+#define X86LAR_F_L               UINT32_C(0x00200000)
+#define X86LAR_F_D               UINT32_C(0x00400000)
+#define X86LAR_F_G               UINT32_C(0x00800000)
+/** @}  */
+
+
+/**
+ * Call-, Interrupt-, Trap- or Task-gate descriptor (legacy).
+ */
+typedef struct X86DESCGATE
+{
+    /** 00 - Target code segment offset - Low word.
+     * Ignored if task-gate. */
+    unsigned    u16OffsetLow : 16;
+    /** 10 - Target code segment selector for call-, interrupt- and trap-gates,
+     * TSS selector if task-gate. */
+    unsigned    u16Sel : 16;
+    /** 20 - Number of parameters for a call-gate.
+     * Ignored if interrupt-, trap- or task-gate. */
+    unsigned    u5ParmCount : 5;
+    /** 25 - Reserved / ignored. */
+    unsigned    u3Reserved : 3;
+    /** 28 - Segment Type. */
+    unsigned    u4Type : 4;
+    /** 2c - Descriptor Type (0 = system). */
+    unsigned    u1DescType : 1;
+    /** 2d - Descriptor Privilege level. */
+    unsigned    u2Dpl : 2;
+    /** 2f - Flags selector present(=1) or not. */
+    unsigned    u1Present : 1;
+    /** 30 - Target code segment offset - High word.
+     * Ignored if task-gate. */
+    unsigned    u16OffsetHigh : 16;
+} X86DESCGATE;
+/** Pointer to a Call-, Interrupt-, Trap- or Task-gate descriptor entry. */
+typedef X86DESCGATE *PX86DESCGATE;
+/** Pointer to a const Call-, Interrupt-, Trap- or Task-gate descriptor entry. */
+typedef const X86DESCGATE *PCX86DESCGATE;
+
+#endif /* VBOX_FOR_DTRACE_LIB */
+
+/**
+ * Descriptor table entry.
+ */
+#pragma pack(1)
+typedef union X86DESC
+{
+#ifndef VBOX_FOR_DTRACE_LIB
+    /** Generic descriptor view. */
+    X86DESCGENERIC  Gen;
+    /** Gate descriptor view. */
+    X86DESCGATE     Gate;
+#endif
+
+    /** 8 bit unsigned integer view. */
+    uint8_t         au8[8];
+    /** 16 bit unsigned integer view. */
+    uint16_t        au16[4];
+    /** 32 bit unsigned integer view. */
+    uint32_t        au32[2];
+    /** 64 bit unsigned integer view. */
+    uint64_t        au64[1];
+    /** Unsigned integer view. */
+    uint64_t        u;
+} X86DESC;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86DESC, 8);
+#endif
+#pragma pack()
+/** Pointer to descriptor table entry. */
+typedef X86DESC *PX86DESC;
+/** Pointer to const descriptor table entry. */
+typedef const X86DESC *PCX86DESC;
+
+/** @def X86DESC_BASE
+ * Return the base address of a descriptor.
+ */
+#define X86DESC_BASE(a_pDesc) /*ASM-NOINC*/ \
+        (  ((uint32_t)((a_pDesc)->Gen.u8BaseHigh2) << 24) \
+         | (           (a_pDesc)->Gen.u8BaseHigh1  << 16) \
+         | (           (a_pDesc)->Gen.u16BaseLow        ) )
+
+/** @def X86DESC_LIMIT
+ * Return the limit of a descriptor.
+ */
+#define X86DESC_LIMIT(a_pDesc) /*ASM-NOINC*/ \
+        (  ((uint32_t)((a_pDesc)->Gen.u4LimitHigh) << 16) \
+         | (           (a_pDesc)->Gen.u16LimitLow       ) )
+
+/** @def X86DESC_LIMIT_G
+ * Return the limit of a descriptor with the granularity bit taken into account.
+ * @returns Selector limit (uint32_t).
+ * @param   a_pDesc     Pointer to the descriptor.
+ */
+#define X86DESC_LIMIT_G(a_pDesc) /*ASM-NOINC*/ \
+        ( (a_pDesc)->Gen.u1Granularity \
+         ? ( ( ((uint32_t)(a_pDesc)->Gen.u4LimitHigh << 16) | (a_pDesc)->Gen.u16LimitLow ) << 12 ) | UINT32_C(0xfff) \
+         :     ((uint32_t)(a_pDesc)->Gen.u4LimitHigh << 16) | (a_pDesc)->Gen.u16LimitLow \
+        )
+
+/** @def X86DESC_GET_HID_ATTR
+ * Get the descriptor attributes for the hidden register.
+ */
+#define X86DESC_GET_HID_ATTR(a_pDesc) /*ASM-NOINC*/ \
+        ( ((a_pDesc)->u >> (16+16+8)) & UINT32_C(0xf0ff) ) /** @todo do we have a define for 0xf0ff? */
+
+#ifndef VBOX_FOR_DTRACE_LIB
+
+/**
+ * 64 bits generic descriptor table entry
+ * Note: most of these bits have no meaning in long mode.
+ */
+#pragma pack(1)
+typedef struct X86DESC64GENERIC
+{
+    /** Limit - Low word - *IGNORED*. */
+    uint32_t    u16LimitLow : 16;
+    /** Base address - low word. - *IGNORED*
+     * Don't try set this to 24 because MSC is doing stupid things then. */
+    uint32_t    u16BaseLow : 16;
+    /** Base address - first 8 bits of high word. - *IGNORED* */
+    uint32_t    u8BaseHigh1 : 8;
+    /** Segment Type. */
+    uint32_t    u4Type : 4;
+    /** Descriptor Type. System(=0) or code/data selector */
+    uint32_t    u1DescType : 1;
+    /** Descriptor Privilege level. */
+    uint32_t    u2Dpl : 2;
+    /** Flags selector present(=1) or not. */
+    uint32_t    u1Present : 1;
+    /** Segment limit 16-19. - *IGNORED* */
+    uint32_t    u4LimitHigh : 4;
+    /** Available for system software. - *IGNORED* */
+    uint32_t    u1Available : 1;
+    /** Long mode flag. */
+    uint32_t    u1Long : 1;
+    /** This flags meaning depends on the segment type. Try make sense out
+     * of the intel manual yourself.  */
+    uint32_t    u1DefBig : 1;
+    /** Granularity of the limit. If set 4KB granularity is used, if
+     * clear byte. - *IGNORED* */
+    uint32_t    u1Granularity : 1;
+    /** Base address - highest 8 bits. - *IGNORED* */
+    uint32_t    u8BaseHigh2 : 8;
+    /** Base address - bits 63-32. */
+    uint32_t    u32BaseHigh3    : 32;
+    uint32_t    u8Reserved      : 8;
+    uint32_t    u5Zeros         : 5;
+    uint32_t    u19Reserved     : 19;
+} X86DESC64GENERIC;
+#pragma pack()
+/** Pointer to a generic descriptor entry. */
+typedef X86DESC64GENERIC *PX86DESC64GENERIC;
+/** Pointer to a const generic descriptor entry. */
+typedef const X86DESC64GENERIC *PCX86DESC64GENERIC;
+
+/**
+ * System descriptor table entry (64 bits)
+ *
+ * @remarks This is, save a couple of comments, identical to X86DESC64GENERIC...
+ */
+#pragma pack(1)
+typedef struct X86DESC64SYSTEM
+{
+    /** Limit - Low word. */
+    uint32_t    u16LimitLow     : 16;
+    /** Base address - low word.
+     * Don't try set this to 24 because MSC is doing stupid things then. */
+    uint32_t    u16BaseLow      : 16;
+    /** Base address - first 8 bits of high word. */
+    uint32_t    u8BaseHigh1     : 8;
+    /** Segment Type. */
+    uint32_t    u4Type          : 4;
+    /** Descriptor Type. System(=0) or code/data selector */
+    uint32_t    u1DescType      : 1;
+    /** Descriptor Privilege level. */
+    uint32_t    u2Dpl           : 2;
+    /** Flags selector present(=1) or not. */
+    uint32_t    u1Present       : 1;
+    /** Segment limit 16-19. */
+    uint32_t    u4LimitHigh     : 4;
+    /** Available for system software. */
+    uint32_t    u1Available     : 1;
+    /** Reserved - 0. */
+    uint32_t    u1Reserved      : 1;
+    /** This flags meaning depends on the segment type. Try make sense out
+     * of the intel manual yourself.  */
+    uint32_t    u1DefBig        : 1;
+    /** Granularity of the limit. If set 4KB granularity is used, if
+     * clear byte. */
+    uint32_t    u1Granularity   : 1;
+    /** Base address - bits 31-24. */
+    uint32_t    u8BaseHigh2     : 8;
+    /** Base address - bits 63-32. */
+    uint32_t    u32BaseHigh3    : 32;
+    uint32_t    u8Reserved      : 8;
+    uint32_t    u5Zeros         : 5;
+    uint32_t    u19Reserved     : 19;
+} X86DESC64SYSTEM;
+#pragma pack()
+/** Pointer to a system descriptor entry. */
+typedef X86DESC64SYSTEM *PX86DESC64SYSTEM;
+/** Pointer to a const system descriptor entry. */
+typedef const X86DESC64SYSTEM *PCX86DESC64SYSTEM;
+
+/**
+ * Call-, Interrupt-, Trap- or Task-gate descriptor (64-bit).
+ */
+typedef struct X86DESC64GATE
+{
+    /** Target code segment offset - Low word. */
+    uint32_t    u16OffsetLow : 16;
+    /** Target code segment selector. */
+    uint32_t    u16Sel : 16;
+    /** Interrupt stack table for interrupt- and trap-gates.
+     * Ignored by call-gates. */
+    uint32_t    u3IST : 3;
+    /** Reserved / ignored. */
+    uint32_t    u5Reserved : 5;
+    /** Segment Type. */
+    uint32_t    u4Type : 4;
+    /** Descriptor Type (0 = system). */
+    uint32_t    u1DescType : 1;
+    /** Descriptor Privilege level. */
+    uint32_t    u2Dpl : 2;
+    /** Flags selector present(=1) or not. */
+    uint32_t    u1Present : 1;
+    /** Target code segment offset - High word.
+     * Ignored if task-gate. */
+    uint32_t    u16OffsetHigh : 16;
+    /** Target code segment offset - Top dword.
+     * Ignored if task-gate. */
+    uint32_t    u32OffsetTop : 32;
+    /** Reserved / ignored / must be zero.
+     * For call-gates bits 8 thru 12 must be zero, the other gates ignores this. */
+    uint32_t    u32Reserved : 32;
+} X86DESC64GATE;
+AssertCompileSize(X86DESC64GATE, 16);
+/** Pointer to a Call-, Interrupt-, Trap- or Task-gate descriptor entry. */
+typedef X86DESC64GATE *PX86DESC64GATE;
+/** Pointer to a const Call-, Interrupt-, Trap- or Task-gate descriptor entry. */
+typedef const X86DESC64GATE *PCX86DESC64GATE;
+
+#endif /* VBOX_FOR_DTRACE_LIB */
+
+/**
+ * Descriptor table entry.
+ */
+#pragma pack(1)
+typedef union X86DESC64
+{
+#ifndef VBOX_FOR_DTRACE_LIB
+    /** Generic descriptor view. */
+    X86DESC64GENERIC    Gen;
+    /** System descriptor view. */
+    X86DESC64SYSTEM     System;
+    /** Gate descriptor view. */
+    X86DESC64GATE       Gate;
+#endif
+
+    /** 8 bit unsigned integer view. */
+    uint8_t             au8[16];
+    /** 16 bit unsigned integer view. */
+    uint16_t            au16[8];
+    /** 32 bit unsigned integer view. */
+    uint32_t            au32[4];
+    /** 64 bit unsigned integer view. */
+    uint64_t            au64[2];
+} X86DESC64;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86DESC64, 16);
+#endif
+#pragma pack()
+/** Pointer to descriptor table entry. */
+typedef X86DESC64 *PX86DESC64;
+/** Pointer to const descriptor table entry. */
+typedef const X86DESC64 *PCX86DESC64;
+
+/** @def X86DESC64_BASE
+ * Return the base of a 64-bit descriptor.
+ */
+#define X86DESC64_BASE(a_pDesc) /*ASM-NOINC*/ \
+        (  ((uint64_t)((a_pDesc)->Gen.u32BaseHigh3) << 32) \
+         | ((uint32_t)((a_pDesc)->Gen.u8BaseHigh2)  << 24) \
+         | (           (a_pDesc)->Gen.u8BaseHigh1   << 16) \
+         | (           (a_pDesc)->Gen.u16BaseLow         ) )
+
+
+
+/** @name Host system descriptor table entry - Use with care!
+ * @{ */
+/** Host system descriptor table entry. */
+#if HC_ARCH_BITS == 64
+typedef X86DESC64   X86DESCHC;
+#else
+typedef X86DESC     X86DESCHC;
+#endif
+/** Pointer to a host system descriptor table entry. */
+#if HC_ARCH_BITS == 64
+typedef PX86DESC64  PX86DESCHC;
+#else
+typedef PX86DESC    PX86DESCHC;
+#endif
+/** Pointer to a const host system descriptor table entry. */
+#if HC_ARCH_BITS == 64
+typedef PCX86DESC64 PCX86DESCHC;
+#else
+typedef PCX86DESC   PCX86DESCHC;
+#endif
+/** @} */
+
+
+/** @name Selector Descriptor Types.
+ * @{
+ */
+
+/** @name Non-System Selector Types.
+ * @{ */
+/** Code(=set)/Data(=clear) bit. */
+#define X86_SEL_TYPE_CODE                   8
+/** Memory(=set)/System(=clear) bit. */
+#define X86_SEL_TYPE_MEMORY                 RT_BIT_32(4)
+/** Accessed bit. */
+#define X86_SEL_TYPE_ACCESSED               1
+/** Expand down bit (for data selectors only). */
+#define X86_SEL_TYPE_DOWN                   4
+/** Conforming bit (for code selectors only). */
+#define X86_SEL_TYPE_CONF                   4
+/** Write bit (for data selectors only). */
+#define X86_SEL_TYPE_WRITE                  2
+/** Read bit (for code selectors only). */
+#define X86_SEL_TYPE_READ                   2
+/** The bit number of the code segment read bit (relative to u4Type). */
+#define X86_SEL_TYPE_READ_BIT               1
+
+/** Read only selector type. */
+#define X86_SEL_TYPE_RO                     0
+/** Accessed read only selector type. */
+#define X86_SEL_TYPE_RO_ACC                (0 | X86_SEL_TYPE_ACCESSED)
+/** Read write selector type. */
+#define X86_SEL_TYPE_RW                     2
+/** Accessed read write selector type. */
+#define X86_SEL_TYPE_RW_ACC                (2 | X86_SEL_TYPE_ACCESSED)
+/** Expand down read only selector type. */
+#define X86_SEL_TYPE_RO_DOWN                4
+/** Accessed expand down read only selector type. */
+#define X86_SEL_TYPE_RO_DOWN_ACC           (4 | X86_SEL_TYPE_ACCESSED)
+/** Expand down read write selector type. */
+#define X86_SEL_TYPE_RW_DOWN                6
+/** Accessed expand down read write selector type. */
+#define X86_SEL_TYPE_RW_DOWN_ACC           (6 | X86_SEL_TYPE_ACCESSED)
+/** Execute only selector type. */
+#define X86_SEL_TYPE_EO                    (0 | X86_SEL_TYPE_CODE)
+/** Accessed execute only selector type. */
+#define X86_SEL_TYPE_EO_ACC                (0 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED)
+/** Execute and read selector type. */
+#define X86_SEL_TYPE_ER                    (2 | X86_SEL_TYPE_CODE)
+/** Accessed execute and read selector type. */
+#define X86_SEL_TYPE_ER_ACC                (2 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED)
+/** Conforming execute only selector type. */
+#define X86_SEL_TYPE_EO_CONF               (4 | X86_SEL_TYPE_CODE)
+/** Accessed Conforming execute only selector type. */
+#define X86_SEL_TYPE_EO_CONF_ACC           (4 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED)
+/** Conforming execute and write selector type. */
+#define X86_SEL_TYPE_ER_CONF               (6 | X86_SEL_TYPE_CODE)
+/** Accessed Conforming execute and write selector type. */
+#define X86_SEL_TYPE_ER_CONF_ACC           (6 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED)
+/** @} */
+
+
+/** @name System Selector Types.
+ * @{ */
+/** The TSS busy bit mask. */
+#define X86_SEL_TYPE_SYS_TSS_BUSY_MASK      2
+
+/** Undefined system selector type. */
+#define X86_SEL_TYPE_SYS_UNDEFINED          0
+/** 286 TSS selector. */
+#define X86_SEL_TYPE_SYS_286_TSS_AVAIL      1
+/** LDT selector. */
+#define X86_SEL_TYPE_SYS_LDT                2
+/** 286 TSS selector - Busy. */
+#define X86_SEL_TYPE_SYS_286_TSS_BUSY       3
+/** 286 Callgate selector. */
+#define X86_SEL_TYPE_SYS_286_CALL_GATE      4
+/** Taskgate selector. */
+#define X86_SEL_TYPE_SYS_TASK_GATE          5
+/** 286 Interrupt gate selector. */
+#define X86_SEL_TYPE_SYS_286_INT_GATE       6
+/** 286 Trapgate selector. */
+#define X86_SEL_TYPE_SYS_286_TRAP_GATE      7
+/** Undefined system selector. */
+#define X86_SEL_TYPE_SYS_UNDEFINED2         8
+/** 386 TSS selector. */
+#define X86_SEL_TYPE_SYS_386_TSS_AVAIL      9
+/** Undefined system selector. */
+#define X86_SEL_TYPE_SYS_UNDEFINED3         0xA
+/** 386 TSS selector - Busy. */
+#define X86_SEL_TYPE_SYS_386_TSS_BUSY       0xB
+/** 386 Callgate selector. */
+#define X86_SEL_TYPE_SYS_386_CALL_GATE      0xC
+/** Undefined system selector. */
+#define X86_SEL_TYPE_SYS_UNDEFINED4         0xD
+/** 386 Interruptgate selector. */
+#define X86_SEL_TYPE_SYS_386_INT_GATE       0xE
+/** 386 Trapgate selector. */
+#define X86_SEL_TYPE_SYS_386_TRAP_GATE      0xF
+/** @} */
+
+/** @name AMD64 System Selector Types.
+ * @{ */
+/** LDT selector. */
+#define AMD64_SEL_TYPE_SYS_LDT              2
+/** TSS selector - Busy. */
+#define AMD64_SEL_TYPE_SYS_TSS_AVAIL        9
+/** TSS selector - Busy. */
+#define AMD64_SEL_TYPE_SYS_TSS_BUSY         0xB
+/** Callgate selector. */
+#define AMD64_SEL_TYPE_SYS_CALL_GATE        0xC
+/** Interruptgate selector. */
+#define AMD64_SEL_TYPE_SYS_INT_GATE         0xE
+/** Trapgate selector. */
+#define AMD64_SEL_TYPE_SYS_TRAP_GATE        0xF
+/** @} */
+
+/** @} */
+
+
+/** @name Descriptor Table Entry Flag Masks.
+ * These are for the 2nd 32-bit word of a descriptor.
+ * @{ */
+/** Bits 8-11 - TYPE - Descriptor type mask. */
+#define X86_DESC_TYPE_MASK                  (RT_BIT_32(8) | RT_BIT_32(9) | RT_BIT_32(10) | RT_BIT_32(11))
+/** Bit 12 - S - System (=0) or Code/Data (=1). */
+#define X86_DESC_S                          RT_BIT_32(12)
+/** Bits 13-14 - DPL - Descriptor Privilege Level. */
+#define X86_DESC_DPL                       (RT_BIT_32(13) | RT_BIT_32(14))
+/** Bit 15 - P - Present. */
+#define X86_DESC_P                          RT_BIT_32(15)
+/** Bit 20 - AVL - Available for system software. */
+#define X86_DESC_AVL                        RT_BIT_32(20)
+/** Bit 22 - DB - Default operation size. 0 = 16 bit, 1 = 32 bit. */
+#define X86_DESC_DB                         RT_BIT_32(22)
+/** Bit 23 - G - Granularity of the limit. If set 4KB granularity is
+ * used, if clear byte. */
+#define X86_DESC_G                          RT_BIT_32(23)
+/** @} */
+
+/** @} */
+
+
+/** @name Task Segments.
+ * @{
+ */
+
+/**
+ * The minimum TSS descriptor limit for 286 tasks.
+ */
+#define X86_SEL_TYPE_SYS_286_TSS_LIMIT_MIN      0x2b
+
+/**
+ * The minimum TSS descriptor segment limit for 386 tasks.
+ */
+#define X86_SEL_TYPE_SYS_386_TSS_LIMIT_MIN      0x67
+
+/**
+ * 16-bit Task Segment (TSS).
+ */
+#pragma pack(1)
+typedef struct X86TSS16
+{
+    /** Back link to previous task. (static) */
+    RTSEL       selPrev;
+    /** Ring-0 stack pointer. (static) */
+    uint16_t    sp0;
+    /** Ring-0 stack segment. (static) */
+    RTSEL       ss0;
+    /** Ring-1 stack pointer. (static) */
+    uint16_t    sp1;
+    /** Ring-1 stack segment. (static) */
+    RTSEL       ss1;
+    /** Ring-2 stack pointer. (static) */
+    uint16_t    sp2;
+    /** Ring-2 stack segment. (static) */
+    RTSEL       ss2;
+    /** IP before task switch. */
+    uint16_t    ip;
+    /** FLAGS before task switch. */
+    uint16_t    flags;
+    /** AX before task switch. */
+    uint16_t    ax;
+    /** CX before task switch. */
+    uint16_t    cx;
+    /** DX before task switch. */
+    uint16_t    dx;
+    /** BX before task switch. */
+    uint16_t    bx;
+    /** SP before task switch. */
+    uint16_t    sp;
+    /** BP before task switch. */
+    uint16_t    bp;
+    /** SI before task switch. */
+    uint16_t    si;
+    /** DI before task switch. */
+    uint16_t    di;
+    /** ES before task switch. */
+    RTSEL       es;
+    /** CS before task switch. */
+    RTSEL       cs;
+    /** SS before task switch. */
+    RTSEL       ss;
+    /** DS before task switch. */
+    RTSEL       ds;
+    /** LDTR before task switch. */
+    RTSEL       selLdt;
+} X86TSS16;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86TSS16, X86_SEL_TYPE_SYS_286_TSS_LIMIT_MIN + 1);
+#endif
+#pragma pack()
+/** Pointer to a 16-bit task segment. */
+typedef X86TSS16 *PX86TSS16;
+/** Pointer to a const 16-bit task segment. */
+typedef const X86TSS16 *PCX86TSS16;
+
+
+/**
+ * 32-bit Task Segment (TSS).
+ */
+#pragma pack(1)
+typedef struct X86TSS32
+{
+    /** Back link to previous task. (static) */
+    RTSEL       selPrev;
+    uint16_t    padding1;
+    /** Ring-0 stack pointer. (static) */
+    uint32_t    esp0;
+    /** Ring-0 stack segment. (static) */
+    RTSEL       ss0;
+    uint16_t    padding_ss0;
+    /** Ring-1 stack pointer. (static) */
+    uint32_t    esp1;
+    /** Ring-1 stack segment. (static) */
+    RTSEL       ss1;
+    uint16_t    padding_ss1;
+    /** Ring-2 stack pointer. (static) */
+    uint32_t    esp2;
+    /** Ring-2 stack segment. (static) */
+    RTSEL       ss2;
+    uint16_t    padding_ss2;
+    /** Page directory for the task. (static) */
+    uint32_t    cr3;
+    /** EIP before task switch. */
+    uint32_t    eip;
+    /** EFLAGS before task switch. */
+    uint32_t    eflags;
+    /** EAX before task switch. */
+    uint32_t    eax;
+    /** ECX before task switch. */
+    uint32_t    ecx;
+    /** EDX before task switch. */
+    uint32_t    edx;
+    /** EBX before task switch. */
+    uint32_t    ebx;
+    /** ESP before task switch. */
+    uint32_t    esp;
+    /** EBP before task switch. */
+    uint32_t    ebp;
+    /** ESI before task switch. */
+    uint32_t    esi;
+    /** EDI before task switch. */
+    uint32_t    edi;
+    /** ES before task switch. */
+    RTSEL       es;
+    uint16_t    padding_es;
+    /** CS before task switch. */
+    RTSEL       cs;
+    uint16_t    padding_cs;
+    /** SS before task switch. */
+    RTSEL       ss;
+    uint16_t    padding_ss;
+    /** DS before task switch. */
+    RTSEL       ds;
+    uint16_t    padding_ds;
+    /** FS before task switch. */
+    RTSEL       fs;
+    uint16_t    padding_fs;
+    /** GS before task switch. */
+    RTSEL       gs;
+    uint16_t    padding_gs;
+    /** LDTR before task switch. */
+    RTSEL       selLdt;
+    uint16_t    padding_ldt;
+    /** Debug trap flag */
+    uint16_t    fDebugTrap;
+    /** Offset relative to the TSS of the start of the I/O Bitmap
+     * and the end of the interrupt redirection bitmap. */
+    uint16_t    offIoBitmap;
+} X86TSS32;
+#pragma pack()
+/** Pointer to task segment. */
+typedef X86TSS32 *PX86TSS32;
+/** Pointer to const task segment. */
+typedef const X86TSS32 *PCX86TSS32;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86TSS32, X86_SEL_TYPE_SYS_386_TSS_LIMIT_MIN + 1);
+AssertCompileMemberOffset(X86TSS32, cr3, 28);
+AssertCompileMemberOffset(X86TSS32, offIoBitmap, 102);
+#endif
+
+/**
+ * 64-bit Task segment.
+ */
+#pragma pack(1)
+typedef struct X86TSS64
+{
+    /** Reserved. */
+    uint32_t    u32Reserved;
+    /** Ring-0 stack pointer. (static) */
+    uint64_t    rsp0;
+    /** Ring-1 stack pointer. (static) */
+    uint64_t    rsp1;
+    /** Ring-2 stack pointer. (static) */
+    uint64_t    rsp2;
+    /** Reserved. */
+    uint32_t    u32Reserved2[2];
+    /* IST */
+    uint64_t    ist1;
+    uint64_t    ist2;
+    uint64_t    ist3;
+    uint64_t    ist4;
+    uint64_t    ist5;
+    uint64_t    ist6;
+    uint64_t    ist7;
+    /* Reserved. */
+    uint16_t    u16Reserved[5];
+    /** Offset relative to the TSS of the start of the I/O Bitmap
+     * and the end of the interrupt redirection bitmap. */
+    uint16_t    offIoBitmap;
+} X86TSS64;
+#pragma pack()
+/** Pointer to a 64-bit task segment. */
+typedef X86TSS64 *PX86TSS64;
+/** Pointer to a const 64-bit task segment. */
+typedef const X86TSS64 *PCX86TSS64;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86TSS64, X86_SEL_TYPE_SYS_386_TSS_LIMIT_MIN + 1);
+#endif
+
+/** @} */
+
+
+/** @name Selectors.
+ * @{
+ */
+
+/**
+ * The shift used to convert a selector from and to index an index (C).
+ */
+#define X86_SEL_SHIFT           3
+
+/**
+ * The mask used to mask off the table indicator and RPL of an selector.
+ */
+#define X86_SEL_MASK            0xfff8U
+
+/**
+ * The mask used to mask off the RPL of an selector.
+ * This is suitable for checking for NULL selectors.
+ */
+#define X86_SEL_MASK_OFF_RPL    0xfffcU
+
+/**
+ * The bit indicating that a selector is in the LDT and not in the GDT.
+ */
+#define X86_SEL_LDT             0x0004U
+
+/**
+ * The bit mask for getting the RPL of a selector.
+ */
+#define X86_SEL_RPL             0x0003U
+
+/**
+ * The mask covering both RPL and LDT.
+ * This is incidentally the same as sizeof(X86DESC) - 1, so good for limit
+ * checks.
+ */
+#define X86_SEL_RPL_LDT         0x0007U
+
+/** @} */
+
+
+/**
+ * x86 Exceptions/Faults/Traps.
+ */
+typedef enum X86XCPT
+{
+    /** \#DE - Divide error. */
+    X86_XCPT_DE = 0x00,
+    /** \#DB - Debug event (single step, DRx, ..) */
+    X86_XCPT_DB = 0x01,
+    /** NMI - Non-Maskable Interrupt */
+    X86_XCPT_NMI = 0x02,
+    /** \#BP - Breakpoint (INT3). */
+    X86_XCPT_BP = 0x03,
+    /** \#OF - Overflow (INTO). */
+    X86_XCPT_OF = 0x04,
+    /** \#BR - Bound range exceeded (BOUND). */
+    X86_XCPT_BR = 0x05,
+    /** \#UD - Undefined opcode. */
+    X86_XCPT_UD = 0x06,
+    /** \#NM - Device not available (math coprocessor device). */
+    X86_XCPT_NM = 0x07,
+    /** \#DF - Double fault. */
+    X86_XCPT_DF = 0x08,
+    /** ??? - Coprocessor segment overrun (obsolete). */
+    X86_XCPT_CO_SEG_OVERRUN = 0x09,
+    /** \#TS - Taskswitch (TSS). */
+    X86_XCPT_TS = 0x0a,
+    /** \#NP - Segment no present. */
+    X86_XCPT_NP = 0x0b,
+    /** \#SS - Stack segment fault. */
+    X86_XCPT_SS = 0x0c,
+    /** \#GP - General protection fault. */
+    X86_XCPT_GP = 0x0d,
+    /** \#PF - Page fault. */
+    X86_XCPT_PF = 0x0e,
+    /* 0x0f is reserved (to avoid conflict with spurious interrupts in BIOS setup). */
+    /** \#MF - Math fault (FPU). */
+    X86_XCPT_MF = 0x10,
+    /** \#AC - Alignment check. */
+    X86_XCPT_AC = 0x11,
+    /** \#MC - Machine check. */
+    X86_XCPT_MC = 0x12,
+    /** \#XF - SIMD Floating-Pointer Exception. */
+    X86_XCPT_XF = 0x13,
+    /** \#VE - Virtualization Exception. */
+    X86_XCPT_VE = 0x14,
+    /** \#SX - Security Exception. */
+    X86_XCPT_SX = 0x1e
+} X86XCPT;
+/** Pointer to a x86 exception code. */
+typedef X86XCPT *PX86XCPT;
+/** Pointer to a const x86 exception code. */
+typedef const X86XCPT *PCX86XCPT;
+/** The last valid (currently reserved) exception value. */
+#define X86_XCPT_LAST               0x1f
+
+
+/** @name Trap Error Codes
+ * @{
+ */
+/** External indicator. */
+#define X86_TRAP_ERR_EXTERNAL       1
+/** IDT indicator. */
+#define X86_TRAP_ERR_IDT            2
+/** Descriptor table indicator - If set LDT, if clear GDT. */
+#define X86_TRAP_ERR_TI             4
+/** Mask for getting the selector. */
+#define X86_TRAP_ERR_SEL_MASK       0xfff8
+/** Shift for getting the selector table index (C type index). */
+#define X86_TRAP_ERR_SEL_SHIFT      3
+/** @} */
+
+
+/** @name \#PF Trap Error Codes
+ * @{
+ */
+/** Bit 0 -   P - Not present (clear) or page level protection (set) fault. */
+#define X86_TRAP_PF_P               RT_BIT_32(0)
+/** Bit 1 - R/W - Read (clear) or write (set) access. */
+#define X86_TRAP_PF_RW              RT_BIT_32(1)
+/** Bit 2 - U/S - CPU executing in user mode (set) or supervisor mode (clear). */
+#define X86_TRAP_PF_US              RT_BIT_32(2)
+/** Bit 3 - RSVD- Reserved bit violation (set), i.e. reserved bit was set to 1. */
+#define X86_TRAP_PF_RSVD            RT_BIT_32(3)
+/** Bit 4 - I/D - Instruction fetch (set) / Data access (clear) - PAE + NXE. */
+#define X86_TRAP_PF_ID              RT_BIT_32(4)
+/** Bit 5 - PK - Protection-key violation (AMD64 mode only). */
+#define X86_TRAP_PF_PK              RT_BIT_32(5)
+/** @} */
+
+#pragma pack(1)
+/**
+ * 16-bit IDTR.
+ */
+typedef struct X86IDTR16
+{
+    /** Offset. */
+    uint16_t    offSel;
+    /** Selector. */
+    uint16_t    uSel;
+} X86IDTR16, *PX86IDTR16;
+#pragma pack()
+
+#pragma pack(1)
+/**
+ * 32-bit IDTR/GDTR.
+ */
+typedef struct X86XDTR32
+{
+    /** Size of the descriptor table. */
+    uint16_t    cb;
+    /** Address of the descriptor table. */
+#ifndef VBOX_FOR_DTRACE_LIB
+    uint32_t    uAddr;
+#else
+    uint16_t    au16Addr[2];
+#endif
+} X86XDTR32, *PX86XDTR32;
+#pragma pack()
+
+#pragma pack(1)
+/**
+ * 64-bit IDTR/GDTR.
+ */
+typedef struct X86XDTR64
+{
+    /** Size of the descriptor table. */
+    uint16_t    cb;
+    /** Address of the descriptor table. */
+#ifndef VBOX_FOR_DTRACE_LIB
+    uint64_t    uAddr;
+#else
+    uint16_t    au16Addr[4];
+#endif
+} X86XDTR64, *PX86XDTR64;
+#pragma pack()
+
+
+/** @name ModR/M
+ * @{ */
+#define X86_MODRM_RM_MASK       UINT8_C(0x07)
+#define X86_MODRM_REG_MASK      UINT8_C(0x38)
+#define X86_MODRM_REG_SMASK     UINT8_C(0x07)
+#define X86_MODRM_REG_SHIFT     3
+#define X86_MODRM_MOD_MASK      UINT8_C(0xc0)
+#define X86_MODRM_MOD_SMASK     UINT8_C(0x03)
+#define X86_MODRM_MOD_SHIFT     6
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompile((X86_MODRM_RM_MASK | X86_MODRM_REG_MASK | X86_MODRM_MOD_MASK) == 0xff);
+AssertCompile((X86_MODRM_REG_MASK >> X86_MODRM_REG_SHIFT) == X86_MODRM_REG_SMASK);
+AssertCompile((X86_MODRM_MOD_MASK >> X86_MODRM_MOD_SHIFT) == X86_MODRM_MOD_SMASK);
+/** @def X86_MODRM_MAKE
+ * @param   a_Mod       The mod value (0..3).
+ * @param   a_Reg       The register value (0..7).
+ * @param   a_RegMem    The register or memory value (0..7). */
+# define X86_MODRM_MAKE(a_Mod, a_Reg, a_RegMem) (((a_Mod) << X86_MODRM_MOD_SHIFT) | ((a_Reg) << X86_MODRM_REG_SHIFT) | (a_RegMem))
+#endif
+/** @} */
+
+/** @name SIB
+ * @{ */
+#define X86_SIB_BASE_MASK     UINT8_C(0x07)
+#define X86_SIB_INDEX_MASK    UINT8_C(0x38)
+#define X86_SIB_INDEX_SMASK   UINT8_C(0x07)
+#define X86_SIB_INDEX_SHIFT   3
+#define X86_SIB_SCALE_MASK    UINT8_C(0xc0)
+#define X86_SIB_SCALE_SMASK   UINT8_C(0x03)
+#define X86_SIB_SCALE_SHIFT   6
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompile((X86_SIB_BASE_MASK | X86_SIB_INDEX_MASK | X86_SIB_SCALE_MASK) == 0xff);
+AssertCompile((X86_SIB_INDEX_MASK >> X86_SIB_INDEX_SHIFT) == X86_SIB_INDEX_SMASK);
+AssertCompile((X86_SIB_SCALE_MASK >> X86_SIB_SCALE_SHIFT) == X86_SIB_SCALE_SMASK);
+#endif
+/** @} */
+
+/** @name General register indexes
+ * @{ */
+#define X86_GREG_xAX            0
+#define X86_GREG_xCX            1
+#define X86_GREG_xDX            2
+#define X86_GREG_xBX            3
+#define X86_GREG_xSP            4
+#define X86_GREG_xBP            5
+#define X86_GREG_xSI            6
+#define X86_GREG_xDI            7
+#define X86_GREG_x8             8
+#define X86_GREG_x9             9
+#define X86_GREG_x10            10
+#define X86_GREG_x11            11
+#define X86_GREG_x12            12
+#define X86_GREG_x13            13
+#define X86_GREG_x14            14
+#define X86_GREG_x15            15
+/** @} */
+
+/** @name X86_SREG_XXX - Segment register indexes.
+ * @{ */
+#define X86_SREG_ES             0
+#define X86_SREG_CS             1
+#define X86_SREG_SS             2
+#define X86_SREG_DS             3
+#define X86_SREG_FS             4
+#define X86_SREG_GS             5
+/** @} */
+/** Segment register count. */
+#define X86_SREG_COUNT          6
+
+
+/** @name X86_OP_XXX - Prefixes
+ * @{ */
+#define X86_OP_PRF_CS           UINT8_C(0x2e)
+#define X86_OP_PRF_SS           UINT8_C(0x36)
+#define X86_OP_PRF_DS           UINT8_C(0x3e)
+#define X86_OP_PRF_ES           UINT8_C(0x26)
+#define X86_OP_PRF_FS           UINT8_C(0x64)
+#define X86_OP_PRF_GS           UINT8_C(0x65)
+#define X86_OP_PRF_SIZE_OP      UINT8_C(0x66)
+#define X86_OP_PRF_SIZE_ADDR    UINT8_C(0x67)
+#define X86_OP_PRF_LOCK         UINT8_C(0xf0)
+#define X86_OP_PRF_REPZ         UINT8_C(0xf3)
+#define X86_OP_PRF_REPNZ        UINT8_C(0xf2)
+#define X86_OP_REX_B            UINT8_C(0x41)
+#define X86_OP_REX_X            UINT8_C(0x42)
+#define X86_OP_REX_R            UINT8_C(0x44)
+#define X86_OP_REX_W            UINT8_C(0x48)
+/** @} */
+
+
+/** @} */
+
+#endif
+
diff --git a/ubuntu/vbox/include/the-linux-kernel.h b/ubuntu/vbox/include/the-linux-kernel.h
new file mode 100644 (file)
index 0000000..3a17bd1
--- /dev/null
@@ -0,0 +1,452 @@
+/* $Id: the-linux-kernel.h $ */
+/** @file
+ * IPRT - Include all necessary headers for the Linux kernel.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___the_linux_kernel_h
+#define ___the_linux_kernel_h
+
+/*
+ * Include iprt/types.h to install the bool wrappers.
+ * Then use the linux bool type for all the stuff include here.
+ */
+#include <iprt/types.h>
+#define bool linux_bool
+
+#if RT_GNUC_PREREQ(4, 6)
+# pragma GCC diagnostic push
+#endif
+#if RT_GNUC_PREREQ(4, 2)
+# pragma GCC diagnostic ignored "-Wunused-parameter"
+# if !defined(__cplusplus) && RT_GNUC_PREREQ(4, 3)
+#  pragma GCC diagnostic ignored "-Wold-style-declaration" /* 2.6.18-411.0.0.0.1.el5/build/include/asm/apic.h:110: warning: 'inline' is not at beginning of declaration [-Wold-style-declaration] */
+# endif
+#endif
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+# include <generated/autoconf.h>
+#else
+# ifndef AUTOCONF_INCLUDED
+#  include <linux/autoconf.h>
+# endif
+#endif
+
+/* We only support 2.4 and 2.6 series kernels */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+# error We only support 2.4 and 2.6 series kernels
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+# error We only support 2.4 and 2.6 series kernels
+#endif
+
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+# define MODVERSIONS
+# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 71)
+#  include <linux/modversions.h>
+# endif
+#endif
+#ifndef KBUILD_STR
+# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
+#  define KBUILD_STR(s) s
+# else
+#  define KBUILD_STR(s) #s
+# endif
+#endif
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+#  include <linux/kconfig.h> /* for macro IS_ENABLED */
+# endif
+#include <linux/string.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+# include <linux/semaphore.h>
+#else /* older kernels */
+# include <asm/semaphore.h>
+#endif /* older kernels */
+#include <linux/module.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+# include <linux/moduleparam.h>
+#endif
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+# include <linux/namei.h>
+#endif
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/sched.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+# include <linux/sched/rt.h>
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+# include <linux/sched/signal.h>
+# include <linux/sched/types.h>
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 7)
+# include <linux/jiffies.h>
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
+# include <linux/ktime.h>
+# include <linux/hrtimer.h>
+#endif
+#include <linux/wait.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 71)
+# include <linux/cpu.h>
+# include <linux/notifier.h>
+#endif
+/* For the basic additions module */
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/compiler.h>
+#ifndef HAVE_UNLOCKED_IOCTL /* linux/fs.h defines this */
+# include <linux/smp_lock.h>
+#endif
+/* For the shared folders module */
+#include <linux/vmalloc.h>
+#define wchar_t linux_wchar_t
+#include <linux/nls.h>
+#undef wchar_t
+#include <asm/mman.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/div64.h>
+
+/* For thread-context hooks. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) && defined(CONFIG_PREEMPT_NOTIFIERS)
+# include <linux/preempt.h>
+#endif
+
+/* for workqueue / task queues. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41)
+# include <linux/workqueue.h>
+#else
+# include <linux/tqueue.h>
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+# include <linux/kthread.h>
+#endif
+
+/* for cr4_init_shadow() / cpu_tlbstate. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 20, 0)
+# include <asm/tlbflush.h>
+#endif
+
+/* for set_pages_x() */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+# include <asm/set_memory.h>
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+# include <asm/smap.h>
+#else
+static inline void clac(void) { }
+static inline void stac(void) { }
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+# ifndef page_to_pfn
+#  define page_to_pfn(page) ((page) - mem_map)
+# endif
+#endif
+
+#ifndef DEFINE_WAIT
+# define DEFINE_WAIT(name) DECLARE_WAITQUEUE(name, current)
+#endif
+
+#ifndef __GFP_NOWARN
+# define __GFP_NOWARN 0
+#endif
+
+/*
+ * 2.4 / early 2.6 compatibility wrappers
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 7)
+
+# ifndef MAX_JIFFY_OFFSET
+#  define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
+# endif
+
+# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 29) || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+
+DECLINLINE(unsigned int) jiffies_to_msecs(unsigned long cJiffies)
+{
+#  if HZ <= 1000 && !(1000 % HZ)
+    return (1000 / HZ) * cJiffies;
+#  elif HZ > 1000 && !(HZ % 1000)
+    return (cJiffies + (HZ / 1000) - 1) / (HZ / 1000);
+#  else
+    return (cJiffies * 1000) / HZ;
+#  endif
+}
+
+DECLINLINE(unsigned long) msecs_to_jiffies(unsigned int cMillies)
+{
+#  if HZ > 1000
+    if (cMillies > jiffies_to_msecs(MAX_JIFFY_OFFSET))
+        return MAX_JIFFY_OFFSET;
+#  endif
+#  if HZ <= 1000 && !(1000 % HZ)
+    return (cMillies + (1000 / HZ) - 1) / (1000 / HZ);
+#  elif HZ > 1000 && !(HZ % 1000)
+    return cMillies * (HZ / 1000);
+#  else
+    return (cMillies * HZ + 999) / 1000;
+#  endif
+}
+
+# endif  /* < 2.4.29 || >= 2.6.0 */
+
+#endif /* < 2.6.7 */
+
+/*
+ * 2.4 compatibility wrappers
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+
+# define prepare_to_wait(q, wait, state) \
+    do { \
+        add_wait_queue(q, wait); \
+        set_current_state(state); \
+    } while (0)
+
+# define after_wait(wait) \
+    do { \
+        list_del_init(&(wait)->task_list); \
+    } while (0)
+
+# define finish_wait(q, wait) \
+    do { \
+        set_current_state(TASK_RUNNING); \
+        remove_wait_queue(q, wait); \
+    } while (0)
+
+#else /* >= 2.6.0 */
+
+# define after_wait(wait)       do {} while (0)
+
+#endif /* >= 2.6.0 */
+
+/** @def TICK_NSEC
+ * The time between ticks in nsec */
+#ifndef TICK_NSEC
+# define TICK_NSEC (1000000000UL / HZ)
+#endif
+
+/*
+ * This sucks soooo badly on x86! Why don't they export __PAGE_KERNEL_EXEC so PAGE_KERNEL_EXEC would be usable?
+ */
+#if   LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8) && defined(RT_ARCH_AMD64)
+# define MY_PAGE_KERNEL_EXEC    PAGE_KERNEL_EXEC
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8) && defined(PAGE_KERNEL_EXEC) && defined(CONFIG_X86_PAE)
+# ifdef __PAGE_KERNEL_EXEC
+   /* >= 2.6.27 */
+#  define MY_PAGE_KERNEL_EXEC   __pgprot(boot_cpu_has(X86_FEATURE_PGE) ? __PAGE_KERNEL_EXEC | _PAGE_GLOBAL : __PAGE_KERNEL_EXEC)
+# else
+#  define MY_PAGE_KERNEL_EXEC   __pgprot(boot_cpu_has(X86_FEATURE_PGE) ? _PAGE_KERNEL_EXEC | _PAGE_GLOBAL : _PAGE_KERNEL_EXEC)
+# endif
+#else
+# define MY_PAGE_KERNEL_EXEC    PAGE_KERNEL
+#endif
+
+
+/*
+ * The redhat hack section.
+ *  - The current hacks are for 2.4.21-15.EL only.
+ */
+#ifndef NO_REDHAT_HACKS
+/* accounting. */
+# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+#  ifdef VM_ACCOUNT
+#   define USE_RHEL4_MUNMAP
+#  endif
+# endif
+
+/* backported remap_page_range. */
+# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+#  include <asm/tlb.h>
+#  ifdef tlb_vma /* probably not good enough... */
+#   define HAVE_26_STYLE_REMAP_PAGE_RANGE 1
+#  endif
+# endif
+
+# ifndef RT_ARCH_AMD64
+/* In 2.6.9-22.ELsmp we have to call change_page_attr() twice when changing
+ * the page attributes from PAGE_KERNEL to something else, because there appears
+ * to be a bug in one of the many patches that redhat applied.
+ * It should be safe to do this on less buggy linux kernels too. ;-)
+ */
+#  define MY_CHANGE_PAGE_ATTR(pPages, cPages, prot) \
+    do { \
+        if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) \
+            change_page_attr(pPages, cPages, prot); \
+        change_page_attr(pPages, cPages, prot); \
+    } while (0)
+# endif  /* !RT_ARCH_AMD64 */
+#endif /* !NO_REDHAT_HACKS */
+
+#ifndef MY_CHANGE_PAGE_ATTR
+# ifdef RT_ARCH_AMD64 /** @todo This is a cheap hack, but it'll get around that 'else BUG();' in __change_page_attr().  */
+#  define MY_CHANGE_PAGE_ATTR(pPages, cPages, prot) \
+    do { \
+        change_page_attr(pPages, cPages, PAGE_KERNEL_NOCACHE); \
+        change_page_attr(pPages, cPages, prot); \
+    } while (0)
+# else
+#  define MY_CHANGE_PAGE_ATTR(pPages, cPages, prot) change_page_attr(pPages, cPages, prot)
+# endif
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+# define MY_SET_PAGES_EXEC(pPages, cPages)    set_pages_x(pPages, cPages)
+# define MY_SET_PAGES_NOEXEC(pPages, cPages)  set_pages_nx(pPages, cPages)
+#else
+# define MY_SET_PAGES_EXEC(pPages, cPages) \
+    do { \
+        if (pgprot_val(MY_PAGE_KERNEL_EXEC) != pgprot_val(PAGE_KERNEL)) \
+            MY_CHANGE_PAGE_ATTR(pPages, cPages, MY_PAGE_KERNEL_EXEC); \
+    } while (0)
+# define MY_SET_PAGES_NOEXEC(pPages, cPages) \
+    do { \
+        if (pgprot_val(MY_PAGE_KERNEL_EXEC) != pgprot_val(PAGE_KERNEL)) \
+            MY_CHANGE_PAGE_ATTR(pPages, cPages, PAGE_KERNEL); \
+    } while (0)
+#endif
+
+/** @def ONE_MSEC_IN_JIFFIES
+ * The number of jiffies that make up 1 millisecond. Must be at least 1! */
+#if HZ <= 1000
+# define ONE_MSEC_IN_JIFFIES       1
+#elif !(HZ % 1000)
+# define ONE_MSEC_IN_JIFFIES       (HZ / 1000)
+#else
+# define ONE_MSEC_IN_JIFFIES       ((HZ + 999) / 1000)
+# error "HZ is not a multiple of 1000, the GIP stuff won't work right!"
+#endif
+
+/*
+ * Stop using the linux bool type.
+ */
+#undef bool
+
+#if RT_GNUC_PREREQ(4, 6)
+# pragma GCC diagnostic pop
+#endif
+
+/*
+ * There are post-2.6.24 kernels (confusingly with unchanged version number)
+ * which eliminate macros which were marked as deprecated.
+ */
+#ifndef __attribute_used__
+#define __attribute_used__ __used
+#endif
+
+/**
+ * Hack for shortening pointers on linux so we can stuff more stuff into the
+ * task_struct::comm field. This is used by the semaphore code but put here
+ * because we don't have any better place atm. Don't use outside IPRT, please.
+ */
+#ifdef RT_ARCH_AMD64
+# define IPRT_DEBUG_SEMS_ADDRESS(addr)  ( ((long)(addr) & (long)~UINT64_C(0xfffffff000000000)) )
+#else
+# define IPRT_DEBUG_SEMS_ADDRESS(addr)  ( (long)(addr) )
+#endif
+
+/**
+ * Puts semaphore info into the task_struct::comm field if IPRT_DEBUG_SEMS is
+ * defined.
+ */
+#ifdef IPRT_DEBUG_SEMS
+# define IPRT_DEBUG_SEMS_STATE(pThis, chState) \
+    snprintf(current->comm, sizeof(current->comm), "%c%lx", (chState), IPRT_DEBUG_SEMS_ADDRESS(pThis));
+#else
+# define IPRT_DEBUG_SEMS_STATE(pThis, chState)  do {  } while (0)
+#endif
+
+/**
+ * Puts semaphore info into the task_struct::comm field if IPRT_DEBUG_SEMS is
+ * defined.
+ */
+#ifdef IPRT_DEBUG_SEMS
+# define IPRT_DEBUG_SEMS_STATE_RC(pThis, chState, rc) \
+    snprintf(current->comm, sizeof(current->comm), "%c%lx:%d", (chState), IPRT_DEBUG_SEMS_ADDRESS(pThis), rc);
+#else
+# define IPRT_DEBUG_SEMS_STATE_RC(pThis, chState, rc)  do {  } while (0)
+#endif
+
+/** @name Macros for preserving EFLAGS.AC on 3.19+/amd64  paranoid.
+ * The AMD 64 switch_to in macro in arch/x86/include/asm/switch_to.h stopped
+ * restoring flags.
+ * @{ */
+#if defined(CONFIG_X86_SMAP) || defined(RT_STRICT) || defined(IPRT_WITH_EFLAGS_AC_PRESERVING)
+# include <iprt/asm-amd64-x86.h>
+# define IPRT_X86_EFL_AC                    RT_BIT(18)
+# define IPRT_LINUX_SAVE_EFL_AC()           RTCCUINTREG fSavedEfl = ASMGetFlags()
+# define IPRT_LINUX_RESTORE_EFL_AC()        ASMSetFlags(fSavedEfl)
+# define IPRT_LINUX_RESTORE_EFL_ONLY_AC()   ASMChangeFlags(~IPRT_X86_EFL_AC, fSavedEfl & IPRT_X86_EFL_AC)
+#else
+# define IPRT_LINUX_SAVE_EFL_AC()           do { } while (0)
+# define IPRT_LINUX_RESTORE_EFL_AC()        do { } while (0)
+# define IPRT_LINUX_RESTORE_EFL_ONLY_AC()   do { } while (0)
+#endif
+/** @} */
+
+/*
+ * There are some conflicting defines in iprt/param.h, sort them out here.
+ */
+#ifndef ___iprt_param_h
+# undef PAGE_SIZE
+# undef PAGE_OFFSET_MASK
+# include <iprt/param.h>
+#endif
+
+/*
+ * Some global indicator macros.
+ */
+/** @def IPRT_LINUX_HAS_HRTIMER
+ * Whether the kernel support high resolution timers (Linux kernel versions
+ * 2.6.28 and later (hrtimer_add_expires_ns() & schedule_hrtimeout). */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+# define IPRT_LINUX_HAS_HRTIMER
+#endif
+
+/*
+ * Workqueue stuff, see initterm-r0drv-linux.c.
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41)
+typedef struct work_struct  RTR0LNXWORKQUEUEITEM;
+#else
+typedef struct tq_struct    RTR0LNXWORKQUEUEITEM;
+#endif
+DECLHIDDEN(void) rtR0LnxWorkqueuePush(RTR0LNXWORKQUEUEITEM *pWork, void (*pfnWorker)(RTR0LNXWORKQUEUEITEM *));
+DECLHIDDEN(void) rtR0LnxWorkqueueFlush(void);
+
+
+#endif
diff --git a/ubuntu/vbox/r0drv/alloc-r0drv.c b/ubuntu/vbox/r0drv/alloc-r0drv.c
new file mode 100644 (file)
index 0000000..ce142a6
--- /dev/null
@@ -0,0 +1,437 @@
+/* $Id: alloc-r0drv.cpp $ */
+/** @file
+ * IPRT - Memory Allocation, Ring-0 Driver.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define RTMEM_NO_WRAP_TO_EF_APIS
+#include <iprt/mem.h>
+#include "internal/iprt.h"
+
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# include <iprt/asm-amd64-x86.h>
+#endif
+#include <iprt/assert.h>
+#ifdef RT_MORE_STRICT
+# include <iprt/mp.h>
+#endif
+#include <iprt/param.h>
+#include <iprt/string.h>
+#include <iprt/thread.h>
+#include "r0drv/alloc-r0drv.h"
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+#ifdef RT_STRICT
+# define RTR0MEM_STRICT
+#endif
+
+#ifdef RTR0MEM_STRICT
+# define RTR0MEM_FENCE_EXTRA    16
+#else
+# define RTR0MEM_FENCE_EXTRA    0
+#endif
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+#ifdef RTR0MEM_STRICT
+/** Fence data. */
+static uint8_t const g_abFence[RTR0MEM_FENCE_EXTRA] =
+{
+    0x77, 0x88, 0x66, 0x99,  0x55, 0xaa, 0x44, 0xbb,
+    0x33, 0xcc, 0x22, 0xdd,  0x11, 0xee, 0x00, 0xff
+};
+#endif
+
+
+/**
+ * Wrapper around rtR0MemAllocEx.
+ *
+ * @returns Pointer to the allocated memory block header.
+ * @param   cb                  The number of bytes to allocate (sans header).
+ * @param   fFlags              The allocation flags.
+ */
+DECLINLINE(PRTMEMHDR) rtR0MemAlloc(size_t cb, uint32_t fFlags)
+{
+    PRTMEMHDR pHdr;
+    int rc = rtR0MemAllocEx(cb, fFlags, &pHdr);
+    if (RT_FAILURE(rc))
+        return NULL;
+    return pHdr;
+}
+
+
+RTDECL(void *)  RTMemTmpAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
+{
+    return RTMemAllocTag(cb, pszTag);
+}
+RT_EXPORT_SYMBOL(RTMemTmpAllocTag);
+
+
+RTDECL(void *)  RTMemTmpAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
+{
+    return RTMemAllocZTag(cb, pszTag);
+}
+RT_EXPORT_SYMBOL(RTMemTmpAllocZTag);
+
+
+RTDECL(void)    RTMemTmpFree(void *pv) RT_NO_THROW_DEF
+{
+    return RTMemFree(pv);
+}
+RT_EXPORT_SYMBOL(RTMemTmpFree);
+
+
+
+
+
+RTDECL(void *)  RTMemAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
+{
+    PRTMEMHDR pHdr;
+    RT_ASSERT_INTS_ON();
+    RT_NOREF_PV(pszTag);
+
+    pHdr = rtR0MemAlloc(cb + RTR0MEM_FENCE_EXTRA, 0);
+    if (pHdr)
+    {
+#ifdef RTR0MEM_STRICT
+        pHdr->cbReq = (uint32_t)cb; Assert(pHdr->cbReq == cb);
+        memcpy((uint8_t *)(pHdr + 1) + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
+#endif
+        return pHdr + 1;
+    }
+    return NULL;
+}
+RT_EXPORT_SYMBOL(RTMemAllocTag);
+
+
+RTDECL(void *)  RTMemAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
+{
+    PRTMEMHDR pHdr;
+    RT_ASSERT_INTS_ON();
+    RT_NOREF_PV(pszTag);
+
+    pHdr = rtR0MemAlloc(cb + RTR0MEM_FENCE_EXTRA, RTMEMHDR_FLAG_ZEROED);
+    if (pHdr)
+    {
+#ifdef RTR0MEM_STRICT
+        pHdr->cbReq = (uint32_t)cb; Assert(pHdr->cbReq == cb);
+        memcpy((uint8_t *)(pHdr + 1) + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
+        return memset(pHdr + 1, 0, cb);
+#else
+        return memset(pHdr + 1, 0, pHdr->cb);
+#endif
+    }
+    return NULL;
+}
+RT_EXPORT_SYMBOL(RTMemAllocZTag);
+
+
+RTDECL(void *) RTMemAllocVarTag(size_t cbUnaligned, const char *pszTag)
+{
+    size_t cbAligned;
+    if (cbUnaligned >= 16)
+        cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
+    else
+        cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
+    return RTMemAllocTag(cbAligned, pszTag);
+}
+RT_EXPORT_SYMBOL(RTMemAllocVarTag);
+
+
+RTDECL(void *) RTMemAllocZVarTag(size_t cbUnaligned, const char *pszTag)
+{
+    size_t cbAligned;
+    if (cbUnaligned >= 16)
+        cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
+    else
+        cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
+    return RTMemAllocZTag(cbAligned, pszTag);
+}
+RT_EXPORT_SYMBOL(RTMemAllocZVarTag);
+
+
+RTDECL(void *) RTMemReallocTag(void *pvOld, size_t cbNew, const char *pszTag) RT_NO_THROW_DEF
+{
+    PRTMEMHDR pHdrOld;
+
+    /* Free. */
+    if (!cbNew && pvOld)
+    {
+        RTMemFree(pvOld);
+        return NULL;
+    }
+
+    /* Alloc. */
+    if (!pvOld)
+        return RTMemAllocTag(cbNew, pszTag);
+
+    /*
+     * Realloc.
+     */
+    pHdrOld = (PRTMEMHDR)pvOld - 1;
+    RT_ASSERT_PREEMPTIBLE();
+
+    if (pHdrOld->u32Magic == RTMEMHDR_MAGIC)
+    {
+        PRTMEMHDR pHdrNew;
+
+        /* If there is sufficient space in the old block and we don't cause
+           substantial internal fragmentation, reuse the old block. */
+        if (   pHdrOld->cb >= cbNew + RTR0MEM_FENCE_EXTRA
+            && pHdrOld->cb - (cbNew + RTR0MEM_FENCE_EXTRA) <= 128)
+        {
+            pHdrOld->cbReq = (uint32_t)cbNew; Assert(pHdrOld->cbReq == cbNew);
+#ifdef RTR0MEM_STRICT
+            memcpy((uint8_t *)(pHdrOld + 1) + cbNew, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
+#endif
+            return pvOld;
+        }
+
+        /* Allocate a new block and copy over the content. */
+        pHdrNew = rtR0MemAlloc(cbNew + RTR0MEM_FENCE_EXTRA, 0);
+        if (pHdrNew)
+        {
+            size_t cbCopy = RT_MIN(pHdrOld->cb, pHdrNew->cb);
+            memcpy(pHdrNew + 1, pvOld, cbCopy);
+#ifdef RTR0MEM_STRICT
+            pHdrNew->cbReq = (uint32_t)cbNew; Assert(pHdrNew->cbReq == cbNew);
+            memcpy((uint8_t *)(pHdrNew + 1) + cbNew, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
+            AssertReleaseMsg(!memcmp((uint8_t *)(pHdrOld + 1) + pHdrOld->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
+                             ("pHdr=%p pvOld=%p cbReq=%u cb=%u cbNew=%zu fFlags=%#x\n"
+                              "fence:    %.*Rhxs\n"
+                              "expected: %.*Rhxs\n",
+                              pHdrOld, pvOld, pHdrOld->cbReq, pHdrOld->cb, cbNew, pHdrOld->fFlags,
+                              RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdrOld + 1) + pHdrOld->cbReq,
+                              RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
+#endif
+            rtR0MemFree(pHdrOld);
+            return pHdrNew + 1;
+        }
+    }
+    else
+        AssertMsgFailed(("pHdrOld->u32Magic=%RX32 pvOld=%p cbNew=%#zx\n", pHdrOld->u32Magic, pvOld, cbNew));
+
+    return NULL;
+}
+RT_EXPORT_SYMBOL(RTMemReallocTag);
+
+
+RTDECL(void) RTMemFree(void *pv) RT_NO_THROW_DEF
+{
+    PRTMEMHDR pHdr;
+    RT_ASSERT_INTS_ON();
+
+    if (!pv)
+        return;
+    pHdr = (PRTMEMHDR)pv - 1;
+    if (pHdr->u32Magic == RTMEMHDR_MAGIC)
+    {
+        Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX));
+        Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_EXEC));
+#ifdef RTR0MEM_STRICT
+        AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
+                         ("pHdr=%p pv=%p cbReq=%u cb=%u fFlags=%#x\n"
+                          "fence:    %.*Rhxs\n"
+                          "expected: %.*Rhxs\n",
+                          pHdr, pv, pHdr->cbReq, pHdr->cb, pHdr->fFlags,
+                          RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdr + 1) + pHdr->cbReq,
+                          RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
+#endif
+        rtR0MemFree(pHdr);
+    }
+    else
+        AssertMsgFailed(("pHdr->u32Magic=%RX32 pv=%p\n", pHdr->u32Magic, pv));
+}
+RT_EXPORT_SYMBOL(RTMemFree);
+
+
+
+
+
+
+RTDECL(void *)    RTMemExecAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
+{
+    PRTMEMHDR pHdr;
+#ifdef RT_OS_SOLARIS /** @todo figure out why */
+    RT_ASSERT_INTS_ON();
+#else
+    RT_ASSERT_PREEMPTIBLE();
+#endif
+    RT_NOREF_PV(pszTag);
+
+
+    pHdr = rtR0MemAlloc(cb + RTR0MEM_FENCE_EXTRA, RTMEMHDR_FLAG_EXEC);
+    if (pHdr)
+    {
+#ifdef RTR0MEM_STRICT
+        pHdr->cbReq = (uint32_t)cb; Assert(pHdr->cbReq == cb);
+        memcpy((uint8_t *)(pHdr + 1) + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
+#endif
+        return pHdr + 1;
+    }
+    return NULL;
+}
+RT_EXPORT_SYMBOL(RTMemExecAllocTag);
+
+
+RTDECL(void)      RTMemExecFree(void *pv, size_t cb) RT_NO_THROW_DEF
+{
+    PRTMEMHDR pHdr;
+    RT_ASSERT_INTS_ON();
+    RT_NOREF_PV(cb);
+
+    if (!pv)
+        return;
+    pHdr = (PRTMEMHDR)pv - 1;
+    if (pHdr->u32Magic == RTMEMHDR_MAGIC)
+    {
+        Assert(!(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX));
+#ifdef RTR0MEM_STRICT
+        AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
+                         ("pHdr=%p pv=%p cbReq=%u cb=%u fFlags=%#x\n"
+                          "fence:    %.*Rhxs\n"
+                          "expected: %.*Rhxs\n",
+                          pHdr, pv, pHdr->cbReq, pHdr->cb, pHdr->fFlags,
+                          RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdr + 1) + pHdr->cbReq,
+                          RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
+#endif
+        rtR0MemFree(pHdr);
+    }
+    else
+        AssertMsgFailed(("pHdr->u32Magic=%RX32 pv=%p\n", pHdr->u32Magic, pv));
+}
+RT_EXPORT_SYMBOL(RTMemExecFree);
+
+
+
+
+RTDECL(int) RTMemAllocExTag(size_t cb, size_t cbAlignment, uint32_t fFlags, const char *pszTag, void **ppv) RT_NO_THROW_DEF
+{
+    uint32_t    fHdrFlags = RTMEMHDR_FLAG_ALLOC_EX;
+    PRTMEMHDR   pHdr;
+    int         rc;
+    RT_NOREF_PV(pszTag);
+
+    RT_ASSERT_PREEMPT_CPUID_VAR();
+    if (!(fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX_ALLOC))
+        RT_ASSERT_INTS_ON();
+
+    /*
+     * Fake up some alignment support.
+     */
+    AssertMsgReturn(cbAlignment <= sizeof(void *), ("%zu (%#x)\n", cbAlignment, cbAlignment), VERR_UNSUPPORTED_ALIGNMENT);
+    if (cb < cbAlignment)
+        cb = cbAlignment;
+
+    /*
+     * Validate and convert flags.
+     */
+    AssertMsgReturn(!(fFlags & ~RTMEMALLOCEX_FLAGS_VALID_MASK_R0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
+    if (fFlags & RTMEMALLOCEX_FLAGS_ZEROED)
+        fHdrFlags |= RTMEMHDR_FLAG_ZEROED;
+    if (fFlags & RTMEMALLOCEX_FLAGS_EXEC)
+        fHdrFlags |= RTMEMHDR_FLAG_EXEC;
+    if (fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX_ALLOC)
+        fHdrFlags |= RTMEMHDR_FLAG_ANY_CTX_ALLOC;
+    if (fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX_FREE)
+        fHdrFlags |= RTMEMHDR_FLAG_ANY_CTX_FREE;
+
+    /*
+     * Do the allocation.
+     */
+    rc = rtR0MemAllocEx(cb + RTR0MEM_FENCE_EXTRA, fHdrFlags, &pHdr);
+    if (RT_SUCCESS(rc))
+    {
+        void *pv;
+
+        Assert(pHdr->cbReq  == cb + RTR0MEM_FENCE_EXTRA);
+        Assert((pHdr->fFlags & fFlags) == fFlags);
+
+        /*
+         * Calc user pointer, initialize the memory if requested, and if
+         * memory strictness is enable set up the fence.
+         */
+        pv = pHdr + 1;
+        *ppv = pv;
+        if (fFlags & RTMEMHDR_FLAG_ZEROED)
+            memset(pv, 0, pHdr->cb);
+
+#ifdef RTR0MEM_STRICT
+        pHdr->cbReq = (uint32_t)cb;
+        memcpy((uint8_t *)pv + cb, &g_abFence[0], RTR0MEM_FENCE_EXTRA);
+#endif
+    }
+    else if (rc == VERR_NO_MEMORY && (fFlags & RTMEMALLOCEX_FLAGS_EXEC))
+        rc = VERR_NO_EXEC_MEMORY;
+
+    RT_ASSERT_PREEMPT_CPUID();
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTMemAllocExTag);
+
+
+RTDECL(void) RTMemFreeEx(void *pv, size_t cb) RT_NO_THROW_DEF
+{
+    PRTMEMHDR pHdr;
+    RT_NOREF_PV(cb);
+
+    if (!pv)
+        return;
+
+    AssertPtr(pv);
+    pHdr = (PRTMEMHDR)pv - 1;
+    if (pHdr->u32Magic == RTMEMHDR_MAGIC)
+    {
+        RT_ASSERT_PREEMPT_CPUID_VAR();
+
+        Assert(pHdr->fFlags & RTMEMHDR_FLAG_ALLOC_EX);
+        if (!(pHdr->fFlags & RTMEMHDR_FLAG_ANY_CTX_FREE))
+            RT_ASSERT_INTS_ON();
+        AssertMsg(pHdr->cbReq == cb, ("cbReq=%zu cb=%zu\n", pHdr->cb, cb));
+
+#ifdef RTR0MEM_STRICT
+        AssertReleaseMsg(!memcmp((uint8_t *)(pHdr + 1) + pHdr->cbReq, &g_abFence[0], RTR0MEM_FENCE_EXTRA),
+                         ("pHdr=%p pv=%p cbReq=%u cb=%u fFlags=%#x\n"
+                          "fence:    %.*Rhxs\n"
+                          "expected: %.*Rhxs\n",
+                          pHdr, pv, pHdr->cbReq, pHdr->cb, pHdr->fFlags,
+                          RTR0MEM_FENCE_EXTRA, (uint8_t *)(pHdr + 1) + pHdr->cbReq,
+                          RTR0MEM_FENCE_EXTRA, &g_abFence[0]));
+#endif
+        rtR0MemFree(pHdr);
+        RT_ASSERT_PREEMPT_CPUID();
+    }
+    else
+        AssertMsgFailed(("pHdr->u32Magic=%RX32 pv=%p\n", pHdr->u32Magic, pv));
+}
+RT_EXPORT_SYMBOL(RTMemFreeEx);
+
diff --git a/ubuntu/vbox/r0drv/alloc-r0drv.h b/ubuntu/vbox/r0drv/alloc-r0drv.h
new file mode 100644 (file)
index 0000000..5e5a3e0
--- /dev/null
@@ -0,0 +1,101 @@
+/* $Id: alloc-r0drv.h $ */
+/** @file
+ * IPRT - Memory Allocation, Ring-0 Driver.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___r0drv_alloc_r0drv_h
+#define ___r0drv_alloc_r0drv_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/mem.h>
+#include "internal/magics.h"
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Header which heading all memory blocks.
+ */
+typedef struct RTMEMHDR
+{
+    /** Magic (RTMEMHDR_MAGIC). */
+    uint32_t    u32Magic;
+    /** Block flags (RTMEMHDR_FLAG_*). */
+    uint32_t    fFlags;
+    /** The actual size of the block, header not included. */
+    uint32_t    cb;
+    /** The requested allocation size. */
+    uint32_t    cbReq;
+} RTMEMHDR, *PRTMEMHDR;
+
+
+/** @name RTMEMHDR::fFlags.
+ * @{ */
+/** Clear the allocated memory. */
+#define RTMEMHDR_FLAG_ZEROED        RT_BIT(0)
+/** Executable flag. */
+#define RTMEMHDR_FLAG_EXEC          RT_BIT(1)
+/** Use allocation method suitable for any context. */
+#define RTMEMHDR_FLAG_ANY_CTX_ALLOC RT_BIT(2)
+/** Use allocation method which allow for freeing in any context. */
+#define RTMEMHDR_FLAG_ANY_CTX_FREE  RT_BIT(3)
+/** Both alloc and free in any context (or we're just darn lazy). */
+#define RTMEMHDR_FLAG_ANY_CTX       (RTMEMHDR_FLAG_ANY_CTX_ALLOC | RTMEMHDR_FLAG_ANY_CTX_FREE)
+/** Indicate that it was allocated by rtR0MemAllocExTag. */
+#define RTMEMHDR_FLAG_ALLOC_EX      RT_BIT(4)
+#ifdef RT_OS_LINUX
+/** Linux: Allocated using vm_area hacks. */
+# define RTMEMHDR_FLAG_EXEC_VM_AREA RT_BIT(29)
+/** Linux: Allocated from the special heap for executable memory. */
+# define RTMEMHDR_FLAG_EXEC_HEAP    RT_BIT(30)
+/** Linux: Allocated by kmalloc() instead of vmalloc(). */
+# define RTMEMHDR_FLAG_KMALLOC      RT_BIT(31)
+#endif
+/** @} */
+
+
+/**
+ * Heap allocation back end for ring-0.
+ *
+ * @returns IPRT status code.  VERR_NO_MEMORY suffices for RTMEMHDR_FLAG_EXEC,
+ *          the caller will change it to VERR_NO_EXEC_MEMORY when appropriate.
+ *
+ * @param   cb          The amount of memory requested by the user.  This does
+ *                      not include the header.
+ * @param   fFlags      The allocation flags and more.  These should be
+ *                      assigned to RTMEMHDR::fFlags together with any flags
+ *                      the backend might be using.
+ * @param   ppHdr       Where to return the memory header on success.
+ */
+DECLHIDDEN(int)     rtR0MemAllocEx(size_t cb, uint32_t fFlags, PRTMEMHDR *ppHdr);
+
+/**
+ * Free memory allocated by rtR0MemAllocEx.
+ * @param   pHdr        The memory block to free.  (Never NULL.)
+ */
+DECLHIDDEN(void)    rtR0MemFree(PRTMEMHDR pHdr);
+
+RT_C_DECLS_END
+#endif
+
diff --git a/ubuntu/vbox/r0drv/generic/semspinmutex-r0drv-generic.c b/ubuntu/vbox/r0drv/generic/semspinmutex-r0drv-generic.c
new file mode 100644 (file)
index 0000000..2136ab7
--- /dev/null
@@ -0,0 +1,503 @@
+/* $Id: semspinmutex-r0drv-generic.c $ */
+/** @file
+ * IPRT - Spinning Mutex Semaphores, Ring-0 Driver, Generic.
+ */
+
+/*
+ * Copyright (C) 2009-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#ifdef RT_OS_WINDOWS
+# include "../nt/the-nt-kernel.h"
+#endif
+#include "internal/iprt.h"
+
+#include <iprt/semaphore.h>
+#include <iprt/asm.h>
+#include <iprt/asm-amd64-x86.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/mem.h>
+#include <iprt/thread.h>
+#include "internal/magics.h"
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * Saved state information.
+ */
+typedef struct RTSEMSPINMUTEXSTATE
+{
+    /** Saved flags register. */
+    RTCCUINTREG             fSavedFlags;
+    /** Preemption state.  */
+    RTTHREADPREEMPTSTATE    PreemptState;
+    /** Whether to spin or sleep. */
+    bool                    fSpin;
+    /** Whether the flags have been saved. */
+    bool                    fValidFlags;
+} RTSEMSPINMUTEXSTATE;
+
+/**
+ * Spinning mutex semaphore.
+ */
+typedef struct RTSEMSPINMUTEXINTERNAL
+{
+    /** Magic value (RTSEMSPINMUTEX_MAGIC)
+     * RTCRITSECT_MAGIC is the value of an initialized & operational section. */
+    uint32_t volatile       u32Magic;
+    /** Flags. This is a combination of RTSEMSPINMUTEX_FLAGS_XXX and
+     *  RTSEMSPINMUTEX_INT_FLAGS_XXX. */
+    uint32_t volatile       fFlags;
+    /** The owner thread.
+     * This is NIL if the semaphore is not owned by anyone. */
+    RTNATIVETHREAD volatile hOwner;
+    /** Number of threads that are fighting for the lock. */
+    int32_t volatile        cLockers;
+    /** The semaphore to block on. */
+    RTSEMEVENT              hEventSem;
+    /** Saved state information of the owner.
+     * This will be restored by RTSemSpinRelease. */
+    RTSEMSPINMUTEXSTATE     SavedState;
+} RTSEMSPINMUTEXINTERNAL;
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+/*#define RTSEMSPINMUTEX_INT_FLAGS_MUST*/
+
+/** Validates the handle, returning if invalid. */
+#define RTSEMSPINMUTEX_VALIDATE_RETURN(pThis) \
+    do \
+    { \
+        uint32_t u32Magic; \
+        AssertPtr(pThis); \
+        u32Magic = (pThis)->u32Magic; \
+        if (u32Magic != RTSEMSPINMUTEX_MAGIC) \
+        { \
+            AssertMsgFailed(("u32Magic=%#x pThis=%p\n", u32Magic, pThis)); \
+            return u32Magic == RTSEMSPINMUTEX_MAGIC_DEAD ? VERR_SEM_DESTROYED : VERR_INVALID_HANDLE; \
+        } \
+    } while (0)
+
+
+RTDECL(int) RTSemSpinMutexCreate(PRTSEMSPINMUTEX phSpinMtx, uint32_t fFlags)
+{
+    RTSEMSPINMUTEXINTERNAL *pThis;
+    int                     rc;
+
+    AssertReturn(!(fFlags & ~RTSEMSPINMUTEX_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
+    AssertPtr(phSpinMtx);
+
+    /*
+     * Allocate and initialize the structure.
+     */
+    pThis = (RTSEMSPINMUTEXINTERNAL *)RTMemAllocZ(sizeof(*pThis));
+    if (!pThis)
+        return VERR_NO_MEMORY;
+    pThis->u32Magic   = RTSEMSPINMUTEX_MAGIC;
+    pThis->fFlags     = fFlags;
+    pThis->hOwner     = NIL_RTNATIVETHREAD;
+    pThis->cLockers   = 0;
+    rc = RTSemEventCreateEx(&pThis->hEventSem, RTSEMEVENT_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS, NULL);
+    if (RT_SUCCESS(rc))
+    {
+        *phSpinMtx = pThis;
+        return VINF_SUCCESS;
+    }
+
+    RTMemFree(pThis);
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTSemSpinMutexCreate);
+
+
+/**
+ * Helper for RTSemSpinMutexTryRequest and RTSemSpinMutexRequest.
+ *
+ * This will check the current context and see if it's usui
+ *
+ * @returns VINF_SUCCESS or VERR_SEM_BAD_CONTEXT.
+ * @param   pState      Output structure.
+ */
+static int rtSemSpinMutexEnter(RTSEMSPINMUTEXSTATE *pState, RTSEMSPINMUTEXINTERNAL *pThis)
+{
+#ifndef RT_OS_WINDOWS
+    RTTHREADPREEMPTSTATE const StateInit = RTTHREADPREEMPTSTATE_INITIALIZER;
+#endif
+    int rc  = VINF_SUCCESS;
+
+    /** @todo Later #1: When entering in interrupt context and we're not able to
+     *        wake up threads from it, we could try switch the lock into pure
+     *        spinlock mode. This would require that there are no other threads
+     *        currently waiting on it and that the RTSEMSPINMUTEX_FLAGS_IRQ_SAFE
+     *        flag is set.
+     *
+     *        Later #2: Similarly, it is possible to turn on the
+     *        RTSEMSPINMUTEX_FLAGS_IRQ_SAFE at run time if we manage to grab the
+     *        semaphore ownership at interrupt time. We might want to try delay the
+     *        RTSEMSPINMUTEX_FLAGS_IRQ_SAFE even, since we're fine if we get it...
+     */
+
+#ifdef RT_OS_WINDOWS
+    /*
+     * NT: IRQL <= DISPATCH_LEVEL for waking up threads; IRQL < DISPATCH_LEVEL for sleeping.
+     */
+    pState->PreemptState.uchOldIrql = KeGetCurrentIrql();
+    if (pState->PreemptState.uchOldIrql > DISPATCH_LEVEL)
+        return VERR_SEM_BAD_CONTEXT;
+
+    if (pState->PreemptState.uchOldIrql >= DISPATCH_LEVEL)
+        pState->fSpin = true;
+    else
+    {
+        pState->fSpin = false;
+        KeRaiseIrql(DISPATCH_LEVEL, &pState->PreemptState.uchOldIrql);
+        Assert(pState->PreemptState.uchOldIrql < DISPATCH_LEVEL);
+    }
+
+#elif defined(RT_OS_SOLARIS)
+    /*
+     * Solaris:  RTSemEventSignal will do bad stuff on S10 if interrupts are disabled.
+     */
+    if (!ASMIntAreEnabled())
+        return VERR_SEM_BAD_CONTEXT;
+
+    pState->fSpin = !RTThreadPreemptIsEnabled(NIL_RTTHREAD);
+    if (RTThreadIsInInterrupt(NIL_RTTHREAD))
+    {
+        if (!(pThis->fFlags & RTSEMSPINMUTEX_FLAGS_IRQ_SAFE))
+            rc = VINF_SEM_BAD_CONTEXT; /* Try, but owner might be interrupted. */
+        pState->fSpin = true;
+    }
+    pState->PreemptState = StateInit;
+    RTThreadPreemptDisable(&pState->PreemptState);
+
+#elif defined(RT_OS_LINUX) || defined(RT_OS_OS2)
+    /*
+     * OSes on which RTSemEventSignal can be called from any context.
+     */
+    pState->fSpin = !RTThreadPreemptIsEnabled(NIL_RTTHREAD);
+    if (RTThreadIsInInterrupt(NIL_RTTHREAD))
+    {
+        if (!(pThis->fFlags & RTSEMSPINMUTEX_FLAGS_IRQ_SAFE))
+            rc = VINF_SEM_BAD_CONTEXT; /* Try, but owner might be interrupted. */
+        pState->fSpin = true;
+    }
+    pState->PreemptState = StateInit;
+    RTThreadPreemptDisable(&pState->PreemptState);
+
+#else /* PORTME: Check for context where we cannot wake up threads. */
+    /*
+     * Default: ASSUME thread can be woken up if interrupts are enabled and
+     *          we're not in an interrupt context.
+     *          ASSUME that we can go to sleep if preemption is enabled.
+     */
+    if (    RTThreadIsInInterrupt(NIL_RTTHREAD)
+        ||  !ASMIntAreEnabled())
+        return VERR_SEM_BAD_CONTEXT;
+
+    pState->fSpin = !RTThreadPreemptIsEnabled(NIL_RTTHREAD);
+    pState->PreemptState = StateInit;
+    RTThreadPreemptDisable(&pState->PreemptState);
+#endif
+
+    /*
+     * Disable interrupts if necessary.
+     */
+    pState->fValidFlags = !!(pThis->fFlags & RTSEMSPINMUTEX_FLAGS_IRQ_SAFE);
+    if (pState->fValidFlags)
+        pState->fSavedFlags = ASMIntDisableFlags();
+    else
+        pState->fSavedFlags = 0;
+
+    return rc;
+}
+
+
+/**
+ * Helper for RTSemSpinMutexTryRequest, RTSemSpinMutexRequest and
+ * RTSemSpinMutexRelease.
+ *
+ * @param  pState
+ */
+DECL_FORCE_INLINE(void) rtSemSpinMutexLeave(RTSEMSPINMUTEXSTATE *pState)
+{
+    /*
+     * Restore the interrupt flag.
+     */
+    if (pState->fValidFlags)
+        ASMSetFlags(pState->fSavedFlags);
+
+#ifdef RT_OS_WINDOWS
+    /*
+     * NT: Lower the IRQL if we raised it.
+     */
+    if (pState->PreemptState.uchOldIrql < DISPATCH_LEVEL)
+        KeLowerIrql(pState->PreemptState.uchOldIrql);
+#else
+    /*
+     * Default: Restore preemption.
+     */
+    RTThreadPreemptRestore(&pState->PreemptState);
+#endif
+}
+
+
+RTDECL(int) RTSemSpinMutexTryRequest(RTSEMSPINMUTEX hSpinMtx)
+{
+    RTSEMSPINMUTEXINTERNAL *pThis = hSpinMtx;
+    RTNATIVETHREAD          hSelf = RTThreadNativeSelf();
+    RTSEMSPINMUTEXSTATE     State;
+    bool                    fRc;
+    int                     rc;
+
+    Assert(hSelf != NIL_RTNATIVETHREAD);
+    RTSEMSPINMUTEX_VALIDATE_RETURN(pThis);
+
+    /*
+     * Check context, disable preemption and save flags if necessary.
+     */
+    rc = rtSemSpinMutexEnter(&State, pThis);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    /*
+     * Try take the ownership.
+     */
+    ASMAtomicCmpXchgHandle(&pThis->hOwner, hSelf, NIL_RTNATIVETHREAD, fRc);
+    if (!fRc)
+    {
+        /* Busy, too bad. Check for attempts at nested access. */
+        rc = VERR_SEM_BUSY;
+        if (RT_UNLIKELY(pThis->hOwner == hSelf))
+        {
+            AssertMsgFailed(("%p attempt at nested access\n"));
+            rc = VERR_SEM_NESTED;
+        }
+
+        rtSemSpinMutexLeave(&State);
+        return rc;
+    }
+
+    /*
+     * We're the semaphore owner.
+     */
+    ASMAtomicIncS32(&pThis->cLockers);
+    pThis->SavedState = State;
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSemSpinMutexTryRequest);
+
+
+RTDECL(int) RTSemSpinMutexRequest(RTSEMSPINMUTEX hSpinMtx)
+{
+    RTSEMSPINMUTEXINTERNAL *pThis = hSpinMtx;
+    RTNATIVETHREAD          hSelf = RTThreadNativeSelf();
+    RTSEMSPINMUTEXSTATE     State;
+    bool                    fRc;
+    int                     rc;
+
+    Assert(hSelf != NIL_RTNATIVETHREAD);
+    RTSEMSPINMUTEX_VALIDATE_RETURN(pThis);
+
+    /*
+     * Check context, disable preemption and save flags if necessary.
+     */
+    rc = rtSemSpinMutexEnter(&State, pThis);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    /*
+     * Try take the ownership.
+     */
+    ASMAtomicIncS32(&pThis->cLockers);
+    ASMAtomicCmpXchgHandle(&pThis->hOwner, hSelf, NIL_RTNATIVETHREAD, fRc);
+    if (!fRc)
+    {
+        uint32_t cSpins;
+
+        /*
+         * It's busy. Check if it's an attempt at nested access.
+         */
+        if (RT_UNLIKELY(pThis->hOwner == hSelf))
+        {
+            AssertMsgFailed(("%p attempt at nested access\n"));
+            rtSemSpinMutexLeave(&State);
+            return VERR_SEM_NESTED;
+        }
+
+        /*
+         * Return if we're in interrupt context and the semaphore isn't
+         * configure to be interrupt safe.
+         */
+        if (rc == VINF_SEM_BAD_CONTEXT)
+        {
+            rtSemSpinMutexLeave(&State);
+            return VERR_SEM_BAD_CONTEXT;
+        }
+
+        /*
+         * Ok, we have to wait.
+         */
+        if (State.fSpin)
+        {
+            for (cSpins = 0; ; cSpins++)
+            {
+                ASMAtomicCmpXchgHandle(&pThis->hOwner, hSelf, NIL_RTNATIVETHREAD, fRc);
+                if (fRc)
+                    break;
+                ASMNopPause();
+                if (RT_UNLIKELY(pThis->u32Magic != RTSEMSPINMUTEX_MAGIC))
+                {
+                    rtSemSpinMutexLeave(&State);
+                    return VERR_SEM_DESTROYED;
+                }
+
+                /*
+                 * "Yield" once in a while. This may lower our IRQL/PIL which
+                 * may preempting us, and it will certainly stop the hammering
+                 * of hOwner for a little while.
+                 */
+                if ((cSpins & 0x7f) == 0x1f)
+                {
+                    rtSemSpinMutexLeave(&State);
+                    rtSemSpinMutexEnter(&State, pThis);
+                    Assert(State.fSpin);
+                }
+            }
+        }
+        else
+        {
+            for (cSpins = 0;; cSpins++)
+            {
+                ASMAtomicCmpXchgHandle(&pThis->hOwner, hSelf, NIL_RTNATIVETHREAD, fRc);
+                if (fRc)
+                    break;
+                ASMNopPause();
+                if (RT_UNLIKELY(pThis->u32Magic != RTSEMSPINMUTEX_MAGIC))
+                {
+                    rtSemSpinMutexLeave(&State);
+                    return VERR_SEM_DESTROYED;
+                }
+
+                if ((cSpins & 15) == 15) /* spin a bit before going sleep (again). */
+                {
+                    rtSemSpinMutexLeave(&State);
+
+                    rc = RTSemEventWait(pThis->hEventSem, RT_INDEFINITE_WAIT);
+                    ASMCompilerBarrier();
+                    if (RT_SUCCESS(rc))
+                        AssertReturn(pThis->u32Magic == RTSEMSPINMUTEX_MAGIC, VERR_SEM_DESTROYED);
+                    else if (rc == VERR_INTERRUPTED)
+                        AssertRC(rc);       /* shouldn't happen */
+                    else
+                    {
+                        AssertRC(rc);
+                        return rc;
+                    }
+
+                    rc = rtSemSpinMutexEnter(&State, pThis);
+                    AssertRCReturn(rc, rc);
+                    Assert(!State.fSpin);
+                }
+            }
+        }
+    }
+
+    /*
+     * We're the semaphore owner.
+     */
+    pThis->SavedState = State;
+    Assert(pThis->hOwner == hSelf);
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSemSpinMutexRequest);
+
+
+RTDECL(int) RTSemSpinMutexRelease(RTSEMSPINMUTEX hSpinMtx)
+{
+    RTSEMSPINMUTEXINTERNAL *pThis = hSpinMtx;
+    RTNATIVETHREAD          hSelf = RTThreadNativeSelf();
+    uint32_t                cLockers;
+    RTSEMSPINMUTEXSTATE     State;
+    bool                    fRc;
+
+    Assert(hSelf != NIL_RTNATIVETHREAD);
+    RTSEMSPINMUTEX_VALIDATE_RETURN(pThis);
+
+    /*
+     * Get the saved state and try release the semaphore.
+     */
+    State = pThis->SavedState;
+    ASMCompilerBarrier();
+    ASMAtomicCmpXchgHandle(&pThis->hOwner, NIL_RTNATIVETHREAD, hSelf, fRc);
+    AssertMsgReturn(fRc,
+                    ("hOwner=%p hSelf=%p cLockers=%d\n", pThis->hOwner, hSelf, pThis->cLockers),
+                    VERR_NOT_OWNER);
+
+    cLockers = ASMAtomicDecS32(&pThis->cLockers);
+    rtSemSpinMutexLeave(&State);
+    if (cLockers > 0)
+    {
+        int rc = RTSemEventSignal(pThis->hEventSem);
+        AssertReleaseMsg(RT_SUCCESS(rc), ("RTSemEventSignal -> %Rrc\n", rc));
+    }
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSemSpinMutexRelease);
+
+
+RTDECL(int) RTSemSpinMutexDestroy(RTSEMSPINMUTEX hSpinMtx)
+{
+    RTSEMSPINMUTEXINTERNAL *pThis;
+    RTSEMEVENT              hEventSem;
+    int                     rc;
+
+    if (hSpinMtx == NIL_RTSEMSPINMUTEX)
+        return VINF_SUCCESS;
+    pThis = hSpinMtx;
+    RTSEMSPINMUTEX_VALIDATE_RETURN(pThis);
+
+    /* No destruction races allowed! */
+    AssertMsg(   pThis->cLockers  == 0
+              && pThis->hOwner    == NIL_RTNATIVETHREAD,
+              ("pThis=%p cLockers=%d hOwner=%p\n", pThis, pThis->cLockers, pThis->hOwner));
+
+    /*
+     * Invalidate the structure, free the mutex and free the structure.
+     */
+    ASMAtomicWriteU32(&pThis->u32Magic, RTSEMSPINMUTEX_MAGIC_DEAD);
+    hEventSem        = pThis->hEventSem;
+    pThis->hEventSem = NIL_RTSEMEVENT;
+    rc = RTSemEventDestroy(hEventSem); AssertRC(rc);
+
+    RTMemFree(pThis);
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTSemSpinMutexDestroy);
+
diff --git a/ubuntu/vbox/r0drv/initterm-r0drv.c b/ubuntu/vbox/r0drv/initterm-r0drv.c
new file mode 100644 (file)
index 0000000..26cea6a
--- /dev/null
@@ -0,0 +1,164 @@
+/* $Id: initterm-r0drv.cpp $ */
+/** @file
+ * IPRT - Initialization & Termination, R0 Driver, Common.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/initterm.h>
+#include "internal/iprt.h"
+
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/mp.h>
+#include <iprt/thread.h>
+#ifndef IN_GUEST /* play safe for now */
+# include "r0drv/mp-r0drv.h"
+# include "r0drv/power-r0drv.h"
+#endif
+
+#include "internal/initterm.h"
+#include "internal/mem.h"
+#include "internal/thread.h"
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** Count of current IPRT users.
+ * In ring-0 several drivers / kmods / kexts / wossnames may share the
+ * same runtime code. So, we need to keep count in order not to terminate
+ * it prematurely. */
+static int32_t volatile g_crtR0Users = 0;
+
+
+/**
+ * Initializes the ring-0 driver runtime library.
+ *
+ * @returns iprt status code.
+ * @param   fReserved       Flags reserved for the future.
+ */
+RTR0DECL(int) RTR0Init(unsigned fReserved)
+{
+    int rc;
+    uint32_t cNewUsers;
+    Assert(fReserved == 0); RT_NOREF_PV(fReserved);
+#ifndef RT_OS_SOLARIS       /* On Solaris our thread preemption information is only obtained in rtR0InitNative().*/
+    RT_ASSERT_PREEMPTIBLE();
+#endif
+
+    /*
+     * The first user initializes it.
+     * We rely on the module loader to ensure that there are no
+     * initialization races should two modules share the IPRT.
+     */
+    cNewUsers = ASMAtomicIncS32(&g_crtR0Users);
+    if (cNewUsers != 1)
+    {
+        if (cNewUsers > 1)
+            return VINF_SUCCESS;
+        ASMAtomicDecS32(&g_crtR0Users);
+        return VERR_INTERNAL_ERROR_3;
+    }
+
+    rc = rtR0InitNative();
+    if (RT_SUCCESS(rc))
+    {
+#ifdef RTR0MEM_WITH_EF_APIS
+        rtR0MemEfInit();
+#endif
+        rc = rtThreadInit();
+        if (RT_SUCCESS(rc))
+        {
+#ifndef IN_GUEST /* play safe for now */
+            rc = rtR0MpNotificationInit();
+            if (RT_SUCCESS(rc))
+            {
+                rc = rtR0PowerNotificationInit();
+                if (RT_SUCCESS(rc))
+                    return rc;
+                rtR0MpNotificationTerm();
+            }
+#else
+            if (RT_SUCCESS(rc))
+                return rc;
+#endif
+            rtThreadTerm();
+        }
+#ifdef RTR0MEM_WITH_EF_APIS
+        rtR0MemEfTerm();
+#endif
+        rtR0TermNative();
+    }
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTR0Init);
+
+
+static void rtR0Term(void)
+{
+    rtThreadTerm();
+#ifndef IN_GUEST /* play safe for now */
+    rtR0PowerNotificationTerm();
+    rtR0MpNotificationTerm();
+#endif
+#ifdef RTR0MEM_WITH_EF_APIS
+    rtR0MemEfTerm();
+#endif
+    rtR0TermNative();
+}
+
+
+/**
+ * Terminates the ring-0 driver runtime library.
+ */
+RTR0DECL(void) RTR0Term(void)
+{
+    int32_t cNewUsers;
+    RT_ASSERT_PREEMPTIBLE();
+
+    cNewUsers = ASMAtomicDecS32(&g_crtR0Users);
+    Assert(cNewUsers >= 0);
+    if (cNewUsers == 0)
+        rtR0Term();
+    else if (cNewUsers < 0)
+        ASMAtomicIncS32(&g_crtR0Users);
+}
+RT_EXPORT_SYMBOL(RTR0Term);
+
+
+/* Note! Should *not* be exported since it's only for static linking. */
+RTR0DECL(void) RTR0TermForced(void)
+{
+    RT_ASSERT_PREEMPTIBLE();
+
+    AssertMsg(g_crtR0Users == 1, ("%d\n", g_crtR0Users));
+    ASMAtomicWriteS32(&g_crtR0Users, 0);
+
+    rtR0Term();
+}
+
diff --git a/ubuntu/vbox/r0drv/linux/RTLogWriteDebugger-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/RTLogWriteDebugger-r0drv-linux.c
new file mode 100644 (file)
index 0000000..a1c858b
--- /dev/null
@@ -0,0 +1,43 @@
+/* $Id: RTLogWriteDebugger-r0drv-linux.c $ */
+/** @file
+ * IPRT - Log To Debugger, Ring-0 Driver, Linux.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/log.h>
+
+
+RTDECL(void) RTLogWriteDebugger(const char *pch, size_t cb)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    printk("%.*s", (int)cb, pch);
+    IPRT_LINUX_RESTORE_EFL_AC();
+}
+RT_EXPORT_SYMBOL(RTLogWriteDebugger);
+
diff --git a/ubuntu/vbox/r0drv/linux/alloc-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/alloc-r0drv-linux.c
new file mode 100644 (file)
index 0000000..e011867
--- /dev/null
@@ -0,0 +1,501 @@
+/* $Id: alloc-r0drv-linux.c $ */
+/** @file
+ * IPRT - Memory Allocation, Ring-0 Driver, Linux.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/mem.h>
+
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include "r0drv/alloc-r0drv.h"
+
+
+#if (defined(RT_ARCH_AMD64) || defined(DOXYGEN_RUNNING)) && !defined(RTMEMALLOC_EXEC_HEAP)
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
+/**
+ * Starting with 2.6.23 we can use __get_vm_area and map_vm_area to allocate
+ * memory in the moduel range.  This is preferrable to the exec heap below.
+ */
+#  define RTMEMALLOC_EXEC_VM_AREA
+# else
+/**
+ * We need memory in the module range (~2GB to ~0) this can only be obtained
+ * thru APIs that are not exported (see module_alloc()).
+ *
+ * So, we'll have to create a quick and dirty heap here using BSS memory.
+ * Very annoying and it's going to restrict us!
+ */
+#  define RTMEMALLOC_EXEC_HEAP
+# endif
+#endif
+
+#ifdef RTMEMALLOC_EXEC_HEAP
+# include <iprt/heap.h>
+# include <iprt/spinlock.h>
+# include <iprt/err.h>
+#endif
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+#ifdef RTMEMALLOC_EXEC_VM_AREA
+/**
+ * Extended header used for headers marked with RTMEMHDR_FLAG_EXEC_VM_AREA.
+ *
+ * This is used with allocating executable memory, for things like generated
+ * code and loaded modules.
+ */
+typedef struct RTMEMLNXHDREX
+{
+    /** The VM area for this allocation. */
+    struct vm_struct   *pVmArea;
+    void               *pvDummy;
+    /** The header we present to the generic API. */
+    RTMEMHDR            Hdr;
+} RTMEMLNXHDREX;
+AssertCompileSize(RTMEMLNXHDREX, 32);
+/** Pointer to an extended memory header. */
+typedef RTMEMLNXHDREX *PRTMEMLNXHDREX;
+#endif
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+#ifdef RTMEMALLOC_EXEC_HEAP
+/** The heap. */
+static RTHEAPSIMPLE g_HeapExec = NIL_RTHEAPSIMPLE;
+/** Spinlock protecting the heap. */
+static RTSPINLOCK   g_HeapExecSpinlock = NIL_RTSPINLOCK;
+#endif
+
+
+/**
+ * API for cleaning up the heap spinlock on IPRT termination.
+ * This is as RTMemExecDonate specific to AMD64 Linux/GNU.
+ */
+DECLHIDDEN(void) rtR0MemExecCleanup(void)
+{
+#ifdef RTMEMALLOC_EXEC_HEAP
+    RTSpinlockDestroy(g_HeapExecSpinlock);
+    g_HeapExecSpinlock = NIL_RTSPINLOCK;
+#endif
+}
+
+
+/**
+ * Donate read+write+execute memory to the exec heap.
+ *
+ * This API is specific to AMD64 and Linux/GNU. A kernel module that desires to
+ * use RTMemExecAlloc on AMD64 Linux/GNU will have to donate some statically
+ * allocated memory in the module if it wishes for GCC generated code to work.
+ * GCC can only generate modules that work in the address range ~2GB to ~0
+ * currently.
+ *
+ * The API only accept one single donation.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NOT_SUPPORTED if the code isn't enabled.
+ * @param   pvMemory    Pointer to the memory block.
+ * @param   cb          The size of the memory block.
+ */
+RTR0DECL(int) RTR0MemExecDonate(void *pvMemory, size_t cb)
+{
+#ifdef RTMEMALLOC_EXEC_HEAP
+    int rc;
+    AssertReturn(g_HeapExec == NIL_RTHEAPSIMPLE, VERR_WRONG_ORDER);
+
+    rc = RTSpinlockCreate(&g_HeapExecSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "RTR0MemExecDonate");
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTHeapSimpleInit(&g_HeapExec, pvMemory, cb);
+        if (RT_FAILURE(rc))
+            rtR0MemExecCleanup();
+    }
+    return rc;
+#else
+    RT_NOREF_PV(pvMemory); RT_NOREF_PV(cb);
+    return VERR_NOT_SUPPORTED;
+#endif
+}
+RT_EXPORT_SYMBOL(RTR0MemExecDonate);
+
+
+
+#ifdef RTMEMALLOC_EXEC_VM_AREA
+/**
+ * Allocate executable kernel memory in the module range.
+ *
+ * @returns Pointer to a allocation header success.  NULL on failure.
+ *
+ * @param   cb          The size the user requested.
+ */
+static PRTMEMHDR rtR0MemAllocExecVmArea(size_t cb)
+{
+    size_t const        cbAlloc = RT_ALIGN_Z(sizeof(RTMEMLNXHDREX) + cb, PAGE_SIZE);
+    size_t const        cPages  = cbAlloc >> PAGE_SHIFT;
+    struct page       **papPages;
+    struct vm_struct   *pVmArea;
+    size_t              iPage;
+
+    pVmArea = __get_vm_area(cbAlloc, VM_ALLOC, MODULES_VADDR, MODULES_END);
+    if (!pVmArea)
+        return NULL;
+    pVmArea->nr_pages = 0;    /* paranoia? */
+    pVmArea->pages    = NULL; /* paranoia? */
+
+    papPages = (struct page **)kmalloc(cPages * sizeof(papPages[0]), GFP_KERNEL | __GFP_NOWARN);
+    if (!papPages)
+    {
+        vunmap(pVmArea->addr);
+        return NULL;
+    }
+
+    for (iPage = 0; iPage < cPages; iPage++)
+    {
+        papPages[iPage] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN);
+        if (!papPages[iPage])
+            break;
+    }
+    if (iPage == cPages)
+    {
+        /*
+         * Map the pages.
+         *
+         * Not entirely sure we really need to set nr_pages and pages here, but
+         * they provide a very convenient place for storing something we need
+         * in the free function, if nothing else...
+         */
+# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
+        struct page **papPagesIterator = papPages;
+# endif
+        pVmArea->nr_pages = cPages;
+        pVmArea->pages    = papPages;
+        if (!map_vm_area(pVmArea, PAGE_KERNEL_EXEC,
+# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
+                         &papPagesIterator
+# else
+                         papPages
+# endif
+                         ))
+        {
+            PRTMEMLNXHDREX pHdrEx = (PRTMEMLNXHDREX)pVmArea->addr;
+            pHdrEx->pVmArea     = pVmArea;
+            pHdrEx->pvDummy     = NULL;
+            return &pHdrEx->Hdr;
+        }
+        /* bail out */
+# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
+        pVmArea->nr_pages = papPagesIterator - papPages;
+# endif
+    }
+
+    vunmap(pVmArea->addr);
+
+    while (iPage-- > 0)
+        __free_page(papPages[iPage]);
+    kfree(papPages);
+
+    return NULL;
+}
+#endif /* RTMEMALLOC_EXEC_VM_AREA */
+
+
+/**
+ * OS specific allocation function.
+ */
+DECLHIDDEN(int) rtR0MemAllocEx(size_t cb, uint32_t fFlags, PRTMEMHDR *ppHdr)
+{
+    PRTMEMHDR pHdr;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * Allocate.
+     */
+    if (fFlags & RTMEMHDR_FLAG_EXEC)
+    {
+        if (fFlags & RTMEMHDR_FLAG_ANY_CTX)
+            return VERR_NOT_SUPPORTED;
+
+#if defined(RT_ARCH_AMD64)
+# ifdef RTMEMALLOC_EXEC_HEAP
+        if (g_HeapExec != NIL_RTHEAPSIMPLE)
+        {
+            RTSpinlockAcquire(g_HeapExecSpinlock);
+            pHdr = (PRTMEMHDR)RTHeapSimpleAlloc(g_HeapExec, cb + sizeof(*pHdr), 0);
+            RTSpinlockRelease(g_HeapExecSpinlock);
+            fFlags |= RTMEMHDR_FLAG_EXEC_HEAP;
+        }
+        else
+            pHdr = NULL;
+
+# elif defined(RTMEMALLOC_EXEC_VM_AREA)
+        pHdr = rtR0MemAllocExecVmArea(cb);
+        fFlags |= RTMEMHDR_FLAG_EXEC_VM_AREA;
+
+# else  /* !RTMEMALLOC_EXEC_HEAP */
+# error "you don not want to go here..."
+        pHdr = (PRTMEMHDR)__vmalloc(cb + sizeof(*pHdr), GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN, MY_PAGE_KERNEL_EXEC);
+# endif /* !RTMEMALLOC_EXEC_HEAP */
+
+#elif defined(PAGE_KERNEL_EXEC) && defined(CONFIG_X86_PAE)
+        pHdr = (PRTMEMHDR)__vmalloc(cb + sizeof(*pHdr), GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN, MY_PAGE_KERNEL_EXEC);
+#else
+        pHdr = (PRTMEMHDR)vmalloc(cb + sizeof(*pHdr));
+#endif
+    }
+    else
+    {
+        if (
+#if 1 /* vmalloc has serious performance issues, avoid it. */
+               cb <= PAGE_SIZE*16 - sizeof(*pHdr)
+#else
+               cb <= PAGE_SIZE
+#endif
+            || (fFlags & RTMEMHDR_FLAG_ANY_CTX)
+           )
+        {
+            fFlags |= RTMEMHDR_FLAG_KMALLOC;
+            pHdr = kmalloc(cb + sizeof(*pHdr),
+                           (fFlags & RTMEMHDR_FLAG_ANY_CTX_ALLOC) ? (GFP_ATOMIC | __GFP_NOWARN)
+                                                                  : (GFP_KERNEL | __GFP_NOWARN));
+            if (RT_UNLIKELY(   !pHdr
+                            && cb > PAGE_SIZE
+                            && !(fFlags & RTMEMHDR_FLAG_ANY_CTX) ))
+            {
+                fFlags &= ~RTMEMHDR_FLAG_KMALLOC;
+                pHdr = vmalloc(cb + sizeof(*pHdr));
+            }
+        }
+        else
+            pHdr = vmalloc(cb + sizeof(*pHdr));
+    }
+    if (RT_UNLIKELY(!pHdr))
+    {
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return VERR_NO_MEMORY;
+    }
+
+    /*
+     * Initialize.
+     */
+    pHdr->u32Magic  = RTMEMHDR_MAGIC;
+    pHdr->fFlags    = fFlags;
+    pHdr->cb        = cb;
+    pHdr->cbReq     = cb;
+
+    *ppHdr = pHdr;
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * OS specific free function.
+ */
+DECLHIDDEN(void) rtR0MemFree(PRTMEMHDR pHdr)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    pHdr->u32Magic += 1;
+    if (pHdr->fFlags & RTMEMHDR_FLAG_KMALLOC)
+        kfree(pHdr);
+#ifdef RTMEMALLOC_EXEC_HEAP
+    else if (pHdr->fFlags & RTMEMHDR_FLAG_EXEC_HEAP)
+    {
+        RTSpinlockAcquire(g_HeapExecSpinlock);
+        RTHeapSimpleFree(g_HeapExec, pHdr);
+        RTSpinlockRelease(g_HeapExecSpinlock);
+    }
+#endif
+#ifdef RTMEMALLOC_EXEC_VM_AREA
+    else if (pHdr->fFlags & RTMEMHDR_FLAG_EXEC_VM_AREA)
+    {
+        PRTMEMLNXHDREX pHdrEx    = RT_FROM_MEMBER(pHdr, RTMEMLNXHDREX, Hdr);
+        size_t         iPage     = pHdrEx->pVmArea->nr_pages;
+        struct page  **papPages  = pHdrEx->pVmArea->pages;
+        void          *pvMapping = pHdrEx->pVmArea->addr;
+
+        vunmap(pvMapping);
+
+        while (iPage-- > 0)
+            __free_page(papPages[iPage]);
+        kfree(papPages);
+    }
+#endif
+    else
+        vfree(pHdr);
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+}
+
+
+
+/**
+ * Compute order. Some functions allocate 2^order pages.
+ *
+ * @returns order.
+ * @param   cPages      Number of pages.
+ */
+static int CalcPowerOf2Order(unsigned long cPages)
+{
+    int             iOrder;
+    unsigned long   cTmp;
+
+    for (iOrder = 0, cTmp = cPages; cTmp >>= 1; ++iOrder)
+        ;
+    if (cPages & ~(1 << iOrder))
+        ++iOrder;
+
+    return iOrder;
+}
+
+
+/**
+ * Allocates physical contiguous memory (below 4GB).
+ * The allocation is page aligned and the content is undefined.
+ *
+ * @returns Pointer to the memory block. This is page aligned.
+ * @param   pPhys   Where to store the physical address.
+ * @param   cb      The allocation size in bytes. This is always
+ *                  rounded up to PAGE_SIZE.
+ */
+RTR0DECL(void *) RTMemContAlloc(PRTCCPHYS pPhys, size_t cb)
+{
+    int             cOrder;
+    unsigned        cPages;
+    struct page    *paPages;
+    void           *pvRet;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * validate input.
+     */
+    Assert(VALID_PTR(pPhys));
+    Assert(cb > 0);
+
+    /*
+     * Allocate page pointer array.
+     */
+    cb = RT_ALIGN_Z(cb, PAGE_SIZE);
+    cPages = cb >> PAGE_SHIFT;
+    cOrder = CalcPowerOf2Order(cPages);
+#if (defined(RT_ARCH_AMD64) || defined(CONFIG_X86_PAE)) && defined(GFP_DMA32)
+    /* ZONE_DMA32: 0-4GB */
+    paPages = alloc_pages(GFP_DMA32 | __GFP_NOWARN, cOrder);
+    if (!paPages)
+#endif
+#ifdef RT_ARCH_AMD64
+        /* ZONE_DMA; 0-16MB */
+        paPages = alloc_pages(GFP_DMA | __GFP_NOWARN, cOrder);
+#else
+        /* ZONE_NORMAL: 0-896MB */
+        paPages = alloc_pages(GFP_USER | __GFP_NOWARN, cOrder);
+#endif
+    if (paPages)
+    {
+        /*
+         * Reserve the pages and mark them executable.
+         */
+        unsigned iPage;
+        for (iPage = 0; iPage < cPages; iPage++)
+        {
+            Assert(!PageHighMem(&paPages[iPage]));
+            if (iPage + 1 < cPages)
+            {
+                AssertMsg(          (uintptr_t)phys_to_virt(page_to_phys(&paPages[iPage])) + PAGE_SIZE
+                                ==  (uintptr_t)phys_to_virt(page_to_phys(&paPages[iPage + 1]))
+                          &&        page_to_phys(&paPages[iPage]) + PAGE_SIZE
+                                ==  page_to_phys(&paPages[iPage + 1]),
+                          ("iPage=%i cPages=%u [0]=%#llx,%p [1]=%#llx,%p\n", iPage, cPages,
+                           (long long)page_to_phys(&paPages[iPage]),     phys_to_virt(page_to_phys(&paPages[iPage])),
+                           (long long)page_to_phys(&paPages[iPage + 1]), phys_to_virt(page_to_phys(&paPages[iPage + 1])) ));
+            }
+
+            SetPageReserved(&paPages[iPage]);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 20) /** @todo find the exact kernel where change_page_attr was introduced. */
+            MY_SET_PAGES_EXEC(&paPages[iPage], 1);
+#endif
+        }
+        *pPhys = page_to_phys(paPages);
+        pvRet = phys_to_virt(page_to_phys(paPages));
+    }
+    else
+        pvRet = NULL;
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return pvRet;
+}
+RT_EXPORT_SYMBOL(RTMemContAlloc);
+
+
+/**
+ * Frees memory allocated using RTMemContAlloc().
+ *
+ * @param   pv      Pointer to return from RTMemContAlloc().
+ * @param   cb      The cb parameter passed to RTMemContAlloc().
+ */
+RTR0DECL(void) RTMemContFree(void *pv, size_t cb)
+{
+    if (pv)
+    {
+        int             cOrder;
+        unsigned        cPages;
+        unsigned        iPage;
+        struct page    *paPages;
+        IPRT_LINUX_SAVE_EFL_AC();
+
+        /* validate */
+        AssertMsg(!((uintptr_t)pv & PAGE_OFFSET_MASK), ("pv=%p\n", pv));
+        Assert(cb > 0);
+
+        /* calc order and get pages */
+        cb = RT_ALIGN_Z(cb, PAGE_SIZE);
+        cPages = cb >> PAGE_SHIFT;
+        cOrder = CalcPowerOf2Order(cPages);
+        paPages = virt_to_page(pv);
+
+        /*
+         * Restore page attributes freeing the pages.
+         */
+        for (iPage = 0; iPage < cPages; iPage++)
+        {
+            ClearPageReserved(&paPages[iPage]);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 20) /** @todo find the exact kernel where change_page_attr was introduced. */
+            MY_SET_PAGES_NOEXEC(&paPages[iPage], 1);
+#endif
+        }
+        __free_pages(paPages, cOrder);
+        IPRT_LINUX_RESTORE_EFL_AC();
+    }
+}
+RT_EXPORT_SYMBOL(RTMemContFree);
+
diff --git a/ubuntu/vbox/r0drv/linux/assert-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/assert-r0drv-linux.c
new file mode 100644 (file)
index 0000000..5a96ffd
--- /dev/null
@@ -0,0 +1,74 @@
+/* $Id: assert-r0drv-linux.c $ */
+/** @file
+ * IPRT -  Assertion Workers, Ring-0 Drivers, Linux.
+ */
+
+/*
+ * Copyright (C) 2007-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/log.h>
+#include <iprt/string.h>
+#include <iprt/stdarg.h>
+#include <iprt/asm.h>
+
+#include "internal/assert.h"
+
+
+DECLHIDDEN(void) rtR0AssertNativeMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    printk(KERN_EMERG
+           "\r\n!!Assertion Failed!!\r\n"
+           "Expression: %s\r\n"
+           "Location  : %s(%d) %s\r\n",
+           pszExpr, pszFile, uLine, pszFunction);
+    IPRT_LINUX_RESTORE_EFL_AC();
+}
+
+
+DECLHIDDEN(void) rtR0AssertNativeMsg2V(bool fInitial, const char *pszFormat, va_list va)
+{
+    char szMsg[256];
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    RTStrPrintfV(szMsg, sizeof(szMsg) - 1, pszFormat, va);
+    szMsg[sizeof(szMsg) - 1] = '\0';
+    printk(KERN_EMERG "%s", szMsg);
+
+    NOREF(fInitial);
+    IPRT_LINUX_RESTORE_EFL_AC();
+}
+
+
+RTR0DECL(void) RTR0AssertPanicSystem(void)
+{
+    panic("%s%s", g_szRTAssertMsg1, g_szRTAssertMsg2);
+}
+RT_EXPORT_SYMBOL(RTR0AssertPanicSystem);
+
diff --git a/ubuntu/vbox/r0drv/linux/initterm-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/initterm-r0drv-linux.c
new file mode 100644 (file)
index 0000000..7ff66af
--- /dev/null
@@ -0,0 +1,137 @@
+/* $Id: initterm-r0drv-linux.c $ */
+/** @file
+ * IPRT - Initialization & Termination, R0 Driver, Linux.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/err.h>
+#include <iprt/assert.h>
+#include "internal/initterm.h"
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** The IPRT work queue. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41)
+static struct workqueue_struct *g_prtR0LnxWorkQueue;
+#else
+static DECLARE_TASK_QUEUE(g_rtR0LnxWorkQueue);
+#endif
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+/* in alloc-r0drv0-linux.c */
+DECLHIDDEN(void) rtR0MemExecCleanup(void);
+
+
+/**
+ * Pushes an item onto the IPRT work queue.
+ *
+ * @param   pWork               The work item.
+ * @param   pfnWorker           The callback function.  It will be called back
+ *                              with @a pWork as argument.
+ */
+DECLHIDDEN(void) rtR0LnxWorkqueuePush(RTR0LNXWORKQUEUEITEM *pWork, void (*pfnWorker)(RTR0LNXWORKQUEUEITEM *))
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41)
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+    INIT_WORK(pWork, pfnWorker);
+# else
+    INIT_WORK(pWork, pfnWorker, pWork);
+# endif
+    queue_work(g_prtR0LnxWorkQueue, pWork);
+#else
+    INIT_TQUEUE(pWork, (void (*)(void *))pfnWorker, pWork);
+    queue_task(pWork, &g_rtR0LnxWorkQueue);
+#endif
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+}
+
+
+/**
+ * Flushes all items in the IPRT work queue.
+ *
+ * @remarks This is mostly for 2.4.x compatability.  Must not be called from
+ *          atomic contexts or with unncessary locks held.
+ */
+DECLHIDDEN(void) rtR0LnxWorkqueueFlush(void)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41)
+    flush_workqueue(g_prtR0LnxWorkQueue);
+#else
+    run_task_queue(&g_rtR0LnxWorkQueue);
+#endif
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+}
+
+
+DECLHIDDEN(int) rtR0InitNative(void)
+{
+    int rc = VINF_SUCCESS;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41)
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
+    g_prtR0LnxWorkQueue = create_workqueue("iprt-VBoxWQueue");
+ #else
+    g_prtR0LnxWorkQueue = create_workqueue("iprt-VBoxQ");
+ #endif
+    if (!g_prtR0LnxWorkQueue)
+        rc = VERR_NO_MEMORY;
+#endif
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return rc;
+}
+
+
+DECLHIDDEN(void) rtR0TermNative(void)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    rtR0LnxWorkqueueFlush();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41)
+    destroy_workqueue(g_prtR0LnxWorkQueue);
+    g_prtR0LnxWorkQueue = NULL;
+#endif
+
+    rtR0MemExecCleanup();
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+}
+
diff --git a/ubuntu/vbox/r0drv/linux/memobj-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/memobj-r0drv-linux.c
new file mode 100644 (file)
index 0000000..1707e8d
--- /dev/null
@@ -0,0 +1,1767 @@
+/* $Id: memobj-r0drv-linux.c $ */
+/** @file
+ * IPRT - Ring-0 Memory Objects, Linux.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "the-linux-kernel.h"
+
+#include <iprt/memobj.h>
+#include <iprt/alloc.h>
+#include <iprt/assert.h>
+#include <iprt/log.h>
+#include <iprt/process.h>
+#include <iprt/string.h>
+#include "internal/memobj.h"
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+/* early 2.6 kernels */
+#ifndef PAGE_SHARED_EXEC
+# define PAGE_SHARED_EXEC PAGE_SHARED
+#endif
+#ifndef PAGE_READONLY_EXEC
+# define PAGE_READONLY_EXEC PAGE_READONLY
+#endif
+
+/*
+ * 2.6.29+ kernels don't work with remap_pfn_range() anymore because
+ * track_pfn_vma_new() is apparently not defined for non-RAM pages.
+ * It should be safe to use vm_insert_page() older kernels as well.
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
+# define VBOX_USE_INSERT_PAGE
+#endif
+#if    defined(CONFIG_X86_PAE) \
+    && (   defined(HAVE_26_STYLE_REMAP_PAGE_RANGE) \
+        || (   LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) \
+            && LINUX_VERSION_CODE <  KERNEL_VERSION(2, 6, 11)))
+# define VBOX_USE_PAE_HACK
+#endif
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * The Darwin version of the memory object structure.
+ */
+typedef struct RTR0MEMOBJLNX
+{
+    /** The core structure. */
+    RTR0MEMOBJINTERNAL  Core;
+    /** Set if the allocation is contiguous.
+     * This means it has to be given back as one chunk. */
+    bool                fContiguous;
+    /** Set if we've vmap'ed the memory into ring-0. */
+    bool                fMappedToRing0;
+    /** The pages in the apPages array. */
+    size_t              cPages;
+    /** Array of struct page pointers. (variable size) */
+    struct page        *apPages[1];
+} RTR0MEMOBJLNX, *PRTR0MEMOBJLNX;
+
+
+static void rtR0MemObjLinuxFreePages(PRTR0MEMOBJLNX pMemLnx);
+
+
+/**
+ * Helper that converts from a RTR0PROCESS handle to a linux task.
+ *
+ * @returns The corresponding Linux task.
+ * @param   R0Process   IPRT ring-0 process handle.
+ */
+static struct task_struct *rtR0ProcessToLinuxTask(RTR0PROCESS R0Process)
+{
+    /** @todo fix rtR0ProcessToLinuxTask!! */
+    /** @todo many (all?) callers currently assume that we return 'current'! */
+    return R0Process == RTR0ProcHandleSelf() ? current : NULL;
+}
+
+
+/**
+ * Compute order. Some functions allocate 2^order pages.
+ *
+ * @returns order.
+ * @param   cPages      Number of pages.
+ */
+static int rtR0MemObjLinuxOrder(size_t cPages)
+{
+    int     iOrder;
+    size_t  cTmp;
+
+    for (iOrder = 0, cTmp = cPages; cTmp >>= 1; ++iOrder)
+        ;
+    if (cPages & ~((size_t)1 << iOrder))
+        ++iOrder;
+
+    return iOrder;
+}
+
+
+/**
+ * Converts from RTMEM_PROT_* to Linux PAGE_*.
+ *
+ * @returns Linux page protection constant.
+ * @param   fProt       The IPRT protection mask.
+ * @param   fKernel     Whether it applies to kernel or user space.
+ */
+static pgprot_t rtR0MemObjLinuxConvertProt(unsigned fProt, bool fKernel)
+{
+    switch (fProt)
+    {
+        default:
+            AssertMsgFailed(("%#x %d\n", fProt, fKernel));
+        case RTMEM_PROT_NONE:
+            return PAGE_NONE;
+
+        case RTMEM_PROT_READ:
+            return fKernel ? PAGE_KERNEL_RO         : PAGE_READONLY;
+
+        case RTMEM_PROT_WRITE:
+        case RTMEM_PROT_WRITE | RTMEM_PROT_READ:
+            return fKernel ? PAGE_KERNEL            : PAGE_SHARED;
+
+        case RTMEM_PROT_EXEC:
+        case RTMEM_PROT_EXEC | RTMEM_PROT_READ:
+#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
+            if (fKernel)
+            {
+                pgprot_t fPg = MY_PAGE_KERNEL_EXEC;
+                pgprot_val(fPg) &= ~_PAGE_RW;
+                return fPg;
+            }
+            return PAGE_READONLY_EXEC;
+#else
+            return fKernel ? MY_PAGE_KERNEL_EXEC    : PAGE_READONLY_EXEC;
+#endif
+
+        case RTMEM_PROT_WRITE | RTMEM_PROT_EXEC:
+        case RTMEM_PROT_WRITE | RTMEM_PROT_EXEC | RTMEM_PROT_READ:
+            return fKernel ? MY_PAGE_KERNEL_EXEC    : PAGE_SHARED_EXEC;
+    }
+}
+
+
+/**
+ * Worker for rtR0MemObjNativeReserveUser and rtR0MemObjNativerMapUser that creates
+ * an empty user space mapping.
+ *
+ * We acquire the mmap_sem of the task!
+ *
+ * @returns Pointer to the mapping.
+ *          (void *)-1 on failure.
+ * @param   R3PtrFixed  (RTR3PTR)-1 if anywhere, otherwise a specific location.
+ * @param   cb          The size of the mapping.
+ * @param   uAlignment  The alignment of the mapping.
+ * @param   pTask       The Linux task to create this mapping in.
+ * @param   fProt       The RTMEM_PROT_* mask.
+ */
+static void *rtR0MemObjLinuxDoMmap(RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, struct task_struct *pTask, unsigned fProt)
+{
+    unsigned fLnxProt;
+    unsigned long ulAddr;
+
+    Assert(pTask == current); /* do_mmap */
+    RT_NOREF_PV(pTask);
+
+    /*
+     * Convert from IPRT protection to mman.h PROT_ and call do_mmap.
+     */
+    fProt &= (RTMEM_PROT_NONE | RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC);
+    if (fProt == RTMEM_PROT_NONE)
+        fLnxProt = PROT_NONE;
+    else
+    {
+        fLnxProt = 0;
+        if (fProt & RTMEM_PROT_READ)
+            fLnxProt |= PROT_READ;
+        if (fProt & RTMEM_PROT_WRITE)
+            fLnxProt |= PROT_WRITE;
+        if (fProt & RTMEM_PROT_EXEC)
+            fLnxProt |= PROT_EXEC;
+    }
+
+    if (R3PtrFixed != (RTR3PTR)-1)
+    {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+        ulAddr = vm_mmap(NULL, R3PtrFixed, cb, fLnxProt, MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, 0);
+#else
+        down_write(&pTask->mm->mmap_sem);
+        ulAddr = do_mmap(NULL, R3PtrFixed, cb, fLnxProt, MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, 0);
+        up_write(&pTask->mm->mmap_sem);
+#endif
+    }
+    else
+    {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+        ulAddr = vm_mmap(NULL, 0, cb, fLnxProt, MAP_SHARED | MAP_ANONYMOUS, 0);
+#else
+        down_write(&pTask->mm->mmap_sem);
+        ulAddr = do_mmap(NULL, 0, cb, fLnxProt, MAP_SHARED | MAP_ANONYMOUS, 0);
+        up_write(&pTask->mm->mmap_sem);
+#endif
+        if (    !(ulAddr & ~PAGE_MASK)
+            &&  (ulAddr & (uAlignment - 1)))
+        {
+            /** @todo implement uAlignment properly... We'll probably need to make some dummy mappings to fill
+             * up alignment gaps. This is of course complicated by fragmentation (which we might have cause
+             * ourselves) and further by there begin two mmap strategies (top / bottom). */
+            /* For now, just ignore uAlignment requirements... */
+        }
+    }
+
+
+    if (ulAddr & ~PAGE_MASK) /* ~PAGE_MASK == PAGE_OFFSET_MASK */
+        return (void *)-1;
+    return (void *)ulAddr;
+}
+
+
+/**
+ * Worker that destroys a user space mapping.
+ * Undoes what rtR0MemObjLinuxDoMmap did.
+ *
+ * We acquire the mmap_sem of the task!
+ *
+ * @param   pv          The ring-3 mapping.
+ * @param   cb          The size of the mapping.
+ * @param   pTask       The Linux task to destroy this mapping in.
+ */
+static void rtR0MemObjLinuxDoMunmap(void *pv, size_t cb, struct task_struct *pTask)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+    Assert(pTask == current); RT_NOREF_PV(pTask);
+    vm_munmap((unsigned long)pv, cb);
+#elif defined(USE_RHEL4_MUNMAP)
+    down_write(&pTask->mm->mmap_sem);
+    do_munmap(pTask->mm, (unsigned long)pv, cb, 0); /* should it be 1 or 0? */
+    up_write(&pTask->mm->mmap_sem);
+#else
+    down_write(&pTask->mm->mmap_sem);
+    do_munmap(pTask->mm, (unsigned long)pv, cb);
+    up_write(&pTask->mm->mmap_sem);
+#endif
+}
+
+
+/**
+ * Internal worker that allocates physical pages and creates the memory object for them.
+ *
+ * @returns IPRT status code.
+ * @param   ppMemLnx    Where to store the memory object pointer.
+ * @param   enmType     The object type.
+ * @param   cb          The number of bytes to allocate.
+ * @param   uAlignment  The alignment of the physical memory.
+ *                      Only valid if fContiguous == true, ignored otherwise.
+ * @param   fFlagsLnx   The page allocation flags (GPFs).
+ * @param   fContiguous Whether the allocation must be contiguous.
+ * @param   rcNoMem     What to return when we're out of pages.
+ */
+static int rtR0MemObjLinuxAllocPages(PRTR0MEMOBJLNX *ppMemLnx, RTR0MEMOBJTYPE enmType, size_t cb,
+                                     size_t uAlignment, unsigned fFlagsLnx, bool fContiguous, int rcNoMem)
+{
+    size_t          iPage;
+    size_t const    cPages = cb >> PAGE_SHIFT;
+    struct page    *paPages;
+
+    /*
+     * Allocate a memory object structure that's large enough to contain
+     * the page pointer array.
+     */
+    PRTR0MEMOBJLNX  pMemLnx = (PRTR0MEMOBJLNX)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJLNX, apPages[cPages]), enmType, NULL, cb);
+    if (!pMemLnx)
+        return VERR_NO_MEMORY;
+    pMemLnx->cPages = cPages;
+
+     if (cPages > 255)
+     {
+# ifdef __GFP_REPEAT
+         /* Try hard to allocate the memory, but the allocation attempt might fail. */
+        fFlagsLnx |= __GFP_REPEAT;
+# endif
+# ifdef __GFP_NOMEMALLOC
+        /* Introduced with Linux 2.6.12: Don't use emergency reserves */
+        fFlagsLnx |= __GFP_NOMEMALLOC;
+# endif
+     }
+
+    /*
+     * Allocate the pages.
+     * For small allocations we'll try contiguous first and then fall back on page by page.
+     */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22)
+    if (    fContiguous
+        ||  cb <= PAGE_SIZE * 2)
+    {
+# ifdef VBOX_USE_INSERT_PAGE
+        paPages = alloc_pages(fFlagsLnx | __GFP_COMP | __GFP_NOWARN, rtR0MemObjLinuxOrder(cPages));
+# else
+        paPages = alloc_pages(fFlagsLnx | __GFP_NOWARN, rtR0MemObjLinuxOrder(cPages));
+# endif
+        if (paPages)
+        {
+            fContiguous = true;
+            for (iPage = 0; iPage < cPages; iPage++)
+                pMemLnx->apPages[iPage] = &paPages[iPage];
+        }
+        else if (fContiguous)
+        {
+            rtR0MemObjDelete(&pMemLnx->Core);
+            return rcNoMem;
+        }
+    }
+
+    if (!fContiguous)
+    {
+        for (iPage = 0; iPage < cPages; iPage++)
+        {
+            pMemLnx->apPages[iPage] = alloc_page(fFlagsLnx | __GFP_NOWARN);
+            if (RT_UNLIKELY(!pMemLnx->apPages[iPage]))
+            {
+                while (iPage-- > 0)
+                    __free_page(pMemLnx->apPages[iPage]);
+                rtR0MemObjDelete(&pMemLnx->Core);
+                return rcNoMem;
+            }
+        }
+    }
+
+#else /* < 2.4.22 */
+    /** @todo figure out why we didn't allocate page-by-page on 2.4.21 and older... */
+    paPages = alloc_pages(fFlagsLnx, rtR0MemObjLinuxOrder(cPages));
+    if (!paPages)
+    {
+        rtR0MemObjDelete(&pMemLnx->Core);
+        return rcNoMem;
+    }
+    for (iPage = 0; iPage < cPages; iPage++)
+    {
+        pMemLnx->apPages[iPage] = &paPages[iPage];
+        MY_SET_PAGES_EXEC(pMemLnx->apPages[iPage], 1);
+        if (PageHighMem(pMemLnx->apPages[iPage]))
+            BUG();
+    }
+
+    fContiguous = true;
+#endif /* < 2.4.22 */
+    pMemLnx->fContiguous = fContiguous;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)
+    /*
+     * Reserve the pages.
+     *
+     * Linux >= 4.5 with CONFIG_DEBUG_VM panics when setting PG_reserved on compound
+     * pages. According to Michal Hocko this shouldn't be necessary anyway because
+     * as pages which are not on the LRU list are never evictable.
+     */
+    for (iPage = 0; iPage < cPages; iPage++)
+        SetPageReserved(pMemLnx->apPages[iPage]);
+#endif
+
+    /*
+     * Note that the physical address of memory allocated with alloc_pages(flags, order)
+     * is always 2^(PAGE_SHIFT+order)-aligned.
+     */
+    if (   fContiguous
+        && uAlignment > PAGE_SIZE)
+    {
+        /*
+         * Check for alignment constraints. The physical address of memory allocated with
+         * alloc_pages(flags, order) is always 2^(PAGE_SHIFT+order)-aligned.
+         */
+        if (RT_UNLIKELY(page_to_phys(pMemLnx->apPages[0]) & (uAlignment - 1)))
+        {
+            /*
+             * This should never happen!
+             */
+            printk("rtR0MemObjLinuxAllocPages(cb=0x%lx, uAlignment=0x%lx): alloc_pages(..., %d) returned physical memory at 0x%lx!\n",
+                    (unsigned long)cb, (unsigned long)uAlignment, rtR0MemObjLinuxOrder(cPages), (unsigned long)page_to_phys(pMemLnx->apPages[0]));
+            rtR0MemObjLinuxFreePages(pMemLnx);
+            return rcNoMem;
+        }
+    }
+
+    *ppMemLnx = pMemLnx;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Frees the physical pages allocated by the rtR0MemObjLinuxAllocPages() call.
+ *
+ * This method does NOT free the object.
+ *
+ * @param   pMemLnx     The object which physical pages should be freed.
+ */
+static void rtR0MemObjLinuxFreePages(PRTR0MEMOBJLNX pMemLnx)
+{
+    size_t iPage = pMemLnx->cPages;
+    if (iPage > 0)
+    {
+        /*
+         * Restore the page flags.
+         */
+        while (iPage-- > 0)
+        {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)
+            /*
+             * See SetPageReserved() in rtR0MemObjLinuxAllocPages()
+             */
+            ClearPageReserved(pMemLnx->apPages[iPage]);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22)
+#else
+            MY_SET_PAGES_NOEXEC(pMemLnx->apPages[iPage], 1);
+#endif
+        }
+
+        /*
+         * Free the pages.
+         */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22)
+        if (!pMemLnx->fContiguous)
+        {
+            iPage = pMemLnx->cPages;
+            while (iPage-- > 0)
+                __free_page(pMemLnx->apPages[iPage]);
+        }
+        else
+#endif
+            __free_pages(pMemLnx->apPages[0], rtR0MemObjLinuxOrder(pMemLnx->cPages));
+
+        pMemLnx->cPages = 0;
+    }
+}
+
+
+/**
+ * Maps the allocation into ring-0.
+ *
+ * This will update the RTR0MEMOBJLNX::Core.pv and RTR0MEMOBJ::fMappedToRing0 members.
+ *
+ * Contiguous mappings that isn't in 'high' memory will already be mapped into kernel
+ * space, so we'll use that mapping if possible. If execute access is required, we'll
+ * play safe and do our own mapping.
+ *
+ * @returns IPRT status code.
+ * @param   pMemLnx     The linux memory object to map.
+ * @param   fExecutable Whether execute access is required.
+ */
+static int rtR0MemObjLinuxVMap(PRTR0MEMOBJLNX pMemLnx, bool fExecutable)
+{
+    int rc = VINF_SUCCESS;
+
+    /*
+     * Choose mapping strategy.
+     */
+    bool fMustMap = fExecutable
+                 || !pMemLnx->fContiguous;
+    if (!fMustMap)
+    {
+        size_t iPage = pMemLnx->cPages;
+        while (iPage-- > 0)
+            if (PageHighMem(pMemLnx->apPages[iPage]))
+            {
+                fMustMap = true;
+                break;
+            }
+    }
+
+    Assert(!pMemLnx->Core.pv);
+    Assert(!pMemLnx->fMappedToRing0);
+
+    if (fMustMap)
+    {
+        /*
+         * Use vmap - 2.4.22 and later.
+         */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22)
+        pgprot_t fPg;
+        pgprot_val(fPg) = _PAGE_PRESENT | _PAGE_RW;
+# ifdef _PAGE_NX
+        if (!fExecutable)
+            pgprot_val(fPg) |= _PAGE_NX;
+# endif
+
+# ifdef VM_MAP
+        pMemLnx->Core.pv = vmap(&pMemLnx->apPages[0], pMemLnx->cPages, VM_MAP, fPg);
+# else
+        pMemLnx->Core.pv = vmap(&pMemLnx->apPages[0], pMemLnx->cPages, VM_ALLOC, fPg);
+# endif
+        if (pMemLnx->Core.pv)
+            pMemLnx->fMappedToRing0 = true;
+        else
+            rc = VERR_MAP_FAILED;
+#else   /* < 2.4.22 */
+        rc = VERR_NOT_SUPPORTED;
+#endif
+    }
+    else
+    {
+        /*
+         * Use the kernel RAM mapping.
+         */
+        pMemLnx->Core.pv = phys_to_virt(page_to_phys(pMemLnx->apPages[0]));
+        Assert(pMemLnx->Core.pv);
+    }
+
+    return rc;
+}
+
+
+/**
+ * Undoes what rtR0MemObjLinuxVMap() did.
+ *
+ * @param   pMemLnx     The linux memory object.
+ */
+static void rtR0MemObjLinuxVUnmap(PRTR0MEMOBJLNX pMemLnx)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22)
+    if (pMemLnx->fMappedToRing0)
+    {
+        Assert(pMemLnx->Core.pv);
+        vunmap(pMemLnx->Core.pv);
+        pMemLnx->fMappedToRing0 = false;
+    }
+#else /* < 2.4.22 */
+    Assert(!pMemLnx->fMappedToRing0);
+#endif
+    pMemLnx->Core.pv = NULL;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeFree(RTR0MEMOBJ pMem)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    PRTR0MEMOBJLNX pMemLnx = (PRTR0MEMOBJLNX)pMem;
+
+    /*
+     * Release any memory that we've allocated or locked.
+     */
+    switch (pMemLnx->Core.enmType)
+    {
+        case RTR0MEMOBJTYPE_LOW:
+        case RTR0MEMOBJTYPE_PAGE:
+        case RTR0MEMOBJTYPE_CONT:
+        case RTR0MEMOBJTYPE_PHYS:
+        case RTR0MEMOBJTYPE_PHYS_NC:
+            rtR0MemObjLinuxVUnmap(pMemLnx);
+            rtR0MemObjLinuxFreePages(pMemLnx);
+            break;
+
+        case RTR0MEMOBJTYPE_LOCK:
+            if (pMemLnx->Core.u.Lock.R0Process != NIL_RTR0PROCESS)
+            {
+                struct task_struct *pTask = rtR0ProcessToLinuxTask(pMemLnx->Core.u.Lock.R0Process);
+                size_t              iPage;
+                Assert(pTask);
+                if (pTask && pTask->mm)
+                    down_read(&pTask->mm->mmap_sem);
+
+                iPage = pMemLnx->cPages;
+                while (iPage-- > 0)
+                {
+                    if (!PageReserved(pMemLnx->apPages[iPage]))
+                        SetPageDirty(pMemLnx->apPages[iPage]);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
+                    put_page(pMemLnx->apPages[iPage]);
+#else
+                    page_cache_release(pMemLnx->apPages[iPage]);
+#endif
+                }
+
+                if (pTask && pTask->mm)
+                    up_read(&pTask->mm->mmap_sem);
+            }
+            /* else: kernel memory - nothing to do here. */
+            break;
+
+        case RTR0MEMOBJTYPE_RES_VIRT:
+            Assert(pMemLnx->Core.pv);
+            if (pMemLnx->Core.u.ResVirt.R0Process != NIL_RTR0PROCESS)
+            {
+                struct task_struct *pTask = rtR0ProcessToLinuxTask(pMemLnx->Core.u.Lock.R0Process);
+                Assert(pTask);
+                if (pTask && pTask->mm)
+                    rtR0MemObjLinuxDoMunmap(pMemLnx->Core.pv, pMemLnx->Core.cb, pTask);
+            }
+            else
+            {
+                vunmap(pMemLnx->Core.pv);
+
+                Assert(pMemLnx->cPages == 1 && pMemLnx->apPages[0] != NULL);
+                __free_page(pMemLnx->apPages[0]);
+                pMemLnx->apPages[0] = NULL;
+                pMemLnx->cPages = 0;
+            }
+            pMemLnx->Core.pv = NULL;
+            break;
+
+        case RTR0MEMOBJTYPE_MAPPING:
+            Assert(pMemLnx->cPages == 0); Assert(pMemLnx->Core.pv);
+            if (pMemLnx->Core.u.ResVirt.R0Process != NIL_RTR0PROCESS)
+            {
+                struct task_struct *pTask = rtR0ProcessToLinuxTask(pMemLnx->Core.u.Lock.R0Process);
+                Assert(pTask);
+                if (pTask && pTask->mm)
+                    rtR0MemObjLinuxDoMunmap(pMemLnx->Core.pv, pMemLnx->Core.cb, pTask);
+            }
+            else
+                vunmap(pMemLnx->Core.pv);
+            pMemLnx->Core.pv = NULL;
+            break;
+
+        default:
+            AssertMsgFailed(("enmType=%d\n", pMemLnx->Core.enmType));
+            return VERR_INTERNAL_ERROR;
+    }
+    IPRT_LINUX_RESTORE_EFL_ONLY_AC();
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    PRTR0MEMOBJLNX pMemLnx;
+    int rc;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22)
+    rc = rtR0MemObjLinuxAllocPages(&pMemLnx, RTR0MEMOBJTYPE_PAGE, cb, PAGE_SIZE, GFP_HIGHUSER,
+                                   false /* non-contiguous */, VERR_NO_MEMORY);
+#else
+    rc = rtR0MemObjLinuxAllocPages(&pMemLnx, RTR0MEMOBJTYPE_PAGE, cb, PAGE_SIZE, GFP_USER,
+                                   false /* non-contiguous */, VERR_NO_MEMORY);
+#endif
+    if (RT_SUCCESS(rc))
+    {
+        rc = rtR0MemObjLinuxVMap(pMemLnx, fExecutable);
+        if (RT_SUCCESS(rc))
+        {
+            *ppMem = &pMemLnx->Core;
+            IPRT_LINUX_RESTORE_EFL_AC();
+            return rc;
+        }
+
+        rtR0MemObjLinuxFreePages(pMemLnx);
+        rtR0MemObjDelete(&pMemLnx->Core);
+    }
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return rc;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    PRTR0MEMOBJLNX pMemLnx;
+    int rc;
+
+    /* Try to avoid GFP_DMA. GFM_DMA32 was introduced with Linux 2.6.15. */
+#if (defined(RT_ARCH_AMD64) || defined(CONFIG_X86_PAE)) && defined(GFP_DMA32)
+    /* ZONE_DMA32: 0-4GB */
+    rc = rtR0MemObjLinuxAllocPages(&pMemLnx, RTR0MEMOBJTYPE_LOW, cb, PAGE_SIZE, GFP_DMA32,
+                                   false /* non-contiguous */, VERR_NO_LOW_MEMORY);
+    if (RT_FAILURE(rc))
+#endif
+#ifdef RT_ARCH_AMD64
+        /* ZONE_DMA: 0-16MB */
+        rc = rtR0MemObjLinuxAllocPages(&pMemLnx, RTR0MEMOBJTYPE_LOW, cb, PAGE_SIZE, GFP_DMA,
+                                       false /* non-contiguous */, VERR_NO_LOW_MEMORY);
+#else
+# ifdef CONFIG_X86_PAE
+# endif
+        /* ZONE_NORMAL: 0-896MB */
+        rc = rtR0MemObjLinuxAllocPages(&pMemLnx, RTR0MEMOBJTYPE_LOW, cb, PAGE_SIZE, GFP_USER,
+                                       false /* non-contiguous */, VERR_NO_LOW_MEMORY);
+#endif
+    if (RT_SUCCESS(rc))
+    {
+        rc = rtR0MemObjLinuxVMap(pMemLnx, fExecutable);
+        if (RT_SUCCESS(rc))
+        {
+            *ppMem = &pMemLnx->Core;
+            IPRT_LINUX_RESTORE_EFL_AC();
+            return rc;
+        }
+
+        rtR0MemObjLinuxFreePages(pMemLnx);
+        rtR0MemObjDelete(&pMemLnx->Core);
+    }
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return rc;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    PRTR0MEMOBJLNX pMemLnx;
+    int rc;
+
+#if (defined(RT_ARCH_AMD64) || defined(CONFIG_X86_PAE)) && defined(GFP_DMA32)
+    /* ZONE_DMA32: 0-4GB */
+    rc = rtR0MemObjLinuxAllocPages(&pMemLnx, RTR0MEMOBJTYPE_CONT, cb, PAGE_SIZE, GFP_DMA32,
+                                   true /* contiguous */, VERR_NO_CONT_MEMORY);
+    if (RT_FAILURE(rc))
+#endif
+#ifdef RT_ARCH_AMD64
+        /* ZONE_DMA: 0-16MB */
+        rc = rtR0MemObjLinuxAllocPages(&pMemLnx, RTR0MEMOBJTYPE_CONT, cb, PAGE_SIZE, GFP_DMA,
+                                       true /* contiguous */, VERR_NO_CONT_MEMORY);
+#else
+        /* ZONE_NORMAL (32-bit hosts): 0-896MB */
+        rc = rtR0MemObjLinuxAllocPages(&pMemLnx, RTR0MEMOBJTYPE_CONT, cb, PAGE_SIZE, GFP_USER,
+                                       true /* contiguous */, VERR_NO_CONT_MEMORY);
+#endif
+    if (RT_SUCCESS(rc))
+    {
+        rc = rtR0MemObjLinuxVMap(pMemLnx, fExecutable);
+        if (RT_SUCCESS(rc))
+        {
+#if defined(RT_STRICT) && (defined(RT_ARCH_AMD64) || defined(CONFIG_HIGHMEM64G))
+            size_t iPage = pMemLnx->cPages;
+            while (iPage-- > 0)
+                Assert(page_to_phys(pMemLnx->apPages[iPage]) < _4G);
+#endif
+            pMemLnx->Core.u.Cont.Phys = page_to_phys(pMemLnx->apPages[0]);
+            *ppMem = &pMemLnx->Core;
+            IPRT_LINUX_RESTORE_EFL_AC();
+            return rc;
+        }
+
+        rtR0MemObjLinuxFreePages(pMemLnx);
+        rtR0MemObjDelete(&pMemLnx->Core);
+    }
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return rc;
+}
+
+
+/**
+ * Worker for rtR0MemObjLinuxAllocPhysSub that tries one allocation strategy.
+ *
+ * @returns IPRT status code.
+ * @param   ppMemLnx    Where to
+ * @param   enmType     The object type.
+ * @param   cb          The size of the allocation.
+ * @param   uAlignment  The alignment of the physical memory.
+ *                      Only valid for fContiguous == true, ignored otherwise.
+ * @param   PhysHighest See rtR0MemObjNativeAllocPhys.
+ * @param   fGfp        The Linux GFP flags to use for the allocation.
+ */
+static int rtR0MemObjLinuxAllocPhysSub2(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJTYPE enmType,
+                                        size_t cb, size_t uAlignment, RTHCPHYS PhysHighest, unsigned fGfp)
+{
+    PRTR0MEMOBJLNX pMemLnx;
+    int rc;
+
+    rc = rtR0MemObjLinuxAllocPages(&pMemLnx, enmType, cb, uAlignment, fGfp,
+                                   enmType == RTR0MEMOBJTYPE_PHYS /* contiguous / non-contiguous */,
+                                   VERR_NO_PHYS_MEMORY);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    /*
+     * Check the addresses if necessary. (Can be optimized a bit for PHYS.)
+     */
+    if (PhysHighest != NIL_RTHCPHYS)
+    {
+        size_t iPage = pMemLnx->cPages;
+        while (iPage-- > 0)
+            if (page_to_phys(pMemLnx->apPages[iPage]) > PhysHighest)
+            {
+                rtR0MemObjLinuxFreePages(pMemLnx);
+                rtR0MemObjDelete(&pMemLnx->Core);
+                return VERR_NO_MEMORY;
+            }
+    }
+
+    /*
+     * Complete the object.
+     */
+    if (enmType == RTR0MEMOBJTYPE_PHYS)
+    {
+        pMemLnx->Core.u.Phys.PhysBase = page_to_phys(pMemLnx->apPages[0]);
+        pMemLnx->Core.u.Phys.fAllocated = true;
+    }
+    *ppMem = &pMemLnx->Core;
+    return rc;
+}
+
+
+/**
+ * Worker for rtR0MemObjNativeAllocPhys and rtR0MemObjNativeAllocPhysNC.
+ *
+ * @returns IPRT status code.
+ * @param   ppMem       Where to store the memory object pointer on success.
+ * @param   enmType     The object type.
+ * @param   cb          The size of the allocation.
+ * @param   uAlignment  The alignment of the physical memory.
+ *                      Only valid for enmType == RTR0MEMOBJTYPE_PHYS, ignored otherwise.
+ * @param   PhysHighest See rtR0MemObjNativeAllocPhys.
+ */
+static int rtR0MemObjLinuxAllocPhysSub(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJTYPE enmType,
+                                       size_t cb, size_t uAlignment, RTHCPHYS PhysHighest)
+{
+    int rc;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * There are two clear cases and that's the <=16MB and anything-goes ones.
+     * When the physical address limit is somewhere in-between those two we'll
+     * just have to try, starting with HIGHUSER and working our way thru the
+     * different types, hoping we'll get lucky.
+     *
+     * We should probably move this physical address restriction logic up to
+     * the page alloc function as it would be more efficient there. But since
+     * we don't expect this to be a performance issue just yet it can wait.
+     */
+    if (PhysHighest == NIL_RTHCPHYS)
+        /* ZONE_HIGHMEM: the whole physical memory */
+        rc = rtR0MemObjLinuxAllocPhysSub2(ppMem, enmType, cb, uAlignment, PhysHighest, GFP_HIGHUSER);
+    else if (PhysHighest <= _1M * 16)
+        /* ZONE_DMA: 0-16MB */
+        rc = rtR0MemObjLinuxAllocPhysSub2(ppMem, enmType, cb, uAlignment, PhysHighest, GFP_DMA);
+    else
+    {
+        rc = VERR_NO_MEMORY;
+        if (RT_FAILURE(rc))
+            /* ZONE_HIGHMEM: the whole physical memory */
+            rc = rtR0MemObjLinuxAllocPhysSub2(ppMem, enmType, cb, uAlignment, PhysHighest, GFP_HIGHUSER);
+        if (RT_FAILURE(rc))
+            /* ZONE_NORMAL: 0-896MB */
+            rc = rtR0MemObjLinuxAllocPhysSub2(ppMem, enmType, cb, uAlignment, PhysHighest, GFP_USER);
+#ifdef GFP_DMA32
+        if (RT_FAILURE(rc))
+            /* ZONE_DMA32: 0-4GB */
+            rc = rtR0MemObjLinuxAllocPhysSub2(ppMem, enmType, cb, uAlignment, PhysHighest, GFP_DMA32);
+#endif
+        if (RT_FAILURE(rc))
+            /* ZONE_DMA: 0-16MB */
+            rc = rtR0MemObjLinuxAllocPhysSub2(ppMem, enmType, cb, uAlignment, PhysHighest, GFP_DMA);
+    }
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return rc;
+}
+
+
+/**
+ * Translates a kernel virtual address to a linux page structure by walking the
+ * page tables.
+ *
+ * @note    We do assume that the page tables will not change as we are walking
+ *          them.  This assumption is rather forced by the fact that I could not
+ *          immediately see any way of preventing this from happening.  So, we
+ *          take some extra care when accessing them.
+ *
+ *          Because of this, we don't want to use this function on memory where
+ *          attribute changes to nearby pages is likely to cause large pages to
+ *          be used or split up. So, don't use this for the linear mapping of
+ *          physical memory.
+ *
+ * @returns Pointer to the page structur or NULL if it could not be found.
+ * @param   pv      The kernel virtual address.
+ */
+static struct page *rtR0MemObjLinuxVirtToPage(void *pv)
+{
+    unsigned long   ulAddr = (unsigned long)pv;
+    unsigned long   pfn;
+    struct page    *pPage;
+    pte_t          *pEntry;
+    union
+    {
+        pgd_t       Global;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+        p4d_t       Four;
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
+        pud_t       Upper;
+#endif
+        pmd_t       Middle;
+        pte_t       Entry;
+    } u;
+
+    /* Should this happen in a situation this code will be called in?  And if
+     * so, can it change under our feet?  See also
+     * "Documentation/vm/active_mm.txt" in the kernel sources. */
+    if (RT_UNLIKELY(!current->active_mm))
+        return NULL;
+    u.Global = *pgd_offset(current->active_mm, ulAddr);
+    if (RT_UNLIKELY(pgd_none(u.Global)))
+        return NULL;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+    u.Four  = *p4d_offset(&u.Global, ulAddr);
+    if (RT_UNLIKELY(p4d_none(u.Four)))
+        return NULL;
+    if (p4d_large(u.Four))
+    {
+        pPage = p4d_page(u.Four);
+        AssertReturn(pPage, NULL);
+        pfn   = page_to_pfn(pPage);      /* doing the safe way... */
+        AssertCompile(P4D_SHIFT - PAGE_SHIFT < 31);
+        pfn  += (ulAddr >> PAGE_SHIFT) & ((UINT32_C(1) << (P4D_SHIFT - PAGE_SHIFT)) - 1);
+        return pfn_to_page(pfn);
+    }
+    u.Upper = *pud_offset(&u.Four, ulAddr);
+# else /* < 4.12 */
+    u.Upper = *pud_offset(&u.Global, ulAddr);
+# endif /* < 4.12 */
+    if (RT_UNLIKELY(pud_none(u.Upper)))
+        return NULL;
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+    if (pud_large(u.Upper))
+    {
+        pPage = pud_page(u.Upper);
+        AssertReturn(pPage, NULL);
+        pfn  = page_to_pfn(pPage);      /* doing the safe way... */
+        pfn += (ulAddr >> PAGE_SHIFT) & ((UINT32_C(1) << (PUD_SHIFT - PAGE_SHIFT)) - 1);
+        return pfn_to_page(pfn);
+    }
+# endif
+    u.Middle = *pmd_offset(&u.Upper, ulAddr);
+#else  /* < 2.6.11 */
+    u.Middle = *pmd_offset(&u.Global, ulAddr);
+#endif /* < 2.6.11 */
+    if (RT_UNLIKELY(pmd_none(u.Middle)))
+        return NULL;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+    if (pmd_large(u.Middle))
+    {
+        pPage = pmd_page(u.Middle);
+        AssertReturn(pPage, NULL);
+        pfn  = page_to_pfn(pPage);      /* doing the safe way... */
+        pfn += (ulAddr >> PAGE_SHIFT) & ((UINT32_C(1) << (PMD_SHIFT - PAGE_SHIFT)) - 1);
+        return pfn_to_page(pfn);
+    }
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 5) || defined(pte_offset_map) /* As usual, RHEL 3 had pte_offset_map earlier. */
+    pEntry = pte_offset_map(&u.Middle, ulAddr);
+#else
+    pEntry = pte_offset(&u.Middle, ulAddr);
+#endif
+    if (RT_UNLIKELY(!pEntry))
+        return NULL;
+    u.Entry = *pEntry;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 5) || defined(pte_offset_map)
+    pte_unmap(pEntry);
+#endif
+
+    if (RT_UNLIKELY(!pte_present(u.Entry)))
+        return NULL;
+    return pte_page(u.Entry);
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment)
+{
+    return rtR0MemObjLinuxAllocPhysSub(ppMem, RTR0MEMOBJTYPE_PHYS, cb, uAlignment, PhysHighest);
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest)
+{
+    return rtR0MemObjLinuxAllocPhysSub(ppMem, RTR0MEMOBJTYPE_PHYS_NC, cb, PAGE_SIZE, PhysHighest);
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeEnterPhys(PPRTR0MEMOBJINTERNAL ppMem, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * All we need to do here is to validate that we can use
+     * ioremap on the specified address (32/64-bit dma_addr_t).
+     */
+    PRTR0MEMOBJLNX  pMemLnx;
+    dma_addr_t      PhysAddr = Phys;
+    AssertMsgReturn(PhysAddr == Phys, ("%#llx\n", (unsigned long long)Phys), VERR_ADDRESS_TOO_BIG);
+
+    pMemLnx = (PRTR0MEMOBJLNX)rtR0MemObjNew(sizeof(*pMemLnx), RTR0MEMOBJTYPE_PHYS, NULL, cb);
+    if (!pMemLnx)
+    {
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return VERR_NO_MEMORY;
+    }
+
+    pMemLnx->Core.u.Phys.PhysBase = PhysAddr;
+    pMemLnx->Core.u.Phys.fAllocated = false;
+    pMemLnx->Core.u.Phys.uCachePolicy = uCachePolicy;
+    Assert(!pMemLnx->cPages);
+    *ppMem = &pMemLnx->Core;
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+
+/* openSUSE Leap 42.3 detection :-/ */
+#if    LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) \
+    && LINUX_VERSION_CODE <  KERNEL_VERSION(4, 6, 0) \
+    && defined(FAULT_FLAG_REMOTE)
+# define GET_USER_PAGES_API     KERNEL_VERSION(4, 10, 0) /* no typo! */
+#else
+# define GET_USER_PAGES_API     LINUX_VERSION_CODE
+#endif
+
+DECLHIDDEN(int) rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    const int cPages = cb >> PAGE_SHIFT;
+    struct task_struct *pTask = rtR0ProcessToLinuxTask(R0Process);
+    struct vm_area_struct **papVMAs;
+    PRTR0MEMOBJLNX pMemLnx;
+    int             rc      = VERR_NO_MEMORY;
+    int  const      fWrite  = fAccess & RTMEM_PROT_WRITE ? 1 : 0;
+
+    /*
+     * Check for valid task and size overflows.
+     */
+    if (!pTask)
+        return VERR_NOT_SUPPORTED;
+    if (((size_t)cPages << PAGE_SHIFT) != cb)
+        return VERR_OUT_OF_RANGE;
+
+    /*
+     * Allocate the memory object and a temporary buffer for the VMAs.
+     */
+    pMemLnx = (PRTR0MEMOBJLNX)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJLNX, apPages[cPages]), RTR0MEMOBJTYPE_LOCK, (void *)R3Ptr, cb);
+    if (!pMemLnx)
+    {
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return VERR_NO_MEMORY;
+    }
+
+    papVMAs = (struct vm_area_struct **)RTMemAlloc(sizeof(*papVMAs) * cPages);
+    if (papVMAs)
+    {
+        down_read(&pTask->mm->mmap_sem);
+
+        /*
+         * Get user pages.
+         */
+#if GET_USER_PAGES_API >= KERNEL_VERSION(4, 6, 0)
+        if (R0Process == RTR0ProcHandleSelf())
+            rc = get_user_pages(R3Ptr,                  /* Where from. */
+                                cPages,                 /* How many pages. */
+# if GET_USER_PAGES_API >= KERNEL_VERSION(4, 9, 0)
+                                fWrite ? FOLL_WRITE |   /* Write to memory. */
+                                         FOLL_FORCE     /* force write access. */
+                                       : 0,             /* Write to memory. */
+# else
+                                fWrite,                 /* Write to memory. */
+                                fWrite,                 /* force write access. */
+# endif
+                                &pMemLnx->apPages[0],   /* Page array. */
+                                papVMAs);               /* vmas */
+        /*
+         * Actually this should not happen at the moment as call this function
+         * only for our own process.
+         */
+        else
+            rc = get_user_pages_remote(
+                                pTask,                  /* Task for fault accounting. */
+                                pTask->mm,              /* Whose pages. */
+                                R3Ptr,                  /* Where from. */
+                                cPages,                 /* How many pages. */
+# if GET_USER_PAGES_API >= KERNEL_VERSION(4, 9, 0)
+                                fWrite ? FOLL_WRITE |   /* Write to memory. */
+                                         FOLL_FORCE     /* force write access. */
+                                       : 0,             /* Write to memory. */
+# else
+                                fWrite,                 /* Write to memory. */
+                                fWrite,                 /* force write access. */
+# endif
+                                &pMemLnx->apPages[0],   /* Page array. */
+                                papVMAs                 /* vmas */
+# if GET_USER_PAGES_API >= KERNEL_VERSION(4, 10, 0)
+                                , NULL                  /* locked */
+# endif
+                                );
+#else /* GET_USER_PAGES_API < KERNEL_VERSION(4, 6, 0) */
+            rc = get_user_pages(pTask,                  /* Task for fault accounting. */
+                                pTask->mm,              /* Whose pages. */
+                                R3Ptr,                  /* Where from. */
+                                cPages,                 /* How many pages. */
+# if GET_USER_PAGES_API >= KERNEL_VERSION(4, 9, 0)
+                                fWrite ? FOLL_WRITE |   /* Write to memory. */
+                                         FOLL_FORCE     /* force write access. */
+                                       : 0,             /* Write to memory. */
+# else
+                                fWrite,                 /* Write to memory. */
+                                fWrite,                 /* force write access. */
+# endif
+                                &pMemLnx->apPages[0],   /* Page array. */
+                                papVMAs);               /* vmas */
+#endif /* GET_USER_PAGES_API < KERNEL_VERSION(4, 6, 0) */
+        if (rc == cPages)
+        {
+            /*
+             * Flush dcache (required?), protect against fork and _really_ pin the page
+             * table entries. get_user_pages() will protect against swapping out the
+             * pages but it will NOT protect against removing page table entries. This
+             * can be achieved with
+             *   - using mlock / mmap(..., MAP_LOCKED, ...) from userland. This requires
+             *     an appropriate limit set up with setrlimit(..., RLIMIT_MEMLOCK, ...).
+             *     Usual Linux distributions support only a limited size of locked pages
+             *     (e.g. 32KB).
+             *   - setting the PageReserved bit (as we do in rtR0MemObjLinuxAllocPages()
+             *     or by
+             *   - setting the VM_LOCKED flag. This is the same as doing mlock() without
+             *     a range check.
+             */
+            /** @todo The Linux fork() protection will require more work if this API
+             * is to be used for anything but locking VM pages. */
+            while (rc-- > 0)
+            {
+                flush_dcache_page(pMemLnx->apPages[rc]);
+                papVMAs[rc]->vm_flags |= (VM_DONTCOPY | VM_LOCKED);
+            }
+
+            up_read(&pTask->mm->mmap_sem);
+
+            RTMemFree(papVMAs);
+
+            pMemLnx->Core.u.Lock.R0Process = R0Process;
+            pMemLnx->cPages = cPages;
+            Assert(!pMemLnx->fMappedToRing0);
+            *ppMem = &pMemLnx->Core;
+
+            IPRT_LINUX_RESTORE_EFL_AC();
+            return VINF_SUCCESS;
+        }
+
+        /*
+         * Failed - we need to unlock any pages that we succeeded to lock.
+         */
+        while (rc-- > 0)
+        {
+            if (!PageReserved(pMemLnx->apPages[rc]))
+                SetPageDirty(pMemLnx->apPages[rc]);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
+            put_page(pMemLnx->apPages[rc]);
+#else
+            page_cache_release(pMemLnx->apPages[rc]);
+#endif
+        }
+
+        up_read(&pTask->mm->mmap_sem);
+
+        RTMemFree(papVMAs);
+        rc = VERR_LOCK_FAILED;
+    }
+
+    rtR0MemObjDelete(&pMemLnx->Core);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return rc;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    void           *pvLast = (uint8_t *)pv + cb - 1;
+    size_t const    cPages = cb >> PAGE_SHIFT;
+    PRTR0MEMOBJLNX  pMemLnx;
+    bool            fLinearMapping;
+    int             rc;
+    uint8_t        *pbPage;
+    size_t          iPage;
+    NOREF(fAccess);
+
+    if (   !RTR0MemKernelIsValidAddr(pv)
+        || !RTR0MemKernelIsValidAddr(pv + cb))
+        return VERR_INVALID_PARAMETER;
+
+    /*
+     * The lower part of the kernel memory has a linear mapping between
+     * physical and virtual addresses. So we take a short cut here.  This is
+     * assumed to be the cleanest way to handle those addresses (and the code
+     * is well tested, though the test for determining it is not very nice).
+     * If we ever decide it isn't we can still remove it.
+     */
+#if 0
+    fLinearMapping = (unsigned long)pvLast < VMALLOC_START;
+#else
+    fLinearMapping = (unsigned long)pv     >= (unsigned long)__va(0)
+                  && (unsigned long)pvLast <  (unsigned long)high_memory;
+#endif
+
+    /*
+     * Allocate the memory object.
+     */
+    pMemLnx = (PRTR0MEMOBJLNX)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJLNX, apPages[cPages]), RTR0MEMOBJTYPE_LOCK, pv, cb);
+    if (!pMemLnx)
+    {
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return VERR_NO_MEMORY;
+    }
+
+    /*
+     * Gather the pages.
+     * We ASSUME all kernel pages are non-swappable and non-movable.
+     */
+    rc     = VINF_SUCCESS;
+    pbPage = (uint8_t *)pvLast;
+    iPage  = cPages;
+    if (!fLinearMapping)
+    {
+        while (iPage-- > 0)
+        {
+            struct page *pPage = rtR0MemObjLinuxVirtToPage(pbPage);
+            if (RT_UNLIKELY(!pPage))
+            {
+                rc = VERR_LOCK_FAILED;
+                break;
+            }
+            pMemLnx->apPages[iPage] = pPage;
+            pbPage -= PAGE_SIZE;
+        }
+    }
+    else
+    {
+        while (iPage-- > 0)
+        {
+            pMemLnx->apPages[iPage] = virt_to_page(pbPage);
+            pbPage -= PAGE_SIZE;
+        }
+    }
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Complete the memory object and return.
+         */
+        pMemLnx->Core.u.Lock.R0Process = NIL_RTR0PROCESS;
+        pMemLnx->cPages = cPages;
+        Assert(!pMemLnx->fMappedToRing0);
+        *ppMem = &pMemLnx->Core;
+
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return VINF_SUCCESS;
+    }
+
+    rtR0MemObjDelete(&pMemLnx->Core);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return rc;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22)
+    IPRT_LINUX_SAVE_EFL_AC();
+    const size_t cPages = cb >> PAGE_SHIFT;
+    struct page *pDummyPage;
+    struct page **papPages;
+
+    /* check for unsupported stuff. */
+    AssertMsgReturn(pvFixed == (void *)-1, ("%p\n", pvFixed), VERR_NOT_SUPPORTED);
+    if (uAlignment > PAGE_SIZE)
+        return VERR_NOT_SUPPORTED;
+
+    /*
+     * Allocate a dummy page and create a page pointer array for vmap such that
+     * the dummy page is mapped all over the reserved area.
+     */
+    pDummyPage = alloc_page(GFP_HIGHUSER | __GFP_NOWARN);
+    if (pDummyPage)
+    {
+        papPages = RTMemAlloc(sizeof(*papPages) * cPages);
+        if (papPages)
+        {
+            void *pv;
+            size_t iPage = cPages;
+            while (iPage-- > 0)
+                papPages[iPage] = pDummyPage;
+# ifdef VM_MAP
+            pv = vmap(papPages, cPages, VM_MAP, PAGE_KERNEL_RO);
+# else
+            pv = vmap(papPages, cPages, VM_ALLOC, PAGE_KERNEL_RO);
+# endif
+            RTMemFree(papPages);
+            if (pv)
+            {
+                PRTR0MEMOBJLNX pMemLnx = (PRTR0MEMOBJLNX)rtR0MemObjNew(sizeof(*pMemLnx), RTR0MEMOBJTYPE_RES_VIRT, pv, cb);
+                if (pMemLnx)
+                {
+                    pMemLnx->Core.u.ResVirt.R0Process = NIL_RTR0PROCESS;
+                    pMemLnx->cPages = 1;
+                    pMemLnx->apPages[0] = pDummyPage;
+                    *ppMem = &pMemLnx->Core;
+                    IPRT_LINUX_RESTORE_EFL_AC();
+                    return VINF_SUCCESS;
+                }
+                vunmap(pv);
+            }
+        }
+        __free_page(pDummyPage);
+    }
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VERR_NO_MEMORY;
+
+#else   /* < 2.4.22 */
+    /*
+     * Could probably use ioremap here, but the caller is in a better position than us
+     * to select some safe physical memory.
+     */
+    return VERR_NOT_SUPPORTED;
+#endif
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    PRTR0MEMOBJLNX      pMemLnx;
+    void               *pv;
+    struct task_struct *pTask = rtR0ProcessToLinuxTask(R0Process);
+    if (!pTask)
+        return VERR_NOT_SUPPORTED;
+
+    /*
+     * Check that the specified alignment is supported.
+     */
+    if (uAlignment > PAGE_SIZE)
+        return VERR_NOT_SUPPORTED;
+
+    /*
+     * Let rtR0MemObjLinuxDoMmap do the difficult bits.
+     */
+    pv = rtR0MemObjLinuxDoMmap(R3PtrFixed, cb, uAlignment, pTask, RTMEM_PROT_NONE);
+    if (pv == (void *)-1)
+    {
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return VERR_NO_MEMORY;
+    }
+
+    pMemLnx = (PRTR0MEMOBJLNX)rtR0MemObjNew(sizeof(*pMemLnx), RTR0MEMOBJTYPE_RES_VIRT, pv, cb);
+    if (!pMemLnx)
+    {
+        rtR0MemObjLinuxDoMunmap(pv, cb, pTask);
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return VERR_NO_MEMORY;
+    }
+
+    pMemLnx->Core.u.ResVirt.R0Process = R0Process;
+    *ppMem = &pMemLnx->Core;
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap,
+                                          void *pvFixed, size_t uAlignment,
+                                          unsigned fProt, size_t offSub, size_t cbSub)
+{
+    int rc = VERR_NO_MEMORY;
+    PRTR0MEMOBJLNX pMemLnxToMap = (PRTR0MEMOBJLNX)pMemToMap;
+    PRTR0MEMOBJLNX pMemLnx;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /* Fail if requested to do something we can't. */
+    AssertMsgReturn(!offSub && !cbSub, ("%#x %#x\n", offSub, cbSub), VERR_NOT_SUPPORTED);
+    AssertMsgReturn(pvFixed == (void *)-1, ("%p\n", pvFixed), VERR_NOT_SUPPORTED);
+    if (uAlignment > PAGE_SIZE)
+        return VERR_NOT_SUPPORTED;
+
+    /*
+     * Create the IPRT memory object.
+     */
+    pMemLnx = (PRTR0MEMOBJLNX)rtR0MemObjNew(sizeof(*pMemLnx), RTR0MEMOBJTYPE_MAPPING, NULL, pMemLnxToMap->Core.cb);
+    if (pMemLnx)
+    {
+        if (pMemLnxToMap->cPages)
+        {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22)
+            /*
+             * Use vmap - 2.4.22 and later.
+             */
+            pgprot_t fPg = rtR0MemObjLinuxConvertProt(fProt, true /* kernel */);
+# ifdef VM_MAP
+            pMemLnx->Core.pv = vmap(&pMemLnxToMap->apPages[0], pMemLnxToMap->cPages, VM_MAP, fPg);
+# else
+            pMemLnx->Core.pv = vmap(&pMemLnxToMap->apPages[0], pMemLnxToMap->cPages, VM_ALLOC, fPg);
+# endif
+            if (pMemLnx->Core.pv)
+            {
+                pMemLnx->fMappedToRing0 = true;
+                rc = VINF_SUCCESS;
+            }
+            else
+                rc = VERR_MAP_FAILED;
+
+#else   /* < 2.4.22 */
+            /*
+             * Only option here is to share mappings if possible and forget about fProt.
+             */
+            if (rtR0MemObjIsRing3(pMemToMap))
+                rc = VERR_NOT_SUPPORTED;
+            else
+            {
+                rc = VINF_SUCCESS;
+                if (!pMemLnxToMap->Core.pv)
+                    rc = rtR0MemObjLinuxVMap(pMemLnxToMap, !!(fProt & RTMEM_PROT_EXEC));
+                if (RT_SUCCESS(rc))
+                {
+                    Assert(pMemLnxToMap->Core.pv);
+                    pMemLnx->Core.pv = pMemLnxToMap->Core.pv;
+                }
+            }
+#endif
+        }
+        else
+        {
+            /*
+             * MMIO / physical memory.
+             */
+            Assert(pMemLnxToMap->Core.enmType == RTR0MEMOBJTYPE_PHYS && !pMemLnxToMap->Core.u.Phys.fAllocated);
+            pMemLnx->Core.pv = pMemLnxToMap->Core.u.Phys.uCachePolicy == RTMEM_CACHE_POLICY_MMIO
+                             ? ioremap_nocache(pMemLnxToMap->Core.u.Phys.PhysBase, pMemLnxToMap->Core.cb)
+                             : ioremap(pMemLnxToMap->Core.u.Phys.PhysBase, pMemLnxToMap->Core.cb);
+            if (pMemLnx->Core.pv)
+            {
+                /** @todo fix protection. */
+                rc = VINF_SUCCESS;
+            }
+        }
+        if (RT_SUCCESS(rc))
+        {
+            pMemLnx->Core.u.Mapping.R0Process = NIL_RTR0PROCESS;
+            *ppMem = &pMemLnx->Core;
+            IPRT_LINUX_RESTORE_EFL_AC();
+            return VINF_SUCCESS;
+        }
+        rtR0MemObjDelete(&pMemLnx->Core);
+    }
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return rc;
+}
+
+
+#ifdef VBOX_USE_PAE_HACK
+/**
+ * Replace the PFN of a PTE with the address of the actual page.
+ *
+ * The caller maps a reserved dummy page at the address with the desired access
+ * and flags.
+ *
+ * This hack is required for older Linux kernels which don't provide
+ * remap_pfn_range().
+ *
+ * @returns 0 on success, -ENOMEM on failure.
+ * @param   mm          The memory context.
+ * @param   ulAddr      The mapping address.
+ * @param   Phys        The physical address of the page to map.
+ */
+static int rtR0MemObjLinuxFixPte(struct mm_struct *mm, unsigned long ulAddr, RTHCPHYS Phys)
+{
+    int rc = -ENOMEM;
+    pgd_t *pgd;
+
+    spin_lock(&mm->page_table_lock);
+
+    pgd = pgd_offset(mm, ulAddr);
+    if (!pgd_none(*pgd) && !pgd_bad(*pgd))
+    {
+        pmd_t *pmd = pmd_offset(pgd, ulAddr);
+        if (!pmd_none(*pmd))
+        {
+            pte_t *ptep = pte_offset_map(pmd, ulAddr);
+            if (ptep)
+            {
+                pte_t pte = *ptep;
+                pte.pte_high &= 0xfff00000;
+                pte.pte_high |= ((Phys >> 32) & 0x000fffff);
+                pte.pte_low  &= 0x00000fff;
+                pte.pte_low  |= (Phys & 0xfffff000);
+                set_pte(ptep, pte);
+                pte_unmap(ptep);
+                rc = 0;
+            }
+        }
+    }
+
+    spin_unlock(&mm->page_table_lock);
+    return rc;
+}
+#endif /* VBOX_USE_PAE_HACK */
+
+
+DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed,
+                                        size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
+{
+    struct task_struct *pTask        = rtR0ProcessToLinuxTask(R0Process);
+    PRTR0MEMOBJLNX      pMemLnxToMap = (PRTR0MEMOBJLNX)pMemToMap;
+    int                 rc           = VERR_NO_MEMORY;
+    PRTR0MEMOBJLNX      pMemLnx;
+#ifdef VBOX_USE_PAE_HACK
+    struct page        *pDummyPage;
+    RTHCPHYS            DummyPhys;
+#endif
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * Check for restrictions.
+     */
+    if (!pTask)
+        return VERR_NOT_SUPPORTED;
+    if (uAlignment > PAGE_SIZE)
+        return VERR_NOT_SUPPORTED;
+
+#ifdef VBOX_USE_PAE_HACK
+    /*
+     * Allocate a dummy page for use when mapping the memory.
+     */
+    pDummyPage = alloc_page(GFP_USER | __GFP_NOWARN);
+    if (!pDummyPage)
+    {
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return VERR_NO_MEMORY;
+    }
+    SetPageReserved(pDummyPage);
+    DummyPhys = page_to_phys(pDummyPage);
+#endif
+
+    /*
+     * Create the IPRT memory object.
+     */
+    pMemLnx = (PRTR0MEMOBJLNX)rtR0MemObjNew(sizeof(*pMemLnx), RTR0MEMOBJTYPE_MAPPING, NULL, pMemLnxToMap->Core.cb);
+    if (pMemLnx)
+    {
+        /*
+         * Allocate user space mapping.
+         */
+        void *pv;
+        pv = rtR0MemObjLinuxDoMmap(R3PtrFixed, pMemLnxToMap->Core.cb, uAlignment, pTask, fProt);
+        if (pv != (void *)-1)
+        {
+            /*
+             * Map page by page into the mmap area.
+             * This is generic, paranoid and not very efficient.
+             */
+            pgprot_t        fPg = rtR0MemObjLinuxConvertProt(fProt, false /* user */);
+            unsigned long   ulAddrCur = (unsigned long)pv;
+            const size_t    cPages = pMemLnxToMap->Core.cb >> PAGE_SHIFT;
+            size_t          iPage;
+
+            down_write(&pTask->mm->mmap_sem);
+
+            rc = VINF_SUCCESS;
+            if (pMemLnxToMap->cPages)
+            {
+                for (iPage = 0; iPage < cPages; iPage++, ulAddrCur += PAGE_SIZE)
+                {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
+                    RTHCPHYS Phys = page_to_phys(pMemLnxToMap->apPages[iPage]);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) || defined(HAVE_26_STYLE_REMAP_PAGE_RANGE)
+                    struct vm_area_struct *vma = find_vma(pTask->mm, ulAddrCur); /* this is probably the same for all the pages... */
+                    AssertBreakStmt(vma, rc = VERR_INTERNAL_ERROR);
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) && defined(RT_ARCH_X86)
+                    /* remap_page_range() limitation on x86 */
+                    AssertBreakStmt(Phys < _4G, rc = VERR_NO_MEMORY);
+#endif
+
+#if   defined(VBOX_USE_INSERT_PAGE) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
+                    rc = vm_insert_page(vma, ulAddrCur, pMemLnxToMap->apPages[iPage]);
+                    /* Thes flags help making 100% sure some bad stuff wont happen (swap, core, ++).
+                     * See remap_pfn_range() in mm/memory.c */
+#if    LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+                    vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+#else
+                    vma->vm_flags |= VM_RESERVED;
+#endif
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
+                    rc = remap_pfn_range(vma, ulAddrCur, page_to_pfn(pMemLnxToMap->apPages[iPage]), PAGE_SIZE, fPg);
+#elif defined(VBOX_USE_PAE_HACK)
+                    rc = remap_page_range(vma, ulAddrCur, DummyPhys, PAGE_SIZE, fPg);
+                    if (!rc)
+                        rc = rtR0MemObjLinuxFixPte(pTask->mm, ulAddrCur, Phys);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) || defined(HAVE_26_STYLE_REMAP_PAGE_RANGE)
+                    rc = remap_page_range(vma, ulAddrCur, Phys, PAGE_SIZE, fPg);
+#else /* 2.4 */
+                    rc = remap_page_range(ulAddrCur, Phys, PAGE_SIZE, fPg);
+#endif
+                    if (rc)
+                    {
+                        rc = VERR_NO_MEMORY;
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                RTHCPHYS Phys;
+                if (pMemLnxToMap->Core.enmType == RTR0MEMOBJTYPE_PHYS)
+                    Phys = pMemLnxToMap->Core.u.Phys.PhysBase;
+                else if (pMemLnxToMap->Core.enmType == RTR0MEMOBJTYPE_CONT)
+                    Phys = pMemLnxToMap->Core.u.Cont.Phys;
+                else
+                {
+                    AssertMsgFailed(("%d\n", pMemLnxToMap->Core.enmType));
+                    Phys = NIL_RTHCPHYS;
+                }
+                if (Phys != NIL_RTHCPHYS)
+                {
+                    for (iPage = 0; iPage < cPages; iPage++, ulAddrCur += PAGE_SIZE, Phys += PAGE_SIZE)
+                    {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) || defined(HAVE_26_STYLE_REMAP_PAGE_RANGE)
+                        struct vm_area_struct *vma = find_vma(pTask->mm, ulAddrCur); /* this is probably the same for all the pages... */
+                        AssertBreakStmt(vma, rc = VERR_INTERNAL_ERROR);
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) && defined(RT_ARCH_X86)
+                        /* remap_page_range() limitation on x86 */
+                        AssertBreakStmt(Phys < _4G, rc = VERR_NO_MEMORY);
+#endif
+
+#if   LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
+                        rc = remap_pfn_range(vma, ulAddrCur, Phys, PAGE_SIZE, fPg);
+#elif defined(VBOX_USE_PAE_HACK)
+                        rc = remap_page_range(vma, ulAddrCur, DummyPhys, PAGE_SIZE, fPg);
+                        if (!rc)
+                            rc = rtR0MemObjLinuxFixPte(pTask->mm, ulAddrCur, Phys);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) || defined(HAVE_26_STYLE_REMAP_PAGE_RANGE)
+                        rc = remap_page_range(vma, ulAddrCur, Phys, PAGE_SIZE, fPg);
+#else /* 2.4 */
+                        rc = remap_page_range(ulAddrCur, Phys, PAGE_SIZE, fPg);
+#endif
+                        if (rc)
+                        {
+                            rc = VERR_NO_MEMORY;
+                            break;
+                        }
+                    }
+                }
+            }
+
+#ifdef CONFIG_NUMA_BALANCING
+# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+#  ifdef RHEL_RELEASE_CODE
+#   if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7, 0)
+#    define VBOX_NUMA_HACK_OLD
+#   endif
+#  endif
+# endif
+            if (RT_SUCCESS(rc))
+            {
+                /** @todo Ugly hack! But right now we have no other means to
+                 *        disable automatic NUMA page balancing. */
+# ifdef RT_OS_X86
+#  ifdef VBOX_NUMA_HACK_OLD
+                pTask->mm->numa_next_reset = jiffies + 0x7fffffffUL;
+#  endif
+                pTask->mm->numa_next_scan  = jiffies + 0x7fffffffUL;
+# else
+#  ifdef VBOX_NUMA_HACK_OLD
+                pTask->mm->numa_next_reset = jiffies + 0x7fffffffffffffffUL;
+#  endif
+                pTask->mm->numa_next_scan  = jiffies + 0x7fffffffffffffffUL;
+# endif
+            }
+#endif /* CONFIG_NUMA_BALANCING */
+
+            up_write(&pTask->mm->mmap_sem);
+
+            if (RT_SUCCESS(rc))
+            {
+#ifdef VBOX_USE_PAE_HACK
+                __free_page(pDummyPage);
+#endif
+                pMemLnx->Core.pv = pv;
+                pMemLnx->Core.u.Mapping.R0Process = R0Process;
+                *ppMem = &pMemLnx->Core;
+                IPRT_LINUX_RESTORE_EFL_AC();
+                return VINF_SUCCESS;
+            }
+
+            /*
+             * Bail out.
+             */
+            rtR0MemObjLinuxDoMunmap(pv, pMemLnxToMap->Core.cb, pTask);
+        }
+        rtR0MemObjDelete(&pMemLnx->Core);
+    }
+#ifdef VBOX_USE_PAE_HACK
+    __free_page(pDummyPage);
+#endif
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return rc;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt)
+{
+    NOREF(pMem);
+    NOREF(offSub);
+    NOREF(cbSub);
+    NOREF(fProt);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+DECLHIDDEN(RTHCPHYS) rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, size_t iPage)
+{
+    PRTR0MEMOBJLNX  pMemLnx = (PRTR0MEMOBJLNX)pMem;
+
+    if (pMemLnx->cPages)
+        return page_to_phys(pMemLnx->apPages[iPage]);
+
+    switch (pMemLnx->Core.enmType)
+    {
+        case RTR0MEMOBJTYPE_CONT:
+            return pMemLnx->Core.u.Cont.Phys     + (iPage << PAGE_SHIFT);
+
+        case RTR0MEMOBJTYPE_PHYS:
+            return pMemLnx->Core.u.Phys.PhysBase + (iPage << PAGE_SHIFT);
+
+            /* the parent knows */
+        case RTR0MEMOBJTYPE_MAPPING:
+            return rtR0MemObjNativeGetPagePhysAddr(pMemLnx->Core.uRel.Child.pParent, iPage);
+
+            /* cPages > 0 */
+        case RTR0MEMOBJTYPE_LOW:
+        case RTR0MEMOBJTYPE_LOCK:
+        case RTR0MEMOBJTYPE_PHYS_NC:
+        case RTR0MEMOBJTYPE_PAGE:
+        default:
+            AssertMsgFailed(("%d\n", pMemLnx->Core.enmType));
+            /* fall thru */
+
+        case RTR0MEMOBJTYPE_RES_VIRT:
+            return NIL_RTHCPHYS;
+    }
+}
+
diff --git a/ubuntu/vbox/r0drv/linux/memuserkernel-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/memuserkernel-r0drv-linux.c
new file mode 100644 (file)
index 0000000..2115443
--- /dev/null
@@ -0,0 +1,172 @@
+/* $Id: memuserkernel-r0drv-linux.c $ */
+/** @file
+ * IPRT - User & Kernel Memory, Ring-0 Driver, Linux.
+ */
+
+/*
+ * Copyright (C) 2009-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+
+#include <iprt/mem.h>
+#include <iprt/err.h>
+
+
+RTR0DECL(int) RTR0MemUserCopyFrom(void *pvDst, RTR3PTR R3PtrSrc, size_t cb)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    if (RT_LIKELY(copy_from_user(pvDst, (void *)R3PtrSrc, cb) == 0))
+    {
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return VINF_SUCCESS;
+    }
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VERR_ACCESS_DENIED;
+}
+RT_EXPORT_SYMBOL(RTR0MemUserCopyFrom);
+
+
+RTR0DECL(int) RTR0MemUserCopyTo(RTR3PTR R3PtrDst, void const *pvSrc, size_t cb)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    if (RT_LIKELY(copy_to_user((void *)R3PtrDst, pvSrc, cb) == 0))
+    {
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return VINF_SUCCESS;
+    }
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VERR_ACCESS_DENIED;
+}
+RT_EXPORT_SYMBOL(RTR0MemUserCopyTo);
+
+
+RTR0DECL(bool) RTR0MemUserIsValidAddr(RTR3PTR R3Ptr)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    bool fRc = access_ok(VERIFY_READ, (void *)R3Ptr, 1);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return fRc;
+}
+RT_EXPORT_SYMBOL(RTR0MemUserIsValidAddr);
+
+
+RTR0DECL(bool) RTR0MemKernelIsValidAddr(void *pv)
+{
+    /* Couldn't find a straight forward way of doing this... */
+#if defined(RT_ARCH_X86) && defined(CONFIG_X86_HIGH_ENTRY)
+    return true; /* ?? */
+#elif defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
+    return (uintptr_t)pv >= PAGE_OFFSET;
+#else
+# error "PORT ME"
+    return !access_ok(VERIFY_READ, pv, 1);
+#endif
+}
+RT_EXPORT_SYMBOL(RTR0MemKernelIsValidAddr);
+
+
+RTR0DECL(bool) RTR0MemAreKrnlAndUsrDifferent(void)
+{
+#if defined(RT_ARCH_X86) && defined(CONFIG_X86_HIGH_ENTRY) /* ?? */
+    return false;
+#else
+    return true;
+#endif
+}
+RT_EXPORT_SYMBOL(RTR0MemAreKrnlAndUsrDifferent);
+
+
+/**
+ * Treats both source and destination as unsafe buffers.
+ */
+static int rtR0MemKernelCopyLnxWorker(void *pvDst, void const *pvSrc, size_t cb)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 55)
+/* _ASM_EXTABLE was introduced in 2.6.25 from what I can tell. Using #ifndef
+   here since it has to be a macro and you never know what someone might have
+   backported to an earlier kernel release. */
+# ifndef _ASM_EXTABLE
+#  if ARCH_BITS == 32
+#   define _ASM_EXTABLE(a_Instr, a_Resume) \
+    ".section __ex_table,\"a\"\n" \
+    ".balign 4\n" \
+    ".long   " #a_Instr "\n" \
+    ".long   " #a_Resume "\n" \
+    ".previous\n"
+#  else
+#   define _ASM_EXTABLE(a_Instr, a_Resume) \
+    ".section __ex_table,\"a\"\n" \
+    ".balign 8\n" \
+    ".quad   " #a_Instr "\n" \
+    ".quad   " #a_Resume "\n" \
+    ".previous\n"
+#  endif
+# endif /* !_ASM_EXTABLE */
+    int rc;
+    IPRT_LINUX_SAVE_EFL_AC(); /* paranoia */
+    if (!cb)
+        return VINF_SUCCESS;
+
+    __asm__ __volatile__ ("cld\n"
+                          "1:\n\t"
+                          "rep; movsb\n"
+                          "2:\n\t"
+                          ".section .fixup,\"ax\"\n"
+                          "3:\n\t"
+                          "movl %4, %0\n"
+                          ".previous\n"
+                          _ASM_EXTABLE(1b, 3b)
+                          : "=r" (rc),
+                            "=D" (pvDst),
+                            "=S" (pvSrc),
+                            "=c" (cb)
+                          : "i" (VERR_ACCESS_DENIED),
+                            "0" (VINF_SUCCESS),
+                            "1" (pvDst),
+                            "2" (pvSrc),
+                            "3" (cb)
+                          : "memory");
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return rc;
+#else
+    return VERR_NOT_SUPPORTED;
+#endif
+}
+
+
+RTR0DECL(int) RTR0MemKernelCopyFrom(void *pvDst, void const *pvSrc, size_t cb)
+{
+    return rtR0MemKernelCopyLnxWorker(pvDst, pvSrc, cb);
+}
+RT_EXPORT_SYMBOL(RTR0MemKernelCopyFrom);
+
+
+RTR0DECL(int) RTR0MemKernelCopyTo(void *pvDst, void const *pvSrc, size_t cb)
+{
+    return rtR0MemKernelCopyLnxWorker(pvDst, pvSrc, cb);
+}
+RT_EXPORT_SYMBOL(RTR0MemKernelCopyTo);
+
diff --git a/ubuntu/vbox/r0drv/linux/mp-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/mp-r0drv-linux.c
new file mode 100644 (file)
index 0000000..3a7acba
--- /dev/null
@@ -0,0 +1,598 @@
+/* $Id: mp-r0drv-linux.c $ */
+/** @file
+ * IPRT - Multiprocessor, Ring-0 Driver, Linux.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+
+#include <iprt/mp.h>
+#include <iprt/cpuset.h>
+#include <iprt/err.h>
+#include <iprt/asm.h>
+#include <iprt/thread.h>
+#include "r0drv/mp-r0drv.h"
+
+#ifdef nr_cpumask_bits
+# define VBOX_NR_CPUMASK_BITS   nr_cpumask_bits
+#else
+# define VBOX_NR_CPUMASK_BITS   NR_CPUS
+#endif
+
+RTDECL(RTCPUID) RTMpCpuId(void)
+{
+    return smp_processor_id();
+}
+RT_EXPORT_SYMBOL(RTMpCpuId);
+
+
+RTDECL(int) RTMpCurSetIndex(void)
+{
+    return smp_processor_id();
+}
+RT_EXPORT_SYMBOL(RTMpCurSetIndex);
+
+
+RTDECL(int) RTMpCurSetIndexAndId(PRTCPUID pidCpu)
+{
+    return *pidCpu = smp_processor_id();
+}
+RT_EXPORT_SYMBOL(RTMpCurSetIndexAndId);
+
+
+RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
+{
+    return idCpu < RTCPUSET_MAX_CPUS && idCpu < VBOX_NR_CPUMASK_BITS ? (int)idCpu : -1;
+}
+RT_EXPORT_SYMBOL(RTMpCpuIdToSetIndex);
+
+
+RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
+{
+    return iCpu < VBOX_NR_CPUMASK_BITS ? (RTCPUID)iCpu : NIL_RTCPUID;
+}
+RT_EXPORT_SYMBOL(RTMpCpuIdFromSetIndex);
+
+
+RTDECL(RTCPUID) RTMpGetMaxCpuId(void)
+{
+    return VBOX_NR_CPUMASK_BITS - 1; //???
+}
+RT_EXPORT_SYMBOL(RTMpGetMaxCpuId);
+
+
+RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
+{
+#if defined(CONFIG_SMP)
+    if (RT_UNLIKELY(idCpu >= VBOX_NR_CPUMASK_BITS))
+        return false;
+
+# if defined(cpu_possible)
+    return cpu_possible(idCpu);
+# else /* < 2.5.29 */
+    return idCpu < (RTCPUID)smp_num_cpus;
+# endif
+#else
+    return idCpu == RTMpCpuId();
+#endif
+}
+RT_EXPORT_SYMBOL(RTMpIsCpuPossible);
+
+
+RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
+{
+    RTCPUID idCpu;
+
+    RTCpuSetEmpty(pSet);
+    idCpu = RTMpGetMaxCpuId();
+    do
+    {
+        if (RTMpIsCpuPossible(idCpu))
+            RTCpuSetAdd(pSet, idCpu);
+    } while (idCpu-- > 0);
+    return pSet;
+}
+RT_EXPORT_SYMBOL(RTMpGetSet);
+
+
+RTDECL(RTCPUID) RTMpGetCount(void)
+{
+#ifdef CONFIG_SMP
+# if defined(CONFIG_HOTPLUG_CPU) /* introduced & uses cpu_present */
+    return num_present_cpus();
+# elif defined(num_possible_cpus)
+    return num_possible_cpus();
+# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
+    return smp_num_cpus;
+# else
+    RTCPUSET Set;
+    RTMpGetSet(&Set);
+    return RTCpuSetCount(&Set);
+# endif
+#else
+    return 1;
+#endif
+}
+RT_EXPORT_SYMBOL(RTMpGetCount);
+
+
+RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
+{
+#ifdef CONFIG_SMP
+    if (RT_UNLIKELY(idCpu >= VBOX_NR_CPUMASK_BITS))
+        return false;
+# ifdef cpu_online
+    return cpu_online(idCpu);
+# else /* 2.4: */
+    return cpu_online_map & RT_BIT_64(idCpu);
+# endif
+#else
+    return idCpu == RTMpCpuId();
+#endif
+}
+RT_EXPORT_SYMBOL(RTMpIsCpuOnline);
+
+
+RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
+{
+#ifdef CONFIG_SMP
+    RTCPUID idCpu;
+
+    RTCpuSetEmpty(pSet);
+    idCpu = RTMpGetMaxCpuId();
+    do
+    {
+        if (RTMpIsCpuOnline(idCpu))
+            RTCpuSetAdd(pSet, idCpu);
+    } while (idCpu-- > 0);
+#else
+    RTCpuSetEmpty(pSet);
+    RTCpuSetAdd(pSet, RTMpCpuId());
+#endif
+    return pSet;
+}
+RT_EXPORT_SYMBOL(RTMpGetOnlineSet);
+
+
+RTDECL(RTCPUID) RTMpGetOnlineCount(void)
+{
+#ifdef CONFIG_SMP
+# if defined(num_online_cpus)
+    return num_online_cpus();
+# else
+    RTCPUSET Set;
+    RTMpGetOnlineSet(&Set);
+    return RTCpuSetCount(&Set);
+# endif
+#else
+    return 1;
+#endif
+}
+RT_EXPORT_SYMBOL(RTMpGetOnlineCount);
+
+
+RTDECL(bool) RTMpIsCpuWorkPending(void)
+{
+    /** @todo (not used on non-Windows platforms yet). */
+    return false;
+}
+RT_EXPORT_SYMBOL(RTMpIsCpuWorkPending);
+
+
+/**
+ * Wrapper between the native linux per-cpu callbacks and PFNRTWORKER.
+ *
+ * @param   pvInfo      Pointer to the RTMPARGS package.
+ */
+static void rtmpLinuxWrapper(void *pvInfo)
+{
+    PRTMPARGS pArgs = (PRTMPARGS)pvInfo;
+    ASMAtomicIncU32(&pArgs->cHits);
+    pArgs->pfnWorker(RTMpCpuId(), pArgs->pvUser1, pArgs->pvUser2);
+}
+
+
+/**
+ * Wrapper between the native linux per-cpu callbacks and PFNRTWORKER, does hit
+ * increment after calling the worker.
+ *
+ * @param   pvInfo      Pointer to the RTMPARGS package.
+ */
+static void rtmpLinuxWrapperPostInc(void *pvInfo)
+{
+    PRTMPARGS pArgs = (PRTMPARGS)pvInfo;
+    pArgs->pfnWorker(RTMpCpuId(), pArgs->pvUser1, pArgs->pvUser2);
+    ASMAtomicIncU32(&pArgs->cHits);
+}
+
+
+/**
+ * Wrapper between the native linux all-cpu callbacks and PFNRTWORKER.
+ *
+ * @param   pvInfo      Pointer to the RTMPARGS package.
+ */
+static void rtmpLinuxAllWrapper(void *pvInfo)
+{
+    PRTMPARGS  pArgs      = (PRTMPARGS)pvInfo;
+    PRTCPUSET  pWorkerSet = pArgs->pWorkerSet;
+    RTCPUID    idCpu      = RTMpCpuId();
+    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
+
+    if (RTCpuSetIsMember(pWorkerSet, idCpu))
+    {
+        pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
+        RTCpuSetDel(pWorkerSet, idCpu);
+    }
+}
+
+
+RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    int rc;
+    RTMPARGS Args;
+    RTCPUSET OnlineSet;
+    RTCPUID  idCpu;
+    uint32_t cLoops;
+
+    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
+
+    Args.pfnWorker  = pfnWorker;
+    Args.pvUser1    = pvUser1;
+    Args.pvUser2    = pvUser2;
+    Args.idCpu      = NIL_RTCPUID;
+    Args.cHits      = 0;
+
+    RTThreadPreemptDisable(&PreemptState);
+    RTMpGetOnlineSet(&OnlineSet);
+    Args.pWorkerSet = &OnlineSet;
+    idCpu = RTMpCpuId();
+
+    if (RTCpuSetCount(&OnlineSet) > 1)
+    {
+        /* Fire the function on all other CPUs without waiting for completion. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+        rc = smp_call_function(rtmpLinuxAllWrapper, &Args, 0 /* wait */);
+#else
+        rc = smp_call_function(rtmpLinuxAllWrapper, &Args, 0 /* retry */, 0 /* wait */);
+#endif
+        Assert(!rc); NOREF(rc);
+    }
+
+    /* Fire the function on this CPU. */
+    Args.pfnWorker(idCpu, Args.pvUser1, Args.pvUser2);
+    RTCpuSetDel(Args.pWorkerSet, idCpu);
+
+    /* Wait for all of them finish. */
+    cLoops = 64000;
+    while (!RTCpuSetIsEmpty(Args.pWorkerSet))
+    {
+        /* Periodically check if any CPU in the wait set has gone offline, if so update the wait set. */
+        if (!cLoops--)
+        {
+            RTCPUSET OnlineSetNow;
+            RTMpGetOnlineSet(&OnlineSetNow);
+            RTCpuSetAnd(Args.pWorkerSet, &OnlineSetNow);
+
+            cLoops = 64000;
+        }
+
+        ASMNopPause();
+    }
+
+    RTThreadPreemptRestore(&PreemptState);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTMpOnAll);
+
+
+RTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    int rc;
+    RTMPARGS Args;
+
+    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
+    Args.pfnWorker = pfnWorker;
+    Args.pvUser1 = pvUser1;
+    Args.pvUser2 = pvUser2;
+    Args.idCpu = NIL_RTCPUID;
+    Args.cHits = 0;
+
+    RTThreadPreemptDisable(&PreemptState);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+    rc = smp_call_function(rtmpLinuxWrapper, &Args, 1 /* wait */);
+#else /* older kernels */
+    rc = smp_call_function(rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
+#endif /* older kernels */
+    RTThreadPreemptRestore(&PreemptState);
+
+    Assert(rc == 0); NOREF(rc);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTMpOnOthers);
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
+/**
+ * Wrapper between the native linux per-cpu callbacks and PFNRTWORKER
+ * employed by RTMpOnPair on older kernels that lacks smp_call_function_many.
+ *
+ * @param   pvInfo      Pointer to the RTMPARGS package.
+ */
+static void rtMpLinuxOnPairWrapper(void *pvInfo)
+{
+    PRTMPARGS pArgs = (PRTMPARGS)pvInfo;
+    RTCPUID   idCpu = RTMpCpuId();
+
+    if (   idCpu == pArgs->idCpu
+        || idCpu == pArgs->idCpu2)
+    {
+        pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
+        ASMAtomicIncU32(&pArgs->cHits);
+    }
+}
+#endif
+
+
+RTDECL(int) RTMpOnPair(RTCPUID idCpu1, RTCPUID idCpu2, uint32_t fFlags, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    int rc;
+    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
+
+    AssertReturn(idCpu1 != idCpu2, VERR_INVALID_PARAMETER);
+    AssertReturn(!(fFlags & RTMPON_F_VALID_MASK), VERR_INVALID_FLAGS);
+
+    /*
+     * Check that both CPUs are online before doing the broadcast call.
+     */
+    RTThreadPreemptDisable(&PreemptState);
+    if (   RTMpIsCpuOnline(idCpu1)
+        && RTMpIsCpuOnline(idCpu2))
+    {
+        /*
+         * Use the smp_call_function variant taking a cpu mask where available,
+         * falling back on broadcast with filter.  Slight snag if one of the
+         * CPUs is the one we're running on, we must do the call and the post
+         * call wait ourselves.
+         */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+        /* 2.6.28 introduces CONFIG_CPUMASK_OFFSTACK */
+        cpumask_var_t DstCpuMask;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+        cpumask_t   DstCpuMask;
+#endif
+        RTCPUID     idCpuSelf = RTMpCpuId();
+        bool const  fCallSelf = idCpuSelf == idCpu1 || idCpuSelf == idCpu2;
+        RTMPARGS    Args;
+        Args.pfnWorker = pfnWorker;
+        Args.pvUser1 = pvUser1;
+        Args.pvUser2 = pvUser2;
+        Args.idCpu   = idCpu1;
+        Args.idCpu2  = idCpu2;
+        Args.cHits   = 0;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+        if (!zalloc_cpumask_var(&DstCpuMask, GFP_KERNEL))
+            return VERR_NO_MEMORY;
+        cpumask_set_cpu(idCpu1, DstCpuMask);
+        cpumask_set_cpu(idCpu2, DstCpuMask);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+        if (!alloc_cpumask_var(&DstCpuMask, GFP_KERNEL))
+            return VERR_NO_MEMORY;
+        cpumask_clear(DstCpuMask);
+        cpumask_set_cpu(idCpu1, DstCpuMask);
+        cpumask_set_cpu(idCpu2, DstCpuMask);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+        cpus_clear(DstCpuMask);
+        cpu_set(idCpu1, DstCpuMask);
+        cpu_set(idCpu2, DstCpuMask);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+        smp_call_function_many(DstCpuMask, rtmpLinuxWrapperPostInc, &Args, !fCallSelf /* wait */);
+        rc = 0;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+        rc = smp_call_function_mask(DstCpuMask, rtmpLinuxWrapperPostInc, &Args, !fCallSelf /* wait */);
+#else /* older kernels */
+        rc = smp_call_function(rtMpLinuxOnPairWrapper, &Args, 0 /* retry */, !fCallSelf /* wait */);
+#endif /* older kernels */
+        Assert(rc == 0);
+
+        /* Call ourselves if necessary and wait for the other party to be done. */
+        if (fCallSelf)
+        {
+            uint32_t cLoops = 0;
+            rtmpLinuxWrapper(&Args);
+            while (ASMAtomicReadU32(&Args.cHits) < 2)
+            {
+                if ((cLoops & 0x1ff) == 0 && !RTMpIsCpuOnline(idCpuSelf == idCpu1 ? idCpu2 : idCpu1))
+                    break;
+                cLoops++;
+                ASMNopPause();
+            }
+        }
+
+        Assert(Args.cHits <= 2);
+        if (Args.cHits == 2)
+            rc = VINF_SUCCESS;
+        else if (Args.cHits == 1)
+            rc = VERR_NOT_ALL_CPUS_SHOWED;
+        else if (Args.cHits == 0)
+            rc = VERR_CPU_OFFLINE;
+        else
+            rc = VERR_CPU_IPE_1;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+        free_cpumask_var(DstCpuMask);
+#endif
+    }
+    /*
+     * A CPU must be present to be considered just offline.
+     */
+    else if (   RTMpIsCpuPresent(idCpu1)
+             && RTMpIsCpuPresent(idCpu2))
+        rc = VERR_CPU_OFFLINE;
+    else
+        rc = VERR_CPU_NOT_FOUND;
+    RTThreadPreemptRestore(&PreemptState);;
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTMpOnPair);
+
+
+RTDECL(bool) RTMpOnPairIsConcurrentExecSupported(void)
+{
+    return true;
+}
+RT_EXPORT_SYMBOL(RTMpOnPairIsConcurrentExecSupported);
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+/**
+ * Wrapper between the native linux per-cpu callbacks and PFNRTWORKER
+ * employed by RTMpOnSpecific on older kernels that lacks smp_call_function_single.
+ *
+ * @param   pvInfo      Pointer to the RTMPARGS package.
+ */
+static void rtmpOnSpecificLinuxWrapper(void *pvInfo)
+{
+    PRTMPARGS pArgs = (PRTMPARGS)pvInfo;
+    RTCPUID idCpu = RTMpCpuId();
+
+    if (idCpu == pArgs->idCpu)
+    {
+        pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
+        ASMAtomicIncU32(&pArgs->cHits);
+    }
+}
+#endif
+
+
+RTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    int rc;
+    RTMPARGS Args;
+
+    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
+    Args.pfnWorker = pfnWorker;
+    Args.pvUser1 = pvUser1;
+    Args.pvUser2 = pvUser2;
+    Args.idCpu = idCpu;
+    Args.cHits = 0;
+
+    if (!RTMpIsCpuPossible(idCpu))
+        return VERR_CPU_NOT_FOUND;
+
+    RTThreadPreemptDisable(&PreemptState);
+    if (idCpu != RTMpCpuId())
+    {
+        if (RTMpIsCpuOnline(idCpu))
+        {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+            rc = smp_call_function_single(idCpu, rtmpLinuxWrapper, &Args, 1 /* wait */);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+            rc = smp_call_function_single(idCpu, rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
+#else /* older kernels */
+            rc = smp_call_function(rtmpOnSpecificLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
+#endif /* older kernels */
+            Assert(rc == 0);
+            rc = Args.cHits ? VINF_SUCCESS : VERR_CPU_OFFLINE;
+        }
+        else
+            rc = VERR_CPU_OFFLINE;
+    }
+    else
+    {
+        rtmpLinuxWrapper(&Args);
+        rc = VINF_SUCCESS;
+    }
+    RTThreadPreemptRestore(&PreemptState);;
+
+    NOREF(rc);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTMpOnSpecific);
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+/**
+ * Dummy callback used by RTMpPokeCpu.
+ *
+ * @param   pvInfo      Ignored.
+ */
+static void rtmpLinuxPokeCpuCallback(void *pvInfo)
+{
+    NOREF(pvInfo);
+}
+#endif
+
+
+RTDECL(int) RTMpPokeCpu(RTCPUID idCpu)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+    int rc;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    if (!RTMpIsCpuPossible(idCpu))
+        return VERR_CPU_NOT_FOUND;
+    if (!RTMpIsCpuOnline(idCpu))
+        return VERR_CPU_OFFLINE;
+
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+    rc = smp_call_function_single(idCpu, rtmpLinuxPokeCpuCallback, NULL, 0 /* wait */);
+# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+    rc = smp_call_function_single(idCpu, rtmpLinuxPokeCpuCallback, NULL, 0 /* retry */, 0 /* wait */);
+# else  /* older kernels */
+#  error oops
+# endif /* older kernels */
+    NOREF(rc);
+    Assert(rc == 0);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+
+#else  /* older kernels */
+    /* no unicast here? */
+    return VERR_NOT_SUPPORTED;
+#endif /* older kernels */
+}
+RT_EXPORT_SYMBOL(RTMpPokeCpu);
+
+
+RTDECL(bool) RTMpOnAllIsConcurrentSafe(void)
+{
+    return true;
+}
+RT_EXPORT_SYMBOL(RTMpOnAllIsConcurrentSafe);
+
diff --git a/ubuntu/vbox/r0drv/linux/mpnotification-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/mpnotification-r0drv-linux.c
new file mode 100644 (file)
index 0000000..9a3a156
--- /dev/null
@@ -0,0 +1,248 @@
+/* $Id: mpnotification-r0drv-linux.c $ */
+/** @file
+ * IPRT - Multiprocessor Event Notifications, Ring-0 Driver, Linux.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+
+#include <iprt/asm-amd64-x86.h>
+#include <iprt/err.h>
+#include <iprt/cpuset.h>
+#include <iprt/thread.h>
+#include "r0drv/mp-r0drv.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
+
+static enum cpuhp_state g_rtR0MpOnline;
+
+/*
+ * Linux 4.10 completely removed CPU notifiers. So let's switch to CPU hotplug
+ * notification.
+ */
+
+static int rtR0MpNotificationLinuxOnline(unsigned int cpu)
+{
+    RTCPUID idCpu = RTMpCpuIdFromSetIndex(cpu);
+    rtMpNotificationDoCallbacks(RTMPEVENT_ONLINE, idCpu);
+    return 0;
+}
+
+static int rtR0MpNotificationLinuxOffline(unsigned int cpu)
+{
+    RTCPUID idCpu = RTMpCpuIdFromSetIndex(cpu);
+    rtMpNotificationDoCallbacks(RTMPEVENT_OFFLINE, idCpu);
+    return 0;
+}
+
+DECLHIDDEN(int) rtR0MpNotificationNativeInit(void)
+{
+    int rc;
+    IPRT_LINUX_SAVE_EFL_AC();
+    rc = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "vboxdrv:online",
+                                   rtR0MpNotificationLinuxOnline, rtR0MpNotificationLinuxOffline);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    /*
+     * cpuhp_setup_state_nocalls() returns a positive state number for
+     * CPUHP_AP_ONLINE_DYN or -ENOSPC if there is no free slot available
+     * (see cpuhp_reserve_state / definition of CPUHP_AP_ONLINE_DYN).
+     */
+    AssertMsgReturn(rc > 0, ("%d\n", rc), RTErrConvertFromErrno(rc));
+    g_rtR0MpOnline = rc;
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(void) rtR0MpNotificationNativeTerm(void)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    cpuhp_remove_state_nocalls(g_rtR0MpOnline);
+    IPRT_LINUX_RESTORE_EFL_AC();
+}
+
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 71) && defined(CONFIG_SMP)
+
+static int rtMpNotificationLinuxCallback(struct notifier_block *pNotifierBlock, unsigned long ulNativeEvent, void *pvCpu);
+
+/**
+ * The notifier block we use for registering the callback.
+ */
+static struct notifier_block g_NotifierBlock =
+{
+    .notifier_call = rtMpNotificationLinuxCallback,
+    .next = NULL,
+    .priority = 0
+};
+
+# ifdef CPU_DOWN_FAILED
+/**
+ * The set of CPUs we've seen going offline recently.
+ */
+static RTCPUSET g_MpPendingOfflineSet;
+# endif
+
+
+/**
+ * The native callback.
+ *
+ * @returns NOTIFY_DONE.
+ * @param   pNotifierBlock  Pointer to g_NotifierBlock.
+ * @param   ulNativeEvent   The native event.
+ * @param   pvCpu           The cpu id cast into a pointer value.
+ *
+ * @remarks This can fire with preemption enabled and on any CPU.
+ */
+static int rtMpNotificationLinuxCallback(struct notifier_block *pNotifierBlock, unsigned long ulNativeEvent, void *pvCpu)
+{
+    bool fProcessEvent = false;
+    RTCPUID idCpu      = (uintptr_t)pvCpu;
+    NOREF(pNotifierBlock);
+
+    /*
+     * Note that redhat/CentOS ported _some_ of the FROZEN macros
+     * back to their 2.6.18-92.1.10.el5 kernel but actually don't
+     * use them. Thus we have to test for both CPU_TASKS_FROZEN and
+     * the individual event variants.
+     */
+    switch (ulNativeEvent)
+    {
+        /*
+         * Pick up online events or failures to go offline.
+         * Ignore failure events for CPUs we didn't see go offline.
+         */
+# ifdef CPU_DOWN_FAILED
+        case CPU_DOWN_FAILED:
+#  if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_FAILED_FROZEN)
+        case CPU_DOWN_FAILED_FROZEN:
+#  endif
+            if (!RTCpuSetIsMember(&g_MpPendingOfflineSet, idCpu))
+                break;      /* fProcessEvents = false */
+        /* fall thru */
+# endif
+        case CPU_ONLINE:
+# if defined(CPU_TASKS_FROZEN) && defined(CPU_ONLINE_FROZEN)
+        case CPU_ONLINE_FROZEN:
+# endif
+# ifdef CPU_DOWN_FAILED
+            RTCpuSetDel(&g_MpPendingOfflineSet, idCpu);
+# endif
+            fProcessEvent = true;
+            break;
+
+        /*
+         * Pick the earliest possible offline event.
+         * The only important thing here is that we get the event and that
+         * it's exactly one.
+         */
+# ifdef CPU_DOWN_PREPARE
+        case CPU_DOWN_PREPARE:
+#  if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_PREPARE_FROZEN)
+        case CPU_DOWN_PREPARE_FROZEN:
+#  endif
+            fProcessEvent = true;
+# else
+        case CPU_DEAD:
+#  if defined(CPU_TASKS_FROZEN) && defined(CPU_DEAD_FROZEN)
+        case CPU_DEAD_FROZEN:
+#  endif
+            /* Don't process CPU_DEAD notifications. */
+# endif
+# ifdef CPU_DOWN_FAILED
+            RTCpuSetAdd(&g_MpPendingOfflineSet, idCpu);
+# endif
+            break;
+    }
+
+    if (!fProcessEvent)
+        return NOTIFY_DONE;
+
+    switch (ulNativeEvent)
+    {
+# ifdef CPU_DOWN_FAILED
+        case CPU_DOWN_FAILED:
+#  if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_FAILED_FROZEN)
+        case CPU_DOWN_FAILED_FROZEN:
+#  endif
+# endif
+        case CPU_ONLINE:
+# if defined(CPU_TASKS_FROZEN) && defined(CPU_ONLINE_FROZEN)
+        case CPU_ONLINE_FROZEN:
+# endif
+            rtMpNotificationDoCallbacks(RTMPEVENT_ONLINE, idCpu);
+            break;
+
+# ifdef CPU_DOWN_PREPARE
+        case CPU_DOWN_PREPARE:
+#  if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_PREPARE_FROZEN)
+        case CPU_DOWN_PREPARE_FROZEN:
+#  endif
+            rtMpNotificationDoCallbacks(RTMPEVENT_OFFLINE, idCpu);
+            break;
+# endif
+    }
+
+    return NOTIFY_DONE;
+}
+
+
+DECLHIDDEN(int) rtR0MpNotificationNativeInit(void)
+{
+    int rc;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+# ifdef CPU_DOWN_FAILED
+    RTCpuSetEmpty(&g_MpPendingOfflineSet);
+# endif
+
+    rc = register_cpu_notifier(&g_NotifierBlock);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    AssertMsgReturn(!rc, ("%d\n", rc), RTErrConvertFromErrno(rc));
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(void) rtR0MpNotificationNativeTerm(void)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    unregister_cpu_notifier(&g_NotifierBlock);
+    IPRT_LINUX_RESTORE_EFL_AC();
+}
+
+#else   /* Not supported / Not needed */
+
+DECLHIDDEN(int) rtR0MpNotificationNativeInit(void)
+{
+    return VINF_SUCCESS;
+}
+
+DECLHIDDEN(void) rtR0MpNotificationNativeTerm(void)
+{
+}
+
+#endif  /* Not supported / Not needed */
+
diff --git a/ubuntu/vbox/r0drv/linux/process-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/process-r0drv-linux.c
new file mode 100644 (file)
index 0000000..f264c1e
--- /dev/null
@@ -0,0 +1,49 @@
+/* $Id: process-r0drv-linux.c $ */
+/** @file
+ * IPRT - Process, Ring-0 Driver, Linux.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+
+#include <iprt/process.h>
+
+
+RTDECL(RTPROCESS) RTProcSelf(void)
+{
+    return (RTPROCESS)current->tgid;
+}
+RT_EXPORT_SYMBOL(RTProcSelf);
+
+
+RTR0DECL(RTR0PROCESS) RTR0ProcHandleSelf(void)
+{
+    return (RTR0PROCESS)current->tgid;
+}
+RT_EXPORT_SYMBOL(RTR0ProcHandleSelf);
+
diff --git a/ubuntu/vbox/r0drv/linux/semevent-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/semevent-r0drv-linux.c
new file mode 100644 (file)
index 0000000..650aa4f
--- /dev/null
@@ -0,0 +1,279 @@
+/* $Id: semevent-r0drv-linux.c $ */
+/** @file
+ * IPRT - Single Release Event Semaphores, Ring-0 Driver, Linux.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define RTSEMEVENT_WITHOUT_REMAPPING
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/semaphore.h>
+
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/lockvalidator.h>
+#include <iprt/mem.h>
+
+#include "waitqueue-r0drv-linux.h"
+#include "internal/magics.h"
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * Linux event semaphore.
+ */
+typedef struct RTSEMEVENTINTERNAL
+{
+    /** Magic value (RTSEMEVENT_MAGIC). */
+    uint32_t volatile   u32Magic;
+    /** The object status - !0 when signaled and 0 when reset. */
+    uint32_t volatile   fState;
+    /** Reference counter. */
+    uint32_t volatile   cRefs;
+    /** The wait queue. */
+    wait_queue_head_t   Head;
+} RTSEMEVENTINTERNAL, *PRTSEMEVENTINTERNAL;
+
+
+
+RTDECL(int)  RTSemEventCreate(PRTSEMEVENT phEventSem)
+{
+    return RTSemEventCreateEx(phEventSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
+}
+
+
+RTDECL(int)  RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...)
+{
+    PRTSEMEVENTINTERNAL pThis;
+    IPRT_LINUX_SAVE_EFL_AC();
+    RT_NOREF_PV(hClass); RT_NOREF_PV(pszNameFmt);
+
+    AssertReturn(!(fFlags & ~(RTSEMEVENT_FLAGS_NO_LOCK_VAL | RTSEMEVENT_FLAGS_BOOTSTRAP_HACK)), VERR_INVALID_PARAMETER);
+    Assert(!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK) || (fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL));
+
+    pThis = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pThis));
+    if (!pThis)
+        return VERR_NO_MEMORY;
+
+    pThis->u32Magic = RTSEMEVENT_MAGIC;
+    pThis->fState   = 0;
+    pThis->cRefs    = 1;
+    init_waitqueue_head(&pThis->Head);
+
+    *phEventSem = pThis;
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSemEventCreate);
+
+
+/**
+ * Retains a reference to the event semaphore.
+ *
+ * @param   pThis       The event semaphore.
+ */
+DECLINLINE(void) rtR0SemEventLnxRetain(PRTSEMEVENTINTERNAL pThis)
+{
+    uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
+    Assert(cRefs < 100000); NOREF(cRefs);
+}
+
+
+/**
+ * Releases a reference to the event semaphore.
+ *
+ * @param   pThis       The event semaphore.
+ */
+DECLINLINE(void) rtR0SemEventLnxRelease(PRTSEMEVENTINTERNAL pThis)
+{
+    if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
+        RTMemFree(pThis);
+}
+
+
+RTDECL(int)  RTSemEventDestroy(RTSEMEVENT hEventSem)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * Validate input.
+     */
+    PRTSEMEVENTINTERNAL pThis = hEventSem;
+    if (pThis == NIL_RTSEMEVENT)
+        return VINF_SUCCESS;
+    AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
+    Assert(pThis->cRefs > 0);
+
+    /*
+     * Invalidate it and signal the object just in case.
+     */
+    ASMAtomicWriteU32(&pThis->u32Magic, ~RTSEMEVENT_MAGIC);
+    ASMAtomicWriteU32(&pThis->fState, 0);
+    Assert(!waitqueue_active(&pThis->Head));
+    wake_up_all(&pThis->Head);
+    rtR0SemEventLnxRelease(pThis);
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSemEventDestroy);
+
+
+RTDECL(int)  RTSemEventSignal(RTSEMEVENT hEventSem)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * Validate input.
+     */
+    PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
+    rtR0SemEventLnxRetain(pThis);
+
+    /*
+     * Signal the event object.
+     */
+    ASMAtomicWriteU32(&pThis->fState, 1);
+    wake_up(&pThis->Head);
+
+    rtR0SemEventLnxRelease(pThis);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSemEventSignal);
+
+
+/**
+ * Worker for RTSemEventWaitEx and RTSemEventWaitExDebug.
+ *
+ * @returns VBox status code.
+ * @param   pThis           The event semaphore.
+ * @param   fFlags          See RTSemEventWaitEx.
+ * @param   uTimeout        See RTSemEventWaitEx.
+ * @param   pSrcPos         The source code position of the wait.
+ */
+static int rtR0SemEventLnxWait(PRTSEMEVENTINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
+                               PCRTLOCKVALSRCPOS pSrcPos)
+{
+    int rc;
+    RT_NOREF_PV(pSrcPos);
+
+    /*
+     * Validate the input.
+     */
+    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
+    AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
+    AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
+    rtR0SemEventLnxRetain(pThis);
+
+    /*
+     * Try grab the event without setting up the wait.
+     */
+    if (   1 /** @todo check if there are someone waiting already - waitqueue_active, but then what do we do below? */
+        && ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
+        rc = VINF_SUCCESS;
+    else
+    {
+        /*
+         * We have to wait.
+         */
+        IPRT_LINUX_SAVE_EFL_AC();
+        RTR0SEMLNXWAIT Wait;
+        rc = rtR0SemLnxWaitInit(&Wait, fFlags, uTimeout, &pThis->Head);
+        if (RT_SUCCESS(rc))
+        {
+            IPRT_DEBUG_SEMS_STATE(pThis, 'E');
+            for (;;)
+            {
+                /* The destruction test. */
+                if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC))
+                    rc = VERR_SEM_DESTROYED;
+                else
+                {
+                    rtR0SemLnxWaitPrepare(&Wait);
+
+                    /* Check the exit conditions. */
+                    if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC))
+                        rc = VERR_SEM_DESTROYED;
+                    else if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
+                        rc = VINF_SUCCESS;
+                    else if (rtR0SemLnxWaitHasTimedOut(&Wait))
+                        rc = VERR_TIMEOUT;
+                    else if (rtR0SemLnxWaitWasInterrupted(&Wait))
+                        rc = VERR_INTERRUPTED;
+                    else
+                    {
+                        /* Do the wait and then recheck the conditions. */
+                        rtR0SemLnxWaitDoIt(&Wait);
+                        continue;
+                    }
+                }
+                break;
+            }
+
+            rtR0SemLnxWaitDelete(&Wait);
+            IPRT_DEBUG_SEMS_STATE_RC(pThis, 'E', rc);
+        }
+        IPRT_LINUX_RESTORE_EFL_AC();
+    }
+
+    rtR0SemEventLnxRelease(pThis);
+    return rc;
+}
+
+
+RTDECL(int)  RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout)
+{
+#ifndef RTSEMEVENT_STRICT
+    return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, NULL);
+#else
+    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
+    return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, &SrcPos);
+#endif
+}
+RT_EXPORT_SYMBOL(RTSemEventWaitEx);
+
+
+RTDECL(int)  RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout,
+                                   RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
+    return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, &SrcPos);
+}
+RT_EXPORT_SYMBOL(RTSemEventWaitExDebug);
+
+
+RTDECL(uint32_t) RTSemEventGetResolution(void)
+{
+    return rtR0SemLnxWaitGetResolution();
+}
+RT_EXPORT_SYMBOL(RTSemEventGetResolution);
+
diff --git a/ubuntu/vbox/r0drv/linux/semeventmulti-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/semeventmulti-r0drv-linux.c
new file mode 100644 (file)
index 0000000..b108c9c
--- /dev/null
@@ -0,0 +1,344 @@
+/* $Id: semeventmulti-r0drv-linux.c $ */
+/** @file
+ * IPRT - Multiple Release Event Semaphores, Ring-0 Driver, Linux.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define RTSEMEVENTMULTI_WITHOUT_REMAPPING
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/semaphore.h>
+
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+#include <iprt/err.h>
+#include <iprt/mem.h>
+#include <iprt/lockvalidator.h>
+
+#include "waitqueue-r0drv-linux.h"
+#include "internal/magics.h"
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+/** @name fStateAndGen values
+ * @{ */
+/** The state bit number. */
+#define RTSEMEVENTMULTILNX_STATE_BIT        0
+/** The state mask. */
+#define RTSEMEVENTMULTILNX_STATE_MASK       RT_BIT_32(RTSEMEVENTMULTILNX_STATE_BIT)
+/** The generation mask. */
+#define RTSEMEVENTMULTILNX_GEN_MASK         ~RTSEMEVENTMULTILNX_STATE_MASK
+/** The generation shift. */
+#define RTSEMEVENTMULTILNX_GEN_SHIFT        1
+/** The initial variable value. */
+#define RTSEMEVENTMULTILNX_STATE_GEN_INIT   UINT32_C(0xfffffffc)
+/** @}  */
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * Linux event semaphore.
+ */
+typedef struct RTSEMEVENTMULTIINTERNAL
+{
+    /** Magic value (RTSEMEVENTMULTI_MAGIC). */
+    uint32_t volatile   u32Magic;
+    /** The object state bit and generation counter.
+     * The generation counter is incremented every time the object is
+     * signalled. */
+    uint32_t volatile   fStateAndGen;
+    /** Reference counter. */
+    uint32_t volatile   cRefs;
+    /** The wait queue. */
+    wait_queue_head_t   Head;
+} RTSEMEVENTMULTIINTERNAL, *PRTSEMEVENTMULTIINTERNAL;
+
+
+
+
+
+RTDECL(int)  RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem)
+{
+    return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
+}
+
+
+RTDECL(int)  RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
+                                     const char *pszNameFmt, ...)
+{
+    PRTSEMEVENTMULTIINTERNAL pThis;
+    IPRT_LINUX_SAVE_EFL_AC();
+    RT_NOREF_PV(hClass); RT_NOREF_PV(pszNameFmt);
+
+    AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
+    pThis = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pThis));
+    if (pThis)
+    {
+        pThis->u32Magic     = RTSEMEVENTMULTI_MAGIC;
+        pThis->fStateAndGen = RTSEMEVENTMULTILNX_STATE_GEN_INIT;
+        pThis->cRefs        = 1;
+        init_waitqueue_head(&pThis->Head);
+
+        *phEventMultiSem = pThis;
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return VINF_SUCCESS;
+    }
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VERR_NO_MEMORY;
+}
+RT_EXPORT_SYMBOL(RTSemEventMultiCreate);
+
+
+/**
+ * Retain a reference to the semaphore.
+ *
+ * @param   pThis       The semaphore.
+ */
+DECLINLINE(void) rtR0SemEventMultiLnxRetain(PRTSEMEVENTMULTIINTERNAL pThis)
+{
+    uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
+    NOREF(cRefs);
+    Assert(cRefs && cRefs < 100000);
+}
+
+
+/**
+ * Release a reference, destroy the thing if necessary.
+ *
+ * @param   pThis       The semaphore.
+ */
+DECLINLINE(void) rtR0SemEventMultiLnxRelease(PRTSEMEVENTMULTIINTERNAL pThis)
+{
+    if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
+    {
+        Assert(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC);
+        RTMemFree(pThis);
+    }
+}
+
+
+RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * Validate input.
+     */
+    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
+    if (pThis == NIL_RTSEMEVENTMULTI)
+        return VINF_SUCCESS;
+    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
+    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
+    Assert(pThis->cRefs > 0);
+
+    /*
+     * Invalidate it and signal the object just in case.
+     */
+    ASMAtomicWriteU32(&pThis->u32Magic, ~RTSEMEVENTMULTI_MAGIC);
+    ASMAtomicAndU32(&pThis->fStateAndGen, RTSEMEVENTMULTILNX_GEN_MASK);
+    Assert(!waitqueue_active(&pThis->Head));
+    wake_up_all(&pThis->Head);
+    rtR0SemEventMultiLnxRelease(pThis);
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSemEventMultiDestroy);
+
+
+RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    uint32_t fNew;
+    uint32_t fOld;
+
+    /*
+     * Validate input.
+     */
+    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
+    if (!pThis)
+        return VERR_INVALID_PARAMETER;
+    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
+    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
+    rtR0SemEventMultiLnxRetain(pThis);
+
+    /*
+     * Signal the event object.  The cause of the paranoia here is racing to try
+     * deal with racing RTSemEventMultiSignal calls (should probably be
+     * forbidden, but it's relatively easy to handle).
+     */
+    do
+    {
+        fNew = fOld = ASMAtomicUoReadU32(&pThis->fStateAndGen);
+        fNew += 1 << RTSEMEVENTMULTILNX_GEN_SHIFT;
+        fNew |= RTSEMEVENTMULTILNX_STATE_MASK;
+    }
+    while (!ASMAtomicCmpXchgU32(&pThis->fStateAndGen, fNew, fOld));
+
+    wake_up_all(&pThis->Head);
+
+    rtR0SemEventMultiLnxRelease(pThis);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSemEventMultiSignal);
+
+
+RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
+{
+    /*
+     * Validate input.
+     */
+    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
+    if (!pThis)
+        return VERR_INVALID_PARAMETER;
+    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
+    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
+    rtR0SemEventMultiLnxRetain(pThis);
+
+    /*
+     * Reset it.
+     */
+    ASMAtomicAndU32(&pThis->fStateAndGen, ~RTSEMEVENTMULTILNX_STATE_MASK);
+
+    rtR0SemEventMultiLnxRelease(pThis);
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSemEventMultiReset);
+
+
+/**
+ * Worker for RTSemEventMultiWaitEx and RTSemEventMultiWaitExDebug.
+ *
+ * @returns VBox status code.
+ * @param   pThis           The event semaphore.
+ * @param   fFlags          See RTSemEventMultiWaitEx.
+ * @param   uTimeout        See RTSemEventMultiWaitEx.
+ * @param   pSrcPos         The source code position of the wait.
+ */
+static int rtR0SemEventMultiLnxWait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
+                                    PCRTLOCKVALSRCPOS pSrcPos)
+{
+    uint32_t    fOrgStateAndGen;
+    int         rc;
+    RT_NOREF_PV(pSrcPos);
+
+    /*
+     * Validate the input.
+     */
+    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
+    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
+    AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
+    rtR0SemEventMultiLnxRetain(pThis);
+
+    /*
+     * Is the event already signalled or do we have to wait?
+     */
+    fOrgStateAndGen = ASMAtomicUoReadU32(&pThis->fStateAndGen);
+    if (fOrgStateAndGen & RTSEMEVENTMULTILNX_STATE_MASK)
+        rc = VINF_SUCCESS;
+    else
+    {
+        /*
+         * We have to wait.
+         */
+        RTR0SEMLNXWAIT Wait;
+        IPRT_LINUX_SAVE_EFL_AC();
+        rc = rtR0SemLnxWaitInit(&Wait, fFlags, uTimeout, &pThis->Head);
+        if (RT_SUCCESS(rc))
+        {
+            IPRT_DEBUG_SEMS_STATE(pThis, 'E');
+            for (;;)
+            {
+                /* The destruction test. */
+                if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
+                    rc = VERR_SEM_DESTROYED;
+                else
+                {
+                    rtR0SemLnxWaitPrepare(&Wait);
+
+                    /* Check the exit conditions. */
+                    if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
+                        rc = VERR_SEM_DESTROYED;
+                    else if (ASMAtomicUoReadU32(&pThis->fStateAndGen) != fOrgStateAndGen)
+                        rc = VINF_SUCCESS;
+                    else if (rtR0SemLnxWaitHasTimedOut(&Wait))
+                        rc = VERR_TIMEOUT;
+                    else if (rtR0SemLnxWaitWasInterrupted(&Wait))
+                        rc = VERR_INTERRUPTED;
+                    else
+                    {
+                        /* Do the wait and then recheck the conditions. */
+                        rtR0SemLnxWaitDoIt(&Wait);
+                        continue;
+                    }
+                }
+                break;
+            }
+
+            rtR0SemLnxWaitDelete(&Wait);
+            IPRT_DEBUG_SEMS_STATE_RC(pThis, 'E', rc);
+        }
+        IPRT_LINUX_RESTORE_EFL_AC();
+    }
+
+    rtR0SemEventMultiLnxRelease(pThis);
+    return rc;
+}
+
+
+RTDECL(int)  RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout)
+{
+#ifndef RTSEMEVENT_STRICT
+    return rtR0SemEventMultiLnxWait(hEventMultiSem, fFlags, uTimeout, NULL);
+#else
+    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
+    return rtR0SemEventMultiLnxWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
+#endif
+}
+RT_EXPORT_SYMBOL(RTSemEventMultiWaitEx);
+
+
+RTDECL(int)  RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
+                                        RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
+    return rtR0SemEventMultiLnxWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
+}
+RT_EXPORT_SYMBOL(RTSemEventMultiWaitExDebug);
+
+
+RTDECL(uint32_t) RTSemEventMultiGetResolution(void)
+{
+    return rtR0SemLnxWaitGetResolution();
+}
+RT_EXPORT_SYMBOL(RTSemEventMultiGetResolution);
+
diff --git a/ubuntu/vbox/r0drv/linux/semfastmutex-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/semfastmutex-r0drv-linux.c
new file mode 100644 (file)
index 0000000..534a434
--- /dev/null
@@ -0,0 +1,157 @@
+/* $Id: semfastmutex-r0drv-linux.c $ */
+/** @file
+ * IPRT - Fast Mutex Semaphores, Ring-0 Driver, Linux.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/semaphore.h>
+#include <iprt/alloc.h>
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+#include <iprt/err.h>
+#if defined(RT_STRICT) || defined(IPRT_DEBUG_SEMS)
+# include <iprt/thread.h>
+#endif
+
+#include "internal/magics.h"
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * Wrapper for the linux semaphore structure.
+ */
+typedef struct RTSEMFASTMUTEXINTERNAL
+{
+    /** Magic value (RTSEMFASTMUTEX_MAGIC). */
+    uint32_t            u32Magic;
+    /** the linux semaphore. */
+    struct semaphore    Semaphore;
+#if defined(RT_STRICT) || defined(IPRT_DEBUG_SEMS)
+    /** For check. */
+    RTNATIVETHREAD volatile Owner;
+#endif
+} RTSEMFASTMUTEXINTERNAL, *PRTSEMFASTMUTEXINTERNAL;
+
+
+RTDECL(int)  RTSemFastMutexCreate(PRTSEMFASTMUTEX phFastMtx)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * Allocate.
+     */
+    PRTSEMFASTMUTEXINTERNAL pThis;
+    pThis = (PRTSEMFASTMUTEXINTERNAL)RTMemAlloc(sizeof(*pThis));
+    if (!pThis)
+        return VERR_NO_MEMORY;
+
+    /*
+     * Initialize.
+     */
+    pThis->u32Magic = RTSEMFASTMUTEX_MAGIC;
+    sema_init(&pThis->Semaphore, 1);
+#if defined(RT_STRICT) || defined(IPRT_DEBUG_SEMS)
+    pThis->Owner = NIL_RTNATIVETHREAD;
+#endif
+
+    *phFastMtx = pThis;
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSemFastMutexCreate);
+
+
+RTDECL(int)  RTSemFastMutexDestroy(RTSEMFASTMUTEX hFastMtx)
+{
+    /*
+     * Validate.
+     */
+    PRTSEMFASTMUTEXINTERNAL pThis = hFastMtx;
+    if (pThis == NIL_RTSEMFASTMUTEX)
+        return VINF_SUCCESS;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertMsgReturn(pThis->u32Magic == RTSEMFASTMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
+
+    ASMAtomicWriteU32(&pThis->u32Magic, RTSEMFASTMUTEX_MAGIC_DEAD);
+    RTMemFree(pThis);
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSemFastMutexDestroy);
+
+
+RTDECL(int)  RTSemFastMutexRequest(RTSEMFASTMUTEX hFastMtx)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * Validate.
+     */
+    PRTSEMFASTMUTEXINTERNAL pThis = hFastMtx;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertMsgReturn(pThis->u32Magic == RTSEMFASTMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
+
+    IPRT_DEBUG_SEMS_STATE(pThis, 'd');
+    down(&pThis->Semaphore);
+#if defined(RT_STRICT) || defined(IPRT_DEBUG_SEMS)
+    IPRT_DEBUG_SEMS_STATE(pThis, 'o');
+    AssertRelease(pThis->Owner == NIL_RTNATIVETHREAD);
+    ASMAtomicUoWriteSize(&pThis->Owner, RTThreadNativeSelf());
+#endif
+
+    IPRT_LINUX_RESTORE_EFL_ONLY_AC();
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSemFastMutexRequest);
+
+
+RTDECL(int)  RTSemFastMutexRelease(RTSEMFASTMUTEX hFastMtx)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * Validate.
+     */
+    PRTSEMFASTMUTEXINTERNAL pThis = hFastMtx;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertMsgReturn(pThis->u32Magic == RTSEMFASTMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
+
+#if defined(RT_STRICT) || defined(IPRT_DEBUG_SEMS)
+    AssertRelease(pThis->Owner == RTThreadNativeSelf());
+    ASMAtomicUoWriteSize(&pThis->Owner, NIL_RTNATIVETHREAD);
+#endif
+    up(&pThis->Semaphore);
+    IPRT_DEBUG_SEMS_STATE(pThis, 'u');
+
+    IPRT_LINUX_RESTORE_EFL_ONLY_AC();
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSemFastMutexRelease);
+
diff --git a/ubuntu/vbox/r0drv/linux/semmutex-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/semmutex-r0drv-linux.c
new file mode 100644 (file)
index 0000000..8202c1a
--- /dev/null
@@ -0,0 +1,421 @@
+/* $Id: semmutex-r0drv-linux.c $ */
+/** @file
+ * IPRT - Mutex Semaphores, Ring-0 Driver, Linux.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define RTSEMMUTEX_WITHOUT_REMAPPING
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/semaphore.h>
+
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+#include <iprt/mem.h>
+#include <iprt/err.h>
+#include <iprt/list.h>
+
+#include "internal/magics.h"
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+typedef struct RTSEMMUTEXLNXWAITER
+{
+    /** The list entry. */
+    RTLISTNODE                  ListEntry;
+    /** The waiting task. */
+    struct task_struct         *pTask;
+    /** Why did we wake up? */
+    enum
+    {
+        /** Wakeup to take the semaphore. */
+        RTSEMMUTEXLNXWAITER_WAKEUP,
+        /** Mutex is being destroyed. */
+        RTSEMMUTEXLNXWAITER_DESTROYED,
+        /** Some other reason. */
+        RTSEMMUTEXLNXWAITER_OTHER
+    } volatile                  enmReason;
+} RTSEMMUTEXLNXWAITER, *PRTSEMMUTEXLNXWAITER;
+
+/**
+ * Wrapper for the linux semaphore structure.
+ */
+typedef struct RTSEMMUTEXINTERNAL
+{
+    /** Magic value (RTSEMMUTEX_MAGIC). */
+    uint32_t                    u32Magic;
+    /** The number of recursions. */
+    uint32_t                    cRecursions;
+    /** The list of waiting threads. */
+    RTLISTANCHOR                WaiterList;
+    /** The current owner, NULL if none. */
+    struct task_struct         *pOwnerTask;
+    /** The number of references to this piece of memory.  This is used to
+     *  prevent it from being kicked from underneath us while waiting. */
+    uint32_t volatile           cRefs;
+    /** The spinlock protecting the members and falling asleep. */
+    spinlock_t                  Spinlock;
+} RTSEMMUTEXINTERNAL, *PRTSEMMUTEXINTERNAL;
+
+
+RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX phMtx)
+{
+    int rc = VINF_SUCCESS;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * Allocate.
+     */
+    PRTSEMMUTEXINTERNAL pThis;
+    pThis = (PRTSEMMUTEXINTERNAL)RTMemAlloc(sizeof(*pThis));
+    if (pThis)
+    {
+        /*
+         * Initialize.
+         */
+        pThis->u32Magic     = RTSEMMUTEX_MAGIC;
+        pThis->cRecursions  = 0;
+        pThis->pOwnerTask   = NULL;
+        pThis->cRefs        = 1;
+        RTListInit(&pThis->WaiterList);
+        spin_lock_init(&pThis->Spinlock);
+
+        *phMtx = pThis;
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTSemMutexCreate);
+
+
+RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX hMtx)
+{
+    PRTSEMMUTEXINTERNAL     pThis = hMtx;
+    PRTSEMMUTEXLNXWAITER    pCur;
+    unsigned long           fSavedIrq;
+
+    /*
+     * Validate.
+     */
+    if (pThis == NIL_RTSEMMUTEX)
+        return VINF_SUCCESS;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
+
+    /*
+     * Kill it, kick waiters and release it.
+     */
+    AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, RTSEMMUTEX_MAGIC_DEAD, RTSEMMUTEX_MAGIC), VERR_INVALID_HANDLE);
+
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    spin_lock_irqsave(&pThis->Spinlock, fSavedIrq);
+    RTListForEach(&pThis->WaiterList, pCur, RTSEMMUTEXLNXWAITER, ListEntry)
+    {
+        pCur->enmReason = RTSEMMUTEXLNXWAITER_DESTROYED;
+        wake_up_process(pCur->pTask);
+    }
+
+    if (ASMAtomicDecU32(&pThis->cRefs) != 0)
+        spin_unlock_irqrestore(&pThis->Spinlock, fSavedIrq);
+    else
+    {
+        spin_unlock_irqrestore(&pThis->Spinlock, fSavedIrq);
+        RTMemFree(pThis);
+    }
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSemMutexDestroy);
+
+
+/**
+ * Worker for rtSemMutexLinuxRequest that handles the case where we go to sleep.
+ *
+ * @returns VINF_SUCCESS, VERR_INTERRUPTED, VERR_TIMEOUT or VERR_SEM_DESTROYED.
+ *          Returns without owning the spinlock.
+ * @param   pThis           The mutex instance.
+ * @param   cMillies        The timeout.
+ * @param   fInterruptible  The wait type.
+ * @param   fSavedIrq       The saved IRQ flags.
+ */
+static int rtSemMutexLinuxRequestSleep(PRTSEMMUTEXINTERNAL pThis, RTMSINTERVAL cMillies,
+                                       bool fInterruptible, unsigned long fSavedIrq)
+{
+    struct task_struct *pSelf    = current;
+    int                 rc       = VERR_TIMEOUT;
+    long                lTimeout = cMillies == RT_INDEFINITE_WAIT ? MAX_SCHEDULE_TIMEOUT : msecs_to_jiffies(cMillies);
+    RTSEMMUTEXLNXWAITER Waiter;
+
+    IPRT_DEBUG_SEMS_STATE(pThis, 'm');
+
+    /*
+     * Grab a reference to the mutex and add ourselves to the waiter list.
+     */
+    ASMAtomicIncU32(&pThis->cRefs);
+
+    Waiter.pTask     = pSelf;
+    Waiter.enmReason = RTSEMMUTEXLNXWAITER_OTHER;
+    RTListAppend(&pThis->WaiterList, &Waiter.ListEntry);
+
+    /*
+     * Do the waiting.
+     */
+    for (;;)
+    {
+        /* Check signal and timeout conditions. */
+        if (    fInterruptible
+            &&  signal_pending(pSelf))
+        {
+            rc = VERR_INTERRUPTED;
+            break;
+        }
+
+        if (!lTimeout)
+            break;
+
+        /* Go to sleep. */
+        set_current_state(fInterruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+        spin_unlock_irq(&pThis->Spinlock);
+
+        lTimeout = schedule_timeout(lTimeout);
+
+        spin_lock_irq(&pThis->Spinlock);
+        set_current_state(TASK_RUNNING);
+
+        /* Did someone wake us up? */
+        if (Waiter.enmReason == RTSEMMUTEXLNXWAITER_WAKEUP)
+        {
+            Assert(pThis->cRecursions == 0);
+            pThis->cRecursions = 1;
+            pThis->pOwnerTask  = pSelf;
+            rc = VINF_SUCCESS;
+            break;
+        }
+
+        /* Is the mutex being destroyed? */
+        if (RT_UNLIKELY(   Waiter.enmReason == RTSEMMUTEXLNXWAITER_DESTROYED
+                        || pThis->u32Magic != RTSEMMUTEX_MAGIC))
+        {
+            rc = VERR_SEM_DESTROYED;
+            break;
+        }
+    }
+
+    /*
+     * Unlink ourself from the waiter list, dereference the mutex and exit the
+     * lock.  We might have to free the mutex if it was the destroyed.
+     */
+    RTListNodeRemove(&Waiter.ListEntry);
+    IPRT_DEBUG_SEMS_STATE_RC(pThis, 'M', rc);
+
+    if (RT_LIKELY(ASMAtomicDecU32(&pThis->cRefs) != 0))
+        spin_unlock_irqrestore(&pThis->Spinlock, fSavedIrq);
+    else
+    {
+        Assert(RT_FAILURE_NP(rc));
+        spin_unlock_irqrestore(&pThis->Spinlock, fSavedIrq);
+        RTMemFree(pThis);
+    }
+    return rc;
+}
+
+
+/**
+ * Internal worker.
+ */
+DECLINLINE(int) rtSemMutexLinuxRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, bool fInterruptible)
+{
+    PRTSEMMUTEXINTERNAL pThis = hMutexSem;
+    struct task_struct *pSelf = current;
+    unsigned long       fSavedIrq;
+    int                 rc;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * Validate.
+     */
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
+    Assert(pThis->cRefs >= 1);
+
+    /*
+     * Lock it and check if it's a recursion.
+     */
+    spin_lock_irqsave(&pThis->Spinlock, fSavedIrq);
+    if (pThis->pOwnerTask == pSelf)
+    {
+        pThis->cRecursions++;
+        Assert(pThis->cRecursions > 1);
+        Assert(pThis->cRecursions < 256);
+        rc = VINF_SUCCESS;
+    }
+    /*
+     * Not a recursion, maybe it's not owned by anyone then?
+     */
+    else if (   pThis->pOwnerTask == NULL
+             && RTListIsEmpty(&pThis->WaiterList))
+    {
+        Assert(pThis->cRecursions == 0);
+        pThis->cRecursions = 1;
+        pThis->pOwnerTask  = pSelf;
+        rc = VINF_SUCCESS;
+    }
+    /*
+     * Was it a polling call?
+     */
+    else if (cMillies == 0)
+        rc = VERR_TIMEOUT;
+    /*
+     * No, so go to sleep.
+     */
+    else
+    {
+        rc = rtSemMutexLinuxRequestSleep(pThis, cMillies, fInterruptible, fSavedIrq);
+        IPRT_LINUX_RESTORE_EFL_ONLY_AC();
+        return rc;
+    }
+
+    IPRT_DEBUG_SEMS_STATE_RC(pThis, 'M', rc);
+    spin_unlock_irqrestore(&pThis->Spinlock, fSavedIrq);
+    IPRT_LINUX_RESTORE_EFL_ONLY_AC();
+    return rc;
+}
+
+
+RTDECL(int) RTSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
+{
+    return rtSemMutexLinuxRequest(hMutexSem, cMillies, false /*fInterruptible*/);
+}
+RT_EXPORT_SYMBOL(RTSemMutexRequest);
+
+
+RTDECL(int) RTSemMutexRequestDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+    RT_NOREF_PV(uId); RT_SRC_POS_NOREF();
+    return RTSemMutexRequest(hMutexSem, cMillies);
+}
+RT_EXPORT_SYMBOL(RTSemMutexRequestDebug);
+
+
+RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
+{
+    return rtSemMutexLinuxRequest(hMutexSem, cMillies, true /*fInterruptible*/);
+}
+RT_EXPORT_SYMBOL(RTSemMutexRequestNoResume);
+
+
+RTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+    RT_NOREF_PV(uId); RT_SRC_POS_NOREF();
+    return RTSemMutexRequestNoResume(hMutexSem, cMillies);
+}
+RT_EXPORT_SYMBOL(RTSemMutexRequestNoResumeDebug);
+
+
+RTDECL(int) RTSemMutexRelease(RTSEMMUTEX hMtx)
+{
+    PRTSEMMUTEXINTERNAL pThis = hMtx;
+    struct task_struct *pSelf = current;
+    unsigned long       fSavedIrq;
+    int                 rc;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * Validate.
+     */
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
+    Assert(pThis->cRefs >= 1);
+
+    /*
+     * Take the lock and release one recursion.
+     */
+    spin_lock_irqsave(&pThis->Spinlock, fSavedIrq);
+    if (pThis->pOwnerTask == pSelf)
+    {
+        Assert(pThis->cRecursions > 0);
+        if (--pThis->cRecursions == 0)
+        {
+            pThis->pOwnerTask = NULL;
+
+            /* anyone to wake up? */
+            if (!RTListIsEmpty(&pThis->WaiterList))
+            {
+                PRTSEMMUTEXLNXWAITER pWaiter = RTListGetFirst(&pThis->WaiterList, RTSEMMUTEXLNXWAITER, ListEntry);
+                pWaiter->enmReason = RTSEMMUTEXLNXWAITER_WAKEUP;
+                wake_up_process(pWaiter->pTask);
+            }
+            IPRT_DEBUG_SEMS_STATE(pThis, 'u');
+        }
+        rc = VINF_SUCCESS;
+    }
+    else
+        rc = VERR_NOT_OWNER;
+    spin_unlock_irqrestore(&pThis->Spinlock, fSavedIrq);
+
+    AssertRC(rc);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTSemMutexRelease);
+
+
+RTDECL(bool) RTSemMutexIsOwned(RTSEMMUTEX hMutexSem)
+{
+    PRTSEMMUTEXINTERNAL pThis = hMutexSem;
+    unsigned long       fSavedIrq;
+    bool                fOwned;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * Validate.
+     */
+    AssertPtrReturn(pThis, false);
+    AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), false);
+    Assert(pThis->cRefs >= 1);
+
+    /*
+     * Take the lock and release one recursion.
+     */
+    spin_lock_irqsave(&pThis->Spinlock, fSavedIrq);
+    fOwned = pThis->pOwnerTask != NULL;
+    spin_unlock_irqrestore(&pThis->Spinlock, fSavedIrq);
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return fOwned;
+
+}
+RT_EXPORT_SYMBOL(RTSemMutexIsOwned);
+
diff --git a/ubuntu/vbox/r0drv/linux/spinlock-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/spinlock-r0drv-linux.c
new file mode 100644 (file)
index 0000000..d6d0895
--- /dev/null
@@ -0,0 +1,186 @@
+/* $Id: spinlock-r0drv-linux.c $ */
+/** @file
+ * IPRT - Spinlocks, Ring-0 Driver, Linux.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/spinlock.h>
+
+#include <iprt/asm.h>
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# include <iprt/asm-amd64-x86.h>
+#endif
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/mem.h>
+#include <iprt/mp.h>
+#include <iprt/thread.h>
+#include "internal/magics.h"
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * Wrapper for the spinlock_t structure.
+ */
+typedef struct RTSPINLOCKINTERNAL
+{
+    /** Spinlock magic value (RTSPINLOCK_MAGIC). */
+    uint32_t volatile       u32Magic;
+    /** The spinlock creation flags.  */
+    uint32_t                fFlags;
+    /** The saved interrupt flag. */
+    unsigned long volatile  fIntSaved;
+    /** The linux spinlock structure. */
+    spinlock_t              Spinlock;
+#ifdef RT_MORE_STRICT
+    /** The idAssertCpu variable before acquring the lock for asserting after
+     *  releasing the spinlock. */
+    RTCPUID volatile        idAssertCpu;
+    /** The CPU that owns the lock. */
+    RTCPUID volatile        idCpuOwner;
+#endif
+} RTSPINLOCKINTERNAL, *PRTSPINLOCKINTERNAL;
+
+
+
+RTDECL(int)  RTSpinlockCreate(PRTSPINLOCK pSpinlock, uint32_t fFlags, const char *pszName)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    PRTSPINLOCKINTERNAL pThis;
+    AssertReturn(fFlags == RTSPINLOCK_FLAGS_INTERRUPT_SAFE || fFlags == RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, VERR_INVALID_PARAMETER);
+    RT_NOREF_PV(pszName);
+
+    /*
+     * Allocate.
+     */
+    Assert(sizeof(RTSPINLOCKINTERNAL) > sizeof(void *));
+    pThis = (PRTSPINLOCKINTERNAL)RTMemAlloc(sizeof(*pThis));
+    if (!pThis)
+        return VERR_NO_MEMORY;
+    /*
+     * Initialize and return.
+     */
+    pThis->u32Magic     = RTSPINLOCK_MAGIC;
+    pThis->fFlags       = fFlags;
+    pThis->fIntSaved    = 0;
+#ifdef RT_MORE_STRICT
+    pThis->idCpuOwner   = NIL_RTCPUID;
+    pThis->idAssertCpu  = NIL_RTCPUID;
+#endif
+
+    spin_lock_init(&pThis->Spinlock);
+
+    *pSpinlock = pThis;
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSpinlockCreate);
+
+
+RTDECL(int)  RTSpinlockDestroy(RTSPINLOCK Spinlock)
+{
+    /*
+     * Validate input.
+     */
+    PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
+    if (!pThis)
+        return VERR_INVALID_PARAMETER;
+    if (pThis->u32Magic != RTSPINLOCK_MAGIC)
+    {
+        AssertMsgFailed(("Invalid spinlock %p magic=%#x\n", pThis, pThis->u32Magic));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    ASMAtomicIncU32(&pThis->u32Magic);
+    RTMemFree(pThis);
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTSpinlockDestroy);
+
+
+RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock)
+{
+    PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
+    IPRT_LINUX_SAVE_EFL_AC();
+    RT_ASSERT_PREEMPT_CPUID_VAR();
+    AssertMsg(pThis && pThis->u32Magic == RTSPINLOCK_MAGIC,
+              ("pThis=%p u32Magic=%08x\n", pThis, pThis ? (int)pThis->u32Magic : 0));
+
+#ifdef CONFIG_PROVE_LOCKING
+    lockdep_off();
+#endif
+    if (pThis->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE)
+    {
+        unsigned long fIntSaved;
+        spin_lock_irqsave(&pThis->Spinlock, fIntSaved);
+        pThis->fIntSaved = fIntSaved;
+    }
+    else
+        spin_lock(&pThis->Spinlock);
+#ifdef CONFIG_PROVE_LOCKING
+    lockdep_on();
+#endif
+
+    IPRT_LINUX_RESTORE_EFL_ONLY_AC();
+    RT_ASSERT_PREEMPT_CPUID_SPIN_ACQUIRED(pThis);
+}
+RT_EXPORT_SYMBOL(RTSpinlockAcquire);
+
+
+RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock)
+{
+    PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
+    IPRT_LINUX_SAVE_EFL_AC();           /* spin_unlock* may preempt and trash eflags.ac. */
+    RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE_VARS();
+    AssertMsg(pThis && pThis->u32Magic == RTSPINLOCK_MAGIC,
+              ("pThis=%p u32Magic=%08x\n", pThis, pThis ? (int)pThis->u32Magic : 0));
+    RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE(pThis);
+
+#ifdef CONFIG_PROVE_LOCKING
+    lockdep_off();
+#endif
+    if (pThis->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE)
+    {
+        unsigned long fIntSaved = pThis->fIntSaved;
+        pThis->fIntSaved = 0;
+        spin_unlock_irqrestore(&pThis->Spinlock, fIntSaved);
+    }
+    else
+        spin_unlock(&pThis->Spinlock);
+#ifdef CONFIG_PROVE_LOCKING
+    lockdep_on();
+#endif
+
+    IPRT_LINUX_RESTORE_EFL_ONLY_AC();
+    RT_ASSERT_PREEMPT_CPUID();
+}
+RT_EXPORT_SYMBOL(RTSpinlockRelease);
+
diff --git a/ubuntu/vbox/r0drv/linux/string.h b/ubuntu/vbox/r0drv/linux/string.h
new file mode 100644 (file)
index 0000000..c475340
--- /dev/null
@@ -0,0 +1,57 @@
+/* $Id: string.h $ */
+/** @file
+ * IPRT - wrapper for the linux kernel asm/string.h.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___string_h
+#define ___string_h
+
+#include <iprt/cdefs.h>
+
+RT_C_DECLS_BEGIN
+#ifndef bool /* Linux 2.6.19 C++ nightmare */
+#define bool bool_type
+#define true true_type
+#define false false_type
+#define _Bool int
+#define bool_type_r0drv_string_h__
+#endif
+#include <linux/types.h>
+#include <linux/string.h>
+#ifdef bool_type_r0drv_string_h__
+#undef bool
+#undef true
+#undef false
+#undef bool_type_r0drv_string_h__
+#endif
+char *strpbrk(const char *pszStr, const char *pszChars)
+#if defined(__THROW)
+    __THROW
+#endif
+    ;
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/r0drv/linux/the-linux-kernel.h b/ubuntu/vbox/r0drv/linux/the-linux-kernel.h
new file mode 100644 (file)
index 0000000..3a17bd1
--- /dev/null
@@ -0,0 +1,452 @@
+/* $Id: the-linux-kernel.h $ */
+/** @file
+ * IPRT - Include all necessary headers for the Linux kernel.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___the_linux_kernel_h
+#define ___the_linux_kernel_h
+
+/*
+ * Include iprt/types.h to install the bool wrappers.
+ * Then use the linux bool type for all the stuff include here.
+ */
+#include <iprt/types.h>
+#define bool linux_bool
+
+#if RT_GNUC_PREREQ(4, 6)
+# pragma GCC diagnostic push
+#endif
+#if RT_GNUC_PREREQ(4, 2)
+# pragma GCC diagnostic ignored "-Wunused-parameter"
+# if !defined(__cplusplus) && RT_GNUC_PREREQ(4, 3)
+#  pragma GCC diagnostic ignored "-Wold-style-declaration" /* 2.6.18-411.0.0.0.1.el5/build/include/asm/apic.h:110: warning: 'inline' is not at beginning of declaration [-Wold-style-declaration] */
+# endif
+#endif
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+# include <generated/autoconf.h>
+#else
+# ifndef AUTOCONF_INCLUDED
+#  include <linux/autoconf.h>
+# endif
+#endif
+
+/* We only support 2.4 and 2.6 series kernels */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+# error We only support 2.4 and 2.6 series kernels
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+# error We only support 2.4 and 2.6 series kernels
+#endif
+
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+# define MODVERSIONS
+# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 71)
+#  include <linux/modversions.h>
+# endif
+#endif
+#ifndef KBUILD_STR
+# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
+#  define KBUILD_STR(s) s
+# else
+#  define KBUILD_STR(s) #s
+# endif
+#endif
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+#  include <linux/kconfig.h> /* for macro IS_ENABLED */
+# endif
+#include <linux/string.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+# include <linux/semaphore.h>
+#else /* older kernels */
+# include <asm/semaphore.h>
+#endif /* older kernels */
+#include <linux/module.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+# include <linux/moduleparam.h>
+#endif
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+# include <linux/namei.h>
+#endif
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/sched.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+# include <linux/sched/rt.h>
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+# include <linux/sched/signal.h>
+# include <linux/sched/types.h>
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 7)
+# include <linux/jiffies.h>
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
+# include <linux/ktime.h>
+# include <linux/hrtimer.h>
+#endif
+#include <linux/wait.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 71)
+# include <linux/cpu.h>
+# include <linux/notifier.h>
+#endif
+/* For the basic additions module */
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/compiler.h>
+#ifndef HAVE_UNLOCKED_IOCTL /* linux/fs.h defines this */
+# include <linux/smp_lock.h>
+#endif
+/* For the shared folders module */
+#include <linux/vmalloc.h>
+#define wchar_t linux_wchar_t
+#include <linux/nls.h>
+#undef wchar_t
+#include <asm/mman.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/div64.h>
+
+/* For thread-context hooks. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) && defined(CONFIG_PREEMPT_NOTIFIERS)
+# include <linux/preempt.h>
+#endif
+
+/* for workqueue / task queues. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41)
+# include <linux/workqueue.h>
+#else
+# include <linux/tqueue.h>
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+# include <linux/kthread.h>
+#endif
+
+/* for cr4_init_shadow() / cpu_tlbstate. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 20, 0)
+# include <asm/tlbflush.h>
+#endif
+
+/* for set_pages_x() */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+# include <asm/set_memory.h>
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+# include <asm/smap.h>
+#else
+static inline void clac(void) { }
+static inline void stac(void) { }
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+# ifndef page_to_pfn
+#  define page_to_pfn(page) ((page) - mem_map)
+# endif
+#endif
+
+#ifndef DEFINE_WAIT
+# define DEFINE_WAIT(name) DECLARE_WAITQUEUE(name, current)
+#endif
+
+#ifndef __GFP_NOWARN
+# define __GFP_NOWARN 0
+#endif
+
+/*
+ * 2.4 / early 2.6 compatibility wrappers
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 7)
+
+# ifndef MAX_JIFFY_OFFSET
+#  define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
+# endif
+
+# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 29) || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+
+DECLINLINE(unsigned int) jiffies_to_msecs(unsigned long cJiffies)
+{
+#  if HZ <= 1000 && !(1000 % HZ)
+    return (1000 / HZ) * cJiffies;
+#  elif HZ > 1000 && !(HZ % 1000)
+    return (cJiffies + (HZ / 1000) - 1) / (HZ / 1000);
+#  else
+    return (cJiffies * 1000) / HZ;
+#  endif
+}
+
+DECLINLINE(unsigned long) msecs_to_jiffies(unsigned int cMillies)
+{
+#  if HZ > 1000
+    if (cMillies > jiffies_to_msecs(MAX_JIFFY_OFFSET))
+        return MAX_JIFFY_OFFSET;
+#  endif
+#  if HZ <= 1000 && !(1000 % HZ)
+    return (cMillies + (1000 / HZ) - 1) / (1000 / HZ);
+#  elif HZ > 1000 && !(HZ % 1000)
+    return cMillies * (HZ / 1000);
+#  else
+    return (cMillies * HZ + 999) / 1000;
+#  endif
+}
+
+# endif  /* < 2.4.29 || >= 2.6.0 */
+
+#endif /* < 2.6.7 */
+
+/*
+ * 2.4 compatibility wrappers
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+
+# define prepare_to_wait(q, wait, state) \
+    do { \
+        add_wait_queue(q, wait); \
+        set_current_state(state); \
+    } while (0)
+
+# define after_wait(wait) \
+    do { \
+        list_del_init(&(wait)->task_list); \
+    } while (0)
+
+# define finish_wait(q, wait) \
+    do { \
+        set_current_state(TASK_RUNNING); \
+        remove_wait_queue(q, wait); \
+    } while (0)
+
+#else /* >= 2.6.0 */
+
+# define after_wait(wait)       do {} while (0)
+
+#endif /* >= 2.6.0 */
+
+/** @def TICK_NSEC
+ * The time between ticks in nsec */
+#ifndef TICK_NSEC
+# define TICK_NSEC (1000000000UL / HZ)
+#endif
+
+/*
+ * This sucks soooo badly on x86! Why don't they export __PAGE_KERNEL_EXEC so PAGE_KERNEL_EXEC would be usable?
+ */
+#if   LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8) && defined(RT_ARCH_AMD64)
+# define MY_PAGE_KERNEL_EXEC    PAGE_KERNEL_EXEC
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8) && defined(PAGE_KERNEL_EXEC) && defined(CONFIG_X86_PAE)
+# ifdef __PAGE_KERNEL_EXEC
+   /* >= 2.6.27 */
+#  define MY_PAGE_KERNEL_EXEC   __pgprot(boot_cpu_has(X86_FEATURE_PGE) ? __PAGE_KERNEL_EXEC | _PAGE_GLOBAL : __PAGE_KERNEL_EXEC)
+# else
+#  define MY_PAGE_KERNEL_EXEC   __pgprot(boot_cpu_has(X86_FEATURE_PGE) ? _PAGE_KERNEL_EXEC | _PAGE_GLOBAL : _PAGE_KERNEL_EXEC)
+# endif
+#else
+# define MY_PAGE_KERNEL_EXEC    PAGE_KERNEL
+#endif
+
+
+/*
+ * The redhat hack section.
+ *  - The current hacks are for 2.4.21-15.EL only.
+ */
+#ifndef NO_REDHAT_HACKS
+/* accounting. */
+# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+#  ifdef VM_ACCOUNT
+#   define USE_RHEL4_MUNMAP
+#  endif
+# endif
+
+/* backported remap_page_range. */
+# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+#  include <asm/tlb.h>
+#  ifdef tlb_vma /* probably not good enough... */
+#   define HAVE_26_STYLE_REMAP_PAGE_RANGE 1
+#  endif
+# endif
+
+# ifndef RT_ARCH_AMD64
+/* In 2.6.9-22.ELsmp we have to call change_page_attr() twice when changing
+ * the page attributes from PAGE_KERNEL to something else, because there appears
+ * to be a bug in one of the many patches that redhat applied.
+ * It should be safe to do this on less buggy linux kernels too. ;-)
+ */
+#  define MY_CHANGE_PAGE_ATTR(pPages, cPages, prot) \
+    do { \
+        if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) \
+            change_page_attr(pPages, cPages, prot); \
+        change_page_attr(pPages, cPages, prot); \
+    } while (0)
+# endif  /* !RT_ARCH_AMD64 */
+#endif /* !NO_REDHAT_HACKS */
+
+#ifndef MY_CHANGE_PAGE_ATTR
+# ifdef RT_ARCH_AMD64 /** @todo This is a cheap hack, but it'll get around that 'else BUG();' in __change_page_attr().  */
+#  define MY_CHANGE_PAGE_ATTR(pPages, cPages, prot) \
+    do { \
+        change_page_attr(pPages, cPages, PAGE_KERNEL_NOCACHE); \
+        change_page_attr(pPages, cPages, prot); \
+    } while (0)
+# else
+#  define MY_CHANGE_PAGE_ATTR(pPages, cPages, prot) change_page_attr(pPages, cPages, prot)
+# endif
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+# define MY_SET_PAGES_EXEC(pPages, cPages)    set_pages_x(pPages, cPages)
+# define MY_SET_PAGES_NOEXEC(pPages, cPages)  set_pages_nx(pPages, cPages)
+#else
+# define MY_SET_PAGES_EXEC(pPages, cPages) \
+    do { \
+        if (pgprot_val(MY_PAGE_KERNEL_EXEC) != pgprot_val(PAGE_KERNEL)) \
+            MY_CHANGE_PAGE_ATTR(pPages, cPages, MY_PAGE_KERNEL_EXEC); \
+    } while (0)
+# define MY_SET_PAGES_NOEXEC(pPages, cPages) \
+    do { \
+        if (pgprot_val(MY_PAGE_KERNEL_EXEC) != pgprot_val(PAGE_KERNEL)) \
+            MY_CHANGE_PAGE_ATTR(pPages, cPages, PAGE_KERNEL); \
+    } while (0)
+#endif
+
+/** @def ONE_MSEC_IN_JIFFIES
+ * The number of jiffies that make up 1 millisecond. Must be at least 1! */
+#if HZ <= 1000
+# define ONE_MSEC_IN_JIFFIES       1
+#elif !(HZ % 1000)
+# define ONE_MSEC_IN_JIFFIES       (HZ / 1000)
+#else
+# define ONE_MSEC_IN_JIFFIES       ((HZ + 999) / 1000)
+# error "HZ is not a multiple of 1000, the GIP stuff won't work right!"
+#endif
+
+/*
+ * Stop using the linux bool type.
+ */
+#undef bool
+
+#if RT_GNUC_PREREQ(4, 6)
+# pragma GCC diagnostic pop
+#endif
+
+/*
+ * There are post-2.6.24 kernels (confusingly with unchanged version number)
+ * which eliminate macros which were marked as deprecated.
+ */
+#ifndef __attribute_used__
+#define __attribute_used__ __used
+#endif
+
+/**
+ * Hack for shortening pointers on linux so we can stuff more stuff into the
+ * task_struct::comm field. This is used by the semaphore code but put here
+ * because we don't have any better place atm. Don't use outside IPRT, please.
+ */
+#ifdef RT_ARCH_AMD64
+# define IPRT_DEBUG_SEMS_ADDRESS(addr)  ( ((long)(addr) & (long)~UINT64_C(0xfffffff000000000)) )
+#else
+# define IPRT_DEBUG_SEMS_ADDRESS(addr)  ( (long)(addr) )
+#endif
+
+/**
+ * Puts semaphore info into the task_struct::comm field if IPRT_DEBUG_SEMS is
+ * defined.
+ */
+#ifdef IPRT_DEBUG_SEMS
+# define IPRT_DEBUG_SEMS_STATE(pThis, chState) \
+    snprintf(current->comm, sizeof(current->comm), "%c%lx", (chState), IPRT_DEBUG_SEMS_ADDRESS(pThis));
+#else
+# define IPRT_DEBUG_SEMS_STATE(pThis, chState)  do {  } while (0)
+#endif
+
+/**
+ * Puts semaphore info into the task_struct::comm field if IPRT_DEBUG_SEMS is
+ * defined.
+ */
+#ifdef IPRT_DEBUG_SEMS
+# define IPRT_DEBUG_SEMS_STATE_RC(pThis, chState, rc) \
+    snprintf(current->comm, sizeof(current->comm), "%c%lx:%d", (chState), IPRT_DEBUG_SEMS_ADDRESS(pThis), rc);
+#else
+# define IPRT_DEBUG_SEMS_STATE_RC(pThis, chState, rc)  do {  } while (0)
+#endif
+
+/** @name Macros for preserving EFLAGS.AC on 3.19+/amd64  paranoid.
+ * The AMD 64 switch_to in macro in arch/x86/include/asm/switch_to.h stopped
+ * restoring flags.
+ * @{ */
+#if defined(CONFIG_X86_SMAP) || defined(RT_STRICT) || defined(IPRT_WITH_EFLAGS_AC_PRESERVING)
+# include <iprt/asm-amd64-x86.h>
+# define IPRT_X86_EFL_AC                    RT_BIT(18)
+# define IPRT_LINUX_SAVE_EFL_AC()           RTCCUINTREG fSavedEfl = ASMGetFlags()
+# define IPRT_LINUX_RESTORE_EFL_AC()        ASMSetFlags(fSavedEfl)
+# define IPRT_LINUX_RESTORE_EFL_ONLY_AC()   ASMChangeFlags(~IPRT_X86_EFL_AC, fSavedEfl & IPRT_X86_EFL_AC)
+#else
+# define IPRT_LINUX_SAVE_EFL_AC()           do { } while (0)
+# define IPRT_LINUX_RESTORE_EFL_AC()        do { } while (0)
+# define IPRT_LINUX_RESTORE_EFL_ONLY_AC()   do { } while (0)
+#endif
+/** @} */
+
+/*
+ * There are some conflicting defines in iprt/param.h, sort them out here.
+ */
+#ifndef ___iprt_param_h
+# undef PAGE_SIZE
+# undef PAGE_OFFSET_MASK
+# include <iprt/param.h>
+#endif
+
+/*
+ * Some global indicator macros.
+ */
+/** @def IPRT_LINUX_HAS_HRTIMER
+ * Whether the kernel support high resolution timers (Linux kernel versions
+ * 2.6.28 and later (hrtimer_add_expires_ns() & schedule_hrtimeout). */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+# define IPRT_LINUX_HAS_HRTIMER
+#endif
+
+/*
+ * Workqueue stuff, see initterm-r0drv-linux.c.
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41)
+typedef struct work_struct  RTR0LNXWORKQUEUEITEM;
+#else
+typedef struct tq_struct    RTR0LNXWORKQUEUEITEM;
+#endif
+DECLHIDDEN(void) rtR0LnxWorkqueuePush(RTR0LNXWORKQUEUEITEM *pWork, void (*pfnWorker)(RTR0LNXWORKQUEUEITEM *));
+DECLHIDDEN(void) rtR0LnxWorkqueueFlush(void);
+
+
+#endif
diff --git a/ubuntu/vbox/r0drv/linux/thread-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/thread-r0drv-linux.c
new file mode 100644 (file)
index 0000000..680a74d
--- /dev/null
@@ -0,0 +1,236 @@
+/* $Id: thread-r0drv-linux.c $ */
+/** @file
+ * IPRT - Threads, Ring-0 Driver, Linux.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/thread.h>
+
+#include <iprt/asm.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 28) || defined(CONFIG_X86_SMAP)
+# include <iprt/asm-amd64-x86.h>
+#endif
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/mp.h>
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+#ifndef CONFIG_PREEMPT
+/** Per-cpu preemption counters. */
+static int32_t volatile g_acPreemptDisabled[NR_CPUS];
+#endif
+
+
+RTDECL(RTNATIVETHREAD) RTThreadNativeSelf(void)
+{
+    return (RTNATIVETHREAD)current;
+}
+RT_EXPORT_SYMBOL(RTThreadNativeSelf);
+
+
+static int rtR0ThreadLnxSleepCommon(RTMSINTERVAL cMillies)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    long cJiffies = msecs_to_jiffies(cMillies);
+    set_current_state(TASK_INTERRUPTIBLE);
+    cJiffies = schedule_timeout(cJiffies);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    if (!cJiffies)
+        return VINF_SUCCESS;
+    return VERR_INTERRUPTED;
+}
+
+
+RTDECL(int) RTThreadSleep(RTMSINTERVAL cMillies)
+{
+    return rtR0ThreadLnxSleepCommon(cMillies);
+}
+RT_EXPORT_SYMBOL(RTThreadSleep);
+
+
+RTDECL(int) RTThreadSleepNoLog(RTMSINTERVAL cMillies)
+{
+    return rtR0ThreadLnxSleepCommon(cMillies);
+}
+RT_EXPORT_SYMBOL(RTThreadSleepNoLog);
+
+
+RTDECL(bool) RTThreadYield(void)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 20)
+    yield();
+#else
+    /** @todo r=ramshankar: Can we use cond_resched() instead?  */
+    set_current_state(TASK_RUNNING);
+    sys_sched_yield();
+    schedule();
+#endif
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return true;
+}
+RT_EXPORT_SYMBOL(RTThreadYield);
+
+
+RTDECL(bool) RTThreadPreemptIsEnabled(RTTHREAD hThread)
+{
+#ifdef CONFIG_PREEMPT
+    Assert(hThread == NIL_RTTHREAD); RT_NOREF_PV(hThread);
+# ifdef preemptible
+    return preemptible();
+# else
+    return preempt_count() == 0 && !in_atomic() && !irqs_disabled();
+# endif
+#else
+    int32_t c;
+
+    Assert(hThread == NIL_RTTHREAD);
+    c = g_acPreemptDisabled[smp_processor_id()];
+    AssertMsg(c >= 0 && c < 32, ("%d\n", c));
+    if (c != 0)
+        return false;
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 32)
+    if (in_atomic())
+        return false;
+# endif
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 28)
+    if (irqs_disabled())
+        return false;
+# else
+    if (!ASMIntAreEnabled())
+        return false;
+# endif
+    return true;
+#endif
+}
+RT_EXPORT_SYMBOL(RTThreadPreemptIsEnabled);
+
+
+RTDECL(bool) RTThreadPreemptIsPending(RTTHREAD hThread)
+{
+    Assert(hThread == NIL_RTTHREAD); RT_NOREF_PV(hThread);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 4)
+    return !!test_tsk_thread_flag(current, TIF_NEED_RESCHED);
+
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 20)
+    return !!need_resched();
+
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 1, 110)
+    return current->need_resched != 0;
+
+#else
+    return need_resched != 0;
+#endif
+}
+RT_EXPORT_SYMBOL(RTThreadPreemptIsPending);
+
+
+RTDECL(bool) RTThreadPreemptIsPendingTrusty(void)
+{
+    /* yes, RTThreadPreemptIsPending is reliable. */
+    return true;
+}
+RT_EXPORT_SYMBOL(RTThreadPreemptIsPendingTrusty);
+
+
+RTDECL(bool) RTThreadPreemptIsPossible(void)
+{
+    /** @todo r=ramshankar: What about CONFIG_PREEMPT_VOLUNTARY? That can preempt
+     *        too but does so in voluntarily in explicit preemption points. */
+#ifdef CONFIG_PREEMPT
+    return true;    /* yes, kernel preemption is possible. */
+#else
+    return false;   /* no kernel preemption */
+#endif
+}
+RT_EXPORT_SYMBOL(RTThreadPreemptIsPossible);
+
+
+RTDECL(void) RTThreadPreemptDisable(PRTTHREADPREEMPTSTATE pState)
+{
+#ifdef CONFIG_PREEMPT
+    AssertPtr(pState);
+    Assert(pState->u32Reserved == 0);
+    pState->u32Reserved = 42;
+    /* This ASSUMES that CONFIG_PREEMPT_COUNT is always defined with CONFIG_PREEMPT. */
+    preempt_disable();
+    RT_ASSERT_PREEMPT_CPUID_DISABLE(pState);
+
+#else /* !CONFIG_PREEMPT */
+    int32_t c;
+    AssertPtr(pState);
+    Assert(pState->u32Reserved == 0);
+
+    /* Do our own accounting. */
+    c = ASMAtomicIncS32(&g_acPreemptDisabled[smp_processor_id()]);
+    AssertMsg(c > 0 && c < 32, ("%d\n", c));
+    pState->u32Reserved = c;
+    RT_ASSERT_PREEMPT_CPUID_DISABLE(pState);
+#endif
+}
+RT_EXPORT_SYMBOL(RTThreadPreemptDisable);
+
+
+RTDECL(void) RTThreadPreemptRestore(PRTTHREADPREEMPTSTATE pState)
+{
+#ifdef CONFIG_PREEMPT
+    IPRT_LINUX_SAVE_EFL_AC(); /* paranoia */
+    AssertPtr(pState);
+    Assert(pState->u32Reserved == 42);
+    RT_ASSERT_PREEMPT_CPUID_RESTORE(pState);
+    preempt_enable();
+    IPRT_LINUX_RESTORE_EFL_ONLY_AC();  /* paranoia */
+
+#else
+    int32_t volatile *pc;
+    AssertPtr(pState);
+    AssertMsg(pState->u32Reserved > 0 && pState->u32Reserved < 32, ("%d\n", pState->u32Reserved));
+    RT_ASSERT_PREEMPT_CPUID_RESTORE(pState);
+
+    /* Do our own accounting. */
+    pc = &g_acPreemptDisabled[smp_processor_id()];
+    AssertMsg(pState->u32Reserved == (uint32_t)*pc, ("u32Reserved=%d *pc=%d \n", pState->u32Reserved, *pc));
+    ASMAtomicUoWriteS32(pc, pState->u32Reserved - 1);
+#endif
+    pState->u32Reserved = 0;
+}
+RT_EXPORT_SYMBOL(RTThreadPreemptRestore);
+
+
+RTDECL(bool) RTThreadIsInInterrupt(RTTHREAD hThread)
+{
+    Assert(hThread == NIL_RTTHREAD); NOREF(hThread);
+
+    return in_interrupt() != 0;
+}
+RT_EXPORT_SYMBOL(RTThreadIsInInterrupt);
+
diff --git a/ubuntu/vbox/r0drv/linux/thread2-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/thread2-r0drv-linux.c
new file mode 100644 (file)
index 0000000..1e7eb70
--- /dev/null
@@ -0,0 +1,162 @@
+/* $Id: thread2-r0drv-linux.c $ */
+/** @file
+ * IPRT - Threads (Part 2), Ring-0 Driver, Linux.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/thread.h>
+#include <iprt/err.h>
+#include "internal/thread.h"
+
+
+RTDECL(RTTHREAD) RTThreadSelf(void)
+{
+    return rtThreadGetByNative((RTNATIVETHREAD)current);
+}
+
+
+DECLHIDDEN(int) rtThreadNativeInit(void)
+{
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(int) rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
+    /* See comment near MAX_RT_PRIO in linux/sched.h for details on
+       sched_priority. */
+    int                 iSchedClass = SCHED_NORMAL;
+    struct sched_param  Param       = { .sched_priority = MAX_PRIO - 1 };
+    switch (enmType)
+    {
+        case RTTHREADTYPE_INFREQUENT_POLLER:
+            Param.sched_priority = MAX_RT_PRIO + 5;
+            break;
+
+        case RTTHREADTYPE_EMULATION:
+            Param.sched_priority = MAX_RT_PRIO + 4;
+            break;
+
+        case RTTHREADTYPE_DEFAULT:
+            Param.sched_priority = MAX_RT_PRIO + 3;
+            break;
+
+        case RTTHREADTYPE_MSG_PUMP:
+            Param.sched_priority = MAX_RT_PRIO + 2;
+            break;
+
+        case RTTHREADTYPE_IO:
+            iSchedClass = SCHED_FIFO;
+            Param.sched_priority = MAX_RT_PRIO - 1;
+            break;
+
+        case RTTHREADTYPE_TIMER:
+            iSchedClass = SCHED_FIFO;
+            Param.sched_priority = 1; /* not 0 just in case */
+            break;
+
+        default:
+            AssertMsgFailed(("enmType=%d\n", enmType));
+            return VERR_INVALID_PARAMETER;
+    }
+
+    sched_setscheduler(current, iSchedClass, &Param);
+#else
+    RT_NOREF_PV(enmType);
+#endif
+    RT_NOREF_PV(pThread);
+
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(int) rtThreadNativeAdopt(PRTTHREADINT pThread)
+{
+    RT_NOREF_PV(pThread);
+    return VERR_NOT_IMPLEMENTED;
+}
+
+
+DECLHIDDEN(void) rtThreadNativeWaitKludge(PRTTHREADINT pThread)
+{
+    /** @todo fix RTThreadWait/RTR0Term race on linux. */
+    RTThreadSleep(1); NOREF(pThread);
+}
+
+
+DECLHIDDEN(void) rtThreadNativeDestroy(PRTTHREADINT pThread)
+{
+    NOREF(pThread);
+}
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 4)
+/**
+ * Native kernel thread wrapper function.
+ *
+ * This will forward to rtThreadMain and do termination upon return.
+ *
+ * @param pvArg         Pointer to the argument package.
+ */
+static int rtThreadNativeMain(void *pvArg)
+{
+    PRTTHREADINT pThread = (PRTTHREADINT)pvArg;
+
+    rtThreadMain(pThread, (RTNATIVETHREAD)current, &pThread->szName[0]);
+    return 0;
+}
+#endif
+
+
+DECLHIDDEN(int) rtThreadNativeCreate(PRTTHREADINT pThreadInt, PRTNATIVETHREAD pNativeThread)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 4)
+    struct task_struct *NativeThread;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    RT_ASSERT_PREEMPTIBLE();
+
+    NativeThread = kthread_run(rtThreadNativeMain, pThreadInt, "iprt-%s", pThreadInt->szName);
+
+    if (!IS_ERR(NativeThread))
+    {
+        *pNativeThread = (RTNATIVETHREAD)NativeThread;
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return VINF_SUCCESS;
+    }
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VERR_GENERAL_FAILURE;
+#else
+    return VERR_NOT_IMPLEMENTED;
+#endif
+}
+
diff --git a/ubuntu/vbox/r0drv/linux/time-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/time-r0drv-linux.c
new file mode 100644 (file)
index 0000000..b7d3e3b
--- /dev/null
@@ -0,0 +1,187 @@
+/* $Id: time-r0drv-linux.c $ */
+/** @file
+ * IPRT - Time, Ring-0 Driver, Linux.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_TIME
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/time.h>
+#include <iprt/asm.h>
+
+
+
+DECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16) /* This must match timer-r0drv-linux.c! */
+    /*
+     * Use ktime_get_ts, this is also what clock_gettime(CLOCK_MONOTONIC,) is using.
+     */
+    uint64_t u64;
+    struct timespec Ts;
+    ktime_get_ts(&Ts);
+    u64 = Ts.tv_sec * RT_NS_1SEC_64 + Ts.tv_nsec;
+    return u64;
+
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 60)
+    /*
+     * Seems there is no way of getting to the exact source of
+     * sys_clock_gettime(CLOCK_MONOTONIC, &ts) here, I think. But
+     * 64-bit jiffies adjusted for the initial value should be pretty
+     * much the same I hope.
+     */
+    uint64_t u64 = get_jiffies_64();
+# ifdef INITIAL_JIFFIES
+    u64 += INITIAL_JIFFIES;
+# endif
+    u64 *= TICK_NSEC;
+    return u64;
+
+#else   /* < 2.5.60 */
+# if BITS_PER_LONG >= 64
+    /*
+     * This is the same as above, except that there is no get_jiffies_64()
+     * here and we rely on long, and therefor jiffies, being 64-bit instead.
+     */
+    uint64_t u64 = jiffies;
+# ifdef INITIAL_JIFFIES
+    u64 += INITIAL_JIFFIES;
+# endif
+    u64 *= TICK_NSEC;
+    return u64;
+
+# else /* 32 bit jiffies */
+    /*
+     * We'll have to try track jiffy rollovers here or we'll be
+     * in trouble every time it flips.
+     *
+     * The high dword of the s_u64Last is the rollover count, the
+     * low dword is the previous jiffies.  Updating is done by
+     * atomic compare & exchange of course.
+     */
+    static uint64_t volatile s_u64Last = 0;
+    uint64_t u64;
+
+    for (;;)
+    {
+        uint64_t u64NewLast;
+        int32_t iDelta;
+        uint32_t cRollovers;
+        uint32_t u32LastJiffies;
+
+        /* sample the values */
+        unsigned long ulNow = jiffies;
+        uint64_t u64Last = s_u64Last;
+        if (ulNow != jiffies)
+            continue; /* try again */
+#  ifdef INITIAL_JIFFIES
+        ulNow += INITIAL_JIFFIES;
+#  endif
+
+        u32LastJiffies = (uint32_t)u64Last;
+        cRollovers = u64Last >> 32;
+
+        /*
+         * Check for rollover and update the static last value.
+         *
+         * We have to make sure we update it successfully to rule out
+         * an underrun because of racing someone.
+         */
+        iDelta = ulNow - u32LastJiffies;
+        if (iDelta < 0)
+        {
+            cRollovers++;
+            u64NewLast = RT_MAKE_U64(ulNow, cRollovers);
+            if (!ASMAtomicCmpXchgU64(&s_u64Last, u64NewLast, u64Last))
+                continue; /* race, try again */
+        }
+        else
+        {
+            u64NewLast = RT_MAKE_U64(ulNow, cRollovers);
+            ASMAtomicCmpXchgU64(&s_u64Last, u64NewLast, u64Last);
+        }
+
+        /* calculate the return value */
+        u64 = ulNow;
+        u64 *= TICK_NSEC;
+        u64 += cRollovers * (_4G * TICK_NSEC);
+        break;
+    }
+
+    return u64;
+# endif /* 32 bit jiffies */
+#endif  /* < 2.5.60 */
+}
+
+
+RTDECL(uint64_t) RTTimeNanoTS(void)
+{
+    return rtTimeGetSystemNanoTS();
+}
+RT_EXPORT_SYMBOL(RTTimeNanoTS);
+
+
+RTDECL(uint64_t) RTTimeMilliTS(void)
+{
+    return rtTimeGetSystemNanoTS() / RT_NS_1MS;
+}
+RT_EXPORT_SYMBOL(RTTimeMilliTS);
+
+
+RTDECL(uint64_t) RTTimeSystemNanoTS(void)
+{
+    return rtTimeGetSystemNanoTS();
+}
+RT_EXPORT_SYMBOL(RTTimeSystemNanoTS);
+
+
+RTDECL(uint64_t) RTTimeSystemMilliTS(void)
+{
+    return rtTimeGetSystemNanoTS() / RT_NS_1MS;
+}
+RT_EXPORT_SYMBOL(RTTimeSystemMilliTS);
+
+
+RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
+    struct timespec Ts;
+    ktime_get_real_ts(&Ts);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return RTTimeSpecSetTimespec(pTime, &Ts);
+
+#else   /* < 2.6.16 */
+    struct timeval Tv;
+    do_gettimeofday(&Tv);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return RTTimeSpecSetTimeval(pTime, &Tv);
+#endif
+}
+RT_EXPORT_SYMBOL(RTTimeNow);
+
diff --git a/ubuntu/vbox/r0drv/linux/timer-r0drv-linux.c b/ubuntu/vbox/r0drv/linux/timer-r0drv-linux.c
new file mode 100644 (file)
index 0000000..e560ade
--- /dev/null
@@ -0,0 +1,1678 @@
+/* $Id: timer-r0drv-linux.c $ */
+/** @file
+ * IPRT - Timers, Ring-0 Driver, Linux.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "the-linux-kernel.h"
+#include "internal/iprt.h"
+
+#include <iprt/timer.h>
+#include <iprt/time.h>
+#include <iprt/mp.h>
+#include <iprt/cpuset.h>
+#include <iprt/spinlock.h>
+#include <iprt/err.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/alloc.h>
+
+#include "internal/magics.h"
+
+/** @def RTTIMER_LINUX_WITH_HRTIMER
+ * Whether to use high resolution timers.  */
+#if !defined(RTTIMER_LINUX_WITH_HRTIMER) \
+    && defined(IPRT_LINUX_HAS_HRTIMER)
+# define RTTIMER_LINUX_WITH_HRTIMER
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+# define mod_timer_pinned               mod_timer
+# define HRTIMER_MODE_ABS_PINNED        HRTIMER_MODE_ABS
+#endif
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * Timer state machine.
+ *
+ * This is used to try handle the issues with MP events and
+ * timers that runs on all CPUs. It's relatively nasty :-/
+ */
+typedef enum RTTIMERLNXSTATE
+{
+    /** Stopped. */
+    RTTIMERLNXSTATE_STOPPED = 0,
+    /** Transient state; next ACTIVE. */
+    RTTIMERLNXSTATE_STARTING,
+    /** Transient state; next ACTIVE. (not really necessary) */
+    RTTIMERLNXSTATE_MP_STARTING,
+    /** Active. */
+    RTTIMERLNXSTATE_ACTIVE,
+    /** Active and in callback; next ACTIVE, STOPPED or CALLBACK_DESTROYING. */
+    RTTIMERLNXSTATE_CALLBACK,
+    /** Stopped while in the callback; next STOPPED. */
+    RTTIMERLNXSTATE_CB_STOPPING,
+    /** Restarted while in the callback; next ACTIVE, STOPPED, DESTROYING. */
+    RTTIMERLNXSTATE_CB_RESTARTING,
+    /** The callback shall destroy the timer; next STOPPED. */
+    RTTIMERLNXSTATE_CB_DESTROYING,
+    /** Transient state; next STOPPED. */
+    RTTIMERLNXSTATE_STOPPING,
+    /** Transient state; next STOPPED. */
+    RTTIMERLNXSTATE_MP_STOPPING,
+    /** The usual 32-bit hack. */
+    RTTIMERLNXSTATE_32BIT_HACK = 0x7fffffff
+} RTTIMERLNXSTATE;
+
+
+/**
+ * A Linux sub-timer.
+ */
+typedef struct RTTIMERLNXSUBTIMER
+{
+    /** Timer specific data.  */
+    union
+    {
+#if defined(RTTIMER_LINUX_WITH_HRTIMER)
+        /** High resolution timer. */
+        struct
+        {
+            /** The linux timer structure. */
+            struct hrtimer          LnxTimer;
+        } Hr;
+#endif
+        /** Standard timer. */
+        struct
+        {
+            /** The linux timer structure. */
+            struct timer_list       LnxTimer;
+            /** The start of the current run (ns).
+             * This is used to calculate when the timer ought to fire the next time. */
+            uint64_t                u64NextTS;
+            /** The u64NextTS in jiffies. */
+            unsigned long           ulNextJiffies;
+            /** Set when starting or changing the timer so that u64StartTs
+             *  and u64NextTS gets reinitialized (eliminating some jitter). */
+            bool volatile           fFirstAfterChg;
+        } Std;
+    } u;
+    /** The current tick number. */
+    uint64_t                iTick;
+    /** Restart the single shot timer at this specific time.
+     * Used when a single shot timer is restarted from the callback. */
+    uint64_t volatile       uNsRestartAt;
+    /** Pointer to the parent timer. */
+    PRTTIMER                pParent;
+    /** The current sub-timer state. */
+    RTTIMERLNXSTATE volatile enmState;
+} RTTIMERLNXSUBTIMER;
+/** Pointer to a linux sub-timer. */
+typedef RTTIMERLNXSUBTIMER *PRTTIMERLNXSUBTIMER;
+
+
+/**
+ * The internal representation of an Linux timer handle.
+ */
+typedef struct RTTIMER
+{
+    /** Magic.
+     * This is RTTIMER_MAGIC, but changes to something else before the timer
+     * is destroyed to indicate clearly that thread should exit. */
+    uint32_t volatile       u32Magic;
+    /** Spinlock synchronizing the fSuspended and MP event handling.
+     * This is NIL_RTSPINLOCK if cCpus == 1. */
+    RTSPINLOCK              hSpinlock;
+    /** Flag indicating that the timer is suspended. */
+    bool volatile           fSuspended;
+    /** Whether the timer must run on one specific CPU or not. */
+    bool                    fSpecificCpu;
+#ifdef CONFIG_SMP
+    /** Whether the timer must run on all CPUs or not. */
+    bool                    fAllCpus;
+#endif /* else: All -> specific on non-SMP kernels */
+    /** Whether it is a high resolution timer or a standard one. */
+    bool                    fHighRes;
+    /** The id of the CPU it must run on if fSpecificCpu is set. */
+    RTCPUID                 idCpu;
+    /** The number of CPUs this timer should run on. */
+    RTCPUID                 cCpus;
+    /** Callback. */
+    PFNRTTIMER              pfnTimer;
+    /** User argument. */
+    void                   *pvUser;
+    /** The timer interval. 0 if one-shot. */
+    uint64_t volatile       u64NanoInterval;
+    /** This is set to the number of jiffies between ticks if the interval is
+     * an exact number of jiffies. (Standard timers only.) */
+    unsigned long volatile  cJiffies;
+    /** The change interval spinlock for standard timers only. */
+    spinlock_t              ChgIntLock;
+    /** Workqueue item for delayed destruction. */
+    RTR0LNXWORKQUEUEITEM    DtorWorkqueueItem;
+    /** Sub-timers.
+     * Normally there is just one, but for RTTIMER_FLAGS_CPU_ALL this will contain
+     * an entry for all possible cpus. In that case the index will be the same as
+     * for the RTCpuSet. */
+    RTTIMERLNXSUBTIMER      aSubTimers[1];
+} RTTIMER;
+
+
+/**
+ * A rtTimerLinuxStartOnCpu and rtTimerLinuxStartOnCpu argument package.
+ */
+typedef struct RTTIMERLINUXSTARTONCPUARGS
+{
+    /** The current time (RTTimeSystemNanoTS). */
+    uint64_t                u64Now;
+    /** When to start firing (delta). */
+    uint64_t                u64First;
+} RTTIMERLINUXSTARTONCPUARGS;
+/** Pointer to a rtTimerLinuxStartOnCpu argument package. */
+typedef RTTIMERLINUXSTARTONCPUARGS *PRTTIMERLINUXSTARTONCPUARGS;
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+#ifdef CONFIG_SMP
+static DECLCALLBACK(void) rtTimerLinuxMpEvent(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvUser);
+#endif
+
+#if 0
+#define DEBUG_HACKING
+#include <iprt/string.h>
+#include <iprt/asm-amd64-x86.h>
+static void myLogBackdoorPrintf(const char *pszFormat, ...)
+{
+    char        szTmp[256];
+    va_list     args;
+    size_t      cb;
+
+    cb = RTStrPrintf(szTmp, sizeof(szTmp) - 10, "%d: ", RTMpCpuId());
+    va_start(args, pszFormat);
+    cb += RTStrPrintfV(&szTmp[cb], sizeof(szTmp) - cb, pszFormat, args);
+    va_end(args);
+
+    ASMOutStrU8(0x504, (uint8_t *)&szTmp[0], cb);
+}
+# define RTAssertMsg1Weak(pszExpr, uLine, pszFile, pszFunction) \
+    myLogBackdoorPrintf("\n!!Guest Assertion failed!!\n%s(%d) %s\n%s\n", uLine, pszFile, pszFunction, (pszExpr))
+# define RTAssertMsg2Weak myLogBackdoorPrintf
+# define RTTIMERLNX_LOG(a)          myLogBackdoorPrintf a
+#else
+# define RTTIMERLNX_LOG(a)          do { } while (0)
+#endif
+
+/**
+ * Sets the state.
+ */
+DECLINLINE(void) rtTimerLnxSetState(RTTIMERLNXSTATE volatile *penmState, RTTIMERLNXSTATE enmNewState)
+{
+#ifdef DEBUG_HACKING
+    RTTIMERLNX_LOG(("set %d -> %d\n", *penmState, enmNewState));
+#endif
+    ASMAtomicWriteU32((uint32_t volatile *)penmState, enmNewState);
+}
+
+
+/**
+ * Sets the state if it has a certain value.
+ *
+ * @return true if xchg was done.
+ * @return false if xchg wasn't done.
+ */
+#ifdef DEBUG_HACKING
+#define rtTimerLnxCmpXchgState(penmState, enmNewState, enmCurState) rtTimerLnxCmpXchgStateDebug(penmState, enmNewState, enmCurState, __LINE__)
+static bool rtTimerLnxCmpXchgStateDebug(RTTIMERLNXSTATE volatile *penmState, RTTIMERLNXSTATE enmNewState,
+                                        RTTIMERLNXSTATE enmCurState, uint32_t uLine)
+{
+    RTTIMERLNXSTATE enmOldState = enmCurState;
+    bool fRc = ASMAtomicCmpXchgExU32((uint32_t volatile *)penmState, enmNewState, enmCurState, (uint32_t *)&enmOldState);
+    RTTIMERLNX_LOG(("cxg %d -> %d - %d at %u\n", enmOldState, enmNewState, fRc, uLine));
+    return fRc;
+}
+#else
+DECLINLINE(bool) rtTimerLnxCmpXchgState(RTTIMERLNXSTATE volatile *penmState, RTTIMERLNXSTATE enmNewState,
+                                        RTTIMERLNXSTATE enmCurState)
+{
+    return ASMAtomicCmpXchgU32((uint32_t volatile *)penmState, enmNewState, enmCurState);
+}
+#endif
+
+
+/**
+ * Gets the state.
+ */
+DECLINLINE(RTTIMERLNXSTATE) rtTimerLnxGetState(RTTIMERLNXSTATE volatile *penmState)
+{
+    return (RTTIMERLNXSTATE)ASMAtomicUoReadU32((uint32_t volatile *)penmState);
+}
+
+#ifdef RTTIMER_LINUX_WITH_HRTIMER
+
+/**
+ * Converts a nano second time stamp to ktime_t.
+ *
+ * ASSUMES RTTimeSystemNanoTS() is implemented using ktime_get_ts().
+ *
+ * @returns ktime_t.
+ * @param   cNanoSecs   Nanoseconds.
+ */
+DECLINLINE(ktime_t) rtTimerLnxNanoToKt(uint64_t cNanoSecs)
+{
+    /* With some luck the compiler optimizes the division out of this... (Bet it doesn't.) */
+    return ktime_set(cNanoSecs / 1000000000, cNanoSecs % 1000000000);
+}
+
+/**
+ * Converts ktime_t to a nano second time stamp.
+ *
+ * ASSUMES RTTimeSystemNanoTS() is implemented using ktime_get_ts().
+ *
+ * @returns nano second time stamp.
+ * @param   Kt          ktime_t.
+ */
+DECLINLINE(uint64_t) rtTimerLnxKtToNano(ktime_t Kt)
+{
+    return ktime_to_ns(Kt);
+}
+
+#endif /* RTTIMER_LINUX_WITH_HRTIMER */
+
+/**
+ * Converts a nano second interval to jiffies.
+ *
+ * @returns Jiffies.
+ * @param   cNanoSecs   Nanoseconds.
+ */
+DECLINLINE(unsigned long) rtTimerLnxNanoToJiffies(uint64_t cNanoSecs)
+{
+    /* this can be made even better... */
+    if (cNanoSecs > (uint64_t)TICK_NSEC * MAX_JIFFY_OFFSET)
+        return MAX_JIFFY_OFFSET;
+# if ARCH_BITS == 32
+    if (RT_LIKELY(cNanoSecs <= UINT32_MAX))
+        return ((uint32_t)cNanoSecs + (TICK_NSEC-1)) / TICK_NSEC;
+# endif
+    return (cNanoSecs + (TICK_NSEC-1)) / TICK_NSEC;
+}
+
+
+/**
+ * Starts a sub-timer (RTTimerStart).
+ *
+ * @param   pSubTimer   The sub-timer to start.
+ * @param   u64Now      The current timestamp (RTTimeSystemNanoTS()).
+ * @param   u64First    The interval from u64Now to the first time the timer should fire.
+ * @param   fPinned     true = timer pinned to a specific CPU,
+ *                      false = timer can migrate between CPUs
+ * @param   fHighRes    Whether the user requested a high resolution timer or not.
+ * @param   enmOldState The old timer state.
+ */
+static void rtTimerLnxStartSubTimer(PRTTIMERLNXSUBTIMER pSubTimer, uint64_t u64Now, uint64_t u64First,
+                                    bool fPinned, bool fHighRes)
+{
+    /*
+     * Calc when it should start firing.
+     */
+    uint64_t u64NextTS = u64Now + u64First;
+    if (!fHighRes)
+        pSubTimer->u.Std.u64NextTS = u64NextTS;
+    RTTIMERLNX_LOG(("startsubtimer %p\n", pSubTimer->pParent));
+
+    pSubTimer->iTick = 0;
+
+#ifdef RTTIMER_LINUX_WITH_HRTIMER
+    if (fHighRes)
+        hrtimer_start(&pSubTimer->u.Hr.LnxTimer, rtTimerLnxNanoToKt(u64NextTS),
+                      fPinned ? HRTIMER_MODE_ABS_PINNED : HRTIMER_MODE_ABS);
+    else
+#endif
+    {
+        unsigned long cJiffies = !u64First ? 0 : rtTimerLnxNanoToJiffies(u64First);
+        pSubTimer->u.Std.ulNextJiffies  = jiffies + cJiffies;
+        pSubTimer->u.Std.fFirstAfterChg = true;
+#ifdef CONFIG_SMP
+        if (fPinned)
+        {
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
+            mod_timer(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies);
+# else
+            mod_timer_pinned(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies);
+# endif
+        }
+        else
+#endif
+            mod_timer(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies);
+    }
+
+    /* Be a bit careful here since we could be racing the callback. */
+    if (!rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_ACTIVE, RTTIMERLNXSTATE_STARTING))
+        rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_ACTIVE, RTTIMERLNXSTATE_MP_STARTING);
+}
+
+
+/**
+ * Stops a sub-timer (RTTimerStart and rtTimerLinuxMpEvent()).
+ *
+ * The caller has already changed the state, so we will not be in a callback
+ * situation wrt to the calling thread.
+ *
+ * @param   pSubTimer   The sub-timer.
+ * @param   fHighRes    Whether the user requested a high resolution timer or not.
+ */
+static void rtTimerLnxStopSubTimer(PRTTIMERLNXSUBTIMER pSubTimer, bool fHighRes)
+{
+    RTTIMERLNX_LOG(("stopsubtimer %p %d\n", pSubTimer->pParent, fHighRes));
+#ifdef RTTIMER_LINUX_WITH_HRTIMER
+    if (fHighRes)
+    {
+        /* There is no equivalent to del_timer in the hrtimer API,
+           hrtimer_cancel() == del_timer_sync().  Just like the WARN_ON in
+           del_timer_sync() asserts, waiting for a timer callback to complete
+           is deadlock prone, so don't do it.  */
+        int rc = hrtimer_try_to_cancel(&pSubTimer->u.Hr.LnxTimer);
+        if (rc < 0)
+        {
+            hrtimer_start(&pSubTimer->u.Hr.LnxTimer, ktime_set(KTIME_SEC_MAX, 0), HRTIMER_MODE_ABS);
+            hrtimer_try_to_cancel(&pSubTimer->u.Hr.LnxTimer);
+        }
+    }
+    else
+#endif
+        del_timer(&pSubTimer->u.Std.LnxTimer);
+
+    rtTimerLnxSetState(&pSubTimer->enmState, RTTIMERLNXSTATE_STOPPED);
+}
+
+
+/**
+ * Used by RTTimerDestroy and rtTimerLnxCallbackDestroy to do the actual work.
+ *
+ * @param   pTimer  The timer in question.
+ */
+static void rtTimerLnxDestroyIt(PRTTIMER pTimer)
+{
+    RTSPINLOCK  hSpinlock = pTimer->hSpinlock;
+    RTCPUID     iCpu;
+    Assert(pTimer->fSuspended);
+    RTTIMERLNX_LOG(("destroyit %p\n", pTimer));
+
+    /*
+     * Remove the MP notifications first because it'll reduce the risk of
+     * us overtaking any MP event that might theoretically be racing us here.
+     */
+#ifdef CONFIG_SMP
+    if (    pTimer->cCpus > 1
+        &&  hSpinlock != NIL_RTSPINLOCK)
+    {
+        int rc = RTMpNotificationDeregister(rtTimerLinuxMpEvent, pTimer);
+        AssertRC(rc);
+    }
+#endif /* CONFIG_SMP */
+
+    /*
+     * Invalidate the handle.
+     */
+    ASMAtomicWriteU32(&pTimer->u32Magic, ~RTTIMER_MAGIC);
+
+    /*
+     * Make sure all timers have stopped executing since we're stopping them in
+     * an asynchronous manner up in rtTimerLnxStopSubTimer.
+     */
+    iCpu = pTimer->cCpus;
+    while (iCpu-- > 0)
+    {
+#ifdef RTTIMER_LINUX_WITH_HRTIMER
+        if (pTimer->fHighRes)
+            hrtimer_cancel(&pTimer->aSubTimers[iCpu].u.Hr.LnxTimer);
+        else
+#endif
+            del_timer_sync(&pTimer->aSubTimers[iCpu].u.Std.LnxTimer);
+    }
+
+    /*
+     * Finally, free the resources.
+     */
+    RTMemFreeEx(pTimer, RT_OFFSETOF(RTTIMER, aSubTimers[pTimer->cCpus]));
+    if (hSpinlock != NIL_RTSPINLOCK)
+        RTSpinlockDestroy(hSpinlock);
+}
+
+
+/**
+ * Workqueue callback (no DECLCALLBACK!) for deferred destruction.
+ *
+ * @param   pWork        Pointer to the DtorWorkqueueItem member of our timer
+ *                       structure.
+ */
+static void rtTimerLnxDestroyDeferred(RTR0LNXWORKQUEUEITEM *pWork)
+{
+    PRTTIMER pTimer = RT_FROM_MEMBER(pWork, RTTIMER, DtorWorkqueueItem);
+    rtTimerLnxDestroyIt(pTimer);
+}
+
+
+/**
+ * Called when the timer was destroyed by the callback function.
+ *
+ * @param   pTimer      The timer.
+ * @param   pSubTimer   The sub-timer which we're handling, the state of this
+ *                      will be RTTIMERLNXSTATE_CALLBACK_DESTROYING.
+ */
+static void rtTimerLnxCallbackDestroy(PRTTIMER pTimer, PRTTIMERLNXSUBTIMER pSubTimer)
+{
+    /*
+     * If it's an omni timer, the last dude does the destroying.
+     */
+    if (pTimer->cCpus > 1)
+    {
+        uint32_t        iCpu        = pTimer->cCpus;
+        RTSpinlockAcquire(pTimer->hSpinlock);
+
+        Assert(pSubTimer->enmState == RTTIMERLNXSTATE_CB_DESTROYING);
+        rtTimerLnxSetState(&pSubTimer->enmState, RTTIMERLNXSTATE_STOPPED);
+
+        while (iCpu-- > 0)
+            if (rtTimerLnxGetState(&pTimer->aSubTimers[iCpu].enmState) != RTTIMERLNXSTATE_STOPPED)
+            {
+                RTSpinlockRelease(pTimer->hSpinlock);
+                return;
+            }
+
+        RTSpinlockRelease(pTimer->hSpinlock);
+    }
+
+    /*
+     * Destroying a timer from the callback is unsafe since the callout code
+     * might be touching the timer structure upon return (hrtimer does!).  So,
+     * we have to defer the actual destruction to the IRPT workqueue.
+     */
+    rtR0LnxWorkqueuePush(&pTimer->DtorWorkqueueItem, rtTimerLnxDestroyDeferred);
+}
+
+
+#ifdef CONFIG_SMP
+/**
+ * Deal with a sub-timer that has migrated.
+ *
+ * @param   pTimer          The timer.
+ * @param   pSubTimer       The sub-timer.
+ */
+static void rtTimerLnxCallbackHandleMigration(PRTTIMER pTimer, PRTTIMERLNXSUBTIMER pSubTimer)
+{
+    RTTIMERLNXSTATE enmState;
+    if (pTimer->cCpus > 1)
+        RTSpinlockAcquire(pTimer->hSpinlock);
+
+    do
+    {
+        enmState = rtTimerLnxGetState(&pSubTimer->enmState);
+        switch (enmState)
+        {
+            case RTTIMERLNXSTATE_STOPPING:
+            case RTTIMERLNXSTATE_MP_STOPPING:
+                enmState = RTTIMERLNXSTATE_STOPPED;
+            case RTTIMERLNXSTATE_STOPPED:
+                break;
+
+            default:
+                AssertMsgFailed(("%d\n", enmState));
+            case RTTIMERLNXSTATE_STARTING:
+            case RTTIMERLNXSTATE_MP_STARTING:
+            case RTTIMERLNXSTATE_ACTIVE:
+            case RTTIMERLNXSTATE_CALLBACK:
+            case RTTIMERLNXSTATE_CB_STOPPING:
+            case RTTIMERLNXSTATE_CB_RESTARTING:
+                if (rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_STOPPED, enmState))
+                    enmState = RTTIMERLNXSTATE_STOPPED;
+                break;
+
+            case RTTIMERLNXSTATE_CB_DESTROYING:
+            {
+                if (pTimer->cCpus > 1)
+                    RTSpinlockRelease(pTimer->hSpinlock);
+
+                rtTimerLnxCallbackDestroy(pTimer, pSubTimer);
+                return;
+            }
+        }
+    } while (enmState != RTTIMERLNXSTATE_STOPPED);
+
+    if (pTimer->cCpus > 1)
+        RTSpinlockRelease(pTimer->hSpinlock);
+}
+#endif /* CONFIG_SMP */
+
+
+/**
+ * The slow path of rtTimerLnxChangeToCallbackState.
+ *
+ * @returns true if changed successfully, false if not.
+ * @param   pSubTimer       The sub-timer.
+ */
+static bool rtTimerLnxChangeToCallbackStateSlow(PRTTIMERLNXSUBTIMER pSubTimer)
+{
+    for (;;)
+    {
+        RTTIMERLNXSTATE enmState = rtTimerLnxGetState(&pSubTimer->enmState);
+        switch (enmState)
+        {
+            case RTTIMERLNXSTATE_ACTIVE:
+            case RTTIMERLNXSTATE_STARTING:
+            case RTTIMERLNXSTATE_MP_STARTING:
+                if (rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_CALLBACK, enmState))
+                    return true;
+                break;
+
+            case RTTIMERLNXSTATE_CALLBACK:
+            case RTTIMERLNXSTATE_CB_STOPPING:
+            case RTTIMERLNXSTATE_CB_RESTARTING:
+            case RTTIMERLNXSTATE_CB_DESTROYING:
+                AssertMsgFailed(("%d\n", enmState));
+            default:
+                return false;
+        }
+        ASMNopPause();
+    }
+}
+
+
+/**
+ * Tries to change the sub-timer state to 'callback'.
+ *
+ * @returns true if changed successfully, false if not.
+ * @param   pSubTimer       The sub-timer.
+ */
+DECLINLINE(bool) rtTimerLnxChangeToCallbackState(PRTTIMERLNXSUBTIMER pSubTimer)
+{
+    if (RT_LIKELY(rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_CALLBACK, RTTIMERLNXSTATE_ACTIVE)))
+        return true;
+    return rtTimerLnxChangeToCallbackStateSlow(pSubTimer);
+}
+
+
+#ifdef RTTIMER_LINUX_WITH_HRTIMER
+/**
+ * Timer callback function for high resolution timers.
+ *
+ * @returns HRTIMER_NORESTART or HRTIMER_RESTART depending on whether it's a
+ *          one-shot or interval timer.
+ * @param   pHrTimer    Pointer to the sub-timer structure.
+ */
+static enum hrtimer_restart rtTimerLinuxHrCallback(struct hrtimer *pHrTimer)
+{
+    PRTTIMERLNXSUBTIMER     pSubTimer = RT_FROM_MEMBER(pHrTimer, RTTIMERLNXSUBTIMER, u.Hr.LnxTimer);
+    PRTTIMER                pTimer    = pSubTimer->pParent;
+
+
+    RTTIMERLNX_LOG(("hrcallback %p\n", pTimer));
+    if (RT_UNLIKELY(!rtTimerLnxChangeToCallbackState(pSubTimer)))
+        return HRTIMER_NORESTART;
+
+#ifdef CONFIG_SMP
+    /*
+     * Check for unwanted migration.
+     */
+    if (pTimer->fAllCpus || pTimer->fSpecificCpu)
+    {
+        RTCPUID idCpu = RTMpCpuId();
+        if (RT_UNLIKELY(  pTimer->fAllCpus
+                        ? (RTCPUID)(pSubTimer - &pTimer->aSubTimers[0]) != idCpu
+                        : pTimer->idCpu != idCpu))
+        {
+            rtTimerLnxCallbackHandleMigration(pTimer, pSubTimer);
+            return HRTIMER_NORESTART;
+        }
+    }
+#endif
+
+    if (pTimer->u64NanoInterval)
+    {
+        /*
+         * Periodic timer, run it and update the native timer afterwards so
+         * we can handle RTTimerStop and RTTimerChangeInterval from the
+         * callback as well as a racing control thread.
+         */
+        pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pSubTimer->iTick);
+        hrtimer_add_expires_ns(&pSubTimer->u.Hr.LnxTimer, ASMAtomicReadU64(&pTimer->u64NanoInterval));
+        if (RT_LIKELY(rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_ACTIVE, RTTIMERLNXSTATE_CALLBACK)))
+            return HRTIMER_RESTART;
+    }
+    else
+    {
+        /*
+         * One shot timer (no omni), stop it before dispatching it.
+         * Allow RTTimerStart as well as RTTimerDestroy to be called from
+         * the callback.
+         */
+        ASMAtomicWriteBool(&pTimer->fSuspended, true);
+        pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pSubTimer->iTick);
+        if (RT_LIKELY(rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_STOPPED, RTTIMERLNXSTATE_CALLBACK)))
+            return HRTIMER_NORESTART;
+    }
+
+    /*
+     * Some state change occurred while we were in the callback routine.
+     */
+    for (;;)
+    {
+        RTTIMERLNXSTATE enmState = rtTimerLnxGetState(&pSubTimer->enmState);
+        switch (enmState)
+        {
+            case RTTIMERLNXSTATE_CB_DESTROYING:
+                rtTimerLnxCallbackDestroy(pTimer, pSubTimer);
+                return HRTIMER_NORESTART;
+
+            case RTTIMERLNXSTATE_CB_STOPPING:
+                if (rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_STOPPED, RTTIMERLNXSTATE_CB_STOPPING))
+                    return HRTIMER_NORESTART;
+                break;
+
+            case RTTIMERLNXSTATE_CB_RESTARTING:
+                if (rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_ACTIVE, RTTIMERLNXSTATE_CB_RESTARTING))
+                {
+                    pSubTimer->iTick = 0;
+                    hrtimer_set_expires(&pSubTimer->u.Hr.LnxTimer, rtTimerLnxNanoToKt(pSubTimer->uNsRestartAt));
+                    return HRTIMER_RESTART;
+                }
+                break;
+
+            default:
+                AssertMsgFailed(("%d\n", enmState));
+                return HRTIMER_NORESTART;
+        }
+        ASMNopPause();
+    }
+}
+#endif /* RTTIMER_LINUX_WITH_HRTIMER */
+
+
+/**
+ * Timer callback function for standard timers.
+ *
+ * @param   ulUser      Address of the sub-timer structure.
+ */
+static void rtTimerLinuxStdCallback(unsigned long ulUser)
+{
+    PRTTIMERLNXSUBTIMER pSubTimer = (PRTTIMERLNXSUBTIMER)ulUser;
+    PRTTIMER            pTimer    = pSubTimer->pParent;
+
+    RTTIMERLNX_LOG(("stdcallback %p\n", pTimer));
+    if (RT_UNLIKELY(!rtTimerLnxChangeToCallbackState(pSubTimer)))
+        return;
+
+#ifdef CONFIG_SMP
+    /*
+     * Check for unwanted migration.
+     */
+    if (pTimer->fAllCpus || pTimer->fSpecificCpu)
+    {
+        RTCPUID idCpu = RTMpCpuId();
+        if (RT_UNLIKELY(  pTimer->fAllCpus
+                        ? (RTCPUID)(pSubTimer - &pTimer->aSubTimers[0]) != idCpu
+                        : pTimer->idCpu != idCpu))
+        {
+            rtTimerLnxCallbackHandleMigration(pTimer, pSubTimer);
+            return;
+        }
+    }
+#endif
+
+    if (pTimer->u64NanoInterval)
+    {
+        /*
+         * Interval timer, calculate the next timeout.
+         *
+         * The first time around, we'll re-adjust the u.Std.u64NextTS to
+         * try prevent some jittering if we were started at a bad time.
+         */
+        const uint64_t  iTick = ++pSubTimer->iTick;
+        uint64_t        u64NanoInterval;
+        unsigned long   cJiffies;
+        unsigned long   flFlags;
+
+        spin_lock_irqsave(&pTimer->ChgIntLock, flFlags);
+        u64NanoInterval = pTimer->u64NanoInterval;
+        cJiffies        = pTimer->cJiffies;
+        if (RT_UNLIKELY(pSubTimer->u.Std.fFirstAfterChg))
+        {
+            pSubTimer->u.Std.fFirstAfterChg = false;
+            pSubTimer->u.Std.u64NextTS      = RTTimeSystemNanoTS();
+            pSubTimer->u.Std.ulNextJiffies  = jiffies;
+        }
+        spin_unlock_irqrestore(&pTimer->ChgIntLock, flFlags);
+
+        pSubTimer->u.Std.u64NextTS += u64NanoInterval;
+        if (cJiffies)
+        {
+            pSubTimer->u.Std.ulNextJiffies += cJiffies;
+            /* Prevent overflows when the jiffies counter wraps around.
+             * Special thanks to Ken Preslan for helping debugging! */
+            while (time_before(pSubTimer->u.Std.ulNextJiffies, jiffies))
+            {
+                pSubTimer->u.Std.ulNextJiffies += cJiffies;
+                pSubTimer->u.Std.u64NextTS     += u64NanoInterval;
+            }
+        }
+        else
+        {
+            const uint64_t u64NanoTS = RTTimeSystemNanoTS();
+            while (pSubTimer->u.Std.u64NextTS < u64NanoTS)
+                pSubTimer->u.Std.u64NextTS += u64NanoInterval;
+            pSubTimer->u.Std.ulNextJiffies = jiffies + rtTimerLnxNanoToJiffies(pSubTimer->u.Std.u64NextTS - u64NanoTS);
+        }
+
+        /*
+         * Run the timer and re-arm it unless the state changed                                                                                                        .
+         *                                                                                                                                                             .
+         * We must re-arm it afterwards as we're not in a position to undo this                                                                                        .
+         * operation if for instance someone stopped or destroyed us while we                                                                                          .
+         * were in the callback.  (Linux takes care of any races here.)
+         */
+        pTimer->pfnTimer(pTimer, pTimer->pvUser, iTick);
+        if (RT_LIKELY(rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_ACTIVE, RTTIMERLNXSTATE_CALLBACK)))
+        {
+#ifdef CONFIG_SMP
+            if (pTimer->fSpecificCpu || pTimer->fAllCpus)
+            {
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
+                mod_timer(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies);
+# else
+                mod_timer_pinned(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies);
+# endif
+            }
+            else
+#endif
+                mod_timer(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies);
+            return;
+        }
+    }
+    else
+    {
+        /*
+         * One shot timer, stop it before dispatching it.
+         * Allow RTTimerStart as well as RTTimerDestroy to be called from
+         * the callback.
+         */
+        ASMAtomicWriteBool(&pTimer->fSuspended, true);
+        pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pSubTimer->iTick);
+        if (RT_LIKELY(rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_STOPPED, RTTIMERLNXSTATE_CALLBACK)))
+            return;
+    }
+
+    /*
+     * Some state change occurred while we were in the callback routine.
+     */
+    for (;;)
+    {
+        RTTIMERLNXSTATE enmState = rtTimerLnxGetState(&pSubTimer->enmState);
+        switch (enmState)
+        {
+            case RTTIMERLNXSTATE_CB_DESTROYING:
+                rtTimerLnxCallbackDestroy(pTimer, pSubTimer);
+                return;
+
+            case RTTIMERLNXSTATE_CB_STOPPING:
+                if (rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_STOPPED, RTTIMERLNXSTATE_CB_STOPPING))
+                    return;
+                break;
+
+            case RTTIMERLNXSTATE_CB_RESTARTING:
+                if (rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_ACTIVE, RTTIMERLNXSTATE_CB_RESTARTING))
+                {
+                    uint64_t        u64NanoTS;
+                    uint64_t        u64NextTS;
+                    unsigned long   flFlags;
+
+                    spin_lock_irqsave(&pTimer->ChgIntLock, flFlags);
+                    u64NextTS = pSubTimer->uNsRestartAt;
+                    u64NanoTS = RTTimeSystemNanoTS();
+                    pSubTimer->iTick                = 0;
+                    pSubTimer->u.Std.u64NextTS      = u64NextTS;
+                    pSubTimer->u.Std.fFirstAfterChg = true;
+                    pSubTimer->u.Std.ulNextJiffies  = u64NextTS > u64NanoTS
+                                                    ? jiffies + rtTimerLnxNanoToJiffies(u64NextTS - u64NanoTS)
+                                                    : jiffies;
+                    spin_unlock_irqrestore(&pTimer->ChgIntLock, flFlags);
+
+#ifdef CONFIG_SMP
+                    if (pTimer->fSpecificCpu || pTimer->fAllCpus)
+                    {
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
+                        mod_timer(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies);
+# else
+                        mod_timer_pinned(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies);
+# endif
+                    }
+                    else
+#endif
+                        mod_timer(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies);
+                    return;
+                }
+                break;
+
+            default:
+                AssertMsgFailed(("%d\n", enmState));
+                return;
+        }
+        ASMNopPause();
+    }
+}
+
+
+#ifdef CONFIG_SMP
+
+/**
+ * Per-cpu callback function (RTMpOnAll/RTMpOnSpecific).
+ *
+ * @param   idCpu       The current CPU.
+ * @param   pvUser1     Pointer to the timer.
+ * @param   pvUser2     Pointer to the argument structure.
+ */
+static DECLCALLBACK(void) rtTimerLnxStartAllOnCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
+{
+    PRTTIMERLINUXSTARTONCPUARGS pArgs = (PRTTIMERLINUXSTARTONCPUARGS)pvUser2;
+    PRTTIMER pTimer = (PRTTIMER)pvUser1;
+    Assert(idCpu < pTimer->cCpus);
+    rtTimerLnxStartSubTimer(&pTimer->aSubTimers[idCpu], pArgs->u64Now, pArgs->u64First, true /*fPinned*/, pTimer->fHighRes);
+}
+
+
+/**
+ * Worker for RTTimerStart() that takes care of the ugly bits.
+ *
+ * @returns RTTimerStart() return value.
+ * @param   pTimer      The timer.
+ * @param   pArgs       The argument structure.
+ */
+static int rtTimerLnxOmniStart(PRTTIMER pTimer, PRTTIMERLINUXSTARTONCPUARGS pArgs)
+{
+    RTCPUID         iCpu;
+    RTCPUSET        OnlineSet;
+    RTCPUSET        OnlineSet2;
+    int             rc2;
+
+    /*
+     * Prepare all the sub-timers for the startup and then flag the timer
+     * as a whole as non-suspended, make sure we get them all before
+     * clearing fSuspended as the MP handler will be waiting on this
+     * should something happen while we're looping.
+     */
+    RTSpinlockAcquire(pTimer->hSpinlock);
+
+    /* Just make it a omni timer restriction that no stop/start races are allowed. */
+    for (iCpu = 0; iCpu < pTimer->cCpus; iCpu++)
+        if (rtTimerLnxGetState(&pTimer->aSubTimers[iCpu].enmState) != RTTIMERLNXSTATE_STOPPED)
+        {
+            RTSpinlockRelease(pTimer->hSpinlock);
+            return VERR_TIMER_BUSY;
+        }
+
+    do
+    {
+        RTMpGetOnlineSet(&OnlineSet);
+        for (iCpu = 0; iCpu < pTimer->cCpus; iCpu++)
+        {
+            Assert(pTimer->aSubTimers[iCpu].enmState != RTTIMERLNXSTATE_MP_STOPPING);
+            rtTimerLnxSetState(&pTimer->aSubTimers[iCpu].enmState,
+                               RTCpuSetIsMember(&OnlineSet, iCpu)
+                               ? RTTIMERLNXSTATE_STARTING
+                               : RTTIMERLNXSTATE_STOPPED);
+        }
+    } while (!RTCpuSetIsEqual(&OnlineSet, RTMpGetOnlineSet(&OnlineSet2)));
+
+    ASMAtomicWriteBool(&pTimer->fSuspended, false);
+
+    RTSpinlockRelease(pTimer->hSpinlock);
+
+    /*
+     * Start them (can't find any exported function that allows me to
+     * do this without the cross calls).
+     */
+    pArgs->u64Now = RTTimeSystemNanoTS();
+    rc2 = RTMpOnAll(rtTimerLnxStartAllOnCpu, pTimer, pArgs);
+    AssertRC(rc2); /* screw this if it fails. */
+
+    /*
+     * Reset the sub-timers who didn't start up (ALL CPUs case).
+     */
+    RTSpinlockAcquire(pTimer->hSpinlock);
+
+    for (iCpu = 0; iCpu < pTimer->cCpus; iCpu++)
+        if (rtTimerLnxCmpXchgState(&pTimer->aSubTimers[iCpu].enmState, RTTIMERLNXSTATE_STOPPED, RTTIMERLNXSTATE_STARTING))
+        {
+            /** @todo very odd case for a rainy day. Cpus that temporarily went offline while
+             * we were between calls needs to nudged as the MP handler will ignore events for
+             * them because of the STARTING state. This is an extremely unlikely case - not that
+             * that means anything in my experience... ;-) */
+            RTTIMERLNX_LOG(("what!? iCpu=%u -> didn't start\n", iCpu));
+        }
+
+    RTSpinlockRelease(pTimer->hSpinlock);
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Worker for RTTimerStop() that takes care of the ugly SMP bits.
+ *
+ * @returns true if there was any active callbacks, false if not.
+ * @param   pTimer      The timer (valid).
+ * @param   fForDestroy Whether this is for RTTimerDestroy or not.
+ */
+static bool rtTimerLnxOmniStop(PRTTIMER pTimer, bool fForDestroy)
+{
+    bool            fActiveCallbacks = false;
+    RTCPUID         iCpu;
+    RTTIMERLNXSTATE enmState;
+
+
+    /*
+     * Mark the timer as suspended and flag all timers as stopping, except
+     * for those being stopped by an MP event.
+     */
+    RTSpinlockAcquire(pTimer->hSpinlock);
+
+    ASMAtomicWriteBool(&pTimer->fSuspended, true);
+    for (iCpu = 0; iCpu < pTimer->cCpus; iCpu++)
+    {
+        for (;;)
+        {
+            enmState = rtTimerLnxGetState(&pTimer->aSubTimers[iCpu].enmState);
+            if (    enmState == RTTIMERLNXSTATE_STOPPED
+                ||  enmState == RTTIMERLNXSTATE_MP_STOPPING)
+                break;
+            if (   enmState == RTTIMERLNXSTATE_CALLBACK
+                || enmState == RTTIMERLNXSTATE_CB_STOPPING
+                || enmState == RTTIMERLNXSTATE_CB_RESTARTING)
+            {
+                Assert(enmState != RTTIMERLNXSTATE_CB_STOPPING || fForDestroy);
+                if (rtTimerLnxCmpXchgState(&pTimer->aSubTimers[iCpu].enmState,
+                                           !fForDestroy ? RTTIMERLNXSTATE_CB_STOPPING : RTTIMERLNXSTATE_CB_DESTROYING,
+                                           enmState))
+                {
+                    fActiveCallbacks = true;
+                    break;
+                }
+            }
+            else
+            {
+                Assert(enmState == RTTIMERLNXSTATE_ACTIVE);
+                if (rtTimerLnxCmpXchgState(&pTimer->aSubTimers[iCpu].enmState, RTTIMERLNXSTATE_STOPPING, enmState))
+                    break;
+            }
+            ASMNopPause();
+        }
+    }
+
+    RTSpinlockRelease(pTimer->hSpinlock);
+
+    /*
+     * Do the actual stopping. Fortunately, this doesn't require any IPIs.
+     * Unfortunately it cannot be done synchronously.
+     */
+    for (iCpu = 0; iCpu < pTimer->cCpus; iCpu++)
+        if (rtTimerLnxGetState(&pTimer->aSubTimers[iCpu].enmState) == RTTIMERLNXSTATE_STOPPING)
+            rtTimerLnxStopSubTimer(&pTimer->aSubTimers[iCpu], pTimer->fHighRes);
+
+    return fActiveCallbacks;
+}
+
+
+/**
+ * Per-cpu callback function (RTMpOnSpecific) used by rtTimerLinuxMpEvent()
+ * to start a sub-timer on a cpu that just have come online.
+ *
+ * @param   idCpu       The current CPU.
+ * @param   pvUser1     Pointer to the timer.
+ * @param   pvUser2     Pointer to the argument structure.
+ */
+static DECLCALLBACK(void) rtTimerLinuxMpStartOnCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
+{
+    PRTTIMERLINUXSTARTONCPUARGS pArgs = (PRTTIMERLINUXSTARTONCPUARGS)pvUser2;
+    PRTTIMER pTimer = (PRTTIMER)pvUser1;
+    RTSPINLOCK hSpinlock;
+    Assert(idCpu < pTimer->cCpus);
+
+    /*
+     * We have to be kind of careful here as we might be racing RTTimerStop
+     * (and/or RTTimerDestroy, thus the paranoia.
+     */
+    hSpinlock = pTimer->hSpinlock;
+    if (    hSpinlock != NIL_RTSPINLOCK
+        &&  pTimer->u32Magic == RTTIMER_MAGIC)
+    {
+        RTSpinlockAcquire(hSpinlock);
+
+        if (    !ASMAtomicUoReadBool(&pTimer->fSuspended)
+            &&  pTimer->u32Magic == RTTIMER_MAGIC)
+        {
+            /* We're sane and the timer is not suspended yet. */
+            PRTTIMERLNXSUBTIMER pSubTimer = &pTimer->aSubTimers[idCpu];
+            if (rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_MP_STARTING, RTTIMERLNXSTATE_STOPPED))
+                rtTimerLnxStartSubTimer(pSubTimer, pArgs->u64Now, pArgs->u64First, true /*fPinned*/, pTimer->fHighRes);
+        }
+
+        RTSpinlockRelease(hSpinlock);
+    }
+}
+
+
+/**
+ * MP event notification callback.
+ *
+ * @param   enmEvent    The event.
+ * @param   idCpu       The cpu it applies to.
+ * @param   pvUser      The timer.
+ */
+static DECLCALLBACK(void) rtTimerLinuxMpEvent(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvUser)
+{
+    PRTTIMER            pTimer    = (PRTTIMER)pvUser;
+    PRTTIMERLNXSUBTIMER pSubTimer = &pTimer->aSubTimers[idCpu];
+    RTSPINLOCK          hSpinlock;
+
+    Assert(idCpu < pTimer->cCpus);
+
+    /*
+     * Some initial paranoia.
+     */
+    if (pTimer->u32Magic != RTTIMER_MAGIC)
+        return;
+    hSpinlock = pTimer->hSpinlock;
+    if (hSpinlock == NIL_RTSPINLOCK)
+        return;
+
+    RTSpinlockAcquire(hSpinlock);
+
+    /* Is it active? */
+    if (    !ASMAtomicUoReadBool(&pTimer->fSuspended)
+        &&  pTimer->u32Magic == RTTIMER_MAGIC)
+    {
+        switch (enmEvent)
+        {
+            /*
+             * Try do it without leaving the spin lock, but if we have to, retake it
+             * when we're on the right cpu.
+             */
+            case RTMPEVENT_ONLINE:
+                if (rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_MP_STARTING, RTTIMERLNXSTATE_STOPPED))
+                {
+                    RTTIMERLINUXSTARTONCPUARGS Args;
+                    Args.u64Now = RTTimeSystemNanoTS();
+                    Args.u64First = 0;
+
+                    if (RTMpCpuId() == idCpu)
+                        rtTimerLnxStartSubTimer(pSubTimer, Args.u64Now, Args.u64First, true /*fPinned*/, pTimer->fHighRes);
+                    else
+                    {
+                        rtTimerLnxSetState(&pSubTimer->enmState, RTTIMERLNXSTATE_STOPPED); /* we'll recheck it. */
+                        RTSpinlockRelease(hSpinlock);
+
+                        RTMpOnSpecific(idCpu, rtTimerLinuxMpStartOnCpu, pTimer, &Args);
+                        return; /* we've left the spinlock */
+                    }
+                }
+                break;
+
+            /*
+             * The CPU is (going) offline, make sure the sub-timer is stopped.
+             *
+             * Linux will migrate it to a different CPU, but we don't want this. The
+             * timer function is checking for this.
+             */
+            case RTMPEVENT_OFFLINE:
+            {
+                RTTIMERLNXSTATE enmState;
+                while (   (enmState = rtTimerLnxGetState(&pSubTimer->enmState)) == RTTIMERLNXSTATE_ACTIVE
+                       || enmState == RTTIMERLNXSTATE_CALLBACK
+                       || enmState == RTTIMERLNXSTATE_CB_RESTARTING)
+                {
+                    if (enmState == RTTIMERLNXSTATE_ACTIVE)
+                    {
+                        if (rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_MP_STOPPING, RTTIMERLNXSTATE_ACTIVE))
+                        {
+                            RTSpinlockRelease(hSpinlock);
+
+                            rtTimerLnxStopSubTimer(pSubTimer, pTimer->fHighRes);
+                            return; /* we've left the spinlock */
+                        }
+                    }
+                    else if (rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_CB_STOPPING, enmState))
+                        break;
+
+                    /* State not stable, try again. */
+                    ASMNopPause();
+                }
+                break;
+            }
+        }
+    }
+
+    RTSpinlockRelease(hSpinlock);
+}
+
+#endif /* CONFIG_SMP */
+
+
+/**
+ * Callback function use by RTTimerStart via RTMpOnSpecific to start a timer
+ * running on a specific CPU.
+ *
+ * @param   idCpu       The current CPU.
+ * @param   pvUser1     Pointer to the timer.
+ * @param   pvUser2     Pointer to the argument structure.
+ */
+static DECLCALLBACK(void) rtTimerLnxStartOnSpecificCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
+{
+    PRTTIMERLINUXSTARTONCPUARGS pArgs = (PRTTIMERLINUXSTARTONCPUARGS)pvUser2;
+    PRTTIMER pTimer = (PRTTIMER)pvUser1;
+    RT_NOREF_PV(idCpu);
+    rtTimerLnxStartSubTimer(&pTimer->aSubTimers[0], pArgs->u64Now, pArgs->u64First, true /*fPinned*/, pTimer->fHighRes);
+}
+
+
+RTDECL(int) RTTimerStart(PRTTIMER pTimer, uint64_t u64First)
+{
+    RTTIMERLINUXSTARTONCPUARGS Args;
+    int rc2;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * Validate.
+     */
+    AssertPtrReturn(pTimer, VERR_INVALID_HANDLE);
+    AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_HANDLE);
+
+    if (!ASMAtomicUoReadBool(&pTimer->fSuspended))
+        return VERR_TIMER_ACTIVE;
+    RTTIMERLNX_LOG(("start %p cCpus=%d\n", pTimer, pTimer->cCpus));
+
+    Args.u64First = u64First;
+#ifdef CONFIG_SMP
+    /*
+     * Omni timer?
+     */
+    if (pTimer->fAllCpus)
+    {
+        rc2 = rtTimerLnxOmniStart(pTimer, &Args);
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return rc2;
+    }
+#endif
+
+    /*
+     * Simple timer - Pretty straight forward if it wasn't for restarting.
+     */
+    Args.u64Now = RTTimeSystemNanoTS();
+    ASMAtomicWriteU64(&pTimer->aSubTimers[0].uNsRestartAt, Args.u64Now + u64First);
+    for (;;)
+    {
+        RTTIMERLNXSTATE enmState = rtTimerLnxGetState(&pTimer->aSubTimers[0].enmState);
+        switch (enmState)
+        {
+            case RTTIMERLNXSTATE_STOPPED:
+                if (rtTimerLnxCmpXchgState(&pTimer->aSubTimers[0].enmState, RTTIMERLNXSTATE_STARTING, RTTIMERLNXSTATE_STOPPED))
+                {
+                    ASMAtomicWriteBool(&pTimer->fSuspended, false);
+                    if (!pTimer->fSpecificCpu)
+                        rtTimerLnxStartSubTimer(&pTimer->aSubTimers[0], Args.u64Now, Args.u64First,
+                                                false /*fPinned*/, pTimer->fHighRes);
+                    else
+                    {
+                        rc2 = RTMpOnSpecific(pTimer->idCpu, rtTimerLnxStartOnSpecificCpu, pTimer, &Args);
+                        if (RT_FAILURE(rc2))
+                        {
+                            /* Suspend it, the cpu id is probably invalid or offline. */
+                            ASMAtomicWriteBool(&pTimer->fSuspended, true);
+                            rtTimerLnxSetState(&pTimer->aSubTimers[0].enmState, RTTIMERLNXSTATE_STOPPED);
+                            return rc2;
+                        }
+                    }
+                    IPRT_LINUX_RESTORE_EFL_AC();
+                    return VINF_SUCCESS;
+                }
+                break;
+
+            case RTTIMERLNXSTATE_CALLBACK:
+            case RTTIMERLNXSTATE_CB_STOPPING:
+                if (rtTimerLnxCmpXchgState(&pTimer->aSubTimers[0].enmState, RTTIMERLNXSTATE_CB_RESTARTING, enmState))
+                {
+                    ASMAtomicWriteBool(&pTimer->fSuspended, false);
+                    IPRT_LINUX_RESTORE_EFL_AC();
+                    return VINF_SUCCESS;
+                }
+                break;
+
+            default:
+                AssertMsgFailed(("%d\n", enmState));
+                IPRT_LINUX_RESTORE_EFL_AC();
+                return VERR_INTERNAL_ERROR_4;
+        }
+        ASMNopPause();
+    }
+}
+RT_EXPORT_SYMBOL(RTTimerStart);
+
+
+/**
+ * Common worker for RTTimerStop and RTTimerDestroy.
+ *
+ * @returns true if there was any active callbacks, false if not.
+ * @param   pTimer              The timer to stop.
+ * @param   fForDestroy         Whether it's RTTimerDestroy calling or not.
+ */
+static bool rtTimerLnxStop(PRTTIMER pTimer, bool fForDestroy)
+{
+    RTTIMERLNX_LOG(("lnxstop %p %d\n", pTimer, fForDestroy));
+#ifdef CONFIG_SMP
+    /*
+     * Omni timer?
+     */
+    if (pTimer->fAllCpus)
+        return rtTimerLnxOmniStop(pTimer, fForDestroy);
+#endif
+
+    /*
+     * Simple timer.
+     */
+    ASMAtomicWriteBool(&pTimer->fSuspended, true);
+    for (;;)
+    {
+        RTTIMERLNXSTATE enmState = rtTimerLnxGetState(&pTimer->aSubTimers[0].enmState);
+        switch (enmState)
+        {
+            case RTTIMERLNXSTATE_ACTIVE:
+                if (rtTimerLnxCmpXchgState(&pTimer->aSubTimers[0].enmState, RTTIMERLNXSTATE_STOPPING, RTTIMERLNXSTATE_ACTIVE))
+                {
+                    rtTimerLnxStopSubTimer(&pTimer->aSubTimers[0], pTimer->fHighRes);
+                    return false;
+                }
+                break;
+
+            case RTTIMERLNXSTATE_CALLBACK:
+            case RTTIMERLNXSTATE_CB_RESTARTING:
+            case RTTIMERLNXSTATE_CB_STOPPING:
+                Assert(enmState != RTTIMERLNXSTATE_CB_STOPPING || fForDestroy);
+                if (rtTimerLnxCmpXchgState(&pTimer->aSubTimers[0].enmState,
+                                           !fForDestroy ? RTTIMERLNXSTATE_CB_STOPPING : RTTIMERLNXSTATE_CB_DESTROYING,
+                                           enmState))
+                    return true;
+                break;
+
+            case RTTIMERLNXSTATE_STOPPED:
+                return VINF_SUCCESS;
+
+            case RTTIMERLNXSTATE_CB_DESTROYING:
+                AssertMsgFailed(("enmState=%d pTimer=%p\n", enmState, pTimer));
+                return true;
+
+            default:
+            case RTTIMERLNXSTATE_STARTING:
+            case RTTIMERLNXSTATE_MP_STARTING:
+            case RTTIMERLNXSTATE_STOPPING:
+            case RTTIMERLNXSTATE_MP_STOPPING:
+                AssertMsgFailed(("enmState=%d pTimer=%p\n", enmState, pTimer));
+                return false;
+        }
+
+        /* State not stable, try again. */
+        ASMNopPause();
+    }
+}
+
+
+RTDECL(int) RTTimerStop(PRTTIMER pTimer)
+{
+    /*
+     * Validate.
+     */
+    IPRT_LINUX_SAVE_EFL_AC();
+    AssertPtrReturn(pTimer, VERR_INVALID_HANDLE);
+    AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_HANDLE);
+    RTTIMERLNX_LOG(("stop %p\n", pTimer));
+
+    if (ASMAtomicUoReadBool(&pTimer->fSuspended))
+        return VERR_TIMER_SUSPENDED;
+
+    rtTimerLnxStop(pTimer, false /*fForDestroy*/);
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTTimerStop);
+
+
+RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval)
+{
+    unsigned long cJiffies;
+    unsigned long flFlags;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * Validate.
+     */
+    AssertPtrReturn(pTimer, VERR_INVALID_HANDLE);
+    AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(u64NanoInterval, VERR_INVALID_PARAMETER);
+    AssertReturn(u64NanoInterval < UINT64_MAX / 8, VERR_INVALID_PARAMETER);
+    AssertReturn(pTimer->u64NanoInterval, VERR_INVALID_STATE);
+    RTTIMERLNX_LOG(("change %p %llu\n", pTimer, u64NanoInterval));
+
+#ifdef RTTIMER_LINUX_WITH_HRTIMER
+    /*
+     * For the high resolution timers it is easy since we don't care so much
+     * about when it is applied to the sub-timers.
+     */
+    if (pTimer->fHighRes)
+    {
+        ASMAtomicWriteU64(&pTimer->u64NanoInterval, u64NanoInterval);
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return VINF_SUCCESS;
+    }
+#endif
+
+    /*
+     * Standard timers have a bit more complicated way of calculating
+     * their interval and such. So, forget omni timers for now.
+     */
+    if (pTimer->cCpus > 1)
+        return VERR_NOT_SUPPORTED;
+
+    cJiffies = u64NanoInterval / RTTimerGetSystemGranularity();
+    if (cJiffies * RTTimerGetSystemGranularity() != u64NanoInterval)
+        cJiffies = 0;
+
+    spin_lock_irqsave(&pTimer->ChgIntLock, flFlags);
+    pTimer->aSubTimers[0].u.Std.fFirstAfterChg = true;
+    pTimer->cJiffies = cJiffies;
+    ASMAtomicWriteU64(&pTimer->u64NanoInterval, u64NanoInterval);
+    spin_unlock_irqrestore(&pTimer->ChgIntLock, flFlags);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTTimerChangeInterval);
+
+
+RTDECL(int) RTTimerDestroy(PRTTIMER pTimer)
+{
+    bool fCanDestroy;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    /*
+     * Validate. It's ok to pass NULL pointer.
+     */
+    if (pTimer == /*NIL_RTTIMER*/ NULL)
+        return VINF_SUCCESS;
+    AssertPtrReturn(pTimer, VERR_INVALID_HANDLE);
+    AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_HANDLE);
+    RTTIMERLNX_LOG(("destroy %p\n", pTimer));
+/** @todo We should invalidate the magic here! */
+
+    /*
+     * Stop the timer if it's still active, then destroy it if we can.
+     */
+    if (!ASMAtomicUoReadBool(&pTimer->fSuspended))
+        fCanDestroy = rtTimerLnxStop(pTimer, true /*fForDestroy*/);
+    else
+    {
+        uint32_t        iCpu = pTimer->cCpus;
+        if (pTimer->cCpus > 1)
+            RTSpinlockAcquire(pTimer->hSpinlock);
+
+        fCanDestroy = true;
+        while (iCpu-- > 0)
+        {
+            for (;;)
+            {
+                RTTIMERLNXSTATE enmState = rtTimerLnxGetState(&pTimer->aSubTimers[iCpu].enmState);
+                switch (enmState)
+                {
+                    case RTTIMERLNXSTATE_CALLBACK:
+                    case RTTIMERLNXSTATE_CB_RESTARTING:
+                    case RTTIMERLNXSTATE_CB_STOPPING:
+                        if (!rtTimerLnxCmpXchgState(&pTimer->aSubTimers[iCpu].enmState, RTTIMERLNXSTATE_CB_DESTROYING, enmState))
+                            continue;
+                        fCanDestroy = false;
+                        break;
+
+                    case RTTIMERLNXSTATE_CB_DESTROYING:
+                        AssertMsgFailed(("%d\n", enmState));
+                        fCanDestroy = false;
+                        break;
+                    default:
+                        break;
+                }
+                break;
+            }
+        }
+
+        if (pTimer->cCpus > 1)
+            RTSpinlockRelease(pTimer->hSpinlock);
+    }
+
+    if (fCanDestroy)
+    {
+        /* For paranoid reasons, defer actually destroying the semaphore when
+           in atomic or interrupt context. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 32)
+        if (in_atomic() || in_interrupt())
+#else
+        if (in_interrupt())
+#endif
+            rtR0LnxWorkqueuePush(&pTimer->DtorWorkqueueItem, rtTimerLnxDestroyDeferred);
+        else
+            rtTimerLnxDestroyIt(pTimer);
+    }
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTTimerDestroy);
+
+
+RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser)
+{
+    PRTTIMER    pTimer;
+    RTCPUID     iCpu;
+    unsigned    cCpus;
+    int         rc;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    rtR0LnxWorkqueueFlush();                /* for 2.4 */
+    *ppTimer = NULL;
+
+    /*
+     * Validate flags.
+     */
+    if (!RTTIMER_FLAGS_ARE_VALID(fFlags))
+    {
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return VERR_INVALID_PARAMETER;
+    }
+    if (    (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC)
+        &&  (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL
+        &&  !RTMpIsCpuPossible(RTMpCpuIdFromSetIndex(fFlags & RTTIMER_FLAGS_CPU_MASK)))
+    {
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return VERR_CPU_NOT_FOUND;
+    }
+
+    /*
+     * Allocate the timer handler.
+     */
+    cCpus = 1;
+#ifdef CONFIG_SMP
+    if ((fFlags & RTTIMER_FLAGS_CPU_ALL) == RTTIMER_FLAGS_CPU_ALL)
+    {
+        cCpus = RTMpGetMaxCpuId() + 1;
+        Assert(cCpus <= RTCPUSET_MAX_CPUS); /* On linux we have a 1:1 relationship between cpuid and set index. */
+        AssertReturnStmt(u64NanoInterval, IPRT_LINUX_RESTORE_EFL_AC(), VERR_NOT_IMPLEMENTED); /* We don't implement single shot on all cpus, sorry. */
+    }
+#endif
+
+    rc = RTMemAllocEx(RT_OFFSETOF(RTTIMER, aSubTimers[cCpus]), 0,
+                      RTMEMALLOCEX_FLAGS_ZEROED | RTMEMALLOCEX_FLAGS_ANY_CTX_FREE, (void **)&pTimer);
+    if (RT_FAILURE(rc))
+    {
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return rc;
+    }
+
+    /*
+     * Initialize it.
+     */
+    pTimer->u32Magic        = RTTIMER_MAGIC;
+    pTimer->hSpinlock       = NIL_RTSPINLOCK;
+    pTimer->fSuspended      = true;
+    pTimer->fHighRes        = !!(fFlags & RTTIMER_FLAGS_HIGH_RES);
+#ifdef CONFIG_SMP
+    pTimer->fSpecificCpu    = (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC) && (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL;
+    pTimer->fAllCpus        = (fFlags & RTTIMER_FLAGS_CPU_ALL) == RTTIMER_FLAGS_CPU_ALL;
+    pTimer->idCpu           = pTimer->fSpecificCpu
+                            ? RTMpCpuIdFromSetIndex(fFlags & RTTIMER_FLAGS_CPU_MASK)
+                            : NIL_RTCPUID;
+#else
+    pTimer->fSpecificCpu    = !!(fFlags & RTTIMER_FLAGS_CPU_SPECIFIC);
+    pTimer->idCpu           = RTMpCpuId();
+#endif
+    pTimer->cCpus           = cCpus;
+    pTimer->pfnTimer        = pfnTimer;
+    pTimer->pvUser          = pvUser;
+    pTimer->u64NanoInterval = u64NanoInterval;
+    pTimer->cJiffies        = u64NanoInterval / RTTimerGetSystemGranularity();
+    if (pTimer->cJiffies * RTTimerGetSystemGranularity() != u64NanoInterval)
+        pTimer->cJiffies    = 0;
+    spin_lock_init(&pTimer->ChgIntLock);
+
+    for (iCpu = 0; iCpu < cCpus; iCpu++)
+    {
+#ifdef RTTIMER_LINUX_WITH_HRTIMER
+        if (pTimer->fHighRes)
+        {
+            hrtimer_init(&pTimer->aSubTimers[iCpu].u.Hr.LnxTimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+            pTimer->aSubTimers[iCpu].u.Hr.LnxTimer.function     = rtTimerLinuxHrCallback;
+        }
+        else
+#endif
+        {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
+            init_timer_pinned(&pTimer->aSubTimers[iCpu].u.Std.LnxTimer);
+#else
+            init_timer(&pTimer->aSubTimers[iCpu].u.Std.LnxTimer);
+#endif
+            pTimer->aSubTimers[iCpu].u.Std.LnxTimer.data        = (unsigned long)&pTimer->aSubTimers[iCpu];
+            pTimer->aSubTimers[iCpu].u.Std.LnxTimer.function    = rtTimerLinuxStdCallback;
+            pTimer->aSubTimers[iCpu].u.Std.LnxTimer.expires     = jiffies;
+            pTimer->aSubTimers[iCpu].u.Std.u64NextTS            = 0;
+        }
+        pTimer->aSubTimers[iCpu].iTick      = 0;
+        pTimer->aSubTimers[iCpu].pParent    = pTimer;
+        pTimer->aSubTimers[iCpu].enmState   = RTTIMERLNXSTATE_STOPPED;
+    }
+
+#ifdef CONFIG_SMP
+    /*
+     * If this is running on ALL cpus, we'll have to register a callback
+     * for MP events (so timers can be started/stopped on cpus going
+     * online/offline). We also create the spinlock for synchronizing
+     * stop/start/mp-event.
+     */
+    if (cCpus > 1)
+    {
+        int rc = RTSpinlockCreate(&pTimer->hSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "RTTimerLnx");
+        if (RT_SUCCESS(rc))
+            rc = RTMpNotificationRegister(rtTimerLinuxMpEvent, pTimer);
+        else
+            pTimer->hSpinlock = NIL_RTSPINLOCK;
+        if (RT_FAILURE(rc))
+        {
+            RTTimerDestroy(pTimer);
+            IPRT_LINUX_RESTORE_EFL_AC();
+            return rc;
+        }
+    }
+#endif /* CONFIG_SMP */
+
+    RTTIMERLNX_LOG(("create %p hires=%d fFlags=%#x cCpus=%u\n", pTimer, pTimer->fHighRes, fFlags, cCpus));
+    *ppTimer = pTimer;
+    IPRT_LINUX_RESTORE_EFL_AC();
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTTimerCreateEx);
+
+
+RTDECL(uint32_t) RTTimerGetSystemGranularity(void)
+{
+#if 0 /** @todo Not sure if this is what we want or not... Add new API for
+       *        querying the resolution of the high res timers? */
+    struct timespec Ts;
+    int rc;
+    IPRT_LINUX_SAVE_EFL_AC();
+    rc = hrtimer_get_res(CLOCK_MONOTONIC, &Ts);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    if (!rc)
+    {
+        Assert(!Ts.tv_sec);
+        return Ts.tv_nsec;
+    }
+#endif
+    return RT_NS_1SEC / HZ; /* ns */
+}
+RT_EXPORT_SYMBOL(RTTimerGetSystemGranularity);
+
+
+RTDECL(int) RTTimerRequestSystemGranularity(uint32_t u32Request, uint32_t *pu32Granted)
+{
+    RT_NOREF_PV(u32Request); RT_NOREF_PV(*pu32Granted);
+    return VERR_NOT_SUPPORTED;
+}
+RT_EXPORT_SYMBOL(RTTimerRequestSystemGranularity);
+
+
+RTDECL(int) RTTimerReleaseSystemGranularity(uint32_t u32Granted)
+{
+    RT_NOREF_PV(u32Granted);
+    return VERR_NOT_SUPPORTED;
+}
+RT_EXPORT_SYMBOL(RTTimerReleaseSystemGranularity);
+
+
+RTDECL(bool) RTTimerCanDoHighResolution(void)
+{
+#ifdef RTTIMER_LINUX_WITH_HRTIMER
+    return true;
+#else
+    return false;
+#endif
+}
+RT_EXPORT_SYMBOL(RTTimerCanDoHighResolution);
+
diff --git a/ubuntu/vbox/r0drv/linux/waitqueue-r0drv-linux.h b/ubuntu/vbox/r0drv/linux/waitqueue-r0drv-linux.h
new file mode 100644 (file)
index 0000000..cfa4d36
--- /dev/null
@@ -0,0 +1,290 @@
+/* $Id: waitqueue-r0drv-linux.h $ */
+/** @file
+ * IPRT - Linux Ring-0 Driver Helpers for Abstracting Wait Queues,
+ */
+
+/*
+ * 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.
+ */
+
+
+#ifndef ___r0drv_linux_waitqueue_r0drv_linux_h
+#define ___r0drv_linux_waitqueue_r0drv_linux_h
+
+#include "the-linux-kernel.h"
+
+#include <iprt/asm-math.h>
+#include <iprt/err.h>
+#include <iprt/string.h>
+#include <iprt/time.h>
+
+/** The resolution (nanoseconds) specified when using
+ *  schedule_hrtimeout_range. */
+#define RTR0SEMLNXWAIT_RESOLUTION   50000
+
+
+/**
+ * Kernel mode Linux wait state structure.
+ */
+typedef struct RTR0SEMLNXWAIT
+{
+    /** The wait queue entry. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
+    wait_queue_entry_t WaitQE;
+#else
+    wait_queue_t    WaitQE;
+#endif
+    /** The absolute timeout given as nano seconds since the start of the
+     *  monotonic clock. */
+    uint64_t        uNsAbsTimeout;
+    /** The timeout in nano seconds relative to the start of the wait. */
+    uint64_t        cNsRelTimeout;
+    /** The native timeout value. */
+    union
+    {
+#ifdef IPRT_LINUX_HAS_HRTIMER
+        /** The timeout when fHighRes is true. Absolute, so no updating. */
+        ktime_t     KtTimeout;
+#endif
+        /** The timeout when fHighRes is false.  Updated after waiting. */
+        long        lTimeout;
+    } u;
+    /** Set if we use high resolution timeouts. */
+    bool            fHighRes;
+    /** Set if it's an indefinite wait. */
+    bool            fIndefinite;
+    /** Set if we've already timed out.
+     * Set by rtR0SemLnxWaitDoIt and read by rtR0SemLnxWaitHasTimedOut. */
+    bool            fTimedOut;
+    /** TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE. */
+    int             iWaitState;
+    /** The wait queue. */
+    wait_queue_head_t *pWaitQueue;
+} RTR0SEMLNXWAIT;
+/** Pointer to a linux wait state. */
+typedef RTR0SEMLNXWAIT *PRTR0SEMLNXWAIT;
+
+
+/**
+ * Initializes a wait.
+ *
+ * The caller MUST check the wait condition BEFORE calling this function or the
+ * timeout logic will be flawed.
+ *
+ * @returns VINF_SUCCESS or VERR_TIMEOUT.
+ * @param   pWait               The wait structure.
+ * @param   fFlags              The wait flags.
+ * @param   uTimeout            The timeout.
+ * @param   pWaitQueue          The wait queue head.
+ */
+DECLINLINE(int) rtR0SemLnxWaitInit(PRTR0SEMLNXWAIT pWait, uint32_t fFlags, uint64_t uTimeout,
+                                   wait_queue_head_t *pWaitQueue)
+{
+    /*
+     * Process the flags and timeout.
+     */
+    if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE))
+    {
+/** @todo optimize: millisecs -> nanosecs -> millisec -> jiffies */
+        if (fFlags & RTSEMWAIT_FLAGS_MILLISECS)
+            uTimeout = uTimeout < UINT64_MAX / RT_US_1SEC * RT_US_1SEC
+                     ? uTimeout * RT_US_1SEC
+                     : UINT64_MAX;
+        if (uTimeout == UINT64_MAX)
+            fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
+        else
+        {
+            uint64_t u64Now;
+            if (fFlags & RTSEMWAIT_FLAGS_RELATIVE)
+            {
+                if (uTimeout == 0)
+                    return VERR_TIMEOUT;
+
+                u64Now = RTTimeSystemNanoTS();
+                pWait->cNsRelTimeout = uTimeout;
+                pWait->uNsAbsTimeout = u64Now + uTimeout;
+                if (pWait->uNsAbsTimeout < u64Now) /* overflow */
+                    fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
+            }
+            else
+            {
+                u64Now = RTTimeSystemNanoTS();
+                if (u64Now >= uTimeout)
+                    return VERR_TIMEOUT;
+
+                pWait->cNsRelTimeout = uTimeout - u64Now;
+                pWait->uNsAbsTimeout = uTimeout;
+            }
+        }
+    }
+
+    if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE))
+    {
+        pWait->fIndefinite      = false;
+#ifdef IPRT_LINUX_HAS_HRTIMER
+        if (   (fFlags & (RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE))
+            || pWait->cNsRelTimeout < RT_NS_1SEC / HZ * 4)
+        {
+            pWait->fHighRes     = true;
+# if BITS_PER_LONG < 64
+            if (   KTIME_SEC_MAX <= LONG_MAX
+                && pWait->uNsAbsTimeout >= KTIME_SEC_MAX * RT_NS_1SEC_64 + (RT_NS_1SEC - 1))
+                fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
+            else
+# endif
+                pWait->u.KtTimeout  = ns_to_ktime(pWait->uNsAbsTimeout);
+        }
+        else
+#endif
+        {
+            uint64_t cJiffies = ASMMultU64ByU32DivByU32(pWait->cNsRelTimeout, HZ, RT_NS_1SEC);
+            if (cJiffies >= MAX_JIFFY_OFFSET)
+                fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
+            else
+            {
+                pWait->u.lTimeout   = (long)cJiffies;
+                pWait->fHighRes     = false;
+            }
+        }
+    }
+
+    if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE)
+    {
+        pWait->fIndefinite      = true;
+        pWait->fHighRes         = false;
+        pWait->uNsAbsTimeout    = UINT64_MAX;
+        pWait->cNsRelTimeout    = UINT64_MAX;
+        pWait->u.lTimeout       = LONG_MAX;
+    }
+
+    pWait->fTimedOut   = false;
+
+    /*
+     * Initialize the wait queue related bits.
+     */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 39)
+    init_wait((&pWait->WaitQE));
+#else
+    RT_ZERO(pWait->WaitQE);
+    init_waitqueue_entry((&pWait->WaitQE), current);
+#endif
+    pWait->pWaitQueue = pWaitQueue;
+    pWait->iWaitState = fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE
+                      ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Prepares the next wait.
+ *
+ * This must be called before rtR0SemLnxWaitDoIt, and the caller should check
+ * the exit conditions in-between the two calls.
+ *
+ * @param   pWait               The wait structure.
+ */
+DECLINLINE(void) rtR0SemLnxWaitPrepare(PRTR0SEMLNXWAIT pWait)
+{
+    /* Make everything thru schedule*() atomic scheduling wise. (Is this correct?) */
+    prepare_to_wait(pWait->pWaitQueue, &pWait->WaitQE, pWait->iWaitState);
+}
+
+
+/**
+ * Do the actual wait.
+ *
+ * @param   pWait               The wait structure.
+ */
+DECLINLINE(void) rtR0SemLnxWaitDoIt(PRTR0SEMLNXWAIT pWait)
+{
+    if (pWait->fIndefinite)
+        schedule();
+#ifdef IPRT_LINUX_HAS_HRTIMER
+    else if (pWait->fHighRes)
+    {
+        int rc = schedule_hrtimeout_range(&pWait->u.KtTimeout, HRTIMER_MODE_ABS, RTR0SEMLNXWAIT_RESOLUTION);
+        if (!rc)
+            pWait->fTimedOut = true;
+    }
+#endif
+    else
+    {
+        pWait->u.lTimeout = schedule_timeout(pWait->u.lTimeout);
+        if (pWait->u.lTimeout <= 0)
+            pWait->fTimedOut = true;
+    }
+    after_wait((&pWait->WaitQE));
+}
+
+
+/**
+ * Checks if a linux wait was interrupted.
+ *
+ * @returns true / false
+ * @param   pWait               The wait structure.
+ * @remarks This shall be called before the first rtR0SemLnxWaitDoIt().
+ */
+DECLINLINE(bool) rtR0SemLnxWaitWasInterrupted(PRTR0SEMLNXWAIT pWait)
+{
+    return pWait->iWaitState == TASK_INTERRUPTIBLE
+        && signal_pending(current);
+}
+
+
+/**
+ * Checks if a linux wait has timed out.
+ *
+ * @returns true / false
+ * @param   pWait               The wait structure.
+ */
+DECLINLINE(bool) rtR0SemLnxWaitHasTimedOut(PRTR0SEMLNXWAIT pWait)
+{
+    return pWait->fTimedOut;
+}
+
+
+/**
+ * Deletes a linux wait.
+ *
+ * @param   pWait               The wait structure.
+ */
+DECLINLINE(void) rtR0SemLnxWaitDelete(PRTR0SEMLNXWAIT pWait)
+{
+    finish_wait(pWait->pWaitQueue, &pWait->WaitQE);
+}
+
+
+/**
+ * Gets the max resolution of the timeout machinery.
+ *
+ * @returns Resolution specified in nanoseconds.
+ */
+DECLINLINE(uint32_t) rtR0SemLnxWaitGetResolution(void)
+{
+#ifdef IPRT_LINUX_HAS_HRTIMER
+    return RTR0SEMLNXWAIT_RESOLUTION;
+#else
+    return RT_NS_1SEC / HZ; /* ns */
+#endif
+}
+
+#endif
+
diff --git a/ubuntu/vbox/r0drv/memobj-r0drv.c b/ubuntu/vbox/r0drv/memobj-r0drv.c
new file mode 100644 (file)
index 0000000..7450444
--- /dev/null
@@ -0,0 +1,808 @@
+/* $Id: memobj-r0drv.cpp $ */
+/** @file
+ * IPRT - Ring-0 Memory Objects, Common Code.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_DEFAULT /// @todo RTLOGGROUP_MEM
+#define RTMEM_NO_WRAP_TO_EF_APIS /* circular dependency otherwise. */
+#include <iprt/memobj.h>
+#include "internal/iprt.h"
+
+#include <iprt/alloc.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/log.h>
+#include <iprt/mp.h>
+#include <iprt/param.h>
+#include <iprt/process.h>
+#include <iprt/thread.h>
+
+#include "internal/memobj.h"
+
+
+/**
+ * Internal function for allocating a new memory object.
+ *
+ * @returns The allocated and initialized handle.
+ * @param   cbSelf      The size of the memory object handle. 0 mean default size.
+ * @param   enmType     The memory object type.
+ * @param   pv          The memory object mapping.
+ * @param   cb          The size of the memory object.
+ */
+DECLHIDDEN(PRTR0MEMOBJINTERNAL) rtR0MemObjNew(size_t cbSelf, RTR0MEMOBJTYPE enmType, void *pv, size_t cb)
+{
+    PRTR0MEMOBJINTERNAL pNew;
+
+    /* validate the size */
+    if (!cbSelf)
+        cbSelf = sizeof(*pNew);
+    Assert(cbSelf >= sizeof(*pNew));
+    Assert(cbSelf == (uint32_t)cbSelf);
+    AssertMsg(RT_ALIGN_Z(cb, PAGE_SIZE) == cb, ("%#zx\n", cb));
+
+    /*
+     * Allocate and initialize the object.
+     */
+    pNew = (PRTR0MEMOBJINTERNAL)RTMemAllocZ(cbSelf);
+    if (pNew)
+    {
+        pNew->u32Magic  = RTR0MEMOBJ_MAGIC;
+        pNew->cbSelf    = (uint32_t)cbSelf;
+        pNew->enmType   = enmType;
+        pNew->fFlags    = 0;
+        pNew->cb        = cb;
+        pNew->pv        = pv;
+    }
+    return pNew;
+}
+
+
+/**
+ * Deletes an incomplete memory object.
+ *
+ * This is for cleaning up after failures during object creation.
+ *
+ * @param   pMem    The incomplete memory object to delete.
+ */
+DECLHIDDEN(void) rtR0MemObjDelete(PRTR0MEMOBJINTERNAL pMem)
+{
+    if (pMem)
+    {
+        ASMAtomicUoWriteU32(&pMem->u32Magic, ~RTR0MEMOBJ_MAGIC);
+        pMem->enmType = RTR0MEMOBJTYPE_END;
+        RTMemFree(pMem);
+    }
+}
+
+
+/**
+ * Links a mapping object to a primary object.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VINF_NO_MEMORY if we couldn't expand the mapping array of the parent.
+ * @param   pParent     The parent (primary) memory object.
+ * @param   pChild      The child (mapping) memory object.
+ */
+static int rtR0MemObjLink(PRTR0MEMOBJINTERNAL pParent, PRTR0MEMOBJINTERNAL pChild)
+{
+    uint32_t i;
+
+    /* sanity */
+    Assert(rtR0MemObjIsMapping(pChild));
+    Assert(!rtR0MemObjIsMapping(pParent));
+
+    /* expand the array? */
+    i = pParent->uRel.Parent.cMappings;
+    if (i >= pParent->uRel.Parent.cMappingsAllocated)
+    {
+        void *pv = RTMemRealloc(pParent->uRel.Parent.papMappings,
+                                (i + 32) * sizeof(pParent->uRel.Parent.papMappings[0]));
+        if (!pv)
+            return VERR_NO_MEMORY;
+        pParent->uRel.Parent.papMappings = (PPRTR0MEMOBJINTERNAL)pv;
+        pParent->uRel.Parent.cMappingsAllocated = i + 32;
+        Assert(i == pParent->uRel.Parent.cMappings);
+    }
+
+    /* do the linking. */
+    pParent->uRel.Parent.papMappings[i] = pChild;
+    pParent->uRel.Parent.cMappings++;
+    pChild->uRel.Child.pParent = pParent;
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Checks if this is mapping or not.
+ *
+ * @returns true if it's a mapping, otherwise false.
+ * @param   MemObj      The ring-0 memory object handle.
+ */
+RTR0DECL(bool) RTR0MemObjIsMapping(RTR0MEMOBJ MemObj)
+{
+    /* Validate the object handle. */
+    PRTR0MEMOBJINTERNAL pMem;
+    AssertPtrReturn(MemObj, false);
+    pMem = (PRTR0MEMOBJINTERNAL)MemObj;
+    AssertMsgReturn(pMem->u32Magic == RTR0MEMOBJ_MAGIC, ("%p: %#x\n", pMem, pMem->u32Magic), false);
+    AssertMsgReturn(pMem->enmType > RTR0MEMOBJTYPE_INVALID && pMem->enmType < RTR0MEMOBJTYPE_END, ("%p: %d\n", pMem, pMem->enmType), false);
+
+    /* hand it on to the inlined worker. */
+    return rtR0MemObjIsMapping(pMem);
+}
+RT_EXPORT_SYMBOL(RTR0MemObjIsMapping);
+
+
+/**
+ * Gets the address of a ring-0 memory object.
+ *
+ * @returns The address of the memory object.
+ * @returns NULL if the handle is invalid (asserts in strict builds) or if there isn't any mapping.
+ * @param   MemObj  The ring-0 memory object handle.
+ */
+RTR0DECL(void *) RTR0MemObjAddress(RTR0MEMOBJ MemObj)
+{
+    /* Validate the object handle. */
+    PRTR0MEMOBJINTERNAL pMem;
+    if (RT_UNLIKELY(MemObj == NIL_RTR0MEMOBJ))
+        return NULL;
+    AssertPtrReturn(MemObj, NULL);
+    pMem = (PRTR0MEMOBJINTERNAL)MemObj;
+    AssertMsgReturn(pMem->u32Magic == RTR0MEMOBJ_MAGIC, ("%p: %#x\n", pMem, pMem->u32Magic), NULL);
+    AssertMsgReturn(pMem->enmType > RTR0MEMOBJTYPE_INVALID && pMem->enmType < RTR0MEMOBJTYPE_END, ("%p: %d\n", pMem, pMem->enmType), NULL);
+
+    /* return the mapping address. */
+    return pMem->pv;
+}
+RT_EXPORT_SYMBOL(RTR0MemObjAddress);
+
+
+/**
+ * Gets the ring-3 address of a ring-0 memory object.
+ *
+ * This only applies to ring-0 memory object with ring-3 mappings of some kind, i.e.
+ * locked user memory, reserved user address space and user mappings. This API should
+ * not be used on any other objects.
+ *
+ * @returns The address of the memory object.
+ * @returns NIL_RTR3PTR if the handle is invalid or if it's not an object with a ring-3 mapping.
+ *          Strict builds will assert in both cases.
+ * @param   MemObj  The ring-0 memory object handle.
+ */
+RTR0DECL(RTR3PTR) RTR0MemObjAddressR3(RTR0MEMOBJ MemObj)
+{
+    PRTR0MEMOBJINTERNAL pMem;
+
+    /* Validate the object handle. */
+    if (RT_UNLIKELY(MemObj == NIL_RTR0MEMOBJ))
+        return NIL_RTR3PTR;
+    AssertPtrReturn(MemObj, NIL_RTR3PTR);
+    pMem = (PRTR0MEMOBJINTERNAL)MemObj;
+    AssertMsgReturn(pMem->u32Magic == RTR0MEMOBJ_MAGIC, ("%p: %#x\n", pMem, pMem->u32Magic), NIL_RTR3PTR);
+    AssertMsgReturn(pMem->enmType > RTR0MEMOBJTYPE_INVALID && pMem->enmType < RTR0MEMOBJTYPE_END, ("%p: %d\n", pMem, pMem->enmType), NIL_RTR3PTR);
+    if (RT_UNLIKELY(    (   pMem->enmType != RTR0MEMOBJTYPE_MAPPING
+                         || pMem->u.Mapping.R0Process == NIL_RTR0PROCESS)
+                    &&  (   pMem->enmType != RTR0MEMOBJTYPE_LOCK
+                         || pMem->u.Lock.R0Process == NIL_RTR0PROCESS)
+                    &&  (   pMem->enmType != RTR0MEMOBJTYPE_PHYS_NC
+                         || pMem->u.Lock.R0Process == NIL_RTR0PROCESS)
+                    &&  (   pMem->enmType != RTR0MEMOBJTYPE_RES_VIRT
+                         || pMem->u.ResVirt.R0Process == NIL_RTR0PROCESS)))
+        return NIL_RTR3PTR;
+
+    /* return the mapping address. */
+    return (RTR3PTR)pMem->pv;
+}
+RT_EXPORT_SYMBOL(RTR0MemObjAddressR3);
+
+
+/**
+ * Gets the size of a ring-0 memory object.
+ *
+ * The returned value may differ from the one specified to the API creating the
+ * object because of alignment adjustments.  The minimal alignment currently
+ * employed by any API is PAGE_SIZE, so the result can safely be shifted by
+ * PAGE_SHIFT to calculate a page count.
+ *
+ * @returns The object size.
+ * @returns 0 if the handle is invalid (asserts in strict builds) or if there isn't any mapping.
+ * @param   MemObj  The ring-0 memory object handle.
+ */
+RTR0DECL(size_t) RTR0MemObjSize(RTR0MEMOBJ MemObj)
+{
+    PRTR0MEMOBJINTERNAL pMem;
+
+    /* Validate the object handle. */
+    if (RT_UNLIKELY(MemObj == NIL_RTR0MEMOBJ))
+        return 0;
+    AssertPtrReturn(MemObj, 0);
+    pMem = (PRTR0MEMOBJINTERNAL)MemObj;
+    AssertMsgReturn(pMem->u32Magic == RTR0MEMOBJ_MAGIC, ("%p: %#x\n", pMem, pMem->u32Magic), 0);
+    AssertMsgReturn(pMem->enmType > RTR0MEMOBJTYPE_INVALID && pMem->enmType < RTR0MEMOBJTYPE_END, ("%p: %d\n", pMem, pMem->enmType), 0);
+    AssertMsg(RT_ALIGN_Z(pMem->cb, PAGE_SIZE) == pMem->cb, ("%#zx\n", pMem->cb));
+
+    /* return the size. */
+    return pMem->cb;
+}
+RT_EXPORT_SYMBOL(RTR0MemObjSize);
+
+
+/**
+ * Get the physical address of an page in the memory object.
+ *
+ * @returns The physical address.
+ * @returns NIL_RTHCPHYS if the object doesn't contain fixed physical pages.
+ * @returns NIL_RTHCPHYS if the iPage is out of range.
+ * @returns NIL_RTHCPHYS if the object handle isn't valid.
+ * @param   MemObj  The ring-0 memory object handle.
+ * @param   iPage   The page number within the object.
+ */
+/* Work around gcc bug 55940 */
+#if defined(__GNUC__) && defined(RT_ARCH_X86) && (__GNUC__ * 100 + __GNUC_MINOR__) == 407
+ __attribute__((__optimize__ ("no-shrink-wrap")))
+#endif
+RTR0DECL(RTHCPHYS) RTR0MemObjGetPagePhysAddr(RTR0MEMOBJ MemObj, size_t iPage)
+{
+    /* Validate the object handle. */
+    PRTR0MEMOBJINTERNAL pMem;
+    size_t cPages;
+    AssertPtrReturn(MemObj, NIL_RTHCPHYS);
+    pMem = (PRTR0MEMOBJINTERNAL)MemObj;
+    AssertReturn(pMem->u32Magic == RTR0MEMOBJ_MAGIC, NIL_RTHCPHYS);
+    AssertReturn(pMem->enmType > RTR0MEMOBJTYPE_INVALID && pMem->enmType < RTR0MEMOBJTYPE_END, NIL_RTHCPHYS);
+    AssertMsgReturn(pMem->u32Magic == RTR0MEMOBJ_MAGIC, ("%p: %#x\n", pMem, pMem->u32Magic), NIL_RTHCPHYS);
+    AssertMsgReturn(pMem->enmType > RTR0MEMOBJTYPE_INVALID && pMem->enmType < RTR0MEMOBJTYPE_END, ("%p: %d\n", pMem, pMem->enmType), NIL_RTHCPHYS);
+    cPages = (pMem->cb >> PAGE_SHIFT);
+    if (iPage >= cPages)
+    {
+        /* permit: while (RTR0MemObjGetPagePhysAddr(pMem, iPage++) != NIL_RTHCPHYS) {} */
+        if (iPage == cPages)
+            return NIL_RTHCPHYS;
+        AssertReturn(iPage < (pMem->cb >> PAGE_SHIFT), NIL_RTHCPHYS);
+    }
+
+    /*
+     * We know the address of physically contiguous allocations and mappings.
+     */
+    if (pMem->enmType == RTR0MEMOBJTYPE_CONT)
+        return pMem->u.Cont.Phys + iPage * PAGE_SIZE;
+    if (pMem->enmType == RTR0MEMOBJTYPE_PHYS)
+        return pMem->u.Phys.PhysBase + iPage * PAGE_SIZE;
+
+    /*
+     * Do the job.
+     */
+    return rtR0MemObjNativeGetPagePhysAddr(pMem, iPage);
+}
+RT_EXPORT_SYMBOL(RTR0MemObjGetPagePhysAddr);
+
+
+/**
+ * Frees a ring-0 memory object.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_HANDLE if
+ * @param   MemObj          The ring-0 memory object to be freed. NULL is accepted.
+ * @param   fFreeMappings   Whether or not to free mappings of the object.
+ */
+RTR0DECL(int) RTR0MemObjFree(RTR0MEMOBJ MemObj, bool fFreeMappings)
+{
+    /*
+     * Validate the object handle.
+     */
+    PRTR0MEMOBJINTERNAL pMem;
+    int rc;
+
+    if (MemObj == NIL_RTR0MEMOBJ)
+        return VINF_SUCCESS;
+    AssertPtrReturn(MemObj, VERR_INVALID_HANDLE);
+    pMem = (PRTR0MEMOBJINTERNAL)MemObj;
+    AssertReturn(pMem->u32Magic == RTR0MEMOBJ_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(pMem->enmType > RTR0MEMOBJTYPE_INVALID && pMem->enmType < RTR0MEMOBJTYPE_END, VERR_INVALID_HANDLE);
+    RT_ASSERT_PREEMPTIBLE();
+
+    /*
+     * Deal with mappings according to fFreeMappings.
+     */
+    if (    !rtR0MemObjIsMapping(pMem)
+        &&  pMem->uRel.Parent.cMappings > 0)
+    {
+        /* fail if not requested to free mappings. */
+        if (!fFreeMappings)
+            return VERR_MEMORY_BUSY;
+
+        while (pMem->uRel.Parent.cMappings > 0)
+        {
+            PRTR0MEMOBJINTERNAL pChild = pMem->uRel.Parent.papMappings[--pMem->uRel.Parent.cMappings];
+            pMem->uRel.Parent.papMappings[pMem->uRel.Parent.cMappings] = NULL;
+
+            /* sanity checks. */
+            AssertPtr(pChild);
+            AssertFatal(pChild->u32Magic == RTR0MEMOBJ_MAGIC);
+            AssertFatal(pChild->enmType > RTR0MEMOBJTYPE_INVALID && pChild->enmType < RTR0MEMOBJTYPE_END);
+            AssertFatal(rtR0MemObjIsMapping(pChild));
+
+            /* free the mapping. */
+            rc = rtR0MemObjNativeFree(pChild);
+            if (RT_FAILURE(rc))
+            {
+                Log(("RTR0MemObjFree: failed to free mapping %p: %p %#zx; rc=%Rrc\n", pChild, pChild->pv, pChild->cb, rc));
+                pMem->uRel.Parent.papMappings[pMem->uRel.Parent.cMappings++] = pChild;
+                return rc;
+            }
+        }
+    }
+
+    /*
+     * Free this object.
+     */
+    rc = rtR0MemObjNativeFree(pMem);
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Ok, it was freed just fine. Now, if it's a mapping we'll have to remove it from the parent.
+         */
+        if (rtR0MemObjIsMapping(pMem))
+        {
+            PRTR0MEMOBJINTERNAL pParent = pMem->uRel.Child.pParent;
+            uint32_t i;
+
+            /* sanity checks */
+            AssertPtr(pParent);
+            AssertFatal(pParent->u32Magic == RTR0MEMOBJ_MAGIC);
+            AssertFatal(pParent->enmType > RTR0MEMOBJTYPE_INVALID && pParent->enmType < RTR0MEMOBJTYPE_END);
+            AssertFatal(!rtR0MemObjIsMapping(pParent));
+            AssertFatal(pParent->uRel.Parent.cMappings > 0);
+            AssertPtr(pParent->uRel.Parent.papMappings);
+
+            /* locate and remove from the array of mappings. */
+            i = pParent->uRel.Parent.cMappings;
+            while (i-- > 0)
+            {
+                if (pParent->uRel.Parent.papMappings[i] == pMem)
+                {
+                    pParent->uRel.Parent.papMappings[i] = pParent->uRel.Parent.papMappings[--pParent->uRel.Parent.cMappings];
+                    break;
+                }
+            }
+            Assert(i != UINT32_MAX);
+        }
+        else
+            Assert(pMem->uRel.Parent.cMappings == 0);
+
+        /*
+         * Finally, destroy the handle.
+         */
+        pMem->u32Magic++;
+        pMem->enmType = RTR0MEMOBJTYPE_END;
+        if (!rtR0MemObjIsMapping(pMem))
+            RTMemFree(pMem->uRel.Parent.papMappings);
+        RTMemFree(pMem);
+    }
+    else
+        Log(("RTR0MemObjFree: failed to free %p: %d %p %#zx; rc=%Rrc\n",
+             pMem, pMem->enmType, pMem->pv, pMem->cb, rc));
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTR0MemObjFree);
+
+
+
+RTR0DECL(int) RTR0MemObjAllocPageTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag)
+{
+    /* sanity checks. */
+    const size_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
+    AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
+    *pMemObj = NIL_RTR0MEMOBJ;
+    AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
+    AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
+    RT_ASSERT_PREEMPTIBLE();
+
+    RT_NOREF_PV(pszTag);
+
+    /* do the allocation. */
+    return rtR0MemObjNativeAllocPage(pMemObj, cbAligned, fExecutable);
+}
+RT_EXPORT_SYMBOL(RTR0MemObjAllocPageTag);
+
+
+RTR0DECL(int) RTR0MemObjAllocLowTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag)
+{
+    /* sanity checks. */
+    const size_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
+    AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
+    *pMemObj = NIL_RTR0MEMOBJ;
+    AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
+    AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
+    RT_ASSERT_PREEMPTIBLE();
+
+    RT_NOREF_PV(pszTag);
+
+    /* do the allocation. */
+    return rtR0MemObjNativeAllocLow(pMemObj, cbAligned, fExecutable);
+}
+RT_EXPORT_SYMBOL(RTR0MemObjAllocLowTag);
+
+
+RTR0DECL(int) RTR0MemObjAllocContTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag)
+{
+    /* sanity checks. */
+    const size_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
+    AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
+    *pMemObj = NIL_RTR0MEMOBJ;
+    AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
+    AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
+    RT_ASSERT_PREEMPTIBLE();
+
+    RT_NOREF_PV(pszTag);
+
+    /* do the allocation. */
+    return rtR0MemObjNativeAllocCont(pMemObj, cbAligned, fExecutable);
+}
+RT_EXPORT_SYMBOL(RTR0MemObjAllocContTag);
+
+
+RTR0DECL(int) RTR0MemObjLockUserTag(PRTR0MEMOBJ pMemObj, RTR3PTR R3Ptr, size_t cb,
+                                    uint32_t fAccess, RTR0PROCESS R0Process, const char *pszTag)
+{
+    /* sanity checks. */
+    const size_t cbAligned = RT_ALIGN_Z(cb + (R3Ptr & PAGE_OFFSET_MASK), PAGE_SIZE);
+    RTR3PTR const R3PtrAligned = (R3Ptr & ~(RTR3PTR)PAGE_OFFSET_MASK);
+    AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
+    *pMemObj = NIL_RTR0MEMOBJ;
+    AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
+    AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
+    if (R0Process == NIL_RTR0PROCESS)
+        R0Process = RTR0ProcHandleSelf();
+    AssertReturn(!(fAccess & ~(RTMEM_PROT_READ | RTMEM_PROT_WRITE)), VERR_INVALID_PARAMETER);
+    AssertReturn(fAccess, VERR_INVALID_PARAMETER);
+    RT_ASSERT_PREEMPTIBLE();
+
+    RT_NOREF_PV(pszTag);
+
+    /* do the locking. */
+    return rtR0MemObjNativeLockUser(pMemObj, R3PtrAligned, cbAligned, fAccess, R0Process);
+}
+RT_EXPORT_SYMBOL(RTR0MemObjLockUserTag);
+
+
+RTR0DECL(int) RTR0MemObjLockKernelTag(PRTR0MEMOBJ pMemObj, void *pv, size_t cb, uint32_t fAccess, const char *pszTag)
+{
+    /* sanity checks. */
+    const size_t cbAligned = RT_ALIGN_Z(cb + ((uintptr_t)pv & PAGE_OFFSET_MASK), PAGE_SIZE);
+    void * const pvAligned = (void *)((uintptr_t)pv & ~(uintptr_t)PAGE_OFFSET_MASK);
+    AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
+    *pMemObj = NIL_RTR0MEMOBJ;
+    AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
+    AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pvAligned, VERR_INVALID_POINTER);
+    AssertReturn(!(fAccess & ~(RTMEM_PROT_READ | RTMEM_PROT_WRITE)), VERR_INVALID_PARAMETER);
+    AssertReturn(fAccess, VERR_INVALID_PARAMETER);
+    RT_ASSERT_PREEMPTIBLE();
+
+    RT_NOREF_PV(pszTag);
+
+    /* do the allocation. */
+    return rtR0MemObjNativeLockKernel(pMemObj, pvAligned, cbAligned, fAccess);
+}
+RT_EXPORT_SYMBOL(RTR0MemObjLockKernelTag);
+
+
+RTR0DECL(int) RTR0MemObjAllocPhysTag(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest, const char *pszTag)
+{
+    /* sanity checks. */
+    const size_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
+    AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
+    *pMemObj = NIL_RTR0MEMOBJ;
+    AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
+    AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
+    AssertReturn(PhysHighest >= cb, VERR_INVALID_PARAMETER);
+    RT_ASSERT_PREEMPTIBLE();
+
+    RT_NOREF_PV(pszTag);
+
+    /* do the allocation. */
+    return rtR0MemObjNativeAllocPhys(pMemObj, cbAligned, PhysHighest, PAGE_SIZE /* page aligned */);
+}
+RT_EXPORT_SYMBOL(RTR0MemObjAllocPhysTag);
+
+
+RTR0DECL(int) RTR0MemObjAllocPhysExTag(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment, const char *pszTag)
+{
+    /* sanity checks. */
+    const size_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
+    AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
+    *pMemObj = NIL_RTR0MEMOBJ;
+    AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
+    AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
+    AssertReturn(PhysHighest >= cb, VERR_INVALID_PARAMETER);
+    if (uAlignment == 0)
+        uAlignment = PAGE_SIZE;
+    AssertReturn(    uAlignment == PAGE_SIZE
+                 ||  uAlignment == _2M
+                 ||  uAlignment == _4M
+                 ||  uAlignment == _1G,
+                 VERR_INVALID_PARAMETER);
+#if HC_ARCH_BITS == 32
+    /* Memory allocated in this way is typically mapped into kernel space as well; simply
+       don't allow this on 32 bits hosts as the kernel space is too crowded already. */
+    if (uAlignment != PAGE_SIZE)
+        return VERR_NOT_SUPPORTED;
+#endif
+    RT_ASSERT_PREEMPTIBLE();
+
+    RT_NOREF_PV(pszTag);
+
+    /* do the allocation. */
+    return rtR0MemObjNativeAllocPhys(pMemObj, cbAligned, PhysHighest, uAlignment);
+}
+RT_EXPORT_SYMBOL(RTR0MemObjAllocPhysExTag);
+
+
+RTR0DECL(int) RTR0MemObjAllocPhysNCTag(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest, const char *pszTag)
+{
+    /* sanity checks. */
+    const size_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
+    AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
+    *pMemObj = NIL_RTR0MEMOBJ;
+    AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
+    AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
+    AssertReturn(PhysHighest >= cb, VERR_INVALID_PARAMETER);
+    RT_ASSERT_PREEMPTIBLE();
+
+    RT_NOREF_PV(pszTag);
+
+    /* do the allocation. */
+    return rtR0MemObjNativeAllocPhysNC(pMemObj, cbAligned, PhysHighest);
+}
+RT_EXPORT_SYMBOL(RTR0MemObjAllocPhysNCTag);
+
+
+RTR0DECL(int) RTR0MemObjEnterPhysTag(PRTR0MEMOBJ pMemObj, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy, const char *pszTag)
+{
+    /* sanity checks. */
+    const size_t cbAligned = RT_ALIGN_Z(cb + (Phys & PAGE_OFFSET_MASK), PAGE_SIZE);
+    const RTHCPHYS PhysAligned = Phys & ~(RTHCPHYS)PAGE_OFFSET_MASK;
+    AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
+    *pMemObj = NIL_RTR0MEMOBJ;
+    AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
+    AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
+    AssertReturn(Phys != NIL_RTHCPHYS, VERR_INVALID_PARAMETER);
+    AssertReturn(   uCachePolicy == RTMEM_CACHE_POLICY_DONT_CARE
+                 || uCachePolicy == RTMEM_CACHE_POLICY_MMIO,
+                 VERR_INVALID_PARAMETER);
+    RT_ASSERT_PREEMPTIBLE();
+
+    RT_NOREF_PV(pszTag);
+
+    /* do the allocation. */
+    return rtR0MemObjNativeEnterPhys(pMemObj, PhysAligned, cbAligned, uCachePolicy);
+}
+RT_EXPORT_SYMBOL(RTR0MemObjEnterPhysTag);
+
+
+RTR0DECL(int) RTR0MemObjReserveKernelTag(PRTR0MEMOBJ pMemObj, void *pvFixed, size_t cb, size_t uAlignment, const char *pszTag)
+{
+    /* sanity checks. */
+    const size_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
+    AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
+    *pMemObj = NIL_RTR0MEMOBJ;
+    if (uAlignment == 0)
+        uAlignment = PAGE_SIZE;
+    AssertReturn(uAlignment == PAGE_SIZE || uAlignment == _2M || uAlignment == _4M, VERR_INVALID_PARAMETER);
+    AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
+    AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
+    if (pvFixed != (void *)-1)
+        AssertReturn(!((uintptr_t)pvFixed & (uAlignment - 1)), VERR_INVALID_PARAMETER);
+    RT_ASSERT_PREEMPTIBLE();
+
+    RT_NOREF_PV(pszTag);
+
+    /* do the reservation. */
+    return rtR0MemObjNativeReserveKernel(pMemObj, pvFixed, cbAligned, uAlignment);
+}
+RT_EXPORT_SYMBOL(RTR0MemObjReserveKernelTag);
+
+
+RTR0DECL(int) RTR0MemObjReserveUserTag(PRTR0MEMOBJ pMemObj, RTR3PTR R3PtrFixed, size_t cb,
+                                       size_t uAlignment, RTR0PROCESS R0Process, const char *pszTag)
+{
+    /* sanity checks. */
+    const size_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
+    AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
+    *pMemObj = NIL_RTR0MEMOBJ;
+    if (uAlignment == 0)
+        uAlignment = PAGE_SIZE;
+    AssertReturn(uAlignment == PAGE_SIZE || uAlignment == _2M || uAlignment == _4M, VERR_INVALID_PARAMETER);
+    AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
+    AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
+    if (R3PtrFixed != (RTR3PTR)-1)
+        AssertReturn(!(R3PtrFixed & (uAlignment - 1)), VERR_INVALID_PARAMETER);
+    if (R0Process == NIL_RTR0PROCESS)
+        R0Process = RTR0ProcHandleSelf();
+    RT_ASSERT_PREEMPTIBLE();
+
+    RT_NOREF_PV(pszTag);
+
+    /* do the reservation. */
+    return rtR0MemObjNativeReserveUser(pMemObj, R3PtrFixed, cbAligned, uAlignment, R0Process);
+}
+RT_EXPORT_SYMBOL(RTR0MemObjReserveUserTag);
+
+
+RTR0DECL(int) RTR0MemObjMapKernelTag(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, void *pvFixed,
+                                     size_t uAlignment, unsigned fProt, const char *pszTag)
+{
+    return RTR0MemObjMapKernelExTag(pMemObj, MemObjToMap, pvFixed, uAlignment, fProt, 0, 0, pszTag);
+}
+RT_EXPORT_SYMBOL(RTR0MemObjMapKernelTag);
+
+
+RTR0DECL(int) RTR0MemObjMapKernelExTag(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, void *pvFixed, size_t uAlignment,
+                                       unsigned fProt, size_t offSub, size_t cbSub, const char *pszTag)
+{
+    PRTR0MEMOBJINTERNAL pMemToMap;
+    PRTR0MEMOBJINTERNAL pNew;
+    int                 rc;
+
+    /* sanity checks. */
+    AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
+    *pMemObj = NIL_RTR0MEMOBJ;
+    AssertPtrReturn(MemObjToMap, VERR_INVALID_HANDLE);
+    pMemToMap = (PRTR0MEMOBJINTERNAL)MemObjToMap;
+    AssertReturn(pMemToMap->u32Magic == RTR0MEMOBJ_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(pMemToMap->enmType > RTR0MEMOBJTYPE_INVALID && pMemToMap->enmType < RTR0MEMOBJTYPE_END, VERR_INVALID_HANDLE);
+    AssertReturn(!rtR0MemObjIsMapping(pMemToMap), VERR_INVALID_PARAMETER);
+    AssertReturn(pMemToMap->enmType != RTR0MEMOBJTYPE_RES_VIRT, VERR_INVALID_PARAMETER);
+    if (uAlignment == 0)
+        uAlignment = PAGE_SIZE;
+    AssertReturn(uAlignment == PAGE_SIZE || uAlignment == _2M || uAlignment == _4M, VERR_INVALID_PARAMETER);
+    if (pvFixed != (void *)-1)
+        AssertReturn(!((uintptr_t)pvFixed & (uAlignment - 1)), VERR_INVALID_PARAMETER);
+    AssertReturn(fProt != RTMEM_PROT_NONE, VERR_INVALID_PARAMETER);
+    AssertReturn(!(fProt & ~(RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC)), VERR_INVALID_PARAMETER);
+    AssertReturn(!(offSub & PAGE_OFFSET_MASK), VERR_INVALID_PARAMETER);
+    AssertReturn(offSub < pMemToMap->cb, VERR_INVALID_PARAMETER);
+    AssertReturn(!(cbSub & PAGE_OFFSET_MASK), VERR_INVALID_PARAMETER);
+    AssertReturn(cbSub <= pMemToMap->cb, VERR_INVALID_PARAMETER);
+    AssertReturn((!offSub && !cbSub) || (offSub + cbSub) <= pMemToMap->cb, VERR_INVALID_PARAMETER);
+    RT_ASSERT_PREEMPTIBLE();
+
+    RT_NOREF_PV(pszTag);
+
+    /* adjust the request to simplify the native code. */
+    if (offSub == 0 && cbSub == pMemToMap->cb)
+        cbSub = 0;
+
+    /* do the mapping. */
+    rc = rtR0MemObjNativeMapKernel(&pNew, pMemToMap, pvFixed, uAlignment, fProt, offSub, cbSub);
+    if (RT_SUCCESS(rc))
+    {
+        /* link it. */
+        rc = rtR0MemObjLink(pMemToMap, pNew);
+        if (RT_SUCCESS(rc))
+            *pMemObj = pNew;
+        else
+        {
+            /* damn, out of memory. bail out. */
+            int rc2 = rtR0MemObjNativeFree(pNew);
+            AssertRC(rc2);
+            pNew->u32Magic++;
+            pNew->enmType = RTR0MEMOBJTYPE_END;
+            RTMemFree(pNew);
+        }
+    }
+
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTR0MemObjMapKernelExTag);
+
+
+RTR0DECL(int) RTR0MemObjMapUserTag(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, RTR3PTR R3PtrFixed,
+                                   size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process, const char *pszTag)
+{
+    /* sanity checks. */
+    PRTR0MEMOBJINTERNAL pMemToMap;
+    PRTR0MEMOBJINTERNAL pNew;
+    int rc;
+    AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
+    pMemToMap = (PRTR0MEMOBJINTERNAL)MemObjToMap;
+    *pMemObj = NIL_RTR0MEMOBJ;
+    AssertPtrReturn(MemObjToMap, VERR_INVALID_HANDLE);
+    AssertReturn(pMemToMap->u32Magic == RTR0MEMOBJ_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(pMemToMap->enmType > RTR0MEMOBJTYPE_INVALID && pMemToMap->enmType < RTR0MEMOBJTYPE_END, VERR_INVALID_HANDLE);
+    AssertReturn(!rtR0MemObjIsMapping(pMemToMap), VERR_INVALID_PARAMETER);
+    AssertReturn(pMemToMap->enmType != RTR0MEMOBJTYPE_RES_VIRT, VERR_INVALID_PARAMETER);
+    if (uAlignment == 0)
+        uAlignment = PAGE_SIZE;
+    AssertReturn(uAlignment == PAGE_SIZE || uAlignment == _2M || uAlignment == _4M, VERR_INVALID_PARAMETER);
+    if (R3PtrFixed != (RTR3PTR)-1)
+        AssertReturn(!(R3PtrFixed & (uAlignment - 1)), VERR_INVALID_PARAMETER);
+    AssertReturn(fProt != RTMEM_PROT_NONE, VERR_INVALID_PARAMETER);
+    AssertReturn(!(fProt & ~(RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC)), VERR_INVALID_PARAMETER);
+    if (R0Process == NIL_RTR0PROCESS)
+        R0Process = RTR0ProcHandleSelf();
+    RT_ASSERT_PREEMPTIBLE();
+
+    RT_NOREF_PV(pszTag);
+
+    /* do the mapping. */
+    rc = rtR0MemObjNativeMapUser(&pNew, pMemToMap, R3PtrFixed, uAlignment, fProt, R0Process);
+    if (RT_SUCCESS(rc))
+    {
+        /* link it. */
+        rc = rtR0MemObjLink(pMemToMap, pNew);
+        if (RT_SUCCESS(rc))
+            *pMemObj = pNew;
+        else
+        {
+            /* damn, out of memory. bail out. */
+            int rc2 = rtR0MemObjNativeFree(pNew);
+            AssertRC(rc2);
+            pNew->u32Magic++;
+            pNew->enmType = RTR0MEMOBJTYPE_END;
+            RTMemFree(pNew);
+        }
+    }
+
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTR0MemObjMapUserTag);
+
+
+RTR0DECL(int) RTR0MemObjProtect(RTR0MEMOBJ hMemObj, size_t offSub, size_t cbSub, uint32_t fProt)
+{
+    PRTR0MEMOBJINTERNAL pMemObj;
+    int                 rc;
+
+    /* sanity checks. */
+    pMemObj = (PRTR0MEMOBJINTERNAL)hMemObj;
+    AssertPtrReturn(pMemObj, VERR_INVALID_HANDLE);
+    AssertReturn(pMemObj->u32Magic == RTR0MEMOBJ_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(pMemObj->enmType > RTR0MEMOBJTYPE_INVALID && pMemObj->enmType < RTR0MEMOBJTYPE_END, VERR_INVALID_HANDLE);
+    AssertReturn(rtR0MemObjIsProtectable(pMemObj), VERR_INVALID_PARAMETER);
+    AssertReturn(!(offSub & PAGE_OFFSET_MASK), VERR_INVALID_PARAMETER);
+    AssertReturn(offSub < pMemObj->cb, VERR_INVALID_PARAMETER);
+    AssertReturn(!(cbSub  & PAGE_OFFSET_MASK), VERR_INVALID_PARAMETER);
+    AssertReturn(cbSub <= pMemObj->cb, VERR_INVALID_PARAMETER);
+    AssertReturn(offSub + cbSub <= pMemObj->cb, VERR_INVALID_PARAMETER);
+    AssertReturn(!(fProt & ~(RTMEM_PROT_NONE | RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC)), VERR_INVALID_PARAMETER);
+    RT_ASSERT_PREEMPTIBLE();
+
+    /* do the job */
+    rc = rtR0MemObjNativeProtect(pMemObj, offSub, cbSub, fProt);
+    if (RT_SUCCESS(rc))
+        pMemObj->fFlags |= RTR0MEMOBJ_FLAGS_PROT_CHANGED; /* record it */
+
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTR0MemObjProtect);
+
diff --git a/ubuntu/vbox/r0drv/mp-r0drv.h b/ubuntu/vbox/r0drv/mp-r0drv.h
new file mode 100644 (file)
index 0000000..e98ee4a
--- /dev/null
@@ -0,0 +1,82 @@
+/* $Id: mp-r0drv.h $ */
+/** @file
+ * IPRT - Multiprocessor, Ring-0 Driver, Internal Header.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+#ifndef ___r0drv_mp_r0drv_h
+#define ___r0drv_mp_r0drv_h
+
+#include <iprt/mp.h>
+
+RT_C_DECLS_BEGIN
+
+/**
+ * MP callback
+ *
+ * @param   idCpu       CPU id
+ * @param   pvUser1     The first user argument.
+ * @param   pvUser2     The second user argument.
+ */
+typedef DECLCALLBACK(void) FNMPWORKER(RTCPUID idCpu, void *pvUser1, void *pvUser2);
+/** Pointer to a FNMPWORKER(). */
+typedef FNMPWORKER *PFNMPWORKER;
+
+/**
+ * RTMpOn* argument packet used by the host specific callback
+ * wrapper functions.
+ */
+typedef struct RTMPARGS
+{
+    PFNMPWORKER pfnWorker;
+    void       *pvUser1;
+    void       *pvUser2;
+    RTCPUID     idCpu;
+    RTCPUID     idCpu2;
+    uint32_t volatile cHits;
+#ifdef RT_OS_WINDOWS
+    /** Turns out that KeFlushQueuedDpcs doesn't necessarily wait till all
+     * callbacks are done.  So, do reference counting to make sure we don't free
+     * this structure befor all CPUs have completely handled their requests.  */
+    int32_t volatile  cRefs;
+#endif
+#ifdef RT_OS_LINUX
+    PRTCPUSET   pWorkerSet;
+#endif
+} RTMPARGS;
+/** Pointer to a RTMpOn* argument packet. */
+typedef RTMPARGS *PRTMPARGS;
+
+/* Called from initterm-r0drv.cpp: */
+DECLHIDDEN(int)  rtR0MpNotificationInit(void);
+DECLHIDDEN(void) rtR0MpNotificationTerm(void);
+
+/* The following is only relevant when using mpnotifcation-r0drv.cpp: */
+DECLHIDDEN(int)  rtR0MpNotificationNativeInit(void);
+DECLHIDDEN(void) rtR0MpNotificationNativeTerm(void);
+DECLHIDDEN(void) rtMpNotificationDoCallbacks(RTMPEVENT enmEvent, RTCPUID idCpu);
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/r0drv/mpnotification-r0drv.c b/ubuntu/vbox/r0drv/mpnotification-r0drv.c
new file mode 100644 (file)
index 0000000..30a48be
--- /dev/null
@@ -0,0 +1,322 @@
+/* $Id: mpnotification-r0drv.c $ */
+/** @file
+ * IPRT - Multiprocessor, Ring-0 Driver, Event Notifications.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/mp.h>
+#include "internal/iprt.h"
+
+#include <iprt/asm.h>
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# include <iprt/asm-amd64-x86.h>
+#endif
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/mem.h>
+#include <iprt/spinlock.h>
+#include <iprt/string.h>
+#include <iprt/thread.h>
+#include "r0drv/mp-r0drv.h"
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * Notification registration record tracking
+ * RTMpRegisterNotification() calls.
+ */
+typedef struct RTMPNOTIFYREG
+{
+    /** Pointer to the next record. */
+    struct RTMPNOTIFYREG * volatile pNext;
+    /** The callback. */
+    PFNRTMPNOTIFICATION pfnCallback;
+    /** The user argument. */
+    void *pvUser;
+    /** Bit mask indicating whether we've done this callback or not. */
+    uint8_t bmDone[sizeof(void *)];
+} RTMPNOTIFYREG;
+/** Pointer to a registration record. */
+typedef RTMPNOTIFYREG *PRTMPNOTIFYREG;
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** The spinlock protecting the list. */
+static RTSPINLOCK volatile g_hRTMpNotifySpinLock = NIL_RTSPINLOCK;
+/** List of callbacks, in registration order. */
+static PRTMPNOTIFYREG volatile g_pRTMpCallbackHead = NULL;
+/** The current done bit. */
+static uint32_t volatile g_iRTMpDoneBit;
+/** The list generation.
+ * This is increased whenever the list has been modified. The callback routine
+ * make use of this to avoid having restart at the list head after each callback. */
+static uint32_t volatile g_iRTMpGeneration;
+
+
+
+
+/**
+ * This is called by the native code.
+ *
+ * @param   idCpu           The CPU id the event applies to.
+ * @param   enmEvent        The event.
+ */
+DECLHIDDEN(void) rtMpNotificationDoCallbacks(RTMPEVENT enmEvent, RTCPUID idCpu)
+{
+    PRTMPNOTIFYREG  pCur;
+    RTSPINLOCK      hSpinlock;
+
+    /*
+     * This is a little bit tricky as we cannot be holding the spinlock
+     * while calling the callback. This means that the list might change
+     * while we're walking it, and that multiple events might be running
+     * concurrently (depending on the OS).
+     *
+     * So, the first measure is to employ a 32-bitmask for each
+     * record where we'll use a bit that rotates for each call to
+     * this function to indicate which records that has been
+     * processed. This will take care of both changes to the list
+     * and a reasonable amount of concurrent events.
+     *
+     * In order to avoid having to restart the list walks for every
+     * callback we make, we'll make use a list generation number that is
+     * incremented everytime the list is changed. So, if it remains
+     * unchanged over a callback we can safely continue the iteration.
+     */
+    uint32_t iDone = ASMAtomicIncU32(&g_iRTMpDoneBit);
+    iDone %= RT_SIZEOFMEMB(RTMPNOTIFYREG, bmDone) * 8;
+
+    hSpinlock = g_hRTMpNotifySpinLock;
+    if (hSpinlock == NIL_RTSPINLOCK)
+        return;
+    RTSpinlockAcquire(hSpinlock);
+
+    /* Clear the bit. */
+    for (pCur = g_pRTMpCallbackHead; pCur; pCur = pCur->pNext)
+        ASMAtomicBitClear(&pCur->bmDone[0], iDone);
+
+    /* Iterate the records and perform the callbacks. */
+    do
+    {
+        uint32_t const iGeneration = ASMAtomicUoReadU32(&g_iRTMpGeneration);
+
+        pCur = g_pRTMpCallbackHead;
+        while (pCur)
+        {
+            if (!ASMAtomicBitTestAndSet(&pCur->bmDone[0], iDone))
+            {
+                PFNRTMPNOTIFICATION pfnCallback = pCur->pfnCallback;
+                void *pvUser = pCur->pvUser;
+                pCur = pCur->pNext;
+                RTSpinlockRelease(g_hRTMpNotifySpinLock);
+
+                pfnCallback(enmEvent, idCpu, pvUser);
+
+                /* carefully require the lock here, see RTR0MpNotificationTerm(). */
+                hSpinlock = g_hRTMpNotifySpinLock;
+                if (hSpinlock == NIL_RTSPINLOCK)
+                    return;
+                RTSpinlockAcquire(hSpinlock);
+                if (ASMAtomicUoReadU32(&g_iRTMpGeneration) != iGeneration)
+                    break;
+            }
+            else
+                pCur = pCur->pNext;
+        }
+    } while (pCur);
+
+    RTSpinlockRelease(hSpinlock);
+}
+
+
+
+RTDECL(int) RTMpNotificationRegister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser)
+{
+    PRTMPNOTIFYREG  pCur;
+    PRTMPNOTIFYREG  pNew;
+
+    /*
+     * Validation.
+     */
+    AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER);
+    AssertReturn(g_hRTMpNotifySpinLock != NIL_RTSPINLOCK, VERR_WRONG_ORDER);
+    RT_ASSERT_PREEMPTIBLE();
+
+    RTSpinlockAcquire(g_hRTMpNotifySpinLock);
+    for (pCur = g_pRTMpCallbackHead; pCur; pCur = pCur->pNext)
+        if (    pCur->pvUser == pvUser
+            &&  pCur->pfnCallback == pfnCallback)
+            break;
+    RTSpinlockRelease(g_hRTMpNotifySpinLock);
+    AssertMsgReturn(!pCur, ("pCur=%p pfnCallback=%p pvUser=%p\n", pCur, pfnCallback, pvUser), VERR_ALREADY_EXISTS);
+
+    /*
+     * Allocate a new record and attempt to insert it.
+     */
+    pNew = (PRTMPNOTIFYREG)RTMemAlloc(sizeof(*pNew));
+    if (!pNew)
+        return VERR_NO_MEMORY;
+
+    pNew->pNext = NULL;
+    pNew->pfnCallback = pfnCallback;
+    pNew->pvUser = pvUser;
+    memset(&pNew->bmDone[0], 0xff, sizeof(pNew->bmDone));
+
+    RTSpinlockAcquire(g_hRTMpNotifySpinLock);
+
+    pCur = g_pRTMpCallbackHead;
+    if (!pCur)
+        g_pRTMpCallbackHead = pNew;
+    else
+    {
+        for (pCur = g_pRTMpCallbackHead; ; pCur = pCur->pNext)
+            if (    pCur->pvUser == pvUser
+                &&  pCur->pfnCallback == pfnCallback)
+                break;
+            else if (!pCur->pNext)
+            {
+                pCur->pNext = pNew;
+                pCur = NULL;
+                break;
+            }
+    }
+
+    ASMAtomicIncU32(&g_iRTMpGeneration);
+
+    RTSpinlockRelease(g_hRTMpNotifySpinLock);
+
+    /* duplicate? */
+    if (pCur)
+    {
+        RTMemFree(pCur);
+        AssertMsgFailedReturn(("pCur=%p pfnCallback=%p pvUser=%p\n", pCur, pfnCallback, pvUser), VERR_ALREADY_EXISTS);
+    }
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTMpNotificationRegister);
+
+
+RTDECL(int) RTMpNotificationDeregister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser)
+{
+    PRTMPNOTIFYREG  pPrev;
+    PRTMPNOTIFYREG  pCur;
+
+    /*
+     * Validation.
+     */
+    AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER);
+    AssertReturn(g_hRTMpNotifySpinLock != NIL_RTSPINLOCK, VERR_WRONG_ORDER);
+    RT_ASSERT_INTS_ON();
+
+    /*
+     * Find and unlink the record from the list.
+     */
+    RTSpinlockAcquire(g_hRTMpNotifySpinLock);
+    pPrev = NULL;
+    for (pCur = g_pRTMpCallbackHead; pCur; pCur = pCur->pNext)
+    {
+        if (    pCur->pvUser == pvUser
+            &&  pCur->pfnCallback == pfnCallback)
+            break;
+        pPrev = pCur;
+    }
+    if (pCur)
+    {
+        if (pPrev)
+            pPrev->pNext = pCur->pNext;
+        else
+            g_pRTMpCallbackHead = pCur->pNext;
+        ASMAtomicIncU32(&g_iRTMpGeneration);
+    }
+    RTSpinlockRelease(g_hRTMpNotifySpinLock);
+
+    if (!pCur)
+        return VERR_NOT_FOUND;
+
+    /*
+     * Invalidate and free the record.
+     */
+    pCur->pNext = NULL;
+    pCur->pfnCallback = NULL;
+    RTMemFree(pCur);
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTMpNotificationDeregister);
+
+
+DECLHIDDEN(int) rtR0MpNotificationInit(void)
+{
+    int rc = RTSpinlockCreate((PRTSPINLOCK)&g_hRTMpNotifySpinLock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "RTR0Mp");
+    if (RT_SUCCESS(rc))
+    {
+        rc = rtR0MpNotificationNativeInit();
+        if (RT_SUCCESS(rc))
+            return rc;
+
+        RTSpinlockDestroy(g_hRTMpNotifySpinLock);
+        g_hRTMpNotifySpinLock = NIL_RTSPINLOCK;
+    }
+    return rc;
+}
+
+
+DECLHIDDEN(void) rtR0MpNotificationTerm(void)
+{
+    PRTMPNOTIFYREG  pHead;
+    RTSPINLOCK      hSpinlock = g_hRTMpNotifySpinLock;
+    AssertReturnVoid(hSpinlock != NIL_RTSPINLOCK);
+
+    rtR0MpNotificationNativeTerm();
+
+    /* pick up the list and the spinlock. */
+    RTSpinlockAcquire(hSpinlock);
+    ASMAtomicWriteHandle(&g_hRTMpNotifySpinLock, NIL_RTSPINLOCK);
+    pHead = g_pRTMpCallbackHead;
+    g_pRTMpCallbackHead = NULL;
+    ASMAtomicIncU32(&g_iRTMpGeneration);
+    RTSpinlockRelease(hSpinlock);
+
+    /* free the list. */
+    while (pHead)
+    {
+        PRTMPNOTIFYREG pFree = pHead;
+        pHead = pHead->pNext;
+
+        pFree->pNext = NULL;
+        pFree->pfnCallback = NULL;
+        RTMemFree(pFree);
+    }
+
+    RTSpinlockDestroy(hSpinlock);
+}
+
diff --git a/ubuntu/vbox/r0drv/power-r0drv.h b/ubuntu/vbox/r0drv/power-r0drv.h
new file mode 100644 (file)
index 0000000..ca9283a
--- /dev/null
@@ -0,0 +1,41 @@
+/* $Id: power-r0drv.h $ */
+/** @file
+ * IPRT - Power Management, Ring-0 Driver, Internal Header.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+#ifndef ___r0drv_powermgt_r0drv_h
+#define ___r0drv_powermgt_r0drv_h
+
+#include <iprt/power.h>
+
+RT_C_DECLS_BEGIN
+
+/* Called from initterm-r0drv.cpp: */
+DECLHIDDEN(int)  rtR0PowerNotificationInit(void);
+DECLHIDDEN(void) rtR0PowerNotificationTerm(void);
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/r0drv/powernotification-r0drv.c b/ubuntu/vbox/r0drv/powernotification-r0drv.c
new file mode 100644 (file)
index 0000000..92acef3
--- /dev/null
@@ -0,0 +1,318 @@
+/* $Id: powernotification-r0drv.c $ */
+/** @file
+ * IPRT - Power Management, Ring-0 Driver, Event Notifications.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/power.h>
+#include "internal/iprt.h"
+
+#include <iprt/asm.h>
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# include <iprt/asm-amd64-x86.h>
+#endif
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/mem.h>
+#include <iprt/spinlock.h>
+#include <iprt/string.h>
+#include <iprt/thread.h>
+#include "r0drv/mp-r0drv.h"
+#include "r0drv/power-r0drv.h"
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * Notification registration record tracking
+ * RTPowerRegisterNotification() calls.
+ */
+typedef struct RTPOWERNOTIFYREG
+{
+    /** Pointer to the next record. */
+    struct RTPOWERNOTIFYREG * volatile pNext;
+    /** The callback. */
+    PFNRTPOWERNOTIFICATION pfnCallback;
+    /** The user argument. */
+    void *pvUser;
+    /** Bit mask indicating whether we've done this callback or not. */
+    uint8_t bmDone[sizeof(void *)];
+} RTPOWERNOTIFYREG;
+/** Pointer to a registration record. */
+typedef RTPOWERNOTIFYREG *PRTPOWERNOTIFYREG;
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** The spinlock protecting the list. */
+static RTSPINLOCK volatile g_hRTPowerNotifySpinLock = NIL_RTSPINLOCK;
+/** List of callbacks, in registration order. */
+static PRTPOWERNOTIFYREG volatile g_pRTPowerCallbackHead = NULL;
+/** The current done bit. */
+static uint32_t volatile g_iRTPowerDoneBit;
+/** The list generation.
+ * This is increased whenever the list has been modified. The callback routine
+ * make use of this to avoid having restart at the list head after each callback. */
+static uint32_t volatile g_iRTPowerGeneration;
+
+
+
+
+RTDECL(int) RTPowerSignalEvent(RTPOWEREVENT enmEvent)
+{
+    PRTPOWERNOTIFYREG pCur;
+    RTSPINLOCK        hSpinlock;
+
+    /*
+     * This is a little bit tricky as we cannot be holding the spinlock
+     * while calling the callback. This means that the list might change
+     * while we're walking it, and that multiple events might be running
+     * concurrently (depending on the OS).
+     *
+     * So, the first measure is to employ a 32-bitmask for each
+     * record where we'll use a bit that rotates for each call to
+     * this function to indicate which records that has been
+     * processed. This will take care of both changes to the list
+     * and a reasonable amount of concurrent events.
+     *
+     * In order to avoid having to restart the list walks for every
+     * callback we make, we'll make use a list generation number that is
+     * incremented everytime the list is changed. So, if it remains
+     * unchanged over a callback we can safely continue the iteration.
+     */
+    uint32_t iDone = ASMAtomicIncU32(&g_iRTPowerDoneBit);
+    iDone %= RT_SIZEOFMEMB(RTPOWERNOTIFYREG, bmDone) * 8;
+
+    hSpinlock = g_hRTPowerNotifySpinLock;
+    if (hSpinlock == NIL_RTSPINLOCK)
+        return VERR_ACCESS_DENIED;
+    RTSpinlockAcquire(hSpinlock);
+
+    /* Clear the bit. */
+    for (pCur = g_pRTPowerCallbackHead; pCur; pCur = pCur->pNext)
+        ASMAtomicBitClear(&pCur->bmDone[0], iDone);
+
+    /* Iterate the records and perform the callbacks. */
+    do
+    {
+        uint32_t const iGeneration = ASMAtomicUoReadU32(&g_iRTPowerGeneration);
+
+        pCur = g_pRTPowerCallbackHead;
+        while (pCur)
+        {
+            if (!ASMAtomicBitTestAndSet(&pCur->bmDone[0], iDone))
+            {
+                PFNRTPOWERNOTIFICATION pfnCallback = pCur->pfnCallback;
+                void *pvUser = pCur->pvUser;
+                pCur = pCur->pNext;
+                RTSpinlockRelease(g_hRTPowerNotifySpinLock);
+
+                pfnCallback(enmEvent, pvUser);
+
+                /* carefully require the lock here, see RTR0MpNotificationTerm(). */
+                hSpinlock = g_hRTPowerNotifySpinLock;
+                if (hSpinlock == NIL_RTSPINLOCK)
+                    return VERR_ACCESS_DENIED;
+                RTSpinlockAcquire(hSpinlock);
+                if (ASMAtomicUoReadU32(&g_iRTPowerGeneration) != iGeneration)
+                    break;
+            }
+            else
+                pCur = pCur->pNext;
+        }
+    } while (pCur);
+
+    RTSpinlockRelease(hSpinlock);
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTPowerSignalEvent);
+
+
+RTDECL(int) RTPowerNotificationRegister(PFNRTPOWERNOTIFICATION pfnCallback, void *pvUser)
+{
+    PRTPOWERNOTIFYREG   pCur;
+    PRTPOWERNOTIFYREG   pNew;
+
+    /*
+     * Validation.
+     */
+    AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER);
+    AssertReturn(g_hRTPowerNotifySpinLock != NIL_RTSPINLOCK, VERR_WRONG_ORDER);
+    RT_ASSERT_PREEMPTIBLE();
+
+    RTSpinlockAcquire(g_hRTPowerNotifySpinLock);
+    for (pCur = g_pRTPowerCallbackHead; pCur; pCur = pCur->pNext)
+        if (    pCur->pvUser == pvUser
+            &&  pCur->pfnCallback == pfnCallback)
+            break;
+    RTSpinlockRelease(g_hRTPowerNotifySpinLock);
+    AssertMsgReturn(!pCur, ("pCur=%p pfnCallback=%p pvUser=%p\n", pCur, pfnCallback, pvUser), VERR_ALREADY_EXISTS);
+
+    /*
+     * Allocate a new record and attempt to insert it.
+     */
+    pNew = (PRTPOWERNOTIFYREG)RTMemAlloc(sizeof(*pNew));
+    if (!pNew)
+        return VERR_NO_MEMORY;
+
+    pNew->pNext = NULL;
+    pNew->pfnCallback = pfnCallback;
+    pNew->pvUser = pvUser;
+    memset(&pNew->bmDone[0], 0xff, sizeof(pNew->bmDone));
+
+    RTSpinlockAcquire(g_hRTPowerNotifySpinLock);
+
+    pCur = g_pRTPowerCallbackHead;
+    if (!pCur)
+        g_pRTPowerCallbackHead = pNew;
+    else
+    {
+        for (pCur = g_pRTPowerCallbackHead; ; pCur = pCur->pNext)
+            if (    pCur->pvUser == pvUser
+                &&  pCur->pfnCallback == pfnCallback)
+                break;
+            else if (!pCur->pNext)
+            {
+                pCur->pNext = pNew;
+                pCur = NULL;
+                break;
+            }
+    }
+
+    ASMAtomicIncU32(&g_iRTPowerGeneration);
+
+    RTSpinlockRelease(g_hRTPowerNotifySpinLock);
+
+    /* duplicate? */
+    if (pCur)
+    {
+        RTMemFree(pCur);
+        AssertMsgFailedReturn(("pCur=%p pfnCallback=%p pvUser=%p\n", pCur, pfnCallback, pvUser), VERR_ALREADY_EXISTS);
+    }
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTPowerNotificationRegister);
+
+
+RTDECL(int) RTPowerNotificationDeregister(PFNRTPOWERNOTIFICATION pfnCallback, void *pvUser)
+{
+    PRTPOWERNOTIFYREG   pPrev;
+    PRTPOWERNOTIFYREG   pCur;
+
+    /*
+     * Validation.
+     */
+    AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER);
+    AssertReturn(g_hRTPowerNotifySpinLock != NIL_RTSPINLOCK, VERR_WRONG_ORDER);
+    RT_ASSERT_INTS_ON();
+
+    /*
+     * Find and unlink the record from the list.
+     */
+    RTSpinlockAcquire(g_hRTPowerNotifySpinLock);
+    pPrev = NULL;
+    for (pCur = g_pRTPowerCallbackHead; pCur; pCur = pCur->pNext)
+    {
+        if (    pCur->pvUser == pvUser
+            &&  pCur->pfnCallback == pfnCallback)
+            break;
+        pPrev = pCur;
+    }
+    if (pCur)
+    {
+        if (pPrev)
+            pPrev->pNext = pCur->pNext;
+        else
+            g_pRTPowerCallbackHead = pCur->pNext;
+        ASMAtomicIncU32(&g_iRTPowerGeneration);
+    }
+    RTSpinlockRelease(g_hRTPowerNotifySpinLock);
+
+    if (!pCur)
+        return VERR_NOT_FOUND;
+
+    /*
+     * Invalidate and free the record.
+     */
+    pCur->pNext = NULL;
+    pCur->pfnCallback = NULL;
+    RTMemFree(pCur);
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTPowerNotificationDeregister);
+
+
+DECLHIDDEN(int) rtR0PowerNotificationInit(void)
+{
+    int rc = RTSpinlockCreate((PRTSPINLOCK)&g_hRTPowerNotifySpinLock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "RTR0Power");
+    if (RT_SUCCESS(rc))
+    {
+        /** @todo OS specific init here */
+        return rc;
+#if 0
+        RTSpinlockDestroy(g_hRTPowerNotifySpinLock);
+        g_hRTPowerNotifySpinLock = NIL_RTSPINLOCK;
+#endif
+    }
+    return rc;
+}
+
+
+DECLHIDDEN(void) rtR0PowerNotificationTerm(void)
+{
+    PRTPOWERNOTIFYREG   pHead;
+    RTSPINLOCK          hSpinlock = g_hRTPowerNotifySpinLock;
+    AssertReturnVoid(hSpinlock != NIL_RTSPINLOCK);
+
+    /** @todo OS specific term here */
+
+    /* pick up the list and the spinlock. */
+    RTSpinlockAcquire(hSpinlock);
+    ASMAtomicWriteHandle(&g_hRTPowerNotifySpinLock, NIL_RTSPINLOCK);
+    pHead = g_pRTPowerCallbackHead;
+    g_pRTPowerCallbackHead = NULL;
+    ASMAtomicIncU32(&g_iRTPowerGeneration);
+    RTSpinlockRelease(hSpinlock);
+
+    /* free the list. */
+    while (pHead)
+    {
+        PRTPOWERNOTIFYREG pFree = pHead;
+        pHead = pHead->pNext;
+
+        pFree->pNext = NULL;
+        pFree->pfnCallback = NULL;
+        RTMemFree(pFree);
+    }
+
+    RTSpinlockDestroy(hSpinlock);
+}
+
diff --git a/ubuntu/vbox/vboxguest/GenericRequest.c b/ubuntu/vbox/vboxguest/GenericRequest.c
new file mode 100644 (file)
index 0000000..22397fd
--- /dev/null
@@ -0,0 +1,170 @@
+/* $Id: GenericRequest.cpp $ */
+/** @file
+ * VBoxGuestLibR0 - Generic VMMDev request management.
+ */
+
+/*
+ * 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.
+ */
+
+#include "VBGLInternal.h"
+#include <iprt/asm.h>
+#include <iprt/asm-amd64-x86.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+
+
+DECLVBGL(int) VbglGRVerify(const VMMDevRequestHeader *pReq, size_t cbReq)
+{
+    size_t cbReqExpected;
+
+    if (RT_UNLIKELY(!pReq || cbReq < sizeof(VMMDevRequestHeader)))
+    {
+        dprintf(("VbglGRVerify: Invalid parameter: pReq = %p, cbReq = %zu\n", pReq, cbReq));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    if (RT_UNLIKELY(pReq->size > cbReq))
+    {
+        dprintf(("VbglGRVerify: request size %u > buffer size %zu\n", pReq->size, cbReq));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    /* The request size must correspond to the request type. */
+    cbReqExpected = vmmdevGetRequestSize(pReq->requestType);
+    if (RT_UNLIKELY(cbReq < cbReqExpected))
+    {
+        dprintf(("VbglGRVerify: buffer size %zu < expected size %zu\n", cbReq, cbReqExpected));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    if (cbReqExpected == cbReq)
+    {
+        /*
+         * This is most likely a fixed size request, and in this case the
+         * request size must be also equal to the expected size.
+         */
+        if (RT_UNLIKELY(pReq->size != cbReqExpected))
+        {
+            dprintf(("VbglGRVerify: request size %u != expected size %zu\n", pReq->size, cbReqExpected));
+            return VERR_INVALID_PARAMETER;
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    /*
+     * This can be a variable size request. Check the request type and limit the size
+     * to VMMDEV_MAX_VMMDEVREQ_SIZE, which is max size supported by the host.
+     *
+     * Note: Keep this list sorted for easier human lookup!
+     */
+    if (   pReq->requestType == VMMDevReq_ChangeMemBalloon
+#ifdef VBOX_WITH_64_BITS_GUESTS
+        || pReq->requestType == VMMDevReq_HGCMCall32
+        || pReq->requestType == VMMDevReq_HGCMCall64
+#else
+        || pReq->requestType == VMMDevReq_HGCMCall
+#endif
+        || pReq->requestType == VMMDevReq_RegisterSharedModule
+        || pReq->requestType == VMMDevReq_ReportGuestUserState
+        || pReq->requestType == VMMDevReq_LogString
+        || pReq->requestType == VMMDevReq_SetPointerShape
+        || pReq->requestType == VMMDevReq_VideoSetVisibleRegion)
+    {
+        if (RT_UNLIKELY(cbReq > VMMDEV_MAX_VMMDEVREQ_SIZE))
+        {
+            dprintf(("VbglGRVerify: VMMDevReq_LogString: buffer size %zu too big\n", cbReq));
+            return VERR_BUFFER_OVERFLOW; /** @todo is this error code ok? */
+        }
+    }
+    else
+    {
+        dprintf(("VbglGRVerify: request size %u > buffer size %zu\n", pReq->size, cbReq));
+        return VERR_IO_BAD_LENGTH; /** @todo is this error code ok? */
+    }
+
+    return VINF_SUCCESS;
+}
+
+DECLVBGL(int) VbglGRAlloc(VMMDevRequestHeader **ppReq, size_t cbReq, VMMDevRequestType enmReqType)
+{
+    int rc = vbglR0Enter();
+    if (RT_SUCCESS(rc))
+    {
+        if (   ppReq
+            && cbReq >= sizeof(VMMDevRequestHeader)
+            && cbReq == (uint32_t)cbReq)
+        {
+            VMMDevRequestHeader *pReq = (VMMDevRequestHeader *)VbglPhysHeapAlloc((uint32_t)cbReq);
+            AssertMsgReturn(pReq, ("VbglGRAlloc: no memory (cbReq=%u)\n", cbReq), VERR_NO_MEMORY);
+            memset(pReq, 0xAA, cbReq);
+
+            pReq->size        = (uint32_t)cbReq;
+            pReq->version     = VMMDEV_REQUEST_HEADER_VERSION;
+            pReq->requestType = enmReqType;
+            pReq->rc          = VERR_GENERAL_FAILURE;
+            pReq->reserved1   = 0;
+            pReq->reserved2   = 0;
+
+            *ppReq = pReq;
+            rc = VINF_SUCCESS;
+        }
+        else
+        {
+            dprintf(("VbglGRAlloc: Invalid parameter: ppReq=%p cbReq=%u\n", ppReq, cbReq));
+            rc = VERR_INVALID_PARAMETER;
+        }
+    }
+    return rc;
+}
+
+DECLVBGL(int) VbglGRPerform(VMMDevRequestHeader *pReq)
+{
+    int rc = vbglR0Enter();
+    if (RT_SUCCESS(rc))
+    {
+        if (pReq)
+        {
+            RTCCPHYS PhysAddr = VbglPhysHeapGetPhysAddr(pReq);
+            if (   PhysAddr != 0
+                && PhysAddr < _4G) /* Port IO is 32 bit. */
+            {
+                ASMOutU32(g_vbgldata.portVMMDev + VMMDEV_PORT_OFF_REQUEST, (uint32_t)PhysAddr);
+                /* Make the compiler aware that the host has changed memory. */
+                ASMCompilerBarrier();
+                rc = pReq->rc;
+            }
+            else
+                rc = VERR_VBGL_INVALID_ADDR;
+        }
+        else
+            rc = VERR_INVALID_PARAMETER;
+    }
+    return rc;
+}
+
+DECLVBGL(void) VbglGRFree(VMMDevRequestHeader *pReq)
+{
+    int rc = vbglR0Enter();
+    if (RT_SUCCESS(rc))
+        VbglPhysHeapFree(pReq);
+}
+
diff --git a/ubuntu/vbox/vboxguest/HGCMInternal.c b/ubuntu/vbox/vboxguest/HGCMInternal.c
new file mode 100644 (file)
index 0000000..8995206
--- /dev/null
@@ -0,0 +1,1082 @@
+/* $Id: HGCMInternal.cpp $ */
+/** @file
+ * VBoxGuestLib - Host-Guest Communication Manager internal functions, implemented by VBoxGuest
+ */
+
+/*
+ * 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.
+ */
+
+/* Entire file is ifdef'ed with VBGL_VBOXGUEST */
+#ifdef VBGL_VBOXGUEST
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_HGCM
+
+#include "VBGLInternal.h"
+#include <iprt/alloca.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/mem.h>
+#include <iprt/memobj.h>
+#include <iprt/string.h>
+#include <iprt/thread.h>
+#include <iprt/time.h>
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+/** The max parameter buffer size for a user request. */
+#define VBGLR0_MAX_HGCM_USER_PARM       (24*_1M)
+/** The max parameter buffer size for a kernel request. */
+#define VBGLR0_MAX_HGCM_KERNEL_PARM     (16*_1M)
+#if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN)
+/** Linux needs to use bounce buffers since RTR0MemObjLockUser has unwanted
+ * side effects.
+ * Darwin 32bit & 64bit also needs this because of 4GB/4GB user/kernel space. */
+# define USE_BOUNCE_BUFFERS
+#endif
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * Lock info structure used by VbglR0HGCMInternalCall and its helpers.
+ */
+struct VbglR0ParmInfo
+{
+    uint32_t cLockBufs;
+    struct
+    {
+        uint32_t    iParm;
+        RTR0MEMOBJ  hObj;
+#ifdef USE_BOUNCE_BUFFERS
+        void       *pvSmallBuf;
+#endif
+    } aLockBufs[10];
+};
+
+
+
+/* These functions can be only used by VBoxGuest. */
+
+DECLVBGL(int) VbglR0HGCMInternalConnect (VBoxGuestHGCMConnectInfo *pConnectInfo,
+                                         PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
+{
+    VMMDevHGCMConnect *pHGCMConnect;
+    int rc;
+
+    if (!pConnectInfo || !pfnAsyncCallback)
+        return VERR_INVALID_PARAMETER;
+
+    pHGCMConnect = NULL;
+
+    /* Allocate request */
+    rc = VbglGRAlloc ((VMMDevRequestHeader **)&pHGCMConnect, sizeof (VMMDevHGCMConnect), VMMDevReq_HGCMConnect);
+
+    if (RT_SUCCESS(rc))
+    {
+        /* Initialize request memory */
+        pHGCMConnect->header.fu32Flags = 0;
+
+        memcpy (&pHGCMConnect->loc, &pConnectInfo->Loc, sizeof (HGCMServiceLocation));
+        pHGCMConnect->u32ClientID = 0;
+
+        /* Issue request */
+        rc = VbglGRPerform (&pHGCMConnect->header.header);
+
+        if (RT_SUCCESS(rc))
+        {
+            /* Check if host decides to process the request asynchronously. */
+            if (rc == VINF_HGCM_ASYNC_EXECUTE)
+            {
+                /* Wait for request completion interrupt notification from host */
+                pfnAsyncCallback (&pHGCMConnect->header, pvAsyncData, u32AsyncData);
+            }
+
+            pConnectInfo->result = pHGCMConnect->header.result;
+
+            if (RT_SUCCESS (pConnectInfo->result))
+                pConnectInfo->u32ClientID = pHGCMConnect->u32ClientID;
+        }
+
+        VbglGRFree (&pHGCMConnect->header.header);
+    }
+
+    return rc;
+}
+
+
+DECLR0VBGL(int) VbglR0HGCMInternalDisconnect (VBoxGuestHGCMDisconnectInfo *pDisconnectInfo,
+                                              PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
+{
+    VMMDevHGCMDisconnect *pHGCMDisconnect;
+    int rc;
+
+    if (!pDisconnectInfo || !pfnAsyncCallback)
+        return VERR_INVALID_PARAMETER;
+
+    pHGCMDisconnect = NULL;
+
+    /* Allocate request */
+    rc = VbglGRAlloc ((VMMDevRequestHeader **)&pHGCMDisconnect, sizeof (VMMDevHGCMDisconnect), VMMDevReq_HGCMDisconnect);
+
+    if (RT_SUCCESS(rc))
+    {
+        /* Initialize request memory */
+        pHGCMDisconnect->header.fu32Flags = 0;
+
+        pHGCMDisconnect->u32ClientID = pDisconnectInfo->u32ClientID;
+
+        /* Issue request */
+        rc = VbglGRPerform (&pHGCMDisconnect->header.header);
+
+        if (RT_SUCCESS(rc))
+        {
+            /* Check if host decides to process the request asynchronously. */
+            if (rc == VINF_HGCM_ASYNC_EXECUTE)
+            {
+                /* Wait for request completion interrupt notification from host */
+                pfnAsyncCallback (&pHGCMDisconnect->header, pvAsyncData, u32AsyncData);
+            }
+
+            pDisconnectInfo->result = pHGCMDisconnect->header.result;
+        }
+
+        VbglGRFree (&pHGCMDisconnect->header.header);
+    }
+
+    return rc;
+}
+
+
+/**
+ * Preprocesses the HGCM call, validating and locking/buffering parameters.
+ *
+ * @returns VBox status code.
+ *
+ * @param   pCallInfo       The call info.
+ * @param   cbCallInfo      The size of the call info structure.
+ * @param   fIsUser         Is it a user request or kernel request.
+ * @param   pcbExtra        Where to return the extra request space needed for
+ *                          physical page lists.
+ */
+static int vbglR0HGCMInternalPreprocessCall(VBoxGuestHGCMCallInfo const *pCallInfo, uint32_t cbCallInfo,
+                                            bool fIsUser, struct VbglR0ParmInfo *pParmInfo,  size_t *pcbExtra)
+{
+    HGCMFunctionParameter const *pSrcParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
+    uint32_t    cParms = pCallInfo->cParms;
+    uint32_t    iParm;
+    uint32_t    cb;
+
+    /*
+     * Lock down the any linear buffers so we can get their addresses
+     * and figure out how much extra storage we need for page lists.
+     *
+     * Note! With kernel mode users we can be assertive. For user mode users
+     *       we should just (debug) log it and fail without any fanfare.
+     */
+    *pcbExtra = 0;
+    pParmInfo->cLockBufs = 0;
+    for (iParm = 0; iParm < cParms; iParm++, pSrcParm++)
+    {
+        switch (pSrcParm->type)
+        {
+            case VMMDevHGCMParmType_32bit:
+                Log4(("GstHGCMCall: parm=%u type=32bit: %#010x\n", iParm, pSrcParm->u.value32));
+                break;
+
+            case VMMDevHGCMParmType_64bit:
+                Log4(("GstHGCMCall: parm=%u type=64bit: %#018RX64\n", iParm, pSrcParm->u.value64));
+                break;
+
+            case VMMDevHGCMParmType_PageList:
+                if (fIsUser)
+                    return VERR_INVALID_PARAMETER;
+                cb = pSrcParm->u.PageList.size;
+                if (cb)
+                {
+                    uint32_t            off = pSrcParm->u.PageList.offset;
+                    HGCMPageListInfo   *pPgLst;
+                    uint32_t            cPages;
+                    uint32_t            u32;
+
+                    AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM),
+                                    VERR_OUT_OF_RANGE);
+                    AssertMsgReturn(   off >= pCallInfo->cParms * sizeof(HGCMFunctionParameter)
+                                    && off <= cbCallInfo - sizeof(HGCMPageListInfo),
+                                    ("offset=%#x cParms=%#x cbCallInfo=%#x\n", off, pCallInfo->cParms, cbCallInfo),
+                                    VERR_INVALID_PARAMETER);
+
+                    pPgLst = (HGCMPageListInfo *)((uint8_t *)pCallInfo + off);
+                    cPages = pPgLst->cPages;
+                    u32    = RT_OFFSETOF(HGCMPageListInfo, aPages[cPages]) + off;
+                    AssertMsgReturn(u32 <= cbCallInfo,
+                                    ("u32=%#x (cPages=%#x offset=%#x) cbCallInfo=%#x\n", u32, cPages, off, cbCallInfo),
+                                    VERR_INVALID_PARAMETER);
+                    AssertMsgReturn(pPgLst->offFirstPage < PAGE_SIZE, ("#x\n", pPgLst->offFirstPage), VERR_INVALID_PARAMETER);
+                    u32 = RT_ALIGN_32(pPgLst->offFirstPage + cb, PAGE_SIZE) >> PAGE_SHIFT;
+                    AssertMsgReturn(cPages == u32, ("cPages=%#x u32=%#x\n", cPages, u32), VERR_INVALID_PARAMETER);
+                    AssertMsgReturn(VBOX_HGCM_F_PARM_ARE_VALID(pPgLst->flags), ("%#x\n", pPgLst->flags), VERR_INVALID_PARAMETER);
+                    Log4(("GstHGCMCall: parm=%u type=pglst: cb=%#010x cPgs=%u offPg0=%#x flags=%#x\n",
+                          iParm, cb, cPages, pPgLst->offFirstPage, pPgLst->flags));
+                    u32 = cPages;
+                    while (u32-- > 0)
+                    {
+                        Log4(("GstHGCMCall:   pg#%u=%RHp\n", u32, pPgLst->aPages[u32]));
+                        AssertMsgReturn(!(pPgLst->aPages[u32] & (PAGE_OFFSET_MASK | UINT64_C(0xfff0000000000000))),
+                                        ("pg#%u=%RHp\n", u32, pPgLst->aPages[u32]),
+                                        VERR_INVALID_PARAMETER);
+                    }
+
+                    *pcbExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[pPgLst->cPages]);
+                }
+                else
+                    Log4(("GstHGCMCall: parm=%u type=pglst: cb=0\n", iParm));
+                break;
+
+            case VMMDevHGCMParmType_LinAddr_Locked_In:
+            case VMMDevHGCMParmType_LinAddr_Locked_Out:
+            case VMMDevHGCMParmType_LinAddr_Locked:
+                if (fIsUser)
+                    return VERR_INVALID_PARAMETER;
+                if (!VBGLR0_CAN_USE_PHYS_PAGE_LIST(/*a_fLocked =*/ true))
+                {
+                    cb = pSrcParm->u.Pointer.size;
+                    AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM),
+                                    VERR_OUT_OF_RANGE);
+                    if (cb != 0)
+                        Log4(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p\n",
+                              iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr));
+                    else
+                        Log4(("GstHGCMCall: parm=%u type=%#x: cb=0\n", iParm, pSrcParm->type));
+                    break;
+                }
+                /* fall thru */
+
+            case VMMDevHGCMParmType_LinAddr_In:
+            case VMMDevHGCMParmType_LinAddr_Out:
+            case VMMDevHGCMParmType_LinAddr:
+                cb = pSrcParm->u.Pointer.size;
+                if (cb != 0)
+                {
+#ifdef USE_BOUNCE_BUFFERS
+                    void       *pvSmallBuf = NULL;
+#endif
+                    uint32_t    iLockBuf   = pParmInfo->cLockBufs;
+                    RTR0MEMOBJ  hObj;
+                    int         rc;
+                    uint32_t    fAccess =    pSrcParm->type == VMMDevHGCMParmType_LinAddr_In
+                                          || pSrcParm->type == VMMDevHGCMParmType_LinAddr_Locked_In
+                                        ? RTMEM_PROT_READ
+                                        : RTMEM_PROT_READ | RTMEM_PROT_WRITE;
+
+                    AssertReturn(iLockBuf < RT_ELEMENTS(pParmInfo->aLockBufs), VERR_INVALID_PARAMETER);
+                    if (!fIsUser)
+                    {
+                        AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM),
+                                        VERR_OUT_OF_RANGE);
+                        rc = RTR0MemObjLockKernel(&hObj, (void *)pSrcParm->u.Pointer.u.linearAddr, cb, fAccess);
+                        if (RT_FAILURE(rc))
+                        {
+                            Log(("GstHGCMCall: id=%#x fn=%u parm=%u RTR0MemObjLockKernel(,%p,%#x) -> %Rrc\n",
+                                 pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, pSrcParm->u.Pointer.u.linearAddr, cb, rc));
+                            return rc;
+                        }
+                        Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p locked kernel -> %p\n",
+                              iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj));
+                    }
+                    else if (cb > VBGLR0_MAX_HGCM_USER_PARM)
+                    {
+                        Log(("GstHGCMCall: id=%#x fn=%u parm=%u pv=%p cb=%#x > %#x -> out of range\n",
+                             pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, pSrcParm->u.Pointer.u.linearAddr,
+                             cb, VBGLR0_MAX_HGCM_USER_PARM));
+                        return VERR_OUT_OF_RANGE;
+                    }
+                    else
+                    {
+#ifndef USE_BOUNCE_BUFFERS
+                        rc = RTR0MemObjLockUser(&hObj, (RTR3PTR)pSrcParm->u.Pointer.u.linearAddr, cb, fAccess, NIL_RTR0PROCESS);
+                        if (RT_FAILURE(rc))
+                        {
+                            Log(("GstHGCMCall: id=%#x fn=%u parm=%u RTR0MemObjLockUser(,%p,%#x,nil) -> %Rrc\n",
+                                 pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, pSrcParm->u.Pointer.u.linearAddr, cb, rc));
+                            return rc;
+                        }
+                        Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p locked user -> %p\n",
+                              iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj));
+
+#else  /* USE_BOUNCE_BUFFERS */
+                        /*
+                         * This is a bit massive, but we don't want to waste a
+                         * whole page for a 3 byte string buffer (guest props).
+                         *
+                         * The threshold is ASSUMING sizeof(RTMEMHDR) == 16 and
+                         * the system is using some power of two allocator.
+                         */
+                        /** @todo A more efficient strategy would be to combine buffers. However it
+                         *        is probably going to be more massive than the current code, so
+                         *        it can wait till later. */
+                        bool fCopyIn = pSrcParm->type != VMMDevHGCMParmType_LinAddr_Out
+                                    && pSrcParm->type != VMMDevHGCMParmType_LinAddr_Locked_Out;
+                        if (cb <= PAGE_SIZE / 2 - 16)
+                        {
+                            pvSmallBuf = fCopyIn ? RTMemTmpAlloc(cb) : RTMemTmpAllocZ(cb);
+                            if (RT_UNLIKELY(!pvSmallBuf))
+                                return VERR_NO_MEMORY;
+                            if (fCopyIn)
+                            {
+                                rc = RTR0MemUserCopyFrom(pvSmallBuf, pSrcParm->u.Pointer.u.linearAddr, cb);
+                                if (RT_FAILURE(rc))
+                                {
+                                    RTMemTmpFree(pvSmallBuf);
+                                    Log(("GstHGCMCall: id=%#x fn=%u parm=%u RTR0MemUserCopyFrom(,%p,%#x) -> %Rrc\n",
+                                         pCallInfo->u32ClientID, pCallInfo->u32Function, iParm,
+                                         pSrcParm->u.Pointer.u.linearAddr, cb, rc));
+                                    return rc;
+                                }
+                            }
+                            rc = RTR0MemObjLockKernel(&hObj, pvSmallBuf, cb, fAccess);
+                            if (RT_FAILURE(rc))
+                            {
+                                RTMemTmpFree(pvSmallBuf);
+                                Log(("GstHGCMCall: RTR0MemObjLockKernel failed for small buffer: rc=%Rrc pvSmallBuf=%p cb=%#x\n",
+                                     rc, pvSmallBuf, cb));
+                                return rc;
+                            }
+                            Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p small buffer %p -> %p\n",
+                                  iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, pvSmallBuf, hObj));
+                        }
+                        else
+                        {
+                            rc = RTR0MemObjAllocPage(&hObj, cb, false /*fExecutable*/);
+                            if (RT_FAILURE(rc))
+                                return rc;
+                            if (!fCopyIn)
+                                memset(RTR0MemObjAddress(hObj), '\0', cb);
+                            else
+                            {
+                                rc = RTR0MemUserCopyFrom(RTR0MemObjAddress(hObj), pSrcParm->u.Pointer.u.linearAddr, cb);
+                                if (RT_FAILURE(rc))
+                                {
+                                    RTR0MemObjFree(hObj, false /*fFreeMappings*/);
+                                    Log(("GstHGCMCall: id=%#x fn=%u parm=%u RTR0MemUserCopyFrom(,%p,%#x) -> %Rrc\n",
+                                         pCallInfo->u32ClientID, pCallInfo->u32Function, iParm,
+                                         pSrcParm->u.Pointer.u.linearAddr, cb, rc));
+                                    return rc;
+                                }
+                            }
+                            Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p big buffer -> %p\n",
+                                  iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj));
+                        }
+#endif /* USE_BOUNCE_BUFFERS */
+                    }
+
+                    pParmInfo->aLockBufs[iLockBuf].iParm      = iParm;
+                    pParmInfo->aLockBufs[iLockBuf].hObj       = hObj;
+#ifdef USE_BOUNCE_BUFFERS
+                    pParmInfo->aLockBufs[iLockBuf].pvSmallBuf = pvSmallBuf;
+#endif
+                    pParmInfo->cLockBufs = iLockBuf + 1;
+
+                    if (VBGLR0_CAN_USE_PHYS_PAGE_LIST(/*a_fLocked =*/ false))
+                    {
+                        size_t const cPages = RTR0MemObjSize(hObj) >> PAGE_SHIFT;
+                        *pcbExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[cPages]);
+                    }
+                }
+                else
+                    Log4(("GstHGCMCall: parm=%u type=%#x: cb=0\n", iParm, pSrcParm->type));
+                break;
+
+            default:
+                return VERR_INVALID_PARAMETER;
+        }
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Translates locked linear address to the normal type.
+ * The locked types are only for the guest side and not handled by the host.
+ *
+ * @returns normal linear address type.
+ * @param   enmType     The type.
+ */
+static HGCMFunctionParameterType vbglR0HGCMInternalConvertLinAddrType(HGCMFunctionParameterType enmType)
+{
+    switch (enmType)
+    {
+        case VMMDevHGCMParmType_LinAddr_Locked_In:
+            return VMMDevHGCMParmType_LinAddr_In;
+        case VMMDevHGCMParmType_LinAddr_Locked_Out:
+            return VMMDevHGCMParmType_LinAddr_Out;
+        case VMMDevHGCMParmType_LinAddr_Locked:
+            return VMMDevHGCMParmType_LinAddr;
+        default:
+            return enmType;
+    }
+}
+
+
+/**
+ * Translates linear address types to page list direction flags.
+ *
+ * @returns page list flags.
+ * @param   enmType     The type.
+ */
+static uint32_t vbglR0HGCMInternalLinAddrTypeToPageListFlags(HGCMFunctionParameterType enmType)
+{
+    switch (enmType)
+    {
+        case VMMDevHGCMParmType_LinAddr_In:
+        case VMMDevHGCMParmType_LinAddr_Locked_In:
+            return VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+
+        case VMMDevHGCMParmType_LinAddr_Out:
+        case VMMDevHGCMParmType_LinAddr_Locked_Out:
+            return VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
+
+        default: AssertFailed();
+        case VMMDevHGCMParmType_LinAddr:
+        case VMMDevHGCMParmType_LinAddr_Locked:
+            return VBOX_HGCM_F_PARM_DIRECTION_BOTH;
+    }
+}
+
+
+/**
+ * Initializes the call request that we're sending to the host.
+ *
+ * @returns VBox status code.
+ *
+ * @param   pCallInfo       The call info.
+ * @param   cbCallInfo      The size of the call info structure.
+ * @param   fIsUser         Is it a user request or kernel request.
+ * @param   pcbExtra        Where to return the extra request space needed for
+ *                          physical page lists.
+ */
+static void vbglR0HGCMInternalInitCall(VMMDevHGCMCall *pHGCMCall, VBoxGuestHGCMCallInfo const *pCallInfo,
+                                       uint32_t cbCallInfo, bool fIsUser, struct VbglR0ParmInfo *pParmInfo)
+{
+    HGCMFunctionParameter const *pSrcParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
+    HGCMFunctionParameter       *pDstParm = VMMDEV_HGCM_CALL_PARMS(pHGCMCall);
+    uint32_t    cParms   = pCallInfo->cParms;
+    uint32_t    offExtra = (uint32_t)((uintptr_t)(pDstParm + cParms) - (uintptr_t)pHGCMCall);
+    uint32_t    iLockBuf = 0;
+    uint32_t    iParm;
+    RT_NOREF1(cbCallInfo);
+#ifndef USE_BOUNCE_BUFFERS
+    RT_NOREF1(fIsUser);
+#endif
+
+    /*
+     * The call request headers.
+     */
+    pHGCMCall->header.fu32Flags = 0;
+    pHGCMCall->header.result    = VINF_SUCCESS;
+
+    pHGCMCall->u32ClientID = pCallInfo->u32ClientID;
+    pHGCMCall->u32Function = pCallInfo->u32Function;
+    pHGCMCall->cParms      = cParms;
+
+    /*
+     * The parameters.
+     */
+    for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pSrcParm++, pDstParm++)
+    {
+        switch (pSrcParm->type)
+        {
+            case VMMDevHGCMParmType_32bit:
+            case VMMDevHGCMParmType_64bit:
+                *pDstParm = *pSrcParm;
+                break;
+
+            case VMMDevHGCMParmType_PageList:
+                pDstParm->type = VMMDevHGCMParmType_PageList;
+                pDstParm->u.PageList.size = pSrcParm->u.PageList.size;
+                if (pSrcParm->u.PageList.size)
+                {
+                    HGCMPageListInfo const *pSrcPgLst = (HGCMPageListInfo *)((uint8_t *)pCallInfo + pSrcParm->u.PageList.offset);
+                    HGCMPageListInfo       *pDstPgLst = (HGCMPageListInfo *)((uint8_t *)pHGCMCall + offExtra);
+                    uint32_t const          cPages    = pSrcPgLst->cPages;
+                    uint32_t                iPage;
+
+                    pDstParm->u.PageList.offset = offExtra;
+                    pDstPgLst->flags            = pSrcPgLst->flags;
+                    pDstPgLst->offFirstPage     = pSrcPgLst->offFirstPage;
+                    pDstPgLst->cPages           = cPages;
+                    for (iPage = 0; iPage < cPages; iPage++)
+                        pDstPgLst->aPages[iPage] = pSrcPgLst->aPages[iPage];
+
+                    offExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[cPages]);
+                }
+                else
+                    pDstParm->u.PageList.offset = 0;
+                break;
+
+            case VMMDevHGCMParmType_LinAddr_Locked_In:
+            case VMMDevHGCMParmType_LinAddr_Locked_Out:
+            case VMMDevHGCMParmType_LinAddr_Locked:
+                if (!VBGLR0_CAN_USE_PHYS_PAGE_LIST(/*a_fLocked =*/ true))
+                {
+                    *pDstParm = *pSrcParm;
+                    pDstParm->type = vbglR0HGCMInternalConvertLinAddrType(pSrcParm->type);
+                    break;
+                }
+                /* fall thru */
+
+            case VMMDevHGCMParmType_LinAddr_In:
+            case VMMDevHGCMParmType_LinAddr_Out:
+            case VMMDevHGCMParmType_LinAddr:
+                if (pSrcParm->u.Pointer.size != 0)
+                {
+#ifdef USE_BOUNCE_BUFFERS
+                    void      *pvSmallBuf = pParmInfo->aLockBufs[iLockBuf].pvSmallBuf;
+#endif
+                    RTR0MEMOBJ hObj       = pParmInfo->aLockBufs[iLockBuf].hObj;
+                    Assert(iParm == pParmInfo->aLockBufs[iLockBuf].iParm);
+
+                    if (VBGLR0_CAN_USE_PHYS_PAGE_LIST(/*a_fLocked =*/ false))
+                    {
+                        HGCMPageListInfo   *pDstPgLst = (HGCMPageListInfo *)((uint8_t *)pHGCMCall + offExtra);
+                        size_t const        cPages    = RTR0MemObjSize(hObj) >> PAGE_SHIFT;
+                        size_t              iPage;
+
+                        pDstParm->type = VMMDevHGCMParmType_PageList;
+                        pDstParm->u.PageList.size   = pSrcParm->u.Pointer.size;
+                        pDstParm->u.PageList.offset = offExtra;
+                        pDstPgLst->flags            = vbglR0HGCMInternalLinAddrTypeToPageListFlags(pSrcParm->type);
+#ifdef USE_BOUNCE_BUFFERS
+                        if (fIsUser)
+                            pDstPgLst->offFirstPage = (uintptr_t)pvSmallBuf & PAGE_OFFSET_MASK;
+                        else
+#endif
+                            pDstPgLst->offFirstPage = pSrcParm->u.Pointer.u.linearAddr & PAGE_OFFSET_MASK;
+                        pDstPgLst->cPages           = (uint32_t)cPages; Assert(pDstPgLst->cPages == cPages);
+                        for (iPage = 0; iPage < cPages; iPage++)
+                        {
+                            pDstPgLst->aPages[iPage] = RTR0MemObjGetPagePhysAddr(hObj, iPage);
+                            Assert(pDstPgLst->aPages[iPage] != NIL_RTHCPHYS);
+                        }
+
+                        offExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[cPages]);
+                    }
+                    else
+                    {
+                        pDstParm->type = vbglR0HGCMInternalConvertLinAddrType(pSrcParm->type);
+                        pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size;
+#ifdef USE_BOUNCE_BUFFERS
+                        if (fIsUser)
+                            pDstParm->u.Pointer.u.linearAddr = pvSmallBuf
+                                                             ? (uintptr_t)pvSmallBuf
+                                                             : (uintptr_t)RTR0MemObjAddress(hObj);
+                        else
+#endif
+                            pDstParm->u.Pointer.u.linearAddr = pSrcParm->u.Pointer.u.linearAddr;
+                    }
+                    iLockBuf++;
+                }
+                else
+                {
+                    pDstParm->type = vbglR0HGCMInternalConvertLinAddrType(pSrcParm->type);
+                    pDstParm->u.Pointer.size = 0;
+                    pDstParm->u.Pointer.u.linearAddr = 0;
+                }
+                break;
+
+            default:
+                AssertFailed();
+                pDstParm->type = VMMDevHGCMParmType_Invalid;
+                break;
+        }
+    }
+}
+
+
+/**
+ * Performs the call and completion wait.
+ *
+ * @returns VBox status code of this operation, not necessarily the call.
+ *
+ * @param   pHGCMCall           The HGCM call info.
+ * @param   pfnAsyncCallback    The async callback that will wait for the call
+ *                              to complete.
+ * @param   pvAsyncData         Argument for the callback.
+ * @param   u32AsyncData        Argument for the callback.
+ * @param   pfLeakIt            Where to return the leak it / free it,
+ *                              indicator. Cancellation fun.
+ */
+static int vbglR0HGCMInternalDoCall(VMMDevHGCMCall *pHGCMCall, PFNVBGLHGCMCALLBACK pfnAsyncCallback,
+                                    void *pvAsyncData, uint32_t u32AsyncData, bool *pfLeakIt)
+{
+    int rc;
+
+    Log(("calling VbglGRPerform\n"));
+    rc = VbglGRPerform(&pHGCMCall->header.header);
+    Log(("VbglGRPerform rc = %Rrc (header rc=%d)\n", rc, pHGCMCall->header.result));
+
+    /*
+     * If the call failed, but as a result of the request itself, then pretend
+     * success. Upper layers will interpret the result code in the packet.
+     */
+    if (    RT_FAILURE(rc)
+        &&  rc == pHGCMCall->header.result)
+    {
+        Assert(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE);
+        rc = VINF_SUCCESS;
+    }
+
+    /*
+     * Check if host decides to process the request asynchronously,
+     * if so, we wait for it to complete using the caller supplied callback.
+     */
+    *pfLeakIt = false;
+    if (rc == VINF_HGCM_ASYNC_EXECUTE)
+    {
+        Log(("Processing HGCM call asynchronously\n"));
+        rc = pfnAsyncCallback(&pHGCMCall->header, pvAsyncData, u32AsyncData);
+        if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)
+        {
+            Assert(!(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_CANCELLED));
+            rc = VINF_SUCCESS;
+        }
+        else
+        {
+            /*
+             * The request didn't complete in time or the call was interrupted,
+             * the RC from the callback indicates which. Try cancel the request.
+             *
+             * This is a bit messy because we're racing request completion. Sorry.
+             */
+            /** @todo It would be nice if we could use the waiter callback to do further
+             *  waiting in case of a completion race. If it wasn't for WINNT having its own
+             *  version of all that stuff, I would've done it already. */
+            VMMDevHGCMCancel2 *pCancelReq;
+            int rc2 = VbglGRAlloc((VMMDevRequestHeader **)&pCancelReq, sizeof(*pCancelReq), VMMDevReq_HGCMCancel2);
+            if (RT_SUCCESS(rc2))
+            {
+                pCancelReq->physReqToCancel = VbglPhysHeapGetPhysAddr(pHGCMCall);
+                rc2 = VbglGRPerform(&pCancelReq->header);
+                VbglGRFree(&pCancelReq->header);
+            }
+#if 1 /** @todo ADDVER: Remove this on next minor version change. */
+            if (rc2 == VERR_NOT_IMPLEMENTED)
+            {
+                /* host is too old, or we're out of heap. */
+                pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED;
+                pHGCMCall->header.header.requestType = VMMDevReq_HGCMCancel;
+                rc2 = VbglGRPerform(&pHGCMCall->header.header);
+                if (rc2 == VERR_INVALID_PARAMETER)
+                    rc2 = VERR_NOT_FOUND;
+                else if (RT_SUCCESS(rc))
+                    RTThreadSleep(1);
+            }
+#endif
+            if (RT_SUCCESS(rc)) rc = VERR_INTERRUPTED; /** @todo weed this out from the WINNT VBoxGuest code. */
+            if (RT_SUCCESS(rc2))
+            {
+                Log(("vbglR0HGCMInternalDoCall: successfully cancelled\n"));
+                pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED;
+            }
+            else
+            {
+                /*
+                 * Wait for a bit while the host (hopefully) completes it.
+                 */
+                uint64_t u64Start       = RTTimeSystemMilliTS();
+                uint32_t cMilliesToWait = rc2 == VERR_NOT_FOUND || rc2 == VERR_SEM_DESTROYED ? 500 : 2000;
+                uint64_t cElapsed       = 0;
+                if (rc2 != VERR_NOT_FOUND)
+                {
+                    static unsigned s_cErrors = 0;
+                    if (s_cErrors++ < 32)
+                        LogRel(("vbglR0HGCMInternalDoCall: Failed to cancel the HGCM call on %Rrc: rc2=%Rrc\n", rc, rc2));
+                }
+                else
+                    Log(("vbglR0HGCMInternalDoCall: Cancel race rc=%Rrc rc2=%Rrc\n", rc, rc2));
+
+                do
+                {
+                    ASMCompilerBarrier();       /* paranoia */
+                    if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)
+                        break;
+                    RTThreadSleep(1);
+                    cElapsed = RTTimeSystemMilliTS() - u64Start;
+                } while (cElapsed < cMilliesToWait);
+
+                ASMCompilerBarrier();           /* paranoia^2 */
+                if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)
+                    rc = VINF_SUCCESS;
+                else
+                {
+                    LogRel(("vbglR0HGCMInternalDoCall: Leaking %u bytes. Pending call to %u with %u parms. (rc2=%Rrc)\n",
+                            pHGCMCall->header.header.size, pHGCMCall->u32Function, pHGCMCall->cParms, rc2));
+                    *pfLeakIt = true;
+                }
+                Log(("vbglR0HGCMInternalDoCall: Cancel race ended with rc=%Rrc (rc2=%Rrc) after %llu ms\n", rc, rc2, cElapsed));
+            }
+        }
+    }
+
+    Log(("GstHGCMCall: rc=%Rrc result=%Rrc fu32Flags=%#x fLeakIt=%d\n",
+         rc, pHGCMCall->header.result, pHGCMCall->header.fu32Flags, *pfLeakIt));
+    return rc;
+}
+
+
+/**
+ * Copies the result of the call back to the caller info structure and user
+ * buffers (if using bounce buffers).
+ *
+ * @returns rc, unless RTR0MemUserCopyTo fails.
+ * @param   pCallInfo           Call info structure to update.
+ * @param   pHGCMCall           HGCM call request.
+ * @param   pParmInfo           Parameter locking/buffering info.
+ * @param   fIsUser             Is it a user (true) or kernel request.
+ * @param   rc                  The current result code. Passed along to
+ *                              preserve informational status codes.
+ */
+static int vbglR0HGCMInternalCopyBackResult(VBoxGuestHGCMCallInfo *pCallInfo, VMMDevHGCMCall const *pHGCMCall,
+                                            struct VbglR0ParmInfo *pParmInfo, bool fIsUser, int rc)
+{
+    HGCMFunctionParameter const *pSrcParm = VMMDEV_HGCM_CALL_PARMS(pHGCMCall);
+    HGCMFunctionParameter       *pDstParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
+    uint32_t    cParms   = pCallInfo->cParms;
+#ifdef USE_BOUNCE_BUFFERS
+    uint32_t    iLockBuf = 0;
+#endif
+    uint32_t    iParm;
+    RT_NOREF1(pParmInfo);
+#ifndef USE_BOUNCE_BUFFERS
+    RT_NOREF1(fIsUser);
+#endif
+
+    /*
+     * The call result.
+     */
+    pCallInfo->result = pHGCMCall->header.result;
+
+    /*
+     * Copy back parameters.
+     */
+    for (iParm = 0; iParm < cParms; iParm++, pSrcParm++, pDstParm++)
+    {
+        switch (pDstParm->type)
+        {
+            case VMMDevHGCMParmType_32bit:
+            case VMMDevHGCMParmType_64bit:
+                *pDstParm = *pSrcParm;
+                break;
+
+            case VMMDevHGCMParmType_PageList:
+                pDstParm->u.PageList.size = pSrcParm->u.PageList.size;
+                break;
+
+            case VMMDevHGCMParmType_LinAddr_Locked_In:
+            case VMMDevHGCMParmType_LinAddr_In:
+#ifdef USE_BOUNCE_BUFFERS
+                if (    fIsUser
+                    &&  iLockBuf < pParmInfo->cLockBufs
+                    &&  iParm   == pParmInfo->aLockBufs[iLockBuf].iParm)
+                    iLockBuf++;
+#endif
+                pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size;
+                break;
+
+            case VMMDevHGCMParmType_LinAddr_Locked_Out:
+            case VMMDevHGCMParmType_LinAddr_Locked:
+                if (!VBGLR0_CAN_USE_PHYS_PAGE_LIST(/*a_fLocked =*/ true))
+                {
+                    pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size;
+                    break;
+                }
+                /* fall thru */
+
+            case VMMDevHGCMParmType_LinAddr_Out:
+            case VMMDevHGCMParmType_LinAddr:
+            {
+#ifdef USE_BOUNCE_BUFFERS
+                if (fIsUser)
+                {
+                    size_t cbOut = RT_MIN(pSrcParm->u.Pointer.size, pDstParm->u.Pointer.size);
+                    if (cbOut)
+                    {
+                        int rc2;
+                        Assert(pParmInfo->aLockBufs[iLockBuf].iParm == iParm);
+                        rc2 = RTR0MemUserCopyTo((RTR3PTR)pDstParm->u.Pointer.u.linearAddr,
+                                                pParmInfo->aLockBufs[iLockBuf].pvSmallBuf
+                                                ? pParmInfo->aLockBufs[iLockBuf].pvSmallBuf
+                                                : RTR0MemObjAddress(pParmInfo->aLockBufs[iLockBuf].hObj),
+                                                cbOut);
+                        if (RT_FAILURE(rc2))
+                            return rc2;
+                        iLockBuf++;
+                    }
+                    else if (   iLockBuf < pParmInfo->cLockBufs
+                             && iParm   == pParmInfo->aLockBufs[iLockBuf].iParm)
+                        iLockBuf++;
+                }
+#endif
+                pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size;
+                break;
+            }
+
+            default:
+                AssertFailed();
+                rc = VERR_INTERNAL_ERROR_4;
+                break;
+        }
+    }
+
+#ifdef USE_BOUNCE_BUFFERS
+    Assert(!fIsUser || pParmInfo->cLockBufs == iLockBuf);
+#endif
+    return rc;
+}
+
+
+DECLR0VBGL(int) VbglR0HGCMInternalCall(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
+                                       PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
+{
+    bool                    fIsUser = (fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER;
+    struct VbglR0ParmInfo   ParmInfo;
+    size_t                  cbExtra;
+    int                     rc;
+
+    /*
+     * Basic validation.
+     */
+    AssertMsgReturn(   !pCallInfo
+                    || !pfnAsyncCallback
+                    || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS
+                    || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK),
+                    ("pCallInfo=%p pfnAsyncCallback=%p fFlags=%#x\n", pCallInfo, pfnAsyncCallback, fFlags),
+                    VERR_INVALID_PARAMETER);
+    AssertReturn(   cbCallInfo >= sizeof(VBoxGuestHGCMCallInfo)
+                 || cbCallInfo >= pCallInfo->cParms * sizeof(HGCMFunctionParameter),
+                 VERR_INVALID_PARAMETER);
+
+    Log(("GstHGCMCall: u32ClientID=%#x u32Function=%u cParms=%u cbCallInfo=%#x fFlags=%#x\n",
+         pCallInfo->u32ClientID, pCallInfo->u32ClientID, pCallInfo->u32Function, pCallInfo->cParms, cbCallInfo, fFlags));
+
+    /*
+     * Validate, lock and buffer the parameters for the call.
+     * This will calculate the amount of extra space for physical page list.
+     */
+    rc = vbglR0HGCMInternalPreprocessCall(pCallInfo, cbCallInfo, fIsUser, &ParmInfo, &cbExtra);
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Allocate the request buffer and recreate the call request.
+         */
+        VMMDevHGCMCall *pHGCMCall;
+        rc = VbglGRAlloc((VMMDevRequestHeader **)&pHGCMCall,
+                         sizeof(VMMDevHGCMCall) + pCallInfo->cParms * sizeof(HGCMFunctionParameter) + cbExtra,
+                         VMMDevReq_HGCMCall);
+        if (RT_SUCCESS(rc))
+        {
+            bool fLeakIt;
+            vbglR0HGCMInternalInitCall(pHGCMCall, pCallInfo, cbCallInfo, fIsUser, &ParmInfo);
+
+            /*
+             * Perform the call.
+             */
+            rc = vbglR0HGCMInternalDoCall(pHGCMCall, pfnAsyncCallback, pvAsyncData, u32AsyncData, &fLeakIt);
+            if (RT_SUCCESS(rc))
+            {
+                /*
+                 * Copy back the result (parameters and buffers that changed).
+                 */
+                rc = vbglR0HGCMInternalCopyBackResult(pCallInfo, pHGCMCall, &ParmInfo, fIsUser, rc);
+            }
+            else
+            {
+                if (   rc != VERR_INTERRUPTED
+                    && rc != VERR_TIMEOUT)
+                {
+                    static unsigned s_cErrors = 0;
+                    if (s_cErrors++ < 32)
+                        LogRel(("VbglR0HGCMInternalCall: vbglR0HGCMInternalDoCall failed. rc=%Rrc\n", rc));
+                }
+            }
+
+            if (!fLeakIt)
+                VbglGRFree(&pHGCMCall->header.header);
+        }
+    }
+    else
+        LogRel(("VbglR0HGCMInternalCall: vbglR0HGCMInternalPreprocessCall failed. rc=%Rrc\n", rc));
+
+    /*
+     * Release locks and free bounce buffers.
+     */
+    if (ParmInfo.cLockBufs)
+        while (ParmInfo.cLockBufs-- > 0)
+        {
+            RTR0MemObjFree(ParmInfo.aLockBufs[ParmInfo.cLockBufs].hObj, false /*fFreeMappings*/);
+#ifdef USE_BOUNCE_BUFFERS
+            RTMemTmpFree(ParmInfo.aLockBufs[ParmInfo.cLockBufs].pvSmallBuf);
+#endif
+        }
+
+    return rc;
+}
+
+
+#if ARCH_BITS == 64
+DECLR0VBGL(int) VbglR0HGCMInternalCall32(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
+                                         PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
+{
+    VBoxGuestHGCMCallInfo   *pCallInfo64 = NULL;
+    HGCMFunctionParameter   *pParm64 = NULL;
+    HGCMFunctionParameter32 *pParm32 = NULL;
+    uint32_t                 cParms = 0;
+    uint32_t                 iParm = 0;
+    int                      rc = VINF_SUCCESS;
+
+    /*
+     * Input validation.
+     */
+    AssertMsgReturn(    !pCallInfo
+                    ||  !pfnAsyncCallback
+                    ||  pCallInfo->cParms > VBOX_HGCM_MAX_PARMS
+                    || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK),
+                    ("pCallInfo=%p pfnAsyncCallback=%p fFlags=%#x\n", pCallInfo, pfnAsyncCallback, fFlags),
+                    VERR_INVALID_PARAMETER);
+    AssertReturn(   cbCallInfo >= sizeof(VBoxGuestHGCMCallInfo)
+                 || cbCallInfo >= pCallInfo->cParms * sizeof(HGCMFunctionParameter32),
+                 VERR_INVALID_PARAMETER);
+
+    /* This Assert does not work on Solaris/Windows 64/32 mixed mode, not sure why, skipping for now */
+#if !defined(RT_OS_SOLARIS) && !defined(RT_OS_WINDOWS)
+    AssertReturn((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_KERNEL, VERR_WRONG_ORDER);
+#endif
+
+    cParms = pCallInfo->cParms;
+    Log(("VbglR0HGCMInternalCall32: cParms=%d, u32Function=%d, fFlags=%#x\n", cParms, pCallInfo->u32Function, fFlags));
+
+    /*
+     * The simple approach, allocate a temporary request and convert the parameters.
+     */
+    pCallInfo64 = (VBoxGuestHGCMCallInfo *)RTMemTmpAllocZ(sizeof(*pCallInfo64) + cParms * sizeof(HGCMFunctionParameter));
+    if (!pCallInfo64)
+        return VERR_NO_TMP_MEMORY;
+
+    *pCallInfo64 = *pCallInfo;
+    pParm32 = VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo);
+    pParm64 = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo64);
+    for (iParm = 0; iParm < cParms; iParm++, pParm32++, pParm64++)
+    {
+        switch (pParm32->type)
+        {
+            case VMMDevHGCMParmType_32bit:
+                pParm64->type      = VMMDevHGCMParmType_32bit;
+                pParm64->u.value32 = pParm32->u.value32;
+                break;
+
+            case VMMDevHGCMParmType_64bit:
+                pParm64->type      = VMMDevHGCMParmType_64bit;
+                pParm64->u.value64 = pParm32->u.value64;
+                break;
+
+            case VMMDevHGCMParmType_LinAddr_Out:
+            case VMMDevHGCMParmType_LinAddr:
+            case VMMDevHGCMParmType_LinAddr_In:
+                pParm64->type                   = pParm32->type;
+                pParm64->u.Pointer.size         = pParm32->u.Pointer.size;
+                pParm64->u.Pointer.u.linearAddr = pParm32->u.Pointer.u.linearAddr;
+                break;
+
+            default:
+                rc = VERR_INVALID_PARAMETER;
+                LogRel(("VbglR0HGCMInternalCall32: pParm32 type %#x invalid.\n", pParm32->type));
+                break;
+        }
+        if (RT_FAILURE(rc))
+            break;
+    }
+    if (RT_SUCCESS(rc))
+    {
+        rc = VbglR0HGCMInternalCall(pCallInfo64, sizeof(*pCallInfo64) + cParms * sizeof(HGCMFunctionParameter), fFlags,
+                                    pfnAsyncCallback, pvAsyncData, u32AsyncData);
+
+        if (RT_SUCCESS(rc))
+        {
+            *pCallInfo = *pCallInfo64;
+
+            /*
+             * Copy back.
+             */
+            pParm32 = VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo);
+            pParm64 = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo64);
+            for (iParm = 0; iParm < cParms; iParm++, pParm32++, pParm64++)
+            {
+                switch (pParm64->type)
+                {
+                    case VMMDevHGCMParmType_32bit:
+                        pParm32->u.value32 = pParm64->u.value32;
+                        break;
+
+                    case VMMDevHGCMParmType_64bit:
+                        pParm32->u.value64 = pParm64->u.value64;
+                        break;
+
+                    case VMMDevHGCMParmType_LinAddr_Out:
+                    case VMMDevHGCMParmType_LinAddr:
+                    case VMMDevHGCMParmType_LinAddr_In:
+                        pParm32->u.Pointer.size = pParm64->u.Pointer.size;
+                        break;
+
+                    default:
+                        LogRel(("VbglR0HGCMInternalCall32: failed invalid pParm32 type %d\n", pParm32->type));
+                        rc = VERR_INTERNAL_ERROR_3;
+                        break;
+                }
+            }
+        }
+        else
+        {
+            static unsigned s_cErrors = 0;
+            if (s_cErrors++ < 32)
+                LogRel(("VbglR0HGCMInternalCall32: VbglR0HGCMInternalCall failed. rc=%Rrc\n", rc));
+        }
+    }
+    else
+    {
+        static unsigned s_cErrors = 0;
+        if (s_cErrors++ < 32)
+            LogRel(("VbglR0HGCMInternalCall32: failed. rc=%Rrc\n", rc));
+    }
+
+    RTMemTmpFree(pCallInfo64);
+    return rc;
+}
+#endif /* ARCH_BITS == 64 */
+
+#endif /* VBGL_VBOXGUEST */
+
diff --git a/ubuntu/vbox/vboxguest/Init.c b/ubuntu/vbox/vboxguest/Init.c
new file mode 100644 (file)
index 0000000..e8c985e
--- /dev/null
@@ -0,0 +1,310 @@
+/* $Id: Init.cpp $ */
+/** @file
+ * VBoxGuestLibR0 - Library initialization.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define VBGL_DECL_DATA
+#include "VBGLInternal.h"
+
+#include <iprt/string.h>
+#include <iprt/assert.h>
+#include <iprt/semaphore.h>
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** The global VBGL instance data.  */
+VBGLDATA g_vbgldata;
+
+/**
+ * Used by vbglQueryDriverInfo and VbglInit to try get the host feature mask and
+ * version information (g_vbgldata::hostVersion).
+ *
+ * This was first implemented by the host in 3.1 and we quietly ignore failures
+ * for that reason.
+ */
+static void vbglR0QueryHostVersion (void)
+{
+    VMMDevReqHostVersion *pReq;
+
+    int rc = VbglGRAlloc ((VMMDevRequestHeader **) &pReq, sizeof (*pReq), VMMDevReq_GetHostVersion);
+
+    if (RT_SUCCESS (rc))
+    {
+        rc = VbglGRPerform (&pReq->header);
+
+        if (RT_SUCCESS (rc))
+        {
+            g_vbgldata.hostVersion = *pReq;
+            Log (("vbglR0QueryHostVersion: %u.%u.%ur%u %#x\n",
+                  pReq->major, pReq->minor, pReq->build, pReq->revision, pReq->features));
+        }
+
+        VbglGRFree (&pReq->header);
+    }
+}
+
+#ifndef VBGL_VBOXGUEST
+/**
+ * The guest library uses lazy initialization for VMMDev port and memory,
+ * because these values are provided by the VBoxGuest driver and it might
+ * be loaded later than other drivers.
+ *
+ * The VbglEnter checks the current library status, tries to retrieve these
+ * values and fails if they are unavailable.
+ *
+ */
+static void vbglQueryDriverInfo (void)
+{
+    int rc = VINF_SUCCESS;
+
+    rc = RTSemMutexRequest(g_vbgldata.mutexDriverInit, RT_INDEFINITE_WAIT);
+
+    if (RT_FAILURE(rc))
+        return;
+
+    if (g_vbgldata.status == VbglStatusReady)
+    {
+        RTSemMutexRelease(g_vbgldata.mutexDriverInit);
+        return;
+    }
+
+    rc = vbglDriverOpen(&g_vbgldata.driver);
+
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Try query the port info.
+         */
+        VBoxGuestPortInfo port;
+
+        rc = vbglDriverIOCtl (&g_vbgldata.driver,
+                              VBOXGUEST_IOCTL_GETVMMDEVPORT, &port,
+                              sizeof (port));
+
+        if (RT_SUCCESS (rc))
+        {
+            dprintf (("port = 0x%04X, mem = %p\n", port.portAddress, port.pVMMDevMemory));
+
+            g_vbgldata.portVMMDev = (RTIOPORT)port.portAddress;
+            g_vbgldata.pVMMDevMemory = port.pVMMDevMemory;
+
+            g_vbgldata.status = VbglStatusReady;
+
+            vbglR0QueryHostVersion();
+        }
+    }
+    RTSemMutexRelease(g_vbgldata.mutexDriverInit);
+    dprintf (("vbglQueryDriverInfo rc = %d\n", rc));
+}
+#endif /* !VBGL_VBOXGUEST */
+
+/**
+ * Checks if VBGL has been initialized.
+ *
+ * The client library, this will lazily complete the initialization.
+ *
+ * @return VINF_SUCCESS or VERR_VBGL_NOT_INITIALIZED.
+ */
+int vbglR0Enter (void)
+{
+    int rc;
+
+#ifndef VBGL_VBOXGUEST
+    if (g_vbgldata.status == VbglStatusInitializing)
+    {
+        vbglQueryDriverInfo ();
+    }
+#endif
+
+    rc = g_vbgldata.status == VbglStatusReady? VINF_SUCCESS: VERR_VBGL_NOT_INITIALIZED;
+
+    // dprintf(("VbglEnter: rc = %d\n", rc));
+
+    return rc;
+}
+
+int vbglInitCommon (void)
+{
+    int rc = VINF_SUCCESS;
+
+    RT_ZERO(g_vbgldata);
+
+    g_vbgldata.status = VbglStatusInitializing;
+
+    rc = VbglPhysHeapInit ();
+
+    if (RT_SUCCESS(rc))
+    {
+        /* other subsystems, none yet */
+        ;
+    }
+    else
+    {
+        LogRel(("vbglInitCommon: VbglPhysHeapInit failed. rc=%Rrc\n", rc));
+        g_vbgldata.status = VbglStatusNotInitialized;
+    }
+
+    dprintf(("vbglInitCommon: rc = %d\n", rc));
+
+    return rc;
+}
+
+DECLVBGL(void) vbglTerminateCommon (void)
+{
+    VbglPhysHeapTerminate ();
+    g_vbgldata.status = VbglStatusNotInitialized;
+
+    return;
+}
+
+#ifdef VBGL_VBOXGUEST
+
+DECLVBGL(int) VbglInitPrimary(RTIOPORT portVMMDev, VMMDevMemory *pVMMDevMemory)
+{
+    int rc = VINF_SUCCESS;
+
+# ifdef RT_OS_WINDOWS /** @todo r=bird: this doesn't make sense. Is there something special going on on windows? */
+    dprintf(("vbglInit: starts g_vbgldata.status %d\n", g_vbgldata.status));
+
+    if (   g_vbgldata.status == VbglStatusInitializing
+        || g_vbgldata.status == VbglStatusReady)
+    {
+        /* Initialization is already in process. */
+        return rc;
+    }
+# else
+    dprintf(("vbglInit: starts\n"));
+# endif
+
+    rc = vbglInitCommon ();
+
+    if (RT_SUCCESS(rc))
+    {
+        g_vbgldata.portVMMDev = portVMMDev;
+        g_vbgldata.pVMMDevMemory = pVMMDevMemory;
+
+        g_vbgldata.status = VbglStatusReady;
+
+        vbglR0QueryHostVersion();
+    }
+    else
+    {
+        g_vbgldata.status = VbglStatusNotInitialized;
+    }
+
+    return rc;
+}
+
+DECLVBGL(void) VbglTerminate (void)
+{
+    vbglTerminateCommon ();
+
+    return;
+}
+
+
+#else /* !VBGL_VBOXGUEST */
+
+DECLVBGL(int) VbglInitClient(void)
+{
+    int rc = VINF_SUCCESS;
+
+    if (   g_vbgldata.status == VbglStatusInitializing
+        || g_vbgldata.status == VbglStatusReady)
+    {
+        /* Initialization is already in process. */
+        return rc;
+    }
+
+    rc = vbglInitCommon ();
+
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTSemMutexCreate(&g_vbgldata.mutexDriverInit);
+        if (RT_SUCCESS(rc))
+        {
+            /* Try to obtain VMMDev port via IOCTL to VBoxGuest main driver. */
+            vbglQueryDriverInfo ();
+
+# ifdef VBOX_WITH_HGCM
+            rc = vbglR0HGCMInit ();
+# endif /* VBOX_WITH_HGCM */
+
+            if (RT_FAILURE(rc))
+            {
+                RTSemMutexDestroy(g_vbgldata.mutexDriverInit);
+                g_vbgldata.mutexDriverInit = NIL_RTSEMMUTEX;
+            }
+        }
+
+        if (RT_FAILURE(rc))
+        {
+            vbglTerminateCommon ();
+        }
+
+    }
+
+    return rc;
+}
+
+DECLVBGL(void) VbglTerminate (void)
+{
+# ifdef VBOX_WITH_HGCM
+    vbglR0HGCMTerminate ();
+# endif
+
+    /* driver open could fail, which does not prevent VbglInit from succeeding,
+     * close the driver only if it is opened */
+    if (vbglDriverIsOpened(&g_vbgldata.driver))
+        vbglDriverClose(&g_vbgldata.driver);
+    RTSemMutexDestroy(g_vbgldata.mutexDriverInit);
+    g_vbgldata.mutexDriverInit = NIL_RTSEMMUTEX;
+
+    /* note: do vbglTerminateCommon as a last step since it zeroez up the g_vbgldata
+     * conceptually, doing vbglTerminateCommon last is correct
+     * since this is the reverse order to how init is done */
+    vbglTerminateCommon ();
+
+    return;
+}
+
+int vbglGetDriver(VBGLDRIVER **ppDriver)
+{
+    if (g_vbgldata.status != VbglStatusReady)
+    {
+        vbglQueryDriverInfo();
+        if (g_vbgldata.status != VbglStatusReady)
+            return VERR_TRY_AGAIN;
+    }
+    *ppDriver = &g_vbgldata.driver;
+    return VINF_SUCCESS;
+}
+
+#endif /* !VBGL_VBOXGUEST */
diff --git a/ubuntu/vbox/vboxguest/Makefile b/ubuntu/vbox/vboxguest/Makefile
new file mode 100644 (file)
index 0000000..4f28034
--- /dev/null
@@ -0,0 +1,150 @@
+KBUILD_EXTMOD=${srctree}/ubuntu/vbox
+# $Revision: 115996 $
+## @file
+# VirtualBox Guest Additions Module Makefile.
+#
+
+#
+# Copyright (C) 2006-2015 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.
+#
+
+# Linux kbuild sets this to our source directory if we are called from there
+obj ?= $(CURDIR)
+include $(obj)/Makefile.include.header
+
+MOD_NAME = vboxguest
+
+MOD_OBJS   = \
+       VBoxGuest-linux.o \
+       VBoxGuest.o \
+       GenericRequest.o \
+       HGCMInternal.o \
+       Init.o \
+       PhysHeap.o \
+       SysHlp.o \
+       VMMDev.o \
+       r0drv/alloc-r0drv.o \
+       r0drv/initterm-r0drv.o \
+       r0drv/memobj-r0drv.o \
+       r0drv/mpnotification-r0drv.o \
+       r0drv/powernotification-r0drv.o \
+       r0drv/linux/alloc-r0drv-linux.o \
+       r0drv/linux/assert-r0drv-linux.o \
+       r0drv/linux/initterm-r0drv-linux.o \
+       r0drv/linux/memobj-r0drv-linux.o \
+       r0drv/linux/memuserkernel-r0drv-linux.o \
+       r0drv/linux/mp-r0drv-linux.o \
+       r0drv/linux/mpnotification-r0drv-linux.o \
+       r0drv/linux/process-r0drv-linux.o \
+       r0drv/linux/semevent-r0drv-linux.o \
+       r0drv/linux/semeventmulti-r0drv-linux.o \
+       r0drv/linux/semfastmutex-r0drv-linux.o \
+       r0drv/linux/semmutex-r0drv-linux.o \
+       r0drv/linux/spinlock-r0drv-linux.o \
+       r0drv/linux/thread-r0drv-linux.o \
+       r0drv/linux/thread2-r0drv-linux.o \
+       r0drv/linux/time-r0drv-linux.o \
+       r0drv/linux/timer-r0drv-linux.o \
+       r0drv/linux/RTLogWriteDebugger-r0drv-linux.o \
+       r0drv/generic/semspinmutex-r0drv-generic.o \
+       common/alloc/alloc.o \
+       common/err/RTErrConvertFromErrno.o \
+       common/err/RTErrConvertToErrno.o \
+       common/log/log.o \
+       common/log/logellipsis.o \
+       common/log/logrel.o \
+       common/log/logrelellipsis.o \
+       common/log/logcom.o \
+       common/log/logformat.o \
+       common/misc/RTAssertMsg1Weak.o \
+       common/misc/RTAssertMsg2.o \
+       common/misc/RTAssertMsg2Add.o \
+       common/misc/RTAssertMsg2AddWeak.o \
+       common/misc/RTAssertMsg2AddWeakV.o \
+       common/misc/RTAssertMsg2Weak.o \
+       common/misc/RTAssertMsg2WeakV.o \
+       common/misc/assert.o \
+       common/misc/thread.o \
+       common/string/RTStrCopy.o \
+       common/string/RTStrCopyEx.o \
+       common/string/RTStrCopyP.o \
+       common/string/strformat.o \
+       common/string/strformatrt.o \
+       common/string/strformattype.o \
+       common/string/strprintf.o \
+       common/string/strtonum.o \
+       common/table/avlpv.o \
+       common/time/time.o \
+       generic/RTAssertShouldPanic-generic.o \
+       generic/RTLogWriteStdErr-stub-generic.o \
+       generic/RTLogWriteStdOut-stub-generic.o \
+       generic/RTMpGetCoreCount-generic.o \
+       generic/RTSemEventWait-2-ex-generic.o \
+       generic/RTSemEventWaitNoResume-2-ex-generic.o \
+       generic/RTSemEventMultiWait-2-ex-generic.o \
+       generic/RTSemEventMultiWaitNoResume-2-ex-generic.o \
+       generic/rtStrFormatKernelAddress-generic.o \
+       generic/errvars-generic.o \
+       generic/mppresent-generic.o \
+       VBox/log-vbox.o \
+       VBox/logbackdoor.o
+ifeq ($(BUILD_TARGET_ARCH),x86)
+MOD_OBJS += \
+       common/math/gcc/divdi3.o \
+       common/math/gcc/moddi3.o \
+       common/math/gcc/udivdi3.o \
+       common/math/gcc/udivmoddi4.o \
+       common/math/gcc/umoddi3.o \
+       common/math/gcc/qdivrem.o
+endif
+ifeq ($(BUILD_TARGET_ARCH),amd64)
+MOD_OBJS +=    common/alloc/heapsimple.o
+endif
+
+MOD_DEFS = -DVBOX -DRT_OS_LINUX -DIN_RING0 -DIN_RT_R0 -DIN_GUEST \
+            -DIN_GUEST_R0 -DIN_MODULE -DRT_WITH_VBOX -DVBGL_VBOXGUEST \
+            -DVBOX_WITH_HGCM
+ifeq ($(BUILD_TARGET_ARCH),amd64)
+ MOD_DEFS  += -DRT_ARCH_AMD64
+else
+ MOD_DEFS  += -DRT_ARCH_X86
+endif
+ifeq ($(BUILD_TARGET_ARCH),amd64)
+ MOD_DEFS += -DVBOX_WITH_64_BITS_GUESTS
+endif
+MOD_INCL  = $(addprefix -I$(KBUILD_EXTMOD),/ /include /r0drv/linux)
+MOD_INCL += $(addprefix -I$(KBUILD_EXTMOD)/vboxguest,/ /include /r0drv/linux)
+
+ifneq ($(wildcard $(KBUILD_EXTMOD)/vboxguest),)
+ MANGLING := $(KBUILD_EXTMOD)/vboxguest/include/VBox/VBoxGuestMangling.h
+else
+ MANGLING := $(KBUILD_EXTMOD)/include/VBox/VBoxGuestMangling.h
+endif
+ifeq ($(KERN_VERSION),24)
+ ## @todo move to MOD_DEFS when we have finished refactoring
+ MOD_CFLAGS = -DEXPORT_SYMTAB
+else
+ MOD_CFLAGS = -Wno-declaration-after-statement -include $(MANGLING) -fno-pie
+endif
+
+MOD_CLEAN = . linux r0drv generic r0drv/linux r0drv/generic VBox \
+               common/alloc common/err common/log common/math/gcc common/misc \
+               common/string common/table common/time
+
+include $(obj)/Makefile.include.footer
+
+check: $(MOD_NAME)
+       @if ! readelf -p __ksymtab_strings vboxguest.ko | grep -E "\[.*\]  *(RT|g_..*RT.*)"; then \
+           echo "All exported IPRT symbols are properly renamed!"; \
+        else \
+           echo "error: Some exported IPRT symbols was not properly renamed! See above." >&2; \
+           false; \
+        fi
diff --git a/ubuntu/vbox/vboxguest/Makefile.include.footer b/ubuntu/vbox/vboxguest/Makefile.include.footer
new file mode 100644 (file)
index 0000000..7830bfd
--- /dev/null
@@ -0,0 +1,101 @@
+#
+# VirtualBox Guest Additions kernel module Makefile, common parts.
+#
+# See Makefile.include.header for details of how to use this.
+#
+# Copyright (C) 2006-2015 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.
+#
+
+# override is required by the Debian guys
+override MODULE = $(MOD_NAME)
+OBJS   = $(MOD_OBJS)
+
+ifneq ($(MAKECMDGOALS),clean)
+
+KBUILD_VERBOSE ?= 1
+
+#
+# Compiler options
+#
+ifndef INCL
+ INCL    := $(addprefix -I,$(KERN_INCL) $(EXTRA_INCL))
+ ifndef KBUILD_EXTMOD
+  KBUILD_EXTMOD := $(shell pwd)
+ endif
+ INCL    += $(MOD_INCL)
+ export INCL
+endif
+KFLAGS   := -D__KERNEL__ -DMODULE $(MOD_DEFS)
+ifeq ($(BUILD_TYPE),debug)
+ KFLAGS  += -DDEBUG -DDEBUG_$(subst $(subst _, ,_),_,$(USERNAME)) -DDEBUG_USERNAME=$(subst $(subst _, ,_),_,$(USERNAME))
+endif
+
+ifeq ($(KERN_VERSION), 24)
+#
+# 2.4
+#
+
+ifeq ($(BUILD_TARGET_ARCH),amd64)
+ KFLAGS  += -mcmodel=kernel
+endif
+
+CFLAGS := -O2 -DVBOX_LINUX_2_4 $(MOD_CFLAGS) $(INCL) $(KFLAGS) $(MOD_EXTRA) $(KDEBUG)
+MODULE_EXT := o
+
+# 2.4 Module linking
+$(MODULE).o: $(OBJS)
+       $(LD) -o $@ -r $(OBJS)
+
+.PHONY: $(MODULE)
+all: $(MODULE)
+$(MODULE): $(MODULE).o
+
+else
+#
+# 2.6 and later
+#
+
+MODULE_EXT := ko
+
+$(MODULE)-y  := $(OBJS)
+
+# build defs
+EXTRA_CFLAGS += $(MOD_CFLAGS) $(INCL) $(KFLAGS) $(MOD_EXTRA) $(KDEBUG)
+
+.PHONY: $(MODULE)
+all: $(MODULE)
+
+obj-m += $(MODULE).o
+
+JOBS := $(shell (getconf _NPROCESSORS_ONLN || grep -Ec '^processor|^CPU[0-9]' /proc/cpuinfo) 2>/dev/null)
+ifeq ($(JOBS),0)
+  JOBS := 1
+endif
+
+# OL/UEK: disable module signing for external modules -- we don't have any private key
+$(MODULE):
+       $(MAKE) KBUILD_VERBOSE=$(KBUILD_VERBOSE) CONFIG_MODULE_SIG= -C $(KERN_DIR) SUBDIRS=$(CURDIR) SRCROOT=$(CURDIR) -j$(JOBS) modules
+
+modules_install:
+       $(MAKE) KBUILD_VERBOSE=$(KBUILD_VERBOSE) CONFIG_MODULE_SIG= -C $(KERN_DIR) SUBDIRS=$(CURDIR) SRCROOT=$(CURDIR) modules_install
+
+endif
+
+install: $(MODULE)
+       @mkdir -p $(MODULE_DIR); \
+       install -m 0644 -o root -g root $(MODULE).$(MODULE_EXT) $(MODULE_DIR); \
+       PATH="$(PATH):/bin:/sbin" depmod -a;
+
+endif # eq($(MAKECMDGOALS),clean)
+
+clean:
+       for f in $(MOD_CLEAN); do rm -f $$f/*.o $$f/.*.cmd $$f/.*.flags; done
+       rm -rf .$(MOD_NAME)* .tmp_ver* $(MOD_NAME).* Modules.symvers modules.order
diff --git a/ubuntu/vbox/vboxguest/Makefile.include.header b/ubuntu/vbox/vboxguest/Makefile.include.header
new file mode 100644 (file)
index 0000000..1c4fb9a
--- /dev/null
@@ -0,0 +1,188 @@
+#
+# VirtualBox Guest Additions kernel module Makefile, common parts.
+#
+# (For 2.6.x, the main file must be called 'Makefile'!)
+#
+# Copyright (C) 2006-2015 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.
+#
+
+# Testing:
+# * Building with KERN_VER set to an installed but non-current kernel works and
+#   installs to the right location.
+# * Building with KERN_DIR and/or MODULE_DIR set uses the value specified and
+#   the default value for the unspecified one if any.
+
+#
+# These file should be included by the Makefiles for any kernel modules we
+# build as part of the Guest Additions.  The intended way of doing this is as
+# follows:
+#
+# # Linux kbuild sets this to our source directory if we are called from
+# # there
+# obj ?= $(CURDIR)
+# include $(obj)/Makefile.include.header
+# MOD_NAME = <name of the module to be built, without extension>
+# MOD_OBJS = <list of object files which should be included>
+# MOD_DEFS = <any additional defines which this module needs>
+# MOD_INCL = <any additional include paths which this module needs>
+# MOD_CFLAGS = <any additional CFLAGS which this module needs>
+# MOD_CLEAN = <list of directories that the clean target should look at>
+# include $(obj)/Makefile.include.footer
+#
+# The kmk kBuild define KBUILD_TARGET_ARCH is available.
+#
+
+
+#
+# First, figure out which architecture we're targeting and the build type.
+# (We have to support basic cross building (ARCH=i386|x86_64).)
+# While at it, warn about BUILD_* vars found to help with user problems.
+#
+ifeq ($(filter-out x86_64 amd64 AMD64,$(shell uname -m)),)
+ BUILD_TARGET_ARCH_DEF := amd64
+else
+ BUILD_TARGET_ARCH_DEF := x86
+endif
+ifneq ($(filter-out amd64 x86,$(BUILD_TARGET_ARCH)),)
+ $(warning Ignoring unknown BUILD_TARGET_ARCH value '$(BUILD_TARGET_ARCH)'.)
+ BUILD_TARGET_ARCH :=
+endif
+ifeq ($(BUILD_TARGET_ARCH),)
+ ifeq ($(ARCH),x86_64)
+  BUILD_TARGET_ARCH := amd64
+ else
+  ifeq ($(ARCH),i386)
+   ifeq ($(CONFIG_X86_32),y)
+     BUILD_TARGET_ARCH := x86
+   else
+     BUILD_TARGET_ARCH := amd64
+   endif
+  else
+    ifeq ($(ARCH),x86)
+      ifeq ($(CONFIG_X86_32),y)
+        BUILD_TARGET_ARCH := x86
+      else
+        BUILD_TARGET_ARCH := amd64
+      endif
+    else
+      BUILD_TARGET_ARCH := $(BUILD_TARGET_ARCH_DEF)
+    endif
+  endif
+ endif
+else
+ ifneq ($(BUILD_TARGET_ARCH),$(BUILD_TARGET_ARCH_DEF))
+  $(warning Using BUILD_TARGET_ARCH='$(BUILD_TARGET_ARCH)' from the $(origin BUILD_TARGET_ARCH).)
+ endif
+endif
+
+ifneq ($(filter-out release profile debug strict,$(BUILD_TYPE)),)
+ $(warning Ignoring unknown BUILD_TYPE value '$(BUILD_TYPE)'.)
+ BUILD_TYPE :=
+endif
+ifeq ($(BUILD_TYPE),)
+ BUILD_TYPE := release
+else
+ ifneq ($(BUILD_TYPE),release)
+  $(warning Using BUILD_TYPE='$(BUILD_TYPE)' from the $(origin BUILD_TYPE).)
+ endif
+endif
+ifeq ($(USERNAME),)
+ USERNAME := noname
+endif
+
+ifneq ($(MAKECMDGOALS),clean)
+
+ifeq ($(KERNELRELEASE),)
+
+ #
+ # building from this directory
+ #
+
+ # target kernel version
+ ifndef KERN_VER
+  KERN_VER := $(shell uname -r)
+ else
+  ifneq ($(shell if test -d /lib/modules/$(KERN_VER)/build; then echo yes; fi),yes)
+   KERN_VER := $(shell uname -r)
+  endif
+ endif
+
+ # kernel base directory
+ ifndef KERN_DIR
+  KERN_DIR := /lib/modules/$(KERN_VER)/build
+  ifneq ($(shell if test -d $(KERN_DIR); then echo yes; fi),yes)
+   KERN_DIR := /usr/src/linux
+   ifneq ($(shell if test -d $(KERN_DIR); then echo yes; fi),yes)
+    $(error Error: unable to find the sources of your current Linux kernel. \
+                  Specify KERN_DIR=<directory> and run Make again)
+   endif
+   $(warning Warning: using /usr/src/linux as the source directory of your \
+                      Linux kernel. If this is not correct, specify \
+                     KERN_DIR=<directory> and run Make again.)
+  endif
+ else
+  ifneq ($(shell if test -d $(KERN_DIR); then echo yes; fi),yes)
+   $(error Error: KERN_DIR does not point to a directory)
+  endif
+ endif
+
+ # includes
+ ifndef KERN_INCL
+  KERN_INCL = $(KERN_DIR)/include
+ endif
+ ifneq ($(shell if test -d $(KERN_INCL); then echo yes; fi),yes)
+  $(error Error: unable to find the include directory for your current Linux \
+                 kernel. Specify KERN_INCL=<directory> and run Make again)
+ endif
+
+ # module install dir, only for current kernel
+ ifneq ($(filter install install_rpm,$(MAKECMDGOALS)),)
+  ifndef MODULE_DIR
+   MODULE_DIR_TST := /lib/modules/$(KERN_VER)
+   ifeq ($(shell if test -d $(MODULE_DIR_TST); then echo yes; fi),yes)
+    MODULE_DIR := $(MODULE_DIR_TST)/misc
+   else
+    $(error Unable to find the folder to install the module to)
+   endif
+  endif # MODULE_DIR unspecified
+ endif
+
+ # guess kernel version (24 or 26)
+ ifeq ($(shell if grep '"2\.4\.' $(KERN_INCL)/linux/version.h > /dev/null; then echo yes; fi),yes)
+  KERN_VERSION := 24
+ else
+  KERN_VERSION := 26
+ endif
+
+else # neq($(KERNELRELEASE),)
+
+ #
+ # building from kbuild (make -C <kernel_directory> M=`pwd`)
+ #
+
+ # guess kernel version (24 or 26)
+ ifeq ($(shell if echo "$(VERSION).$(PATCHLEVEL)." | grep '2\.4\.' > /dev/null; then echo yes; fi),yes)
+  KERN_VERSION := 24
+ else
+  KERN_VERSION := 26
+ endif
+
+endif # neq($(KERNELRELEASE),)
+
+# debug - show guesses.
+ifdef DEBUG
+$(warning dbg: KERN_DIR     = $(KERN_DIR))
+$(warning dbg: KERN_INCL    = $(KERN_INCL))
+$(warning dbg: MODULE_DIR   = $(MODULE_DIR))
+$(warning dbg: KERN_VERSION = $(KERN_VERSION))
+endif
+
+endif # eq($(MAKECMDGOALS),clean)
diff --git a/ubuntu/vbox/vboxguest/PhysHeap.c b/ubuntu/vbox/vboxguest/PhysHeap.c
new file mode 100644 (file)
index 0000000..7ba42a4
--- /dev/null
@@ -0,0 +1,636 @@
+/* $Id: PhysHeap.cpp $ */
+/** @file
+ * VBoxGuestLibR0 - Physical memory heap.
+ */
+
+/*
+ * 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.
+ */
+
+#include "VBGLInternal.h"
+
+#include <iprt/assert.h>
+#include <iprt/semaphore.h>
+#include <iprt/alloc.h>
+
+/* Physical memory heap consists of double linked list
+ * of chunks. Memory blocks are allocated inside these chunks
+ * and are members of Allocated and Free double linked lists.
+ *
+ * When allocating a block, we search in Free linked
+ * list for a suitable free block. If there is no such block,
+ * a new chunk is allocated and the new block is taken from
+ * the new chunk as the only chunk-sized free block.
+ * Allocated block is excluded from the Free list and goes to
+ * Alloc list.
+ *
+ * When freeing block, we check the pointer and then
+ * exclude block from Alloc list and move it to free list.
+ *
+ * For each chunk we maintain the allocated blocks counter.
+ * if 2 (or more) entire chunks are free they are immediately
+ * deallocated, so we always have at most 1 free chunk.
+ *
+ * When freeing blocks, two subsequent free blocks are always
+ * merged together. Current implementation merges blocks only
+ * when there is a block after the just freed one.
+ *
+ */
+
+#define VBGL_PH_ASSERT      Assert
+#define VBGL_PH_ASSERTMsg   AssertMsg
+
+// #define DUMPHEAP
+
+#ifdef DUMPHEAP
+# define VBGL_PH_dprintf(a) RTAssertMsg2Weak a
+#else
+# define VBGL_PH_dprintf(a)
+#endif
+
+/* Heap block signature */
+#define VBGL_PH_BLOCKSIGNATURE (0xADDBBBBB)
+
+
+/* Heap chunk signature */
+#define VBGL_PH_CHUNKSIGNATURE (0xADDCCCCC)
+/* Heap chunk allocation unit */
+#define VBGL_PH_CHUNKSIZE (0x10000)
+
+/* Heap block bit flags */
+#define VBGL_PH_BF_ALLOCATED (0x1)
+
+struct _VBGLPHYSHEAPBLOCK
+{
+    uint32_t u32Signature;
+
+    /* Size of user data in the block. Does not include the block header. */
+    uint32_t cbDataSize;
+
+    uint32_t fu32Flags;
+
+    struct _VBGLPHYSHEAPBLOCK *pNext;
+    struct _VBGLPHYSHEAPBLOCK *pPrev;
+
+    struct _VBGLPHYSHEAPCHUNK *pChunk;
+};
+
+struct _VBGLPHYSHEAPCHUNK
+{
+    uint32_t u32Signature;
+
+    /* Size of the chunk. Includes the chunk header. */
+    uint32_t cbSize;
+
+    /* Physical address of the chunk */
+    uint32_t physAddr;
+
+    /* Number of allocated blocks in the chunk */
+    int32_t cAllocatedBlocks;
+
+    struct _VBGLPHYSHEAPCHUNK *pNext;
+    struct _VBGLPHYSHEAPCHUNK *pPrev;
+};
+
+
+#ifndef DUMPHEAP
+#define dumpheap(a)
+#else
+void dumpheap (char *point)
+{
+   VBGL_PH_dprintf(("VBGL_PH dump at '%s'\n", point));
+
+   VBGL_PH_dprintf(("Chunks:\n"));
+
+   VBGLPHYSHEAPCHUNK *pChunk = g_vbgldata.pChunkHead;
+
+   while (pChunk)
+   {
+       VBGL_PH_dprintf(("%p: pNext = %p, pPrev = %p, sign = %08X, size = %8d, allocated = %8d, phys = %08X\n",
+                        pChunk, pChunk->pNext, pChunk->pPrev, pChunk->u32Signature, pChunk->cbSize, pChunk->cAllocatedBlocks, pChunk->physAddr));
+
+       pChunk = pChunk->pNext;
+   }
+
+   VBGL_PH_dprintf(("Allocated blocks:\n"));
+
+   VBGLPHYSHEAPBLOCK *pBlock = g_vbgldata.pAllocBlocksHead;
+
+   while (pBlock)
+   {
+       VBGL_PH_dprintf(("%p: pNext = %p, pPrev = %p, sign = %08X, size = %8d, flags = %08X, pChunk = %p\n",
+                        pBlock, pBlock->pNext, pBlock->pPrev, pBlock->u32Signature, pBlock->cbDataSize, pBlock->fu32Flags, pBlock->pChunk));
+
+       pBlock = pBlock->pNext;
+   }
+
+   VBGL_PH_dprintf(("Free blocks:\n"));
+
+   pBlock = g_vbgldata.pFreeBlocksHead;
+
+   while (pBlock)
+   {
+       VBGL_PH_dprintf(("%p: pNext = %p, pPrev = %p, sign = %08X, size = %8d, flags = %08X, pChunk = %p\n",
+                        pBlock, pBlock->pNext, pBlock->pPrev, pBlock->u32Signature, pBlock->cbDataSize, pBlock->fu32Flags, pBlock->pChunk));
+
+       pBlock = pBlock->pNext;
+   }
+
+   VBGL_PH_dprintf(("VBGL_PH dump at '%s' done\n", point));
+}
+#endif
+
+
+DECLINLINE(void *) vbglPhysHeapBlock2Data (VBGLPHYSHEAPBLOCK *pBlock)
+{
+    return (void *)(pBlock? (char *)pBlock + sizeof (VBGLPHYSHEAPBLOCK): NULL);
+}
+
+DECLINLINE(VBGLPHYSHEAPBLOCK *) vbglPhysHeapData2Block (void *p)
+{
+    VBGLPHYSHEAPBLOCK *pBlock = (VBGLPHYSHEAPBLOCK *)(p? (char *)p - sizeof (VBGLPHYSHEAPBLOCK): NULL);
+
+    VBGL_PH_ASSERTMsg(pBlock == NULL || pBlock->u32Signature == VBGL_PH_BLOCKSIGNATURE,
+                     ("pBlock->u32Signature = %08X\n", pBlock->u32Signature));
+
+    return pBlock;
+}
+
+DECLINLINE(int) vbglPhysHeapEnter (void)
+{
+    int rc = RTSemFastMutexRequest(g_vbgldata.mutexHeap);
+
+    VBGL_PH_ASSERTMsg(RT_SUCCESS(rc),
+                     ("Failed to request heap mutex, rc = %Rrc\n", rc));
+
+    return rc;
+}
+
+DECLINLINE(void) vbglPhysHeapLeave (void)
+{
+    RTSemFastMutexRelease(g_vbgldata.mutexHeap);
+}
+
+
+static void vbglPhysHeapInitBlock (VBGLPHYSHEAPBLOCK *pBlock, VBGLPHYSHEAPCHUNK *pChunk, uint32_t cbDataSize)
+{
+    VBGL_PH_ASSERT(pBlock != NULL);
+    VBGL_PH_ASSERT(pChunk != NULL);
+
+    pBlock->u32Signature = VBGL_PH_BLOCKSIGNATURE;
+    pBlock->cbDataSize   = cbDataSize;
+    pBlock->fu32Flags    = 0;
+    pBlock->pNext        = NULL;
+    pBlock->pPrev        = NULL;
+    pBlock->pChunk       = pChunk;
+}
+
+
+static void vbglPhysHeapInsertBlock (VBGLPHYSHEAPBLOCK *pInsertAfter, VBGLPHYSHEAPBLOCK *pBlock)
+{
+    VBGL_PH_ASSERTMsg(pBlock->pNext == NULL,
+                     ("pBlock->pNext = %p\n", pBlock->pNext));
+    VBGL_PH_ASSERTMsg(pBlock->pPrev == NULL,
+                     ("pBlock->pPrev = %p\n", pBlock->pPrev));
+
+    if (pInsertAfter)
+    {
+        pBlock->pNext = pInsertAfter->pNext;
+        pBlock->pPrev = pInsertAfter;
+
+        if (pInsertAfter->pNext)
+        {
+            pInsertAfter->pNext->pPrev = pBlock;
+        }
+
+        pInsertAfter->pNext = pBlock;
+    }
+    else
+    {
+        /* inserting to head of list */
+        pBlock->pPrev = NULL;
+
+        if (pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED)
+        {
+            pBlock->pNext = g_vbgldata.pAllocBlocksHead;
+
+            if (g_vbgldata.pAllocBlocksHead)
+            {
+                g_vbgldata.pAllocBlocksHead->pPrev = pBlock;
+            }
+
+            g_vbgldata.pAllocBlocksHead = pBlock;
+        }
+        else
+        {
+            pBlock->pNext = g_vbgldata.pFreeBlocksHead;
+
+            if (g_vbgldata.pFreeBlocksHead)
+            {
+                g_vbgldata.pFreeBlocksHead->pPrev = pBlock;
+            }
+
+            g_vbgldata.pFreeBlocksHead = pBlock;
+        }
+    }
+}
+
+static void vbglPhysHeapExcludeBlock (VBGLPHYSHEAPBLOCK *pBlock)
+{
+    if (pBlock->pNext)
+    {
+        pBlock->pNext->pPrev = pBlock->pPrev;
+    }
+    else
+    {
+        /* this is tail of list but we do not maintain tails of block lists.
+         * so do nothing.
+         */
+        ;
+    }
+
+    if (pBlock->pPrev)
+    {
+        pBlock->pPrev->pNext = pBlock->pNext;
+    }
+    else
+    {
+        /* this is head of list but we do not maintain tails of block lists. */
+        if (pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED)
+        {
+            g_vbgldata.pAllocBlocksHead = pBlock->pNext;
+        }
+        else
+        {
+            g_vbgldata.pFreeBlocksHead = pBlock->pNext;
+        }
+    }
+
+    pBlock->pNext = NULL;
+    pBlock->pPrev = NULL;
+}
+
+static VBGLPHYSHEAPBLOCK *vbglPhysHeapChunkAlloc (uint32_t cbSize)
+{
+    RTCCPHYS physAddr;
+    VBGLPHYSHEAPCHUNK *pChunk;
+    VBGLPHYSHEAPBLOCK *pBlock;
+    VBGL_PH_dprintf(("Allocating new chunk of size %d\n", cbSize));
+
+    /* Compute chunk size to allocate */
+    if (cbSize < VBGL_PH_CHUNKSIZE)
+    {
+        /* Includes case of block size 0 during initialization */
+        cbSize = VBGL_PH_CHUNKSIZE;
+    }
+    else
+    {
+        /* Round up to next chunk size, which must be power of 2 */
+        cbSize = (cbSize + (VBGL_PH_CHUNKSIZE - 1)) & ~(VBGL_PH_CHUNKSIZE - 1);
+    }
+
+    physAddr = 0;
+    /* This function allocates physical contiguous memory (below 4GB) according to the IPRT docs.
+     * Address < 4G is required for the port IO.
+     */
+    pChunk = (VBGLPHYSHEAPCHUNK *)RTMemContAlloc (&physAddr, cbSize);
+
+    if (!pChunk)
+    {
+        LogRel(("vbglPhysHeapChunkAlloc: failed to alloc %u contiguous bytes.\n", cbSize));
+        return NULL;
+    }
+
+    AssertRelease(physAddr < _4G && physAddr + cbSize <= _4G);
+
+    pChunk->u32Signature     = VBGL_PH_CHUNKSIGNATURE;
+    pChunk->cbSize           = cbSize;
+    pChunk->physAddr         = (uint32_t)physAddr;
+    pChunk->cAllocatedBlocks = 0;
+    pChunk->pNext            = g_vbgldata.pChunkHead;
+    pChunk->pPrev            = NULL;
+
+    /* Initialize the free block, which now occupies entire chunk. */
+    pBlock = (VBGLPHYSHEAPBLOCK *)((char *)pChunk + sizeof (VBGLPHYSHEAPCHUNK));
+
+    vbglPhysHeapInitBlock (pBlock, pChunk, cbSize - sizeof (VBGLPHYSHEAPCHUNK) - sizeof (VBGLPHYSHEAPBLOCK));
+
+    vbglPhysHeapInsertBlock (NULL, pBlock);
+
+    g_vbgldata.pChunkHead = pChunk;
+
+    VBGL_PH_dprintf(("Allocated chunk %p, block = %p size=%x\n", pChunk, pBlock, cbSize));
+
+    return pBlock;
+}
+
+
+void vbglPhysHeapChunkDelete (VBGLPHYSHEAPCHUNK *pChunk)
+{
+    char *p;
+    VBGL_PH_ASSERT(pChunk != NULL);
+    VBGL_PH_ASSERTMsg(pChunk->u32Signature == VBGL_PH_CHUNKSIGNATURE,
+                     ("pChunk->u32Signature = %08X\n", pChunk->u32Signature));
+
+    VBGL_PH_dprintf(("Deleting chunk %p size %x\n", pChunk, pChunk->cbSize));
+
+    /* first scan the chunk and exclude all blocks from lists */
+
+    p = (char *)pChunk + sizeof (VBGLPHYSHEAPCHUNK);
+
+    while (p < (char *)pChunk + pChunk->cbSize)
+    {
+        VBGLPHYSHEAPBLOCK *pBlock = (VBGLPHYSHEAPBLOCK *)p;
+
+        p += pBlock->cbDataSize + sizeof (VBGLPHYSHEAPBLOCK);
+
+        vbglPhysHeapExcludeBlock (pBlock);
+    }
+
+    VBGL_PH_ASSERTMsg(p == (char *)pChunk + pChunk->cbSize,
+                      ("p = %p, (char *)pChunk + pChunk->cbSize = %p, pChunk->cbSize = %08X\n",
+                       p, (char *)pChunk + pChunk->cbSize, pChunk->cbSize));
+
+    /* Exclude chunk from the chunk list */
+    if (pChunk->pNext)
+    {
+        pChunk->pNext->pPrev = pChunk->pPrev;
+    }
+    else
+    {
+        /* we do not maintain tail */
+        ;
+    }
+
+    if (pChunk->pPrev)
+    {
+        pChunk->pPrev->pNext = pChunk->pNext;
+    }
+    else
+    {
+        /* the chunk was head */
+        g_vbgldata.pChunkHead = pChunk->pNext;
+    }
+
+    RTMemContFree (pChunk, pChunk->cbSize);
+}
+
+
+DECLVBGL(void *) VbglPhysHeapAlloc (uint32_t cbSize)
+{
+    VBGLPHYSHEAPBLOCK *pBlock, *iter;
+    int rc = vbglPhysHeapEnter ();
+
+    if (RT_FAILURE(rc))
+        return NULL;
+
+    dumpheap ("pre alloc");
+
+    pBlock = NULL;
+
+    /* If there are free blocks in the heap, look at them. */
+    iter = g_vbgldata.pFreeBlocksHead;
+
+    /* There will be not many blocks in the heap, so
+     * linear search would be fast enough.
+     */
+
+    while (iter)
+    {
+        if (iter->cbDataSize == cbSize)
+        {
+            /* exact match */
+            pBlock = iter;
+            break;
+        }
+
+        /* Looking for a free block with nearest size */
+        if (iter->cbDataSize > cbSize)
+        {
+            if (pBlock)
+            {
+                if (iter->cbDataSize < pBlock->cbDataSize)
+                {
+                    pBlock = iter;
+                }
+            }
+            else
+            {
+                pBlock = iter;
+            }
+        }
+
+        iter = iter->pNext;
+    }
+
+    if (!pBlock)
+    {
+        /* No free blocks, allocate a new chunk,
+         * the only free block of the chunk will
+         * be returned.
+         */
+        pBlock = vbglPhysHeapChunkAlloc (cbSize);
+    }
+
+    if (pBlock)
+    {
+        VBGL_PH_ASSERTMsg(pBlock->u32Signature == VBGL_PH_BLOCKSIGNATURE,
+                         ("pBlock = %p, pBlock->u32Signature = %08X\n", pBlock, pBlock->u32Signature));
+        VBGL_PH_ASSERTMsg((pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED) == 0,
+                         ("pBlock = %p, pBlock->fu32Flags = %08X\n", pBlock, pBlock->fu32Flags));
+
+        /* We have a free block, either found or allocated. */
+
+        if (pBlock->cbDataSize > 2*(cbSize + sizeof (VBGLPHYSHEAPBLOCK)))
+        {
+            /* Data will occupy less than a half of the block,
+             * the block should be split.
+             */
+            iter = (VBGLPHYSHEAPBLOCK *)((char *)pBlock + sizeof (VBGLPHYSHEAPBLOCK) + cbSize);
+
+            /* Init the new 'iter' block, initialized blocks are always marked as free. */
+            vbglPhysHeapInitBlock (iter, pBlock->pChunk, pBlock->cbDataSize - cbSize - sizeof (VBGLPHYSHEAPBLOCK));
+
+            pBlock->cbDataSize = cbSize;
+
+            /* Insert the new 'iter' block after the 'pBlock' in the free list */
+            vbglPhysHeapInsertBlock (pBlock, iter);
+        }
+
+        /* Exclude pBlock from free list */
+        vbglPhysHeapExcludeBlock (pBlock);
+
+        /* Mark as allocated */
+        pBlock->fu32Flags |= VBGL_PH_BF_ALLOCATED;
+
+        /* Insert to allocated list */
+        vbglPhysHeapInsertBlock (NULL, pBlock);
+
+        /* Adjust the chunk allocated blocks counter */
+        pBlock->pChunk->cAllocatedBlocks++;
+    }
+
+    dumpheap ("post alloc");
+
+    vbglPhysHeapLeave ();
+    VBGL_PH_dprintf(("VbglPhysHeapAlloc %x size %x\n", vbglPhysHeapBlock2Data (pBlock), pBlock->cbDataSize));
+
+    return vbglPhysHeapBlock2Data (pBlock);
+}
+
+DECLVBGL(uint32_t) VbglPhysHeapGetPhysAddr (void *p)
+{
+    uint32_t physAddr = 0;
+    VBGLPHYSHEAPBLOCK *pBlock = vbglPhysHeapData2Block (p);
+
+    if (pBlock)
+    {
+        VBGL_PH_ASSERTMsg((pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED) != 0,
+                         ("pBlock = %p, pBlock->fu32Flags = %08X\n", pBlock, pBlock->fu32Flags));
+
+        if (pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED)
+            physAddr = pBlock->pChunk->physAddr + (uint32_t)((uintptr_t)p - (uintptr_t)pBlock->pChunk);
+    }
+
+    return physAddr;
+}
+
+DECLVBGL(void) VbglPhysHeapFree(void *p)
+{
+    VBGLPHYSHEAPBLOCK *pBlock;
+    VBGLPHYSHEAPBLOCK *pNeighbour;
+
+    int rc = vbglPhysHeapEnter ();
+    if (RT_FAILURE(rc))
+        return;
+
+    dumpheap ("pre free");
+
+    pBlock = vbglPhysHeapData2Block (p);
+
+    if (!pBlock)
+    {
+        vbglPhysHeapLeave ();
+        return;
+    }
+
+    VBGL_PH_ASSERTMsg((pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED) != 0,
+                     ("pBlock = %p, pBlock->fu32Flags = %08X\n", pBlock, pBlock->fu32Flags));
+
+    /* Exclude from allocated list */
+    vbglPhysHeapExcludeBlock (pBlock);
+
+    dumpheap ("post exclude");
+
+    VBGL_PH_dprintf(("VbglPhysHeapFree %x size %x\n", p, pBlock->cbDataSize));
+
+    /* Mark as free */
+    pBlock->fu32Flags &= ~VBGL_PH_BF_ALLOCATED;
+
+    /* Insert to free list */
+    vbglPhysHeapInsertBlock (NULL, pBlock);
+
+    dumpheap ("post insert");
+
+    /* Adjust the chunk allocated blocks counter */
+    pBlock->pChunk->cAllocatedBlocks--;
+
+    VBGL_PH_ASSERT(pBlock->pChunk->cAllocatedBlocks >= 0);
+
+    /* Check if we can merge 2 free blocks. To simplify heap maintenance,
+     * we will look at block after the just freed one.
+     * This will not prevent us from detecting free memory chunks.
+     * Also in most cases blocks are deallocated in reverse allocation order
+     * and in that case the merging will work.
+     */
+
+    pNeighbour = (VBGLPHYSHEAPBLOCK *)((char *)p + pBlock->cbDataSize);
+
+    if ((char *)pNeighbour < (char *)pBlock->pChunk + pBlock->pChunk->cbSize
+        && (pNeighbour->fu32Flags & VBGL_PH_BF_ALLOCATED) == 0)
+    {
+        /* The next block is free as well. */
+
+        /* Adjust size of current memory block */
+        pBlock->cbDataSize += pNeighbour->cbDataSize + sizeof (VBGLPHYSHEAPBLOCK);
+
+        /* Exclude the next neighbour */
+        vbglPhysHeapExcludeBlock (pNeighbour);
+    }
+
+    dumpheap ("post merge");
+
+    /* now check if there are 2 or more free chunks */
+    if (pBlock->pChunk->cAllocatedBlocks == 0)
+    {
+        VBGLPHYSHEAPCHUNK *pChunk = g_vbgldata.pChunkHead;
+
+        uint32_t u32FreeChunks = 0;
+
+        while (pChunk)
+        {
+            if (pChunk->cAllocatedBlocks == 0)
+            {
+                u32FreeChunks++;
+            }
+
+            pChunk = pChunk->pNext;
+        }
+
+        if (u32FreeChunks > 1)
+        {
+            /* Delete current chunk, it will also exclude all free blocks
+             * remaining in the chunk from the free list, so the pBlock
+             * will also be invalid after this.
+             */
+            vbglPhysHeapChunkDelete (pBlock->pChunk);
+        }
+    }
+
+    dumpheap ("post free");
+
+    vbglPhysHeapLeave ();
+}
+
+DECLVBGL(int) VbglPhysHeapInit (void)
+{
+    int rc = VINF_SUCCESS;
+
+    /* Allocate the first chunk of the heap. */
+    VBGLPHYSHEAPBLOCK *pBlock = vbglPhysHeapChunkAlloc (0);
+
+    if (!pBlock)
+        rc = VERR_NO_MEMORY;
+
+    RTSemFastMutexCreate(&g_vbgldata.mutexHeap);
+
+    return rc;
+}
+
+DECLVBGL(void) VbglPhysHeapTerminate (void)
+{
+    while (g_vbgldata.pChunkHead)
+    {
+        vbglPhysHeapChunkDelete (g_vbgldata.pChunkHead);
+    }
+
+    RTSemFastMutexDestroy(g_vbgldata.mutexHeap);
+}
+
diff --git a/ubuntu/vbox/vboxguest/SysHlp.c b/ubuntu/vbox/vboxguest/SysHlp.c
new file mode 100644 (file)
index 0000000..1485af2
--- /dev/null
@@ -0,0 +1,345 @@
+/* $Id: SysHlp.cpp $ */
+/** @file
+ * VBoxGuestLibR0 - IDC with VBoxGuest and HGCM helpers.
+ */
+
+/*
+ * 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.
+ */
+
+#define LOG_GROUP LOG_GROUP_HGCM
+#include <VBox/log.h>
+
+#include <VBox/VBoxGuestLib.h>
+#include "SysHlp.h"
+
+#include <iprt/assert.h>
+
+#ifdef VBGL_VBOXGUEST
+
+#if !defined (RT_OS_WINDOWS)
+# include <iprt/memobj.h>
+# include <iprt/mem.h>
+#endif
+
+
+/**
+ * Internal worker for locking a range of linear addresses.
+ *
+ * @returns VBox status code.
+ * @param   ppvCtx          Where to store context data.
+ * @param   pv              The start of the range.
+ * @param   u32Size         The size of the range.
+ * @param   fWriteAccess    Lock for read-write (true) or readonly (false).
+ * @param   fFlags          HGCM call flags, VBGLR0_HGCM_F_XXX.
+ */
+int vbglLockLinear(void **ppvCtx, void *pv, uint32_t u32Size, bool fWriteAccess, uint32_t fFlags)
+{
+    int         rc      = VINF_SUCCESS;
+#ifndef RT_OS_WINDOWS
+    RTR0MEMOBJ  MemObj  = NIL_RTR0MEMOBJ;
+    uint32_t    fAccess = RTMEM_PROT_READ | (fWriteAccess ? RTMEM_PROT_WRITE : 0);
+#endif
+
+    /* Zero size buffers shouldn't be locked. */
+    if (u32Size == 0)
+    {
+        Assert(pv == NULL);
+#ifdef RT_OS_WINDOWS
+        *ppvCtx = NULL;
+#else
+        *ppvCtx = NIL_RTR0MEMOBJ;
+#endif
+        return VINF_SUCCESS;
+    }
+
+    /** @todo just use IPRT here. the extra allocation shouldn't matter much...
+     *        Then we can move all this up one level even. */
+#ifdef RT_OS_WINDOWS
+    PMDL pMdl = IoAllocateMdl(pv, u32Size, FALSE, FALSE, NULL);
+
+    if (pMdl == NULL)
+    {
+        rc = VERR_NOT_SUPPORTED;
+        AssertMsgFailed(("IoAllocateMdl %p %x failed!!\n", pv, u32Size));
+    }
+    else
+    {
+        __try {
+            /* Calls to MmProbeAndLockPages must be enclosed in a try/except block. */
+            RT_NOREF1(fFlags);  /** @todo fFlags on windows */
+            MmProbeAndLockPages(pMdl,
+                                /** @todo (fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER? UserMode: KernelMode */
+                                KernelMode,
+                                (fWriteAccess) ? IoModifyAccess : IoReadAccess);
+
+            *ppvCtx = pMdl;
+
+        } __except(EXCEPTION_EXECUTE_HANDLER) {
+
+            IoFreeMdl(pMdl);
+            /** @todo  */
+            rc = VERR_INVALID_PARAMETER;
+            AssertMsgFailed(("MmProbeAndLockPages %p %x failed!!\n", pv, u32Size));
+        }
+    }
+
+#else
+    /*
+     * Lock depending on context.
+     *
+     * Note: We will later use the memory object here to convert the HGCM
+     *       linear buffer parameter into a physical page list. This is why
+     *       we lock both kernel pages on all systems, even those where we
+     *       know they aren't pageable.
+     */
+    if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER)
+        rc = RTR0MemObjLockUser(&MemObj, (RTR3PTR)pv, u32Size, fAccess, NIL_RTR0PROCESS);
+    else
+        rc = RTR0MemObjLockKernel(&MemObj, pv, u32Size, fAccess);
+    if (RT_SUCCESS(rc))
+        *ppvCtx = MemObj;
+    else
+        *ppvCtx = NIL_RTR0MEMOBJ;
+
+#endif
+
+    return rc;
+}
+
+void vbglUnlockLinear(void *pvCtx, void *pv, uint32_t u32Size)
+{
+#ifdef RT_OS_WINDOWS
+    PMDL pMdl = (PMDL)pvCtx;
+
+    Assert(pMdl);
+    if (pMdl != NULL)
+    {
+        MmUnlockPages(pMdl);
+        IoFreeMdl(pMdl);
+    }
+
+#else
+    RTR0MEMOBJ MemObj = (RTR0MEMOBJ)pvCtx;
+    int rc = RTR0MemObjFree(MemObj, false);
+    AssertRC(rc);
+
+#endif
+
+    NOREF(pv);
+    NOREF(u32Size);
+}
+
+#else  /* !VBGL_VBOXGUEST */
+
+# ifdef RT_OS_OS2
+#  include <VBox/VBoxGuest.h> /* for VBOXGUESTOS2IDCCONNECT */
+RT_C_DECLS_BEGIN
+/*
+ * On OS/2 we'll do the connecting in the assembly code of the
+ * client driver, exporting a g_VBoxGuestIDC symbol containing
+ * the connection information obtained from the 16-bit IDC.
+ */
+extern VBOXGUESTOS2IDCCONNECT g_VBoxGuestIDC;
+RT_C_DECLS_END
+# endif
+
+# if !defined(RT_OS_OS2) \
+  && !defined(RT_OS_WINDOWS)
+RT_C_DECLS_BEGIN
+extern DECLVBGL(void *) VBoxGuestIDCOpen(uint32_t *pu32Version);
+extern DECLVBGL(void)   VBoxGuestIDCClose(void *pvOpaque);
+extern DECLVBGL(int)    VBoxGuestIDCCall(void *pvOpaque, unsigned int iCmd, void *pvData, size_t cbSize, size_t *pcbReturn);
+RT_C_DECLS_END
+# endif
+
+bool vbglDriverIsOpened(VBGLDRIVER *pDriver)
+{
+# ifdef RT_OS_WINDOWS
+    return pDriver->pFileObject != NULL;
+# elif defined (RT_OS_OS2)
+    return pDriver->u32Session != UINT32_MAX && pDriver->u32Session != 0;
+# else
+    return pDriver->pvOpaque != NULL;
+# endif
+}
+
+int vbglDriverOpen(VBGLDRIVER *pDriver)
+{
+# ifdef RT_OS_WINDOWS
+    UNICODE_STRING uszDeviceName;
+    RtlInitUnicodeString(&uszDeviceName, L"\\Device\\VBoxGuest");
+
+    PDEVICE_OBJECT pDeviceObject = NULL;
+    PFILE_OBJECT pFileObject = NULL;
+
+    NTSTATUS rc = IoGetDeviceObjectPointer(&uszDeviceName, FILE_ALL_ACCESS, &pFileObject, &pDeviceObject);
+    if (NT_SUCCESS(rc))
+    {
+        Log(("vbglDriverOpen VBoxGuest successful pDeviceObject=%x\n", pDeviceObject));
+        pDriver->pDeviceObject = pDeviceObject;
+        pDriver->pFileObject = pFileObject;
+        return VINF_SUCCESS;
+    }
+    /** @todo return RTErrConvertFromNtStatus(rc)! */
+    Log(("vbglDriverOpen VBoxGuest failed with ntstatus=%x\n", rc));
+    return rc;
+
+# elif defined (RT_OS_OS2)
+    /*
+     * Just check whether the connection was made or not.
+     */
+    if (   g_VBoxGuestIDC.u32Version == VMMDEV_VERSION
+        && RT_VALID_PTR(g_VBoxGuestIDC.u32Session)
+        && RT_VALID_PTR(g_VBoxGuestIDC.pfnServiceEP))
+    {
+        pDriver->u32Session = g_VBoxGuestIDC.u32Session;
+        return VINF_SUCCESS;
+    }
+    pDriver->u32Session = UINT32_MAX;
+    Log(("vbglDriverOpen: failed\n"));
+    return VERR_FILE_NOT_FOUND;
+
+# else
+    uint32_t u32VMMDevVersion;
+    pDriver->pvOpaque = VBoxGuestIDCOpen(&u32VMMDevVersion);
+    if (   pDriver->pvOpaque
+        && u32VMMDevVersion == VMMDEV_VERSION)
+        return VINF_SUCCESS;
+
+    Log(("vbglDriverOpen: failed\n"));
+    return VERR_FILE_NOT_FOUND;
+# endif
+}
+
+# ifdef RT_OS_WINDOWS
+static NTSTATUS vbglDriverIOCtlCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
+{
+    RT_NOREF2(DeviceObject, Irp);
+    Log(("VBGL completion %x\n", Irp));
+
+    KEVENT *pEvent = (KEVENT *)Context;
+    KeSetEvent(pEvent, IO_NO_INCREMENT, FALSE);
+
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+# endif
+
+int vbglDriverIOCtl(VBGLDRIVER *pDriver, uint32_t u32Function, void *pvData, uint32_t cbData)
+{
+    Log(("vbglDriverIOCtl: pDriver: %p, Func: %x, pvData: %p, cbData: %d\n", pDriver, u32Function, pvData, cbData));
+
+# ifdef RT_OS_WINDOWS
+    KEVENT Event;
+
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+    /* Have to use the IoAllocateIRP method because this code is generic and
+     * must work in any thread context.
+     * The IoBuildDeviceIoControlRequest, which was used here, does not work
+     * when APCs are disabled, for example.
+     */
+    PIRP irp = IoAllocateIrp(pDriver->pDeviceObject->StackSize, FALSE);
+
+    Log(("vbglDriverIOCtl: irp %p, IRQL = %d\n", irp, KeGetCurrentIrql()));
+
+    if (irp == NULL)
+    {
+        Log(("vbglDriverIOCtl: IRP allocation failed!\n"));
+        return VERR_NO_MEMORY;
+    }
+
+    /*
+     * Setup the IRP_MJ_DEVICE_CONTROL IRP.
+     */
+
+    PIO_STACK_LOCATION nextStack = IoGetNextIrpStackLocation(irp);
+
+    nextStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
+    nextStack->MinorFunction = 0;
+    nextStack->DeviceObject = pDriver->pDeviceObject;
+    nextStack->Parameters.DeviceIoControl.OutputBufferLength = cbData;
+    nextStack->Parameters.DeviceIoControl.InputBufferLength = cbData;
+    nextStack->Parameters.DeviceIoControl.IoControlCode = u32Function;
+    nextStack->Parameters.DeviceIoControl.Type3InputBuffer = pvData;
+
+    irp->AssociatedIrp.SystemBuffer = pvData; /* Output buffer. */
+    irp->MdlAddress = NULL;
+
+    /* A completion routine is required to signal the Event. */
+    IoSetCompletionRoutine(irp, vbglDriverIOCtlCompletion, &Event, TRUE, TRUE, TRUE);
+
+    NTSTATUS rc = IoCallDriver(pDriver->pDeviceObject, irp);
+
+    if (NT_SUCCESS (rc))
+    {
+        /* Wait the event to be signalled by the completion routine. */
+        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+
+        rc = irp->IoStatus.Status;
+
+        Log(("vbglDriverIOCtl: wait completed IRQL = %d\n", KeGetCurrentIrql()));
+    }
+
+    IoFreeIrp(irp);
+
+    if (rc != STATUS_SUCCESS)
+        Log(("vbglDriverIOCtl: ntstatus=%x\n", rc));
+
+    if (NT_SUCCESS(rc))
+        return VINF_SUCCESS;
+    if (rc == STATUS_INVALID_PARAMETER)
+        return VERR_INVALID_PARAMETER;
+    if (rc == STATUS_INVALID_BUFFER_SIZE)
+        return VERR_OUT_OF_RANGE;
+    return VERR_VBGL_IOCTL_FAILED;
+
+# elif defined (RT_OS_OS2)
+    if (    pDriver->u32Session
+        &&  pDriver->u32Session == g_VBoxGuestIDC.u32Session)
+        return g_VBoxGuestIDC.pfnServiceEP(pDriver->u32Session, u32Function, pvData, cbData, NULL);
+
+    Log(("vbglDriverIOCtl: No connection\n"));
+    return VERR_WRONG_ORDER;
+
+# else
+    return VBoxGuestIDCCall(pDriver->pvOpaque, u32Function, pvData, cbData, NULL);
+# endif
+}
+
+void vbglDriverClose(VBGLDRIVER *pDriver)
+{
+# ifdef RT_OS_WINDOWS
+    Log(("vbglDriverClose pDeviceObject=%x\n", pDriver->pDeviceObject));
+    ObDereferenceObject(pDriver->pFileObject);
+    pDriver->pFileObject = NULL;
+    pDriver->pDeviceObject = NULL;
+
+# elif defined (RT_OS_OS2)
+    pDriver->u32Session = 0;
+
+# else
+    VBoxGuestIDCClose(pDriver->pvOpaque);
+    pDriver->pvOpaque = NULL;
+# endif
+}
+
+#endif /* !VBGL_VBOXGUEST */
+
diff --git a/ubuntu/vbox/vboxguest/SysHlp.h b/ubuntu/vbox/vboxguest/SysHlp.h
new file mode 100644 (file)
index 0000000..3d0d444
--- /dev/null
@@ -0,0 +1,103 @@
+/* $Id: SysHlp.h $ */
+/** @file
+ * VBoxGuestLibR0 - System dependent helpers internal header.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBoxGuestLib_SysHlp_h
+#define ___VBoxGuestLib_SysHlp_h
+
+#include <iprt/types.h>
+
+#ifdef RT_OS_WINDOWS
+# undef PAGE_SIZE
+# undef PAGE_SHIFT
+# include <iprt/nt/ntddk.h>
+/* XP DDK #defines ExFreePool to ExFreePoolWithTag. The latter does not exist on NT4, so...
+ * The same for ExAllocatePool.
+ */
+# undef ExAllocatePool
+# undef ExFreePool
+#endif
+
+typedef struct _VBGLDRIVER
+{
+#ifdef RT_OS_WINDOWS
+    PDEVICE_OBJECT pDeviceObject;
+    PFILE_OBJECT pFileObject;
+#elif defined (RT_OS_OS2)
+    uint32_t u32Session; /**< just for sanity checking. */
+#else /* PORTME */
+    void *pvOpaque;
+#endif
+} VBGLDRIVER;
+
+int  vbglLockLinear(void **ppvCtx, void *pv, uint32_t cb, bool fWriteAccess, uint32_t fFlags);
+void vbglUnlockLinear(void *pvCtx, void *pv, uint32_t cb);
+
+
+#ifndef VBGL_VBOXGUEST
+
+/**
+ * Open VBoxGuest driver.
+ *
+ * @param pDriver      Pointer to the driver structure.
+ *
+ * @return VBox status code
+ */
+int vbglDriverOpen(VBGLDRIVER *pDriver);
+
+/**
+ * Answers whether the VBoxGuest driver is opened
+ *
+ * @param pDriver      Pointer to the driver structure.
+ *
+ * @return true - if opened, false - otherwise
+ */
+bool vbglDriverIsOpened(VBGLDRIVER *pDriver);
+
+/**
+ * Call VBoxGuest driver.
+ *
+ * @param pDriver      Pointer to the driver structure.
+ * @param u32Function  Function code.
+ * @param pvData       Pointer to supplied in/out data buffer.
+ * @param cbData       Size of data buffer.
+ *
+ * @returns VBox status code
+ */
+int vbglDriverIOCtl(VBGLDRIVER *pDriver, uint32_t u32Function, void *pvData, uint32_t cbData);
+
+/**
+ * Close VBoxGuest driver.
+ *
+ * @param pDriver      Pointer to the driver structure.
+ *
+ * @returns VBox status code
+ */
+void vbglDriverClose(VBGLDRIVER *pDriver);
+
+#endif
+
+#endif
+
diff --git a/ubuntu/vbox/vboxguest/VBGLInternal.h b/ubuntu/vbox/vboxguest/VBGLInternal.h
new file mode 100644 (file)
index 0000000..14208f6
--- /dev/null
@@ -0,0 +1,169 @@
+/* $Id: VBGLInternal.h $ */
+/** @file
+ * VBoxGuestLibR0 - Internal header.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBoxGuestLib_VBGLInternal_h
+#define ___VBoxGuestLib_VBGLInternal_h
+
+#include <VBox/VMMDev.h>
+#include <VBox/VBoxGuest.h>
+#include <VBox/VBoxGuestLib.h>
+
+#include <VBox/log.h>
+
+
+#ifdef RT_OS_WINDOWS /** @todo dprintf() -> Log() */
+# if (defined(DEBUG) && !defined(NO_LOGGING)) || defined(LOG_ENABLED)
+#  define dprintf(a) RTLogBackdoorPrintf a
+# else
+#  define dprintf(a) do {} while (0)
+# endif
+#else
+# define dprintf(a) Log(a)
+#endif
+
+#include "SysHlp.h"
+
+struct _VBGLPHYSHEAPBLOCK;
+typedef struct _VBGLPHYSHEAPBLOCK VBGLPHYSHEAPBLOCK;
+struct _VBGLPHYSHEAPCHUNK;
+typedef struct _VBGLPHYSHEAPCHUNK VBGLPHYSHEAPCHUNK;
+
+#ifndef VBGL_VBOXGUEST
+struct VBGLHGCMHANDLEDATA
+{
+    uint32_t fAllocated;
+    VBGLDRIVER driver;
+};
+#endif
+
+enum VbglLibStatus
+{
+    VbglStatusNotInitialized = 0,
+    VbglStatusInitializing,
+    VbglStatusReady
+};
+
+/**
+ * Global VBGL ring-0 data.
+ * Lives in VbglR0Init.cpp.
+ */
+typedef struct VBGLDATA
+{
+    enum VbglLibStatus status;
+
+    RTIOPORT portVMMDev;
+
+    VMMDevMemory *pVMMDevMemory;
+
+    /**
+     * Physical memory heap data.
+     * @{
+     */
+
+    VBGLPHYSHEAPBLOCK *pFreeBlocksHead;
+    VBGLPHYSHEAPBLOCK *pAllocBlocksHead;
+    VBGLPHYSHEAPCHUNK *pChunkHead;
+
+    RTSEMFASTMUTEX mutexHeap;
+    /** @} */
+
+    /**
+     * The host version data.
+     */
+    VMMDevReqHostVersion hostVersion;
+
+
+#ifndef VBGL_VBOXGUEST
+    /**
+     * Handle for the main driver instance.
+     * @{
+     */
+
+    RTSEMMUTEX mutexDriverInit;
+
+    VBGLDRIVER driver;
+
+    /** @} */
+
+    /**
+     * Fast heap for HGCM handles data.
+     * @{
+     */
+
+    RTSEMFASTMUTEX mutexHGCMHandle;
+
+    struct VBGLHGCMHANDLEDATA aHGCMHandleData[64];
+
+    /** @} */
+#endif
+} VBGLDATA;
+
+
+#ifndef VBGL_DECL_DATA
+extern VBGLDATA g_vbgldata;
+#endif
+
+/**
+ * Internal macro for checking whether we can pass physical page lists to the
+ * host.
+ *
+ * ASSUMES that vbglR0Enter has been called already.
+ *
+ * @param   a_fLocked       For the windows shared folders workarounds.
+ *
+ * @remarks Disabled the PageList feature for locked memory on Windows,
+ *          because a new MDL is created by VBGL to get the page addresses
+ *          and the pages from the MDL are marked as dirty when they should not.
+ */
+#if defined(RT_OS_WINDOWS)
+# define VBGLR0_CAN_USE_PHYS_PAGE_LIST(a_fLocked) \
+    ( !(a_fLocked) && (g_vbgldata.hostVersion.features & VMMDEV_HVF_HGCM_PHYS_PAGE_LIST) )
+#else
+# define VBGLR0_CAN_USE_PHYS_PAGE_LIST(a_fLocked) \
+    ( !!(g_vbgldata.hostVersion.features & VMMDEV_HVF_HGCM_PHYS_PAGE_LIST) )
+#endif
+
+int vbglR0Enter (void);
+
+#ifdef VBOX_WITH_HGCM
+# ifndef VBGL_VBOXGUEST
+int                         vbglR0HGCMInit(void);
+int                         vbglR0HGCMTerminate(void);
+# endif
+struct VBGLHGCMHANDLEDATA  *vbglHGCMHandleAlloc(void);
+void                        vbglHGCMHandleFree(struct VBGLHGCMHANDLEDATA *pHandle);
+#endif /* VBOX_WITH_HGCM */
+
+#ifndef VBGL_VBOXGUEST
+/**
+ * Get a handle to the main VBoxGuest driver.
+ * @returns VERR_TRY_AGAIN if the main driver has not yet been loaded.
+ */
+int vbglGetDriver(VBGLDRIVER **ppDriver);
+#endif
+
+#endif /* !___VBoxGuestLib_VBGLInternal_h */
+
diff --git a/ubuntu/vbox/vboxguest/VBox/log-vbox.c b/ubuntu/vbox/vboxguest/VBox/log-vbox.c
new file mode 100644 (file)
index 0000000..207889c
--- /dev/null
@@ -0,0 +1,776 @@
+/* $Id: log-vbox.cpp $ */
+/** @file
+ * VirtualBox Runtime - Logging configuration.
+ */
+
+/*
+ * 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.
+ */
+
+/** @page pg_rtlog      Runtime - Logging
+ *
+ * VBox uses the IPRT logging system which supports group level flags and multiple
+ * destinations. The GC logging is making it even more interesting since GC logging will
+ * have to be buffered and written when back in host context.
+ *
+ * [more later]
+ *
+ *
+ * @section sec_logging_destination     The Destination Specifier.
+ *
+ * The {logger-env-base}_DEST environment variable can be used to specify where
+ * the log output goes. The following specifiers are recognized:
+ *
+ *      - file=\<filename\>
+ *        This sets the logger output filename to \<filename\>. Not formatting
+ *        or anything is supported. Each logger specifies a default name if
+ *        file logging should be enabled by default.
+ *
+ *      - nofile
+ *        This disables the file output.
+ *
+ *      - stdout
+ *        Enables logger output to stdout.
+ *
+ *      - nostdout
+ *        Disables logger output to stdout.
+ *
+ *      - stderr
+ *        Enables logger output to stderr.
+ *
+ *      - nostderr
+ *        Disables logger output to stderr.
+ *
+ *      - debugger
+ *        Enables logger output to native debugger. (Win32/64 only)
+ *
+ *      - nodebugger
+ *        Disables logger output to native debugger. (Win32/64 only)
+ *
+ *      - user
+ *        Enables logger output to special backdoor if in guest r0.
+ *
+ *      - nodebugger
+ *        Disables logger output to special user stream.
+ *
+ *
+ *
+ * @section sec_logging_group           The Group Specifier.
+ *
+ * The {logger-env-base} environment variable can be used to specify which
+ * logger groups to enable and which to disable. By default all groups are
+ * disabled. For your convenience this specifier is case in-sensitive (ASCII).
+ *
+ * The specifier is evaluated from left to right.
+ *
+ * [more later]
+ *
+ * The groups settings can be reprogrammed during execution using the
+ * RTLogGroupSettings() command and a group specifier.
+ *
+ *
+ *
+ * @section sec_logging_default         The Default Logger
+ *
+ * The default logger uses VBOX_LOG_DEST as destination specifier. File output is
+ * enabled by default and goes to a file "./VBox-\<pid\>.log".
+ *
+ * The default logger have all groups turned off by default to force the developer
+ * to be careful with what log information to collect - logging everything is
+ * generally NOT a good idea.
+ *
+ * The log groups of the default logger can be found in the LOGGROUP in enum. The
+ * VBOX_LOG environment variable and the .log debugger command can be used to
+ * configure the groups.
+ *
+ * Each group have flags in addition to the enable/disable flag. These flags can
+ * be appended to the group name using dot separators. The flags correspond to
+ * RTLOGGRPFLAGS and have a short and a long version:
+ *
+ *      - e - Enabled:  Whether the group is enabled at all.
+ *      - l - Level2:   Level-2 logging.
+ *      - f - Flow:     Execution flow logging (entry messages)
+ *      - s - Sander:   Special Sander logging messages.
+ *      - b - Bird:     Special Bird logging messages.
+ *
+ * @todo Update this section...
+ *
+ * Example:
+ *
+ *      VBOX_LOG=+all+pgm.e.s.b.z.l-qemu
+ *
+ * Space and ';' separators are allowed:
+ *
+ *      VBOX_LOG=+all +pgm.e.s.b.z.l ; - qemu
+ *
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#ifdef IN_RING3
+# if defined(RT_OS_WINDOWS)
+#  include <iprt/win/windows.h>
+# elif defined(RT_OS_LINUX)
+#  include <unistd.h>
+# elif defined(RT_OS_FREEBSD) || defined(RT_OS_NETBSD)
+#  include <sys/param.h>
+#  include <sys/sysctl.h>
+#  if defined(RT_OS_FREEBSD)
+#    include <sys/user.h>
+#  endif
+#  include <stdlib.h>
+#  include <unistd.h>
+# elif defined(RT_OS_HAIKU)
+#  include <OS.h>
+# elif defined(RT_OS_SOLARIS)
+#  define _STRUCTURED_PROC 1
+#  undef _FILE_OFFSET_BITS /* procfs doesn't like this */
+#  include <sys/procfs.h>
+#  include <unistd.h>
+# elif defined(RT_OS_OS2)
+#  include <stdlib.h>
+# endif
+#endif
+
+#include <VBox/log.h>
+#include <iprt/asm.h>
+#include <iprt/err.h>
+#include <iprt/time.h>
+#ifdef IN_RING3
+# include <iprt/param.h>
+# include <iprt/assert.h>
+# include <iprt/path.h>
+# include <iprt/process.h>
+# include <iprt/string.h>
+# include <iprt/mem.h>
+# include <stdio.h>
+#endif
+#if defined(IN_RING0) && defined(RT_OS_DARWIN)
+# include <iprt/asm-amd64-x86.h>
+# include <iprt/thread.h>
+#endif
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** The default logger. */
+static PRTLOGGER                    g_pLogger = NULL;
+/** The default logger groups.
+ * This must match LOGGROUP! */
+static const char                  *g_apszGroups[] =
+VBOX_LOGGROUP_NAMES;
+
+
+/**
+ * Creates the default logger instance for a VBox process.
+ *
+ * @returns Pointer to the logger instance.
+ */
+RTDECL(PRTLOGGER) RTLogDefaultInit(void)
+{
+    /*
+     * Initialize the default logger instance.
+     * Take care to do this once and not recursively.
+     */
+    static volatile uint32_t fInitializing = 0;
+    PRTLOGGER pLogger;
+    int rc;
+
+    if (g_pLogger || !ASMAtomicCmpXchgU32(&fInitializing, 1, 0))
+        return g_pLogger;
+
+#ifdef IN_RING3
+    /*
+     * Assert the group definitions.
+     */
+#define ASSERT_LOG_GROUP(grp)  ASSERT_LOG_GROUP2(LOG_GROUP_##grp, #grp)
+#define ASSERT_LOG_GROUP2(def, str) \
+    do { if (strcmp(g_apszGroups[def], str)) {printf("%s='%s' expects '%s'\n", #def, g_apszGroups[def], str); RTAssertDoPanic(); } } while (0)
+    ASSERT_LOG_GROUP(DEFAULT);
+    ASSERT_LOG_GROUP(AUDIO_MIXER);
+    ASSERT_LOG_GROUP(AUDIO_MIXER_BUFFER);
+    ASSERT_LOG_GROUP(AUTOLOGON);
+    ASSERT_LOG_GROUP(CFGM);
+    ASSERT_LOG_GROUP(CPUM);
+    ASSERT_LOG_GROUP(CSAM);
+    ASSERT_LOG_GROUP(DBGC);
+    ASSERT_LOG_GROUP(DBGF);
+    ASSERT_LOG_GROUP(DBGF_INFO);
+    ASSERT_LOG_GROUP(DBGG);
+    ASSERT_LOG_GROUP(DEV);
+    ASSERT_LOG_GROUP(DEV_AC97);
+    ASSERT_LOG_GROUP(DEV_ACPI);
+    ASSERT_LOG_GROUP(DEV_APIC);
+    ASSERT_LOG_GROUP(DEV_BUSLOGIC);
+    ASSERT_LOG_GROUP(DEV_DMA);
+    ASSERT_LOG_GROUP(DEV_E1000);
+    ASSERT_LOG_GROUP(DEV_EFI);
+    ASSERT_LOG_GROUP(DEV_EHCI);
+    ASSERT_LOG_GROUP(DEV_FDC);
+    ASSERT_LOG_GROUP(DEV_GIM);
+    ASSERT_LOG_GROUP(DEV_HDA);
+    ASSERT_LOG_GROUP(DEV_HDA_CODEC);
+    ASSERT_LOG_GROUP(DEV_HPET);
+    ASSERT_LOG_GROUP(DEV_IDE);
+    ASSERT_LOG_GROUP(DEV_INIP);
+    ASSERT_LOG_GROUP(DEV_KBD);
+    ASSERT_LOG_GROUP(DEV_LPC);
+    ASSERT_LOG_GROUP(DEV_LSILOGICSCSI);
+    ASSERT_LOG_GROUP(DEV_NVME);
+    ASSERT_LOG_GROUP(DEV_OHCI);
+    ASSERT_LOG_GROUP(DEV_PARALLEL);
+    ASSERT_LOG_GROUP(DEV_PC);
+    ASSERT_LOG_GROUP(DEV_PC_ARCH);
+    ASSERT_LOG_GROUP(DEV_PC_BIOS);
+    ASSERT_LOG_GROUP(DEV_PCI);
+    ASSERT_LOG_GROUP(DEV_PCI_RAW);
+    ASSERT_LOG_GROUP(DEV_PCNET);
+    ASSERT_LOG_GROUP(DEV_PIC);
+    ASSERT_LOG_GROUP(DEV_PIT);
+    ASSERT_LOG_GROUP(DEV_RTC);
+    ASSERT_LOG_GROUP(DEV_SB16);
+    ASSERT_LOG_GROUP(DEV_SERIAL);
+    ASSERT_LOG_GROUP(DEV_SMC);
+    ASSERT_LOG_GROUP(DEV_VGA);
+    ASSERT_LOG_GROUP(DEV_VIRTIO);
+    ASSERT_LOG_GROUP(DEV_VIRTIO_NET);
+    ASSERT_LOG_GROUP(DEV_VMM);
+    ASSERT_LOG_GROUP(DEV_VMM_BACKDOOR);
+    ASSERT_LOG_GROUP(DEV_VMM_STDERR);
+    ASSERT_LOG_GROUP(DEV_VMSVGA);
+    ASSERT_LOG_GROUP(DEV_XHCI);
+    ASSERT_LOG_GROUP(DIS);
+    ASSERT_LOG_GROUP(DRV);
+    ASSERT_LOG_GROUP(DRV_ACPI);
+    ASSERT_LOG_GROUP(DRV_AUDIO);
+    ASSERT_LOG_GROUP(DRV_BLOCK);
+    ASSERT_LOG_GROUP(DRV_CHAR);
+    ASSERT_LOG_GROUP(DRV_DISK_INTEGRITY);
+    ASSERT_LOG_GROUP(DRV_DISPLAY);
+    ASSERT_LOG_GROUP(DRV_FLOPPY);
+    ASSERT_LOG_GROUP(DRV_HOST_AUDIO);
+    ASSERT_LOG_GROUP(DRV_HOST_BASE);
+    ASSERT_LOG_GROUP(DRV_HOST_DVD);
+    ASSERT_LOG_GROUP(DRV_HOST_FLOPPY);
+    ASSERT_LOG_GROUP(DRV_HOST_PARALLEL);
+    ASSERT_LOG_GROUP(DRV_HOST_SERIAL);
+    ASSERT_LOG_GROUP(DRV_INTNET);
+    ASSERT_LOG_GROUP(DRV_ISO);
+    ASSERT_LOG_GROUP(DRV_KBD_QUEUE);
+    ASSERT_LOG_GROUP(DRV_LWIP);
+    ASSERT_LOG_GROUP(DRV_MINIPORT);
+    ASSERT_LOG_GROUP(DRV_MOUSE_QUEUE);
+    ASSERT_LOG_GROUP(DRV_NAMEDPIPE);
+    ASSERT_LOG_GROUP(DRV_NAT);
+    ASSERT_LOG_GROUP(DRV_RAW_IMAGE);
+    ASSERT_LOG_GROUP(DRV_SCSI);
+    ASSERT_LOG_GROUP(DRV_SCSIHOST);
+    ASSERT_LOG_GROUP(DRV_TCP);
+    ASSERT_LOG_GROUP(DRV_TRANSPORT_ASYNC);
+    ASSERT_LOG_GROUP(DRV_TUN);
+    ASSERT_LOG_GROUP(DRV_UDPTUNNEL);
+    ASSERT_LOG_GROUP(DRV_USBPROXY);
+    ASSERT_LOG_GROUP(DRV_VBOXHDD);
+    ASSERT_LOG_GROUP(DRV_VD);
+    ASSERT_LOG_GROUP(DRV_VRDE_AUDIO);
+    ASSERT_LOG_GROUP(DRV_VSWITCH);
+    ASSERT_LOG_GROUP(DRV_VUSB);
+    ASSERT_LOG_GROUP(EM);
+    ASSERT_LOG_GROUP(FTM);
+    ASSERT_LOG_GROUP(GIM);
+    ASSERT_LOG_GROUP(GMM);
+    ASSERT_LOG_GROUP(GUEST_CONTROL);
+    ASSERT_LOG_GROUP(GUEST_DND);
+    ASSERT_LOG_GROUP(GUI);
+    ASSERT_LOG_GROUP(GVMM);
+    ASSERT_LOG_GROUP(HGCM);
+    ASSERT_LOG_GROUP(HGSMI);
+    ASSERT_LOG_GROUP(HM);
+    ASSERT_LOG_GROUP(IEM);
+    ASSERT_LOG_GROUP(IOM);
+    ASSERT_LOG_GROUP(IPC);
+    ASSERT_LOG_GROUP(LWIP);
+    ASSERT_LOG_GROUP(LWIP_API_LIB);
+    ASSERT_LOG_GROUP(LWIP_API_MSG);
+    ASSERT_LOG_GROUP(LWIP_ETHARP);
+    ASSERT_LOG_GROUP(LWIP_ICMP);
+    ASSERT_LOG_GROUP(LWIP_IGMP);
+    ASSERT_LOG_GROUP(LWIP_INET);
+    ASSERT_LOG_GROUP(LWIP_IP4);
+    ASSERT_LOG_GROUP(LWIP_IP4_REASS);
+    ASSERT_LOG_GROUP(LWIP_IP6);
+    ASSERT_LOG_GROUP(LWIP_MEM);
+    ASSERT_LOG_GROUP(LWIP_MEMP);
+    ASSERT_LOG_GROUP(LWIP_NETIF);
+    ASSERT_LOG_GROUP(LWIP_PBUF);
+    ASSERT_LOG_GROUP(LWIP_RAW);
+    ASSERT_LOG_GROUP(LWIP_SOCKETS);
+    ASSERT_LOG_GROUP(LWIP_SYS);
+    ASSERT_LOG_GROUP(LWIP_TCP);
+    ASSERT_LOG_GROUP(LWIP_TCPIP);
+    ASSERT_LOG_GROUP(LWIP_TCP_CWND);
+    ASSERT_LOG_GROUP(LWIP_TCP_FR);
+    ASSERT_LOG_GROUP(LWIP_TCP_INPUT);
+    ASSERT_LOG_GROUP(LWIP_TCP_OUTPUT);
+    ASSERT_LOG_GROUP(LWIP_TCP_QLEN);
+    ASSERT_LOG_GROUP(LWIP_TCP_RST);
+    ASSERT_LOG_GROUP(LWIP_TCP_RTO);
+    ASSERT_LOG_GROUP(LWIP_TCP_WND);
+    ASSERT_LOG_GROUP(LWIP_TIMERS);
+    ASSERT_LOG_GROUP(LWIP_UDP);
+    ASSERT_LOG_GROUP(MAIN);
+    ASSERT_LOG_GROUP(MAIN_ADDITIONSFACILITY);
+    ASSERT_LOG_GROUP(MAIN_ADDITIONSSTATECHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_APPLIANCE);
+    ASSERT_LOG_GROUP(MAIN_AUDIOADAPTER);
+    ASSERT_LOG_GROUP(MAIN_BANDWIDTHCONTROL);
+    ASSERT_LOG_GROUP(MAIN_BANDWIDTHGROUP);
+    ASSERT_LOG_GROUP(MAIN_BANDWIDTHGROUPCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_BIOSSETTINGS);
+    ASSERT_LOG_GROUP(MAIN_CANSHOWWINDOWEVENT);
+    ASSERT_LOG_GROUP(MAIN_CLIPBOARDMODECHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_CONSOLE);
+    ASSERT_LOG_GROUP(MAIN_CPUCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_CPUEXECUTIONCAPCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_DHCPSERVER);
+    ASSERT_LOG_GROUP(MAIN_DIRECTORY);
+    ASSERT_LOG_GROUP(MAIN_DISPLAY);
+    ASSERT_LOG_GROUP(MAIN_DISPLAYSOURCEBITMAP);
+    ASSERT_LOG_GROUP(MAIN_DNDBASE);
+    ASSERT_LOG_GROUP(MAIN_DNDMODECHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_DNDSOURCE);
+    ASSERT_LOG_GROUP(MAIN_DNDTARGET);
+    ASSERT_LOG_GROUP(MAIN_EMULATEDUSB);
+    ASSERT_LOG_GROUP(MAIN_EVENT);
+    ASSERT_LOG_GROUP(MAIN_EVENTLISTENER);
+    ASSERT_LOG_GROUP(MAIN_EVENTSOURCE);
+    ASSERT_LOG_GROUP(MAIN_EVENTSOURCECHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_EXTPACK);
+    ASSERT_LOG_GROUP(MAIN_EXTPACKBASE);
+    ASSERT_LOG_GROUP(MAIN_EXTPACKFILE);
+    ASSERT_LOG_GROUP(MAIN_EXTPACKMANAGER);
+    ASSERT_LOG_GROUP(MAIN_EXTPACKPLUGIN);
+    ASSERT_LOG_GROUP(MAIN_EXTRADATACANCHANGEEVENT);
+    ASSERT_LOG_GROUP(MAIN_EXTRADATACHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_FILE);
+    ASSERT_LOG_GROUP(MAIN_FRAMEBUFFER);
+    ASSERT_LOG_GROUP(MAIN_FRAMEBUFFEROVERLAY);
+    ASSERT_LOG_GROUP(MAIN_FSOBJINFO);
+    ASSERT_LOG_GROUP(MAIN_GUEST);
+    ASSERT_LOG_GROUP(MAIN_GUESTDIRECTORY);
+    ASSERT_LOG_GROUP(MAIN_GUESTDNDSOURCE);
+    ASSERT_LOG_GROUP(MAIN_GUESTDNDTARGET);
+    ASSERT_LOG_GROUP(MAIN_GUESTERRORINFO);
+    ASSERT_LOG_GROUP(MAIN_GUESTFILE);
+    ASSERT_LOG_GROUP(MAIN_GUESTFILEEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTFILEIOEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTFILEOFFSETCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTFILEREADEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTFILEREGISTEREDEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTFILESTATECHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTFILEWRITEEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTFSOBJINFO);
+    ASSERT_LOG_GROUP(MAIN_GUESTKEYBOARDEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTMONITORCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTMOUSEEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTMULTITOUCHEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTOSTYPE);
+    ASSERT_LOG_GROUP(MAIN_GUESTPROCESS);
+    ASSERT_LOG_GROUP(MAIN_GUESTPROCESSEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTPROCESSINPUTNOTIFYEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTPROCESSIOEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTPROCESSOUTPUTEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTPROCESSREGISTEREDEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTPROCESSSTATECHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTPROPERTYCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTSESSION);
+    ASSERT_LOG_GROUP(MAIN_GUESTSESSIONEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTSESSIONREGISTEREDEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTSESSIONSTATECHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_GUESTUSERSTATECHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_HOST);
+    ASSERT_LOG_GROUP(MAIN_HOSTNAMERESOLUTIONCONFIGURATIONCHANGEEVENT);
+    ASSERT_LOG_GROUP(MAIN_HOSTNETWORKINTERFACE);
+    ASSERT_LOG_GROUP(MAIN_HOSTPCIDEVICEPLUGEVENT);
+    ASSERT_LOG_GROUP(MAIN_HOSTUSBDEVICE);
+    ASSERT_LOG_GROUP(MAIN_HOSTUSBDEVICEFILTER);
+    ASSERT_LOG_GROUP(MAIN_HOSTVIDEOINPUTDEVICE);
+    ASSERT_LOG_GROUP(MAIN_INTERNALMACHINECONTROL);
+    ASSERT_LOG_GROUP(MAIN_INTERNALSESSIONCONTROL);
+    ASSERT_LOG_GROUP(MAIN_KEYBOARD);
+    ASSERT_LOG_GROUP(MAIN_KEYBOARDLEDSCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_MACHINE);
+    ASSERT_LOG_GROUP(MAIN_MACHINEDATACHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_MACHINEDEBUGGER);
+    ASSERT_LOG_GROUP(MAIN_MACHINEEVENT);
+    ASSERT_LOG_GROUP(MAIN_MACHINEREGISTEREDEVENT);
+    ASSERT_LOG_GROUP(MAIN_MACHINESTATECHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_MEDIUM);
+    ASSERT_LOG_GROUP(MAIN_MEDIUMATTACHMENT);
+    ASSERT_LOG_GROUP(MAIN_MEDIUMCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_MEDIUMCONFIGCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_MEDIUMFORMAT);
+    ASSERT_LOG_GROUP(MAIN_MEDIUMREGISTEREDEVENT);
+    ASSERT_LOG_GROUP(MAIN_MOUSE);
+    ASSERT_LOG_GROUP(MAIN_MOUSECAPABILITYCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_MOUSEPOINTERSHAPE);
+    ASSERT_LOG_GROUP(MAIN_MOUSEPOINTERSHAPECHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_NATENGINE);
+    ASSERT_LOG_GROUP(MAIN_NATNETWORK);
+    ASSERT_LOG_GROUP(MAIN_NATNETWORKALTEREVENT);
+    ASSERT_LOG_GROUP(MAIN_NATNETWORKCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_NATNETWORKCREATIONDELETIONEVENT);
+    ASSERT_LOG_GROUP(MAIN_NATNETWORKPORTFORWARDEVENT);
+    ASSERT_LOG_GROUP(MAIN_NATNETWORKSETTINGEVENT);
+    ASSERT_LOG_GROUP(MAIN_NATNETWORKSTARTSTOPEVENT);
+    ASSERT_LOG_GROUP(MAIN_NATREDIRECTEVENT);
+    ASSERT_LOG_GROUP(MAIN_NETWORKADAPTER);
+    ASSERT_LOG_GROUP(MAIN_NETWORKADAPTERCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_PARALLELPORT);
+    ASSERT_LOG_GROUP(MAIN_PARALLELPORTCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_PCIADDRESS);
+    ASSERT_LOG_GROUP(MAIN_PCIDEVICEATTACHMENT);
+    ASSERT_LOG_GROUP(MAIN_PERFORMANCECOLLECTOR);
+    ASSERT_LOG_GROUP(MAIN_PERFORMANCEMETRIC);
+    ASSERT_LOG_GROUP(MAIN_PROCESS);
+    ASSERT_LOG_GROUP(MAIN_PROGRESS);
+    ASSERT_LOG_GROUP(MAIN_REUSABLEEVENT);
+    ASSERT_LOG_GROUP(MAIN_RUNTIMEERROREVENT);
+    ASSERT_LOG_GROUP(MAIN_SERIALPORT);
+    ASSERT_LOG_GROUP(MAIN_SERIALPORTCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_SESSION);
+    ASSERT_LOG_GROUP(MAIN_SESSIONSTATECHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_SHAREDFOLDER);
+    ASSERT_LOG_GROUP(MAIN_SHAREDFOLDERCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_SHOWWINDOWEVENT);
+    ASSERT_LOG_GROUP(MAIN_SNAPSHOT);
+    ASSERT_LOG_GROUP(MAIN_SNAPSHOTCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_SNAPSHOTDELETEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_SNAPSHOTEVENT);
+    ASSERT_LOG_GROUP(MAIN_SNAPSHOTRESTOREDEVENT);
+    ASSERT_LOG_GROUP(MAIN_SNAPSHOTTAKENEVENT);
+    ASSERT_LOG_GROUP(MAIN_STATECHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_STORAGECONTROLLER);
+    ASSERT_LOG_GROUP(MAIN_STORAGECONTROLLERCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_STORAGEDEVICECHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_SYSTEMPROPERTIES);
+    ASSERT_LOG_GROUP(MAIN_TOKEN);
+    ASSERT_LOG_GROUP(MAIN_USBCONTROLLER);
+    ASSERT_LOG_GROUP(MAIN_USBCONTROLLERCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_USBDEVICE);
+    ASSERT_LOG_GROUP(MAIN_USBDEVICEFILTERS);
+    ASSERT_LOG_GROUP(MAIN_USBDEVICESTATECHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_VBOXSVCAVAILABILITYCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_VIRTUALBOX);
+    ASSERT_LOG_GROUP(MAIN_VIRTUALBOXCLIENT);
+    ASSERT_LOG_GROUP(MAIN_VIRTUALSYSTEMDESCRIPTION);
+    ASSERT_LOG_GROUP(MAIN_VRDESERVER);
+    ASSERT_LOG_GROUP(MAIN_VRDESERVERCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MAIN_VRDESERVERINFO);
+    ASSERT_LOG_GROUP(MAIN_VRDESERVERINFOCHANGEDEVENT);
+    ASSERT_LOG_GROUP(MISC);
+    ASSERT_LOG_GROUP(MM);
+    ASSERT_LOG_GROUP(MM_HEAP);
+    ASSERT_LOG_GROUP(MM_HYPER);
+    ASSERT_LOG_GROUP(MM_HYPER_HEAP);
+    ASSERT_LOG_GROUP(MM_PHYS);
+    ASSERT_LOG_GROUP(MM_POOL);
+    ASSERT_LOG_GROUP(NAT_SERVICE);
+    ASSERT_LOG_GROUP(NET_ADP_DRV);
+    ASSERT_LOG_GROUP(NET_FLT_DRV);
+    ASSERT_LOG_GROUP(NET_SERVICE);
+    ASSERT_LOG_GROUP(NET_SHAPER);
+    ASSERT_LOG_GROUP(PATM);
+    ASSERT_LOG_GROUP(PDM);
+    ASSERT_LOG_GROUP(PDM_ASYNC_COMPLETION);
+    ASSERT_LOG_GROUP(PDM_BLK_CACHE);
+    ASSERT_LOG_GROUP(PDM_DEVICE);
+    ASSERT_LOG_GROUP(PDM_DRIVER);
+    ASSERT_LOG_GROUP(PDM_LDR);
+    ASSERT_LOG_GROUP(PDM_QUEUE);
+    ASSERT_LOG_GROUP(PGM);
+    ASSERT_LOG_GROUP(PGM_DYNMAP);
+    ASSERT_LOG_GROUP(PGM_PHYS);
+    ASSERT_LOG_GROUP(PGM_PHYS_ACCESS);
+    ASSERT_LOG_GROUP(PGM_POOL);
+    ASSERT_LOG_GROUP(PGM_SHARED);
+    ASSERT_LOG_GROUP(REM);
+    ASSERT_LOG_GROUP(REM_DISAS);
+    ASSERT_LOG_GROUP(REM_HANDLER);
+    ASSERT_LOG_GROUP(REM_IOPORT);
+    ASSERT_LOG_GROUP(REM_MMIO);
+    ASSERT_LOG_GROUP(REM_PRINTF);
+    ASSERT_LOG_GROUP(REM_RUN);
+    ASSERT_LOG_GROUP(SELM);
+    ASSERT_LOG_GROUP(SHARED_CLIPBOARD);
+    ASSERT_LOG_GROUP(SHARED_CROPENGL);
+    ASSERT_LOG_GROUP(SHARED_FOLDERS);
+    ASSERT_LOG_GROUP(SHARED_OPENGL);
+    ASSERT_LOG_GROUP(SRV_INTNET);
+    ASSERT_LOG_GROUP(SSM);
+    ASSERT_LOG_GROUP(STAM);
+    ASSERT_LOG_GROUP(SUP);
+    ASSERT_LOG_GROUP(TM);
+    ASSERT_LOG_GROUP(TRPM);
+    ASSERT_LOG_GROUP(USB_CARDREADER);
+    ASSERT_LOG_GROUP(USB_DRV);
+    ASSERT_LOG_GROUP(USB_FILTER);
+    ASSERT_LOG_GROUP(USB_KBD);
+    ASSERT_LOG_GROUP(USB_MOUSE);
+    ASSERT_LOG_GROUP(USB_MSD);
+    ASSERT_LOG_GROUP(USB_REMOTE);
+    ASSERT_LOG_GROUP(USB_WEBCAM);
+    ASSERT_LOG_GROUP(VGDRV);
+    ASSERT_LOG_GROUP(VBGL);
+    ASSERT_LOG_GROUP(VD);
+    ASSERT_LOG_GROUP(VD_DMG);
+    ASSERT_LOG_GROUP(VD_ISCSI);
+    ASSERT_LOG_GROUP(VD_PARALLELS);
+    ASSERT_LOG_GROUP(VD_QCOW);
+    ASSERT_LOG_GROUP(VD_QED);
+    ASSERT_LOG_GROUP(VD_RAW);
+    ASSERT_LOG_GROUP(VD_VDI);
+    ASSERT_LOG_GROUP(VD_VHD);
+    ASSERT_LOG_GROUP(VD_VHDX);
+    ASSERT_LOG_GROUP(VD_VMDK);
+    ASSERT_LOG_GROUP(VM);
+    ASSERT_LOG_GROUP(VMM);
+    ASSERT_LOG_GROUP(VRDE);
+    ASSERT_LOG_GROUP(VRDP);
+    ASSERT_LOG_GROUP(VSCSI);
+    ASSERT_LOG_GROUP(WEBSERVICE);
+#undef ASSERT_LOG_GROUP
+#undef ASSERT_LOG_GROUP2
+#endif /* IN_RING3 */
+
+    /*
+     * Create the default logging instance.
+     */
+#ifdef IN_RING3
+# ifndef IN_GUEST
+    char szExecName[RTPATH_MAX];
+    if (!RTProcGetExecutablePath(szExecName, sizeof(szExecName)))
+        strcpy(szExecName, "VBox");
+    RTTIMESPEC TimeSpec;
+    RTTIME Time;
+    RTTimeExplode(&Time, RTTimeNow(&TimeSpec));
+    rc = RTLogCreate(&pLogger, 0, NULL, "VBOX_LOG", RT_ELEMENTS(g_apszGroups), &g_apszGroups[0], RTLOGDEST_FILE,
+                     "./%04d-%02d-%02d-%02d-%02d-%02d.%03d-%s-%d.log",
+                     Time.i32Year, Time.u8Month, Time.u8MonthDay, Time.u8Hour, Time.u8Minute, Time.u8Second, Time.u32Nanosecond / 10000000,
+                     RTPathFilename(szExecName), RTProcSelf());
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Write a log header.
+         */
+        char szBuf[RTPATH_MAX];
+        RTTimeSpecToString(&TimeSpec, szBuf, sizeof(szBuf));
+        RTLogLoggerEx(pLogger, 0, ~0U, "Log created: %s\n", szBuf);
+        RTLogLoggerEx(pLogger, 0, ~0U, "Executable: %s\n", szExecName);
+
+        /* executable and arguments - tricky and all platform specific. */
+#  if defined(RT_OS_WINDOWS)
+        RTLogLoggerEx(pLogger, 0, ~0U, "Commandline: %ls\n", GetCommandLineW());
+
+#  elif defined(RT_OS_SOLARIS)
+        psinfo_t psi;
+        char szArgFileBuf[80];
+        RTStrPrintf(szArgFileBuf, sizeof(szArgFileBuf), "/proc/%ld/psinfo", (long)getpid());
+        FILE* pFile = fopen(szArgFileBuf, "rb");
+        if (pFile)
+        {
+            if (fread(&psi, sizeof(psi), 1, pFile) == 1)
+            {
+#   if 0     /* 100% safe:*/
+                RTLogLoggerEx(pLogger, 0, ~0U, "Args: %s\n", psi.pr_psargs);
+#   else     /* probably safe: */
+                const char * const *argv = (const char * const *)psi.pr_argv;
+                for (int iArg = 0; iArg < psi.pr_argc; iArg++)
+                    RTLogLoggerEx(pLogger, 0, ~0U, "Arg[%d]: %s\n", iArg, argv[iArg]);
+#   endif
+
+            }
+            fclose(pFile);
+        }
+
+#  elif defined(RT_OS_LINUX)
+        FILE *pFile = fopen("/proc/self/cmdline", "r");
+        if (pFile)
+        {
+            /* braindead */
+            unsigned iArg = 0;
+            int ch;
+            bool fNew = true;
+            while (!feof(pFile) && (ch = fgetc(pFile)) != EOF)
+            {
+                if (fNew)
+                {
+                    RTLogLoggerEx(pLogger, 0, ~0U, "Arg[%u]: ", iArg++);
+                    fNew = false;
+                }
+                if (ch)
+                    RTLogLoggerEx(pLogger, 0, ~0U, "%c", ch);
+                else
+                {
+                    RTLogLoggerEx(pLogger, 0, ~0U, "\n");
+                    fNew = true;
+                }
+            }
+            if (!fNew)
+                RTLogLoggerEx(pLogger, 0, ~0U, "\n");
+            fclose(pFile);
+        }
+
+#  elif defined(RT_OS_HAIKU)
+        team_info info;
+        if (get_team_info(0, &info) == B_OK)
+        {
+            /* there is an info.argc, but no way to know arg boundaries */
+            RTLogLoggerEx(pLogger, 0, ~0U, "Commandline: %.64s\n", info.args);
+        }
+
+#  elif defined(RT_OS_FREEBSD) || defined(RT_OS_NETBSD)
+        /* Retrieve the required length first */
+        int aiName[4];
+#  if defined(RT_OS_FREEBSD)
+        aiName[0] = CTL_KERN;
+        aiName[1] = KERN_PROC;
+        aiName[2] = KERN_PROC_ARGS;     /* Introduced in FreeBSD 4.0 */
+        aiName[3] = getpid();
+#  elif defined(RT_OS_NETBSD)
+        aiName[0] = CTL_KERN;
+        aiName[1] = KERN_PROC_ARGS;
+        aiName[2] = getpid();
+        aiName[3] = KERN_PROC_ARGV;
+#  endif
+        size_t cchArgs = 0;
+        int rcBSD = sysctl(aiName, RT_ELEMENTS(aiName), NULL, &cchArgs, NULL, 0);
+        if (cchArgs > 0)
+        {
+            char *pszArgFileBuf = (char *)RTMemAllocZ(cchArgs + 1 /* Safety */);
+            if (pszArgFileBuf)
+            {
+                /* Retrieve the argument list */
+                rcBSD = sysctl(aiName, RT_ELEMENTS(aiName), pszArgFileBuf, &cchArgs, NULL, 0);
+                if (!rcBSD)
+                {
+                    unsigned    iArg = 0;
+                    size_t      off = 0;
+                    while (off < cchArgs)
+                    {
+                        size_t cchArg = strlen(&pszArgFileBuf[off]);
+                        RTLogLoggerEx(pLogger, 0, ~0U, "Arg[%u]: %s\n", iArg, &pszArgFileBuf[off]);
+
+                        /* advance */
+                        off += cchArg + 1;
+                        iArg++;
+                    }
+                }
+                RTMemFree(pszArgFileBuf);
+            }
+        }
+
+#  elif defined(RT_OS_OS2) || defined(RT_OS_DARWIN)
+        /* commandline? */
+#  else
+#   error needs porting.
+#  endif
+    }
+
+# else  /* IN_GUEST */
+    /* The user destination is backdoor logging. */
+    rc = RTLogCreate(&pLogger, 0, NULL, "VBOX_LOG", RT_ELEMENTS(g_apszGroups), &g_apszGroups[0], RTLOGDEST_USER, "VBox.log");
+# endif /* IN_GUEST */
+
+#else /* IN_RING0 */
+
+    /* Some platforms has trouble allocating memory with interrupts and/or
+       preemption disabled. Check and fail before we panic. */
+# if defined(RT_OS_DARWIN)
+    if (   !ASMIntAreEnabled()
+        || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
+        return NULL;
+# endif
+
+# ifndef IN_GUEST
+    rc = RTLogCreate(&pLogger, 0, NULL, "VBOX_LOG", RT_ELEMENTS(g_apszGroups), &g_apszGroups[0], RTLOGDEST_FILE, "VBox-ring0.log");
+# else  /* IN_GUEST */
+    rc = RTLogCreate(&pLogger, 0, NULL, "VBOX_LOG", RT_ELEMENTS(g_apszGroups), &g_apszGroups[0], RTLOGDEST_USER, "VBox-ring0.log");
+# endif /* IN_GUEST */
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * This is where you set your ring-0 logging preferences.
+         *
+         * On platforms which don't differ between debugger and kernel
+         * log printing, STDOUT is gonna be a stub and the DEBUGGER
+         * destination is the one doing all the work. On platforms
+         * that do differ (like Darwin), STDOUT is the kernel log.
+         */
+# if defined(DEBUG_bird)
+        /*RTLogGroupSettings(pLogger, "all=~0 -default.l6.l5.l4.l3");*/
+        RTLogFlags(pLogger, "enabled unbuffered pid tid");
+#  ifndef IN_GUEST
+        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER | RTLOGDEST_STDOUT;
+#  else
+        RTLogGroupSettings(pLogger, "all=~0 -default.l6.l5.l4.l3");
+#  endif
+# endif
+# if defined(DEBUG_sandervl) && !defined(IN_GUEST)
+        RTLogGroupSettings(pLogger, "+all");
+        RTLogFlags(pLogger, "enabled unbuffered");
+        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER;
+# endif
+# if defined(DEBUG_ramshankar)  /* Guest ring-0 as well */
+        RTLogGroupSettings(pLogger, "+all.e.l.f");
+        RTLogFlags(pLogger, "enabled unbuffered");
+        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER;
+# endif
+# if defined(DEBUG_aleksey)  /* Guest ring-0 as well */
+        RTLogGroupSettings(pLogger, "net_flt_drv.e.l.f.l3.l4.l5 +net_adp_drv.e.l.f.l3.l4.l5.l6");
+        RTLogFlags(pLogger, "enabled unbuffered");
+        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER | RTLOGDEST_STDOUT;
+# endif
+# if defined(DEBUG_andy)  /* Guest ring-0 as well */
+        RTLogGroupSettings(pLogger, "+all.e.l.f");
+        RTLogFlags(pLogger, "enabled unbuffered pid tid");
+        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER | RTLOGDEST_STDOUT;
+# endif
+# if defined(DEBUG_misha) /* Guest ring-0 as well */
+        RTLogFlags(pLogger, "enabled unbuffered");
+        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER;
+# endif
+# if defined(DEBUG_michael) && defined(IN_GUEST)
+        RTLogGroupSettings(pLogger, "+vga.e.l.f");
+        RTLogFlags(pLogger, "enabled unbuffered");
+        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER | RTLOGDEST_STDOUT;
+# endif
+# if 0 /* vboxdrv logging - ATTENTION: this is what we're referring to guys! Change to '# if 1'. */
+        RTLogGroupSettings(pLogger, "all=~0 -default.l6.l5.l4.l3");
+        RTLogFlags(pLogger, "enabled unbuffered tid");
+        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER | RTLOGDEST_STDOUT;
+# endif
+    }
+#endif /* IN_RING0 */
+    return g_pLogger = RT_SUCCESS(rc) ? pLogger : NULL;
+}
diff --git a/ubuntu/vbox/vboxguest/VBox/logbackdoor.c b/ubuntu/vbox/vboxguest/VBox/logbackdoor.c
new file mode 100644 (file)
index 0000000..5ac3667
--- /dev/null
@@ -0,0 +1,95 @@
+/* $Id: logbackdoor.cpp $ */
+/** @file
+ * VirtualBox Runtime - Guest Backdoor Logging.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <VBox/log.h>
+#include "internal/iprt.h"
+#include <iprt/asm-amd64-x86.h>
+#include <iprt/string.h>
+#ifdef IN_GUEST_R3
+# include <VBox/VBoxGuestLib.h>
+#endif
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+static DECLCALLBACK(size_t) rtLogBackdoorOutput(void *pv, const char *pachChars, size_t cbChars);
+
+
+RTDECL(size_t) RTLogBackdoorPrintf(const char *pszFormat, ...)
+{
+    va_list args;
+    size_t cb;
+
+    va_start(args, pszFormat);
+    cb = RTLogBackdoorPrintfV(pszFormat, args);
+    va_end(args);
+
+    return cb;
+}
+
+RT_EXPORT_SYMBOL(RTLogBackdoorPrintf);
+
+
+RTDECL(size_t) RTLogBackdoorPrintfV(const char *pszFormat, va_list args)
+{
+    return RTLogFormatV(rtLogBackdoorOutput, NULL, pszFormat, args);
+}
+
+RT_EXPORT_SYMBOL(RTLogBackdoorPrintfV);
+
+
+/**
+ * Callback for RTLogFormatV which writes to the backdoor.
+ * See PFNRTSTROUTPUT() for details.
+ */
+static DECLCALLBACK(size_t) rtLogBackdoorOutput(void *pvArg, const char *pachChars, size_t cbChars)
+{
+    RT_NOREF_PV(pvArg);
+    RTLogWriteUser(pachChars, cbChars);
+    return cbChars;
+}
+
+
+RTDECL(void) RTLogWriteUser(const char *pch, size_t cb)
+{
+#ifdef IN_GUEST_R3
+    VbglR3WriteLog(pch, cb);
+#else  /* !IN_GUEST_R3 */
+    const uint8_t *pau8 = (const uint8_t *)pch;
+    if (cb > 1)
+        ASMOutStrU8(RTLOG_DEBUG_PORT, pau8, cb);
+    else if (cb)
+        ASMOutU8(RTLOG_DEBUG_PORT, *pau8);
+#endif /* !IN_GUEST_R3 */
+}
+
+RT_EXPORT_SYMBOL(RTLogWriteUser);
+
diff --git a/ubuntu/vbox/vboxguest/VBoxGuest-linux.c b/ubuntu/vbox/vboxguest/VBoxGuest-linux.c
new file mode 100644 (file)
index 0000000..bd81000
--- /dev/null
@@ -0,0 +1,1087 @@
+/* $Rev: 109079 $ */
+/** @file
+ * VBoxGuest - Linux specifics.
+ *
+ * Note. Unfortunately, the difference between this and SUPDrv-linux.c is
+ *       a little bit too big to be helpful.
+ */
+
+/*
+ * 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.
+  */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_SUP_DRV
+
+#include "the-linux-kernel.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 15)
+# define VBOXGUEST_WITH_INPUT_DRIVER
+#endif
+
+#include "VBoxGuestInternal.h"
+#ifdef VBOXGUEST_WITH_INPUT_DRIVER
+# include <linux/input.h>
+#endif
+#include <linux/miscdevice.h>
+#include <linux/poll.h>
+#include <VBox/version.h>
+#include "revision-generated.h"
+
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+#include <iprt/err.h>
+#include <iprt/initterm.h>
+#include <iprt/mem.h>
+#include <iprt/mp.h>
+#include <iprt/process.h>
+#include <iprt/spinlock.h>
+#include <iprt/semaphore.h>
+#include <VBox/log.h>
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+/** The device name. */
+#define DEVICE_NAME             "vboxguest"
+/** The device name for the device node open to everyone. */
+#define DEVICE_NAME_USER        "vboxuser"
+/** The name of the PCI driver */
+#define DRIVER_NAME             DEVICE_NAME
+
+
+/* 2.4.x compatibility macros that may or may not be defined. */
+#ifndef IRQ_RETVAL
+# define irqreturn_t            void
+# define IRQ_RETVAL(n)
+#endif
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+static void vgdrvLinuxTermPci(struct pci_dev *pPciDev);
+static int  vgdrvLinuxProbePci(struct pci_dev *pPciDev, const struct pci_device_id *id);
+static int  vgdrvLinuxModInit(void);
+static void vgdrvLinuxModExit(void);
+static int  vgdrvLinuxOpen(struct inode *pInode, struct file *pFilp);
+static int  vgdrvLinuxRelease(struct inode *pInode, struct file *pFilp);
+#ifdef HAVE_UNLOCKED_IOCTL
+static long vgdrvLinuxIOCtl(struct file *pFilp, unsigned int uCmd, unsigned long ulArg);
+#else
+static int  vgdrvLinuxIOCtl(struct inode *pInode, struct file *pFilp, unsigned int uCmd, unsigned long ulArg);
+#endif
+static int  vgdrvLinuxFAsync(int fd, struct file *pFile, int fOn);
+static unsigned int vgdrvLinuxPoll(struct file *pFile, poll_table *pPt);
+static ssize_t vgdrvLinuxRead(struct file *pFile, char *pbBuf, size_t cbRead, loff_t *poff);
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/**
+ * Device extention & session data association structure.
+ */
+static VBOXGUESTDEVEXT          g_DevExt;
+/** The PCI device. */
+static struct pci_dev          *g_pPciDev = NULL;
+/** The base of the I/O port range. */
+static RTIOPORT                 g_IOPortBase;
+/** The base of the MMIO range. */
+static RTHCPHYS                 g_MMIOPhysAddr = NIL_RTHCPHYS;
+/** The size of the MMIO range as seen by PCI. */
+static uint32_t                 g_cbMMIO;
+/** The pointer to the mapping of the MMIO range. */
+static void                    *g_pvMMIOBase;
+/** Wait queue used by polling. */
+static wait_queue_head_t        g_PollEventQueue;
+/** Asynchronous notification stuff.  */
+static struct fasync_struct    *g_pFAsyncQueue;
+#ifdef VBOXGUEST_WITH_INPUT_DRIVER
+/** Pre-allocated mouse status VMMDev request for use in the IRQ
+ * handler. */
+static VMMDevReqMouseStatus    *g_pMouseStatusReq;
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+/** Whether we've create the logger or not. */
+static volatile bool            g_fLoggerCreated;
+/** Release logger group settings. */
+static char                     g_szLogGrp[128];
+/** Release logger flags settings. */
+static char                     g_szLogFlags[128];
+/** Release logger destination settings. */
+static char                     g_szLogDst[128];
+# if 0
+/** Debug logger group settings. */
+static char                     g_szDbgLogGrp[128];
+/** Debug logger flags settings. */
+static char                     g_szDbgLogFlags[128];
+/** Debug logger destination settings. */
+static char                     g_szDbgLogDst[128];
+# endif
+#endif
+
+/** The input device handle */
+#ifdef VBOXGUEST_WITH_INPUT_DRIVER
+static struct input_dev        *g_pInputDevice = NULL;
+#endif
+
+/** The file_operations structure. */
+static struct file_operations   g_FileOps =
+{
+    owner:          THIS_MODULE,
+    open:           vgdrvLinuxOpen,
+    release:        vgdrvLinuxRelease,
+#ifdef HAVE_UNLOCKED_IOCTL
+    unlocked_ioctl: vgdrvLinuxIOCtl,
+#else
+    ioctl:          vgdrvLinuxIOCtl,
+#endif
+    fasync:         vgdrvLinuxFAsync,
+    read:           vgdrvLinuxRead,
+    poll:           vgdrvLinuxPoll,
+    llseek:         no_llseek,
+};
+
+/** The miscdevice structure. */
+static struct miscdevice        g_MiscDevice =
+{
+    minor:          MISC_DYNAMIC_MINOR,
+    name:           DEVICE_NAME,
+    fops:           &g_FileOps,
+};
+
+/** The file_operations structure for the user device.
+ * @remarks For the time being we'll be using the same implementation as
+ *          /dev/vboxguest here. */
+static struct file_operations   g_FileOpsUser =
+{
+    owner:          THIS_MODULE,
+    open:           vgdrvLinuxOpen,
+    release:        vgdrvLinuxRelease,
+#ifdef HAVE_UNLOCKED_IOCTL
+    unlocked_ioctl: vgdrvLinuxIOCtl,
+#else
+    ioctl:          vgdrvLinuxIOCtl,
+#endif
+};
+
+/** The miscdevice structure for the user device. */
+static struct miscdevice        g_MiscDeviceUser =
+{
+    minor:          MISC_DYNAMIC_MINOR,
+    name:           DEVICE_NAME_USER,
+    fops:           &g_FileOpsUser,
+};
+
+
+/** PCI hotplug structure. */
+static const struct pci_device_id
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+__devinitdata
+#endif
+g_VBoxGuestPciId[] =
+{
+    {
+        vendor:     VMMDEV_VENDORID,
+        device:     VMMDEV_DEVICEID
+    },
+    {
+        /* empty entry */
+    }
+};
+
+MODULE_DEVICE_TABLE(pci, g_VBoxGuestPciId);
+
+/** Structure for registering the PCI driver. */
+static struct pci_driver  g_PciDriver =
+{
+    name:           DRIVER_NAME,
+    id_table:       g_VBoxGuestPciId,
+    probe:          vgdrvLinuxProbePci,
+    remove:         vgdrvLinuxTermPci
+};
+
+static PVBOXGUESTSESSION        g_pKernelSession = NULL;
+
+
+
+/**
+ * Converts a VBox status code to a linux error code.
+ *
+ * @returns corresponding negative linux error code.
+ * @param   rc  supdrv error code (SUPDRV_ERR_* defines).
+ */
+static int vgdrvLinuxConvertToNegErrno(int rc)
+{
+    if (   rc > -1000
+        && rc < 1000)
+        return -RTErrConvertToErrno(rc);
+    switch (rc)
+    {
+        case VERR_HGCM_SERVICE_NOT_FOUND:      return -ESRCH;
+        case VINF_HGCM_CLIENT_REJECTED:        return 0;
+        case VERR_HGCM_INVALID_CMD_ADDRESS:    return -EFAULT;
+        case VINF_HGCM_ASYNC_EXECUTE:          return 0;
+        case VERR_HGCM_INTERNAL:               return -EPROTO;
+        case VERR_HGCM_INVALID_CLIENT_ID:      return -EINVAL;
+        case VINF_HGCM_SAVE_STATE:             return 0;
+        /* No reason to return this to a guest */
+        // case VERR_HGCM_SERVICE_EXISTS:         return -EEXIST;
+        default:
+            AssertMsgFailed(("Unhandled error code %Rrc\n", rc));
+            return -EPROTO;
+    }
+}
+
+
+/**
+ * Does the PCI detection and init of the device.
+ *
+ * @returns 0 on success, negated errno on failure.
+ */
+static int vgdrvLinuxProbePci(struct pci_dev *pPciDev, const struct pci_device_id *id)
+{
+    int rc;
+
+    NOREF(id);
+    AssertReturn(!g_pPciDev, -EINVAL);
+    rc = pci_enable_device(pPciDev);
+    if (rc >= 0)
+    {
+        /* I/O Ports are mandatory, the MMIO bit is not. */
+        g_IOPortBase = pci_resource_start(pPciDev, 0);
+        if (g_IOPortBase != 0)
+        {
+            /*
+             * Map the register address space.
+             */
+            g_MMIOPhysAddr = pci_resource_start(pPciDev, 1);
+            g_cbMMIO       = pci_resource_len(pPciDev, 1);
+            if (request_mem_region(g_MMIOPhysAddr, g_cbMMIO, DEVICE_NAME) != NULL)
+            {
+                g_pvMMIOBase = ioremap(g_MMIOPhysAddr, g_cbMMIO);
+                if (g_pvMMIOBase)
+                {
+                    /** @todo why aren't we requesting ownership of the I/O ports as well? */
+                    g_pPciDev = pPciDev;
+                    return 0;
+                }
+
+                /* failure cleanup path */
+                LogRel((DEVICE_NAME ": ioremap failed; MMIO Addr=%RHp cb=%#x\n", g_MMIOPhysAddr, g_cbMMIO));
+                rc = -ENOMEM;
+                release_mem_region(g_MMIOPhysAddr, g_cbMMIO);
+            }
+            else
+            {
+                LogRel((DEVICE_NAME ": failed to obtain adapter memory\n"));
+                rc = -EBUSY;
+            }
+            g_MMIOPhysAddr = NIL_RTHCPHYS;
+            g_cbMMIO       = 0;
+            g_IOPortBase   = 0;
+        }
+        else
+        {
+            LogRel((DEVICE_NAME ": did not find expected hardware resources\n"));
+            rc = -ENXIO;
+        }
+        pci_disable_device(pPciDev);
+    }
+    else
+        LogRel((DEVICE_NAME ": could not enable device: %d\n", rc));
+    return rc;
+}
+
+
+/**
+ * Clean up the usage of the PCI device.
+ */
+static void vgdrvLinuxTermPci(struct pci_dev *pPciDev)
+{
+    g_pPciDev = NULL;
+    if (pPciDev)
+    {
+        iounmap(g_pvMMIOBase);
+        g_pvMMIOBase = NULL;
+
+        release_mem_region(g_MMIOPhysAddr, g_cbMMIO);
+        g_MMIOPhysAddr = NIL_RTHCPHYS;
+        g_cbMMIO = 0;
+
+        pci_disable_device(pPciDev);
+    }
+}
+
+
+/**
+ * Interrupt service routine.
+ *
+ * @returns In 2.4 it returns void.
+ *          In 2.6 we indicate whether we've handled the IRQ or not.
+ *
+ * @param   iIrq            The IRQ number.
+ * @param   pvDevId         The device ID, a pointer to g_DevExt.
+ * @param   pRegs           Register set. Removed in 2.6.19.
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) && !defined(DOXYGEN_RUNNING)
+static irqreturn_t vgdrvLinuxISR(int iIrq, void *pvDevId)
+#else
+static irqreturn_t vgdrvLinuxISR(int iIrq, void *pvDevId, struct pt_regs *pRegs)
+#endif
+{
+    bool fTaken = VGDrvCommonISR(&g_DevExt);
+    return IRQ_RETVAL(fTaken);
+}
+
+
+/**
+ * Registers the ISR and initializes the poll wait queue.
+ */
+static int __init vgdrvLinuxInitISR(void)
+{
+    int rc;
+
+    init_waitqueue_head(&g_PollEventQueue);
+    rc = request_irq(g_pPciDev->irq,
+                     vgdrvLinuxISR,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+                     IRQF_SHARED,
+#else
+                     SA_SHIRQ,
+#endif
+                     DEVICE_NAME,
+                     &g_DevExt);
+    if (rc)
+    {
+        LogRel((DEVICE_NAME ": could not request IRQ %d: err=%d\n", g_pPciDev->irq, rc));
+        return rc;
+    }
+    return 0;
+}
+
+
+/**
+ * Deregisters the ISR.
+ */
+static void vgdrvLinuxTermISR(void)
+{
+    free_irq(g_pPciDev->irq, &g_DevExt);
+}
+
+
+#ifdef VBOXGUEST_WITH_INPUT_DRIVER
+
+/**
+ * Reports the mouse integration status to the host.
+ *
+ * Calls the kernel IOCtl to report mouse status to the host on behalf of
+ * our kernel session.
+ *
+ * @param   fStatus     The mouse status to report.
+ */
+static int vgdrvLinuxSetMouseStatus(uint32_t fStatus)
+{
+    return VGDrvCommonIoCtl(VBOXGUEST_IOCTL_SET_MOUSE_STATUS, &g_DevExt, g_pKernelSession, &fStatus, sizeof(fStatus), NULL);
+}
+
+
+/**
+ * Called when the input device is first opened.
+ *
+ * Sets up absolute mouse reporting.
+ */
+static int vboxguestOpenInputDevice(struct input_dev *pDev)
+{
+    int rc = vgdrvLinuxSetMouseStatus(VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE | VMMDEV_MOUSE_NEW_PROTOCOL);
+    if (RT_FAILURE(rc))
+        return ENODEV;
+    NOREF(pDev);
+    return 0;
+}
+
+
+/**
+ * Called if all open handles to the input device are closed.
+ *
+ * Disables absolute reporting.
+ */
+static void vboxguestCloseInputDevice(struct input_dev *pDev)
+{
+    NOREF(pDev);
+    vgdrvLinuxSetMouseStatus(0);
+}
+
+
+/**
+ * Creates the kernel input device.
+ */
+static int __init vgdrvLinuxCreateInputDevice(void)
+{
+    int rc = VbglGRAlloc((VMMDevRequestHeader **)&g_pMouseStatusReq, sizeof(*g_pMouseStatusReq), VMMDevReq_GetMouseStatus);
+    if (RT_SUCCESS(rc))
+    {
+        g_pInputDevice = input_allocate_device();
+        if (g_pInputDevice)
+        {
+            g_pInputDevice->id.bustype = BUS_PCI;
+            g_pInputDevice->id.vendor  = VMMDEV_VENDORID;
+            g_pInputDevice->id.product = VMMDEV_DEVICEID;
+            g_pInputDevice->id.version = VBOX_SHORT_VERSION;
+            g_pInputDevice->open       = vboxguestOpenInputDevice;
+            g_pInputDevice->close      = vboxguestCloseInputDevice;
+# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
+            g_pInputDevice->cdev.dev   = &g_pPciDev->dev;
+# else
+            g_pInputDevice->dev.parent = &g_pPciDev->dev;
+# endif
+            rc = input_register_device(g_pInputDevice);
+            if (rc == 0)
+            {
+                /* Do what one of our competitors apparently does as that works. */
+                ASMBitSet(g_pInputDevice->evbit, EV_ABS);
+                ASMBitSet(g_pInputDevice->evbit, EV_KEY);
+# ifdef EV_SYN
+                ASMBitSet(g_pInputDevice->evbit, EV_SYN);
+# endif
+                input_set_abs_params(g_pInputDevice, ABS_X, VMMDEV_MOUSE_RANGE_MIN, VMMDEV_MOUSE_RANGE_MAX, 0, 0);
+                input_set_abs_params(g_pInputDevice, ABS_Y, VMMDEV_MOUSE_RANGE_MIN, VMMDEV_MOUSE_RANGE_MAX, 0, 0);
+                ASMBitSet(g_pInputDevice->keybit, BTN_MOUSE);
+                /** @todo this string should be in a header file somewhere. */
+                g_pInputDevice->name = "VirtualBox mouse integration";
+                return 0;
+            }
+
+            input_free_device(g_pInputDevice);
+        }
+        else
+            rc = -ENOMEM;
+        VbglGRFree(&g_pMouseStatusReq->header);
+        g_pMouseStatusReq = NULL;
+    }
+    else
+        rc = -ENOMEM;
+    return rc;
+}
+
+
+/**
+ * Terminates the kernel input device.
+ */
+static void vgdrvLinuxTermInputDevice(void)
+{
+    VbglGRFree(&g_pMouseStatusReq->header);
+    g_pMouseStatusReq = NULL;
+
+    /* See documentation of input_register_device(): input_free_device()
+     * should not be called after a device has been registered. */
+    input_unregister_device(g_pInputDevice);
+}
+
+#endif /* VBOXGUEST_WITH_INPUT_DRIVER */
+
+
+/**
+ * Creates the device nodes.
+ *
+ * @returns 0 on success, negated errno on failure.
+ */
+static int __init vgdrvLinuxInitDeviceNodes(void)
+{
+    /*
+     * The full feature device node.
+     */
+    int rc = misc_register(&g_MiscDevice);
+    if (!rc)
+    {
+        /*
+         * The device node intended to be accessible by all users.
+         */
+        rc = misc_register(&g_MiscDeviceUser);
+        if (!rc)
+            return 0;
+        LogRel((DEVICE_NAME ": misc_register failed for %s (rc=%d)\n", DEVICE_NAME_USER, rc));
+        misc_deregister(&g_MiscDevice);
+    }
+    else
+        LogRel((DEVICE_NAME ": misc_register failed for %s (rc=%d)\n", DEVICE_NAME, rc));
+    return rc;
+}
+
+
+/**
+ * Deregisters the device nodes.
+ */
+static void vgdrvLinuxTermDeviceNodes(void)
+{
+    misc_deregister(&g_MiscDevice);
+    misc_deregister(&g_MiscDeviceUser);
+}
+
+
+/**
+ * Initialize module.
+ *
+ * @returns appropriate status code.
+ */
+static int __init vgdrvLinuxModInit(void)
+{
+    static const char * const   s_apszGroups[] = VBOX_LOGGROUP_NAMES;
+    PRTLOGGER                   pRelLogger;
+    int                         rc;
+
+    /*
+     * Initialize IPRT first.
+     */
+    rc = RTR0Init(0);
+    if (RT_FAILURE(rc))
+    {
+        printk(KERN_ERR DEVICE_NAME ": RTR0Init failed, rc=%d.\n", rc);
+        return -EINVAL;
+    }
+
+    /*
+     * Create the release log.
+     * (We do that here instead of common code because we want to log
+     * early failures using the LogRel macro.)
+     */
+    rc = RTLogCreate(&pRelLogger, 0 /* fFlags */, "all",
+                     "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups,
+                     RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER | RTLOGDEST_USER, NULL);
+    if (RT_SUCCESS(rc))
+    {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+        RTLogGroupSettings(pRelLogger, g_szLogGrp);
+        RTLogFlags(pRelLogger, g_szLogFlags);
+        RTLogDestinations(pRelLogger, g_szLogDst);
+#endif
+        RTLogRelSetDefaultInstance(pRelLogger);
+    }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+    g_fLoggerCreated = true;
+#endif
+
+    /*
+     * Locate and initialize the PCI device.
+     */
+    rc = pci_register_driver(&g_PciDriver);
+    if (rc >= 0 && g_pPciDev)
+    {
+        /*
+         * Register the interrupt service routine for it.
+         */
+        rc = vgdrvLinuxInitISR();
+        if (rc >= 0)
+        {
+            /*
+             * Call the common device extension initializer.
+             */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && defined(RT_ARCH_X86)
+            VBOXOSTYPE enmOSType = VBOXOSTYPE_Linux26;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && defined(RT_ARCH_AMD64)
+            VBOXOSTYPE enmOSType = VBOXOSTYPE_Linux26_x64;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) && defined(RT_ARCH_X86)
+            VBOXOSTYPE enmOSType = VBOXOSTYPE_Linux24;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) && defined(RT_ARCH_AMD64)
+            VBOXOSTYPE enmOSType = VBOXOSTYPE_Linux24_x64;
+#else
+# warning "huh? which arch + version is this?"
+            VBOXOSTYPE enmOsType = VBOXOSTYPE_Linux;
+#endif
+            rc = VGDrvCommonInitDevExt(&g_DevExt,
+                                       g_IOPortBase,
+                                       g_pvMMIOBase,
+                                       g_cbMMIO,
+                                       enmOSType,
+                                       VMMDEV_EVENT_MOUSE_POSITION_CHANGED);
+            if (RT_SUCCESS(rc))
+            {
+                /*
+                 * Create the kernel session for this driver.
+                 */
+                rc = VGDrvCommonCreateKernelSession(&g_DevExt, &g_pKernelSession);
+                if (RT_SUCCESS(rc))
+                {
+                    /*
+                     * Create the kernel input device.
+                     */
+#ifdef VBOXGUEST_WITH_INPUT_DRIVER
+                    rc = vgdrvLinuxCreateInputDevice();
+                    if (rc >= 0)
+                    {
+#endif
+                        /*
+                         * Finally, create the device nodes.
+                         */
+                        rc = vgdrvLinuxInitDeviceNodes();
+                        if (rc >= 0)
+                        {
+                            /* some useful information for the user but don't show this on the console */
+                            LogRel((DEVICE_NAME ": misc device minor %d, IRQ %d, I/O port %RTiop, MMIO at %RHp (size 0x%x)\n",
+                                    g_MiscDevice.minor, g_pPciDev->irq, g_IOPortBase, g_MMIOPhysAddr, g_cbMMIO));
+                            printk(KERN_DEBUG DEVICE_NAME ": Successfully loaded version "
+                                   VBOX_VERSION_STRING " (interface " RT_XSTR(VMMDEV_VERSION) ")\n");
+                            return rc;
+                        }
+
+                        /* bail out */
+#ifdef VBOXGUEST_WITH_INPUT_DRIVER
+                        vgdrvLinuxTermInputDevice();
+                    }
+                    else
+                    {
+                        LogRel((DEVICE_NAME ": vboxguestCreateInputDevice failed with rc=%Rrc\n", rc));
+                        rc = RTErrConvertFromErrno(rc);
+                    }
+#endif
+                    VGDrvCommonCloseSession(&g_DevExt, g_pKernelSession);
+                }
+                VGDrvCommonDeleteDevExt(&g_DevExt);
+            }
+            else
+            {
+                LogRel((DEVICE_NAME ": VGDrvCommonInitDevExt failed with rc=%Rrc\n", rc));
+                rc = RTErrConvertFromErrno(rc);
+            }
+            vgdrvLinuxTermISR();
+        }
+    }
+    else
+    {
+        LogRel((DEVICE_NAME ": PCI device not found, probably running on physical hardware.\n"));
+        rc = -ENODEV;
+    }
+    pci_unregister_driver(&g_PciDriver);
+    RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
+    RTLogDestroy(RTLogSetDefaultInstance(NULL));
+    RTR0Term();
+    return rc;
+}
+
+
+/**
+ * Unload the module.
+ */
+static void __exit vgdrvLinuxModExit(void)
+{
+    /*
+     * Inverse order of init.
+     */
+    vgdrvLinuxTermDeviceNodes();
+#ifdef VBOXGUEST_WITH_INPUT_DRIVER
+    vgdrvLinuxTermInputDevice();
+#endif
+    VGDrvCommonCloseSession(&g_DevExt, g_pKernelSession);
+    VGDrvCommonDeleteDevExt(&g_DevExt);
+    vgdrvLinuxTermISR();
+    pci_unregister_driver(&g_PciDriver);
+    RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
+    RTLogDestroy(RTLogSetDefaultInstance(NULL));
+    RTR0Term();
+}
+
+
+/**
+ * Device open. Called on open /dev/vboxdrv
+ *
+ * @param   pInode      Pointer to inode info structure.
+ * @param   pFilp       Associated file pointer.
+ */
+static int vgdrvLinuxOpen(struct inode *pInode, struct file *pFilp)
+{
+    int                 rc;
+    PVBOXGUESTSESSION   pSession;
+    Log((DEVICE_NAME ": pFilp=%p pid=%d/%d %s\n", pFilp, RTProcSelf(), current->pid, current->comm));
+
+    /*
+     * Call common code to create the user session. Associate it with
+     * the file so we can access it in the other methods.
+     */
+    rc = VGDrvCommonCreateUserSession(&g_DevExt, &pSession);
+    if (RT_SUCCESS(rc))
+    {
+        pFilp->private_data = pSession;
+        if (MINOR(pInode->i_rdev) == g_MiscDeviceUser.minor)
+            pSession->fUserSession = true;
+    }
+
+    Log(("vgdrvLinuxOpen: g_DevExt=%p pSession=%p rc=%d/%d (pid=%d/%d %s)\n",
+         &g_DevExt, pSession, rc, vgdrvLinuxConvertToNegErrno(rc), RTProcSelf(), current->pid, current->comm));
+    return vgdrvLinuxConvertToNegErrno(rc);
+}
+
+
+/**
+ * Close device.
+ *
+ * @param   pInode      Pointer to inode info structure.
+ * @param   pFilp       Associated file pointer.
+ */
+static int vgdrvLinuxRelease(struct inode *pInode, struct file *pFilp)
+{
+    Log(("vgdrvLinuxRelease: pFilp=%p pSession=%p pid=%d/%d %s\n",
+         pFilp, pFilp->private_data, RTProcSelf(), current->pid, current->comm));
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
+    /* This housekeeping was needed in older kernel versions to ensure that
+     * the file pointer didn't get left on the polling queue. */
+    vgdrvLinuxFAsync(-1, pFilp, 0);
+#endif
+    VGDrvCommonCloseSession(&g_DevExt, (PVBOXGUESTSESSION)pFilp->private_data);
+    pFilp->private_data = NULL;
+    return 0;
+}
+
+
+/**
+ * Device I/O Control entry point.
+ *
+ * @param   pInode      Associated inode pointer.
+ * @param   pFilp       Associated file pointer.
+ * @param   uCmd        The function specified to ioctl().
+ * @param   ulArg       The argument specified to ioctl().
+ */
+#ifdef HAVE_UNLOCKED_IOCTL
+static long vgdrvLinuxIOCtl(struct file *pFilp, unsigned int uCmd, unsigned long ulArg)
+#else
+static int vgdrvLinuxIOCtl(struct inode *pInode, struct file *pFilp, unsigned int uCmd, unsigned long ulArg)
+#endif
+{
+    PVBOXGUESTSESSION   pSession = (PVBOXGUESTSESSION)pFilp->private_data;
+    uint32_t            cbData   = _IOC_SIZE(uCmd);
+    void               *pvBufFree;
+    void               *pvBuf;
+    int                 rc;
+    uint64_t            au64Buf[32/sizeof(uint64_t)];
+
+    Log6(("vgdrvLinuxIOCtl: pFilp=%p uCmd=%#x ulArg=%p pid=%d/%d\n", pFilp, uCmd, (void *)ulArg, RTProcSelf(), current->pid));
+
+    /*
+     * Buffer the request.
+     */
+    if (cbData <= sizeof(au64Buf))
+    {
+        pvBufFree = NULL;
+        pvBuf = &au64Buf[0];
+    }
+    else
+    {
+        pvBufFree = pvBuf = RTMemTmpAlloc(cbData);
+        if (RT_UNLIKELY(!pvBuf))
+        {
+            LogRel((DEVICE_NAME "::IOCtl: RTMemTmpAlloc failed to alloc %u bytes.\n", cbData));
+            return -ENOMEM;
+        }
+    }
+    if (RT_LIKELY(copy_from_user(pvBuf, (void *)ulArg, cbData) == 0))
+    {
+        /*
+         * Process the IOCtl.
+         */
+        size_t cbDataReturned;
+        rc = VGDrvCommonIoCtl(uCmd, &g_DevExt, pSession, pvBuf, cbData, &cbDataReturned);
+
+        /*
+         * Copy ioctl data and output buffer back to user space.
+         */
+        if (RT_SUCCESS(rc))
+        {
+            rc = 0;
+            if (RT_UNLIKELY(cbDataReturned > cbData))
+            {
+                LogRel((DEVICE_NAME "::IOCtl: too much output data %u expected %u\n", cbDataReturned, cbData));
+                cbDataReturned = cbData;
+            }
+            if (cbDataReturned > 0)
+            {
+                if (RT_UNLIKELY(copy_to_user((void *)ulArg, pvBuf, cbDataReturned) != 0))
+                {
+                    LogRel((DEVICE_NAME "::IOCtl: copy_to_user failed; pvBuf=%p ulArg=%p cbDataReturned=%u uCmd=%d\n",
+                            pvBuf, (void *)ulArg, cbDataReturned, uCmd, rc));
+                    rc = -EFAULT;
+                }
+            }
+        }
+        else
+        {
+            Log(("vgdrvLinuxIOCtl: pFilp=%p uCmd=%#x ulArg=%p failed, rc=%d\n", pFilp, uCmd, (void *)ulArg, rc));
+            rc = -rc; Assert(rc > 0); /* Positive returns == negated VBox error status codes. */
+        }
+    }
+    else
+    {
+        Log((DEVICE_NAME "::IOCtl: copy_from_user(,%#lx, %#x) failed; uCmd=%#x.\n", ulArg, cbData, uCmd));
+        rc = -EFAULT;
+    }
+    if (pvBufFree)
+        RTMemFree(pvBufFree);
+
+    Log6(("vgdrvLinuxIOCtl: returns %d (pid=%d/%d)\n", rc, RTProcSelf(), current->pid));
+    return rc;
+}
+
+
+/**
+ * Asynchronous notification activation method.
+ *
+ * @returns 0 on success, negative errno on failure.
+ *
+ * @param   fd          The file descriptor.
+ * @param   pFile       The file structure.
+ * @param   fOn         On/off indicator.
+ */
+static int vgdrvLinuxFAsync(int fd, struct file *pFile, int fOn)
+{
+    return fasync_helper(fd, pFile, fOn, &g_pFAsyncQueue);
+}
+
+
+/**
+ * Poll function.
+ *
+ * This returns ready to read if the mouse pointer mode or the pointer position
+ * has changed since last call to read.
+ *
+ * @returns 0 if no changes, POLLIN | POLLRDNORM if there are unseen changes.
+ *
+ * @param   pFile       The file structure.
+ * @param   pPt         The poll table.
+ *
+ * @remarks This is probably not really used, X11 is said to use the fasync
+ *          interface instead.
+ */
+static unsigned int vgdrvLinuxPoll(struct file *pFile, poll_table *pPt)
+{
+    PVBOXGUESTSESSION   pSession  = (PVBOXGUESTSESSION)pFile->private_data;
+    uint32_t            u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq);
+    unsigned int        fMask     = pSession->u32MousePosChangedSeq != u32CurSeq
+                                  ? POLLIN | POLLRDNORM
+                                  : 0;
+    poll_wait(pFile, &g_PollEventQueue, pPt);
+    return fMask;
+}
+
+
+/**
+ * Read to go with our poll/fasync response.
+ *
+ * @returns 1 or -EINVAL.
+ *
+ * @param   pFile       The file structure.
+ * @param   pbBuf       The buffer to read into.
+ * @param   cbRead      The max number of bytes to read.
+ * @param   poff        The current file position.
+ *
+ * @remarks This is probably not really used as X11 lets the driver do its own
+ *          event reading. The poll condition is therefore also cleared when we
+ *          see VMMDevReq_GetMouseStatus in vgdrvIoCtl_VMMRequest.
+ */
+static ssize_t vgdrvLinuxRead(struct file *pFile, char *pbBuf, size_t cbRead, loff_t *poff)
+{
+    PVBOXGUESTSESSION   pSession  = (PVBOXGUESTSESSION)pFile->private_data;
+    uint32_t            u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq);
+
+    if (*poff != 0)
+        return -EINVAL;
+
+    /*
+     * Fake a single byte read if we're not up to date with the current mouse position.
+     */
+    if (    pSession->u32MousePosChangedSeq != u32CurSeq
+        &&  cbRead > 0)
+    {
+        pSession->u32MousePosChangedSeq = u32CurSeq;
+        pbBuf[0] = 0;
+        return 1;
+    }
+    return 0;
+}
+
+
+void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
+{
+#ifdef VBOXGUEST_WITH_INPUT_DRIVER
+    int rc;
+#endif
+    NOREF(pDevExt);
+
+    /*
+     * Wake up everyone that's in a poll() and post anyone that has
+     * subscribed to async notifications.
+     */
+    Log3(("VGDrvNativeISRMousePollEvent: wake_up_all\n"));
+    wake_up_all(&g_PollEventQueue);
+    Log3(("VGDrvNativeISRMousePollEvent: kill_fasync\n"));
+    kill_fasync(&g_pFAsyncQueue, SIGIO, POLL_IN);
+#ifdef VBOXGUEST_WITH_INPUT_DRIVER
+    /* Report events to the kernel input device */
+    g_pMouseStatusReq->mouseFeatures = 0;
+    g_pMouseStatusReq->pointerXPos = 0;
+    g_pMouseStatusReq->pointerYPos = 0;
+    rc = VbglGRPerform(&g_pMouseStatusReq->header);
+    if (RT_SUCCESS(rc))
+    {
+        input_report_abs(g_pInputDevice, ABS_X,
+                         g_pMouseStatusReq->pointerXPos);
+        input_report_abs(g_pInputDevice, ABS_Y,
+                         g_pMouseStatusReq->pointerYPos);
+# ifdef EV_SYN
+        input_sync(g_pInputDevice);
+# endif
+    }
+#endif
+    Log3(("VGDrvNativeISRMousePollEvent: done\n"));
+}
+
+
+/* Common code that depend on g_DevExt. */
+#include "VBoxGuestIDC-unix.c.h"
+
+EXPORT_SYMBOL(VBoxGuestIDCOpen);
+EXPORT_SYMBOL(VBoxGuestIDCClose);
+EXPORT_SYMBOL(VBoxGuestIDCCall);
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+
+/** log and dbg_log parameter setter. */
+static int vgdrvLinuxParamLogGrpSet(const char *pszValue, struct kernel_param *pParam)
+{
+    if (g_fLoggerCreated)
+    {
+        PRTLOGGER pLogger = pParam->name[0] == 'd' ? RTLogDefaultInstance() : RTLogRelGetDefaultInstance();
+        if (pLogger)
+            RTLogGroupSettings(pLogger, pszValue);
+    }
+    else if (pParam->name[0] != 'd')
+        strlcpy(&g_szLogGrp[0], pszValue, sizeof(g_szLogGrp));
+
+    return 0;
+}
+
+/** log and dbg_log parameter getter. */
+static int vgdrvLinuxParamLogGrpGet(char *pszBuf, struct kernel_param *pParam)
+{
+    PRTLOGGER pLogger = pParam->name[0] == 'd' ? RTLogDefaultInstance() : RTLogRelGetDefaultInstance();
+    *pszBuf = '\0';
+    if (pLogger)
+        RTLogGetGroupSettings(pLogger, pszBuf, _4K);
+    return strlen(pszBuf);
+}
+
+
+/** log and dbg_log_flags parameter setter. */
+static int vgdrvLinuxParamLogFlagsSet(const char *pszValue, struct kernel_param *pParam)
+{
+    if (g_fLoggerCreated)
+    {
+        PRTLOGGER pLogger = pParam->name[0] == 'd' ? RTLogDefaultInstance() : RTLogRelGetDefaultInstance();
+        if (pLogger)
+            RTLogFlags(pLogger, pszValue);
+    }
+    else if (pParam->name[0] != 'd')
+        strlcpy(&g_szLogFlags[0], pszValue, sizeof(g_szLogFlags));
+    return 0;
+}
+
+/** log and dbg_log_flags parameter getter. */
+static int vgdrvLinuxParamLogFlagsGet(char *pszBuf, struct kernel_param *pParam)
+{
+    PRTLOGGER pLogger = pParam->name[0] == 'd' ? RTLogDefaultInstance() : RTLogRelGetDefaultInstance();
+    *pszBuf = '\0';
+    if (pLogger)
+        RTLogGetFlags(pLogger, pszBuf, _4K);
+    return strlen(pszBuf);
+}
+
+
+/** log and dbg_log_dest parameter setter. */
+static int vgdrvLinuxParamLogDstSet(const char *pszValue, struct kernel_param *pParam)
+{
+    if (g_fLoggerCreated)
+    {
+        PRTLOGGER pLogger = pParam->name[0] == 'd' ? RTLogDefaultInstance() : RTLogRelGetDefaultInstance();
+        if (pLogger)
+            RTLogDestinations(pLogger, pszValue);
+    }
+    else if (pParam->name[0] != 'd')
+        strlcpy(&g_szLogDst[0], pszValue, sizeof(g_szLogDst));
+    return 0;
+}
+
+/** log and dbg_log_dest parameter getter. */
+static int vgdrvLinuxParamLogDstGet(char *pszBuf, struct kernel_param *pParam)
+{
+    PRTLOGGER pLogger = pParam->name[0] == 'd' ? RTLogDefaultInstance() : RTLogRelGetDefaultInstance();
+    *pszBuf = '\0';
+    if (pLogger)
+        RTLogGetDestinations(pLogger, pszBuf, _4K);
+    return strlen(pszBuf);
+}
+
+
+/** r3_log_to_host parameter setter. */
+static int vgdrvLinuxParamR3LogToHostSet(const char *pszValue, struct kernel_param *pParam)
+{
+    if (    pszValue == NULL
+        || *pszValue == '\0'
+        || *pszValue == 'n'
+        || *pszValue == 'N'
+        || *pszValue == 'd'
+        || *pszValue == 'D'
+        || (   (*pszValue == 'o' || *pszValue == 'O')
+            && (*pszValue == 'f' || *pszValue == 'F') )
+       )
+        g_DevExt.fLoggingEnabled = false;
+    else
+        g_DevExt.fLoggingEnabled = true;
+    return 0;
+}
+
+/** r3_log_to_host parameter getter. */
+static int vgdrvLinuxParamR3LogToHostGet(char *pszBuf, struct kernel_param *pParam)
+{
+    strcpy(pszBuf, g_DevExt.fLoggingEnabled ? "enabled" : "disabled");
+    return strlen(pszBuf);
+}
+
+
+/*
+ * Define module parameters.
+ */
+module_param_call(log,            vgdrvLinuxParamLogGrpSet,   vgdrvLinuxParamLogGrpGet,   NULL, 0664);
+module_param_call(log_flags,      vgdrvLinuxParamLogFlagsSet, vgdrvLinuxParamLogFlagsGet, NULL, 0664);
+module_param_call(log_dest,       vgdrvLinuxParamLogDstSet,   vgdrvLinuxParamLogDstGet,   NULL, 0664);
+# ifdef LOG_ENABLED
+module_param_call(dbg_log,        vgdrvLinuxParamLogGrpSet,   vgdrvLinuxParamLogGrpGet,   NULL, 0664);
+module_param_call(dbg_log_flags,  vgdrvLinuxParamLogFlagsSet, vgdrvLinuxParamLogFlagsGet, NULL, 0664);
+module_param_call(dbg_log_dest,   vgdrvLinuxParamLogDstSet,   vgdrvLinuxParamLogDstGet,   NULL, 0664);
+# endif
+module_param_call(r3_log_to_host, vgdrvLinuxParamR3LogToHostSet, vgdrvLinuxParamR3LogToHostGet, NULL, 0664);
+
+#endif /* 2.6.0 and later */
+
+
+module_init(vgdrvLinuxModInit);
+module_exit(vgdrvLinuxModExit);
+
+MODULE_AUTHOR(VBOX_VENDOR);
+MODULE_DESCRIPTION(VBOX_PRODUCT " Guest Additions for Linux Module");
+MODULE_LICENSE("GPL");
+#ifdef MODULE_VERSION
+MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
+#endif
+
diff --git a/ubuntu/vbox/vboxguest/VBoxGuest.c b/ubuntu/vbox/vboxguest/VBoxGuest.c
new file mode 100644 (file)
index 0000000..3166730
--- /dev/null
@@ -0,0 +1,3791 @@
+/* $Id: VBoxGuest.cpp $ */
+/** @file
+ * VBoxGuest - Guest Additions Driver, Common Code.
+ */
+
+/*
+ * Copyright (C) 2007-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.
+ */
+
+/** @page pg_vbdrv VBoxGuest
+ *
+ * VBoxGuest is the device driver for VMMDev.
+ *
+ * The device driver is shipped as part of the guest additions.  It has roots in
+ * the host VMM support driver (usually known as VBoxDrv), so fixes in platform
+ * specific code may apply to both drivers.
+ *
+ * The common code lives in VBoxGuest.cpp and is compiled both as C++ and C.
+ * The VBoxGuest.cpp source file shall not contain platform specific code,
+ * though it must occationally do a few \#ifdef RT_OS_XXX tests to cater for
+ * platform differences.  Though, in those cases, it is common that more than
+ * one platform needs special handling.
+ *
+ * On most platforms the device driver should create two device nodes, one for
+ * full (unrestricted) access to the feature set, and one which only provides a
+ * restrict set of functions.  These are generally referred to as 'vboxguest'
+ * and 'vboxuser' respectively.  Currently, this two device approach is only
+ * implemented on Linux!
+ *
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP   LOG_GROUP_DEFAULT
+#include "VBoxGuestInternal.h"
+#include <VBox/VMMDev.h> /* for VMMDEV_RAM_SIZE */
+#include <VBox/log.h>
+#include <iprt/mem.h>
+#include <iprt/time.h>
+#include <iprt/memobj.h>
+#include <iprt/asm.h>
+#include <iprt/asm-amd64-x86.h>
+#include <iprt/string.h>
+#include <iprt/process.h>
+#include <iprt/assert.h>
+#include <iprt/param.h>
+#include <iprt/timer.h>
+#ifdef VBOX_WITH_HGCM
+# include <iprt/thread.h>
+#endif
+#include "version-generated.h"
+#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
+# include "revision-generated.h"
+#endif
+#ifdef RT_OS_WINDOWS
+# ifndef CTL_CODE
+#  include <iprt/win/windows.h>
+# endif
+#endif
+#if defined(RT_OS_SOLARIS) || defined(RT_OS_DARWIN)
+# include <iprt/rand.h>
+#endif
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+#define VBOXGUEST_ACQUIRE_STYLE_EVENTS (VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST | VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST)
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+#ifdef VBOX_WITH_HGCM
+static DECLCALLBACK(int) vgdrvHgcmAsyncWaitCallback(VMMDevHGCMRequestHeader *pHdrNonVolatile, void *pvUser, uint32_t u32User);
+#endif
+static int      vgdrvIoCtl_CancelAllWaitEvents(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession);
+static void     vgdrvBitUsageTrackerClear(PVBOXGUESTBITUSAGETRACER pTracker);
+static uint32_t vgdrvGetAllowedEventMaskForSession(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession);
+static int      vgdrvResetEventFilterOnHost(PVBOXGUESTDEVEXT pDevExt, uint32_t fFixedEvents);
+static int      vgdrvResetMouseStatusOnHost(PVBOXGUESTDEVEXT pDevExt);
+static int      vgdrvResetCapabilitiesOnHost(PVBOXGUESTDEVEXT pDevExt);
+static int      vgdrvSetSessionEventFilter(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                                           uint32_t fOrMask, uint32_t fNotMask, bool fSessionTermination);
+static int      vgdrvSetSessionMouseStatus(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                                           uint32_t fOrMask, uint32_t fNotMask, bool fSessionTermination);
+static int      vgdrvSetSessionCapabilities(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                                            uint32_t fOrMask, uint32_t fNoMask, bool fSessionTermination);
+static int      vgdrvAcquireSessionCapabilities(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fOrMask,
+                                                uint32_t fNotMask, VBOXGUESTCAPSACQUIRE_FLAGS enmFlags, bool fSessionTermination);
+static int      vgdrvDispatchEventsLocked(PVBOXGUESTDEVEXT pDevExt, uint32_t fEvents);
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+static const uint32_t g_cbChangeMemBalloonReq = RT_OFFSETOF(VMMDevChangeMemBalloon, aPhysPage[VMMDEV_MEMORY_BALLOON_CHUNK_PAGES]);
+
+#if defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)
+/**
+ * Drag in the rest of IRPT since we share it with the
+ * rest of the kernel modules on Solaris.
+ */
+PFNRT g_apfnVBoxGuestIPRTDeps[] =
+{
+    /* VirtioNet */
+    (PFNRT)RTRandBytes,
+    /* RTSemMutex* */
+    (PFNRT)RTSemMutexCreate,
+    (PFNRT)RTSemMutexDestroy,
+    (PFNRT)RTSemMutexRequest,
+    (PFNRT)RTSemMutexRequestNoResume,
+    (PFNRT)RTSemMutexRequestDebug,
+    (PFNRT)RTSemMutexRequestNoResumeDebug,
+    (PFNRT)RTSemMutexRelease,
+    (PFNRT)RTSemMutexIsOwned,
+    NULL
+};
+#endif  /* RT_OS_DARWIN || RT_OS_SOLARIS  */
+
+
+/**
+ * Reserves memory in which the VMM can relocate any guest mappings
+ * that are floating around.
+ *
+ * This operation is a little bit tricky since the VMM might not accept
+ * just any address because of address clashes between the three contexts
+ * it operates in, so use a small stack to perform this operation.
+ *
+ * @returns VBox status code (ignored).
+ * @param   pDevExt     The device extension.
+ */
+static int vgdrvInitFixateGuestMappings(PVBOXGUESTDEVEXT pDevExt)
+{
+    /*
+     * Query the required space.
+     */
+    VMMDevReqHypervisorInfo *pReq;
+    int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(VMMDevReqHypervisorInfo), VMMDevReq_GetHypervisorInfo);
+    if (RT_FAILURE(rc))
+        return rc;
+    pReq->hypervisorStart = 0;
+    pReq->hypervisorSize  = 0;
+    rc = VbglGRPerform(&pReq->header);
+    if (RT_FAILURE(rc)) /* this shouldn't happen! */
+    {
+        VbglGRFree(&pReq->header);
+        return rc;
+    }
+
+    /*
+     * The VMM will report back if there is nothing it wants to map, like for
+     * instance in VT-x and AMD-V mode.
+     */
+    if (pReq->hypervisorSize == 0)
+        Log(("vgdrvInitFixateGuestMappings: nothing to do\n"));
+    else
+    {
+        /*
+         * We have to try several times since the host can be picky
+         * about certain addresses.
+         */
+        RTR0MEMOBJ  hFictive     = NIL_RTR0MEMOBJ;
+        uint32_t    cbHypervisor = pReq->hypervisorSize;
+        RTR0MEMOBJ  ahTries[5];
+        uint32_t    iTry;
+        bool        fBitched = false;
+        Log(("vgdrvInitFixateGuestMappings: cbHypervisor=%#x\n", cbHypervisor));
+        for (iTry = 0; iTry < RT_ELEMENTS(ahTries); iTry++)
+        {
+            /*
+             * Reserve space, or if that isn't supported, create a object for
+             * some fictive physical memory and map that in to kernel space.
+             *
+             * To make the code a bit uglier, most systems cannot help with
+             * 4MB alignment, so we have to deal with that in addition to
+             * having two ways of getting the memory.
+             */
+            uint32_t    uAlignment = _4M;
+            RTR0MEMOBJ  hObj;
+            rc = RTR0MemObjReserveKernel(&hObj, (void *)-1, RT_ALIGN_32(cbHypervisor, _4M), uAlignment);
+            if (rc == VERR_NOT_SUPPORTED)
+            {
+                uAlignment = PAGE_SIZE;
+                rc = RTR0MemObjReserveKernel(&hObj, (void *)-1, RT_ALIGN_32(cbHypervisor, _4M) + _4M, uAlignment);
+            }
+            /*
+             * If both RTR0MemObjReserveKernel calls above failed because either not supported or
+             * not implemented at all at the current platform, try to map the memory object into the
+             * virtual kernel space.
+             */
+            if (rc == VERR_NOT_SUPPORTED)
+            {
+                if (hFictive == NIL_RTR0MEMOBJ)
+                {
+                    rc = RTR0MemObjEnterPhys(&hObj, VBOXGUEST_HYPERVISOR_PHYSICAL_START, cbHypervisor + _4M, RTMEM_CACHE_POLICY_DONT_CARE);
+                    if (RT_FAILURE(rc))
+                        break;
+                    hFictive = hObj;
+                }
+                uAlignment = _4M;
+                rc = RTR0MemObjMapKernel(&hObj, hFictive, (void *)-1, uAlignment, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
+                if (rc == VERR_NOT_SUPPORTED)
+                {
+                    uAlignment = PAGE_SIZE;
+                    rc = RTR0MemObjMapKernel(&hObj, hFictive, (void *)-1, uAlignment, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
+                }
+            }
+            if (RT_FAILURE(rc))
+            {
+                LogRel(("VBoxGuest: Failed to reserve memory for the hypervisor: rc=%Rrc (cbHypervisor=%#x uAlignment=%#x iTry=%u)\n",
+                        rc, cbHypervisor, uAlignment, iTry));
+                fBitched = true;
+                break;
+            }
+
+            /*
+             * Try set it.
+             */
+            pReq->header.requestType = VMMDevReq_SetHypervisorInfo;
+            pReq->header.rc          = VERR_INTERNAL_ERROR;
+            pReq->hypervisorSize     = cbHypervisor;
+            pReq->hypervisorStart    = (RTGCPTR32)(uintptr_t)RTR0MemObjAddress(hObj);
+            if (    uAlignment == PAGE_SIZE
+                &&  pReq->hypervisorStart & (_4M - 1))
+                pReq->hypervisorStart = RT_ALIGN_32(pReq->hypervisorStart, _4M);
+            AssertMsg(RT_ALIGN_32(pReq->hypervisorStart, _4M) == pReq->hypervisorStart, ("%#x\n", pReq->hypervisorStart));
+
+            rc = VbglGRPerform(&pReq->header);
+            if (RT_SUCCESS(rc))
+            {
+                pDevExt->hGuestMappings = hFictive != NIL_RTR0MEMOBJ ? hFictive : hObj;
+                Log(("VBoxGuest: %p LB %#x; uAlignment=%#x iTry=%u hGuestMappings=%p (%s)\n",
+                     RTR0MemObjAddress(pDevExt->hGuestMappings),
+                     RTR0MemObjSize(pDevExt->hGuestMappings),
+                     uAlignment, iTry, pDevExt->hGuestMappings, hFictive != NIL_RTR0PTR ? "fictive" : "reservation"));
+                break;
+            }
+            ahTries[iTry] = hObj;
+        }
+
+        /*
+         * Cleanup failed attempts.
+         */
+        while (iTry-- > 0)
+            RTR0MemObjFree(ahTries[iTry], false /* fFreeMappings */);
+        if (    RT_FAILURE(rc)
+            &&  hFictive != NIL_RTR0PTR)
+            RTR0MemObjFree(hFictive, false /* fFreeMappings */);
+        if (RT_FAILURE(rc) && !fBitched)
+            LogRel(("VBoxGuest: Warning: failed to reserve %#d of memory for guest mappings.\n", cbHypervisor));
+    }
+    VbglGRFree(&pReq->header);
+
+    /*
+     * We ignore failed attempts for now.
+     */
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Undo what vgdrvInitFixateGuestMappings did.
+ *
+ * @param   pDevExt     The device extension.
+ */
+static void vgdrvTermUnfixGuestMappings(PVBOXGUESTDEVEXT pDevExt)
+{
+    if (pDevExt->hGuestMappings != NIL_RTR0PTR)
+    {
+        /*
+         * Tell the host that we're going to free the memory we reserved for
+         * it, the free it up. (Leak the memory if anything goes wrong here.)
+         */
+        VMMDevReqHypervisorInfo *pReq;
+        int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(VMMDevReqHypervisorInfo), VMMDevReq_SetHypervisorInfo);
+        if (RT_SUCCESS(rc))
+        {
+            pReq->hypervisorStart = 0;
+            pReq->hypervisorSize  = 0;
+            rc = VbglGRPerform(&pReq->header);
+            VbglGRFree(&pReq->header);
+        }
+        if (RT_SUCCESS(rc))
+        {
+            rc = RTR0MemObjFree(pDevExt->hGuestMappings, true /* fFreeMappings */);
+            AssertRC(rc);
+        }
+        else
+            LogRel(("vgdrvTermUnfixGuestMappings: Failed to unfix the guest mappings! rc=%Rrc\n", rc));
+
+        pDevExt->hGuestMappings = NIL_RTR0MEMOBJ;
+    }
+}
+
+
+
+/**
+ * Report the guest information to the host.
+ *
+ * @returns IPRT status code.
+ * @param   enmOSType       The OS type to report.
+ */
+static int vgdrvReportGuestInfo(VBOXOSTYPE enmOSType)
+{
+    /*
+     * Allocate and fill in the two guest info reports.
+     */
+    VMMDevReportGuestInfo2 *pReqInfo2 = NULL;
+    VMMDevReportGuestInfo  *pReqInfo1 = NULL;
+    int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReqInfo2, sizeof (VMMDevReportGuestInfo2), VMMDevReq_ReportGuestInfo2);
+    Log(("vgdrvReportGuestInfo: VbglGRAlloc VMMDevReportGuestInfo2 completed with rc=%Rrc\n", rc));
+    if (RT_SUCCESS(rc))
+    {
+        pReqInfo2->guestInfo.additionsMajor    = VBOX_VERSION_MAJOR;
+        pReqInfo2->guestInfo.additionsMinor    = VBOX_VERSION_MINOR;
+        pReqInfo2->guestInfo.additionsBuild    = VBOX_VERSION_BUILD;
+        pReqInfo2->guestInfo.additionsRevision = VBOX_SVN_REV;
+        pReqInfo2->guestInfo.additionsFeatures = 0; /* (no features defined yet) */
+        RTStrCopy(pReqInfo2->guestInfo.szName, sizeof(pReqInfo2->guestInfo.szName), VBOX_VERSION_STRING);
+
+        rc = VbglGRAlloc((VMMDevRequestHeader **)&pReqInfo1, sizeof (VMMDevReportGuestInfo), VMMDevReq_ReportGuestInfo);
+        Log(("vgdrvReportGuestInfo: VbglGRAlloc VMMDevReportGuestInfo completed with rc=%Rrc\n", rc));
+        if (RT_SUCCESS(rc))
+        {
+            pReqInfo1->guestInfo.interfaceVersion = VMMDEV_VERSION;
+            pReqInfo1->guestInfo.osType           = enmOSType;
+
+            /*
+             * There are two protocols here:
+             *      1. Info2 + Info1. Supported by >=3.2.51.
+             *      2. Info1 and optionally Info2. The old protocol.
+             *
+             * We try protocol 1 first.  It will fail with VERR_NOT_SUPPORTED
+             * if not supported by the VMMDev (message ordering requirement).
+             */
+            rc = VbglGRPerform(&pReqInfo2->header);
+            Log(("vgdrvReportGuestInfo: VbglGRPerform VMMDevReportGuestInfo2 completed with rc=%Rrc\n", rc));
+            if (RT_SUCCESS(rc))
+            {
+                rc = VbglGRPerform(&pReqInfo1->header);
+                Log(("vgdrvReportGuestInfo: VbglGRPerform VMMDevReportGuestInfo completed with rc=%Rrc\n", rc));
+            }
+            else if (   rc == VERR_NOT_SUPPORTED
+                     || rc == VERR_NOT_IMPLEMENTED)
+            {
+                rc = VbglGRPerform(&pReqInfo1->header);
+                Log(("vgdrvReportGuestInfo: VbglGRPerform VMMDevReportGuestInfo completed with rc=%Rrc\n", rc));
+                if (RT_SUCCESS(rc))
+                {
+                    rc = VbglGRPerform(&pReqInfo2->header);
+                    Log(("vgdrvReportGuestInfo: VbglGRPerform VMMDevReportGuestInfo2 completed with rc=%Rrc\n", rc));
+                    if (rc == VERR_NOT_IMPLEMENTED)
+                        rc = VINF_SUCCESS;
+                }
+            }
+            VbglGRFree(&pReqInfo1->header);
+        }
+        VbglGRFree(&pReqInfo2->header);
+    }
+
+    return rc;
+}
+
+
+/**
+ * Report the guest driver status to the host.
+ *
+ * @returns IPRT status code.
+ * @param   fActive         Flag whether the driver is now active or not.
+ */
+static int vgdrvReportDriverStatus(bool fActive)
+{
+    /*
+     * Report guest status of the VBox driver to the host.
+     */
+    VMMDevReportGuestStatus *pReq2 = NULL;
+    int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq2, sizeof(*pReq2), VMMDevReq_ReportGuestStatus);
+    Log(("vgdrvReportDriverStatus: VbglGRAlloc VMMDevReportGuestStatus completed with rc=%Rrc\n", rc));
+    if (RT_SUCCESS(rc))
+    {
+        pReq2->guestStatus.facility = VBoxGuestFacilityType_VBoxGuestDriver;
+        pReq2->guestStatus.status = fActive ?
+                                    VBoxGuestFacilityStatus_Active
+                                  : VBoxGuestFacilityStatus_Inactive;
+        pReq2->guestStatus.flags = 0;
+        rc = VbglGRPerform(&pReq2->header);
+        Log(("vgdrvReportDriverStatus: VbglGRPerform VMMDevReportGuestStatus completed with fActive=%d, rc=%Rrc\n",
+             fActive ? 1 : 0, rc));
+        if (rc == VERR_NOT_IMPLEMENTED) /* Compatibility with older hosts. */
+            rc = VINF_SUCCESS;
+        VbglGRFree(&pReq2->header);
+    }
+
+    return rc;
+}
+
+
+/** @name Memory Ballooning
+ * @{
+ */
+
+/**
+ * Inflate the balloon by one chunk represented by an R0 memory object.
+ *
+ * The caller owns the balloon mutex.
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj     Pointer to the R0 memory object.
+ * @param   pReq        The pre-allocated request for performing the VMMDev call.
+ */
+static int vgdrvBalloonInflate(PRTR0MEMOBJ pMemObj, VMMDevChangeMemBalloon *pReq)
+{
+    uint32_t iPage;
+    int rc;
+
+    for (iPage = 0; iPage < VMMDEV_MEMORY_BALLOON_CHUNK_PAGES; iPage++)
+    {
+        RTHCPHYS phys = RTR0MemObjGetPagePhysAddr(*pMemObj, iPage);
+        pReq->aPhysPage[iPage] = phys;
+    }
+
+    pReq->fInflate = true;
+    pReq->header.size = g_cbChangeMemBalloonReq;
+    pReq->cPages = VMMDEV_MEMORY_BALLOON_CHUNK_PAGES;
+
+    rc = VbglGRPerform(&pReq->header);
+    if (RT_FAILURE(rc))
+        LogRel(("vgdrvBalloonInflate: VbglGRPerform failed. rc=%Rrc\n", rc));
+    return rc;
+}
+
+
+/**
+ * Deflate the balloon by one chunk - info the host and free the memory object.
+ *
+ * The caller owns the balloon mutex.
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj     Pointer to the R0 memory object.
+ *                      The memory object will be freed afterwards.
+ * @param   pReq        The pre-allocated request for performing the VMMDev call.
+ */
+static int vgdrvBalloonDeflate(PRTR0MEMOBJ pMemObj, VMMDevChangeMemBalloon *pReq)
+{
+    uint32_t iPage;
+    int rc;
+
+    for (iPage = 0; iPage < VMMDEV_MEMORY_BALLOON_CHUNK_PAGES; iPage++)
+    {
+        RTHCPHYS phys = RTR0MemObjGetPagePhysAddr(*pMemObj, iPage);
+        pReq->aPhysPage[iPage] = phys;
+    }
+
+    pReq->fInflate = false;
+    pReq->header.size = g_cbChangeMemBalloonReq;
+    pReq->cPages = VMMDEV_MEMORY_BALLOON_CHUNK_PAGES;
+
+    rc = VbglGRPerform(&pReq->header);
+    if (RT_FAILURE(rc))
+    {
+        LogRel(("vgdrvBalloonDeflate: VbglGRPerform failed. rc=%Rrc\n", rc));
+        return rc;
+    }
+
+    rc = RTR0MemObjFree(*pMemObj, true);
+    if (RT_FAILURE(rc))
+    {
+        LogRel(("vgdrvBalloonDeflate: RTR0MemObjFree(%p,true) -> %Rrc; this is *BAD*!\n", *pMemObj, rc));
+        return rc;
+    }
+
+    *pMemObj = NIL_RTR0MEMOBJ;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Inflate/deflate the memory balloon and notify the host.
+ *
+ * This is a worker used by vgdrvIoCtl_CheckMemoryBalloon - it takes the mutex.
+ *
+ * @returns VBox status code.
+ * @param   pDevExt         The device extension.
+ * @param   cBalloonChunks  The new size of the balloon in chunks of 1MB.
+ * @param   pfHandleInR3    Where to return the handle-in-ring3 indicator
+ *                          (VINF_SUCCESS if set).
+ */
+static int vgdrvSetBalloonSizeKernel(PVBOXGUESTDEVEXT pDevExt, uint32_t cBalloonChunks, uint32_t *pfHandleInR3)
+{
+    int rc = VINF_SUCCESS;
+
+    if (pDevExt->MemBalloon.fUseKernelAPI)
+    {
+        VMMDevChangeMemBalloon *pReq;
+        uint32_t i;
+
+        if (cBalloonChunks > pDevExt->MemBalloon.cMaxChunks)
+        {
+            LogRel(("vgdrvSetBalloonSizeKernel: illegal balloon size %u (max=%u)\n",
+                    cBalloonChunks, pDevExt->MemBalloon.cMaxChunks));
+            return VERR_INVALID_PARAMETER;
+        }
+
+        if (cBalloonChunks == pDevExt->MemBalloon.cMaxChunks)
+            return VINF_SUCCESS;   /* nothing to do */
+
+        if (   cBalloonChunks > pDevExt->MemBalloon.cChunks
+            && !pDevExt->MemBalloon.paMemObj)
+        {
+            pDevExt->MemBalloon.paMemObj = (PRTR0MEMOBJ)RTMemAllocZ(sizeof(RTR0MEMOBJ) * pDevExt->MemBalloon.cMaxChunks);
+            if (!pDevExt->MemBalloon.paMemObj)
+            {
+                LogRel(("vgdrvSetBalloonSizeKernel: no memory for paMemObj!\n"));
+                return VERR_NO_MEMORY;
+            }
+        }
+
+        rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, g_cbChangeMemBalloonReq, VMMDevReq_ChangeMemBalloon);
+        if (RT_FAILURE(rc))
+            return rc;
+
+        if (cBalloonChunks > pDevExt->MemBalloon.cChunks)
+        {
+            /* inflate */
+            for (i = pDevExt->MemBalloon.cChunks; i < cBalloonChunks; i++)
+            {
+                rc = RTR0MemObjAllocPhysNC(&pDevExt->MemBalloon.paMemObj[i],
+                                           VMMDEV_MEMORY_BALLOON_CHUNK_SIZE, NIL_RTHCPHYS);
+                if (RT_FAILURE(rc))
+                {
+                    if (rc == VERR_NOT_SUPPORTED)
+                    {
+                        /* not supported -- fall back to the R3-allocated memory. */
+                        rc = VINF_SUCCESS;
+                        pDevExt->MemBalloon.fUseKernelAPI = false;
+                        Assert(pDevExt->MemBalloon.cChunks == 0);
+                        Log(("VBoxGuestSetBalloonSizeKernel: PhysNC allocs not supported, falling back to R3 allocs.\n"));
+                    }
+                    /* else if (rc == VERR_NO_MEMORY || rc == VERR_NO_PHYS_MEMORY):
+                     *      cannot allocate more memory => don't try further, just stop here */
+                    /* else: XXX what else can fail?  VERR_MEMOBJ_INIT_FAILED for instance. just stop. */
+                    break;
+                }
+
+                rc = vgdrvBalloonInflate(&pDevExt->MemBalloon.paMemObj[i], pReq);
+                if (RT_FAILURE(rc))
+                {
+                    Log(("vboxGuestSetBalloonSize(inflate): failed, rc=%Rrc!\n", rc));
+                    RTR0MemObjFree(pDevExt->MemBalloon.paMemObj[i], true);
+                    pDevExt->MemBalloon.paMemObj[i] = NIL_RTR0MEMOBJ;
+                    break;
+                }
+                pDevExt->MemBalloon.cChunks++;
+            }
+        }
+        else
+        {
+            /* deflate */
+            for (i = pDevExt->MemBalloon.cChunks; i-- > cBalloonChunks;)
+            {
+                rc = vgdrvBalloonDeflate(&pDevExt->MemBalloon.paMemObj[i], pReq);
+                if (RT_FAILURE(rc))
+                {
+                    Log(("vboxGuestSetBalloonSize(deflate): failed, rc=%Rrc!\n", rc));
+                    break;
+                }
+                pDevExt->MemBalloon.cChunks--;
+            }
+        }
+
+        VbglGRFree(&pReq->header);
+    }
+
+    /*
+     * Set the handle-in-ring3 indicator.  When set Ring-3 will have to work
+     * the balloon changes via the other API.
+     */
+    *pfHandleInR3 = pDevExt->MemBalloon.fUseKernelAPI ? false : true;
+
+    return rc;
+}
+
+
+/**
+ * Inflate/deflate the balloon by one chunk.
+ *
+ * Worker for vgdrvIoCtl_ChangeMemoryBalloon - it takes the mutex.
+ *
+ * @returns VBox status code.
+ * @param   pDevExt         The device extension.
+ * @param   pSession        The session.
+ * @param   u64ChunkAddr    The address of the chunk to add to / remove from the
+ *                          balloon.
+ * @param   fInflate        Inflate if true, deflate if false.
+ */
+static int vgdrvSetBalloonSizeFromUser(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint64_t u64ChunkAddr, bool fInflate)
+{
+    VMMDevChangeMemBalloon *pReq;
+    PRTR0MEMOBJ pMemObj = NULL;
+    int rc = VINF_SUCCESS;
+    uint32_t i;
+    RT_NOREF1(pSession);
+
+    if (fInflate)
+    {
+        if (   pDevExt->MemBalloon.cChunks > pDevExt->MemBalloon.cMaxChunks - 1
+            || pDevExt->MemBalloon.cMaxChunks == 0 /* If called without first querying. */)
+        {
+            LogRel(("vboxGuestSetBalloonSize: cannot inflate balloon, already have %u chunks (max=%u)\n",
+                    pDevExt->MemBalloon.cChunks, pDevExt->MemBalloon.cMaxChunks));
+            return VERR_INVALID_PARAMETER;
+        }
+
+        if (!pDevExt->MemBalloon.paMemObj)
+        {
+            pDevExt->MemBalloon.paMemObj = (PRTR0MEMOBJ)RTMemAlloc(sizeof(RTR0MEMOBJ) * pDevExt->MemBalloon.cMaxChunks);
+            if (!pDevExt->MemBalloon.paMemObj)
+            {
+                LogRel(("VBoxGuestSetBalloonSizeFromUser: no memory for paMemObj!\n"));
+                return VERR_NO_MEMORY;
+            }
+            for (i = 0; i < pDevExt->MemBalloon.cMaxChunks; i++)
+                pDevExt->MemBalloon.paMemObj[i] = NIL_RTR0MEMOBJ;
+        }
+    }
+    else
+    {
+        if (pDevExt->MemBalloon.cChunks == 0)
+        {
+            AssertMsgFailed(("vboxGuestSetBalloonSize: cannot decrease balloon, already at size 0\n"));
+            return VERR_INVALID_PARAMETER;
+        }
+    }
+
+    /*
+     * Enumerate all memory objects and check if the object is already registered.
+     */
+    for (i = 0; i < pDevExt->MemBalloon.cMaxChunks; i++)
+    {
+        if (   fInflate
+            && !pMemObj
+            && pDevExt->MemBalloon.paMemObj[i] == NIL_RTR0MEMOBJ)
+            pMemObj = &pDevExt->MemBalloon.paMemObj[i]; /* found free object pointer */
+        if (RTR0MemObjAddressR3(pDevExt->MemBalloon.paMemObj[i]) == u64ChunkAddr)
+        {
+            if (fInflate)
+                return VERR_ALREADY_EXISTS; /* don't provide the same memory twice */
+            pMemObj = &pDevExt->MemBalloon.paMemObj[i];
+            break;
+        }
+    }
+    if (!pMemObj)
+    {
+        if (fInflate)
+        {
+            /* no free object pointer found -- should not happen */
+            return VERR_NO_MEMORY;
+        }
+
+        /* cannot free this memory as it wasn't provided before */
+        return VERR_NOT_FOUND;
+    }
+
+    /*
+     * Try inflate / default the balloon as requested.
+     */
+    rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, g_cbChangeMemBalloonReq, VMMDevReq_ChangeMemBalloon);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    if (fInflate)
+    {
+        rc = RTR0MemObjLockUser(pMemObj, (RTR3PTR)u64ChunkAddr, VMMDEV_MEMORY_BALLOON_CHUNK_SIZE,
+                                RTMEM_PROT_READ | RTMEM_PROT_WRITE, NIL_RTR0PROCESS);
+        if (RT_SUCCESS(rc))
+        {
+            rc = vgdrvBalloonInflate(pMemObj, pReq);
+            if (RT_SUCCESS(rc))
+                pDevExt->MemBalloon.cChunks++;
+            else
+            {
+                Log(("vboxGuestSetBalloonSize(inflate): failed, rc=%Rrc!\n", rc));
+                RTR0MemObjFree(*pMemObj, true);
+                *pMemObj = NIL_RTR0MEMOBJ;
+            }
+        }
+    }
+    else
+    {
+        rc = vgdrvBalloonDeflate(pMemObj, pReq);
+        if (RT_SUCCESS(rc))
+            pDevExt->MemBalloon.cChunks--;
+        else
+            Log(("vboxGuestSetBalloonSize(deflate): failed, rc=%Rrc!\n", rc));
+    }
+
+    VbglGRFree(&pReq->header);
+    return rc;
+}
+
+
+/**
+ * Cleanup the memory balloon of a session.
+ *
+ * Will request the balloon mutex, so it must be valid and the caller must not
+ * own it already.
+ *
+ * @param   pDevExt     The device extension.
+ * @param   pSession    The session.  Can be NULL at unload.
+ */
+static void vgdrvCloseMemBalloon(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession)
+{
+    RTSemFastMutexRequest(pDevExt->MemBalloon.hMtx);
+    if (    pDevExt->MemBalloon.pOwner == pSession
+        ||  pSession == NULL /*unload*/)
+    {
+        if (pDevExt->MemBalloon.paMemObj)
+        {
+            VMMDevChangeMemBalloon *pReq;
+            int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, g_cbChangeMemBalloonReq, VMMDevReq_ChangeMemBalloon);
+            if (RT_SUCCESS(rc))
+            {
+                uint32_t i;
+                for (i = pDevExt->MemBalloon.cChunks; i-- > 0;)
+                {
+                    rc = vgdrvBalloonDeflate(&pDevExt->MemBalloon.paMemObj[i], pReq);
+                    if (RT_FAILURE(rc))
+                    {
+                        LogRel(("vgdrvCloseMemBalloon: Deflate failed with rc=%Rrc.  Will leak %u chunks.\n",
+                                rc, pDevExt->MemBalloon.cChunks));
+                        break;
+                    }
+                    pDevExt->MemBalloon.paMemObj[i] = NIL_RTR0MEMOBJ;
+                    pDevExt->MemBalloon.cChunks--;
+                }
+                VbglGRFree(&pReq->header);
+            }
+            else
+                LogRel(("vgdrvCloseMemBalloon: Failed to allocate VMMDev request buffer (rc=%Rrc).  Will leak %u chunks.\n",
+                        rc, pDevExt->MemBalloon.cChunks));
+            RTMemFree(pDevExt->MemBalloon.paMemObj);
+            pDevExt->MemBalloon.paMemObj = NULL;
+        }
+
+        pDevExt->MemBalloon.pOwner = NULL;
+    }
+    RTSemFastMutexRelease(pDevExt->MemBalloon.hMtx);
+}
+
+/** @} */
+
+
+
+/** @name Heartbeat
+ * @{
+ */
+
+/**
+ * Sends heartbeat to host.
+ *
+ * @returns VBox status code.
+ */
+static int vgdrvHeartbeatSend(PVBOXGUESTDEVEXT pDevExt)
+{
+    int rc;
+    if (pDevExt->pReqGuestHeartbeat)
+    {
+        rc = VbglGRPerform(pDevExt->pReqGuestHeartbeat);
+        Log3(("vgdrvHeartbeatSend: VbglGRPerform vgdrvHeartbeatSend completed with rc=%Rrc\n", rc));
+    }
+    else
+        rc = VERR_INVALID_STATE;
+    return rc;
+}
+
+
+/**
+ * Callback for heartbeat timer.
+ */
+static DECLCALLBACK(void) vgdrvHeartbeatTimerHandler(PRTTIMER hTimer, void *pvUser, uint64_t iTick)
+{
+    PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pvUser;
+    int rc;
+    AssertReturnVoid(pDevExt);
+
+    rc = vgdrvHeartbeatSend(pDevExt);
+    if (RT_FAILURE(rc))
+        Log(("HB Timer: vgdrvHeartbeatSend failed: rc=%Rrc\n", rc));
+
+    NOREF(hTimer); NOREF(iTick);
+}
+
+
+/**
+ * Configure the host to check guest's heartbeat
+ * and get heartbeat interval from the host.
+ *
+ * @returns VBox status code.
+ * @param   pDevExt         The device extension.
+ * @param   fEnabled        Set true to enable guest heartbeat checks on host.
+ */
+static int vgdrvHeartbeatHostConfigure(PVBOXGUESTDEVEXT pDevExt, bool fEnabled)
+{
+    VMMDevReqHeartbeat *pReq;
+    int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_HeartbeatConfigure);
+    Log(("vgdrvHeartbeatHostConfigure: VbglGRAlloc vgdrvHeartbeatHostConfigure completed with rc=%Rrc\n", rc));
+    if (RT_SUCCESS(rc))
+    {
+        pReq->fEnabled = fEnabled;
+        pReq->cNsInterval = 0;
+        rc = VbglGRPerform(&pReq->header);
+        Log(("vgdrvHeartbeatHostConfigure: VbglGRPerform vgdrvHeartbeatHostConfigure completed with rc=%Rrc\n", rc));
+        pDevExt->cNsHeartbeatInterval = pReq->cNsInterval;
+        VbglGRFree(&pReq->header);
+    }
+    return rc;
+}
+
+
+/**
+ * Initializes the heartbeat timer.
+ *
+ * This feature may be disabled by the host.
+ *
+ * @returns VBox status (ignored).
+ * @param   pDevExt             The device extension.
+ */
+static int vgdrvHeartbeatInit(PVBOXGUESTDEVEXT pDevExt)
+{
+    /*
+     * Make sure that heartbeat checking is disabled.
+     */
+    int rc = vgdrvHeartbeatHostConfigure(pDevExt, false);
+    if (RT_SUCCESS(rc))
+    {
+        rc = vgdrvHeartbeatHostConfigure(pDevExt, true);
+        if (RT_SUCCESS(rc))
+        {
+            /*
+             * Preallocate the request to use it from the timer callback because:
+             *    1) on Windows VbglGRAlloc must be called at IRQL <= APC_LEVEL
+             *       and the timer callback runs at DISPATCH_LEVEL;
+             *    2) avoid repeated allocations.
+             */
+            rc = VbglGRAlloc(&pDevExt->pReqGuestHeartbeat, sizeof(*pDevExt->pReqGuestHeartbeat), VMMDevReq_GuestHeartbeat);
+            if (RT_SUCCESS(rc))
+            {
+                LogRel(("vgdrvHeartbeatInit: Setting up heartbeat to trigger every %RU64 milliseconds\n",
+                        pDevExt->cNsHeartbeatInterval / RT_NS_1MS));
+                rc = RTTimerCreateEx(&pDevExt->pHeartbeatTimer, pDevExt->cNsHeartbeatInterval, 0 /*fFlags*/,
+                                     (PFNRTTIMER)vgdrvHeartbeatTimerHandler, pDevExt);
+                if (RT_SUCCESS(rc))
+                {
+                    rc = RTTimerStart(pDevExt->pHeartbeatTimer, 0);
+                    if (RT_SUCCESS(rc))
+                        return VINF_SUCCESS;
+
+                    LogRel(("vgdrvHeartbeatInit: Heartbeat timer failed to start, rc=%Rrc\n", rc));
+                }
+                else
+                    LogRel(("vgdrvHeartbeatInit: Failed to create heartbeat timer: %Rrc\n", rc));
+
+                VbglGRFree(pDevExt->pReqGuestHeartbeat);
+                pDevExt->pReqGuestHeartbeat = NULL;
+            }
+            else
+                LogRel(("vgdrvHeartbeatInit: VbglGRAlloc(VMMDevReq_GuestHeartbeat): %Rrc\n", rc));
+
+            LogRel(("vgdrvHeartbeatInit: Failed to set up the timer, guest heartbeat is disabled\n"));
+            vgdrvHeartbeatHostConfigure(pDevExt, false);
+        }
+        else
+            LogRel(("vgdrvHeartbeatInit: Failed to configure host for heartbeat checking: rc=%Rrc\n", rc));
+    }
+    return rc;
+}
+
+/** @} */
+
+
+/**
+ * Helper to reinit the VMMDev communication after hibernation.
+ *
+ * @returns VBox status code.
+ * @param   pDevExt         The device extension.
+ * @param   enmOSType       The OS type.
+ *
+ * @todo Call this on all platforms, not just windows.
+ */
+int VGDrvCommonReinitDevExtAfterHibernation(PVBOXGUESTDEVEXT pDevExt, VBOXOSTYPE enmOSType)
+{
+    int rc = vgdrvReportGuestInfo(enmOSType);
+    if (RT_SUCCESS(rc))
+    {
+        rc = vgdrvReportDriverStatus(true /* Driver is active */);
+        if (RT_FAILURE(rc))
+            Log(("VGDrvCommonReinitDevExtAfterHibernation: could not report guest driver status, rc=%Rrc\n", rc));
+    }
+    else
+        Log(("VGDrvCommonReinitDevExtAfterHibernation: could not report guest information to host, rc=%Rrc\n", rc));
+    LogFlow(("VGDrvCommonReinitDevExtAfterHibernation: returned with rc=%Rrc\n", rc));
+    RT_NOREF1(pDevExt);
+    return rc;
+}
+
+
+/**
+ * Initializes the VBoxGuest device extension when the
+ * device driver is loaded.
+ *
+ * The native code locates the VMMDev on the PCI bus and retrieve
+ * the MMIO and I/O port ranges, this function will take care of
+ * mapping the MMIO memory (if present). Upon successful return
+ * the native code should set up the interrupt handler.
+ *
+ * @returns VBox status code.
+ *
+ * @param   pDevExt         The device extension. Allocated by the native code.
+ * @param   IOPortBase      The base of the I/O port range.
+ * @param   pvMMIOBase      The base of the MMIO memory mapping.
+ *                          This is optional, pass NULL if not present.
+ * @param   cbMMIO          The size of the MMIO memory mapping.
+ *                          This is optional, pass 0 if not present.
+ * @param   enmOSType       The guest OS type to report to the VMMDev.
+ * @param   fFixedEvents    Events that will be enabled upon init and no client
+ *                          will ever be allowed to mask.
+ */
+int VGDrvCommonInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase,
+                          void *pvMMIOBase, uint32_t cbMMIO, VBOXOSTYPE enmOSType, uint32_t fFixedEvents)
+{
+    int rc, rc2;
+
+#ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER
+    /*
+     * Create the release log.
+     */
+    static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
+    PRTLOGGER pRelLogger;
+    rc = RTLogCreate(&pRelLogger, 0 /*fFlags*/, "all", "VBOXGUEST_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups,
+                     RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER, NULL);
+    if (RT_SUCCESS(rc))
+        RTLogRelSetDefaultInstance(pRelLogger);
+    /** @todo Add native hook for getting logger config parameters and setting
+     *        them.  On linux we should use the module parameter stuff... */
+#endif
+
+    /*
+     * Adjust fFixedEvents.
+     */
+#ifdef VBOX_WITH_HGCM
+    fFixedEvents |= VMMDEV_EVENT_HGCM;
+#endif
+
+    /*
+     * Initialize the data.
+     */
+    pDevExt->IOPortBase = IOPortBase;
+    pDevExt->pVMMDevMemory = NULL;
+    pDevExt->hGuestMappings = NIL_RTR0MEMOBJ;
+    pDevExt->EventSpinlock = NIL_RTSPINLOCK;
+    pDevExt->pIrqAckEvents = NULL;
+    pDevExt->PhysIrqAckEvents = NIL_RTCCPHYS;
+    RTListInit(&pDevExt->WaitList);
+#ifdef VBOX_WITH_HGCM
+    RTListInit(&pDevExt->HGCMWaitList);
+#endif
+#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
+    RTListInit(&pDevExt->WakeUpList);
+#endif
+    RTListInit(&pDevExt->WokenUpList);
+    RTListInit(&pDevExt->FreeList);
+    RTListInit(&pDevExt->SessionList);
+    pDevExt->cSessions = 0;
+    pDevExt->fLoggingEnabled = false;
+    pDevExt->f32PendingEvents = 0;
+    pDevExt->u32MousePosChangedSeq = 0;
+    pDevExt->SessionSpinlock = NIL_RTSPINLOCK;
+    pDevExt->MemBalloon.hMtx = NIL_RTSEMFASTMUTEX;
+    pDevExt->MemBalloon.cChunks = 0;
+    pDevExt->MemBalloon.cMaxChunks = 0;
+    pDevExt->MemBalloon.fUseKernelAPI = true;
+    pDevExt->MemBalloon.paMemObj = NULL;
+    pDevExt->MemBalloon.pOwner = NULL;
+    pDevExt->MouseNotifyCallback.pfnNotify = NULL;
+    pDevExt->MouseNotifyCallback.pvUser = NULL;
+    pDevExt->pReqGuestHeartbeat = NULL;
+
+    pDevExt->fFixedEvents = fFixedEvents;
+    vgdrvBitUsageTrackerClear(&pDevExt->EventFilterTracker);
+    pDevExt->fEventFilterHost = UINT32_MAX;  /* forces a report */
+
+    vgdrvBitUsageTrackerClear(&pDevExt->MouseStatusTracker);
+    pDevExt->fMouseStatusHost = UINT32_MAX;  /* forces a report */
+
+    pDevExt->fAcquireModeGuestCaps = 0;
+    pDevExt->fSetModeGuestCaps = 0;
+    pDevExt->fAcquiredGuestCaps = 0;
+    vgdrvBitUsageTrackerClear(&pDevExt->SetGuestCapsTracker);
+    pDevExt->fGuestCapsHost = UINT32_MAX; /* forces a report */
+
+    /*
+     * If there is an MMIO region validate the version and size.
+     */
+    if (pvMMIOBase)
+    {
+        VMMDevMemory *pVMMDev = (VMMDevMemory *)pvMMIOBase;
+        Assert(cbMMIO);
+        if (    pVMMDev->u32Version == VMMDEV_MEMORY_VERSION
+            &&  pVMMDev->u32Size >= 32
+            &&  pVMMDev->u32Size <= cbMMIO)
+        {
+            pDevExt->pVMMDevMemory = pVMMDev;
+            Log(("VGDrvCommonInitDevExt: VMMDevMemory: mapping=%p size=%#RX32 (%#RX32) version=%#RX32\n",
+                 pVMMDev, pVMMDev->u32Size, cbMMIO, pVMMDev->u32Version));
+        }
+        else /* try live without it. */
+            LogRel(("VGDrvCommonInitDevExt: Bogus VMMDev memory; u32Version=%RX32 (expected %RX32) u32Size=%RX32 (expected <= %RX32)\n",
+                    pVMMDev->u32Version, VMMDEV_MEMORY_VERSION, pVMMDev->u32Size, cbMMIO));
+    }
+
+    /*
+     * Create the wait and session spinlocks as well as the ballooning mutex.
+     */
+    rc = RTSpinlockCreate(&pDevExt->EventSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestEvent");
+    if (RT_SUCCESS(rc))
+        rc = RTSpinlockCreate(&pDevExt->SessionSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestSession");
+    if (RT_FAILURE(rc))
+    {
+        LogRel(("VGDrvCommonInitDevExt: failed to create spinlock, rc=%Rrc!\n", rc));
+        if (pDevExt->EventSpinlock != NIL_RTSPINLOCK)
+            RTSpinlockDestroy(pDevExt->EventSpinlock);
+        return rc;
+    }
+
+    rc = RTSemFastMutexCreate(&pDevExt->MemBalloon.hMtx);
+    if (RT_FAILURE(rc))
+    {
+        LogRel(("VGDrvCommonInitDevExt: failed to create mutex, rc=%Rrc!\n", rc));
+        RTSpinlockDestroy(pDevExt->SessionSpinlock);
+        RTSpinlockDestroy(pDevExt->EventSpinlock);
+        return rc;
+    }
+
+    /*
+     * Initialize the guest library and report the guest info back to VMMDev,
+     * set the interrupt control filter mask, and fixate the guest mappings
+     * made by the VMM.
+     */
+    rc = VbglInitPrimary(pDevExt->IOPortBase, (VMMDevMemory *)pDevExt->pVMMDevMemory);
+    if (RT_SUCCESS(rc))
+    {
+        rc = VbglGRAlloc((VMMDevRequestHeader **)&pDevExt->pIrqAckEvents, sizeof(VMMDevEvents), VMMDevReq_AcknowledgeEvents);
+        if (RT_SUCCESS(rc))
+        {
+            pDevExt->PhysIrqAckEvents = VbglPhysHeapGetPhysAddr(pDevExt->pIrqAckEvents);
+            Assert(pDevExt->PhysIrqAckEvents != 0);
+
+            rc = vgdrvReportGuestInfo(enmOSType);
+            if (RT_SUCCESS(rc))
+            {
+                /*
+                 * Set the fixed event and make sure the host doesn't have any lingering
+                 * the guest capabilities or mouse status bits set.
+                 */
+                rc = vgdrvResetEventFilterOnHost(pDevExt, pDevExt->fFixedEvents);
+                if (RT_SUCCESS(rc))
+                {
+                    rc = vgdrvResetCapabilitiesOnHost(pDevExt);
+                    if (RT_SUCCESS(rc))
+                    {
+                        rc = vgdrvResetMouseStatusOnHost(pDevExt);
+                        if (RT_SUCCESS(rc))
+                        {
+                            /*
+                             * Initialize stuff which may fail without requiring the driver init to fail.
+                             */
+                            vgdrvInitFixateGuestMappings(pDevExt);
+                            vgdrvHeartbeatInit(pDevExt);
+
+                            /*
+                             * Done!
+                             */
+                            rc = vgdrvReportDriverStatus(true /* Driver is active */);
+                            if (RT_FAILURE(rc))
+                                LogRel(("VGDrvCommonInitDevExt: VBoxReportGuestDriverStatus failed, rc=%Rrc\n", rc));
+
+                            LogFlowFunc(("VGDrvCommonInitDevExt: returns success\n"));
+                            return VINF_SUCCESS;
+                        }
+                        LogRel(("VGDrvCommonInitDevExt: failed to clear mouse status: rc=%Rrc\n", rc));
+                    }
+                    else
+                        LogRel(("VGDrvCommonInitDevExt: failed to clear guest capabilities: rc=%Rrc\n", rc));
+                }
+                else
+                    LogRel(("VGDrvCommonInitDevExt: failed to set fixed event filter: rc=%Rrc\n", rc));
+            }
+            else
+                LogRel(("VGDrvCommonInitDevExt: VBoxReportGuestInfo failed: rc=%Rrc\n", rc));
+            VbglGRFree((VMMDevRequestHeader *)pDevExt->pIrqAckEvents);
+        }
+        else
+            LogRel(("VGDrvCommonInitDevExt: VBoxGRAlloc failed: rc=%Rrc\n", rc));
+
+        VbglTerminate();
+    }
+    else
+        LogRel(("VGDrvCommonInitDevExt: VbglInit failed: rc=%Rrc\n", rc));
+
+    rc2 = RTSemFastMutexDestroy(pDevExt->MemBalloon.hMtx); AssertRC(rc2);
+    rc2 = RTSpinlockDestroy(pDevExt->EventSpinlock); AssertRC(rc2);
+    rc2 = RTSpinlockDestroy(pDevExt->SessionSpinlock); AssertRC(rc2);
+
+#ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER
+    RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
+    RTLogDestroy(RTLogSetDefaultInstance(NULL));
+#endif
+    return rc; /* (failed) */
+}
+
+
+/**
+ * Deletes all the items in a wait chain.
+ * @param   pList       The head of the chain.
+ */
+static void vgdrvDeleteWaitList(PRTLISTNODE pList)
+{
+    while (!RTListIsEmpty(pList))
+    {
+        int             rc2;
+        PVBOXGUESTWAIT  pWait = RTListGetFirst(pList, VBOXGUESTWAIT, ListNode);
+        RTListNodeRemove(&pWait->ListNode);
+
+        rc2 = RTSemEventMultiDestroy(pWait->Event); AssertRC(rc2);
+        pWait->Event = NIL_RTSEMEVENTMULTI;
+        pWait->pSession = NULL;
+        RTMemFree(pWait);
+    }
+}
+
+
+/**
+ * Destroys the VBoxGuest device extension.
+ *
+ * The native code should call this before the driver is loaded,
+ * but don't call this on shutdown.
+ *
+ * @param   pDevExt         The device extension.
+ */
+void VGDrvCommonDeleteDevExt(PVBOXGUESTDEVEXT pDevExt)
+{
+    int rc2;
+    Log(("VGDrvCommonDeleteDevExt:\n"));
+    Log(("VBoxGuest: The additions driver is terminating.\n"));
+
+    /*
+     * Stop and destroy HB timer and
+     * disable host heartbeat checking.
+     */
+    if (pDevExt->pHeartbeatTimer)
+    {
+        RTTimerDestroy(pDevExt->pHeartbeatTimer);
+        vgdrvHeartbeatHostConfigure(pDevExt, false);
+    }
+
+    VbglGRFree(pDevExt->pReqGuestHeartbeat);
+    pDevExt->pReqGuestHeartbeat = NULL;
+
+    /*
+     * Clean up the bits that involves the host first.
+     */
+    vgdrvTermUnfixGuestMappings(pDevExt);
+    if (!RTListIsEmpty(&pDevExt->SessionList))
+    {
+        LogRelFunc(("session list not empty!\n"));
+        RTListInit(&pDevExt->SessionList);
+    }
+    /* Update the host flags (mouse status etc) not to reflect this session. */
+    pDevExt->fFixedEvents = 0;
+    vgdrvResetEventFilterOnHost(pDevExt, 0 /*fFixedEvents*/);
+    vgdrvResetCapabilitiesOnHost(pDevExt);
+    vgdrvResetMouseStatusOnHost(pDevExt);
+
+    vgdrvCloseMemBalloon(pDevExt, (PVBOXGUESTSESSION)NULL);
+
+    /*
+     * Cleanup all the other resources.
+     */
+    rc2 = RTSpinlockDestroy(pDevExt->EventSpinlock); AssertRC(rc2);
+    rc2 = RTSpinlockDestroy(pDevExt->SessionSpinlock); AssertRC(rc2);
+    rc2 = RTSemFastMutexDestroy(pDevExt->MemBalloon.hMtx); AssertRC(rc2);
+
+    vgdrvDeleteWaitList(&pDevExt->WaitList);
+#ifdef VBOX_WITH_HGCM
+    vgdrvDeleteWaitList(&pDevExt->HGCMWaitList);
+#endif
+#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
+    vgdrvDeleteWaitList(&pDevExt->WakeUpList);
+#endif
+    vgdrvDeleteWaitList(&pDevExt->WokenUpList);
+    vgdrvDeleteWaitList(&pDevExt->FreeList);
+
+    VbglTerminate();
+
+    pDevExt->pVMMDevMemory = NULL;
+
+    pDevExt->IOPortBase = 0;
+    pDevExt->pIrqAckEvents = NULL;
+
+#ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER
+    RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
+    RTLogDestroy(RTLogSetDefaultInstance(NULL));
+#endif
+
+}
+
+
+/**
+ * Creates a VBoxGuest user session.
+ *
+ * The native code calls this when a ring-3 client opens the device.
+ * Use VGDrvCommonCreateKernelSession when a ring-0 client connects.
+ *
+ * @returns VBox status code.
+ * @param   pDevExt         The device extension.
+ * @param   ppSession       Where to store the session on success.
+ */
+int VGDrvCommonCreateUserSession(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION *ppSession)
+{
+    PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)RTMemAllocZ(sizeof(*pSession));
+    if (RT_UNLIKELY(!pSession))
+    {
+        LogRel(("VGDrvCommonCreateUserSession: no memory!\n"));
+        return VERR_NO_MEMORY;
+    }
+
+    pSession->Process = RTProcSelf();
+    pSession->R0Process = RTR0ProcHandleSelf();
+    pSession->pDevExt = pDevExt;
+    RTSpinlockAcquire(pDevExt->SessionSpinlock);
+    RTListAppend(&pDevExt->SessionList, &pSession->ListNode);
+    pDevExt->cSessions++;
+    RTSpinlockRelease(pDevExt->SessionSpinlock);
+
+    *ppSession = pSession;
+    LogFlow(("VGDrvCommonCreateUserSession: pSession=%p proc=%RTproc (%d) r0proc=%p\n",
+             pSession, pSession->Process, (int)pSession->Process, (uintptr_t)pSession->R0Process)); /** @todo %RTr0proc */
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Creates a VBoxGuest kernel session.
+ *
+ * The native code calls this when a ring-0 client connects to the device.
+ * Use VGDrvCommonCreateUserSession when a ring-3 client opens the device.
+ *
+ * @returns VBox status code.
+ * @param   pDevExt         The device extension.
+ * @param   ppSession       Where to store the session on success.
+ */
+int VGDrvCommonCreateKernelSession(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION *ppSession)
+{
+    PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)RTMemAllocZ(sizeof(*pSession));
+    if (RT_UNLIKELY(!pSession))
+    {
+        LogRel(("VGDrvCommonCreateKernelSession: no memory!\n"));
+        return VERR_NO_MEMORY;
+    }
+
+    pSession->Process = NIL_RTPROCESS;
+    pSession->R0Process = NIL_RTR0PROCESS;
+    pSession->pDevExt = pDevExt;
+    RTSpinlockAcquire(pDevExt->SessionSpinlock);
+    RTListAppend(&pDevExt->SessionList, &pSession->ListNode);
+    pDevExt->cSessions++;
+    RTSpinlockRelease(pDevExt->SessionSpinlock);
+
+    *ppSession = pSession;
+    LogFlow(("VGDrvCommonCreateKernelSession: pSession=%p proc=%RTproc (%d) r0proc=%p\n",
+             pSession, pSession->Process, (int)pSession->Process, (uintptr_t)pSession->R0Process)); /** @todo %RTr0proc */
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Closes a VBoxGuest session.
+ *
+ * @param   pDevExt         The device extension.
+ * @param   pSession        The session to close (and free).
+ */
+void VGDrvCommonCloseSession(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession)
+{
+#ifdef VBOX_WITH_HGCM
+    unsigned i;
+#endif
+    LogFlow(("VGDrvCommonCloseSession: pSession=%p proc=%RTproc (%d) r0proc=%p\n",
+             pSession, pSession->Process, (int)pSession->Process, (uintptr_t)pSession->R0Process)); /** @todo %RTr0proc */
+
+    RTSpinlockAcquire(pDevExt->SessionSpinlock);
+    RTListNodeRemove(&pSession->ListNode);
+    pDevExt->cSessions--;
+    RTSpinlockRelease(pDevExt->SessionSpinlock);
+    vgdrvAcquireSessionCapabilities(pDevExt, pSession, 0, UINT32_MAX, VBOXGUESTCAPSACQUIRE_FLAGS_NONE,
+                                   true /*fSessionTermination*/);
+    vgdrvSetSessionCapabilities(pDevExt, pSession, 0 /*fOrMask*/, UINT32_MAX /*fNotMask*/, true /*fSessionTermination*/);
+    vgdrvSetSessionEventFilter(pDevExt, pSession, 0 /*fOrMask*/, UINT32_MAX /*fNotMask*/, true /*fSessionTermination*/);
+    vgdrvSetSessionMouseStatus(pDevExt, pSession, 0 /*fOrMask*/, UINT32_MAX /*fNotMask*/, true /*fSessionTermination*/);
+
+    vgdrvIoCtl_CancelAllWaitEvents(pDevExt, pSession);
+
+#ifdef VBOX_WITH_HGCM
+    for (i = 0; i < RT_ELEMENTS(pSession->aHGCMClientIds); i++)
+        if (pSession->aHGCMClientIds[i])
+        {
+            VBoxGuestHGCMDisconnectInfo Info;
+            Info.result = 0;
+            Info.u32ClientID = pSession->aHGCMClientIds[i];
+            pSession->aHGCMClientIds[i] = 0;
+            Log(("VGDrvCommonCloseSession: disconnecting client id %#RX32\n", Info.u32ClientID));
+            VbglR0HGCMInternalDisconnect(&Info, vgdrvHgcmAsyncWaitCallback, pDevExt, RT_INDEFINITE_WAIT);
+        }
+#endif
+
+    pSession->pDevExt = NULL;
+    pSession->Process = NIL_RTPROCESS;
+    pSession->R0Process = NIL_RTR0PROCESS;
+    vgdrvCloseMemBalloon(pDevExt, pSession);
+    RTMemFree(pSession);
+}
+
+
+/**
+ * Allocates a wait-for-event entry.
+ *
+ * @returns The wait-for-event entry.
+ * @param   pDevExt         The device extension.
+ * @param   pSession        The session that's allocating this. Can be NULL.
+ */
+static PVBOXGUESTWAIT vgdrvWaitAlloc(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession)
+{
+    /*
+     * Allocate it one way or the other.
+     */
+    PVBOXGUESTWAIT pWait = RTListGetFirst(&pDevExt->FreeList, VBOXGUESTWAIT, ListNode);
+    if (pWait)
+    {
+        RTSpinlockAcquire(pDevExt->EventSpinlock);
+
+        pWait = RTListGetFirst(&pDevExt->FreeList, VBOXGUESTWAIT, ListNode);
+        if (pWait)
+            RTListNodeRemove(&pWait->ListNode);
+
+        RTSpinlockRelease(pDevExt->EventSpinlock);
+    }
+    if (!pWait)
+    {
+        int rc;
+
+        pWait = (PVBOXGUESTWAIT)RTMemAlloc(sizeof(*pWait));
+        if (!pWait)
+        {
+            LogRelMax(32, ("vgdrvWaitAlloc: out-of-memory!\n"));
+            return NULL;
+        }
+
+        rc = RTSemEventMultiCreate(&pWait->Event);
+        if (RT_FAILURE(rc))
+        {
+            LogRelMax(32, ("vgdrvWaitAlloc: RTSemEventMultiCreate failed with rc=%Rrc!\n", rc));
+            RTMemFree(pWait);
+            return NULL;
+        }
+
+        pWait->ListNode.pNext = NULL;
+        pWait->ListNode.pPrev = NULL;
+    }
+
+    /*
+     * Zero members just as an precaution.
+     */
+    pWait->fReqEvents = 0;
+    pWait->fResEvents = 0;
+#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
+    pWait->fPendingWakeUp = false;
+    pWait->fFreeMe = false;
+#endif
+    pWait->pSession = pSession;
+#ifdef VBOX_WITH_HGCM
+    pWait->pHGCMReq = NULL;
+#endif
+    RTSemEventMultiReset(pWait->Event);
+    return pWait;
+}
+
+
+/**
+ * Frees the wait-for-event entry.
+ *
+ * The caller must own the wait spinlock !
+ * The entry must be in a list!
+ *
+ * @param   pDevExt         The device extension.
+ * @param   pWait           The wait-for-event entry to free.
+ */
+static void vgdrvWaitFreeLocked(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTWAIT pWait)
+{
+    pWait->fReqEvents = 0;
+    pWait->fResEvents = 0;
+#ifdef VBOX_WITH_HGCM
+    pWait->pHGCMReq = NULL;
+#endif
+#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
+    Assert(!pWait->fFreeMe);
+    if (pWait->fPendingWakeUp)
+        pWait->fFreeMe = true;
+    else
+#endif
+    {
+        RTListNodeRemove(&pWait->ListNode);
+        RTListAppend(&pDevExt->FreeList, &pWait->ListNode);
+    }
+}
+
+
+/**
+ * Frees the wait-for-event entry.
+ *
+ * @param   pDevExt         The device extension.
+ * @param   pWait           The wait-for-event entry to free.
+ */
+static void vgdrvWaitFreeUnlocked(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTWAIT pWait)
+{
+    RTSpinlockAcquire(pDevExt->EventSpinlock);
+    vgdrvWaitFreeLocked(pDevExt, pWait);
+    RTSpinlockRelease(pDevExt->EventSpinlock);
+}
+
+
+#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
+/**
+ * Processes the wake-up list.
+ *
+ * All entries in the wake-up list gets signalled and moved to the woken-up
+ * list.
+ * At least on Windows this function can be invoked concurrently from
+ * different VCPUs. So, be thread-safe.
+ *
+ * @param   pDevExt         The device extension.
+ */
+void VGDrvCommonWaitDoWakeUps(PVBOXGUESTDEVEXT pDevExt)
+{
+    if (!RTListIsEmpty(&pDevExt->WakeUpList))
+    {
+        RTSpinlockAcquire(pDevExt->EventSpinlock);
+        for (;;)
+        {
+            int            rc;
+            PVBOXGUESTWAIT pWait = RTListGetFirst(&pDevExt->WakeUpList, VBOXGUESTWAIT, ListNode);
+            if (!pWait)
+                break;
+            /* Prevent other threads from accessing pWait when spinlock is released. */
+            RTListNodeRemove(&pWait->ListNode);
+
+            pWait->fPendingWakeUp = true;
+            RTSpinlockRelease(pDevExt->EventSpinlock);
+
+            rc = RTSemEventMultiSignal(pWait->Event);
+            AssertRC(rc);
+
+            RTSpinlockAcquire(pDevExt->EventSpinlock);
+            Assert(pWait->ListNode.pNext == NULL && pWait->ListNode.pPrev == NULL);
+            RTListAppend(&pDevExt->WokenUpList, &pWait->ListNode);
+            pWait->fPendingWakeUp = false;
+            if (RT_LIKELY(!pWait->fFreeMe))
+            { /* likely */ }
+            else
+            {
+                pWait->fFreeMe = false;
+                vgdrvWaitFreeLocked(pDevExt, pWait);
+            }
+        }
+        RTSpinlockRelease(pDevExt->EventSpinlock);
+    }
+}
+#endif /* VBOXGUEST_USE_DEFERRED_WAKE_UP */
+
+
+/**
+ * Implements the fast (no input or output) type of IOCtls.
+ *
+ * This is currently just a placeholder stub inherited from the support driver code.
+ *
+ * @returns VBox status code.
+ * @param   iFunction   The IOCtl function number.
+ * @param   pDevExt     The device extension.
+ * @param   pSession    The session.
+ */
+int VGDrvCommonIoCtlFast(unsigned iFunction, PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession)
+{
+    LogFlow(("VGDrvCommonIoCtlFast: iFunction=%#x pDevExt=%p pSession=%p\n", iFunction, pDevExt, pSession));
+
+    NOREF(iFunction);
+    NOREF(pDevExt);
+    NOREF(pSession);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+/**
+ * Return the VMM device port.
+ *
+ * returns IPRT status code.
+ * @param   pDevExt         The device extension.
+ * @param   pInfo           The request info.
+ * @param   pcbDataReturned (out) contains the number of bytes to return.
+ */
+static int vgdrvIoCtl_GetVMMDevPort(PVBOXGUESTDEVEXT pDevExt, VBoxGuestPortInfo *pInfo, size_t *pcbDataReturned)
+{
+    LogFlow(("VBOXGUEST_IOCTL_GETVMMDEVPORT\n"));
+
+    pInfo->portAddress = pDevExt->IOPortBase;
+    pInfo->pVMMDevMemory = (VMMDevMemory *)pDevExt->pVMMDevMemory;
+    if (pcbDataReturned)
+        *pcbDataReturned = sizeof(*pInfo);
+    return VINF_SUCCESS;
+}
+
+
+#ifndef RT_OS_WINDOWS
+/**
+ * Set the callback for the kernel mouse handler.
+ *
+ * returns IPRT status code.
+ * @param   pDevExt         The device extension.
+ * @param   pNotify         The new callback information.
+ */
+int vgdrvIoCtl_SetMouseNotifyCallback(PVBOXGUESTDEVEXT pDevExt, VBoxGuestMouseSetNotifyCallback *pNotify)
+{
+    LogFlow(("VBOXGUEST_IOCTL_SET_MOUSE_NOTIFY_CALLBACK: pfnNotify=%p pvUser=%p\n", pNotify->pfnNotify, pNotify->pvUser));
+
+#ifdef VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT
+    VGDrvNativeSetMouseNotifyCallback(pDevExt, pNotify);
+#else
+    RTSpinlockAcquire(pDevExt->EventSpinlock);
+    pDevExt->MouseNotifyCallback = *pNotify;
+    RTSpinlockRelease(pDevExt->EventSpinlock);
+#endif
+    return VINF_SUCCESS;
+}
+#endif
+
+
+/**
+ * Worker vgdrvIoCtl_WaitEvent.
+ *
+ * The caller enters the spinlock, we leave it.
+ *
+ * @returns VINF_SUCCESS if we've left the spinlock and can return immediately.
+ */
+DECLINLINE(int) vbdgCheckWaitEventCondition(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                                            VBoxGuestWaitEventInfo *pInfo, int iEvent, const uint32_t fReqEvents)
+{
+    uint32_t fMatches = pDevExt->f32PendingEvents & fReqEvents;
+    if (fMatches & VBOXGUEST_ACQUIRE_STYLE_EVENTS)
+        fMatches &= vgdrvGetAllowedEventMaskForSession(pDevExt, pSession);
+    if (fMatches || pSession->fPendingCancelWaitEvents)
+    {
+        ASMAtomicAndU32(&pDevExt->f32PendingEvents, ~fMatches);
+        RTSpinlockRelease(pDevExt->EventSpinlock);
+
+        pInfo->u32EventFlagsOut = fMatches;
+        pInfo->u32Result = VBOXGUEST_WAITEVENT_OK;
+        if (fReqEvents & ~((uint32_t)1 << iEvent))
+            LogFlow(("VBOXGUEST_IOCTL_WAITEVENT: returns %#x\n", pInfo->u32EventFlagsOut));
+        else
+            LogFlow(("VBOXGUEST_IOCTL_WAITEVENT: returns %#x/%d\n", pInfo->u32EventFlagsOut, iEvent));
+        pSession->fPendingCancelWaitEvents = false;
+        return VINF_SUCCESS;
+    }
+
+    RTSpinlockRelease(pDevExt->EventSpinlock);
+    return VERR_TIMEOUT;
+}
+
+
+static int vgdrvIoCtl_WaitEvent(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                                VBoxGuestWaitEventInfo *pInfo,  size_t *pcbDataReturned, bool fInterruptible)
+{
+    const uint32_t  fReqEvents = pInfo->u32EventMaskIn;
+    uint32_t        fResEvents;
+    int             iEvent;
+    PVBOXGUESTWAIT  pWait;
+    int             rc;
+
+    pInfo->u32EventFlagsOut = 0;
+    pInfo->u32Result = VBOXGUEST_WAITEVENT_ERROR;
+    if (pcbDataReturned)
+        *pcbDataReturned = sizeof(*pInfo);
+
+    /*
+     * Copy and verify the input mask.
+     */
+    iEvent = ASMBitFirstSetU32(fReqEvents) - 1;
+    if (RT_UNLIKELY(iEvent < 0))
+    {
+        LogRel(("VBOXGUEST_IOCTL_WAITEVENT: Invalid input mask %#x!!\n", fReqEvents));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    /*
+     * Check the condition up front, before doing the wait-for-event allocations.
+     */
+    RTSpinlockAcquire(pDevExt->EventSpinlock);
+    rc = vbdgCheckWaitEventCondition(pDevExt, pSession, pInfo, iEvent, fReqEvents);
+    if (rc == VINF_SUCCESS)
+        return rc;
+
+    if (!pInfo->u32TimeoutIn)
+    {
+        pInfo->u32Result = VBOXGUEST_WAITEVENT_TIMEOUT;
+        LogFlow(("VBOXGUEST_IOCTL_WAITEVENT: returns VERR_TIMEOUT\n"));
+        return VERR_TIMEOUT;
+    }
+
+    pWait = vgdrvWaitAlloc(pDevExt, pSession);
+    if (!pWait)
+        return VERR_NO_MEMORY;
+    pWait->fReqEvents = fReqEvents;
+
+    /*
+     * We've got the wait entry now, re-enter the spinlock and check for the condition.
+     * If the wait condition is met, return.
+     * Otherwise enter into the list and go to sleep waiting for the ISR to signal us.
+     */
+    RTSpinlockAcquire(pDevExt->EventSpinlock);
+    RTListAppend(&pDevExt->WaitList, &pWait->ListNode);
+    rc = vbdgCheckWaitEventCondition(pDevExt, pSession, pInfo, iEvent, fReqEvents);
+    if (rc == VINF_SUCCESS)
+    {
+        vgdrvWaitFreeUnlocked(pDevExt, pWait);
+        return rc;
+    }
+
+    if (fInterruptible)
+        rc = RTSemEventMultiWaitNoResume(pWait->Event,
+                                         pInfo->u32TimeoutIn == UINT32_MAX ? RT_INDEFINITE_WAIT : pInfo->u32TimeoutIn);
+    else
+        rc = RTSemEventMultiWait(pWait->Event,
+                                 pInfo->u32TimeoutIn == UINT32_MAX ? RT_INDEFINITE_WAIT : pInfo->u32TimeoutIn);
+
+    /*
+     * There is one special case here and that's when the semaphore is
+     * destroyed upon device driver unload. This shouldn't happen of course,
+     * but in case it does, just get out of here ASAP.
+     */
+    if (rc == VERR_SEM_DESTROYED)
+        return rc;
+
+    /*
+     * Unlink the wait item and dispose of it.
+     */
+    RTSpinlockAcquire(pDevExt->EventSpinlock);
+    fResEvents = pWait->fResEvents;
+    vgdrvWaitFreeLocked(pDevExt, pWait);
+    RTSpinlockRelease(pDevExt->EventSpinlock);
+
+    /*
+     * Now deal with the return code.
+     */
+    if (    fResEvents
+        &&  fResEvents != UINT32_MAX)
+    {
+        pInfo->u32EventFlagsOut = fResEvents;
+        pInfo->u32Result = VBOXGUEST_WAITEVENT_OK;
+        if (fReqEvents & ~((uint32_t)1 << iEvent))
+            LogFlow(("VBOXGUEST_IOCTL_WAITEVENT: returns %#x\n", pInfo->u32EventFlagsOut));
+        else
+            LogFlow(("VBOXGUEST_IOCTL_WAITEVENT: returns %#x/%d\n", pInfo->u32EventFlagsOut, iEvent));
+        rc = VINF_SUCCESS;
+    }
+    else if (   fResEvents == UINT32_MAX
+             || rc == VERR_INTERRUPTED)
+    {
+        pInfo->u32Result = VBOXGUEST_WAITEVENT_INTERRUPTED;
+        rc = VERR_INTERRUPTED;
+        LogFlow(("VBOXGUEST_IOCTL_WAITEVENT: returns VERR_INTERRUPTED\n"));
+    }
+    else if (rc == VERR_TIMEOUT)
+    {
+        pInfo->u32Result = VBOXGUEST_WAITEVENT_TIMEOUT;
+        LogFlow(("VBOXGUEST_IOCTL_WAITEVENT: returns VERR_TIMEOUT (2)\n"));
+    }
+    else
+    {
+        if (RT_SUCCESS(rc))
+        {
+            LogRelMax(32, ("VBOXGUEST_IOCTL_WAITEVENT: returns %Rrc but no events!\n", rc));
+            rc = VERR_INTERNAL_ERROR;
+        }
+        pInfo->u32Result = VBOXGUEST_WAITEVENT_ERROR;
+        LogFlow(("VBOXGUEST_IOCTL_WAITEVENT: returns %Rrc\n", rc));
+    }
+
+    return rc;
+}
+
+
+static int vgdrvIoCtl_CancelAllWaitEvents(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession)
+{
+    PVBOXGUESTWAIT          pWait;
+    PVBOXGUESTWAIT          pSafe;
+    int                     rc = 0;
+    /* Was as least one WAITEVENT in process for this session?  If not we
+     * set a flag that the next call should be interrupted immediately.  This
+     * is needed so that a user thread can reliably interrupt another one in a
+     * WAITEVENT loop. */
+    bool                    fCancelledOne = false;
+
+    LogFlow(("VBOXGUEST_IOCTL_CANCEL_ALL_WAITEVENTS\n"));
+
+    /*
+     * Walk the event list and wake up anyone with a matching session.
+     */
+    RTSpinlockAcquire(pDevExt->EventSpinlock);
+    RTListForEachSafe(&pDevExt->WaitList, pWait, pSafe, VBOXGUESTWAIT, ListNode)
+    {
+        if (pWait->pSession == pSession)
+        {
+            fCancelledOne = true;
+            pWait->fResEvents = UINT32_MAX;
+            RTListNodeRemove(&pWait->ListNode);
+#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
+            RTListAppend(&pDevExt->WakeUpList, &pWait->ListNode);
+#else
+            rc |= RTSemEventMultiSignal(pWait->Event);
+            RTListAppend(&pDevExt->WokenUpList, &pWait->ListNode);
+#endif
+        }
+    }
+    if (!fCancelledOne)
+        pSession->fPendingCancelWaitEvents = true;
+    RTSpinlockRelease(pDevExt->EventSpinlock);
+    Assert(rc == 0);
+    NOREF(rc);
+
+#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
+    VGDrvCommonWaitDoWakeUps(pDevExt);
+#endif
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Checks if the VMM request is allowed in the context of the given session.
+ *
+ * @returns VINF_SUCCESS or VERR_PERMISSION_DENIED.
+ * @param   pDevExt             The device extension.
+ * @param   pSession            The calling session.
+ * @param   enmType             The request type.
+ * @param   pReqHdr             The request.
+ */
+static int vgdrvCheckIfVmmReqIsAllowed(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, VMMDevRequestType enmType,
+                                       VMMDevRequestHeader const *pReqHdr)
+{
+    /*
+     * Categorize the request being made.
+     */
+    /** @todo This need quite some more work! */
+    enum
+    {
+        kLevel_Invalid, kLevel_NoOne, kLevel_OnlyVBoxGuest, kLevel_OnlyKernel, kLevel_TrustedUsers, kLevel_AllUsers
+    } enmRequired;
+    RT_NOREF1(pDevExt);
+
+    switch (enmType)
+    {
+        /*
+         * Deny access to anything we don't know or provide specialized I/O controls for.
+         */
+#ifdef VBOX_WITH_HGCM
+        case VMMDevReq_HGCMConnect:
+        case VMMDevReq_HGCMDisconnect:
+# ifdef VBOX_WITH_64_BITS_GUESTS
+        case VMMDevReq_HGCMCall32:
+        case VMMDevReq_HGCMCall64:
+# else
+        case VMMDevReq_HGCMCall:
+# endif /* VBOX_WITH_64_BITS_GUESTS */
+        case VMMDevReq_HGCMCancel:
+        case VMMDevReq_HGCMCancel2:
+#endif /* VBOX_WITH_HGCM */
+        case VMMDevReq_SetGuestCapabilities:
+        default:
+            enmRequired = kLevel_NoOne;
+            break;
+
+        /*
+         * There are a few things only this driver can do (and it doesn't use
+         * the VMMRequst I/O control route anyway, but whatever).
+         */
+        case VMMDevReq_ReportGuestInfo:
+        case VMMDevReq_ReportGuestInfo2:
+        case VMMDevReq_GetHypervisorInfo:
+        case VMMDevReq_SetHypervisorInfo:
+        case VMMDevReq_RegisterPatchMemory:
+        case VMMDevReq_DeregisterPatchMemory:
+        case VMMDevReq_GetMemBalloonChangeRequest:
+            enmRequired = kLevel_OnlyVBoxGuest;
+            break;
+
+        /*
+         * Trusted users apps only.
+         */
+        case VMMDevReq_QueryCredentials:
+        case VMMDevReq_ReportCredentialsJudgement:
+        case VMMDevReq_RegisterSharedModule:
+        case VMMDevReq_UnregisterSharedModule:
+        case VMMDevReq_WriteCoreDump:
+        case VMMDevReq_GetCpuHotPlugRequest:
+        case VMMDevReq_SetCpuHotPlugStatus:
+        case VMMDevReq_CheckSharedModules:
+        case VMMDevReq_GetPageSharingStatus:
+        case VMMDevReq_DebugIsPageShared:
+        case VMMDevReq_ReportGuestStats:
+        case VMMDevReq_ReportGuestUserState:
+        case VMMDevReq_GetStatisticsChangeRequest:
+        case VMMDevReq_ChangeMemBalloon:
+            enmRequired = kLevel_TrustedUsers;
+            break;
+
+        /*
+         * Anyone.
+         */
+        case VMMDevReq_GetMouseStatus:
+        case VMMDevReq_SetMouseStatus:
+        case VMMDevReq_SetPointerShape:
+        case VMMDevReq_GetHostVersion:
+        case VMMDevReq_Idle:
+        case VMMDevReq_GetHostTime:
+        case VMMDevReq_SetPowerStatus:
+        case VMMDevReq_AcknowledgeEvents:
+        case VMMDevReq_CtlGuestFilterMask:
+        case VMMDevReq_ReportGuestStatus:
+        case VMMDevReq_GetDisplayChangeRequest:
+        case VMMDevReq_VideoModeSupported:
+        case VMMDevReq_GetHeightReduction:
+        case VMMDevReq_GetDisplayChangeRequest2:
+        case VMMDevReq_VideoModeSupported2:
+        case VMMDevReq_VideoAccelEnable:
+        case VMMDevReq_VideoAccelFlush:
+        case VMMDevReq_VideoSetVisibleRegion:
+        case VMMDevReq_GetDisplayChangeRequestEx:
+        case VMMDevReq_GetSeamlessChangeRequest:
+        case VMMDevReq_GetVRDPChangeRequest:
+        case VMMDevReq_LogString:
+        case VMMDevReq_GetSessionId:
+            enmRequired = kLevel_AllUsers;
+            break;
+
+        /*
+         * Depends on the request parameters...
+         */
+        /** @todo this have to be changed into an I/O control and the facilities
+         *        tracked in the session so they can automatically be failed when the
+         *        session terminates without reporting the new status.
+         *
+         *  The information presented by IGuest is not reliable without this! */
+        case VMMDevReq_ReportGuestCapabilities:
+            switch (((VMMDevReportGuestStatus const *)pReqHdr)->guestStatus.facility)
+            {
+                case VBoxGuestFacilityType_All:
+                case VBoxGuestFacilityType_VBoxGuestDriver:
+                    enmRequired = kLevel_OnlyVBoxGuest;
+                    break;
+                case VBoxGuestFacilityType_VBoxService:
+                    enmRequired = kLevel_TrustedUsers;
+                    break;
+                case VBoxGuestFacilityType_VBoxTrayClient:
+                case VBoxGuestFacilityType_Seamless:
+                case VBoxGuestFacilityType_Graphics:
+                default:
+                    enmRequired = kLevel_AllUsers;
+                    break;
+            }
+            break;
+    }
+
+    /*
+     * Check against the session.
+     */
+    switch (enmRequired)
+    {
+        default:
+        case kLevel_NoOne:
+            break;
+        case kLevel_OnlyVBoxGuest:
+        case kLevel_OnlyKernel:
+            if (pSession->R0Process == NIL_RTR0PROCESS)
+                return VINF_SUCCESS;
+            break;
+        case kLevel_TrustedUsers:
+        case kLevel_AllUsers:
+            return VINF_SUCCESS;
+    }
+
+    return VERR_PERMISSION_DENIED;
+}
+
+static int vgdrvIoCtl_VMMRequest(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                                 VMMDevRequestHeader *pReqHdr, size_t cbData, size_t *pcbDataReturned)
+{
+    int                     rc;
+    VMMDevRequestHeader    *pReqCopy;
+
+    /*
+     * Validate the header and request size.
+     */
+    const VMMDevRequestType enmType   = pReqHdr->requestType;
+    const uint32_t          cbReq     = pReqHdr->size;
+    const uint32_t          cbMinSize = (uint32_t)vmmdevGetRequestSize(enmType);
+
+    LogFlow(("VBOXGUEST_IOCTL_VMMREQUEST: type %d\n", pReqHdr->requestType));
+
+    if (cbReq < cbMinSize)
+    {
+        LogRel(("VBOXGUEST_IOCTL_VMMREQUEST: invalid hdr size %#x, expected >= %#x; type=%#x!!\n",
+                cbReq, cbMinSize, enmType));
+        return VERR_INVALID_PARAMETER;
+    }
+    if (cbReq > cbData)
+    {
+        LogRel(("VBOXGUEST_IOCTL_VMMREQUEST: invalid size %#x, expected >= %#x (hdr); type=%#x!!\n",
+                cbData, cbReq, enmType));
+        return VERR_INVALID_PARAMETER;
+    }
+    rc = VbglGRVerify(pReqHdr, cbData);
+    if (RT_FAILURE(rc))
+    {
+        Log(("VBOXGUEST_IOCTL_VMMREQUEST: invalid header: size %#x, expected >= %#x (hdr); type=%#x; rc=%Rrc!!\n",
+             cbData, cbReq, enmType, rc));
+        return rc;
+    }
+
+    rc = vgdrvCheckIfVmmReqIsAllowed(pDevExt, pSession, enmType, pReqHdr);
+    if (RT_FAILURE(rc))
+    {
+        Log(("VBOXGUEST_IOCTL_VMMREQUEST: Operation not allowed! type=%#x rc=%Rrc\n", enmType, rc));
+        return rc;
+    }
+
+    /*
+     * Make a copy of the request in the physical memory heap so
+     * the VBoxGuestLibrary can more easily deal with the request.
+     * (This is really a waste of time since the OS or the OS specific
+     * code has already buffered or locked the input/output buffer, but
+     * it does makes things a bit simpler wrt to phys address.)
+     */
+    rc = VbglGRAlloc(&pReqCopy, cbReq, enmType);
+    if (RT_FAILURE(rc))
+    {
+        Log(("VBOXGUEST_IOCTL_VMMREQUEST: failed to allocate %u (%#x) bytes to cache the request. rc=%Rrc!!\n",
+             cbReq, cbReq, rc));
+        return rc;
+    }
+    memcpy(pReqCopy, pReqHdr, cbReq);
+
+    if (enmType == VMMDevReq_GetMouseStatus) /* clear poll condition. */
+        pSession->u32MousePosChangedSeq = ASMAtomicUoReadU32(&pDevExt->u32MousePosChangedSeq);
+
+    rc = VbglGRPerform(pReqCopy);
+    if (   RT_SUCCESS(rc)
+        && RT_SUCCESS(pReqCopy->rc))
+    {
+        Assert(rc != VINF_HGCM_ASYNC_EXECUTE);
+        Assert(pReqCopy->rc != VINF_HGCM_ASYNC_EXECUTE);
+
+        memcpy(pReqHdr, pReqCopy, cbReq);
+        if (pcbDataReturned)
+            *pcbDataReturned = cbReq;
+    }
+    else if (RT_FAILURE(rc))
+        Log(("VBOXGUEST_IOCTL_VMMREQUEST: VbglGRPerform - rc=%Rrc!\n", rc));
+    else
+    {
+        Log(("VBOXGUEST_IOCTL_VMMREQUEST: request execution failed; VMMDev rc=%Rrc!\n", pReqCopy->rc));
+        rc = pReqCopy->rc;
+    }
+
+    VbglGRFree(pReqCopy);
+    return rc;
+}
+
+
+#ifdef VBOX_WITH_HGCM
+
+AssertCompile(RT_INDEFINITE_WAIT == (uint32_t)RT_INDEFINITE_WAIT); /* assumed by code below */
+
+/** Worker for vgdrvHgcmAsyncWaitCallback*. */
+static int vgdrvHgcmAsyncWaitCallbackWorker(VMMDevHGCMRequestHeader volatile *pHdr, PVBOXGUESTDEVEXT pDevExt,
+                                            bool fInterruptible, uint32_t cMillies)
+{
+    int rc;
+
+    /*
+     * Check to see if the condition was met by the time we got here.
+     *
+     * We create a simple poll loop here for dealing with out-of-memory
+     * conditions since the caller isn't necessarily able to deal with
+     * us returning too early.
+     */
+    PVBOXGUESTWAIT pWait;
+    for (;;)
+    {
+        RTSpinlockAcquire(pDevExt->EventSpinlock);
+        if ((pHdr->fu32Flags & VBOX_HGCM_REQ_DONE) != 0)
+        {
+            RTSpinlockRelease(pDevExt->EventSpinlock);
+            return VINF_SUCCESS;
+        }
+        RTSpinlockRelease(pDevExt->EventSpinlock);
+
+        pWait = vgdrvWaitAlloc(pDevExt, NULL);
+        if (pWait)
+            break;
+        if (fInterruptible)
+            return VERR_INTERRUPTED;
+        RTThreadSleep(1);
+    }
+    pWait->fReqEvents = VMMDEV_EVENT_HGCM;
+    pWait->pHGCMReq = pHdr;
+
+    /*
+     * Re-enter the spinlock and re-check for the condition.
+     * If the condition is met, return.
+     * Otherwise link us into the HGCM wait list and go to sleep.
+     */
+    RTSpinlockAcquire(pDevExt->EventSpinlock);
+    RTListAppend(&pDevExt->HGCMWaitList, &pWait->ListNode);
+    if ((pHdr->fu32Flags & VBOX_HGCM_REQ_DONE) != 0)
+    {
+        vgdrvWaitFreeLocked(pDevExt, pWait);
+        RTSpinlockRelease(pDevExt->EventSpinlock);
+        return VINF_SUCCESS;
+    }
+    RTSpinlockRelease(pDevExt->EventSpinlock);
+
+    if (fInterruptible)
+        rc = RTSemEventMultiWaitNoResume(pWait->Event, cMillies);
+    else
+        rc = RTSemEventMultiWait(pWait->Event, cMillies);
+    if (rc == VERR_SEM_DESTROYED)
+        return rc;
+
+    /*
+     * Unlink, free and return.
+     */
+    if (   RT_FAILURE(rc)
+        && rc != VERR_TIMEOUT
+        && (   !fInterruptible
+            || rc != VERR_INTERRUPTED))
+        LogRel(("vgdrvHgcmAsyncWaitCallback: wait failed! %Rrc\n", rc));
+
+    vgdrvWaitFreeUnlocked(pDevExt, pWait);
+    return rc;
+}
+
+
+/**
+ * This is a callback for dealing with async waits.
+ *
+ * It operates in a manner similar to vgdrvIoCtl_WaitEvent.
+ */
+static DECLCALLBACK(int) vgdrvHgcmAsyncWaitCallback(VMMDevHGCMRequestHeader *pHdr, void *pvUser, uint32_t u32User)
+{
+    PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pvUser;
+    LogFlow(("vgdrvHgcmAsyncWaitCallback: requestType=%d\n", pHdr->header.requestType));
+    return vgdrvHgcmAsyncWaitCallbackWorker((VMMDevHGCMRequestHeader volatile *)pHdr, pDevExt,
+                                            false /* fInterruptible */, u32User  /* cMillies */);
+}
+
+
+/**
+ * This is a callback for dealing with async waits with a timeout.
+ *
+ * It operates in a manner similar to vgdrvIoCtl_WaitEvent.
+ */
+static DECLCALLBACK(int) vgdrvHgcmAsyncWaitCallbackInterruptible(VMMDevHGCMRequestHeader *pHdr, void *pvUser, uint32_t u32User)
+{
+    PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pvUser;
+    LogFlow(("vgdrvHgcmAsyncWaitCallbackInterruptible: requestType=%d\n", pHdr->header.requestType));
+    return vgdrvHgcmAsyncWaitCallbackWorker((VMMDevHGCMRequestHeader volatile *)pHdr, pDevExt,
+                                            true /* fInterruptible */, u32User /* cMillies */);
+}
+
+
+static int vgdrvIoCtl_HGCMConnect(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                                  VBoxGuestHGCMConnectInfo *pInfo, size_t *pcbDataReturned)
+{
+    int rc;
+
+    /*
+     * The VbglHGCMConnect call will invoke the callback if the HGCM
+     * call is performed in an ASYNC fashion. The function is not able
+     * to deal with cancelled requests.
+     */
+    Log(("VBOXGUEST_IOCTL_HGCM_CONNECT: %.128s\n",
+         pInfo->Loc.type == VMMDevHGCMLoc_LocalHost || pInfo->Loc.type == VMMDevHGCMLoc_LocalHost_Existing
+         ? pInfo->Loc.u.host.achName : "<not local host>"));
+
+    rc = VbglR0HGCMInternalConnect(pInfo, vgdrvHgcmAsyncWaitCallback, pDevExt, RT_INDEFINITE_WAIT);
+    if (RT_SUCCESS(rc))
+    {
+        Log(("VBOXGUEST_IOCTL_HGCM_CONNECT: u32Client=%RX32 result=%Rrc (rc=%Rrc)\n",
+             pInfo->u32ClientID, pInfo->result, rc));
+        if (RT_SUCCESS(pInfo->result))
+        {
+            /*
+             * Append the client id to the client id table.
+             * If the table has somehow become filled up, we'll disconnect the session.
+             */
+            unsigned i;
+            RTSpinlockAcquire(pDevExt->SessionSpinlock);
+            for (i = 0; i < RT_ELEMENTS(pSession->aHGCMClientIds); i++)
+                if (!pSession->aHGCMClientIds[i])
+                {
+                    pSession->aHGCMClientIds[i] = pInfo->u32ClientID;
+                    break;
+                }
+            RTSpinlockRelease(pDevExt->SessionSpinlock);
+            if (i >= RT_ELEMENTS(pSession->aHGCMClientIds))
+            {
+                VBoxGuestHGCMDisconnectInfo Info;
+                LogRelMax(32, ("VBOXGUEST_IOCTL_HGCM_CONNECT: too many HGCMConnect calls for one session!\n"));
+                Info.result = 0;
+                Info.u32ClientID = pInfo->u32ClientID;
+                VbglR0HGCMInternalDisconnect(&Info, vgdrvHgcmAsyncWaitCallback, pDevExt, RT_INDEFINITE_WAIT);
+                return VERR_TOO_MANY_OPEN_FILES;
+            }
+        }
+        else
+            rc = pInfo->result;
+        if (pcbDataReturned)
+            *pcbDataReturned = sizeof(*pInfo);
+    }
+    return rc;
+}
+
+
+static int vgdrvIoCtl_HGCMDisconnect(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                                     VBoxGuestHGCMDisconnectInfo *pInfo, size_t *pcbDataReturned)
+{
+    /*
+     * Validate the client id and invalidate its entry while we're in the call.
+     */
+    int             rc;
+    const uint32_t  u32ClientId = pInfo->u32ClientID;
+    unsigned        i;
+    RTSpinlockAcquire(pDevExt->SessionSpinlock);
+    for (i = 0; i < RT_ELEMENTS(pSession->aHGCMClientIds); i++)
+        if (pSession->aHGCMClientIds[i] == u32ClientId)
+        {
+            pSession->aHGCMClientIds[i] = UINT32_MAX;
+            break;
+        }
+    RTSpinlockRelease(pDevExt->SessionSpinlock);
+    if (i >= RT_ELEMENTS(pSession->aHGCMClientIds))
+    {
+        LogRelMax(32, ("VBOXGUEST_IOCTL_HGCM_DISCONNECT: u32Client=%RX32\n", u32ClientId));
+        return VERR_INVALID_HANDLE;
+    }
+
+    /*
+     * The VbglHGCMConnect call will invoke the callback if the HGCM
+     * call is performed in an ASYNC fashion. The function is not able
+     * to deal with cancelled requests.
+     */
+    Log(("VBOXGUEST_IOCTL_HGCM_DISCONNECT: u32Client=%RX32\n", pInfo->u32ClientID));
+    rc = VbglR0HGCMInternalDisconnect(pInfo, vgdrvHgcmAsyncWaitCallback, pDevExt, RT_INDEFINITE_WAIT);
+    if (RT_SUCCESS(rc))
+    {
+        LogFlow(("VBOXGUEST_IOCTL_HGCM_DISCONNECT: result=%Rrc\n", pInfo->result));
+        if (pcbDataReturned)
+            *pcbDataReturned = sizeof(*pInfo);
+    }
+
+    /* Update the client id array according to the result. */
+    RTSpinlockAcquire(pDevExt->SessionSpinlock);
+    if (pSession->aHGCMClientIds[i] == UINT32_MAX)
+        pSession->aHGCMClientIds[i] = RT_SUCCESS(rc) && RT_SUCCESS(pInfo->result) ? 0 : u32ClientId;
+    RTSpinlockRelease(pDevExt->SessionSpinlock);
+
+    return rc;
+}
+
+
+static int vgdrvIoCtl_HGCMCall(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, VBoxGuestHGCMCallInfo *pInfo,
+                               uint32_t cMillies, bool fInterruptible, bool f32bit, bool fUserData,
+                               size_t cbExtra, size_t cbData, size_t *pcbDataReturned)
+{
+    const uint32_t  u32ClientId = pInfo->u32ClientID;
+    uint32_t        fFlags;
+    size_t          cbActual;
+    unsigned        i;
+    int             rc;
+
+    /*
+     * Some more validations.
+     */
+    if (pInfo->cParms > 4096) /* (Just make sure it doesn't overflow the next check.) */
+    {
+        LogRel(("VBOXGUEST_IOCTL_HGCM_CALL: cParm=%RX32 is not sane\n", pInfo->cParms));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    cbActual = cbExtra + sizeof(*pInfo);
+#ifdef RT_ARCH_AMD64
+    if (f32bit)
+        cbActual += pInfo->cParms * sizeof(HGCMFunctionParameter32);
+    else
+#endif
+        cbActual += pInfo->cParms * sizeof(HGCMFunctionParameter);
+    if (cbData < cbActual)
+    {
+        LogRel(("VBOXGUEST_IOCTL_HGCM_CALL: cbData=%#zx (%zu) required size is %#zx (%zu)\n",
+               cbData, cbData, cbActual, cbActual));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    /*
+     * Validate the client id.
+     */
+    RTSpinlockAcquire(pDevExt->SessionSpinlock);
+    for (i = 0; i < RT_ELEMENTS(pSession->aHGCMClientIds); i++)
+        if (pSession->aHGCMClientIds[i] == u32ClientId)
+            break;
+    RTSpinlockRelease(pDevExt->SessionSpinlock);
+    if (RT_UNLIKELY(i >= RT_ELEMENTS(pSession->aHGCMClientIds)))
+    {
+        LogRelMax(32, ("VBOXGUEST_IOCTL_HGCM_CALL: Invalid handle. u32Client=%RX32\n", u32ClientId));
+        return VERR_INVALID_HANDLE;
+    }
+
+    /*
+     * The VbglHGCMCall call will invoke the callback if the HGCM
+     * call is performed in an ASYNC fashion. This function can
+     * deal with cancelled requests, so we let user more requests
+     * be interruptible (should add a flag for this later I guess).
+     */
+    LogFlow(("VBOXGUEST_IOCTL_HGCM_CALL: u32Client=%RX32\n", pInfo->u32ClientID));
+    fFlags = !fUserData && pSession->R0Process == NIL_RTR0PROCESS ? VBGLR0_HGCMCALL_F_KERNEL : VBGLR0_HGCMCALL_F_USER;
+    uint32_t cbInfo = (uint32_t)(cbData - cbExtra);
+#ifdef RT_ARCH_AMD64
+    if (f32bit)
+    {
+        if (fInterruptible)
+            rc = VbglR0HGCMInternalCall32(pInfo, cbInfo, fFlags, vgdrvHgcmAsyncWaitCallbackInterruptible, pDevExt, cMillies);
+        else
+            rc = VbglR0HGCMInternalCall32(pInfo, cbInfo, fFlags, vgdrvHgcmAsyncWaitCallback, pDevExt, cMillies);
+    }
+    else
+#endif
+    {
+        if (fInterruptible)
+            rc = VbglR0HGCMInternalCall(pInfo, cbInfo, fFlags, vgdrvHgcmAsyncWaitCallbackInterruptible, pDevExt, cMillies);
+        else
+            rc = VbglR0HGCMInternalCall(pInfo, cbInfo, fFlags, vgdrvHgcmAsyncWaitCallback, pDevExt, cMillies);
+    }
+    if (RT_SUCCESS(rc))
+    {
+        LogFlow(("VBOXGUEST_IOCTL_HGCM_CALL: result=%Rrc\n", pInfo->result));
+        if (pcbDataReturned)
+            *pcbDataReturned = cbActual;
+    }
+    else
+    {
+        if (   rc != VERR_INTERRUPTED
+            && rc != VERR_TIMEOUT)
+            LogRelMax(32, ("VBOXGUEST_IOCTL_HGCM_CALL: %s Failed. rc=%Rrc.\n", f32bit ? "32" : "64", rc));
+        else
+            Log(("VBOXGUEST_IOCTL_HGCM_CALL: %s Failed. rc=%Rrc.\n", f32bit ? "32" : "64", rc));
+    }
+    return rc;
+}
+
+#endif /* VBOX_WITH_HGCM */
+
+/**
+ * Handle VBOXGUEST_IOCTL_CHECK_BALLOON from R3.
+ *
+ * Ask the host for the size of the balloon and try to set it accordingly.  If
+ * this approach fails because it's not supported, return with fHandleInR3 set
+ * and let the user land supply memory we can lock via the other ioctl.
+ *
+ * @returns VBox status code.
+ *
+ * @param   pDevExt             The device extension.
+ * @param   pSession            The session.
+ * @param   pInfo               The output buffer.
+ * @param   pcbDataReturned     Where to store the amount of returned data. Can
+ *                              be NULL.
+ */
+static int vgdrvIoCtl_CheckMemoryBalloon(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                                         VBoxGuestCheckBalloonInfo *pInfo, size_t *pcbDataReturned)
+{
+    VMMDevGetMemBalloonChangeRequest *pReq;
+    int rc;
+
+    LogFlow(("VBOXGUEST_IOCTL_CHECK_BALLOON:\n"));
+    rc = RTSemFastMutexRequest(pDevExt->MemBalloon.hMtx);
+    AssertRCReturn(rc, rc);
+
+    /*
+     * The first user trying to query/change the balloon becomes the
+     * owner and owns it until the session is closed (vgdrvCloseMemBalloon).
+     */
+    if (   pDevExt->MemBalloon.pOwner != pSession
+        && pDevExt->MemBalloon.pOwner == NULL)
+        pDevExt->MemBalloon.pOwner = pSession;
+
+    if (pDevExt->MemBalloon.pOwner == pSession)
+    {
+        rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(VMMDevGetMemBalloonChangeRequest), VMMDevReq_GetMemBalloonChangeRequest);
+        if (RT_SUCCESS(rc))
+        {
+            /*
+             * This is a response to that event. Setting this bit means that
+             * we request the value from the host and change the guest memory
+             * balloon according to this value.
+             */
+            pReq->eventAck = VMMDEV_EVENT_BALLOON_CHANGE_REQUEST;
+            rc = VbglGRPerform(&pReq->header);
+            if (RT_SUCCESS(rc))
+            {
+                Assert(pDevExt->MemBalloon.cMaxChunks == pReq->cPhysMemChunks || pDevExt->MemBalloon.cMaxChunks == 0);
+                pDevExt->MemBalloon.cMaxChunks = pReq->cPhysMemChunks;
+
+                pInfo->cBalloonChunks = pReq->cBalloonChunks;
+                pInfo->fHandleInR3    = false;
+
+                rc = vgdrvSetBalloonSizeKernel(pDevExt, pReq->cBalloonChunks, &pInfo->fHandleInR3);
+                /* Ignore various out of memory failures. */
+                if (   rc == VERR_NO_MEMORY
+                    || rc == VERR_NO_PHYS_MEMORY
+                    || rc == VERR_NO_CONT_MEMORY)
+                    rc = VINF_SUCCESS;
+
+                if (pcbDataReturned)
+                    *pcbDataReturned = sizeof(VBoxGuestCheckBalloonInfo);
+            }
+            else
+                LogRel(("VBOXGUEST_IOCTL_CHECK_BALLOON: VbglGRPerform failed. rc=%Rrc\n", rc));
+            VbglGRFree(&pReq->header);
+        }
+    }
+    else
+        rc = VERR_PERMISSION_DENIED;
+
+    RTSemFastMutexRelease(pDevExt->MemBalloon.hMtx);
+    LogFlow(("VBOXGUEST_IOCTL_CHECK_BALLOON returns %Rrc\n", rc));
+    return rc;
+}
+
+
+/**
+ * Handle a request for changing the memory balloon.
+ *
+ * @returns VBox status code.
+ *
+ * @param   pDevExt             The device extention.
+ * @param   pSession            The session.
+ * @param   pInfo               The change request structure (input).
+ * @param   pcbDataReturned     Where to store the amount of returned data. Can
+ *                              be NULL.
+ */
+static int vgdrvIoCtl_ChangeMemoryBalloon(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                                          VBoxGuestChangeBalloonInfo *pInfo, size_t *pcbDataReturned)
+{
+    int rc;
+    LogFlow(("VBOXGUEST_IOCTL_CHANGE_BALLOON: fInflate=%RTbool u64ChunkAddr=%#RX64\n", pInfo->fInflate, pInfo->u64ChunkAddr));
+
+    rc = RTSemFastMutexRequest(pDevExt->MemBalloon.hMtx);
+    AssertRCReturn(rc, rc);
+
+    if (!pDevExt->MemBalloon.fUseKernelAPI)
+    {
+        /*
+         * The first user trying to query/change the balloon becomes the
+         * owner and owns it until the session is closed (vgdrvCloseMemBalloon).
+         */
+        if (   pDevExt->MemBalloon.pOwner != pSession
+            && pDevExt->MemBalloon.pOwner == NULL)
+            pDevExt->MemBalloon.pOwner = pSession;
+
+        if (pDevExt->MemBalloon.pOwner == pSession)
+        {
+            rc = vgdrvSetBalloonSizeFromUser(pDevExt, pSession, pInfo->u64ChunkAddr, !!pInfo->fInflate);
+            if (pcbDataReturned)
+                *pcbDataReturned = 0;
+        }
+        else
+            rc = VERR_PERMISSION_DENIED;
+    }
+    else
+        rc = VERR_PERMISSION_DENIED;
+
+    RTSemFastMutexRelease(pDevExt->MemBalloon.hMtx);
+    return rc;
+}
+
+
+/**
+ * Handle a request for writing a core dump of the guest on the host.
+ *
+ * @returns VBox status code.
+ *
+ * @param pDevExt               The device extension.
+ * @param pInfo                 The output buffer.
+ */
+static int vgdrvIoCtl_WriteCoreDump(PVBOXGUESTDEVEXT pDevExt, VBoxGuestWriteCoreDump *pInfo)
+{
+    VMMDevReqWriteCoreDump *pReq = NULL;
+    int rc;
+    LogFlow(("VBOXGUEST_IOCTL_WRITE_CORE_DUMP\n"));
+    RT_NOREF1(pDevExt);
+
+    rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_WriteCoreDump);
+    if (RT_SUCCESS(rc))
+    {
+        pReq->fFlags = pInfo->fFlags;
+        rc = VbglGRPerform(&pReq->header);
+        if (RT_FAILURE(rc))
+            Log(("VBOXGUEST_IOCTL_WRITE_CORE_DUMP: VbglGRPerform failed, rc=%Rrc!\n", rc));
+
+        VbglGRFree(&pReq->header);
+    }
+    else
+        Log(("VBOXGUEST_IOCTL_WRITE_CORE_DUMP: failed to allocate %u (%#x) bytes to cache the request. rc=%Rrc!!\n",
+             sizeof(*pReq), sizeof(*pReq), rc));
+    return rc;
+}
+
+
+/**
+ * Guest backdoor logging.
+ *
+ * @returns VBox status code.
+ *
+ * @param   pDevExt             The device extension.
+ * @param   pch                 The log message (need not be NULL terminated).
+ * @param   cbData              Size of the buffer.
+ * @param   pcbDataReturned     Where to store the amount of returned data. Can be NULL.
+ * @param   fUserSession        Copy of VBOXGUESTSESSION::fUserSession for the
+ *                              call.  True normal user, false root user.
+ */
+static int vgdrvIoCtl_Log(PVBOXGUESTDEVEXT pDevExt, const char *pch, size_t cbData, size_t *pcbDataReturned, bool fUserSession)
+{
+    if (pDevExt->fLoggingEnabled)
+        RTLogBackdoorPrintf("%.*s", cbData, pch);
+    else if (!fUserSession)
+        LogRel(("%.*s", cbData, pch));
+    else
+        Log(("%.*s", cbData, pch));
+    if (pcbDataReturned)
+        *pcbDataReturned = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @name Guest Capabilities, Mouse Status and Event Filter
+ * @{
+ */
+
+/**
+ * Clears a bit usage tracker (init time).
+ *
+ * @param   pTracker            The tracker to clear.
+ */
+static void vgdrvBitUsageTrackerClear(PVBOXGUESTBITUSAGETRACER pTracker)
+{
+    uint32_t iBit;
+    AssertCompile(sizeof(pTracker->acPerBitUsage) == 32 * sizeof(uint32_t));
+
+    for (iBit = 0; iBit < 32; iBit++)
+        pTracker->acPerBitUsage[iBit] = 0;
+    pTracker->fMask = 0;
+}
+
+
+#ifdef VBOX_STRICT
+/**
+ * Checks that pTracker->fMask is correct and that the usage values are within
+ * the valid range.
+ *
+ * @param   pTracker            The tracker.
+ * @param   cMax                Max valid usage value.
+ * @param   pszWhat             Identifies the tracker in assertions.
+ */
+static void vgdrvBitUsageTrackerCheckMask(PCVBOXGUESTBITUSAGETRACER pTracker, uint32_t cMax, const char *pszWhat)
+{
+    uint32_t fMask = 0;
+    uint32_t iBit;
+    AssertCompile(sizeof(pTracker->acPerBitUsage) == 32 * sizeof(uint32_t));
+
+    for (iBit = 0; iBit < 32; iBit++)
+        if (pTracker->acPerBitUsage[iBit])
+        {
+            fMask |= RT_BIT_32(iBit);
+            AssertMsg(pTracker->acPerBitUsage[iBit] <= cMax,
+                      ("%s: acPerBitUsage[%u]=%#x cMax=%#x\n", pszWhat, iBit, pTracker->acPerBitUsage[iBit], cMax));
+        }
+
+    AssertMsg(fMask == pTracker->fMask, ("%s: %#x vs %#x\n", pszWhat, fMask, pTracker->fMask));
+}
+#endif
+
+
+/**
+ * Applies a change to the bit usage tracker.
+ *
+ *
+ * @returns true if the mask changed, false if not.
+ * @param   pTracker            The bit usage tracker.
+ * @param   fChanged            The bits to change.
+ * @param   fPrevious           The previous value of the bits.
+ * @param   cMax                The max valid usage value for assertions.
+ * @param   pszWhat             Identifies the tracker in assertions.
+ */
+static bool vgdrvBitUsageTrackerChange(PVBOXGUESTBITUSAGETRACER pTracker, uint32_t fChanged, uint32_t fPrevious,
+                                       uint32_t cMax, const char *pszWhat)
+{
+    bool fGlobalChange = false;
+    AssertCompile(sizeof(pTracker->acPerBitUsage) == 32 * sizeof(uint32_t));
+
+    while (fChanged)
+    {
+        uint32_t const iBit     = ASMBitFirstSetU32(fChanged) - 1;
+        uint32_t const fBitMask = RT_BIT_32(iBit);
+        Assert(iBit < 32); Assert(fBitMask & fChanged);
+
+        if (fBitMask & fPrevious)
+        {
+            pTracker->acPerBitUsage[iBit] -= 1;
+            AssertMsg(pTracker->acPerBitUsage[iBit] <= cMax,
+                      ("%s: acPerBitUsage[%u]=%#x cMax=%#x\n", pszWhat, iBit, pTracker->acPerBitUsage[iBit], cMax));
+            if (pTracker->acPerBitUsage[iBit] == 0)
+            {
+                fGlobalChange = true;
+                pTracker->fMask &= ~fBitMask;
+            }
+        }
+        else
+        {
+            pTracker->acPerBitUsage[iBit] += 1;
+            AssertMsg(pTracker->acPerBitUsage[iBit] > 0 && pTracker->acPerBitUsage[iBit] <= cMax,
+                      ("pTracker->acPerBitUsage[%u]=%#x cMax=%#x\n", pszWhat, iBit, pTracker->acPerBitUsage[iBit], cMax));
+            if (pTracker->acPerBitUsage[iBit] == 1)
+            {
+                fGlobalChange = true;
+                pTracker->fMask |= fBitMask;
+            }
+        }
+
+        fChanged &= ~fBitMask;
+    }
+
+#ifdef VBOX_STRICT
+    vgdrvBitUsageTrackerCheckMask(pTracker, cMax, pszWhat);
+#endif
+    NOREF(pszWhat); NOREF(cMax);
+    return fGlobalChange;
+}
+
+
+/**
+ * Init and termination worker for resetting the (host) event filter on the host
+ *
+ * @returns VBox status code.
+ * @param   pDevExt         The device extension.
+ * @param   fFixedEvents    Fixed events (init time).
+ */
+static int vgdrvResetEventFilterOnHost(PVBOXGUESTDEVEXT pDevExt, uint32_t fFixedEvents)
+{
+    VMMDevCtlGuestFilterMask *pReq;
+    int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_CtlGuestFilterMask);
+    if (RT_SUCCESS(rc))
+    {
+        pReq->u32NotMask = UINT32_MAX & ~fFixedEvents;
+        pReq->u32OrMask  = fFixedEvents;
+        rc = VbglGRPerform(&pReq->header);
+        if (RT_FAILURE(rc))
+            LogRelFunc(("failed with rc=%Rrc\n", rc));
+        VbglGRFree(&pReq->header);
+    }
+    RT_NOREF1(pDevExt);
+    return rc;
+}
+
+
+/**
+ * Changes the event filter mask for the given session.
+ *
+ * This is called in response to VBOXGUEST_IOCTL_CTL_FILTER_MASK as well as to
+ * do session cleanup.
+ *
+ * @returns VBox status code.
+ * @param   pDevExt             The device extension.
+ * @param   pSession            The session.
+ * @param   fOrMask             The events to add.
+ * @param   fNotMask            The events to remove.
+ * @param   fSessionTermination Set if we're called by the session cleanup code.
+ *                              This tweaks the error handling so we perform
+ *                              proper session cleanup even if the host
+ *                              misbehaves.
+ *
+ * @remarks Takes the session spinlock.
+ */
+static int vgdrvSetSessionEventFilter(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                                      uint32_t fOrMask, uint32_t fNotMask, bool fSessionTermination)
+{
+    VMMDevCtlGuestFilterMask   *pReq;
+    uint32_t                    fChanged;
+    uint32_t                    fPrevious;
+    int                         rc;
+
+    /*
+     * Preallocate a request buffer so we can do all in one go without leaving the spinlock.
+     */
+    rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_CtlGuestFilterMask);
+    if (RT_SUCCESS(rc))
+    { /* nothing */ }
+    else if (!fSessionTermination)
+    {
+        LogRel(("vgdrvSetSessionFilterMask: VbglGRAlloc failure: %Rrc\n", rc));
+        return rc;
+    }
+    else
+        pReq = NULL; /* Ignore failure, we must do session cleanup. */
+
+
+    RTSpinlockAcquire(pDevExt->SessionSpinlock);
+
+    /*
+     * Apply the changes to the session mask.
+     */
+    fPrevious = pSession->fEventFilter;
+    pSession->fEventFilter |= fOrMask;
+    pSession->fEventFilter &= ~fNotMask;
+
+    /*
+     * If anything actually changed, update the global usage counters.
+     */
+    fChanged = fPrevious ^ pSession->fEventFilter;
+    if (fChanged)
+    {
+        bool fGlobalChange = vgdrvBitUsageTrackerChange(&pDevExt->EventFilterTracker, fChanged, fPrevious,
+                                                        pDevExt->cSessions, "EventFilterTracker");
+
+        /*
+         * If there are global changes, update the event filter on the host.
+         */
+        if (fGlobalChange || pDevExt->fEventFilterHost == UINT32_MAX)
+        {
+            Assert(pReq || fSessionTermination);
+            if (pReq)
+            {
+                pReq->u32OrMask = pDevExt->fFixedEvents | pDevExt->EventFilterTracker.fMask;
+                if (pReq->u32OrMask == pDevExt->fEventFilterHost)
+                    rc = VINF_SUCCESS;
+                else
+                {
+                    pDevExt->fEventFilterHost = pReq->u32OrMask;
+                    pReq->u32NotMask = ~pReq->u32OrMask;
+                    rc = VbglGRPerform(&pReq->header);
+                    if (RT_FAILURE(rc))
+                    {
+                        /*
+                         * Failed, roll back (unless it's session termination time).
+                         */
+                        pDevExt->fEventFilterHost = UINT32_MAX;
+                        if (!fSessionTermination)
+                        {
+                            vgdrvBitUsageTrackerChange(&pDevExt->EventFilterTracker, fChanged, pSession->fEventFilter,
+                                                       pDevExt->cSessions, "EventFilterTracker");
+                            pSession->fEventFilter = fPrevious;
+                        }
+                    }
+                }
+            }
+            else
+                rc = VINF_SUCCESS;
+        }
+    }
+
+    RTSpinlockRelease(pDevExt->SessionSpinlock);
+    if (pReq)
+        VbglGRFree(&pReq->header);
+    return rc;
+}
+
+
+/**
+ * Handle VBOXGUEST_IOCTL_CTL_FILTER_MASK.
+ *
+ * @returns VBox status code.
+ *
+ * @param   pDevExt             The device extension.
+ * @param   pSession            The session.
+ * @param   pInfo               The request.
+ */
+static int vgdrvIoCtl_CtlFilterMask(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, VBoxGuestFilterMaskInfo *pInfo)
+{
+    LogFlow(("VBOXGUEST_IOCTL_CTL_FILTER_MASK: or=%#x not=%#x\n", pInfo->u32OrMask, pInfo->u32NotMask));
+
+    if ((pInfo->u32OrMask | pInfo->u32NotMask) & ~VMMDEV_EVENT_VALID_EVENT_MASK)
+    {
+        Log(("VBOXGUEST_IOCTL_CTL_FILTER_MASK: or=%#x not=%#x: Invalid masks!\n", pInfo->u32OrMask, pInfo->u32NotMask));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    return vgdrvSetSessionEventFilter(pDevExt, pSession, pInfo->u32OrMask, pInfo->u32NotMask, false /*fSessionTermination*/);
+}
+
+
+/**
+ * Init and termination worker for set mouse feature status to zero on the host.
+ *
+ * @returns VBox status code.
+ * @param   pDevExt         The device extension.
+ */
+static int vgdrvResetMouseStatusOnHost(PVBOXGUESTDEVEXT pDevExt)
+{
+    VMMDevReqMouseStatus *pReq;
+    int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_SetMouseStatus);
+    if (RT_SUCCESS(rc))
+    {
+        pReq->mouseFeatures = 0;
+        pReq->pointerXPos   = 0;
+        pReq->pointerYPos   = 0;
+        rc = VbglGRPerform(&pReq->header);
+        if (RT_FAILURE(rc))
+            LogRelFunc(("failed with rc=%Rrc\n", rc));
+        VbglGRFree(&pReq->header);
+    }
+    RT_NOREF1(pDevExt);
+    return rc;
+}
+
+
+/**
+ * Changes the mouse status mask for the given session.
+ *
+ * This is called in response to VBOXGUEST_IOCTL_SET_MOUSE_STATUS as well as to
+ * do session cleanup.
+ *
+ * @returns VBox status code.
+ * @param   pDevExt             The device extension.
+ * @param   pSession            The session.
+ * @param   fOrMask             The status flags to add.
+ * @param   fNotMask            The status flags to remove.
+ * @param   fSessionTermination Set if we're called by the session cleanup code.
+ *                              This tweaks the error handling so we perform
+ *                              proper session cleanup even if the host
+ *                              misbehaves.
+ *
+ * @remarks Takes the session spinlock.
+ */
+static int vgdrvSetSessionMouseStatus(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                                      uint32_t fOrMask, uint32_t fNotMask, bool fSessionTermination)
+{
+    VMMDevReqMouseStatus   *pReq;
+    uint32_t                fChanged;
+    uint32_t                fPrevious;
+    int                     rc;
+
+    /*
+     * Preallocate a request buffer so we can do all in one go without leaving the spinlock.
+     */
+    rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_SetMouseStatus);
+    if (RT_SUCCESS(rc))
+    { /* nothing */ }
+    else if (!fSessionTermination)
+    {
+        LogRel(("vgdrvSetSessionMouseStatus: VbglGRAlloc failure: %Rrc\n", rc));
+        return rc;
+    }
+    else
+        pReq = NULL; /* Ignore failure, we must do session cleanup. */
+
+
+    RTSpinlockAcquire(pDevExt->SessionSpinlock);
+
+    /*
+     * Apply the changes to the session mask.
+     */
+    fPrevious = pSession->fMouseStatus;
+    pSession->fMouseStatus |= fOrMask;
+    pSession->fMouseStatus &= ~fNotMask;
+
+    /*
+     * If anything actually changed, update the global usage counters.
+     */
+    fChanged = fPrevious ^ pSession->fMouseStatus;
+    if (fChanged)
+    {
+        bool fGlobalChange = vgdrvBitUsageTrackerChange(&pDevExt->MouseStatusTracker, fChanged, fPrevious,
+                                                        pDevExt->cSessions, "MouseStatusTracker");
+
+        /*
+         * If there are global changes, update the event filter on the host.
+         */
+        if (fGlobalChange || pDevExt->fMouseStatusHost == UINT32_MAX)
+        {
+            Assert(pReq || fSessionTermination);
+            if (pReq)
+            {
+                pReq->mouseFeatures = pDevExt->MouseStatusTracker.fMask;
+                if (pReq->mouseFeatures == pDevExt->fMouseStatusHost)
+                    rc = VINF_SUCCESS;
+                else
+                {
+                    pDevExt->fMouseStatusHost = pReq->mouseFeatures;
+                    pReq->pointerXPos = 0;
+                    pReq->pointerYPos = 0;
+                    rc = VbglGRPerform(&pReq->header);
+                    if (RT_FAILURE(rc))
+                    {
+                        /*
+                         * Failed, roll back (unless it's session termination time).
+                         */
+                        pDevExt->fMouseStatusHost = UINT32_MAX;
+                        if (!fSessionTermination)
+                        {
+                            vgdrvBitUsageTrackerChange(&pDevExt->MouseStatusTracker, fChanged, pSession->fMouseStatus,
+                                                       pDevExt->cSessions, "MouseStatusTracker");
+                            pSession->fMouseStatus = fPrevious;
+                        }
+                    }
+                }
+            }
+            else
+                rc = VINF_SUCCESS;
+        }
+    }
+
+    RTSpinlockRelease(pDevExt->SessionSpinlock);
+    if (pReq)
+        VbglGRFree(&pReq->header);
+    return rc;
+}
+
+
+/**
+ * Sets the mouse status features for this session and updates them globally.
+ *
+ * @returns VBox status code.
+ *
+ * @param   pDevExt             The device extention.
+ * @param   pSession            The session.
+ * @param   fFeatures           New bitmap of enabled features.
+ */
+static int vgdrvIoCtl_SetMouseStatus(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fFeatures)
+{
+    LogFlow(("VBOXGUEST_IOCTL_SET_MOUSE_STATUS: features=%#x\n", fFeatures));
+
+    if (fFeatures & ~VMMDEV_MOUSE_GUEST_MASK)
+        return VERR_INVALID_PARAMETER;
+
+    return vgdrvSetSessionMouseStatus(pDevExt, pSession, fFeatures, ~fFeatures, false /*fSessionTermination*/);
+}
+
+
+/**
+ * Return the mask of VMM device events that this session is allowed to see (wrt
+ * to "acquire" mode guest capabilities).
+ *
+ * The events associated with guest capabilities in "acquire" mode will be
+ * restricted to sessions which has acquired the respective capabilities.
+ * If someone else tries to wait for acquired events, they won't be woken up
+ * when the event becomes pending.  Should some other thread in the session
+ * acquire the capability while the corresponding event is pending, the waiting
+ * thread will woken up.
+ *
+ * @returns Mask of events valid for the given session.
+ * @param   pDevExt             The device extension.
+ * @param   pSession            The session.
+ *
+ * @remarks Needs only be called when dispatching events in the
+ *          VBOXGUEST_ACQUIRE_STYLE_EVENTS mask.
+ */
+static uint32_t vgdrvGetAllowedEventMaskForSession(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession)
+{
+    uint32_t fAcquireModeGuestCaps;
+    uint32_t fAcquiredGuestCaps;
+    uint32_t fAllowedEvents;
+
+    /*
+     * Note! Reads pSession->fAcquiredGuestCaps and pDevExt->fAcquireModeGuestCaps
+     *       WITHOUT holding VBOXGUESTDEVEXT::SessionSpinlock.
+     */
+    fAcquireModeGuestCaps = ASMAtomicUoReadU32(&pDevExt->fAcquireModeGuestCaps);
+    if (fAcquireModeGuestCaps == 0)
+        return VMMDEV_EVENT_VALID_EVENT_MASK;
+    fAcquiredGuestCaps = ASMAtomicUoReadU32(&pSession->fAcquiredGuestCaps);
+
+    /*
+     * Calculate which events to allow according to the cap config and caps
+     * acquired by the session.
+     */
+    fAllowedEvents = VMMDEV_EVENT_VALID_EVENT_MASK;
+    if (   !(fAcquiredGuestCaps   & VMMDEV_GUEST_SUPPORTS_GRAPHICS)
+        && (fAcquireModeGuestCaps & VMMDEV_GUEST_SUPPORTS_GRAPHICS))
+        fAllowedEvents &= ~VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST;
+
+    if (   !(fAcquiredGuestCaps   & VMMDEV_GUEST_SUPPORTS_SEAMLESS)
+        && (fAcquireModeGuestCaps & VMMDEV_GUEST_SUPPORTS_SEAMLESS))
+        fAllowedEvents &= ~VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST;
+
+    return fAllowedEvents;
+}
+
+
+/**
+ * Init and termination worker for set guest capabilities to zero on the host.
+ *
+ * @returns VBox status code.
+ * @param   pDevExt         The device extension.
+ */
+static int vgdrvResetCapabilitiesOnHost(PVBOXGUESTDEVEXT pDevExt)
+{
+    VMMDevReqGuestCapabilities2 *pReq;
+    int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_SetGuestCapabilities);
+    if (RT_SUCCESS(rc))
+    {
+        pReq->u32NotMask = UINT32_MAX;
+        pReq->u32OrMask  = 0;
+        rc = VbglGRPerform(&pReq->header);
+
+        if (RT_FAILURE(rc))
+            LogRelFunc(("failed with rc=%Rrc\n", rc));
+        VbglGRFree(&pReq->header);
+    }
+    RT_NOREF1(pDevExt);
+    return rc;
+}
+
+
+/**
+ * Sets the guest capabilities to the host while holding the lock.
+ *
+ * This will ASSUME that we're the ones in charge of the mask, so
+ * we'll simply clear all bits we don't set.
+ *
+ * @returns VBox status code.
+ * @param   pDevExt             The device extension.
+ * @param   pReq                The request.
+ */
+static int vgdrvUpdateCapabilitiesOnHostWithReqAndLock(PVBOXGUESTDEVEXT pDevExt, VMMDevReqGuestCapabilities2 *pReq)
+{
+    int rc;
+
+    pReq->u32OrMask = pDevExt->fAcquiredGuestCaps | pDevExt->SetGuestCapsTracker.fMask;
+    if (pReq->u32OrMask == pDevExt->fGuestCapsHost)
+        rc = VINF_SUCCESS;
+    else
+    {
+        pDevExt->fGuestCapsHost = pReq->u32OrMask;
+        pReq->u32NotMask = ~pReq->u32OrMask;
+        rc = VbglGRPerform(&pReq->header);
+        if (RT_FAILURE(rc))
+            pDevExt->fGuestCapsHost = UINT32_MAX;
+    }
+
+    return rc;
+}
+
+
+/**
+ * Switch a set of capabilities into "acquire" mode and (maybe) acquire them for
+ * the given session.
+ *
+ * This is called in response to VBOXGUEST_IOCTL_GUEST_CAPS_ACQUIRE as well as
+ * to do session cleanup.
+ *
+ * @returns VBox status code.
+ * @param   pDevExt             The device extension.
+ * @param   pSession            The session.
+ * @param   fOrMask             The capabilities to add .
+ * @param   fNotMask            The capabilities to remove.  Ignored in
+ *                              VBOXGUESTCAPSACQUIRE_FLAGS_CONFIG_ACQUIRE_MODE.
+ * @param   enmFlags            Confusing operation modifier.
+ *                              VBOXGUESTCAPSACQUIRE_FLAGS_NONE means to both
+ *                              configure and acquire/release the capabilities.
+ *                              VBOXGUESTCAPSACQUIRE_FLAGS_CONFIG_ACQUIRE_MODE
+ *                              means only configure capabilities in the
+ *                              @a fOrMask capabilities for "acquire" mode.
+ * @param   fSessionTermination Set if we're called by the session cleanup code.
+ *                              This tweaks the error handling so we perform
+ *                              proper session cleanup even if the host
+ *                              misbehaves.
+ *
+ * @remarks Takes both the session and event spinlocks.
+ */
+static int vgdrvAcquireSessionCapabilities(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                                           uint32_t fOrMask, uint32_t fNotMask, VBOXGUESTCAPSACQUIRE_FLAGS enmFlags,
+                                           bool fSessionTermination)
+{
+    uint32_t fCurrentOwnedCaps;
+    uint32_t fSessionRemovedCaps;
+    uint32_t fSessionAddedCaps;
+    uint32_t fOtherConflictingCaps;
+    VMMDevReqGuestCapabilities2 *pReq = NULL;
+    int rc;
+
+
+    /*
+     * Validate and adjust input.
+     */
+    if (fOrMask & ~(  VMMDEV_GUEST_SUPPORTS_SEAMLESS
+                    | VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING
+                    | VMMDEV_GUEST_SUPPORTS_GRAPHICS ) )
+    {
+        LogRel(("vgdrvAcquireSessionCapabilities: pSession=%p fOrMask=%#x fNotMask=%#x enmFlags=%#x -- invalid fOrMask\n",
+                pSession, fOrMask, fNotMask, enmFlags));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    if (   enmFlags != VBOXGUESTCAPSACQUIRE_FLAGS_CONFIG_ACQUIRE_MODE
+        && enmFlags != VBOXGUESTCAPSACQUIRE_FLAGS_NONE)
+    {
+        LogRel(("vgdrvAcquireSessionCapabilities: pSession=%p fOrMask=%#x fNotMask=%#x enmFlags=%#x: invalid enmFlags %d\n",
+                pSession, fOrMask, fNotMask, enmFlags));
+        return VERR_INVALID_PARAMETER;
+    }
+    Assert(!fOrMask || !fSessionTermination);
+
+    /* The fNotMask no need to have all values valid, invalid ones will simply be ignored. */
+    fNotMask &= ~fOrMask;
+
+    /*
+     * Preallocate a update request if we're about to do more than just configure
+     * the capability mode.
+     */
+    if (enmFlags != VBOXGUESTCAPSACQUIRE_FLAGS_CONFIG_ACQUIRE_MODE)
+    {
+        rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_SetGuestCapabilities);
+        if (RT_SUCCESS(rc))
+        { /* do nothing */ }
+        else if (!fSessionTermination)
+        {
+            LogRel(("vgdrvAcquireSessionCapabilities: pSession=%p fOrMask=%#x fNotMask=%#x enmFlags=%#x: VbglGRAlloc failure: %Rrc\n",
+                    pSession, fOrMask, fNotMask, enmFlags, rc));
+            return rc;
+        }
+        else
+            pReq = NULL; /* Ignore failure, we must do session cleanup. */
+    }
+
+    /*
+     * Try switch the capabilities in the OR mask into "acquire" mode.
+     *
+     * Note! We currently ignore anyone which may already have "set" the capabilities
+     *       in fOrMask.  Perhaps not the best way to handle it, but it's simple...
+     */
+    RTSpinlockAcquire(pDevExt->EventSpinlock);
+
+    if (!(pDevExt->fSetModeGuestCaps & fOrMask))
+        pDevExt->fAcquireModeGuestCaps |= fOrMask;
+    else
+    {
+        RTSpinlockRelease(pDevExt->EventSpinlock);
+
+        if (pReq)
+            VbglGRFree(&pReq->header);
+        AssertMsgFailed(("Trying to change caps mode: %#x\n", fOrMask));
+        LogRel(("vgdrvAcquireSessionCapabilities: pSession=%p fOrMask=%#x fNotMask=%#x enmFlags=%#x: calling caps acquire for set caps\n",
+                pSession, fOrMask, fNotMask, enmFlags));
+        return VERR_INVALID_STATE;
+    }
+
+    /*
+     * If we only wanted to switch the capabilities into "acquire" mode, we're done now.
+     */
+    if (enmFlags & VBOXGUESTCAPSACQUIRE_FLAGS_CONFIG_ACQUIRE_MODE)
+    {
+        RTSpinlockRelease(pDevExt->EventSpinlock);
+
+        Assert(!pReq);
+        Log(("vgdrvAcquireSessionCapabilities: pSession=%p fOrMask=%#x fNotMask=%#x enmFlags=%#x: configured acquire caps: 0x%x\n",
+             pSession, fOrMask, fNotMask, enmFlags));
+        return VINF_SUCCESS;
+    }
+    Assert(pReq || fSessionTermination);
+
+    /*
+     * Caller wants to acquire/release the capabilities too.
+     *
+     * Note! The mode change of the capabilities above won't be reverted on
+     *       failure, this is intentional.
+     */
+    fCurrentOwnedCaps      = pSession->fAcquiredGuestCaps;
+    fSessionRemovedCaps    = fCurrentOwnedCaps & fNotMask;
+    fSessionAddedCaps      = fOrMask & ~fCurrentOwnedCaps;
+    fOtherConflictingCaps  = pDevExt->fAcquiredGuestCaps & ~fCurrentOwnedCaps;
+    fOtherConflictingCaps &= fSessionAddedCaps;
+
+    if (!fOtherConflictingCaps)
+    {
+        if (fSessionAddedCaps)
+        {
+            pSession->fAcquiredGuestCaps |= fSessionAddedCaps;
+            pDevExt->fAcquiredGuestCaps  |= fSessionAddedCaps;
+        }
+
+        if (fSessionRemovedCaps)
+        {
+            pSession->fAcquiredGuestCaps &= ~fSessionRemovedCaps;
+            pDevExt->fAcquiredGuestCaps  &= ~fSessionRemovedCaps;
+        }
+
+        /*
+         * If something changes (which is very likely), tell the host.
+         */
+        if (fSessionAddedCaps || fSessionRemovedCaps || pDevExt->fGuestCapsHost == UINT32_MAX)
+        {
+            Assert(pReq || fSessionTermination);
+            if (pReq)
+            {
+                rc = vgdrvUpdateCapabilitiesOnHostWithReqAndLock(pDevExt, pReq);
+                if (RT_FAILURE(rc) && !fSessionTermination)
+                {
+                    /* Failed, roll back. */
+                    if (fSessionAddedCaps)
+                    {
+                        pSession->fAcquiredGuestCaps &= ~fSessionAddedCaps;
+                        pDevExt->fAcquiredGuestCaps  &= ~fSessionAddedCaps;
+                    }
+                    if (fSessionRemovedCaps)
+                    {
+                        pSession->fAcquiredGuestCaps |= fSessionRemovedCaps;
+                        pDevExt->fAcquiredGuestCaps  |= fSessionRemovedCaps;
+                    }
+
+                    RTSpinlockRelease(pDevExt->EventSpinlock);
+                    LogRel(("vgdrvAcquireSessionCapabilities: vgdrvUpdateCapabilitiesOnHostWithReqAndLock failed: rc=%Rrc\n", rc));
+                    VbglGRFree(&pReq->header);
+                    return rc;
+                }
+            }
+        }
+    }
+    else
+    {
+        RTSpinlockRelease(pDevExt->EventSpinlock);
+
+        Log(("vgdrvAcquireSessionCapabilities: Caps %#x were busy\n", fOtherConflictingCaps));
+        VbglGRFree(&pReq->header);
+        return VERR_RESOURCE_BUSY;
+    }
+
+    RTSpinlockRelease(pDevExt->EventSpinlock);
+    if (pReq)
+        VbglGRFree(&pReq->header);
+
+    /*
+     * If we added a capability, check if that means some other thread in our
+     * session should be unblocked because there are events pending.
+     *
+     * HACK ALERT! When the seamless support capability is added we generate a
+     *             seamless change event so that the ring-3 client can sync with
+     *             the seamless state. Although this introduces a spurious
+     *             wakeups of the ring-3 client, it solves the problem of client
+     *             state inconsistency in multiuser environment (on Windows).
+     */
+    if (fSessionAddedCaps)
+    {
+        uint32_t fGenFakeEvents = 0;
+        if (fSessionAddedCaps & VMMDEV_GUEST_SUPPORTS_SEAMLESS)
+            fGenFakeEvents |= VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST;
+
+        RTSpinlockAcquire(pDevExt->EventSpinlock);
+        if (fGenFakeEvents || pDevExt->f32PendingEvents)
+            vgdrvDispatchEventsLocked(pDevExt, fGenFakeEvents);
+        RTSpinlockRelease(pDevExt->EventSpinlock);
+
+#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
+        VGDrvCommonWaitDoWakeUps(pDevExt);
+#endif
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Handle VBOXGUEST_IOCTL_GUEST_CAPS_ACQUIRE.
+ *
+ * @returns VBox status code.
+ *
+ * @param   pDevExt             The device extension.
+ * @param   pSession            The session.
+ * @param   pAcquire            The request.
+ */
+static int vgdrvIoCtl_GuestCapsAcquire(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, VBoxGuestCapsAquire *pAcquire)
+{
+    int rc;
+    LogFlow(("VBOXGUEST_IOCTL_GUEST_CAPS_ACQUIRE: or=%#x not=%#x flags=%#x\n",
+             pAcquire->u32OrMask, pAcquire->u32NotMask, pAcquire->enmFlags));
+
+    rc = vgdrvAcquireSessionCapabilities(pDevExt, pSession, pAcquire->u32OrMask, pAcquire->u32NotMask, pAcquire->enmFlags,
+                                         false /*fSessionTermination*/);
+    if (RT_FAILURE(rc))
+        LogRel(("VGDrvCommonIoCtl: GUEST_CAPS_ACQUIRE failed rc=%Rrc\n", rc));
+    pAcquire->rc = rc;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Sets the guest capabilities for a session.
+ *
+ * @returns VBox status code.
+ * @param   pDevExt             The device extension.
+ * @param   pSession            The session.
+ * @param   fOrMask             The capabilities to add.
+ * @param   fNotMask            The capabilities to remove.
+ * @param   fSessionTermination Set if we're called by the session cleanup code.
+ *                              This tweaks the error handling so we perform
+ *                              proper session cleanup even if the host
+ *                              misbehaves.
+ *
+ * @remarks Takes the session spinlock.
+ */
+static int vgdrvSetSessionCapabilities(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                                       uint32_t fOrMask, uint32_t fNotMask, bool fSessionTermination)
+{
+    /*
+     * Preallocate a request buffer so we can do all in one go without leaving the spinlock.
+     */
+    VMMDevReqGuestCapabilities2 *pReq;
+    int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_SetGuestCapabilities);
+    if (RT_SUCCESS(rc))
+    { /* nothing */ }
+    else if (!fSessionTermination)
+    {
+        LogRel(("vgdrvSetSessionCapabilities: VbglGRAlloc failure: %Rrc\n", rc));
+        return rc;
+    }
+    else
+        pReq = NULL; /* Ignore failure, we must do session cleanup. */
+
+
+    RTSpinlockAcquire(pDevExt->SessionSpinlock);
+
+#ifndef VBOXGUEST_DISREGARD_ACQUIRE_MODE_GUEST_CAPS
+    /*
+     * Capabilities in "acquire" mode cannot be set via this API.
+     * (Acquire mode is only used on windows at the time of writing.)
+     */
+    if (!(fOrMask & pDevExt->fAcquireModeGuestCaps))
+#endif
+    {
+        /*
+         * Apply the changes to the session mask.
+         */
+        uint32_t fChanged;
+        uint32_t fPrevious = pSession->fCapabilities;
+        pSession->fCapabilities |= fOrMask;
+        pSession->fCapabilities &= ~fNotMask;
+
+        /*
+         * If anything actually changed, update the global usage counters.
+         */
+        fChanged = fPrevious ^ pSession->fCapabilities;
+        if (fChanged)
+        {
+            bool fGlobalChange = vgdrvBitUsageTrackerChange(&pDevExt->SetGuestCapsTracker, fChanged, fPrevious,
+                                                            pDevExt->cSessions, "SetGuestCapsTracker");
+
+            /*
+             * If there are global changes, update the capabilities on the host.
+             */
+            if (fGlobalChange || pDevExt->fGuestCapsHost == UINT32_MAX)
+            {
+                Assert(pReq || fSessionTermination);
+                if (pReq)
+                {
+                    rc = vgdrvUpdateCapabilitiesOnHostWithReqAndLock(pDevExt, pReq);
+
+                    /* On failure, roll back (unless it's session termination time). */
+                    if (RT_FAILURE(rc) && !fSessionTermination)
+                    {
+                        vgdrvBitUsageTrackerChange(&pDevExt->SetGuestCapsTracker, fChanged, pSession->fCapabilities,
+                                                   pDevExt->cSessions, "SetGuestCapsTracker");
+                        pSession->fCapabilities = fPrevious;
+                    }
+                }
+            }
+        }
+    }
+#ifndef VBOXGUEST_DISREGARD_ACQUIRE_MODE_GUEST_CAPS
+    else
+        rc = VERR_RESOURCE_BUSY;
+#endif
+
+    RTSpinlockRelease(pDevExt->SessionSpinlock);
+    if (pReq)
+        VbglGRFree(&pReq->header);
+    return rc;
+}
+
+
+/**
+ * Handle VBOXGUEST_IOCTL_SET_GUEST_CAPABILITIES.
+ *
+ * @returns VBox status code.
+ *
+ * @param   pDevExt             The device extension.
+ * @param   pSession            The session.
+ * @param   pInfo               The request.
+ */
+static int vgdrvIoCtl_SetCapabilities(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, VBoxGuestSetCapabilitiesInfo *pInfo)
+{
+    int rc;
+    LogFlow(("VBOXGUEST_IOCTL_SET_GUEST_CAPABILITIES: or=%#x not=%#x\n", pInfo->u32OrMask, pInfo->u32NotMask));
+
+    if (!((pInfo->u32OrMask | pInfo->u32NotMask) & ~VMMDEV_GUEST_CAPABILITIES_MASK))
+        rc = vgdrvSetSessionCapabilities(pDevExt, pSession, pInfo->u32OrMask, pInfo->u32NotMask, false /*fSessionTermination*/);
+    else
+        rc = VERR_INVALID_PARAMETER;
+
+    return rc;
+}
+
+/** @} */
+
+
+/**
+ * Common IOCtl for user to kernel and kernel to kernel communication.
+ *
+ * This function only does the basic validation and then invokes
+ * worker functions that takes care of each specific function.
+ *
+ * @returns VBox status code.
+ *
+ * @param   iFunction           The requested function.
+ * @param   pDevExt             The device extension.
+ * @param   pSession            The client session.
+ * @param   pvData              The input/output data buffer. Can be NULL depending on the function.
+ * @param   cbData              The max size of the data buffer.
+ * @param   pcbDataReturned     Where to store the amount of returned data. Can be NULL.
+ */
+int VGDrvCommonIoCtl(unsigned iFunction, PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                     void *pvData, size_t cbData, size_t *pcbDataReturned)
+{
+    int rc;
+    LogFlow(("VGDrvCommonIoCtl: iFunction=%#x pDevExt=%p pSession=%p pvData=%p cbData=%zu\n",
+             iFunction, pDevExt, pSession, pvData, cbData));
+
+    /*
+     * Make sure the returned data size is set to zero.
+     */
+    if (pcbDataReturned)
+        *pcbDataReturned = 0;
+
+    /*
+     * Define some helper macros to simplify validation.
+     */
+#define CHECKRET_RING0(mnemonic) \
+    do { \
+        if (pSession->R0Process != NIL_RTR0PROCESS) \
+        { \
+            LogFunc((mnemonic ": Ring-0 only, caller is %RTproc/%p\n", \
+                     pSession->Process, (uintptr_t)pSession->R0Process)); \
+            return VERR_PERMISSION_DENIED; \
+        } \
+    } while (0)
+#define CHECKRET_MIN_SIZE(mnemonic, cbMin) \
+    do { \
+        if (cbData < (cbMin)) \
+        { \
+            LogFunc((mnemonic ": cbData=%#zx (%zu) min is %#zx (%zu)\n", \
+                     cbData, cbData, (size_t)(cbMin), (size_t)(cbMin))); \
+            return VERR_BUFFER_OVERFLOW; \
+        } \
+        if ((cbMin) != 0 && !VALID_PTR(pvData)) \
+        { \
+            LogFunc((mnemonic ": Invalid pointer %p\n", pvData)); \
+            return VERR_INVALID_POINTER; \
+        } \
+    } while (0)
+#define CHECKRET_SIZE(mnemonic, cb) \
+    do { \
+        if (cbData != (cb)) \
+        { \
+            LogFunc((mnemonic ": cbData=%#zx (%zu) expected is %#zx (%zu)\n", \
+                     cbData, cbData, (size_t)(cb), (size_t)(cb))); \
+            return VERR_BUFFER_OVERFLOW; \
+        } \
+        if ((cb) != 0 && !VALID_PTR(pvData)) \
+        { \
+            LogFunc((mnemonic ": Invalid pointer %p\n", pvData)); \
+            return VERR_INVALID_POINTER; \
+        } \
+    } while (0)
+
+
+    /*
+     * Deal with variably sized requests first.
+     */
+    rc = VINF_SUCCESS;
+    if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_VMMREQUEST(0)))
+    {
+        CHECKRET_MIN_SIZE("VMMREQUEST", sizeof(VMMDevRequestHeader));
+        rc = vgdrvIoCtl_VMMRequest(pDevExt, pSession, (VMMDevRequestHeader *)pvData, cbData, pcbDataReturned);
+    }
+#ifdef VBOX_WITH_HGCM
+    /*
+     * These ones are a bit tricky.
+     */
+    else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_HGCM_CALL(0)))
+    {
+        bool fInterruptible = pSession->R0Process != NIL_RTR0PROCESS;
+        CHECKRET_MIN_SIZE("HGCM_CALL", sizeof(VBoxGuestHGCMCallInfo));
+        rc = vgdrvIoCtl_HGCMCall(pDevExt, pSession, (VBoxGuestHGCMCallInfo *)pvData, RT_INDEFINITE_WAIT,
+                                 fInterruptible, false /*f32bit*/, false /* fUserData */,
+                                 0, cbData, pcbDataReturned);
+    }
+    else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_HGCM_CALL_TIMED(0)))
+    {
+        VBoxGuestHGCMCallInfoTimed *pInfo = (VBoxGuestHGCMCallInfoTimed *)pvData;
+        CHECKRET_MIN_SIZE("HGCM_CALL_TIMED", sizeof(VBoxGuestHGCMCallInfoTimed));
+        rc = vgdrvIoCtl_HGCMCall(pDevExt, pSession, &pInfo->info, pInfo->u32Timeout,
+                                 !!pInfo->fInterruptible || pSession->R0Process != NIL_RTR0PROCESS,
+                                 false /*f32bit*/, false /* fUserData */,
+                                 RT_OFFSETOF(VBoxGuestHGCMCallInfoTimed, info), cbData, pcbDataReturned);
+    }
+    else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_HGCM_CALL_USERDATA(0)))
+    {
+        bool fInterruptible = true;
+        CHECKRET_MIN_SIZE("HGCM_CALL", sizeof(VBoxGuestHGCMCallInfo));
+        rc = vgdrvIoCtl_HGCMCall(pDevExt, pSession, (VBoxGuestHGCMCallInfo *)pvData, RT_INDEFINITE_WAIT,
+                                 fInterruptible, false /*f32bit*/, true /* fUserData */,
+                                 0, cbData, pcbDataReturned);
+    }
+# ifdef RT_ARCH_AMD64
+    else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_HGCM_CALL_32(0)))
+    {
+        bool fInterruptible = pSession->R0Process != NIL_RTR0PROCESS;
+        CHECKRET_MIN_SIZE("HGCM_CALL", sizeof(VBoxGuestHGCMCallInfo));
+        rc = vgdrvIoCtl_HGCMCall(pDevExt, pSession, (VBoxGuestHGCMCallInfo *)pvData, RT_INDEFINITE_WAIT,
+                                 fInterruptible, true /*f32bit*/, false /* fUserData */,
+                                 0, cbData, pcbDataReturned);
+    }
+    else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_HGCM_CALL_TIMED_32(0)))
+    {
+        CHECKRET_MIN_SIZE("HGCM_CALL_TIMED", sizeof(VBoxGuestHGCMCallInfoTimed));
+        VBoxGuestHGCMCallInfoTimed *pInfo = (VBoxGuestHGCMCallInfoTimed *)pvData;
+        rc = vgdrvIoCtl_HGCMCall(pDevExt, pSession, &pInfo->info, pInfo->u32Timeout,
+                                 !!pInfo->fInterruptible || pSession->R0Process != NIL_RTR0PROCESS,
+                                 true /*f32bit*/, false /* fUserData */,
+                                 RT_OFFSETOF(VBoxGuestHGCMCallInfoTimed, info), cbData, pcbDataReturned);
+    }
+# endif
+#endif /* VBOX_WITH_HGCM */
+    else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_LOG(0)))
+    {
+        CHECKRET_MIN_SIZE("LOG", 1);
+        rc = vgdrvIoCtl_Log(pDevExt, (char *)pvData, cbData, pcbDataReturned, pSession->fUserSession);
+    }
+    else
+    {
+        switch (iFunction)
+        {
+            case VBOXGUEST_IOCTL_GETVMMDEVPORT:
+                CHECKRET_RING0("GETVMMDEVPORT");
+                CHECKRET_MIN_SIZE("GETVMMDEVPORT", sizeof(VBoxGuestPortInfo));
+                rc = vgdrvIoCtl_GetVMMDevPort(pDevExt, (VBoxGuestPortInfo *)pvData, pcbDataReturned);
+                break;
+
+#ifndef RT_OS_WINDOWS  /* Windows has its own implementation of this. */
+            case VBOXGUEST_IOCTL_SET_MOUSE_NOTIFY_CALLBACK:
+                CHECKRET_RING0("SET_MOUSE_NOTIFY_CALLBACK");
+                CHECKRET_SIZE("SET_MOUSE_NOTIFY_CALLBACK", sizeof(VBoxGuestMouseSetNotifyCallback));
+                rc = vgdrvIoCtl_SetMouseNotifyCallback(pDevExt, (VBoxGuestMouseSetNotifyCallback *)pvData);
+                break;
+#endif
+
+            case VBOXGUEST_IOCTL_WAITEVENT:
+                CHECKRET_MIN_SIZE("WAITEVENT", sizeof(VBoxGuestWaitEventInfo));
+                rc = vgdrvIoCtl_WaitEvent(pDevExt, pSession, (VBoxGuestWaitEventInfo *)pvData,
+                                          pcbDataReturned, pSession->R0Process != NIL_RTR0PROCESS);
+                break;
+
+            case VBOXGUEST_IOCTL_CANCEL_ALL_WAITEVENTS:
+                CHECKRET_SIZE("CANCEL_ALL_WAITEVENTS", 0);
+                rc = vgdrvIoCtl_CancelAllWaitEvents(pDevExt, pSession);
+                break;
+
+            case VBOXGUEST_IOCTL_CTL_FILTER_MASK:
+                CHECKRET_MIN_SIZE("CTL_FILTER_MASK", sizeof(VBoxGuestFilterMaskInfo));
+                rc = vgdrvIoCtl_CtlFilterMask(pDevExt, pSession, (VBoxGuestFilterMaskInfo *)pvData);
+                break;
+
+#ifdef VBOX_WITH_HGCM
+            case VBOXGUEST_IOCTL_HGCM_CONNECT:
+# ifdef RT_ARCH_AMD64
+            case VBOXGUEST_IOCTL_HGCM_CONNECT_32:
+# endif
+                CHECKRET_MIN_SIZE("HGCM_CONNECT", sizeof(VBoxGuestHGCMConnectInfo));
+                rc = vgdrvIoCtl_HGCMConnect(pDevExt, pSession, (VBoxGuestHGCMConnectInfo *)pvData, pcbDataReturned);
+                break;
+
+            case VBOXGUEST_IOCTL_HGCM_DISCONNECT:
+# ifdef RT_ARCH_AMD64
+            case VBOXGUEST_IOCTL_HGCM_DISCONNECT_32:
+# endif
+                CHECKRET_MIN_SIZE("HGCM_DISCONNECT", sizeof(VBoxGuestHGCMDisconnectInfo));
+                rc = vgdrvIoCtl_HGCMDisconnect(pDevExt, pSession, (VBoxGuestHGCMDisconnectInfo *)pvData, pcbDataReturned);
+                break;
+#endif /* VBOX_WITH_HGCM */
+
+            case VBOXGUEST_IOCTL_CHECK_BALLOON:
+                CHECKRET_MIN_SIZE("CHECK_MEMORY_BALLOON", sizeof(VBoxGuestCheckBalloonInfo));
+                rc = vgdrvIoCtl_CheckMemoryBalloon(pDevExt, pSession, (VBoxGuestCheckBalloonInfo *)pvData, pcbDataReturned);
+                break;
+
+            case VBOXGUEST_IOCTL_CHANGE_BALLOON:
+                CHECKRET_MIN_SIZE("CHANGE_MEMORY_BALLOON", sizeof(VBoxGuestChangeBalloonInfo));
+                rc = vgdrvIoCtl_ChangeMemoryBalloon(pDevExt, pSession, (VBoxGuestChangeBalloonInfo *)pvData, pcbDataReturned);
+                break;
+
+            case VBOXGUEST_IOCTL_WRITE_CORE_DUMP:
+                CHECKRET_MIN_SIZE("WRITE_CORE_DUMP", sizeof(VBoxGuestWriteCoreDump));
+                rc = vgdrvIoCtl_WriteCoreDump(pDevExt, (VBoxGuestWriteCoreDump *)pvData);
+                break;
+
+            case VBOXGUEST_IOCTL_SET_MOUSE_STATUS:
+                CHECKRET_SIZE("SET_MOUSE_STATUS", sizeof(uint32_t));
+                rc = vgdrvIoCtl_SetMouseStatus(pDevExt, pSession, *(uint32_t *)pvData);
+                break;
+
+#ifdef VBOX_WITH_DPC_LATENCY_CHECKER
+            case VBOXGUEST_IOCTL_DPC_LATENCY_CHECKER:
+                CHECKRET_SIZE("DPC_LATENCY_CHECKER", 0);
+                rc = VGDrvNtIOCtl_DpcLatencyChecker();
+                break;
+#endif
+
+            case VBOXGUEST_IOCTL_GUEST_CAPS_ACQUIRE:
+                CHECKRET_SIZE("GUEST_CAPS_ACQUIRE", sizeof(VBoxGuestCapsAquire));
+                rc = vgdrvIoCtl_GuestCapsAcquire(pDevExt, pSession, (VBoxGuestCapsAquire *)pvData);
+                *pcbDataReturned = sizeof(VBoxGuestCapsAquire);
+                break;
+
+            case VBOXGUEST_IOCTL_SET_GUEST_CAPABILITIES:
+                CHECKRET_MIN_SIZE("SET_GUEST_CAPABILITIES", sizeof(VBoxGuestSetCapabilitiesInfo));
+                rc = vgdrvIoCtl_SetCapabilities(pDevExt, pSession, (VBoxGuestSetCapabilitiesInfo *)pvData);
+                break;
+
+            default:
+            {
+                LogRel(("VGDrvCommonIoCtl: Unknown request iFunction=%#x stripped size=%#x\n",
+                        iFunction, VBOXGUEST_IOCTL_STRIP_SIZE(iFunction)));
+                rc = VERR_NOT_SUPPORTED;
+                break;
+            }
+        }
+    }
+
+    LogFlow(("VGDrvCommonIoCtl: returns %Rrc *pcbDataReturned=%zu\n", rc, pcbDataReturned ? *pcbDataReturned : 0));
+    return rc;
+}
+
+
+/**
+ * Used by VGDrvCommonISR as well as the acquire guest capability code.
+ *
+ * @returns VINF_SUCCESS on success. On failure, ORed together
+ *          RTSemEventMultiSignal errors (completes processing despite errors).
+ * @param   pDevExt             The VBoxGuest device extension.
+ * @param   fEvents             The events to dispatch.
+ */
+static int vgdrvDispatchEventsLocked(PVBOXGUESTDEVEXT pDevExt, uint32_t fEvents)
+{
+    PVBOXGUESTWAIT  pWait;
+    PVBOXGUESTWAIT  pSafe;
+    int             rc = VINF_SUCCESS;
+
+    fEvents |= pDevExt->f32PendingEvents;
+
+    RTListForEachSafe(&pDevExt->WaitList, pWait, pSafe, VBOXGUESTWAIT, ListNode)
+    {
+        uint32_t fHandledEvents = pWait->fReqEvents & fEvents;
+        if (    fHandledEvents != 0
+            &&  !pWait->fResEvents)
+        {
+            /* Does this one wait on any of the events we're dispatching?  We do a quick
+               check first, then deal with VBOXGUEST_ACQUIRE_STYLE_EVENTS as applicable. */
+            if (fHandledEvents & VBOXGUEST_ACQUIRE_STYLE_EVENTS)
+                fHandledEvents &= vgdrvGetAllowedEventMaskForSession(pDevExt, pWait->pSession);
+            if (fHandledEvents)
+            {
+                pWait->fResEvents = pWait->fReqEvents & fEvents & fHandledEvents;
+                fEvents &= ~pWait->fResEvents;
+                RTListNodeRemove(&pWait->ListNode);
+#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
+                RTListAppend(&pDevExt->WakeUpList, &pWait->ListNode);
+#else
+                RTListAppend(&pDevExt->WokenUpList, &pWait->ListNode);
+                rc |= RTSemEventMultiSignal(pWait->Event);
+#endif
+                if (!fEvents)
+                    break;
+            }
+        }
+    }
+
+    ASMAtomicWriteU32(&pDevExt->f32PendingEvents, fEvents);
+    return rc;
+}
+
+
+/**
+ * Simply checks whether the IRQ is ours or not, does not do any interrupt
+ * procesing.
+ *
+ * @returns true if it was our interrupt, false if it wasn't.
+ * @param   pDevExt     The VBoxGuest device extension.
+ */
+bool VGDrvCommonIsOurIRQ(PVBOXGUESTDEVEXT pDevExt)
+{
+    RTSpinlockAcquire(pDevExt->EventSpinlock);
+    bool const fOurIrq = pDevExt->pVMMDevMemory->V.V1_04.fHaveEvents;
+    RTSpinlockRelease(pDevExt->EventSpinlock);
+
+    return fOurIrq;
+}
+
+
+/**
+ * Common interrupt service routine.
+ *
+ * This deals with events and with waking up thread waiting for those events.
+ *
+ * @returns true if it was our interrupt, false if it wasn't.
+ * @param   pDevExt     The VBoxGuest device extension.
+ */
+bool VGDrvCommonISR(PVBOXGUESTDEVEXT pDevExt)
+{
+    VMMDevEvents volatile  *pReq                  = pDevExt->pIrqAckEvents;
+    bool                    fMousePositionChanged = false;
+    int                     rc                    = 0;
+    bool                    fOurIrq;
+
+    /*
+     * Make sure we've initialized the device extension.
+     */
+    if (RT_UNLIKELY(!pReq))
+        return false;
+
+    /*
+     * Enter the spinlock and check if it's our IRQ or not.
+     */
+    RTSpinlockAcquire(pDevExt->EventSpinlock);
+    fOurIrq = pDevExt->pVMMDevMemory->V.V1_04.fHaveEvents;
+    if (fOurIrq)
+    {
+        /*
+         * Acknowlegde events.
+         * We don't use VbglGRPerform here as it may take another spinlocks.
+         */
+        pReq->header.rc = VERR_INTERNAL_ERROR;
+        pReq->events    = 0;
+        ASMCompilerBarrier();
+        ASMOutU32(pDevExt->IOPortBase + VMMDEV_PORT_OFF_REQUEST, (uint32_t)pDevExt->PhysIrqAckEvents);
+        ASMCompilerBarrier();   /* paranoia */
+        if (RT_SUCCESS(pReq->header.rc))
+        {
+            uint32_t        fEvents = pReq->events;
+
+            Log3(("VGDrvCommonISR: acknowledge events succeeded %#RX32\n", fEvents));
+
+            /*
+             * VMMDEV_EVENT_MOUSE_POSITION_CHANGED can only be polled for.
+             */
+            if (fEvents & VMMDEV_EVENT_MOUSE_POSITION_CHANGED)
+            {
+                fMousePositionChanged = true;
+                fEvents &= ~VMMDEV_EVENT_MOUSE_POSITION_CHANGED;
+#if !defined(RT_OS_WINDOWS) && !defined(VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT)
+                if (pDevExt->MouseNotifyCallback.pfnNotify)
+                    pDevExt->MouseNotifyCallback.pfnNotify(pDevExt->MouseNotifyCallback.pvUser);
+#endif
+            }
+
+#ifdef VBOX_WITH_HGCM
+            /*
+             * The HGCM event/list is kind of different in that we evaluate all entries.
+             */
+            if (fEvents & VMMDEV_EVENT_HGCM)
+            {
+                PVBOXGUESTWAIT pWait;
+                PVBOXGUESTWAIT pSafe;
+                RTListForEachSafe(&pDevExt->HGCMWaitList, pWait, pSafe, VBOXGUESTWAIT, ListNode)
+                {
+                    if (pWait->pHGCMReq->fu32Flags & VBOX_HGCM_REQ_DONE)
+                    {
+                        pWait->fResEvents = VMMDEV_EVENT_HGCM;
+                        RTListNodeRemove(&pWait->ListNode);
+# ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
+                        RTListAppend(&pDevExt->WakeUpList, &pWait->ListNode);
+# else
+                        RTListAppend(&pDevExt->WokenUpList, &pWait->ListNode);
+                        rc |= RTSemEventMultiSignal(pWait->Event);
+# endif
+                    }
+                }
+                fEvents &= ~VMMDEV_EVENT_HGCM;
+            }
+#endif
+
+            /*
+             * Normal FIFO waiter evaluation.
+             */
+            rc |= vgdrvDispatchEventsLocked(pDevExt, fEvents);
+        }
+        else /* something is serious wrong... */
+            Log(("VGDrvCommonISR: acknowledge events failed rc=%Rrc (events=%#x)!!\n",
+                 pReq->header.rc, pReq->events));
+    }
+    else
+        Log3(("VGDrvCommonISR: not ours\n"));
+
+    RTSpinlockRelease(pDevExt->EventSpinlock);
+
+    /*
+     * Execute the mouse notification callback here if it cannot be executed while
+     * holding the interrupt safe spinlock, see @bugref{8639}.
+     */
+#if defined(VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT)
+    if (   fMousePositionChanged
+        && pDevExt->MouseNotifyCallback.pfnNotify)
+        pDevExt->MouseNotifyCallback.pfnNotify(pDevExt->MouseNotifyCallback.pvUser);
+#endif
+
+#if defined(VBOXGUEST_USE_DEFERRED_WAKE_UP) && !defined(RT_OS_DARWIN) && !defined(RT_OS_WINDOWS)
+    /*
+     * Do wake-ups.
+     * Note. On Windows this isn't possible at this IRQL, so a DPC will take
+     *       care of it.  Same on darwin, doing it in the work loop callback.
+     */
+    VGDrvCommonWaitDoWakeUps(pDevExt);
+#endif
+
+    /*
+     * Work the poll and async notification queues on OSes that implements that.
+     * (Do this outside the spinlock to prevent some recursive spinlocking.)
+     */
+    if (fMousePositionChanged)
+    {
+        ASMAtomicIncU32(&pDevExt->u32MousePosChangedSeq);
+        VGDrvNativeISRMousePollEvent(pDevExt);
+    }
+
+    Assert(rc == 0);
+    NOREF(rc);
+    return fOurIrq;
+}
+
diff --git a/ubuntu/vbox/vboxguest/VBoxGuestIDC-unix.c.h b/ubuntu/vbox/vboxguest/VBoxGuestIDC-unix.c.h
new file mode 100644 (file)
index 0000000..613c2f6
--- /dev/null
@@ -0,0 +1,147 @@
+/* $Rev: 109079 $ */
+/** @file
+ * VBoxGuest - Inter Driver Communication, unix implementation.
+ *
+ * This file is included by the platform specific source file.
+ */
+
+/*
+ * 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.
+ */
+
+
+/** @todo Use some header that we have in common with VBoxGuestLib.h... */
+/** @todo fix DECLVBGL usage. */
+RT_C_DECLS_BEGIN
+DECLEXPORT(void *) VBOXCALL VBoxGuestIDCOpen(uint32_t *pu32Version);
+DECLEXPORT(int) VBOXCALL VBoxGuestIDCClose(void *pvSession);
+DECLEXPORT(int) VBOXCALL VBoxGuestIDCCall(void *pvSession, unsigned iCmd, void *pvData, size_t cbData, size_t *pcbDataReturned);
+RT_C_DECLS_END
+
+
+/**
+ * Open a new IDC connection.
+ *
+ * @returns Opaque pointer to session object.
+ * @param   pu32Version         Where to store VMMDev version.
+ */
+DECLEXPORT(void *) VBOXCALL VBoxGuestIDCOpen(uint32_t *pu32Version)
+{
+    PVBOXGUESTSESSION   pSession;
+    int                 rc;
+    LogFlow(("VBoxGuestIDCOpen: Version=%#x\n", pu32Version ? *pu32Version : 0));
+
+    AssertPtrReturn(pu32Version, NULL);
+
+#ifdef RT_OS_SOLARIS
+    mutex_enter(&g_LdiMtx);
+    if (!g_LdiHandle)
+    {
+        ldi_ident_t DevIdent = ldi_ident_from_anon();
+        rc = ldi_open_by_name(VBOXGUEST_DEVICE_NAME, FREAD, kcred, &g_LdiHandle, DevIdent);
+        ldi_ident_release(DevIdent);
+        if (rc)
+        {
+            LogRel(("VBoxGuestIDCOpen: ldi_open_by_name failed. rc=%d\n", rc));
+            mutex_exit(&g_LdiMtx);
+            return NULL;
+        }
+    }
+    ++g_cLdiOpens;
+    mutex_exit(&g_LdiMtx);
+#endif
+
+    rc = VGDrvCommonCreateKernelSession(&g_DevExt, &pSession);
+    if (RT_SUCCESS(rc))
+    {
+        *pu32Version = VMMDEV_VERSION;
+        return pSession;
+    }
+
+#ifdef RT_OS_SOLARIS
+    mutex_enter(&g_LdiMtx);
+    if (g_cLdiOpens > 0)
+        --g_cLdiOpens;
+    if (   g_cLdiOpens == 0
+        && g_LdiHandle)
+    {
+        ldi_close(g_LdiHandle, FREAD, kcred);
+        g_LdiHandle = NULL;
+    }
+    mutex_exit(&g_LdiMtx);
+#endif
+
+    LogRel(("VBoxGuestIDCOpen: VGDrvCommonCreateKernelSession failed. rc=%d\n", rc));
+    return NULL;
+}
+
+
+/**
+ * Close an IDC connection.
+ *
+ * @returns VBox error code.
+ * @param   pvSession           Opaque pointer to the session object.
+ */
+DECLEXPORT(int) VBOXCALL VBoxGuestIDCClose(void *pvSession)
+{
+    PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pvSession;
+    LogFlow(("VBoxGuestIDCClose: pvSession=%p\n", pvSession));
+
+    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
+    VGDrvCommonCloseSession(&g_DevExt, pSession);
+
+#ifdef RT_OS_SOLARIS
+    mutex_enter(&g_LdiMtx);
+    if (g_cLdiOpens > 0)
+        --g_cLdiOpens;
+    if (   g_cLdiOpens == 0
+        && g_LdiHandle)
+    {
+        ldi_close(g_LdiHandle, FREAD, kcred);
+        g_LdiHandle = NULL;
+    }
+    mutex_exit(&g_LdiMtx);
+#endif
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Perform an IDC call.
+ *
+ * @returns VBox error code.
+ * @param   pvSession           Opaque pointer to the session.
+ * @param   iCmd                Requested function.
+ * @param   pvData              IO data buffer.
+ * @param   cbData              Size of the data buffer.
+ * @param   pcbDataReturned     Where to store the amount of returned data.
+ */
+DECLEXPORT(int) VBOXCALL VBoxGuestIDCCall(void *pvSession, unsigned iCmd, void *pvData, size_t cbData, size_t *pcbDataReturned)
+{
+    PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pvSession;
+    LogFlow(("VBoxGuestIDCCall: %pvSession=%p Cmd=%u pvData=%p cbData=%d\n", pvSession, iCmd, pvData, cbData));
+
+    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
+    AssertMsgReturn(pSession->pDevExt == &g_DevExt, ("SC: %p != %p\n", pSession->pDevExt, &g_DevExt), VERR_INVALID_HANDLE);
+
+    return VGDrvCommonIoCtl(iCmd, &g_DevExt, pSession, pvData, cbData, pcbDataReturned);
+}
+
diff --git a/ubuntu/vbox/vboxguest/VBoxGuestInternal.h b/ubuntu/vbox/vboxguest/VBoxGuestInternal.h
new file mode 100644 (file)
index 0000000..c5b652b
--- /dev/null
@@ -0,0 +1,363 @@
+/* $Id: VBoxGuestInternal.h $ */
+/** @file
+ * VBoxGuest - Guest Additions Driver, Internal Header.
+ */
+
+/*
+ * Copyright (C) 2010-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.
+ */
+
+#ifndef ___VBoxGuestInternal_h
+#define ___VBoxGuestInternal_h
+
+#include <iprt/types.h>
+#include <iprt/list.h>
+#include <iprt/semaphore.h>
+#include <iprt/spinlock.h>
+#include <iprt/timer.h>
+#include <VBox/VMMDev.h>
+#include <VBox/VBoxGuest.h>
+#include <VBox/VBoxGuestLib.h>
+
+/** @def VBOXGUEST_USE_DEFERRED_WAKE_UP
+ * Defer wake-up of waiting thread when defined. */
+#if defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS) || defined(DOXYGEN_RUNNING)
+# define VBOXGUEST_USE_DEFERRED_WAKE_UP
+#endif
+
+/** @def VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT
+ * The mouse notification callback can cause preemption and must not be invoked
+ * while holding a high-level spinlock.
+ */
+#if defined(RT_OS_SOLARIS) || defined(DOXYGEN_RUNNING)
+# define VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT
+#endif
+
+/** Pointer to the VBoxGuest per session data. */
+typedef struct VBOXGUESTSESSION *PVBOXGUESTSESSION;
+
+/** Pointer to a wait-for-event entry. */
+typedef struct VBOXGUESTWAIT *PVBOXGUESTWAIT;
+
+/**
+ * VBox guest wait for event entry.
+ *
+ * Each waiting thread allocates one of these items and adds
+ * it to the wait list before going to sleep on the event sem.
+ */
+typedef struct VBOXGUESTWAIT
+{
+    /** The list node. */
+    RTLISTNODE                  ListNode;
+    /** The events we are waiting on. */
+    uint32_t                    fReqEvents;
+    /** The events we received. */
+    uint32_t volatile           fResEvents;
+#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
+    /** Set by VGDrvCommonWaitDoWakeUps before leaving the spinlock to call
+     *  RTSemEventMultiSignal. */
+    bool volatile               fPendingWakeUp;
+    /** Set by the requestor thread if it got the spinlock before the
+     * signaller.  Deals with the race in VGDrvCommonWaitDoWakeUps. */
+    bool volatile               fFreeMe;
+#endif
+    /** The event semaphore. */
+    RTSEMEVENTMULTI             Event;
+    /** The session that's waiting. */
+    PVBOXGUESTSESSION           pSession;
+#ifdef VBOX_WITH_HGCM
+    /** The HGCM request we're waiting for to complete. */
+    VMMDevHGCMRequestHeader volatile *pHGCMReq;
+#endif
+} VBOXGUESTWAIT;
+
+
+/**
+ * VBox guest memory balloon.
+ */
+typedef struct VBOXGUESTMEMBALLOON
+{
+    /** Mutex protecting the members below from concurrent access. */
+    RTSEMFASTMUTEX              hMtx;
+    /** The current number of chunks in the balloon. */
+    uint32_t                    cChunks;
+    /** The maximum number of chunks in the balloon (typically the amount of guest
+     * memory / chunksize). */
+    uint32_t                    cMaxChunks;
+    /** This is true if we are using RTR0MemObjAllocPhysNC() / RTR0MemObjGetPagePhysAddr()
+     * and false otherwise. */
+    bool                        fUseKernelAPI;
+    /** The current owner of the balloon.
+     * This is automatically assigned to the first session using the ballooning
+     * API and first released when the session closes. */
+    PVBOXGUESTSESSION           pOwner;
+    /** The pointer to the array of memory objects holding the chunks of the
+     *  balloon.  This array is cMaxChunks in size when present. */
+    PRTR0MEMOBJ                 paMemObj;
+} VBOXGUESTMEMBALLOON;
+/** Pointer to a memory balloon. */
+typedef VBOXGUESTMEMBALLOON *PVBOXGUESTMEMBALLOON;
+
+
+/**
+ * Per bit usage tracker for a uint32_t mask.
+ *
+ * Used for optimal handling of guest properties, mouse status and event filter.
+ */
+typedef struct VBOXGUESTBITUSAGETRACER
+{
+    /** Per bit usage counters. */
+    uint32_t        acPerBitUsage[32];
+    /** The current mask according to acPerBitUsage. */
+    uint32_t        fMask;
+} VBOXGUESTBITUSAGETRACER;
+/** Pointer to a per bit usage tracker.  */
+typedef VBOXGUESTBITUSAGETRACER *PVBOXGUESTBITUSAGETRACER;
+/** Pointer to a const per bit usage tracker.  */
+typedef VBOXGUESTBITUSAGETRACER const *PCVBOXGUESTBITUSAGETRACER;
+
+
+/**
+ * VBox guest device (data) extension.
+ */
+typedef struct VBOXGUESTDEVEXT
+{
+    /** The base of the adapter I/O ports. */
+    RTIOPORT                    IOPortBase;
+    /** Pointer to the mapping of the VMMDev adapter memory. */
+    VMMDevMemory volatile      *pVMMDevMemory;
+    /** The memory object reserving space for the guest mappings. */
+    RTR0MEMOBJ                  hGuestMappings;
+    /** Spinlock protecting the signaling and resetting of the wait-for-event
+     * semaphores as well as the event acking in the ISR. */
+    RTSPINLOCK                  EventSpinlock;
+    /** Preallocated VMMDevEvents for the IRQ handler. */
+    VMMDevEvents               *pIrqAckEvents;
+    /** The physical address of pIrqAckEvents. */
+    RTCCPHYS                    PhysIrqAckEvents;
+    /** Wait-for-event list for threads waiting for multiple events
+     * (VBOXGUESTWAIT). */
+    RTLISTANCHOR                WaitList;
+#ifdef VBOX_WITH_HGCM
+    /** Wait-for-event list for threads waiting on HGCM async completion
+     * (VBOXGUESTWAIT).
+     *
+     * The entire list is evaluated upon the arrival of an HGCM event, unlike
+     * the other lists which are only evaluated till the first thread has
+     * been woken up. */
+    RTLISTANCHOR                HGCMWaitList;
+#endif
+#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
+    /** List of wait-for-event entries that needs waking up
+     * (VBOXGUESTWAIT). */
+    RTLISTANCHOR                WakeUpList;
+#endif
+    /** List of wait-for-event entries that has been woken up
+     * (VBOXGUESTWAIT). */
+    RTLISTANCHOR                WokenUpList;
+    /** List of free wait-for-event entries (VBOXGUESTWAIT). */
+    RTLISTANCHOR                FreeList;
+    /** Mask of pending events. */
+    uint32_t volatile           f32PendingEvents;
+    /** Current VMMDEV_EVENT_MOUSE_POSITION_CHANGED sequence number.
+     * Used to implement polling.  */
+    uint32_t volatile           u32MousePosChangedSeq;
+
+    /** Spinlock various items in the VBOXGUESTSESSION. */
+    RTSPINLOCK                  SessionSpinlock;
+    /** List of guest sessions (VBOXGUESTSESSION).  We currently traverse this
+     * but do not search it, so a list data type should be fine.  Use under the
+     * #SessionSpinlock lock. */
+    RTLISTANCHOR                SessionList;
+    /** Number of session. */
+    uint32_t                    cSessions;
+    /** Flag indicating whether logging to the release log
+     *  is enabled. */
+    bool                        fLoggingEnabled;
+    /** Memory balloon information for RTR0MemObjAllocPhysNC(). */
+    VBOXGUESTMEMBALLOON         MemBalloon;
+    /** Callback and user data for a kernel mouse handler. */
+    VBoxGuestMouseSetNotifyCallback MouseNotifyCallback;
+
+    /** @name Host Event Filtering
+     * @{ */
+    /** Events we won't permit anyone to filter out. */
+    uint32_t                    fFixedEvents;
+    /** Usage counters for the host events. (Fixed events are not included.) */
+    VBOXGUESTBITUSAGETRACER     EventFilterTracker;
+    /** The event filter last reported to the host (UINT32_MAX on failure). */
+    uint32_t                    fEventFilterHost;
+    /** @} */
+
+    /** @name Mouse Status
+     * @{ */
+    /** Usage counters for the mouse statuses (VMMDEV_MOUSE_XXX). */
+    VBOXGUESTBITUSAGETRACER     MouseStatusTracker;
+    /** The mouse status last reported to the host (UINT32_MAX on failure). */
+    uint32_t                    fMouseStatusHost;
+    /** @} */
+
+    /** @name Guest Capabilities
+     * @{ */
+    /** Guest capabilities which have been set to "acquire" mode.  This means
+     * that only one session can use them at a time, and that they will be
+     * automatically cleaned up if that session exits without doing so.
+     *
+     * Protected by VBOXGUESTDEVEXT::SessionSpinlock, but is unfortunately read
+     * without holding the lock in a couple of places. */
+    uint32_t volatile           fAcquireModeGuestCaps;
+    /** Guest capabilities which have been set to "set" mode.  This just means
+     * that they have been blocked from ever being set to "acquire" mode. */
+    uint32_t                    fSetModeGuestCaps;
+    /** Mask of all capabilities which are currently acquired by some session
+     * and as such reported to the host. */
+    uint32_t                    fAcquiredGuestCaps;
+    /** Usage counters for guest capabilities in "set" mode. Indexed by
+     *  capability bit number, one count per session using a capability. */
+    VBOXGUESTBITUSAGETRACER     SetGuestCapsTracker;
+    /** The guest capabilities last reported to the host (UINT32_MAX on failure). */
+    uint32_t                    fGuestCapsHost;
+    /** @} */
+
+    /** Heartbeat timer which fires with interval
+      * cNsHearbeatInterval and its handler sends
+      * VMMDevReq_GuestHeartbeat to VMMDev. */
+    PRTTIMER                    pHeartbeatTimer;
+    /** Heartbeat timer interval in nanoseconds. */
+    uint64_t                    cNsHeartbeatInterval;
+    /** Preallocated VMMDevReq_GuestHeartbeat request. */
+    VMMDevRequestHeader         *pReqGuestHeartbeat;
+} VBOXGUESTDEVEXT;
+/** Pointer to the VBoxGuest driver data. */
+typedef VBOXGUESTDEVEXT *PVBOXGUESTDEVEXT;
+
+
+/**
+ * The VBoxGuest per session data.
+ */
+typedef struct VBOXGUESTSESSION
+{
+    /** The list node. */
+    RTLISTNODE                  ListNode;
+#if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) || defined(RT_OS_OS2) || defined(RT_OS_SOLARIS)
+    /** Pointer to the next session with the same hash. */
+    PVBOXGUESTSESSION           pNextHash;
+#endif
+#if defined(RT_OS_OS2)
+    /** The system file number of this session. */
+    uint16_t                    sfn;
+    uint16_t                    Alignment; /**< Alignment */
+#endif
+    /** The process (id) of the session.
+     * This is NIL if it's a kernel session. */
+    RTPROCESS                   Process;
+    /** Which process this session is associated with.
+     * This is NIL if it's a kernel session. */
+    RTR0PROCESS                 R0Process;
+    /** Pointer to the device extension. */
+    PVBOXGUESTDEVEXT            pDevExt;
+
+#ifdef VBOX_WITH_HGCM
+    /** Array containing HGCM client IDs associated with this session.
+     * This will be automatically disconnected when the session is closed. */
+    uint32_t volatile           aHGCMClientIds[64];
+#endif
+    /** The last consumed VMMDEV_EVENT_MOUSE_POSITION_CHANGED sequence number.
+     * Used to implement polling.  */
+    uint32_t volatile           u32MousePosChangedSeq;
+    /** Host events requested by the session.
+     * An event type requested in any guest session will be added to the host
+     * filter.  Protected by VBOXGUESTDEVEXT::SessionSpinlock. */
+    uint32_t                    fEventFilter;
+    /** Guest capabilities held in "acquired" by this session.
+     * Protected by VBOXGUESTDEVEXT::SessionSpinlock, but is unfortunately read
+     * without holding the lock in a couple of places. */
+    uint32_t volatile           fAcquiredGuestCaps;
+    /** Guest capabilities in "set" mode for this session.
+     * These accumulated for sessions via VBOXGUESTDEVEXT::acGuestCapsSet and
+     * reported to the host.  Protected by VBOXGUESTDEVEXT::SessionSpinlock.  */
+    uint32_t                    fCapabilities;
+    /** Mouse features supported.  A feature enabled in any guest session will
+     * be enabled for the host.
+     * @note We invert the VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR feature in this
+     * bitmap.  The logic of this is that the real feature is when the host
+     * cursor is not needed, and we tell the host it is not needed if any
+     * session explicitly fails to assert it.  Storing it inverted simplifies
+     * the checks.
+     * Use under the VBOXGUESTDEVEXT#SessionSpinlock lock. */
+    uint32_t                    fMouseStatus;
+#ifdef RT_OS_DARWIN
+    /** Pointer to the associated org_virtualbox_VBoxGuestClient object. */
+    void                       *pvVBoxGuestClient;
+    /** Whether this session has been opened or not. */
+    bool                        fOpened;
+#endif
+    /** Whether a CANCEL_ALL_WAITEVENTS is pending.  This happens when
+     * CANCEL_ALL_WAITEVENTS is called, but no call to WAITEVENT is in process
+     * in the current session.  In that case the next call will be interrupted
+     * at once. */
+    bool volatile               fPendingCancelWaitEvents;
+    /** Does this session belong to a root process or a user one? */
+    bool                        fUserSession;
+} VBOXGUESTSESSION;
+
+RT_C_DECLS_BEGIN
+
+int  VGDrvCommonInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, void *pvMMIOBase, uint32_t cbMMIO,
+                           VBOXOSTYPE enmOSType, uint32_t fEvents);
+bool VGDrvCommonIsOurIRQ(PVBOXGUESTDEVEXT pDevExt);
+bool VGDrvCommonISR(PVBOXGUESTDEVEXT pDevExt);
+void VGDrvCommonDeleteDevExt(PVBOXGUESTDEVEXT pDevExt);
+int  VGDrvCommonReinitDevExtAfterHibernation(PVBOXGUESTDEVEXT pDevExt, VBOXOSTYPE enmOSType);
+#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
+void VGDrvCommonWaitDoWakeUps(PVBOXGUESTDEVEXT pDevExt);
+#endif
+
+int  VGDrvCommonCreateUserSession(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION *ppSession);
+int  VGDrvCommonCreateKernelSession(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION *ppSession);
+void VGDrvCommonCloseSession(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession);
+
+int  VGDrvCommonIoCtlFast(unsigned iFunction, PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession);
+int  VGDrvCommonIoCtl(unsigned iFunction, PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
+                      void *pvData, size_t cbData, size_t *pcbDataReturned);
+
+/**
+ * ISR callback for notifying threads polling for mouse events.
+ *
+ * This is called at the end of the ISR, after leaving the event spinlock, if
+ * VMMDEV_EVENT_MOUSE_POSITION_CHANGED was raised by the host.
+ *
+ * @param   pDevExt     The device extension.
+ */
+void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt);
+
+
+#ifdef VBOX_WITH_DPC_LATENCY_CHECKER
+int VGDrvNtIOCtl_DpcLatencyChecker(void);
+#endif
+
+#ifdef VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT
+int VGDrvNativeSetMouseNotifyCallback(PVBOXGUESTDEVEXT pDevExt, VBoxGuestMouseSetNotifyCallback *pNotify);
+#endif
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/ubuntu/vbox/vboxguest/VBoxGuestLog.h b/ubuntu/vbox/vboxguest/VBoxGuestLog.h
new file mode 100644 (file)
index 0000000..26feeb7
--- /dev/null
@@ -0,0 +1,59 @@
+/* $Id: VBoxGuestLog.h $ */
+/** @file
+ * VBoxGuestLibR0 - Guest Logging facility.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef __VBOXGUESTLOG__H
+#define __VBOXGUESTLOG__H
+
+#ifndef RT_OS_WINDOWS
+# error "Don't include this file."
+#else  /* RT_OS_WINDOWS */
+/* Save LOG_ENABLED state, because "VBox/rt/log.h"
+ * may undefine it for IN_RING0 code.
+ */
+# if (defined(DEBUG) && !defined(NO_LOGGING)) || defined(LOG_ENABLED)
+#  define __LOG_ENABLED_SAVED__
+# endif
+
+# if (defined(DEBUG) && !defined(NO_LOGGING)) || defined(LOG_ENABLED)
+#  ifdef VBOX_GUEST
+#   include <VBox/log.h>
+#   undef Log
+#   define Log(a)  RTLogBackdoorPrintf a
+#  else
+#   define Log(a)  DbgPrint a
+#  endif
+# else
+#  define Log(a)
+# endif
+
+# ifdef __LOG_ENABLED_SAVED__
+#  define LOG_ENABLED
+#  undef __LOG_ENABLED_SAVED__
+# endif
+
+#endif  /* RT_OS_WINDOWS */
+
+#endif /* !__VBOXGUESTLOG__H */
diff --git a/ubuntu/vbox/vboxguest/VMMDev.c b/ubuntu/vbox/vboxguest/VMMDev.c
new file mode 100644 (file)
index 0000000..cbd9326
--- /dev/null
@@ -0,0 +1,43 @@
+/* $Id: VMMDev.cpp $ */
+/** @file
+ * VBoxGuestLibR0 - VMMDev device related functions.
+ */
+
+/*
+ * 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.
+ */
+
+#include "VBGLInternal.h"
+
+
+DECLVBGL(int) VbglQueryVMMDevMemory(VMMDevMemory **ppVMMDevMemory)
+{
+    int rc = vbglR0Enter();
+    if (RT_FAILURE(rc))
+        return rc;
+
+    /* If the memory was not found, return an error. */
+    if (!g_vbgldata.pVMMDevMemory)
+        return VERR_NOT_SUPPORTED;
+
+    *ppVMMDevMemory = g_vbgldata.pVMMDevMemory;
+    return rc;
+}
+
diff --git a/ubuntu/vbox/vboxguest/common/alloc/alloc.c b/ubuntu/vbox/vboxguest/common/alloc/alloc.c
new file mode 100644 (file)
index 0000000..8733ee0
--- /dev/null
@@ -0,0 +1,63 @@
+/* $Id: alloc.cpp $ */
+/** @file
+ * IPRT - Memory Allocation.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#ifndef RTMEM_NO_WRAP_TO_EF_APIS
+# define RTMEM_NO_WRAP_TO_EF_APIS
+#endif
+#include <iprt/mem.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/string.h>
+
+
+
+RTDECL(void *) RTMemDupTag(const void *pvSrc, size_t cb, const char *pszTag) RT_NO_THROW_DEF
+{
+    void *pvDst = RTMemAllocTag(cb, pszTag);
+    if (pvDst)
+        memcpy(pvDst, pvSrc, cb);
+    return pvDst;
+}
+RT_EXPORT_SYMBOL(RTMemDupTag);
+
+
+RTDECL(void *) RTMemDupExTag(const void *pvSrc, size_t cbSrc, size_t cbExtra, const char *pszTag) RT_NO_THROW_DEF
+{
+    void *pvDst = RTMemAllocTag(cbSrc + cbExtra, pszTag);
+    if (pvDst)
+    {
+        memcpy(pvDst, pvSrc, cbSrc);
+        memset((uint8_t *)pvDst + cbSrc, 0, cbExtra);
+    }
+    return pvDst;
+}
+RT_EXPORT_SYMBOL(RTMemDupExTag);
+
diff --git a/ubuntu/vbox/vboxguest/common/alloc/heapsimple.c b/ubuntu/vbox/vboxguest/common/alloc/heapsimple.c
new file mode 100644 (file)
index 0000000..0294c2f
--- /dev/null
@@ -0,0 +1,920 @@
+/* $Id: heapsimple.cpp $ */
+/** @file
+ * IPRT - A Simple Heap.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_DEFAULT
+#include <iprt/heap.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+#include <iprt/err.h>
+#include <iprt/log.h>
+#include <iprt/string.h>
+#include <iprt/param.h>
+
+#include "internal/magics.h"
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/** Pointer to the heap anchor block. */
+typedef struct RTHEAPSIMPLEINTERNAL *PRTHEAPSIMPLEINTERNAL;
+/** Pointer to a heap block. */
+typedef struct RTHEAPSIMPLEBLOCK *PRTHEAPSIMPLEBLOCK;
+/** Pointer to a free heap block. */
+typedef struct RTHEAPSIMPLEFREE *PRTHEAPSIMPLEFREE;
+
+/**
+ * Structure describing a simple heap block.
+ * If this block is allocated, it is followed by the user data.
+ * If this block is free, see RTHEAPSIMPLEFREE.
+ */
+typedef struct RTHEAPSIMPLEBLOCK
+{
+    /** The next block in the global block list. */
+    PRTHEAPSIMPLEBLOCK      pNext;
+    /** The previous block in the global block list. */
+    PRTHEAPSIMPLEBLOCK      pPrev;
+    /** Pointer to the heap anchor block. */
+    PRTHEAPSIMPLEINTERNAL   pHeap;
+    /** Flags + magic. */
+    uintptr_t               fFlags;
+} RTHEAPSIMPLEBLOCK;
+AssertCompileSizeAlignment(RTHEAPSIMPLEBLOCK, 16);
+
+/** The block is free if this flag is set. When cleared it's allocated. */
+#define RTHEAPSIMPLEBLOCK_FLAGS_FREE        ((uintptr_t)RT_BIT(0))
+/** The magic value. */
+#define RTHEAPSIMPLEBLOCK_FLAGS_MAGIC       ((uintptr_t)0xabcdef00)
+/** The mask that needs to be applied to RTHEAPSIMPLEBLOCK::fFlags to obtain the magic value. */
+#define RTHEAPSIMPLEBLOCK_FLAGS_MAGIC_MASK  (~(uintptr_t)RT_BIT(0))
+
+/**
+ * Checks if the specified block is valid or not.
+ * @returns boolean answer.
+ * @param   pBlock      Pointer to a RTHEAPSIMPLEBLOCK structure.
+ */
+#define RTHEAPSIMPLEBLOCK_IS_VALID(pBlock)  \
+    ( ((pBlock)->fFlags & RTHEAPSIMPLEBLOCK_FLAGS_MAGIC_MASK) == RTHEAPSIMPLEBLOCK_FLAGS_MAGIC )
+
+/**
+ * Checks if the specified block is valid and in use.
+ * @returns boolean answer.
+ * @param   pBlock      Pointer to a RTHEAPSIMPLEBLOCK structure.
+ */
+#define RTHEAPSIMPLEBLOCK_IS_VALID_USED(pBlock)  \
+    ( ((pBlock)->fFlags & (RTHEAPSIMPLEBLOCK_FLAGS_MAGIC_MASK | RTHEAPSIMPLEBLOCK_FLAGS_FREE)) \
+       == RTHEAPSIMPLEBLOCK_FLAGS_MAGIC )
+
+/**
+ * Checks if the specified block is valid and free.
+ * @returns boolean answer.
+ * @param   pBlock      Pointer to a RTHEAPSIMPLEBLOCK structure.
+ */
+#define RTHEAPSIMPLEBLOCK_IS_VALID_FREE(pBlock)  \
+    ( ((pBlock)->fFlags & (RTHEAPSIMPLEBLOCK_FLAGS_MAGIC_MASK | RTHEAPSIMPLEBLOCK_FLAGS_FREE)) \
+       == (RTHEAPSIMPLEBLOCK_FLAGS_MAGIC | RTHEAPSIMPLEBLOCK_FLAGS_FREE) )
+
+/**
+ * Checks if the specified block is free or not.
+ * @returns boolean answer.
+ * @param   pBlock      Pointer to a valid RTHEAPSIMPLEBLOCK structure.
+ */
+#define RTHEAPSIMPLEBLOCK_IS_FREE(pBlock)   (!!((pBlock)->fFlags & RTHEAPSIMPLEBLOCK_FLAGS_FREE))
+
+/**
+ * A free heap block.
+ * This is an extended version of RTHEAPSIMPLEBLOCK that takes the unused
+ * user data to store free list pointers and a cached size value.
+ */
+typedef struct RTHEAPSIMPLEFREE
+{
+    /** Core stuff. */
+    RTHEAPSIMPLEBLOCK       Core;
+    /** Pointer to the next free block. */
+    PRTHEAPSIMPLEFREE       pNext;
+    /** Pointer to the previous free block. */
+    PRTHEAPSIMPLEFREE       pPrev;
+    /** The size of the block (excluding the RTHEAPSIMPLEBLOCK part). */
+    size_t                  cb;
+    /** An alignment filler to make it a multiple of (sizeof(void *) * 2). */
+    size_t                  Alignment;
+} RTHEAPSIMPLEFREE;
+
+
+/**
+ * The heap anchor block.
+ * This structure is placed at the head of the memory block specified to RTHeapSimpleInit(),
+ * which means that the first RTHEAPSIMPLEBLOCK appears immediately after this structure.
+ */
+typedef struct RTHEAPSIMPLEINTERNAL
+{
+    /** The typical magic (RTHEAPSIMPLE_MAGIC). */
+    size_t                  uMagic;
+    /** The heap size. (This structure is included!) */
+    size_t                  cbHeap;
+    /** Pointer to the end of the heap. */
+    void                   *pvEnd;
+    /** The amount of free memory in the heap. */
+    size_t                  cbFree;
+    /** Free head pointer. */
+    PRTHEAPSIMPLEFREE       pFreeHead;
+    /** Free tail pointer. */
+    PRTHEAPSIMPLEFREE       pFreeTail;
+    /** Make the size of this structure is a multiple of 32. */
+    size_t                  auAlignment[2];
+} RTHEAPSIMPLEINTERNAL;
+AssertCompileSizeAlignment(RTHEAPSIMPLEINTERNAL, 32);
+
+
+/** The minimum allocation size. */
+#define RTHEAPSIMPLE_MIN_BLOCK  (sizeof(RTHEAPSIMPLEBLOCK))
+AssertCompile(RTHEAPSIMPLE_MIN_BLOCK >= sizeof(RTHEAPSIMPLEBLOCK));
+AssertCompile(RTHEAPSIMPLE_MIN_BLOCK >= sizeof(RTHEAPSIMPLEFREE) - sizeof(RTHEAPSIMPLEBLOCK));
+
+/** The minimum and default alignment.  */
+#define RTHEAPSIMPLE_ALIGNMENT  (sizeof(RTHEAPSIMPLEBLOCK))
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+#ifdef RT_STRICT
+# define RTHEAPSIMPLE_STRICT 1
+#endif
+
+#define ASSERT_L(a, b)    AssertMsg((uintptr_t)(a) <  (uintptr_t)(b), ("a=%p b=%p\n", (uintptr_t)(a), (uintptr_t)(b)))
+#define ASSERT_LE(a, b)   AssertMsg((uintptr_t)(a) <= (uintptr_t)(b), ("a=%p b=%p\n", (uintptr_t)(a), (uintptr_t)(b)))
+#define ASSERT_G(a, b)    AssertMsg((uintptr_t)(a) >  (uintptr_t)(b), ("a=%p b=%p\n", (uintptr_t)(a), (uintptr_t)(b)))
+#define ASSERT_GE(a, b)   AssertMsg((uintptr_t)(a) >= (uintptr_t)(b), ("a=%p b=%p\n", (uintptr_t)(a), (uintptr_t)(b)))
+#define ASSERT_ALIGN(a)   AssertMsg(!((uintptr_t)(a) & (RTHEAPSIMPLE_ALIGNMENT - 1)), ("a=%p\n", (uintptr_t)(a)))
+
+#define ASSERT_PREV(pHeapInt, pBlock)  \
+    do { ASSERT_ALIGN((pBlock)->pPrev); \
+         if ((pBlock)->pPrev) \
+         { \
+             ASSERT_L((pBlock)->pPrev, (pBlock)); \
+             ASSERT_GE((pBlock)->pPrev, (pHeapInt) + 1); \
+         } \
+         else \
+             Assert((pBlock) == (PRTHEAPSIMPLEBLOCK)((pHeapInt) + 1)); \
+    } while (0)
+
+#define ASSERT_NEXT(pHeap, pBlock) \
+    do { ASSERT_ALIGN((pBlock)->pNext); \
+         if ((pBlock)->pNext) \
+         { \
+             ASSERT_L((pBlock)->pNext, (pHeapInt)->pvEnd); \
+             ASSERT_G((pBlock)->pNext, (pBlock)); \
+         } \
+    } while (0)
+
+#define ASSERT_BLOCK(pHeapInt, pBlock) \
+    do { AssertMsg(RTHEAPSIMPLEBLOCK_IS_VALID(pBlock), ("%#x\n", (pBlock)->fFlags)); \
+         AssertMsg((pBlock)->pHeap == (pHeapInt), ("%p != %p\n", (pBlock)->pHeap, (pHeapInt))); \
+         ASSERT_GE((pBlock), (pHeapInt) + 1); \
+         ASSERT_L((pBlock), (pHeapInt)->pvEnd); \
+         ASSERT_NEXT(pHeapInt, pBlock); \
+         ASSERT_PREV(pHeapInt, pBlock); \
+    } while (0)
+
+#define ASSERT_BLOCK_USED(pHeapInt, pBlock) \
+    do { AssertMsg(RTHEAPSIMPLEBLOCK_IS_VALID_USED((pBlock)), ("%#x\n", (pBlock)->fFlags)); \
+         AssertMsg((pBlock)->pHeap == (pHeapInt), ("%p != %p\n", (pBlock)->pHeap, (pHeapInt))); \
+         ASSERT_GE((pBlock), (pHeapInt) + 1); \
+         ASSERT_L((pBlock), (pHeapInt)->pvEnd); \
+         ASSERT_NEXT(pHeapInt, pBlock); \
+         ASSERT_PREV(pHeapInt, pBlock); \
+    } while (0)
+
+#define ASSERT_FREE_PREV(pHeapInt, pBlock) \
+    do { ASSERT_ALIGN((pBlock)->pPrev); \
+         if ((pBlock)->pPrev) \
+         { \
+             ASSERT_GE((pBlock)->pPrev, (pHeapInt)->pFreeHead); \
+             ASSERT_L((pBlock)->pPrev, (pBlock)); \
+             ASSERT_LE((pBlock)->pPrev, (pBlock)->Core.pPrev); \
+         } \
+         else \
+             Assert((pBlock) == (pHeapInt)->pFreeHead); \
+    } while (0)
+
+#define ASSERT_FREE_NEXT(pHeapInt, pBlock) \
+    do { ASSERT_ALIGN((pBlock)->pNext); \
+         if ((pBlock)->pNext) \
+         { \
+             ASSERT_LE((pBlock)->pNext, (pHeapInt)->pFreeTail); \
+             ASSERT_G((pBlock)->pNext, (pBlock)); \
+             ASSERT_GE((pBlock)->pNext, (pBlock)->Core.pNext); \
+         } \
+         else \
+             Assert((pBlock) == (pHeapInt)->pFreeTail); \
+    } while (0)
+
+#ifdef RTHEAPSIMPLE_STRICT
+# define ASSERT_FREE_CB(pHeapInt, pBlock) \
+    do { size_t cbCalc = ((pBlock)->Core.pNext ? (uintptr_t)(pBlock)->Core.pNext : (uintptr_t)(pHeapInt)->pvEnd) \
+                       - (uintptr_t)(pBlock) - sizeof(RTHEAPSIMPLEBLOCK); \
+         AssertMsg((pBlock)->cb == cbCalc, ("cb=%#zx cbCalc=%#zx\n", (pBlock)->cb, cbCalc)); \
+    } while (0)
+#else
+# define ASSERT_FREE_CB(pHeapInt, pBlock) do {} while (0)
+#endif
+
+/** Asserts that a free block is valid. */
+#define ASSERT_BLOCK_FREE(pHeapInt, pBlock) \
+    do { ASSERT_BLOCK(pHeapInt, &(pBlock)->Core); \
+         Assert(RTHEAPSIMPLEBLOCK_IS_VALID_FREE(&(pBlock)->Core)); \
+         ASSERT_GE((pBlock), (pHeapInt)->pFreeHead); \
+         ASSERT_LE((pBlock), (pHeapInt)->pFreeTail); \
+         ASSERT_FREE_NEXT(pHeapInt, pBlock); \
+         ASSERT_FREE_PREV(pHeapInt, pBlock); \
+         ASSERT_FREE_CB(pHeapInt, pBlock); \
+    } while (0)
+
+/** Asserts that the heap anchor block is ok. */
+#define ASSERT_ANCHOR(pHeapInt) \
+    do { AssertPtr(pHeapInt);\
+         Assert((pHeapInt)->uMagic == RTHEAPSIMPLE_MAGIC); \
+    } while (0)
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+#ifdef RTHEAPSIMPLE_STRICT
+static void rtHeapSimpleAssertAll(PRTHEAPSIMPLEINTERNAL pHeapInt);
+#endif
+static PRTHEAPSIMPLEBLOCK rtHeapSimpleAllocBlock(PRTHEAPSIMPLEINTERNAL pHeapInt, size_t cb, size_t uAlignment);
+static void rtHeapSimpleFreeBlock(PRTHEAPSIMPLEINTERNAL pHeapInt, PRTHEAPSIMPLEBLOCK pBlock);
+
+
+RTDECL(int) RTHeapSimpleInit(PRTHEAPSIMPLE phHeap, void *pvMemory, size_t cbMemory)
+{
+    PRTHEAPSIMPLEINTERNAL pHeapInt;
+    PRTHEAPSIMPLEFREE pFree;
+    unsigned i;
+
+    /*
+     * Validate input. The imposed minimum heap size is just a convenient value.
+     */
+    AssertReturn(cbMemory >= PAGE_SIZE, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pvMemory, VERR_INVALID_POINTER);
+    AssertReturn((uintptr_t)pvMemory + (cbMemory - 1) > (uintptr_t)cbMemory, VERR_INVALID_PARAMETER);
+
+    /*
+     * Place the heap anchor block at the start of the heap memory,
+     * enforce 32 byte alignment of it. Also align the heap size correctly.
+     */
+    pHeapInt = (PRTHEAPSIMPLEINTERNAL)pvMemory;
+    if ((uintptr_t)pvMemory & 31)
+    {
+        const uintptr_t off = 32 - ((uintptr_t)pvMemory & 31);
+        cbMemory -= off;
+        pHeapInt = (PRTHEAPSIMPLEINTERNAL)((uintptr_t)pvMemory + off);
+    }
+    cbMemory &= ~(RTHEAPSIMPLE_ALIGNMENT - 1);
+
+
+    /* Init the heap anchor block. */
+    pHeapInt->uMagic = RTHEAPSIMPLE_MAGIC;
+    pHeapInt->pvEnd = (uint8_t *)pHeapInt + cbMemory;
+    pHeapInt->cbHeap = cbMemory;
+    pHeapInt->cbFree = cbMemory
+                     - sizeof(RTHEAPSIMPLEBLOCK)
+                     - sizeof(RTHEAPSIMPLEINTERNAL);
+    pHeapInt->pFreeTail = pHeapInt->pFreeHead = (PRTHEAPSIMPLEFREE)(pHeapInt + 1);
+    for (i = 0; i < RT_ELEMENTS(pHeapInt->auAlignment); i++)
+        pHeapInt->auAlignment[i] = ~(size_t)0;
+
+    /* Init the single free block. */
+    pFree = pHeapInt->pFreeHead;
+    pFree->Core.pNext = NULL;
+    pFree->Core.pPrev = NULL;
+    pFree->Core.pHeap = pHeapInt;
+    pFree->Core.fFlags = RTHEAPSIMPLEBLOCK_FLAGS_MAGIC | RTHEAPSIMPLEBLOCK_FLAGS_FREE;
+    pFree->pNext = NULL;
+    pFree->pPrev = NULL;
+    pFree->cb = pHeapInt->cbFree;
+
+    *phHeap = pHeapInt;
+
+#ifdef RTHEAPSIMPLE_STRICT
+    rtHeapSimpleAssertAll(pHeapInt);
+#endif
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTHeapSimpleInit);
+
+
+RTDECL(int) RTHeapSimpleRelocate(RTHEAPSIMPLE hHeap, uintptr_t offDelta)
+{
+    PRTHEAPSIMPLEINTERNAL   pHeapInt = hHeap;
+    PRTHEAPSIMPLEFREE       pCur;
+
+    /*
+     * Validate input.
+     */
+    AssertPtrReturn(pHeapInt, VERR_INVALID_HANDLE);
+    AssertReturn(pHeapInt->uMagic == RTHEAPSIMPLE_MAGIC, VERR_INVALID_HANDLE);
+    AssertMsgReturn((uintptr_t)pHeapInt - (uintptr_t)pHeapInt->pvEnd + pHeapInt->cbHeap == offDelta,
+                    ("offDelta=%p, expected=%p\n", offDelta, (uintptr_t)pHeapInt->pvEnd - pHeapInt->cbHeap - (uintptr_t)pHeapInt),
+                    VERR_INVALID_PARAMETER);
+
+    /*
+     * Relocate the heap anchor block.
+     */
+#define RELOCATE_IT(var, type, offDelta)    do { if (RT_UNLIKELY((var) != NULL)) { (var) = (type)((uintptr_t)(var) + offDelta); } } while (0)
+    RELOCATE_IT(pHeapInt->pvEnd,     void *,            offDelta);
+    RELOCATE_IT(pHeapInt->pFreeHead, PRTHEAPSIMPLEFREE, offDelta);
+    RELOCATE_IT(pHeapInt->pFreeTail, PRTHEAPSIMPLEFREE, offDelta);
+
+    /*
+     * Walk the heap blocks.
+     */
+    for (pCur = (PRTHEAPSIMPLEFREE)(pHeapInt + 1);
+         pCur && (uintptr_t)pCur < (uintptr_t)pHeapInt->pvEnd;
+         pCur = (PRTHEAPSIMPLEFREE)pCur->Core.pNext)
+    {
+        RELOCATE_IT(pCur->Core.pNext, PRTHEAPSIMPLEBLOCK,    offDelta);
+        RELOCATE_IT(pCur->Core.pPrev, PRTHEAPSIMPLEBLOCK,    offDelta);
+        RELOCATE_IT(pCur->Core.pHeap, PRTHEAPSIMPLEINTERNAL, offDelta);
+        if (RTHEAPSIMPLEBLOCK_IS_FREE(&pCur->Core))
+        {
+            RELOCATE_IT(pCur->pNext, PRTHEAPSIMPLEFREE, offDelta);
+            RELOCATE_IT(pCur->pPrev, PRTHEAPSIMPLEFREE, offDelta);
+        }
+    }
+#undef RELOCATE_IT
+
+#ifdef RTHEAPSIMPLE_STRICT
+    /*
+     * Give it a once over before we return.
+     */
+    rtHeapSimpleAssertAll(pHeapInt);
+#endif
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTHeapSimpleRelocate);
+
+
+RTDECL(void *) RTHeapSimpleAlloc(RTHEAPSIMPLE hHeap, size_t cb, size_t cbAlignment)
+{
+    PRTHEAPSIMPLEINTERNAL pHeapInt = hHeap;
+    PRTHEAPSIMPLEBLOCK pBlock;
+
+    /*
+     * Validate and adjust the input.
+     */
+    AssertPtrReturn(pHeapInt, NULL);
+    if (cb < RTHEAPSIMPLE_MIN_BLOCK)
+        cb = RTHEAPSIMPLE_MIN_BLOCK;
+    else
+        cb = RT_ALIGN_Z(cb, RTHEAPSIMPLE_ALIGNMENT);
+    if (!cbAlignment)
+        cbAlignment = RTHEAPSIMPLE_ALIGNMENT;
+    else
+    {
+        Assert(!(cbAlignment & (cbAlignment - 1)));
+        Assert((cbAlignment & ~(cbAlignment - 1)) == cbAlignment);
+        if (cbAlignment < RTHEAPSIMPLE_ALIGNMENT)
+            cbAlignment = RTHEAPSIMPLE_ALIGNMENT;
+    }
+
+    /*
+     * Do the allocation.
+     */
+    pBlock = rtHeapSimpleAllocBlock(pHeapInt, cb, cbAlignment);
+    if (RT_LIKELY(pBlock))
+    {
+        void *pv = pBlock + 1;
+        return pv;
+    }
+    return NULL;
+}
+RT_EXPORT_SYMBOL(RTHeapSimpleAlloc);
+
+
+RTDECL(void *) RTHeapSimpleAllocZ(RTHEAPSIMPLE hHeap, size_t cb, size_t cbAlignment)
+{
+    PRTHEAPSIMPLEINTERNAL pHeapInt = hHeap;
+    PRTHEAPSIMPLEBLOCK pBlock;
+
+    /*
+     * Validate and adjust the input.
+     */
+    AssertPtrReturn(pHeapInt, NULL);
+    if (cb < RTHEAPSIMPLE_MIN_BLOCK)
+        cb = RTHEAPSIMPLE_MIN_BLOCK;
+    else
+        cb = RT_ALIGN_Z(cb, RTHEAPSIMPLE_ALIGNMENT);
+    if (!cbAlignment)
+        cbAlignment = RTHEAPSIMPLE_ALIGNMENT;
+    else
+    {
+        Assert(!(cbAlignment & (cbAlignment - 1)));
+        Assert((cbAlignment & ~(cbAlignment - 1)) == cbAlignment);
+        if (cbAlignment < RTHEAPSIMPLE_ALIGNMENT)
+            cbAlignment = RTHEAPSIMPLE_ALIGNMENT;
+    }
+
+    /*
+     * Do the allocation.
+     */
+    pBlock = rtHeapSimpleAllocBlock(pHeapInt, cb, cbAlignment);
+    if (RT_LIKELY(pBlock))
+    {
+        void *pv = pBlock + 1;
+        memset(pv, 0, cb);
+        return pv;
+    }
+    return NULL;
+}
+RT_EXPORT_SYMBOL(RTHeapSimpleAllocZ);
+
+
+/**
+ * Allocates a block of memory from the specified heap.
+ *
+ * No parameter validation or adjustment is performed.
+ *
+ * @returns Pointer to the allocated block.
+ * @returns NULL on failure.
+ *
+ * @param   pHeapInt    The heap.
+ * @param   cb          Size of the memory block to allocate.
+ * @param   uAlignment  The alignment specifications for the allocated block.
+ */
+static PRTHEAPSIMPLEBLOCK rtHeapSimpleAllocBlock(PRTHEAPSIMPLEINTERNAL pHeapInt, size_t cb, size_t uAlignment)
+{
+    PRTHEAPSIMPLEBLOCK  pRet = NULL;
+    PRTHEAPSIMPLEFREE   pFree;
+
+#ifdef RTHEAPSIMPLE_STRICT
+    rtHeapSimpleAssertAll(pHeapInt);
+#endif
+
+    /*
+     * Search for a fitting block from the lower end of the heap.
+     */
+    for (pFree = pHeapInt->pFreeHead;
+         pFree;
+         pFree = pFree->pNext)
+    {
+        uintptr_t offAlign;
+        ASSERT_BLOCK_FREE(pHeapInt, pFree);
+
+        /*
+         * Match for size and alignment.
+         */
+        if (pFree->cb < cb)
+            continue;
+        offAlign = (uintptr_t)(&pFree->Core + 1) & (uAlignment - 1);
+        if (offAlign)
+        {
+            RTHEAPSIMPLEFREE Free;
+            PRTHEAPSIMPLEBLOCK pPrev;
+
+            offAlign = uAlignment - offAlign;
+            if (pFree->cb - offAlign < cb)
+                continue;
+
+            /*
+             * Make a stack copy of the free block header and adjust the pointer.
+             */
+            Free = *pFree;
+            pFree = (PRTHEAPSIMPLEFREE)((uintptr_t)pFree + offAlign);
+
+            /*
+             * Donate offAlign bytes to the node in front of us.
+             * If we're the head node, we'll have to create a fake node. We'll
+             * mark it USED for simplicity.
+             *
+             * (Should this policy of donating memory to the guy in front of us
+             * cause big 'leaks', we could create a new free node if there is room
+             * for that.)
+             */
+            pPrev = Free.Core.pPrev;
+            if (pPrev)
+            {
+                AssertMsg(!RTHEAPSIMPLEBLOCK_IS_FREE(pPrev), ("Impossible!\n"));
+                pPrev->pNext = &pFree->Core;
+            }
+            else
+            {
+                pPrev = (PRTHEAPSIMPLEBLOCK)(pHeapInt + 1);
+                Assert(pPrev == &pFree->Core);
+                pPrev->pPrev = NULL;
+                pPrev->pNext = &pFree->Core;
+                pPrev->pHeap = pHeapInt;
+                pPrev->fFlags = RTHEAPSIMPLEBLOCK_FLAGS_MAGIC;
+            }
+            pHeapInt->cbFree -= offAlign;
+
+            /*
+             * Recreate pFree in the new position and adjust the neighbors.
+             */
+            *pFree = Free;
+
+            /* the core */
+            if (pFree->Core.pNext)
+                pFree->Core.pNext->pPrev = &pFree->Core;
+            pFree->Core.pPrev = pPrev;
+
+            /* the free part */
+            pFree->cb -= offAlign;
+            if (pFree->pNext)
+                pFree->pNext->pPrev = pFree;
+            else
+                pHeapInt->pFreeTail = pFree;
+            if (pFree->pPrev)
+                pFree->pPrev->pNext = pFree;
+            else
+                pHeapInt->pFreeHead = pFree;
+            ASSERT_BLOCK_FREE(pHeapInt, pFree);
+            ASSERT_BLOCK_USED(pHeapInt, pPrev);
+        }
+
+        /*
+         * Split off a new FREE block?
+         */
+        if (pFree->cb >= cb + RT_ALIGN_Z(sizeof(RTHEAPSIMPLEFREE), RTHEAPSIMPLE_ALIGNMENT))
+        {
+            /*
+             * Move the FREE block up to make room for the new USED block.
+             */
+            PRTHEAPSIMPLEFREE   pNew = (PRTHEAPSIMPLEFREE)((uintptr_t)&pFree->Core + cb + sizeof(RTHEAPSIMPLEBLOCK));
+
+            pNew->Core.pNext = pFree->Core.pNext;
+            if (pFree->Core.pNext)
+                pFree->Core.pNext->pPrev = &pNew->Core;
+            pNew->Core.pPrev = &pFree->Core;
+            pNew->Core.pHeap = pHeapInt;
+            pNew->Core.fFlags = RTHEAPSIMPLEBLOCK_FLAGS_MAGIC | RTHEAPSIMPLEBLOCK_FLAGS_FREE;
+
+            pNew->pNext = pFree->pNext;
+            if (pNew->pNext)
+                pNew->pNext->pPrev = pNew;
+            else
+                pHeapInt->pFreeTail = pNew;
+            pNew->pPrev = pFree->pPrev;
+            if (pNew->pPrev)
+                pNew->pPrev->pNext = pNew;
+            else
+                pHeapInt->pFreeHead = pNew;
+            pNew->cb    = (pNew->Core.pNext ? (uintptr_t)pNew->Core.pNext : (uintptr_t)pHeapInt->pvEnd) \
+                        - (uintptr_t)pNew - sizeof(RTHEAPSIMPLEBLOCK);
+            ASSERT_BLOCK_FREE(pHeapInt, pNew);
+
+            /*
+             * Update the old FREE node making it a USED node.
+             */
+            pFree->Core.fFlags &= ~RTHEAPSIMPLEBLOCK_FLAGS_FREE;
+            pFree->Core.pNext = &pNew->Core;
+            pHeapInt->cbFree -= pFree->cb;
+            pHeapInt->cbFree += pNew->cb;
+            pRet = &pFree->Core;
+            ASSERT_BLOCK_USED(pHeapInt, pRet);
+        }
+        else
+        {
+            /*
+             * Link it out of the free list.
+             */
+            if (pFree->pNext)
+                pFree->pNext->pPrev = pFree->pPrev;
+            else
+                pHeapInt->pFreeTail = pFree->pPrev;
+            if (pFree->pPrev)
+                pFree->pPrev->pNext = pFree->pNext;
+            else
+                pHeapInt->pFreeHead = pFree->pNext;
+
+            /*
+             * Convert it to a used block.
+             */
+            pHeapInt->cbFree -= pFree->cb;
+            pFree->Core.fFlags &= ~RTHEAPSIMPLEBLOCK_FLAGS_FREE;
+            pRet = &pFree->Core;
+            ASSERT_BLOCK_USED(pHeapInt, pRet);
+        }
+        break;
+    }
+
+#ifdef RTHEAPSIMPLE_STRICT
+    rtHeapSimpleAssertAll(pHeapInt);
+#endif
+    return pRet;
+}
+
+
+RTDECL(void) RTHeapSimpleFree(RTHEAPSIMPLE hHeap, void *pv)
+{
+    PRTHEAPSIMPLEINTERNAL pHeapInt;
+    PRTHEAPSIMPLEBLOCK pBlock;
+
+    /*
+     * Validate input.
+     */
+    if (!pv)
+        return;
+    AssertPtr(pv);
+    Assert(RT_ALIGN_P(pv, RTHEAPSIMPLE_ALIGNMENT) == pv);
+
+    /*
+     * Get the block and heap. If in strict mode, validate these.
+     */
+    pBlock = (PRTHEAPSIMPLEBLOCK)pv - 1;
+    pHeapInt = pBlock->pHeap;
+    ASSERT_BLOCK_USED(pHeapInt, pBlock);
+    ASSERT_ANCHOR(pHeapInt);
+    Assert(pHeapInt == (PRTHEAPSIMPLEINTERNAL)hHeap || !hHeap); RT_NOREF_PV(hHeap);
+
+#ifdef RTHEAPSIMPLE_FREE_POISON
+    /*
+     * Poison the block.
+     */
+    const size_t cbBlock = (pBlock->pNext ? (uintptr_t)pBlock->pNext : (uintptr_t)pHeapInt->pvEnd)
+                         - (uintptr_t)pBlock - sizeof(RTHEAPSIMPLEBLOCK);
+    memset(pBlock + 1, RTHEAPSIMPLE_FREE_POISON, cbBlock);
+#endif
+
+    /*
+     * Call worker which does the actual job.
+     */
+    rtHeapSimpleFreeBlock(pHeapInt, pBlock);
+}
+RT_EXPORT_SYMBOL(RTHeapSimpleFree);
+
+
+/**
+ * Free a memory block.
+ *
+ * @param   pHeapInt       The heap.
+ * @param   pBlock         The memory block to free.
+ */
+static void rtHeapSimpleFreeBlock(PRTHEAPSIMPLEINTERNAL pHeapInt, PRTHEAPSIMPLEBLOCK pBlock)
+{
+    PRTHEAPSIMPLEFREE   pFree = (PRTHEAPSIMPLEFREE)pBlock;
+    PRTHEAPSIMPLEFREE   pLeft;
+    PRTHEAPSIMPLEFREE   pRight;
+
+#ifdef RTHEAPSIMPLE_STRICT
+    rtHeapSimpleAssertAll(pHeapInt);
+#endif
+
+    /*
+     * Look for the closest free list blocks by walking the blocks right
+     * of us (both lists are sorted by address).
+     */
+    pLeft = NULL;
+    pRight = NULL;
+    if (pHeapInt->pFreeTail)
+    {
+        pRight = (PRTHEAPSIMPLEFREE)pFree->Core.pNext;
+        while (pRight && !RTHEAPSIMPLEBLOCK_IS_FREE(&pRight->Core))
+        {
+            ASSERT_BLOCK(pHeapInt, &pRight->Core);
+            pRight = (PRTHEAPSIMPLEFREE)pRight->Core.pNext;
+        }
+        if (!pRight)
+            pLeft = pHeapInt->pFreeTail;
+        else
+        {
+            ASSERT_BLOCK_FREE(pHeapInt, pRight);
+            pLeft = pRight->pPrev;
+        }
+        if (pLeft)
+            ASSERT_BLOCK_FREE(pHeapInt, pLeft);
+    }
+    AssertMsgReturnVoid(pLeft != pFree, ("Freed twice! pv=%p (pBlock=%p)\n", pBlock + 1, pBlock));
+    ASSERT_L(pLeft, pFree);
+    Assert(!pRight || (uintptr_t)pRight > (uintptr_t)pFree);
+    Assert(!pLeft || pLeft->pNext == pRight);
+
+    /*
+     * Insert at the head of the free block list?
+     */
+    if (!pLeft)
+    {
+        Assert(pRight == pHeapInt->pFreeHead);
+        pFree->Core.fFlags |= RTHEAPSIMPLEBLOCK_FLAGS_FREE;
+        pFree->pPrev = NULL;
+        pFree->pNext = pRight;
+        if (pRight)
+            pRight->pPrev = pFree;
+        else
+            pHeapInt->pFreeTail = pFree;
+        pHeapInt->pFreeHead = pFree;
+    }
+    else
+    {
+        /*
+         * Can we merge with left hand free block?
+         */
+        if (pLeft->Core.pNext == &pFree->Core)
+        {
+            pLeft->Core.pNext = pFree->Core.pNext;
+            if (pFree->Core.pNext)
+                pFree->Core.pNext->pPrev = &pLeft->Core;
+            pHeapInt->cbFree -= pLeft->cb;
+            pFree = pLeft;
+        }
+        /*
+         * No, just link it into the free list then.
+         */
+        else
+        {
+            pFree->Core.fFlags |= RTHEAPSIMPLEBLOCK_FLAGS_FREE;
+            pFree->pNext = pRight;
+            pFree->pPrev = pLeft;
+            pLeft->pNext = pFree;
+            if (pRight)
+                pRight->pPrev = pFree;
+            else
+                pHeapInt->pFreeTail = pFree;
+        }
+    }
+
+    /*
+     * Can we merge with right hand free block?
+     */
+    if (    pRight
+        &&  pRight->Core.pPrev == &pFree->Core)
+    {
+        /* core */
+        pFree->Core.pNext = pRight->Core.pNext;
+        if (pRight->Core.pNext)
+            pRight->Core.pNext->pPrev = &pFree->Core;
+
+        /* free */
+        pFree->pNext = pRight->pNext;
+        if (pRight->pNext)
+            pRight->pNext->pPrev = pFree;
+        else
+            pHeapInt->pFreeTail = pFree;
+        pHeapInt->cbFree -= pRight->cb;
+    }
+
+    /*
+     * Calculate the size and update free stats.
+     */
+    pFree->cb = (pFree->Core.pNext ? (uintptr_t)pFree->Core.pNext : (uintptr_t)pHeapInt->pvEnd)
+              - (uintptr_t)pFree - sizeof(RTHEAPSIMPLEBLOCK);
+    pHeapInt->cbFree += pFree->cb;
+    ASSERT_BLOCK_FREE(pHeapInt, pFree);
+
+#ifdef RTHEAPSIMPLE_STRICT
+    rtHeapSimpleAssertAll(pHeapInt);
+#endif
+}
+
+
+#ifdef RTHEAPSIMPLE_STRICT
+/**
+ * Internal consistency check (relying on assertions).
+ * @param   pHeapInt
+ */
+static void rtHeapSimpleAssertAll(PRTHEAPSIMPLEINTERNAL pHeapInt)
+{
+    PRTHEAPSIMPLEFREE pPrev = NULL;
+    PRTHEAPSIMPLEFREE pPrevFree = NULL;
+    PRTHEAPSIMPLEFREE pBlock;
+    for (pBlock = (PRTHEAPSIMPLEFREE)(pHeapInt + 1);
+         pBlock;
+         pBlock = (PRTHEAPSIMPLEFREE)pBlock->Core.pNext)
+    {
+        if (RTHEAPSIMPLEBLOCK_IS_FREE(&pBlock->Core))
+        {
+            ASSERT_BLOCK_FREE(pHeapInt, pBlock);
+            Assert(pBlock->pPrev == pPrevFree);
+            Assert(pPrevFree || pHeapInt->pFreeHead == pBlock);
+            pPrevFree = pBlock;
+        }
+        else
+            ASSERT_BLOCK_USED(pHeapInt, &pBlock->Core);
+        Assert(!pPrev || pPrev == (PRTHEAPSIMPLEFREE)pBlock->Core.pPrev);
+        pPrev = pBlock;
+    }
+    Assert(pHeapInt->pFreeTail == pPrevFree);
+}
+#endif
+
+
+RTDECL(size_t) RTHeapSimpleSize(RTHEAPSIMPLE hHeap, void *pv)
+{
+    PRTHEAPSIMPLEINTERNAL pHeapInt;
+    PRTHEAPSIMPLEBLOCK pBlock;
+    size_t cbBlock;
+
+    /*
+     * Validate input.
+     */
+    if (!pv)
+        return 0;
+    AssertPtrReturn(pv, 0);
+    AssertReturn(RT_ALIGN_P(pv, RTHEAPSIMPLE_ALIGNMENT) == pv, 0);
+
+    /*
+     * Get the block and heap. If in strict mode, validate these.
+     */
+    pBlock = (PRTHEAPSIMPLEBLOCK)pv - 1;
+    pHeapInt = pBlock->pHeap;
+    ASSERT_BLOCK_USED(pHeapInt, pBlock);
+    ASSERT_ANCHOR(pHeapInt);
+    Assert(pHeapInt == (PRTHEAPSIMPLEINTERNAL)hHeap || !hHeap); RT_NOREF_PV(hHeap);
+
+    /*
+     * Calculate the block size.
+     */
+    cbBlock = (pBlock->pNext ? (uintptr_t)pBlock->pNext : (uintptr_t)pHeapInt->pvEnd)
+            - (uintptr_t)pBlock- sizeof(RTHEAPSIMPLEBLOCK);
+    return cbBlock;
+}
+RT_EXPORT_SYMBOL(RTHeapSimpleSize);
+
+
+RTDECL(size_t) RTHeapSimpleGetHeapSize(RTHEAPSIMPLE hHeap)
+{
+    PRTHEAPSIMPLEINTERNAL pHeapInt;
+
+    if (hHeap == NIL_RTHEAPSIMPLE)
+        return 0;
+
+    pHeapInt = hHeap;
+    AssertPtrReturn(pHeapInt, 0);
+    ASSERT_ANCHOR(pHeapInt);
+    return pHeapInt->cbHeap;
+}
+RT_EXPORT_SYMBOL(RTHeapSimpleGetHeapSize);
+
+
+RTDECL(size_t) RTHeapSimpleGetFreeSize(RTHEAPSIMPLE hHeap)
+{
+    PRTHEAPSIMPLEINTERNAL pHeapInt;
+
+    if (hHeap == NIL_RTHEAPSIMPLE)
+        return 0;
+
+    pHeapInt = hHeap;
+    AssertPtrReturn(pHeapInt, 0);
+    ASSERT_ANCHOR(pHeapInt);
+    return pHeapInt->cbFree;
+}
+RT_EXPORT_SYMBOL(RTHeapSimpleGetFreeSize);
+
+
+RTDECL(void) RTHeapSimpleDump(RTHEAPSIMPLE hHeap, PFNRTHEAPSIMPLEPRINTF pfnPrintf)
+{
+    PRTHEAPSIMPLEINTERNAL pHeapInt = (PRTHEAPSIMPLEINTERNAL)hHeap;
+    PRTHEAPSIMPLEFREE pBlock;
+
+    pfnPrintf("**** Dumping Heap %p - cbHeap=%zx cbFree=%zx ****\n",
+              hHeap, pHeapInt->cbHeap, pHeapInt->cbFree);
+
+    for (pBlock = (PRTHEAPSIMPLEFREE)(pHeapInt + 1);
+         pBlock;
+         pBlock = (PRTHEAPSIMPLEFREE)pBlock->Core.pNext)
+    {
+        size_t cb = (pBlock->pNext ? (uintptr_t)pBlock->Core.pNext : (uintptr_t)pHeapInt->pvEnd)
+                  - (uintptr_t)pBlock - sizeof(RTHEAPSIMPLEBLOCK);
+        if (RTHEAPSIMPLEBLOCK_IS_FREE(&pBlock->Core))
+            pfnPrintf("%p  %06x FREE pNext=%p pPrev=%p fFlags=%#x cb=%#06x : cb=%#06x pNext=%p pPrev=%p\n",
+                      pBlock, (uintptr_t)pBlock - (uintptr_t)(pHeapInt + 1), pBlock->Core.pNext, pBlock->Core.pPrev, pBlock->Core.fFlags, cb,
+                      pBlock->cb, pBlock->pNext, pBlock->pPrev);
+        else
+            pfnPrintf("%p  %06x USED pNext=%p pPrev=%p fFlags=%#x cb=%#06x\n",
+                      pBlock, (uintptr_t)pBlock - (uintptr_t)(pHeapInt + 1), pBlock->Core.pNext, pBlock->Core.pPrev, pBlock->Core.fFlags, cb);
+    }
+    pfnPrintf("**** Done dumping Heap %p ****\n", hHeap);
+}
+RT_EXPORT_SYMBOL(RTHeapSimpleDump);
+
diff --git a/ubuntu/vbox/vboxguest/common/err/RTErrConvertFromErrno.c b/ubuntu/vbox/vboxguest/common/err/RTErrConvertFromErrno.c
new file mode 100644 (file)
index 0000000..8e6e242
--- /dev/null
@@ -0,0 +1,452 @@
+/* $Id: RTErrConvertFromErrno.cpp $ */
+/** @file
+ * IPRT - Convert errno to iprt status codes.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/err.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/errno.h>
+
+
+RTDECL(int)  RTErrConvertFromErrno(unsigned uNativeCode)
+{
+    /* very fast check for no error. */
+    if (uNativeCode == 0)
+        return VINF_SUCCESS;
+
+    /*
+     * Process error codes.
+     *
+     * (Use a switch and not a table since the numbers vary among compilers
+     * and OSes. So we let the compiler switch optimizer handle speed issues.)
+     *
+     * This switch is arranged like the Linux i386 errno.h! This switch is mirrored
+     * by RTErrConvertToErrno.
+     */
+    switch (uNativeCode)
+    {                                                                           /* Linux number */
+#ifdef EPERM
+        case EPERM:             return VERR_ACCESS_DENIED;                      /*   1 */
+#endif
+#ifdef ENOENT
+        case ENOENT:            return VERR_FILE_NOT_FOUND;
+#endif
+#ifdef ESRCH
+        case ESRCH:             return VERR_PROCESS_NOT_FOUND;
+#endif
+#ifdef EINTR
+        case EINTR:             return VERR_INTERRUPTED;
+#endif
+#ifdef EIO
+        case EIO:               return VERR_DEV_IO_ERROR;
+#endif
+#ifdef ENXIO
+        case ENXIO:             return VERR_DEV_IO_ERROR; /** @todo fix this duplicate error */
+#endif
+#ifdef E2BIG
+        case E2BIG:             return VERR_TOO_MUCH_DATA;
+#endif
+#ifdef ENOEXEC
+        case ENOEXEC:           return VERR_BAD_EXE_FORMAT;
+#endif
+#ifdef EBADF
+        case EBADF:             return VERR_INVALID_HANDLE;
+#endif
+#ifdef ECHILD
+        case ECHILD:            return VERR_PROCESS_NOT_FOUND;                  /*  10 */ /** @todo fix duplicate error */
+#endif
+#ifdef EAGAIN
+        case EAGAIN:            return VERR_TRY_AGAIN;
+#endif
+#ifdef ENOMEM
+        case ENOMEM:            return VERR_NO_MEMORY;
+#endif
+#ifdef EACCES
+        case EACCES:            return VERR_ACCESS_DENIED; /** @todo fix duplicate error */
+#endif
+#ifdef EFAULT
+        case EFAULT:            return VERR_INVALID_POINTER;
+#endif
+#ifdef ENOTBLK
+        //case ENOTBLK:           return VERR_;
+#endif
+#ifdef EBUSY
+        case EBUSY:             return VERR_RESOURCE_BUSY;
+#endif
+#ifdef EEXIST
+        case EEXIST:            return VERR_ALREADY_EXISTS;
+#endif
+#ifdef EXDEV
+        case EXDEV:             return VERR_NOT_SAME_DEVICE;
+#endif
+#ifdef ENODEV
+        case ENODEV:            return VERR_NOT_SUPPORTED; /** @todo fix duplicate error */
+#endif
+#ifdef ENOTDIR
+        case ENOTDIR:           return VERR_PATH_NOT_FOUND;                     /*  20 */
+#endif
+#ifdef EISDIR
+        case EISDIR:            return VERR_IS_A_DIRECTORY;
+#endif
+#ifdef EINVAL
+        case EINVAL:            return VERR_INVALID_PARAMETER;
+#endif
+#ifdef ENFILE
+        case ENFILE:            return VERR_TOO_MANY_OPEN_FILES; /** @todo fix duplicate error */
+#endif
+#ifdef EMFILE
+        case EMFILE:            return VERR_TOO_MANY_OPEN_FILES;
+#endif
+#ifdef ENOTTY
+        case ENOTTY:            return VERR_INVALID_FUNCTION;
+#endif
+#ifdef ETXTBSY
+        case ETXTBSY:           return VERR_SHARING_VIOLATION;
+#endif
+#ifdef EFBIG
+        case EFBIG:             return VERR_FILE_TOO_BIG;
+#endif
+#ifdef ENOSPC
+        case ENOSPC:            return VERR_DISK_FULL;
+#endif
+#ifdef ESPIPE
+        case ESPIPE:            return VERR_SEEK_ON_DEVICE;
+#endif
+#ifdef EROFS
+        case EROFS:             return VERR_WRITE_PROTECT;                      /*  30 */
+#endif
+#ifdef EMLINK
+        //case EMLINK:
+#endif
+#ifdef EPIPE
+        case EPIPE:             return VERR_BROKEN_PIPE;
+#endif
+#ifdef EDOM
+        case EDOM:              return VERR_INVALID_PARAMETER;  /** @todo fix duplicate error */
+#endif
+#ifdef ERANGE
+        case ERANGE:            return VERR_INVALID_PARAMETER;  /** @todo fix duplicate error */
+#endif
+#ifdef EDEADLK
+        case EDEADLK:           return VERR_DEADLOCK;
+#endif
+#ifdef ENAMETOOLONG
+        case ENAMETOOLONG:      return VERR_FILENAME_TOO_LONG;
+#endif
+#ifdef ENOLCK
+        case ENOLCK:            return VERR_FILE_LOCK_FAILED;
+#endif
+#ifdef ENOSYS /** @todo map this differently on solaris. */
+        case ENOSYS:            return VERR_NOT_SUPPORTED;
+#endif
+#ifdef ENOTEMPTY
+        case ENOTEMPTY:         return VERR_DIR_NOT_EMPTY;
+#endif
+#ifdef ELOOP
+        case ELOOP:             return VERR_TOO_MANY_SYMLINKS;                  /*  40 */
+#endif
+        //41??
+#ifdef ENOMSG
+        //case ENOMSG           42      /* No message of desired type */
+#endif
+#ifdef EIDRM
+        //case EIDRM            43      /* Identifier removed */
+#endif
+#ifdef ECHRNG
+        //case ECHRNG           44      /* Channel number out of range */
+#endif
+#ifdef EL2NSYNC
+        //case EL2NSYNC 45      /* Level 2 not synchronized */
+#endif
+#ifdef EL3HLT
+        //case EL3HLT           46      /* Level 3 halted */
+#endif
+#ifdef EL3RST
+        //case EL3RST           47      /* Level 3 reset */
+#endif
+#ifdef ELNRNG
+        //case ELNRNG           48      /* Link number out of range */
+#endif
+#ifdef EUNATCH
+        //case EUNATCH          49      /* Protocol driver not attached */
+#endif
+#ifdef ENOCSI
+        //case ENOCSI           50      /* No CSI structure available */
+#endif
+#ifdef EL2HLT
+        //case EL2HLT           51      /* Level 2 halted */
+#endif
+#ifdef EBADE
+        //case EBADE            52      /* Invalid exchange */
+#endif
+#ifdef EBADR
+        //case EBADR            53      /* Invalid request descriptor */
+#endif
+#ifdef EXFULL
+        //case EXFULL           54      /* Exchange full */
+#endif
+#ifdef ENOANO
+        //case ENOANO           55      /* No anode */
+#endif
+#ifdef EBADRQC
+        //case EBADRQC          56      /* Invalid request code */
+#endif
+#ifdef EBADSLT
+        //case EBADSLT          57      /* Invalid slot */
+#endif
+        //case 58:
+#ifdef EBFONT
+        //case EBFONT           59      /* Bad font file format */
+#endif
+#ifdef ENOSTR
+        //case ENOSTR           60      /* Device not a stream */
+#endif
+#ifdef ENODATA
+        case ENODATA:           return  VERR_NO_DATA;
+#endif
+#ifdef ETIME
+        //case ETIME            62      /* Timer expired */
+#endif
+#ifdef ENOSR
+        //case ENOSR            63      /* Out of streams resources */
+#endif
+#ifdef ENONET
+        case ENONET:            return VERR_NET_NO_NETWORK;
+#endif
+#ifdef ENOPKG
+        //case ENOPKG           65      /* Package not installed */
+#endif
+#ifdef EREMOTE
+        //case EREMOTE          66      /* Object is remote */
+#endif
+#ifdef ENOLINK
+        //case ENOLINK          67      /* Link has been severed */
+#endif
+#ifdef EADV
+        //case EADV             68      /* Advertise error */
+#endif
+#ifdef ESRMNT
+        //case ESRMNT           69      /* Srmount error */
+#endif
+#ifdef ECOMM
+        //case ECOMM            70      /* Communication error on send */
+#endif
+#ifdef EPROTO
+        case EPROTO:            return VERR_NET_PROTOCOL_ERROR;
+#endif
+#ifdef EMULTIHOP
+        //case EMULTIHOP        72      /* Multihop attempted */
+#endif
+#ifdef EDOTDOT
+        //case EDOTDOT          73      /* RFS specific error */
+#endif
+#ifdef EBADMSG
+        //case EBADMSG          74      /* Not a data message */
+#endif
+#ifdef EOVERFLOW
+        case EOVERFLOW:         return VERR_TOO_MUCH_DATA;   /** @todo fix duplicate error */
+#endif
+#ifdef ENOTUNIQ
+        case ENOTUNIQ:          return VERR_NET_NOT_UNIQUE_NAME;
+#endif
+#ifdef EBADFD
+        case EBADFD:            return VERR_INVALID_HANDLE; /** @todo fix duplicate error? */
+#endif
+#ifdef EREMCHG
+        //case EREMCHG          78      /* Remote address changed */
+#endif
+#ifdef ELIBACC
+        //case ELIBACC          79      /* Can not access a needed shared library */
+#endif
+#ifdef ELIBBAD
+        //case ELIBBAD          80      /* Accessing a corrupted shared library */
+#endif
+#ifdef ELIBSCN
+        //case ELIBSCN          81      /* .lib section in a.out corrupted */
+#endif
+#ifdef ELIBMAX
+        //case ELIBMAX          82      /* Attempting to link in too many shared libraries */
+#endif
+#ifdef ELIBEXEC
+        //case ELIBEXEC 83      /* Cannot exec a shared library directly */
+#endif
+#ifdef EILSEQ
+        case EILSEQ:            return VERR_NO_TRANSLATION;
+#endif
+#ifdef ERESTART
+        case ERESTART:          return VERR_INTERRUPTED;/** @todo fix duplicate error?*/
+#endif
+#ifdef ESTRPIPE
+        //case ESTRPIPE 86      /* Streams pipe error */
+#endif
+#ifdef EUSERS
+        //case EUSERS           87      /* Too many users */
+#endif
+#ifdef ENOTSOCK
+        case ENOTSOCK:          return VERR_NET_NOT_SOCKET;
+#endif
+#ifdef EDESTADDRREQ
+        case EDESTADDRREQ:      return VERR_NET_DEST_ADDRESS_REQUIRED;
+#endif
+#ifdef EMSGSIZE
+        case EMSGSIZE:          return VERR_NET_MSG_SIZE;
+#endif
+#ifdef EPROTOTYPE
+        case EPROTOTYPE:        return VERR_NET_PROTOCOL_TYPE;
+#endif
+#ifdef ENOPROTOOPT
+        case ENOPROTOOPT:       return VERR_NET_PROTOCOL_NOT_AVAILABLE;
+#endif
+#ifdef EPROTONOSUPPORT
+        case EPROTONOSUPPORT:   return VERR_NET_PROTOCOL_NOT_SUPPORTED;
+#endif
+#ifdef ESOCKTNOSUPPORT
+        case ESOCKTNOSUPPORT:   return VERR_NET_SOCKET_TYPE_NOT_SUPPORTED;
+#endif
+#ifdef EOPNOTSUPP /** @todo map this differently on solaris. */
+        case EOPNOTSUPP:        return VERR_NET_OPERATION_NOT_SUPPORTED;
+#endif
+#ifdef EPFNOSUPPORT
+        case EPFNOSUPPORT:      return VERR_NET_PROTOCOL_FAMILY_NOT_SUPPORTED;
+#endif
+#ifdef EAFNOSUPPORT
+        case EAFNOSUPPORT:      return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;
+#endif
+#ifdef EADDRINUSE
+        case EADDRINUSE:        return VERR_NET_ADDRESS_IN_USE;
+#endif
+#ifdef EADDRNOTAVAIL
+        case EADDRNOTAVAIL:     return VERR_NET_ADDRESS_NOT_AVAILABLE;
+#endif
+#ifdef ENETDOWN
+        case ENETDOWN:          return VERR_NET_DOWN;
+#endif
+#ifdef ENETUNREACH
+        case ENETUNREACH:       return VERR_NET_UNREACHABLE;
+#endif
+#ifdef ENETRESET
+        case ENETRESET:         return VERR_NET_CONNECTION_RESET;
+#endif
+#ifdef ECONNABORTED
+        case ECONNABORTED:      return VERR_NET_CONNECTION_ABORTED;
+#endif
+#ifdef ECONNRESET
+        case ECONNRESET:        return VERR_NET_CONNECTION_RESET_BY_PEER;
+#endif
+#ifdef ENOBUFS
+        case ENOBUFS:           return VERR_NET_NO_BUFFER_SPACE;
+#endif
+#ifdef EISCONN
+        case EISCONN:           return VERR_NET_ALREADY_CONNECTED;
+#endif
+#ifdef ENOTCONN
+        case ENOTCONN:          return VERR_NET_NOT_CONNECTED;
+#endif
+#ifdef ESHUTDOWN
+        case ESHUTDOWN:         return VERR_NET_SHUTDOWN;
+#endif
+#ifdef ETOOMANYREFS
+        case ETOOMANYREFS:      return VERR_NET_TOO_MANY_REFERENCES;
+#endif
+#ifdef ETIMEDOUT
+        case ETIMEDOUT:         return VERR_TIMEOUT;
+#endif
+#ifdef ECONNREFUSED
+        case ECONNREFUSED:      return VERR_NET_CONNECTION_REFUSED;
+#endif
+#ifdef EHOSTDOWN
+        case EHOSTDOWN:         return VERR_NET_HOST_DOWN;
+#endif
+#ifdef EHOSTUNREACH
+        case EHOSTUNREACH:      return VERR_NET_HOST_UNREACHABLE;
+#endif
+#ifdef EALREADY
+        case EALREADY:          return VERR_NET_ALREADY_IN_PROGRESS;
+#endif
+#ifdef EINPROGRESS
+        case EINPROGRESS:       return VERR_NET_IN_PROGRESS;
+#endif
+#ifdef ESTALE
+        //case ESTALE           116     /* Stale NFS file handle */
+#endif
+#ifdef EUCLEAN
+        //case EUCLEAN          117     /* Structure needs cleaning */
+#endif
+#ifdef ENOTNAM
+        //case ENOTNAM          118     /* Not a XENIX named type file */
+#endif
+#ifdef ENAVAIL
+        //case ENAVAIL          119     /* No XENIX semaphores available */
+#endif
+#ifdef EISNAM
+        //case EISNAM           120     /* Is a named type file */
+#endif
+#ifdef EREMOTEIO
+        //case EREMOTEIO        121     /* Remote I/O error */
+#endif
+#ifdef EDQUOT
+        case EDQUOT:            return VERR_DISK_FULL; /** @todo fix duplicate error */
+#endif
+#ifdef ENOMEDIUM
+        case ENOMEDIUM:         return VERR_MEDIA_NOT_PRESENT;
+#endif
+#ifdef EMEDIUMTYPE
+        case EMEDIUMTYPE:       return VERR_MEDIA_NOT_RECOGNIZED;
+#endif
+#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
+        case EWOULDBLOCK:       return VERR_TRY_AGAIN;
+#endif
+
+        /* Non-linux */
+
+#ifdef EPROCLIM
+        case EPROCLIM:          return VERR_MAX_PROCS_REACHED;
+#endif
+#ifdef EDOOFUS
+# if EDOOFUS != EINVAL
+        case EDOOFUS:           return VERR_INTERNAL_ERROR;
+# endif
+#endif
+#ifdef ENOTSUP
+# ifndef EOPNOTSUPP
+        case ENOTSUP:           return VERR_NOT_SUPPORTED;
+# else
+#  if ENOTSUP != EOPNOTSUPP
+        case ENOTSUP:           return VERR_NOT_SUPPORTED;
+#  endif
+# endif
+#endif
+        default:
+            AssertMsgFailed(("Unhandled error code %d\n", uNativeCode));
+            return VERR_UNRESOLVED_ERROR;
+    }
+}
+RT_EXPORT_SYMBOL(RTErrConvertFromErrno);
+
diff --git a/ubuntu/vbox/vboxguest/common/err/RTErrConvertToErrno.c b/ubuntu/vbox/vboxguest/common/err/RTErrConvertToErrno.c
new file mode 100644 (file)
index 0000000..ba93173
--- /dev/null
@@ -0,0 +1,451 @@
+/* $Id: RTErrConvertToErrno.cpp $ */
+/** @file
+ * IPRT - Convert iprt status codes to errno.
+ */
+
+/*
+ * Copyright (C) 2007-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/err.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/errno.h>
+
+
+RTDECL(int) RTErrConvertToErrno(int iErr)
+{
+    /* very fast check for no error. */
+    if (RT_SUCCESS(iErr))
+        return 0;
+
+    /*
+     * Process error codes.
+     *
+     * (Use a switch and not a table since the numbers vary among compilers
+     * and OSes. So we let the compiler switch optimizer handle speed issues.)
+     *
+     * This switch is arranged like the Linux i386 errno.h! It also mirrors the
+     * conversions performed by RTErrConvertFromErrno with a few extra case since
+     * there are far more IPRT status codes than Unix ones.
+     */
+    switch (iErr)
+    {
+#ifdef EPERM
+        case VERR_ACCESS_DENIED:                    return EPERM;
+#endif
+#ifdef ENOENT
+        case VERR_FILE_NOT_FOUND:                   return ENOENT;
+#endif
+#ifdef ESRCH
+        case VERR_PROCESS_NOT_FOUND:                return ESRCH;
+#endif
+#ifdef EINTR
+        case VERR_INTERRUPTED:                      return EINTR;
+#endif
+#ifdef EIO
+        case VERR_DEV_IO_ERROR:                     return EIO;
+#endif
+#ifdef ENXIO
+        //case VERR_DEV_IO_ERROR:                     return ENXIO;
+#endif
+#ifdef E2BIG
+        case VERR_TOO_MUCH_DATA:                    return E2BIG;
+#endif
+#ifdef ENOEXEC
+        case VERR_BAD_EXE_FORMAT:                   return ENOEXEC;
+#endif
+#ifdef EBADF
+        case VERR_INVALID_HANDLE:                   return EBADF;
+#endif
+#ifdef ECHILD
+        //case VERR_PROCESS_NOT_FOUND:                return ECHILD;
+#endif
+#ifdef EAGAIN
+        case VERR_TRY_AGAIN:                        return EAGAIN;
+#endif
+#ifdef ENOMEM
+        case VERR_NO_MEMORY:                        return ENOMEM;
+#endif
+#ifdef EACCES
+        //case VERR_ACCESS_DENIED:                    return EACCES;
+#endif
+#ifdef EFAULT
+        case VERR_INVALID_POINTER:                  return EFAULT;
+#endif
+#ifdef ENOTBLK
+        //case ENOTBLK:           return VERR_;
+#endif
+#ifdef EBUSY
+        case VERR_RESOURCE_BUSY:                    return EBUSY;
+#endif
+#ifdef EEXIST
+        case VERR_ALREADY_EXISTS:                   return EEXIST;
+#endif
+#ifdef EXDEV
+        case VERR_NOT_SAME_DEVICE:                  return EXDEV;
+#endif
+#ifdef ENODEV
+        //case VERR_NOT_SUPPORTED:                    return ENODEV;
+#endif
+#ifdef ENOTDIR
+        case VERR_NOT_A_DIRECTORY:
+        case VERR_PATH_NOT_FOUND:                   return ENOTDIR;
+#endif
+#ifdef EISDIR
+        case VERR_IS_A_DIRECTORY:                   return EISDIR;
+#endif
+#ifdef EINVAL
+        case VERR_INVALID_PARAMETER:                return EINVAL;
+#endif
+#ifdef ENFILE
+        case VERR_TOO_MANY_OPEN_FILES:              return ENFILE;
+#endif
+#ifdef EMFILE
+        //case VERR_TOO_MANY_OPEN_FILES:              return EMFILE;
+#endif
+#ifdef ENOTTY
+        case VERR_INVALID_FUNCTION:                 return ENOTTY;
+#endif
+#ifdef ETXTBSY
+        case VERR_SHARING_VIOLATION:                return ETXTBSY;
+#endif
+#ifdef EFBIG
+        case VERR_FILE_TOO_BIG:                     return EFBIG;
+#endif
+#ifdef ENOSPC
+        case VERR_DISK_FULL:                        return ENOSPC;
+#endif
+#ifdef ESPIPE
+        case VERR_SEEK_ON_DEVICE:                   return ESPIPE;
+#endif
+#ifdef EROFS
+        case VERR_WRITE_PROTECT:                    return EROFS;
+#endif
+#ifdef EMLINK
+        //case EMLINK:
+#endif
+#ifdef EPIPE
+        case VERR_BROKEN_PIPE:                      return EPIPE;
+#endif
+#ifdef EDOM
+        //case VERR_INVALID_PARAMETER:    return EDOM;
+#endif
+#ifdef ERANGE
+        //case VERR_INVALID_PARAMETER:    return ERANGE;
+#endif
+#ifdef EDEADLK
+        case VERR_DEADLOCK:                         return EDEADLK;
+#endif
+#ifdef ENAMETOOLONG
+        case VERR_FILENAME_TOO_LONG:                return ENAMETOOLONG;
+#endif
+#ifdef ENOLCK
+        case VERR_FILE_LOCK_FAILED:                 return ENOLCK;
+#endif
+#ifdef ENOSYS
+        case VERR_NOT_IMPLEMENTED:
+        case VERR_NOT_SUPPORTED:                    return ENOSYS;
+#endif
+#ifdef ENOTEMPTY
+        case VERR_DIR_NOT_EMPTY:                    return ENOTEMPTY;
+#endif
+#ifdef ELOOP
+        case VERR_TOO_MANY_SYMLINKS:                return ELOOP;
+#endif
+        //41??
+#ifdef ENOMSG
+        //case ENOMSG           42      /* No message of desired type */
+#endif
+#ifdef EIDRM
+        //case EIDRM            43      /* Identifier removed */
+#endif
+#ifdef ECHRNG
+        //case ECHRNG           44      /* Channel number out of range */
+#endif
+#ifdef EL2NSYNC
+        //case EL2NSYNC 45      /* Level 2 not synchronized */
+#endif
+#ifdef EL3HLT
+        //case EL3HLT           46      /* Level 3 halted */
+#endif
+#ifdef EL3RST
+        //case EL3RST           47      /* Level 3 reset */
+#endif
+#ifdef ELNRNG
+        //case ELNRNG           48      /* Link number out of range */
+#endif
+#ifdef EUNATCH
+        //case EUNATCH          49      /* Protocol driver not attached */
+#endif
+#ifdef ENOCSI
+        //case ENOCSI           50      /* No CSI structure available */
+#endif
+#ifdef EL2HLT
+        //case EL2HLT           51      /* Level 2 halted */
+#endif
+#ifdef EBADE
+        //case EBADE            52      /* Invalid exchange */
+#endif
+#ifdef EBADR
+        //case EBADR            53      /* Invalid request descriptor */
+#endif
+#ifdef EXFULL
+        //case EXFULL           54      /* Exchange full */
+#endif
+#ifdef ENOANO
+        //case ENOANO           55      /* No anode */
+#endif
+#ifdef EBADRQC
+        //case EBADRQC          56      /* Invalid request code */
+#endif
+#ifdef EBADSLT
+        //case EBADSLT          57      /* Invalid slot */
+#endif
+        //case 58:
+#ifdef EBFONT
+        //case EBFONT           59      /* Bad font file format */
+#endif
+#ifdef ENOSTR
+        //case ENOSTR           60      /* Device not a stream */
+#endif
+#ifdef ENODATA
+        case VERR_NO_DATA:                          return ENODATA;
+#endif
+#ifdef ETIME
+        //case ETIME            62      /* Timer expired */
+#endif
+#ifdef ENOSR
+        //case ENOSR            63      /* Out of streams resources */
+#endif
+#ifdef ENONET
+        case VERR_NET_NO_NETWORK:                   return ENONET;
+#endif
+#ifdef ENOPKG
+        //case ENOPKG           65      /* Package not installed */
+#endif
+#ifdef EREMOTE
+        //case EREMOTE          66      /* Object is remote */
+#endif
+#ifdef ENOLINK
+        //case ENOLINK          67      /* Link has been severed */
+#endif
+#ifdef EADV
+        //case EADV             68      /* Advertise error */
+#endif
+#ifdef ESRMNT
+        //case ESRMNT           69      /* Srmount error */
+#endif
+#ifdef ECOMM
+        //case ECOMM            70      /* Communication error on send */
+#endif
+#ifdef EPROTO
+        //case EPROTO           71      /* Protocol error */
+#endif
+#ifdef EMULTIHOP
+        //case EMULTIHOP        72      /* Multihop attempted */
+#endif
+#ifdef EDOTDOT
+        //case EDOTDOT          73      /* RFS specific error */
+#endif
+#ifdef EBADMSG
+        //case EBADMSG          74      /* Not a data message */
+#endif
+#ifdef EOVERFLOW
+        //case VERR_TOO_MUCH_DATA:                    return EOVERFLOW;
+#endif
+#ifdef ENOTUNIQ
+        case VERR_NET_NOT_UNIQUE_NAME:              return ENOTUNIQ;
+#endif
+#ifdef EBADFD
+        //case VERR_INVALID_HANDLE:                   return EBADFD;
+#endif
+#ifdef EREMCHG
+        //case EREMCHG          78      /* Remote address changed */
+#endif
+#ifdef ELIBACC
+        //case ELIBACC          79      /* Can not access a needed shared library */
+#endif
+#ifdef ELIBBAD
+        //case ELIBBAD          80      /* Accessing a corrupted shared library */
+#endif
+#ifdef ELIBSCN
+        //case ELIBSCN          81      /* .lib section in a.out corrupted */
+#endif
+#ifdef ELIBMAX
+        //case ELIBMAX          82      /* Attempting to link in too many shared libraries */
+#endif
+#ifdef ELIBEXEC
+        //case ELIBEXEC 83      /* Cannot exec a shared library directly */
+#endif
+#ifdef EILSEQ
+        case VERR_NO_TRANSLATION:                   return EILSEQ;
+#endif
+#ifdef ERESTART
+        //case VERR_INTERRUPTED:                      return ERESTART;
+#endif
+#ifdef ESTRPIPE
+        //case ESTRPIPE 86      /* Streams pipe error */
+#endif
+#ifdef EUSERS
+        //case EUSERS           87      /* Too many users */
+#endif
+#ifdef ENOTSOCK
+        case VERR_NET_NOT_SOCKET:                   return ENOTSOCK;
+#endif
+#ifdef EDESTADDRREQ
+        case VERR_NET_DEST_ADDRESS_REQUIRED:        return EDESTADDRREQ;
+#endif
+#ifdef EMSGSIZE
+        case VERR_NET_MSG_SIZE:                     return EMSGSIZE;
+#endif
+#ifdef EPROTOTYPE
+        case VERR_NET_PROTOCOL_TYPE:                return EPROTOTYPE;
+#endif
+#ifdef ENOPROTOOPT
+        case VERR_NET_PROTOCOL_NOT_AVAILABLE:       return ENOPROTOOPT;
+#endif
+#ifdef EPROTONOSUPPORT
+        case VERR_NET_PROTOCOL_NOT_SUPPORTED:       return EPROTONOSUPPORT;
+#endif
+#ifdef ESOCKTNOSUPPORT
+        case VERR_NET_SOCKET_TYPE_NOT_SUPPORTED:    return ESOCKTNOSUPPORT;
+#endif
+#ifdef EOPNOTSUPP
+        case VERR_NET_OPERATION_NOT_SUPPORTED:      return EOPNOTSUPP;
+#endif
+#ifdef EPFNOSUPPORT
+        case VERR_NET_PROTOCOL_FAMILY_NOT_SUPPORTED: return EPFNOSUPPORT;
+#endif
+#ifdef EAFNOSUPPORT
+        case VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED: return EAFNOSUPPORT;
+#endif
+#ifdef EADDRINUSE
+        case VERR_NET_ADDRESS_IN_USE:               return EADDRINUSE;
+#endif
+#ifdef EADDRNOTAVAIL
+        case VERR_NET_ADDRESS_NOT_AVAILABLE:        return EADDRNOTAVAIL;
+#endif
+#ifdef ENETDOWN
+        case VERR_NET_DOWN:                         return ENETDOWN;
+#endif
+#ifdef ENETUNREACH
+        case VERR_NET_UNREACHABLE:                  return ENETUNREACH;
+#endif
+#ifdef ENETRESET
+        case VERR_NET_CONNECTION_RESET:             return ENETRESET;
+#endif
+#ifdef ECONNABORTED
+        case VERR_NET_CONNECTION_ABORTED:           return ECONNABORTED;
+#endif
+#ifdef ECONNRESET
+        case VERR_NET_CONNECTION_RESET_BY_PEER:     return ECONNRESET;
+#endif
+#ifdef ENOBUFS
+        case VERR_NET_NO_BUFFER_SPACE:              return ENOBUFS;
+#endif
+#ifdef EISCONN
+        case VERR_NET_ALREADY_CONNECTED:            return EISCONN;
+#endif
+#ifdef ENOTCONN
+        case VERR_NET_NOT_CONNECTED:                return ENOTCONN;
+#endif
+#ifdef ESHUTDOWN
+        case VERR_NET_SHUTDOWN:                     return ESHUTDOWN;
+#endif
+#ifdef ETOOMANYREFS
+        case VERR_NET_TOO_MANY_REFERENCES:          return ETOOMANYREFS;
+#endif
+#ifdef ETIMEDOUT
+        case VERR_TIMEOUT:                          return ETIMEDOUT;
+#endif
+#ifdef ECONNREFUSED
+        case VERR_NET_CONNECTION_REFUSED:           return ECONNREFUSED;
+#endif
+#ifdef EHOSTDOWN
+        case VERR_NET_HOST_DOWN:                    return EHOSTDOWN;
+#endif
+#ifdef EHOSTUNREACH
+        case VERR_NET_HOST_UNREACHABLE:             return EHOSTUNREACH;
+#endif
+#ifdef EALREADY
+        case VERR_NET_ALREADY_IN_PROGRESS:          return EALREADY;
+#endif
+#ifdef EINPROGRESS
+        case VERR_NET_IN_PROGRESS:                  return EINPROGRESS;
+#endif
+#ifdef ESTALE
+        //case ESTALE           116     /* Stale NFS file handle */
+#endif
+#ifdef EUCLEAN
+        //case EUCLEAN          117     /* Structure needs cleaning */
+#endif
+#ifdef ENOTNAM
+        //case ENOTNAM          118     /* Not a XENIX named type file */
+#endif
+#ifdef ENAVAIL
+        //case ENAVAIL          119     /* No XENIX semaphores available */
+#endif
+#ifdef EISNAM
+        //case EISNAM           120     /* Is a named type file */
+#endif
+#ifdef EREMOTEIO
+        //case EREMOTEIO        121     /* Remote I/O error */
+#endif
+#ifdef EDQUOT
+        //case VERR_DISK_FULL:                        return EDQUOT;
+#endif
+#ifdef ENOMEDIUM
+        case VERR_MEDIA_NOT_PRESENT:                return ENOMEDIUM;
+#endif
+#ifdef EMEDIUMTYPE
+        case VERR_MEDIA_NOT_RECOGNIZED:             return EMEDIUMTYPE;
+#endif
+
+        /* Non-linux */
+
+#ifdef EPROCLIM
+        case VERR_MAX_PROCS_REACHED:                return EPROCLIM;
+#endif
+#ifdef EDOOFUS
+        case VERR_INTERNAL_ERROR:
+        case VERR_INTERNAL_ERROR_2:
+        case VERR_INTERNAL_ERROR_3:                 return EDOOFUS;
+#endif
+
+        default:
+            /* The idea here is that if you hit this, you will have to
+               translate the status code yourself. */
+            AssertMsgFailed(("Unhandled error code %Rrc\n", iErr));
+#ifdef EPROTO
+            return EPROTO;
+#else
+            return EINVAL;
+#endif
+    }
+}
+RT_EXPORT_SYMBOL(RTErrConvertToErrno);
+
diff --git a/ubuntu/vbox/vboxguest/common/log/log.c b/ubuntu/vbox/vboxguest/common/log/log.c
new file mode 100644 (file)
index 0000000..7d134b2
--- /dev/null
@@ -0,0 +1,3968 @@
+/* $Id: log.cpp $ */
+/** @file
+ * Runtime VBox - Logger.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/log.h>
+#include "internal/iprt.h"
+
+#ifndef IN_RC
+# include <iprt/alloc.h>
+# include <iprt/process.h>
+# include <iprt/semaphore.h>
+# include <iprt/thread.h>
+# include <iprt/mp.h>
+#endif
+#ifdef IN_RING3
+# include <iprt/env.h>
+# include <iprt/file.h>
+# include <iprt/lockvalidator.h>
+# include <iprt/path.h>
+#endif
+#include <iprt/time.h>
+#include <iprt/asm.h>
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# include <iprt/asm-amd64-x86.h>
+#endif
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/param.h>
+
+#include <iprt/stdarg.h>
+#include <iprt/string.h>
+#include <iprt/ctype.h>
+#ifdef IN_RING3
+# include <iprt/alloca.h>
+# include <stdio.h>
+#endif
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+/** @def RTLOG_RINGBUF_DEFAULT_SIZE
+ * The default ring buffer size. */
+/** @def RTLOG_RINGBUF_MAX_SIZE
+ * The max ring buffer size. */
+/** @def RTLOG_RINGBUF_MIN_SIZE
+ * The min ring buffer size. */
+#ifdef IN_RING0
+# define RTLOG_RINGBUF_DEFAULT_SIZE     _64K
+# define RTLOG_RINGBUF_MAX_SIZE         _4M
+# define RTLOG_RINGBUF_MIN_SIZE         _1K
+#elif defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+# define RTLOG_RINGBUF_DEFAULT_SIZE     _512K
+# define RTLOG_RINGBUF_MAX_SIZE         _1G
+# define RTLOG_RINGBUF_MIN_SIZE         _4K
+#endif
+/** The start of ring buffer eye catcher (16 bytes). */
+#define RTLOG_RINGBUF_EYE_CATCHER           "START RING BUF\0"
+AssertCompile(sizeof(RTLOG_RINGBUF_EYE_CATCHER) == 16);
+/** The end of ring buffer eye catcher (16 bytes).  This also ensures that the ring buffer
+ * forms are properly terminated C string (leading zero chars).  */
+#define RTLOG_RINGBUF_EYE_CATCHER_END    "\0\0\0END RING BUF"
+AssertCompile(sizeof(RTLOG_RINGBUF_EYE_CATCHER_END) == 16);
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * Arguments passed to the output function.
+ */
+typedef struct RTLOGOUTPUTPREFIXEDARGS
+{
+    /** The logger instance. */
+    PRTLOGGER               pLogger;
+    /** The flags. (used for prefixing.) */
+    unsigned                fFlags;
+    /** The group. (used for prefixing.) */
+    unsigned                iGroup;
+} RTLOGOUTPUTPREFIXEDARGS, *PRTLOGOUTPUTPREFIXEDARGS;
+
+#ifndef IN_RC
+
+/**
+ * Internal logger data.
+ *
+ * @remarks Don't make casual changes to this structure.
+ */
+typedef struct RTLOGGERINTERNAL
+{
+    /** The structure revision (RTLOGGERINTERNAL_REV). */
+    uint32_t                uRevision;
+    /** The size of the internal logger structure. */
+    uint32_t                cbSelf;
+
+    /** Spinning mutex semaphore.  Can be NIL. */
+    RTSEMSPINMUTEX          hSpinMtx;
+    /** Pointer to the flush function. */
+    PFNRTLOGFLUSH           pfnFlush;
+
+    /** Custom prefix callback. */
+    PFNRTLOGPREFIX          pfnPrefix;
+    /** Prefix callback argument. */
+    void                   *pvPrefixUserArg;
+    /** This is set if a prefix is pending. */
+    bool                    fPendingPrefix;
+    /** Alignment padding. */
+    bool                    afPadding1[2];
+    /** Set if fully created.  Used to avoid confusing in a few functions used to
+     * parse logger settings from environment variables. */
+    bool                    fCreated;
+
+    /** The max number of groups that there is room for in afGroups and papszGroups.
+     * Used by RTLogCopyGroupAndFlags(). */
+    uint32_t                cMaxGroups;
+    /** Pointer to the group name array.
+     * (The data is readonly and provided by the user.) */
+    const char * const     *papszGroups;
+
+    /** The number of log entries per group.  NULL if
+     * RTLOGFLAGS_RESTRICT_GROUPS is not specified. */
+    uint32_t               *pacEntriesPerGroup;
+    /** The max number of entries per group. */
+    uint32_t                cMaxEntriesPerGroup;
+
+    /** @name Ring buffer logging
+     * The ring buffer records the last cbRingBuf - 1 of log output.  The
+     * other configured log destinations are not touched until someone calls
+     * RTLogFlush(), when the ring buffer content is written to them all.
+     *
+     * The aim here is a fast logging destination, that avoids wasting storage
+     * space saving disk space when dealing with huge log volumes where the
+     * interesting bits usually are found near the end of the log.  This is
+     * typically the case for scenarios that crashes or hits assertions.
+     *
+     * RTLogFlush() is called implicitly when hitting an assertion.  While on a
+     * crash the most debuggers are able to make calls these days, it's usually
+     * possible to view the ring buffer memory.
+     *
+     * @{ */
+    /** Ring buffer size (including both eye catchers). */
+    uint32_t                cbRingBuf;
+    /** Number of bytes passing thru the ring buffer since last RTLogFlush call.
+     * (This is used to avoid writing out the same bytes twice.) */
+    uint64_t volatile       cbRingBufUnflushed;
+    /** Ring buffer pointer (points at RTLOG_RINGBUF_EYE_CATCHER). */
+    char                   *pszRingBuf;
+    /** Current ring buffer position (where to write the next char). */
+    char * volatile         pchRingBufCur;
+    /** @} */
+
+# ifdef IN_RING3 /* Note! Must be at the end! */
+    /** @name File logging bits for the logger.
+     * @{ */
+    /** Pointer to the function called when starting logging, and when
+     * ending or starting a new log file as part of history rotation.
+     * This can be NULL. */
+    PFNRTLOGPHASE           pfnPhase;
+
+    /** Handle to log file (if open). */
+    RTFILE                  hFile;
+    /** Log file history settings: maximum amount of data to put in a file. */
+    uint64_t                cbHistoryFileMax;
+    /** Log file history settings: current amount of data in a file. */
+    uint64_t                cbHistoryFileWritten;
+    /** Log file history settings: maximum time to use a file (in seconds). */
+    uint32_t                cSecsHistoryTimeSlot;
+    /** Log file history settings: in what time slot was the file created. */
+    uint32_t                uHistoryTimeSlotStart;
+    /** Log file history settings: number of older files to keep.
+     * 0 means no history. */
+    uint32_t                cHistory;
+    /** Pointer to filename. */
+    char                    szFilename[RTPATH_MAX];
+    /** @} */
+# endif /* IN_RING3 */
+} RTLOGGERINTERNAL;
+
+/** The revision of the internal logger structure. */
+# define RTLOGGERINTERNAL_REV    UINT32_C(10)
+
+# ifdef IN_RING3
+/** The size of the RTLOGGERINTERNAL structure in ring-0.  */
+#  define RTLOGGERINTERNAL_R0_SIZE       RT_OFFSETOF(RTLOGGERINTERNAL, pfnPhase)
+AssertCompileMemberAlignment(RTLOGGERINTERNAL, hFile, sizeof(void *));
+AssertCompileMemberAlignment(RTLOGGERINTERNAL, cbHistoryFileMax, sizeof(uint64_t));
+# endif
+AssertCompileMemberAlignment(RTLOGGERINTERNAL, cbRingBufUnflushed, sizeof(uint64_t));
+
+#endif /* !IN_RC */
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+#ifndef IN_RC
+static unsigned rtlogGroupFlags(const char *psz);
+#endif
+#ifdef IN_RING0
+static void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, PRTLOGGERINTERNAL pInt,
+                                    const char *pszFormat, va_list va);
+#endif
+#ifdef IN_RING3
+static int rtlogFileOpen(PRTLOGGER pLogger, char *pszErrorMsg, size_t cchErrorMsg);
+static void rtlogRotate(PRTLOGGER pLogger, uint32_t uTimeSlot, bool fFirst);
+#endif
+#ifndef IN_RC
+static void rtLogRingBufFlush(PRTLOGGER pLogger);
+#endif
+static void rtlogFlush(PRTLOGGER pLogger);
+static DECLCALLBACK(size_t) rtLogOutput(void *pv, const char *pachChars, size_t cbChars);
+static DECLCALLBACK(size_t) rtLogOutputPrefixed(void *pv, const char *pachChars, size_t cbChars);
+static void rtlogLoggerExVLocked(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, va_list args);
+#ifndef IN_RC
+static void rtlogLoggerExFLocked(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, ...);
+#endif
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+#ifdef IN_RC
+/** Default logger instance. Make it weak because our RC module loader does not
+ *  necessarily resolve this symbol and the compiler _must_ check if this is
+ *  the case or not. That doesn't work for Darwin (``incompatible feature used:
+ *  .weak_reference (must specify "-dynamic" to be used'') */
+# ifdef RT_OS_DARWIN
+extern "C" DECLIMPORT(RTLOGGERRC) g_Logger;
+# else
+extern "C" DECLWEAK(DECLIMPORT(RTLOGGERRC)) g_Logger;
+# endif
+#else /* !IN_RC */
+/** Default logger instance. */
+static PRTLOGGER                    g_pLogger;
+#endif /* !IN_RC */
+#ifdef IN_RING3
+/** The RTThreadGetWriteLockCount() change caused by the logger mutex semaphore. */
+static uint32_t volatile            g_cLoggerLockCount;
+#endif
+
+#ifdef IN_RING0
+/** Number of per-thread loggers. */
+static int32_t volatile             g_cPerThreadLoggers;
+/** Per-thread loggers.
+ * This is just a quick TLS hack suitable for debug logging only.
+ * If we run out of entries, just unload and reload the driver. */
+static struct RTLOGGERPERTHREAD
+{
+    /** The thread. */
+    RTNATIVETHREAD volatile NativeThread;
+    /** The (process / session) key. */
+    uintptr_t volatile      uKey;
+    /** The logger instance.*/
+    PRTLOGGER volatile      pLogger;
+} g_aPerThreadLoggers[8] =
+{
+    { NIL_RTNATIVETHREAD, 0, 0},
+    { NIL_RTNATIVETHREAD, 0, 0},
+    { NIL_RTNATIVETHREAD, 0, 0},
+    { NIL_RTNATIVETHREAD, 0, 0},
+    { NIL_RTNATIVETHREAD, 0, 0},
+    { NIL_RTNATIVETHREAD, 0, 0},
+    { NIL_RTNATIVETHREAD, 0, 0},
+    { NIL_RTNATIVETHREAD, 0, 0}
+};
+#endif /* IN_RING0 */
+
+/**
+ * Logger flags instructions.
+ */
+static struct
+{
+    const char *pszInstr;               /**< The name  */
+    size_t      cchInstr;               /**< The size of the name. */
+    uint32_t    fFlag;                  /**< The flag value. */
+    bool        fInverted;              /**< Inverse meaning? */
+} const g_aLogFlags[] =
+{
+    { "disabled",     sizeof("disabled"    ) - 1,   RTLOGFLAGS_DISABLED,            false },
+    { "enabled",      sizeof("enabled"     ) - 1,   RTLOGFLAGS_DISABLED,            true  },
+    { "buffered",     sizeof("buffered"    ) - 1,   RTLOGFLAGS_BUFFERED,            false },
+    { "unbuffered",   sizeof("unbuffered"  ) - 1,   RTLOGFLAGS_BUFFERED,            true  },
+    { "usecrlf",      sizeof("usecrlf"     ) - 1,   RTLOGFLAGS_USECRLF,             false },
+    { "uself",        sizeof("uself"       ) - 1,   RTLOGFLAGS_USECRLF,             true  },
+    { "append",       sizeof("append"      ) - 1,   RTLOGFLAGS_APPEND,              false },
+    { "overwrite",    sizeof("overwrite"   ) - 1,   RTLOGFLAGS_APPEND,              true  },
+    { "rel",          sizeof("rel"         ) - 1,   RTLOGFLAGS_REL_TS,              false },
+    { "abs",          sizeof("abs"         ) - 1,   RTLOGFLAGS_REL_TS,              true  },
+    { "dec",          sizeof("dec"         ) - 1,   RTLOGFLAGS_DECIMAL_TS,          false },
+    { "hex",          sizeof("hex"         ) - 1,   RTLOGFLAGS_DECIMAL_TS,          true  },
+    { "writethru",    sizeof("writethru"   ) - 1,   RTLOGFLAGS_WRITE_THROUGH,       false },
+    { "writethrough", sizeof("writethrough") - 1,   RTLOGFLAGS_WRITE_THROUGH,       false },
+    { "flush",        sizeof("flush"       ) - 1,   RTLOGFLAGS_FLUSH,               false },
+    { "lockcnts",     sizeof("lockcnts"    ) - 1,   RTLOGFLAGS_PREFIX_LOCK_COUNTS,  false },
+    { "cpuid",        sizeof("cpuid"       ) - 1,   RTLOGFLAGS_PREFIX_CPUID,        false },
+    { "pid",          sizeof("pid"         ) - 1,   RTLOGFLAGS_PREFIX_PID,          false },
+    { "flagno",       sizeof("flagno"      ) - 1,   RTLOGFLAGS_PREFIX_FLAG_NO,      false },
+    { "flag",         sizeof("flag"        ) - 1,   RTLOGFLAGS_PREFIX_FLAG,         false },
+    { "groupno",      sizeof("groupno"     ) - 1,   RTLOGFLAGS_PREFIX_GROUP_NO,     false },
+    { "group",        sizeof("group"       ) - 1,   RTLOGFLAGS_PREFIX_GROUP,        false },
+    { "tid",          sizeof("tid"         ) - 1,   RTLOGFLAGS_PREFIX_TID,          false },
+    { "thread",       sizeof("thread"      ) - 1,   RTLOGFLAGS_PREFIX_THREAD,       false },
+    { "custom",       sizeof("custom"      ) - 1,   RTLOGFLAGS_PREFIX_CUSTOM,       false },
+    { "timeprog",     sizeof("timeprog"    ) - 1,   RTLOGFLAGS_PREFIX_TIME_PROG,    false },
+    { "time",         sizeof("time"        ) - 1,   RTLOGFLAGS_PREFIX_TIME,         false },
+    { "msprog",       sizeof("msprog"      ) - 1,   RTLOGFLAGS_PREFIX_MS_PROG,      false },
+    { "tsc",          sizeof("tsc"         ) - 1,   RTLOGFLAGS_PREFIX_TSC,          false }, /* before ts! */
+    { "ts",           sizeof("ts"          ) - 1,   RTLOGFLAGS_PREFIX_TS,           false },
+    /* We intentionally omit RTLOGFLAGS_RESTRICT_GROUPS. */
+};
+
+/**
+ * Logger destination instructions.
+ */
+static struct
+{
+    const char *pszInstr;               /**< The name. */
+    size_t      cchInstr;               /**< The size of the name. */
+    uint32_t    fFlag;                  /**< The corresponding destination flag. */
+} const g_aLogDst[] =
+{
+    { RT_STR_TUPLE("file"),         RTLOGDEST_FILE },       /* Must be 1st! */
+    { RT_STR_TUPLE("dir"),          RTLOGDEST_FILE },       /* Must be 2nd! */
+    { RT_STR_TUPLE("history"),      0 },                    /* Must be 3rd! */
+    { RT_STR_TUPLE("histsize"),     0 },                    /* Must be 4th! */
+    { RT_STR_TUPLE("histtime"),     0 },                    /* Must be 5th! */
+    { RT_STR_TUPLE("ringbuf"),      RTLOGDEST_RINGBUF },    /* Must be 6th! */
+    { RT_STR_TUPLE("stdout"),       RTLOGDEST_STDOUT },
+    { RT_STR_TUPLE("stderr"),       RTLOGDEST_STDERR },
+    { RT_STR_TUPLE("debugger"),     RTLOGDEST_DEBUGGER },
+    { RT_STR_TUPLE("com"),          RTLOGDEST_COM },
+    { RT_STR_TUPLE("user"),         RTLOGDEST_USER },
+};
+
+#ifdef IN_RING3
+/** Log rotation backoff table - millisecond sleep intervals.
+ * Important on Windows host, especially for VBoxSVC release logging.  Only a
+ * medium term solution, until a proper fix for log file handling is available.
+ * 10 seconds total.
+ */
+static const uint32_t g_acMsLogBackoff[] =
+{ 10, 10, 10, 20, 50, 100, 200, 200, 200, 200, 500, 500, 500, 500, 1000, 1000, 1000, 1000, 1000, 1000, 1000 };
+#endif
+
+
+/**
+ * Locks the logger instance.
+ *
+ * @returns See RTSemSpinMutexRequest().
+ * @param   pLogger     The logger instance.
+ */
+DECLINLINE(int) rtlogLock(PRTLOGGER pLogger)
+{
+#ifndef IN_RC
+    PRTLOGGERINTERNAL pInt = pLogger->pInt;
+    AssertMsgReturn(pInt->uRevision == RTLOGGERINTERNAL_REV, ("%#x != %#x\n", pInt->uRevision, RTLOGGERINTERNAL_REV),
+                    VERR_LOG_REVISION_MISMATCH);
+    AssertMsgReturn(pInt->cbSelf == sizeof(*pInt), ("%#x != %#x\n", pInt->cbSelf, sizeof(*pInt)),
+                    VERR_LOG_REVISION_MISMATCH);
+    if (pInt->hSpinMtx != NIL_RTSEMSPINMUTEX)
+    {
+        int rc = RTSemSpinMutexRequest(pInt->hSpinMtx);
+        if (RT_FAILURE(rc))
+            return rc;
+    }
+#else
+    NOREF(pLogger);
+#endif
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Unlocks the logger instance.
+ * @param   pLogger     The logger instance.
+ */
+DECLINLINE(void) rtlogUnlock(PRTLOGGER pLogger)
+{
+#ifndef IN_RC
+    if (pLogger->pInt->hSpinMtx != NIL_RTSEMSPINMUTEX)
+        RTSemSpinMutexRelease(pLogger->pInt->hSpinMtx);
+#else
+    NOREF(pLogger);
+#endif
+    return;
+}
+
+#ifndef IN_RC
+# ifdef IN_RING3
+
+#  ifdef SOME_UNUSED_FUNCTION
+/**
+ * Logging to file, output callback.
+ *
+ * @param  pvArg        User argument.
+ * @param  pachChars    Pointer to an array of utf-8 characters.
+ * @param  cbChars      Number of bytes in the character array pointed to by pachChars.
+ */
+static DECLCALLBACK(size_t) rtlogPhaseWrite(void *pvArg, const char *pachChars, size_t cbChars)
+{
+    PRTLOGGER pLogger = (PRTLOGGER)pvArg;
+    RTFileWrite(pLogger->pInt->hFile, pachChars, cbChars, NULL);
+    return cbChars;
+}
+
+
+/**
+ * Callback to format VBox formatting extentions.
+ * See @ref pg_rt_str_format for a reference on the format types.
+ *
+ * @returns The number of bytes formatted.
+ * @param   pvArg           Formatter argument.
+ * @param   pfnOutput       Pointer to output function.
+ * @param   pvArgOutput     Argument for the output function.
+ * @param   ppszFormat      Pointer to the format string pointer. Advance this till the char
+ *                          after the format specifier.
+ * @param   pArgs           Pointer to the argument list. Use this to fetch the arguments.
+ * @param   cchWidth        Format Width. -1 if not specified.
+ * @param   cchPrecision    Format Precision. -1 if not specified.
+ * @param   fFlags          Flags (RTSTR_NTFS_*).
+ * @param   chArgSize       The argument size specifier, 'l' or 'L'.
+ */
+static DECLCALLBACK(size_t) rtlogPhaseFormatStr(void *pvArg, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
+                                                const char **ppszFormat, va_list *pArgs, int cchWidth,
+                                                int cchPrecision, unsigned fFlags, char chArgSize)
+{
+    char ch = *(*ppszFormat)++;
+
+    AssertMsgFailed(("Invalid logger phase format type '%%%c%.10s'!\n", ch, *ppszFormat)); NOREF(ch);
+
+    return 0;
+}
+
+#  endif /* SOME_UNUSED_FUNCTION */
+
+
+/**
+ * Log phase callback function, assumes the lock is already held
+ *
+ * @param   pLogger     The logger instance.
+ * @param   pszFormat   Format string.
+ * @param   ...         Optional arguments as specified in the format string.
+ */
+static DECLCALLBACK(void) rtlogPhaseMsgLocked(PRTLOGGER pLogger, const char *pszFormat, ...)
+{
+    va_list args;
+    AssertPtrReturnVoid(pLogger);
+    AssertPtrReturnVoid(pLogger->pInt);
+    Assert(pLogger->pInt->hSpinMtx != NIL_RTSEMSPINMUTEX);
+
+    va_start(args, pszFormat);
+    rtlogLoggerExVLocked(pLogger, 0, ~0U, pszFormat, args);
+    va_end(args);
+}
+
+
+/**
+ * Log phase callback function, assumes the lock is not held.
+ *
+ * @param   pLogger     The logger instance.
+ * @param   pszFormat   Format string.
+ * @param   ...         Optional arguments as specified in the format string.
+ */
+static DECLCALLBACK(void) rtlogPhaseMsgNormal(PRTLOGGER pLogger, const char *pszFormat, ...)
+{
+    va_list args;
+    AssertPtrReturnVoid(pLogger);
+    AssertPtrReturnVoid(pLogger->pInt);
+    Assert(pLogger->pInt->hSpinMtx != NIL_RTSEMSPINMUTEX);
+
+    va_start(args, pszFormat);
+    RTLogLoggerExV(pLogger, 0, ~0U, pszFormat, args);
+    va_end(args);
+}
+
+# endif /* IN_RING3 */
+
+/**
+ * Adjusts the ring buffer.
+ *
+ * @returns IPRT status code.
+ * @param   pLogger     The logger instance.
+ * @param   cbNewSize   The new ring buffer size (0 == default).
+ * @param   fForce      Whether to do this even if the logger instance hasn't
+ *                      really been fully created yet (i.e. during RTLogCreate).
+ */
+static int rtLogRingBufAdjust(PRTLOGGER pLogger, uint32_t cbNewSize, bool fForce)
+{
+    /*
+     * If this is early logger init, don't do anything.
+     */
+    if (!pLogger->pInt->fCreated && !fForce)
+        return VINF_SUCCESS;
+
+    /*
+     * Lock the logger and make the necessary changes.
+     */
+    int rc = rtlogLock(pLogger);
+    if (RT_SUCCESS(rc))
+    {
+        if (cbNewSize == 0)
+            cbNewSize = RTLOG_RINGBUF_DEFAULT_SIZE;
+        if (   pLogger->pInt->cbRingBuf != cbNewSize
+            || !pLogger->pInt->pchRingBufCur)
+        {
+            uintptr_t offOld = pLogger->pInt->pchRingBufCur - pLogger->pInt->pszRingBuf;
+            if (offOld < sizeof(RTLOG_RINGBUF_EYE_CATCHER))
+                offOld = sizeof(RTLOG_RINGBUF_EYE_CATCHER);
+            else if (offOld >= cbNewSize)
+            {
+                memmove(pLogger->pInt->pszRingBuf, &pLogger->pInt->pszRingBuf[offOld - cbNewSize], cbNewSize);
+                offOld = sizeof(RTLOG_RINGBUF_EYE_CATCHER);
+            }
+
+            void *pvNew = RTMemRealloc(pLogger->pInt->pchRingBufCur, cbNewSize);
+            if (pvNew)
+            {
+                pLogger->pInt->pszRingBuf    = (char *)pvNew;
+                pLogger->pInt->pchRingBufCur = (char *)pvNew + offOld;
+                pLogger->pInt->cbRingBuf     = cbNewSize;
+                memcpy(pvNew, RTLOG_RINGBUF_EYE_CATCHER, sizeof(RTLOG_RINGBUF_EYE_CATCHER));
+                memcpy((char *)pvNew + cbNewSize - sizeof(RTLOG_RINGBUF_EYE_CATCHER_END),
+                       RTLOG_RINGBUF_EYE_CATCHER_END, sizeof(RTLOG_RINGBUF_EYE_CATCHER_END));
+                rc = VINF_SUCCESS;
+            }
+            else
+                rc = VERR_NO_MEMORY;
+        }
+        rtlogUnlock(pLogger);
+    }
+
+    return rc;
+}
+
+
+/**
+ * Writes text to the ring buffer.
+ *
+ * @param   pInt                The internal logger data structure.
+ * @param   pachText            The text to write.
+ * @param   cchText             The number of chars (bytes) to write.
+ */
+static void rtLogRingBufWrite(PRTLOGGERINTERNAL pInt, const char *pachText, size_t cchText)
+{
+    /*
+     * Get the ring buffer data, adjusting it to only describe the writable
+     * part of the buffer.
+     */
+    char * const pchStart = &pInt->pszRingBuf[sizeof(RTLOG_RINGBUF_EYE_CATCHER)];
+    size_t const cchBuf   = pInt->cbRingBuf - sizeof(RTLOG_RINGBUF_EYE_CATCHER) - sizeof(RTLOG_RINGBUF_EYE_CATCHER_END);
+    char        *pchCur   = pInt->pchRingBufCur;
+    size_t       cchLeft  = pchCur - pchStart;
+    if (RT_LIKELY(cchLeft < cchBuf))
+        cchLeft = cchBuf - cchLeft;
+    else
+    {
+        /* May happen in ring-0 where a thread or two went ahead without getting the lock. */
+        pchCur = pchStart;
+        cchLeft = cchBuf;
+    }
+    Assert(cchBuf < pInt->cbRingBuf);
+
+    if (cchText < cchLeft)
+    {
+        /*
+         * The text fits in the remaining space.
+         */
+        memcpy(pchCur, pachText, cchText);
+        pchCur[cchText] = '\0';
+        pInt->pchRingBufCur = &pchCur[cchText];
+        pInt->cbRingBufUnflushed += cchText;
+    }
+    else
+    {
+        /*
+         * The text wraps around.  Taking the simple but inefficient approach
+         * to input texts that are longer than the ring buffer since that
+         * is unlikely to the be a frequent case.
+         */
+        /* Fill to the end of the buffer. */
+        memcpy(pchCur, pachText, cchLeft);
+        pachText += cchLeft;
+        cchText  -= cchLeft;
+        pInt->cbRingBufUnflushed += cchLeft;
+        pInt->pchRingBufCur       = pchStart;
+
+        /* Ring buffer overflows (the plainly inefficient bit). */
+        while (cchText >= cchBuf)
+        {
+            memcpy(pchStart, pachText, cchBuf);
+            pachText += cchBuf;
+            cchText  -= cchBuf;
+            pInt->cbRingBufUnflushed += cchBuf;
+        }
+
+        /* The final bit, if any. */
+        if (cchText > 0)
+        {
+            memcpy(pchStart, pachText, cchText);
+            pInt->cbRingBufUnflushed += cchText;
+        }
+        pchStart[cchText] = '\0';
+        pInt->pchRingBufCur = &pchStart[cchText];
+    }
+}
+
+
+/**
+ * Flushes the ring buffer to all the other log destinations.
+ *
+ * @param   pLogger     The logger instance which ring buffer should be flushed.
+ */
+static void rtLogRingBufFlush(PRTLOGGER pLogger)
+{
+    const char  *pszPreamble;
+    size_t       cchPreamble;
+    const char  *pszFirst;
+    size_t       cchFirst;
+    const char  *pszSecond;
+    size_t       cchSecond;
+
+    /*
+     * Get the ring buffer data, adjusting it to only describe the writable
+     * part of the buffer.
+     */
+    uint64_t     cchUnflushed = pLogger->pInt->cbRingBufUnflushed;
+    char * const pszBuf   = &pLogger->pInt->pszRingBuf[sizeof(RTLOG_RINGBUF_EYE_CATCHER)];
+    size_t const cchBuf   = pLogger->pInt->cbRingBuf - sizeof(RTLOG_RINGBUF_EYE_CATCHER) - sizeof(RTLOG_RINGBUF_EYE_CATCHER_END);
+    size_t       offCur   = pLogger->pInt->pchRingBufCur - pszBuf;
+    size_t       cchAfter;
+    if (RT_LIKELY(offCur < cchBuf))
+        cchAfter = cchBuf - offCur;
+    else /* May happen in ring-0 where a thread or two went ahead without getting the lock. */
+    {
+        offCur   = 0;
+        cchAfter = cchBuf;
+    }
+
+    pLogger->pInt->cbRingBufUnflushed = 0;
+
+    /*
+     * Figure out whether there are one or two segments that needs writing,
+     * making the last segment is terminated.  (The first is always
+     * terminated because of the eye-catcher at the end of the buffer.)
+     */
+    if (cchUnflushed == 0)
+        return;
+    pszBuf[offCur] = '\0';
+    if (cchUnflushed >= cchBuf)
+    {
+        pszFirst    = &pszBuf[offCur + 1];
+        cchFirst    = cchAfter ? cchAfter - 1 : 0;
+        pszSecond   = pszBuf;
+        cchSecond   = offCur;
+        pszPreamble =        "\n*FLUSH RING BUF*\n";
+        cchPreamble = sizeof("\n*FLUSH RING BUF*\n") - 1;
+    }
+    else if ((size_t)cchUnflushed <= offCur)
+    {
+        cchFirst    = (size_t)cchUnflushed;
+        pszFirst    = &pszBuf[offCur - cchFirst];
+        pszSecond   = "";
+        cchSecond   = 0;
+        pszPreamble = "";
+        cchPreamble = 0;
+    }
+    else
+    {
+        cchFirst    = (size_t)cchUnflushed - offCur;
+        pszFirst    = &pszBuf[cchBuf - cchFirst];
+        pszSecond   = pszBuf;
+        cchSecond   = offCur;
+        pszPreamble = "";
+        cchPreamble = 0;
+    }
+
+    /*
+     * Write the ring buffer to all other destiations.
+     */
+    if (pLogger->fDestFlags & RTLOGDEST_USER)
+    {
+        if (cchPreamble)
+            RTLogWriteUser(pszPreamble, cchPreamble);
+        if (cchFirst)
+            RTLogWriteUser(pszFirst, cchFirst);
+        if (cchSecond)
+            RTLogWriteUser(pszSecond, cchSecond);
+    }
+
+    if (pLogger->fDestFlags & RTLOGDEST_DEBUGGER)
+    {
+        if (cchPreamble)
+            RTLogWriteDebugger(pszPreamble, cchPreamble);
+        if (cchFirst)
+            RTLogWriteDebugger(pszFirst, cchFirst);
+        if (cchSecond)
+            RTLogWriteDebugger(pszSecond, cchSecond);
+    }
+
+# ifdef IN_RING3
+    if (pLogger->fDestFlags & RTLOGDEST_FILE)
+    {
+        if (pLogger->pInt->hFile != NIL_RTFILE)
+        {
+            if (cchPreamble)
+                RTFileWrite(pLogger->pInt->hFile, pszPreamble, cchPreamble, NULL);
+            if (cchFirst)
+                RTFileWrite(pLogger->pInt->hFile, pszFirst, cchFirst, NULL);
+            if (cchSecond)
+                RTFileWrite(pLogger->pInt->hFile, pszSecond, cchSecond, NULL);
+            if (pLogger->fFlags & RTLOGFLAGS_FLUSH)
+                RTFileFlush(pLogger->pInt->hFile);
+        }
+        if (pLogger->pInt->cHistory)
+            pLogger->pInt->cbHistoryFileWritten += cchFirst + cchSecond;
+    }
+# endif
+
+    if (pLogger->fDestFlags & RTLOGDEST_STDOUT)
+    {
+        if (cchPreamble)
+            RTLogWriteStdOut(pszPreamble, cchPreamble);
+        if (cchFirst)
+            RTLogWriteStdOut(pszFirst, cchFirst);
+        if (cchSecond)
+            RTLogWriteStdOut(pszSecond, cchSecond);
+    }
+
+    if (pLogger->fDestFlags & RTLOGDEST_STDERR)
+    {
+        if (cchPreamble)
+            RTLogWriteStdErr(pszPreamble, cchPreamble);
+        if (cchFirst)
+            RTLogWriteStdErr(pszFirst, cchFirst);
+        if (cchSecond)
+            RTLogWriteStdErr(pszSecond, cchSecond);
+    }
+
+# if defined(IN_RING0) && !defined(LOG_NO_COM)
+    if (pLogger->fDestFlags & RTLOGDEST_COM)
+    {
+        if (cchPreamble)
+            RTLogWriteCom(pszPreamble, cchPreamble);
+        if (cchFirst)
+            RTLogWriteCom(pszFirst, cchFirst);
+        if (cchSecond)
+            RTLogWriteCom(pszSecond, cchSecond);
+    }
+# endif
+}
+
+
+
+
+RTDECL(int) RTLogCreateExV(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings,
+                           const char *pszEnvVarBase, unsigned cGroups, const char * const *papszGroups,
+                           uint32_t fDestFlags, PFNRTLOGPHASE pfnPhase, uint32_t cHistory,
+                           uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot,
+                           char *pszErrorMsg, size_t cchErrorMsg, const char *pszFilenameFmt, va_list args)
+{
+    int         rc;
+    size_t      offInternal;
+    size_t      cbLogger;
+    PRTLOGGER   pLogger;
+
+    /*
+     * Validate input.
+     */
+    if (    (cGroups && !papszGroups)
+        ||  !VALID_PTR(ppLogger) )
+    {
+        AssertMsgFailed(("Invalid parameters!\n"));
+        return VERR_INVALID_PARAMETER;
+    }
+    *ppLogger = NULL;
+
+    if (pszErrorMsg)
+        RTStrPrintf(pszErrorMsg, cchErrorMsg, N_("unknown error"));
+
+    AssertMsgReturn(cHistory < _1M, ("%#x", cHistory), VERR_OUT_OF_RANGE);
+
+    /*
+     * Allocate a logger instance.
+     */
+    offInternal = RT_OFFSETOF(RTLOGGER, afGroups[cGroups]);
+    offInternal = RT_ALIGN_Z(offInternal, sizeof(uint64_t));
+    cbLogger = offInternal + sizeof(RTLOGGERINTERNAL);
+    if (fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
+        cbLogger += cGroups * sizeof(uint32_t);
+    pLogger = (PRTLOGGER)RTMemAllocZVar(cbLogger);
+    if (pLogger)
+    {
+# if defined(RT_ARCH_X86) && (!defined(LOG_USE_C99) || !defined(RT_WITHOUT_EXEC_ALLOC))
+        uint8_t *pu8Code;
+# endif
+        pLogger->u32Magic       = RTLOGGER_MAGIC;
+        pLogger->cGroups        = cGroups;
+        pLogger->fFlags         = fFlags;
+        pLogger->fDestFlags     = fDestFlags;
+        pLogger->pInt           = (PRTLOGGERINTERNAL)((uintptr_t)pLogger + offInternal);
+        pLogger->pInt->uRevision                = RTLOGGERINTERNAL_REV;
+        pLogger->pInt->cbSelf                   = sizeof(RTLOGGERINTERNAL);
+        pLogger->pInt->hSpinMtx                 = NIL_RTSEMSPINMUTEX;
+        pLogger->pInt->pfnFlush                 = NULL;
+        pLogger->pInt->pfnPrefix                = NULL;
+        pLogger->pInt->pvPrefixUserArg          = NULL;
+        pLogger->pInt->afPadding1[0]            = false;
+        pLogger->pInt->afPadding1[1]            = false;
+        pLogger->pInt->fCreated                 = false;
+        pLogger->pInt->cMaxGroups               = cGroups;
+        pLogger->pInt->papszGroups              = papszGroups;
+        if (fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
+            pLogger->pInt->pacEntriesPerGroup   = (uint32_t *)(pLogger->pInt + 1);
+        else
+            pLogger->pInt->pacEntriesPerGroup   = NULL;
+        pLogger->pInt->cMaxEntriesPerGroup      = UINT32_MAX;
+# ifdef IN_RING3
+        pLogger->pInt->pfnPhase                 = pfnPhase;
+        pLogger->pInt->hFile                    = NIL_RTFILE;
+        pLogger->pInt->cHistory                 = cHistory;
+        if (cbHistoryFileMax == 0)
+            pLogger->pInt->cbHistoryFileMax     = UINT64_MAX;
+        else
+            pLogger->pInt->cbHistoryFileMax     = cbHistoryFileMax;
+        if (cSecsHistoryTimeSlot == 0)
+            pLogger->pInt->cSecsHistoryTimeSlot = UINT32_MAX;
+        else
+            pLogger->pInt->cSecsHistoryTimeSlot = cSecsHistoryTimeSlot;
+# else   /* !IN_RING3 */
+        RT_NOREF_PV(pfnPhase); RT_NOREF_PV(cHistory); RT_NOREF_PV(cbHistoryFileMax); RT_NOREF_PV(cSecsHistoryTimeSlot);
+# endif  /* !IN_RING3 */
+        if (pszGroupSettings)
+            RTLogGroupSettings(pLogger, pszGroupSettings);
+
+# if defined(RT_ARCH_X86) && (!defined(LOG_USE_C99) || !defined(RT_WITHOUT_EXEC_ALLOC))
+        /*
+         * Emit wrapper code.
+         */
+        pu8Code = (uint8_t *)RTMemExecAlloc(64);
+        if (pu8Code)
+        {
+            pLogger->pfnLogger = *(PFNRTLOGGER*)&pu8Code;
+            *pu8Code++ = 0x68;          /* push imm32 */
+            *(void **)pu8Code = pLogger;
+            pu8Code += sizeof(void *);
+            *pu8Code++ = 0xe8;          /* call rel32 */
+            *(uint32_t *)pu8Code = (uintptr_t)RTLogLogger - ((uintptr_t)pu8Code + sizeof(uint32_t));
+            pu8Code += sizeof(uint32_t);
+            *pu8Code++ = 0x8d;          /* lea esp, [esp + 4] */
+            *pu8Code++ = 0x64;
+            *pu8Code++ = 0x24;
+            *pu8Code++ = 0x04;
+            *pu8Code++ = 0xc3;          /* ret near */
+            AssertMsg((uintptr_t)pu8Code - (uintptr_t)pLogger->pfnLogger <= 64,
+                      ("Wrapper assembly is too big! %d bytes\n", (uintptr_t)pu8Code - (uintptr_t)pLogger->pfnLogger));
+            rc = VINF_SUCCESS;
+        }
+        else
+        {
+#  ifdef RT_OS_LINUX
+            if (pszErrorMsg) /* Most probably SELinux causing trouble since the larger RTMemAlloc succeeded. */
+                RTStrPrintf(pszErrorMsg, cchErrorMsg, N_("mmap(PROT_WRITE | PROT_EXEC) failed -- SELinux?"));
+#  endif
+            rc = VERR_NO_MEMORY;
+        }
+        if (RT_SUCCESS(rc))
+# endif /* X86 wrapper code*/
+        {
+# ifdef IN_RING3 /* files and env.vars. are only accessible when in R3 at the present time. */
+            /*
+             * Format the filename.
+             */
+            if (pszFilenameFmt)
+            {
+                /** @todo validate the length, fail on overflow. */
+                RTStrPrintfV(pLogger->pInt->szFilename, sizeof(pLogger->pInt->szFilename), pszFilenameFmt, args);
+                pLogger->fDestFlags |= RTLOGDEST_FILE;
+            }
+
+            /*
+             * Parse the environment variables.
+             */
+            if (pszEnvVarBase)
+            {
+                /* make temp copy of environment variable base. */
+                size_t  cchEnvVarBase = strlen(pszEnvVarBase);
+                char   *pszEnvVar = (char *)alloca(cchEnvVarBase + 16);
+                memcpy(pszEnvVar, pszEnvVarBase, cchEnvVarBase);
+
+                /*
+                 * Destination.
+                 */
+                strcpy(pszEnvVar + cchEnvVarBase, "_DEST");
+                const char *pszValue = RTEnvGet(pszEnvVar);
+                if (pszValue)
+                    RTLogDestinations(pLogger, pszValue);
+
+                /*
+                 * The flags.
+                 */
+                strcpy(pszEnvVar + cchEnvVarBase, "_FLAGS");
+                pszValue = RTEnvGet(pszEnvVar);
+                if (pszValue)
+                    RTLogFlags(pLogger, pszValue);
+
+                /*
+                 * The group settings.
+                 */
+                pszEnvVar[cchEnvVarBase] = '\0';
+                pszValue = RTEnvGet(pszEnvVar);
+                if (pszValue)
+                    RTLogGroupSettings(pLogger, pszValue);
+            }
+# else  /* !IN_RING3 */
+            RT_NOREF_PV(pszEnvVarBase); RT_NOREF_PV(pszFilenameFmt); RT_NOREF_PV(args);
+# endif /* !IN_RING3 */
+
+            /*
+             * Open the destination(s).
+             */
+            rc = VINF_SUCCESS;
+# ifdef IN_RING3
+            if (pLogger->fDestFlags & RTLOGDEST_FILE)
+            {
+                if (pLogger->fFlags & RTLOGFLAGS_APPEND)
+                {
+                    rc = rtlogFileOpen(pLogger, pszErrorMsg, cchErrorMsg);
+
+                    /* Rotate in case of appending to a too big log file,
+                       otherwise this simply doesn't do anything. */
+                    rtlogRotate(pLogger, 0, true /* fFirst */);
+                }
+                else
+                {
+                    /* Force rotation if it is configured. */
+                    pLogger->pInt->cbHistoryFileWritten = UINT64_MAX;
+                    rtlogRotate(pLogger, 0, true /* fFirst */);
+
+                    /* If the file is not open then rotation is not set up. */
+                    if (pLogger->pInt->hFile == NIL_RTFILE)
+                    {
+                        pLogger->pInt->cbHistoryFileWritten = 0;
+                        rc = rtlogFileOpen(pLogger, pszErrorMsg, cchErrorMsg);
+                    }
+                }
+            }
+# endif  /* IN_RING3 */
+
+            if ((pLogger->fDestFlags & RTLOGDEST_RINGBUF) && RT_SUCCESS(rc))
+                rc = rtLogRingBufAdjust(pLogger, pLogger->pInt->cbRingBuf, true /*fForce*/);
+
+            /*
+             * Create mutex and check how much it counts when entering the lock
+             * so that we can report the values for RTLOGFLAGS_PREFIX_LOCK_COUNTS.
+             */
+            if (RT_SUCCESS(rc))
+            {
+                rc = RTSemSpinMutexCreate(&pLogger->pInt->hSpinMtx, RTSEMSPINMUTEX_FLAGS_IRQ_SAFE);
+                if (RT_SUCCESS(rc))
+                {
+# ifdef IN_RING3 /** @todo do counters in ring-0 too? */
+                    RTTHREAD Thread = RTThreadSelf();
+                    if (Thread != NIL_RTTHREAD)
+                    {
+                        int32_t c = RTLockValidatorWriteLockGetCount(Thread);
+                        RTSemSpinMutexRequest(pLogger->pInt->hSpinMtx);
+                        c = RTLockValidatorWriteLockGetCount(Thread) - c;
+                        RTSemSpinMutexRelease(pLogger->pInt->hSpinMtx);
+                        ASMAtomicWriteU32(&g_cLoggerLockCount, c);
+                    }
+
+                    /* Use the callback to generate some initial log contents. */
+                    Assert(VALID_PTR(pLogger->pInt->pfnPhase) || pLogger->pInt->pfnPhase == NULL);
+                    if (pLogger->pInt->pfnPhase)
+                        pLogger->pInt->pfnPhase(pLogger, RTLOGPHASE_BEGIN, rtlogPhaseMsgNormal);
+# endif
+                    pLogger->pInt->fCreated = true;
+                    *ppLogger = pLogger;
+                    return VINF_SUCCESS;
+                }
+
+                if (pszErrorMsg)
+                    RTStrPrintf(pszErrorMsg, cchErrorMsg, N_("failed to create semaphore"));
+            }
+# ifdef IN_RING3
+            RTFileClose(pLogger->pInt->hFile);
+# endif
+# if defined(LOG_USE_C99) && defined(RT_WITHOUT_EXEC_ALLOC)
+            RTMemFree(*(void **)&pLogger->pfnLogger);
+# else
+            RTMemExecFree(*(void **)&pLogger->pfnLogger, 64);
+# endif
+        }
+        RTMemFree(pLogger);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTLogCreateExV);
+
+
+RTDECL(int) RTLogCreate(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings,
+                        const char *pszEnvVarBase, unsigned cGroups, const char * const * papszGroups,
+                        uint32_t fDestFlags, const char *pszFilenameFmt, ...)
+{
+    va_list args;
+    int rc;
+
+    va_start(args, pszFilenameFmt);
+    rc = RTLogCreateExV(ppLogger, fFlags, pszGroupSettings, pszEnvVarBase, cGroups, papszGroups,
+                        fDestFlags, NULL /*pfnPhase*/, 0 /*cHistory*/, 0 /*cbHistoryFileMax*/, 0 /*cSecsHistoryTimeSlot*/,
+                        NULL /*pszErrorMsg*/, 0 /*cchErrorMsg*/, pszFilenameFmt, args);
+    va_end(args);
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTLogCreate);
+
+
+RTDECL(int) RTLogCreateEx(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings,
+                          const char *pszEnvVarBase, unsigned cGroups, const char * const * papszGroups,
+                          uint32_t fDestFlags, PFNRTLOGPHASE pfnPhase, uint32_t cHistory,
+                          uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot,
+                          char *pszErrorMsg, size_t cchErrorMsg, const char *pszFilenameFmt, ...)
+{
+    va_list args;
+    int rc;
+
+    va_start(args, pszFilenameFmt);
+    rc = RTLogCreateExV(ppLogger, fFlags, pszGroupSettings, pszEnvVarBase, cGroups, papszGroups,
+                        fDestFlags, pfnPhase, cHistory, cbHistoryFileMax, cSecsHistoryTimeSlot,
+                        pszErrorMsg, cchErrorMsg, pszFilenameFmt, args);
+    va_end(args);
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTLogCreateEx);
+
+
+/**
+ * Destroys a logger instance.
+ *
+ * The instance is flushed and all output destinations closed (where applicable).
+ *
+ * @returns iprt status code.
+ * @param   pLogger             The logger instance which close destroyed. NULL is fine.
+ */
+RTDECL(int) RTLogDestroy(PRTLOGGER pLogger)
+{
+    int             rc;
+    uint32_t        iGroup;
+    RTSEMSPINMUTEX  hSpinMtx;
+
+    /*
+     * Validate input.
+     */
+    if (!pLogger)
+        return VINF_SUCCESS;
+    AssertPtrReturn(pLogger, VERR_INVALID_POINTER);
+    AssertReturn(pLogger->u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
+    AssertPtrReturn(pLogger->pInt, VERR_INVALID_POINTER);
+
+    /*
+     * Acquire logger instance sem and disable all logging. (paranoia)
+     */
+    rc = rtlogLock(pLogger);
+    AssertMsgRCReturn(rc, ("%Rrc\n", rc), rc);
+
+    pLogger->fFlags |= RTLOGFLAGS_DISABLED;
+    iGroup = pLogger->cGroups;
+    while (iGroup-- > 0)
+        pLogger->afGroups[iGroup] = 0;
+
+    /*
+     * Flush it.
+     */
+    rtlogFlush(pLogger);
+
+# ifdef IN_RING3
+    /*
+     * Add end of logging message.
+     */
+    if (   (pLogger->fDestFlags & RTLOGDEST_FILE)
+        && pLogger->pInt->hFile != NIL_RTFILE)
+        pLogger->pInt->pfnPhase(pLogger, RTLOGPHASE_END, rtlogPhaseMsgLocked);
+
+    /*
+     * Close output stuffs.
+     */
+    if (pLogger->pInt->hFile != NIL_RTFILE)
+    {
+        int rc2 = RTFileClose(pLogger->pInt->hFile);
+        AssertRC(rc2);
+        if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
+            rc = rc2;
+        pLogger->pInt->hFile = NIL_RTFILE;
+    }
+# endif
+
+    /*
+     * Free the mutex, the wrapper and the instance memory.
+     */
+    hSpinMtx = pLogger->pInt->hSpinMtx;
+    pLogger->pInt->hSpinMtx = NIL_RTSEMSPINMUTEX;
+    if (hSpinMtx != NIL_RTSEMSPINMUTEX)
+    {
+        int rc2;
+        RTSemSpinMutexRelease(hSpinMtx);
+        rc2 = RTSemSpinMutexDestroy(hSpinMtx);
+        AssertRC(rc2);
+        if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
+            rc = rc2;
+    }
+
+    if (pLogger->pfnLogger)
+    {
+# if defined(LOG_USE_C99) && defined(RT_WITHOUT_EXEC_ALLOC)
+        RTMemFree(*(void **)&pLogger->pfnLogger);
+# else
+        RTMemExecFree(*(void **)&pLogger->pfnLogger, 64);
+# endif
+        pLogger->pfnLogger = NULL;
+    }
+    RTMemFree(pLogger);
+
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTLogDestroy);
+
+
+/**
+ * Create a logger instance clone for RC usage.
+ *
+ * @returns iprt status code.
+ *
+ * @param   pLogger             The logger instance to be cloned.
+ * @param   pLoggerRC           Where to create the RC logger instance.
+ * @param   cbLoggerRC          Amount of memory allocated to for the RC logger
+ *                              instance clone.
+ * @param   pfnLoggerRCPtr      Pointer to logger wrapper function for this
+ *                              instance (RC Ptr).
+ * @param   pfnFlushRCPtr       Pointer to flush function (RC Ptr).
+ * @param   fFlags              Logger instance flags, a combination of the RTLOGFLAGS_* values.
+ */
+RTDECL(int) RTLogCloneRC(PRTLOGGER pLogger, PRTLOGGERRC pLoggerRC, size_t cbLoggerRC,
+                         RTRCPTR pfnLoggerRCPtr, RTRCPTR pfnFlushRCPtr, uint32_t fFlags)
+{
+    /*
+     * Validate input.
+     */
+   if (    !pLoggerRC
+       ||  !pfnFlushRCPtr
+       ||  !pfnLoggerRCPtr)
+    {
+       AssertMsgFailed(("Invalid parameters!\n"));
+       return VERR_INVALID_PARAMETER;
+    }
+    if (cbLoggerRC < sizeof(*pLoggerRC))
+    {
+        AssertMsgFailed(("%d min=%d\n", cbLoggerRC, sizeof(*pLoggerRC)));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    /*
+     * Initialize GC instance.
+     */
+    pLoggerRC->offScratch   = 0;
+    pLoggerRC->fPendingPrefix = false;
+    pLoggerRC->pfnLogger    = pfnLoggerRCPtr;
+    pLoggerRC->pfnFlush     = pfnFlushRCPtr;
+    pLoggerRC->u32Magic     = RTLOGGERRC_MAGIC;
+    pLoggerRC->fFlags       = fFlags | RTLOGFLAGS_DISABLED;
+    pLoggerRC->cGroups      = 1;
+    pLoggerRC->afGroups[0]  = 0;
+
+    /*
+     * Resolve defaults.
+     */
+    if (!pLogger)
+    {
+        pLogger = RTLogDefaultInstance();
+        if (!pLogger)
+            return VINF_SUCCESS;
+    }
+
+    /*
+     * Check if there's enough space for the groups.
+     */
+    if (cbLoggerRC < (size_t)RT_OFFSETOF(RTLOGGERRC, afGroups[pLogger->cGroups]))
+    {
+        AssertMsgFailed(("%d req=%d cGroups=%d\n", cbLoggerRC, RT_OFFSETOF(RTLOGGERRC, afGroups[pLogger->cGroups]), pLogger->cGroups));
+        return VERR_BUFFER_OVERFLOW;
+    }
+    memcpy(&pLoggerRC->afGroups[0], &pLogger->afGroups[0], pLogger->cGroups * sizeof(pLoggerRC->afGroups[0]));
+    pLoggerRC->cGroups = pLogger->cGroups;
+
+    /*
+     * Copy bits from the HC instance.
+     */
+    pLoggerRC->fPendingPrefix = pLogger->pInt->fPendingPrefix;
+    pLoggerRC->fFlags |= pLogger->fFlags;
+
+    /*
+     * Check if we can remove the disabled flag.
+     */
+    if (    pLogger->fDestFlags
+        &&  !((pLogger->fFlags | fFlags) & RTLOGFLAGS_DISABLED))
+        pLoggerRC->fFlags &= ~RTLOGFLAGS_DISABLED;
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTLogCloneRC);
+
+
+/**
+ * Flushes a RC logger instance to a R3 logger.
+ *
+ *
+ * @returns iprt status code.
+ * @param   pLogger     The R3 logger instance to flush pLoggerRC to. If NULL
+ *                      the default logger is used.
+ * @param   pLoggerRC   The RC logger instance to flush.
+ */
+RTDECL(void) RTLogFlushRC(PRTLOGGER pLogger, PRTLOGGERRC pLoggerRC)
+{
+    /*
+     * Resolve defaults.
+     */
+    if (!pLogger)
+    {
+        pLogger = RTLogDefaultInstance();
+        if (!pLogger)
+        {
+            pLoggerRC->offScratch = 0;
+            return;
+        }
+    }
+
+    /*
+     * Any thing to flush?
+     */
+    if (    pLogger->offScratch
+        ||  pLoggerRC->offScratch)
+    {
+        /*
+         * Acquire logger instance sem.
+         */
+        int rc = rtlogLock(pLogger);
+        if (RT_FAILURE(rc))
+            return;
+
+        /*
+         * Write whatever the GC instance contains to the HC one, and then
+         * flush the HC instance.
+         */
+        if (pLoggerRC->offScratch)
+        {
+            rtLogOutput(pLogger, pLoggerRC->achScratch, pLoggerRC->offScratch);
+            rtLogOutput(pLogger, NULL, 0);
+            pLoggerRC->offScratch = 0;
+        }
+
+        /*
+         * Release the semaphore.
+         */
+        rtlogUnlock(pLogger);
+    }
+}
+RT_EXPORT_SYMBOL(RTLogFlushRC);
+
+# ifdef IN_RING3
+
+RTDECL(int) RTLogCreateForR0(PRTLOGGER pLogger, size_t cbLogger,
+                             RTR0PTR pLoggerR0Ptr, RTR0PTR pfnLoggerR0Ptr, RTR0PTR pfnFlushR0Ptr,
+                             uint32_t fFlags, uint32_t fDestFlags)
+{
+    /*
+     * Validate input.
+     */
+    AssertPtrReturn(pLogger, VERR_INVALID_PARAMETER);
+    size_t const cbRequired = sizeof(*pLogger) + RTLOGGERINTERNAL_R0_SIZE;
+    AssertReturn(cbLogger >= cbRequired, VERR_BUFFER_OVERFLOW);
+    AssertReturn(pLoggerR0Ptr != NIL_RTR0PTR, VERR_INVALID_PARAMETER);
+    AssertReturn(pfnLoggerR0Ptr != NIL_RTR0PTR, VERR_INVALID_PARAMETER);
+
+    /*
+     * Initialize the ring-0 instance.
+     */
+    pLogger->achScratch[0]  = 0;
+    pLogger->offScratch     = 0;
+    pLogger->pfnLogger      = (PFNRTLOGGER)pfnLoggerR0Ptr;
+    pLogger->fFlags         = fFlags;
+    pLogger->fDestFlags     = fDestFlags & ~RTLOGDEST_FILE;
+    pLogger->pInt           = NULL;
+    pLogger->cGroups        = 1;
+    pLogger->afGroups[0]    = 0;
+
+    uint32_t cMaxGroups     = (uint32_t)((cbLogger - cbRequired) / sizeof(pLogger->afGroups[0]));
+    if (fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
+        cMaxGroups /= 2;
+    PRTLOGGERINTERNAL pInt;
+    for (;;)
+    {
+        AssertReturn(cMaxGroups > 0, VERR_BUFFER_OVERFLOW);
+        pInt = (PRTLOGGERINTERNAL)&pLogger->afGroups[cMaxGroups];
+        if (!((uintptr_t)pInt & (sizeof(uint64_t) - 1)))
+            break;
+        cMaxGroups--;
+    }
+    pLogger->pInt               = (PRTLOGGERINTERNAL)(pLoggerR0Ptr + (uintptr_t)pInt - (uintptr_t)pLogger);
+    pInt->uRevision             = RTLOGGERINTERNAL_REV;
+    pInt->cbSelf                = RTLOGGERINTERNAL_R0_SIZE;
+    pInt->hSpinMtx              = NIL_RTSEMSPINMUTEX; /* Not serialized. */
+    pInt->pfnFlush              = (PFNRTLOGFLUSH)pfnFlushR0Ptr;
+    pInt->pfnPrefix             = NULL;
+    pInt->pvPrefixUserArg       = NULL;
+    pInt->fPendingPrefix        = false;
+    pInt->cMaxGroups            = cMaxGroups;
+    pInt->papszGroups           = NULL;
+    pInt->cMaxEntriesPerGroup   = UINT32_MAX;
+    if (fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
+    {
+        memset(pInt + 1, 0, sizeof(uint32_t) * cMaxGroups);
+        pInt->pacEntriesPerGroup= (uint32_t *)(pLogger->pInt + 1);
+    }
+    else
+        pInt->pacEntriesPerGroup= NULL;
+
+    pInt->fCreated              = true;
+    pLogger->u32Magic           = RTLOGGER_MAGIC;
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTLogCreateForR0);
+
+
+RTDECL(size_t) RTLogCalcSizeForR0(uint32_t cGroups, uint32_t fFlags)
+{
+    size_t cb = RT_OFFSETOF(RTLOGGER, afGroups[cGroups]);
+    cb = RT_ALIGN_Z(cb, sizeof(uint64_t));
+    cb += sizeof(RTLOGGERINTERNAL);
+    if (fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
+        cb += sizeof(uint32_t) * cGroups;
+    return cb;
+}
+RT_EXPORT_SYMBOL(RTLogCalcSizeForR0);
+
+
+RTDECL(int) RTLogCopyGroupsAndFlagsForR0(PRTLOGGER pDstLogger, RTR0PTR pDstLoggerR0Ptr,
+                                         PCRTLOGGER pSrcLogger, uint32_t fFlagsOr, uint32_t fFlagsAnd)
+{
+    /*
+     * Validate input.
+     */
+    AssertPtrReturn(pDstLogger, VERR_INVALID_PARAMETER);
+    AssertPtrNullReturn(pSrcLogger, VERR_INVALID_PARAMETER);
+
+    /*
+     * Resolve defaults.
+     */
+    if (!pSrcLogger)
+    {
+        pSrcLogger = RTLogDefaultInstance();
+        if (!pSrcLogger)
+        {
+            pDstLogger->fFlags |= RTLOGFLAGS_DISABLED | fFlagsOr;
+            pDstLogger->cGroups = 1;
+            pDstLogger->afGroups[0] = 0;
+            return VINF_SUCCESS;
+        }
+    }
+
+    /*
+     * Copy flags and group settings.
+     */
+    pDstLogger->fFlags = (pSrcLogger->fFlags & fFlagsAnd & ~RTLOGFLAGS_RESTRICT_GROUPS) | fFlagsOr;
+
+    PRTLOGGERINTERNAL   pDstInt = (PRTLOGGERINTERNAL)((uintptr_t)pDstLogger->pInt - pDstLoggerR0Ptr + (uintptr_t)pDstLogger);
+    int                 rc      = VINF_SUCCESS;
+    uint32_t            cGroups = pSrcLogger->cGroups;
+    if (cGroups > pDstInt->cMaxGroups)
+    {
+        AssertMsgFailed(("cMaxGroups=%zd cGroups=%zd (min size %d)\n", pDstInt->cMaxGroups,
+                         pSrcLogger->cGroups, RT_OFFSETOF(RTLOGGER, afGroups[pSrcLogger->cGroups]) + RTLOGGERINTERNAL_R0_SIZE));
+        rc = VERR_INVALID_PARAMETER;
+        cGroups = pDstInt->cMaxGroups;
+    }
+    memcpy(&pDstLogger->afGroups[0], &pSrcLogger->afGroups[0], cGroups * sizeof(pDstLogger->afGroups[0]));
+    pDstLogger->cGroups = cGroups;
+
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTLogCopyGroupsAndFlagsForR0);
+
+
+RTDECL(int) RTLogSetCustomPrefixCallbackForR0(PRTLOGGER pLogger, RTR0PTR pLoggerR0Ptr,
+                                              RTR0PTR pfnCallbackR0Ptr, RTR0PTR pvUserR0Ptr)
+{
+    AssertPtrReturn(pLogger, VERR_INVALID_POINTER);
+    AssertReturn(pLogger->u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
+
+    /*
+     * Do the work.
+     */
+    PRTLOGGERINTERNAL pInt = (PRTLOGGERINTERNAL)((uintptr_t)pLogger->pInt - pLoggerR0Ptr + (uintptr_t)pLogger);
+    AssertReturn(pInt->uRevision == RTLOGGERINTERNAL_REV, VERR_LOG_REVISION_MISMATCH);
+    pInt->pvPrefixUserArg = (void *)pvUserR0Ptr;
+    pInt->pfnPrefix       = (PFNRTLOGPREFIX)pfnCallbackR0Ptr;
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTLogSetCustomPrefixCallbackForR0);
+
+RTDECL(void) RTLogFlushR0(PRTLOGGER pLogger, PRTLOGGER pLoggerR0)
+{
+    /*
+     * Resolve defaults.
+     */
+    if (!pLogger)
+    {
+        pLogger = RTLogDefaultInstance();
+        if (!pLogger)
+        {
+            /* flushing to "/dev/null". */
+            if (pLoggerR0->offScratch)
+                    pLoggerR0->offScratch = 0;
+            return;
+        }
+    }
+
+    /*
+     * Anything to flush?
+     */
+    if (    pLoggerR0->offScratch
+        ||  pLogger->offScratch)
+    {
+        /*
+         * Acquire logger semaphores.
+         */
+        int rc = rtlogLock(pLogger);
+        if (RT_FAILURE(rc))
+            return;
+        if (RT_SUCCESS(rc))
+        {
+            /*
+             * Write whatever the GC instance contains to the HC one, and then
+             * flush the HC instance.
+             */
+            if (pLoggerR0->offScratch)
+            {
+                rtLogOutput(pLogger, pLoggerR0->achScratch, pLoggerR0->offScratch);
+                rtLogOutput(pLogger, NULL, 0);
+                pLoggerR0->offScratch = 0;
+            }
+        }
+        rtlogUnlock(pLogger);
+    }
+}
+RT_EXPORT_SYMBOL(RTLogFlushR0);
+
+# endif /* IN_RING3 */
+
+
+/**
+ * Flushes the buffer in one logger instance onto another logger.
+ *
+ * @returns iprt status code.
+ *
+ * @param   pSrcLogger   The logger instance to flush.
+ * @param   pDstLogger   The logger instance to flush onto.
+ *                       If NULL the default logger will be used.
+ */
+RTDECL(void) RTLogFlushToLogger(PRTLOGGER pSrcLogger, PRTLOGGER pDstLogger)
+{
+    /*
+     * Resolve defaults.
+     */
+    if (!pDstLogger)
+    {
+        pDstLogger = RTLogDefaultInstance();
+        if (!pDstLogger)
+        {
+            /* flushing to "/dev/null". */
+            if (pSrcLogger->offScratch)
+            {
+                int rc = rtlogLock(pSrcLogger);
+                if (RT_SUCCESS(rc))
+                {
+                    pSrcLogger->offScratch = 0;
+                    rtlogUnlock(pSrcLogger);
+                }
+            }
+            return;
+        }
+    }
+
+    /*
+     * Any thing to flush?
+     */
+    if (    pSrcLogger->offScratch
+        ||  pDstLogger->offScratch)
+    {
+        /*
+         * Acquire logger semaphores.
+         */
+        int rc = rtlogLock(pDstLogger);
+        if (RT_FAILURE(rc))
+            return;
+        rc = rtlogLock(pSrcLogger);
+        if (RT_SUCCESS(rc))
+        {
+            /*
+             * Write whatever the GC instance contains to the HC one, and then
+             * flush the HC instance.
+             */
+            if (pSrcLogger->offScratch)
+            {
+                rtLogOutput(pDstLogger, pSrcLogger->achScratch, pSrcLogger->offScratch);
+                rtLogOutput(pDstLogger, NULL, 0);
+                pSrcLogger->offScratch = 0;
+            }
+
+            /*
+             * Release the semaphores.
+             */
+            rtlogUnlock(pSrcLogger);
+        }
+        rtlogUnlock(pDstLogger);
+    }
+}
+RT_EXPORT_SYMBOL(RTLogFlushToLogger);
+
+
+/**
+ * Sets the custom prefix callback.
+ *
+ * @returns IPRT status code.
+ * @param   pLogger     The logger instance.
+ * @param   pfnCallback The callback.
+ * @param   pvUser      The user argument for the callback.
+ *  */
+RTDECL(int) RTLogSetCustomPrefixCallback(PRTLOGGER pLogger, PFNRTLOGPREFIX pfnCallback, void *pvUser)
+{
+    /*
+     * Resolve defaults.
+     */
+    if (!pLogger)
+    {
+        pLogger = RTLogDefaultInstance();
+        if (!pLogger)
+            return VINF_SUCCESS;
+    }
+    AssertReturn(pLogger->u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
+
+    /*
+     * Do the work.
+     */
+    rtlogLock(pLogger);
+    pLogger->pInt->pvPrefixUserArg = pvUser;
+    pLogger->pInt->pfnPrefix       = pfnCallback;
+    rtlogUnlock(pLogger);
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTLogSetCustomPrefixCallback);
+
+
+/**
+ * Matches a group name with a pattern mask in an case insensitive manner (ASCII).
+ *
+ * @returns true if matching and *ppachMask set to the end of the pattern.
+ * @returns false if no match.
+ * @param   pszGrp      The group name.
+ * @param   ppachMask   Pointer to the pointer to the mask. Only wildcard supported is '*'.
+ * @param   cchMask     The length of the mask, including modifiers. The modifiers is why
+ *                      we update *ppachMask on match.
+ */
+static bool rtlogIsGroupMatching(const char *pszGrp, const char **ppachMask, size_t cchMask)
+{
+    const char *pachMask;
+
+    if (!pszGrp || !*pszGrp)
+        return false;
+    pachMask = *ppachMask;
+    for (;;)
+    {
+        if (RT_C_TO_LOWER(*pszGrp) != RT_C_TO_LOWER(*pachMask))
+        {
+            const char *pszTmp;
+
+            /*
+             * Check for wildcard and do a minimal match if found.
+             */
+            if (*pachMask != '*')
+                return false;
+
+            /* eat '*'s. */
+            do  pachMask++;
+            while (--cchMask && *pachMask == '*');
+
+            /* is there more to match? */
+            if (    !cchMask
+                ||  *pachMask == '.'
+                ||  *pachMask == '=')
+                break; /* we're good */
+
+            /* do extremely minimal matching (fixme) */
+            pszTmp = strchr(pszGrp, RT_C_TO_LOWER(*pachMask));
+            if (!pszTmp)
+                pszTmp = strchr(pszGrp, RT_C_TO_UPPER(*pachMask));
+            if (!pszTmp)
+                return false;
+            pszGrp = pszTmp;
+            continue;
+        }
+
+        /* done? */
+        if (!*++pszGrp)
+        {
+            /* trailing wildcard is ok. */
+            do
+            {
+                pachMask++;
+                cchMask--;
+            } while (cchMask && *pachMask == '*');
+            if (    !cchMask
+                ||  *pachMask == '.'
+                ||  *pachMask == '=')
+                break; /* we're good */
+            return false;
+        }
+
+        if (!--cchMask)
+            return false;
+        pachMask++;
+    }
+
+    /* match */
+    *ppachMask = pachMask;
+    return true;
+}
+
+
+/**
+ * Updates the group settings for the logger instance using the specified
+ * specification string.
+ *
+ * @returns iprt status code.
+ *          Failures can safely be ignored.
+ * @param   pLogger     Logger instance.
+ * @param   pszValue    Value to parse.
+ */
+RTDECL(int) RTLogGroupSettings(PRTLOGGER pLogger, const char *pszValue)
+{
+    /*
+     * Resolve defaults.
+     */
+    if (!pLogger)
+    {
+        pLogger = RTLogDefaultInstance();
+        if (!pLogger)
+            return VINF_SUCCESS;
+    }
+
+    /*
+     * Iterate the string.
+     */
+    while (*pszValue)
+    {
+        /*
+         * Skip prefixes (blanks, ;, + and -).
+         */
+        bool    fEnabled = true;
+        char    ch;
+        const char *pszStart;
+        unsigned i;
+        size_t cch;
+
+        while ((ch = *pszValue) == '+' || ch == '-' || ch == ' ' || ch == '\t' || ch == '\n' || ch == ';')
+        {
+            if (ch == '+' || ch == '-' || ch == ';')
+                fEnabled = ch != '-';
+            pszValue++;
+        }
+        if (!*pszValue)
+            break;
+
+        /*
+         * Find end.
+         */
+        pszStart = pszValue;
+        while ((ch = *pszValue) != '\0' && ch != '+' && ch != '-' && ch != ' ' && ch != '\t')
+            pszValue++;
+
+        /*
+         * Find the group (ascii case insensitive search).
+         * Special group 'all'.
+         */
+        cch = pszValue - pszStart;
+        if (    cch >= 3
+            &&  (pszStart[0] == 'a' || pszStart[0] == 'A')
+            &&  (pszStart[1] == 'l' || pszStart[1] == 'L')
+            &&  (pszStart[2] == 'l' || pszStart[2] == 'L')
+            &&  (cch == 3 || pszStart[3] == '.' || pszStart[3] == '='))
+        {
+            /*
+             * All.
+             */
+            unsigned fFlags = cch == 3
+                            ? RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1
+                            : rtlogGroupFlags(&pszStart[3]);
+            for (i = 0; i < pLogger->cGroups; i++)
+            {
+                if (fEnabled)
+                    pLogger->afGroups[i] |= fFlags;
+                else
+                    pLogger->afGroups[i] &= ~fFlags;
+            }
+        }
+        else
+        {
+            /*
+             * Specific group(s).
+             */
+            for (i = 0; i < pLogger->cGroups; i++)
+            {
+                const char *psz2 = (const char*)pszStart;
+                if (rtlogIsGroupMatching(pLogger->pInt->papszGroups[i], &psz2, cch))
+                {
+                    unsigned fFlags = RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1;
+                    if (*psz2 == '.' || *psz2 == '=')
+                        fFlags = rtlogGroupFlags(psz2);
+                    if (fEnabled)
+                        pLogger->afGroups[i] |= fFlags;
+                    else
+                        pLogger->afGroups[i] &= ~fFlags;
+                }
+            } /* for each group */
+        }
+
+    } /* parse specification */
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTLogGroupSettings);
+
+
+/**
+ * Interprets the group flags suffix.
+ *
+ * @returns Flags specified. (0 is possible!)
+ * @param   psz     Start of Suffix. (Either dot or equal sign.)
+ */
+static unsigned rtlogGroupFlags(const char *psz)
+{
+    unsigned fFlags = 0;
+
+    /*
+     * Literal flags.
+     */
+    while (*psz == '.')
+    {
+        static struct
+        {
+            const char *pszFlag;        /* lowercase!! */
+            unsigned    fFlag;
+        } aFlags[] =
+        {
+            { "eo",         RTLOGGRPFLAGS_ENABLED },
+            { "enabledonly",RTLOGGRPFLAGS_ENABLED },
+            { "e",          RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1 | RTLOGGRPFLAGS_WARN },
+            { "enabled",    RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1 | RTLOGGRPFLAGS_WARN },
+            { "l1",         RTLOGGRPFLAGS_LEVEL_1 },
+            { "level1",     RTLOGGRPFLAGS_LEVEL_1 },
+            { "l",          RTLOGGRPFLAGS_LEVEL_2 },
+            { "l2",         RTLOGGRPFLAGS_LEVEL_2 },
+            { "level2",     RTLOGGRPFLAGS_LEVEL_2 },
+            { "l3",         RTLOGGRPFLAGS_LEVEL_3 },
+            { "level3",     RTLOGGRPFLAGS_LEVEL_3 },
+            { "l4",         RTLOGGRPFLAGS_LEVEL_4 },
+            { "level4",     RTLOGGRPFLAGS_LEVEL_4 },
+            { "l5",         RTLOGGRPFLAGS_LEVEL_5 },
+            { "level5",     RTLOGGRPFLAGS_LEVEL_5 },
+            { "l6",         RTLOGGRPFLAGS_LEVEL_6 },
+            { "level6",     RTLOGGRPFLAGS_LEVEL_6 },
+            { "l7",         RTLOGGRPFLAGS_LEVEL_7 },
+            { "level7",     RTLOGGRPFLAGS_LEVEL_7 },
+            { "l8",         RTLOGGRPFLAGS_LEVEL_8 },
+            { "level8",     RTLOGGRPFLAGS_LEVEL_8 },
+            { "l9",         RTLOGGRPFLAGS_LEVEL_9 },
+            { "level9",     RTLOGGRPFLAGS_LEVEL_9 },
+            { "l10",        RTLOGGRPFLAGS_LEVEL_10 },
+            { "level10",    RTLOGGRPFLAGS_LEVEL_10 },
+            { "l11",        RTLOGGRPFLAGS_LEVEL_11 },
+            { "level11",    RTLOGGRPFLAGS_LEVEL_11 },
+            { "l12",        RTLOGGRPFLAGS_LEVEL_12 },
+            { "level12",    RTLOGGRPFLAGS_LEVEL_12 },
+            { "f",          RTLOGGRPFLAGS_FLOW },
+            { "flow",       RTLOGGRPFLAGS_FLOW },
+            { "w",          RTLOGGRPFLAGS_WARN },
+            { "warn",       RTLOGGRPFLAGS_WARN },
+            { "warning",    RTLOGGRPFLAGS_WARN },
+            { "restrict",   RTLOGGRPFLAGS_RESTRICT },
+
+        };
+        unsigned    i;
+        bool        fFound = false;
+        psz++;
+        for (i = 0; i < RT_ELEMENTS(aFlags) && !fFound; i++)
+        {
+            const char *psz1 = aFlags[i].pszFlag;
+            const char *psz2 = psz;
+            while (*psz1 == RT_C_TO_LOWER(*psz2))
+            {
+                psz1++;
+                psz2++;
+                if (!*psz1)
+                {
+                    if (    (*psz2 >= 'a' && *psz2 <= 'z')
+                        ||  (*psz2 >= 'A' && *psz2 <= 'Z')
+                        ||  (*psz2 >= '0' && *psz2 <= '9') )
+                        break;
+                    fFlags |= aFlags[i].fFlag;
+                    fFound = true;
+                    psz = psz2;
+                    break;
+                }
+            } /* strincmp */
+        } /* for each flags */
+        AssertMsg(fFound, ("%.15s...", psz));
+    }
+
+    /*
+     * Flag value.
+     */
+    if (*psz == '=')
+    {
+        psz++;
+        if (*psz == '~')
+            fFlags = ~RTStrToInt32(psz + 1);
+        else
+            fFlags = RTStrToInt32(psz);
+    }
+
+    return fFlags;
+}
+
+/**
+ * Helper for RTLogGetGroupSettings.
+ */
+static int rtLogGetGroupSettingsAddOne(const char *pszName, uint32_t fGroup, char **ppszBuf, size_t *pcchBuf, bool *pfNotFirst)
+{
+# define APPEND_PSZ(psz,cch) do { memcpy(*ppszBuf, (psz), (cch)); *ppszBuf += (cch); *pcchBuf -= (cch); } while (0)
+# define APPEND_SZ(sz)       APPEND_PSZ(sz, sizeof(sz) - 1)
+# define APPEND_CH(ch)       do { **ppszBuf = (ch); *ppszBuf += 1; *pcchBuf -= 1; } while (0)
+
+    /*
+     * Add the name.
+     */
+    size_t cchName = strlen(pszName);
+    if (cchName + 1 + *pfNotFirst > *pcchBuf)
+        return VERR_BUFFER_OVERFLOW;
+    if (*pfNotFirst)
+        APPEND_CH(' ');
+    else
+        *pfNotFirst = true;
+    APPEND_PSZ(pszName, cchName);
+
+    /*
+     * Only generate mnemonics for the simple+common bits.
+     */
+    if (fGroup == (RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1))
+        /* nothing */;
+    else if (    fGroup == (RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1 | RTLOGGRPFLAGS_LEVEL_2 |  RTLOGGRPFLAGS_FLOW)
+             &&  *pcchBuf >= sizeof(".e.l.f"))
+        APPEND_SZ(".e.l.f");
+    else if (    fGroup == (RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1 | RTLOGGRPFLAGS_FLOW)
+             &&  *pcchBuf >= sizeof(".e.f"))
+        APPEND_SZ(".e.f");
+    else if (*pcchBuf >= 1 + 10 + 1)
+    {
+        size_t cch;
+        APPEND_CH('=');
+        cch = RTStrFormatNumber(*ppszBuf, fGroup, 16, 0, 0, RTSTR_F_SPECIAL | RTSTR_F_32BIT);
+        *ppszBuf += cch;
+        *pcchBuf -= cch;
+    }
+    else
+        return VERR_BUFFER_OVERFLOW;
+
+# undef APPEND_PSZ
+# undef APPEND_SZ
+# undef APPEND_CH
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Get the current log group settings as a string.
+ *
+ * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
+ * @param   pLogger             Logger instance (NULL for default logger).
+ * @param   pszBuf              The output buffer.
+ * @param   cchBuf              The size of the output buffer. Must be greater
+ *                              than zero.
+ */
+RTDECL(int) RTLogGetGroupSettings(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf)
+{
+    bool        fNotFirst = false;
+    int         rc        = VINF_SUCCESS;
+    uint32_t    cGroups;
+    uint32_t    fGroup;
+    uint32_t    i;
+
+    Assert(cchBuf);
+
+    /*
+     * Resolve defaults.
+     */
+    if (!pLogger)
+    {
+        pLogger = RTLogDefaultInstance();
+        if (!pLogger)
+        {
+            *pszBuf = '\0';
+            return VINF_SUCCESS;
+        }
+    }
+
+    cGroups = pLogger->cGroups;
+
+    /*
+     * Check if all are the same.
+     */
+    fGroup = pLogger->afGroups[0];
+    for (i = 1; i < cGroups; i++)
+        if (pLogger->afGroups[i] != fGroup)
+            break;
+    if (i >= cGroups)
+        rc = rtLogGetGroupSettingsAddOne("all", fGroup, &pszBuf, &cchBuf, &fNotFirst);
+    else
+    {
+
+        /*
+         * Iterate all the groups and print all that are enabled.
+         */
+        for (i = 0; i < cGroups; i++)
+        {
+            fGroup = pLogger->afGroups[i];
+            if (fGroup)
+            {
+                const char *pszName = pLogger->pInt->papszGroups[i];
+                if (pszName)
+                {
+                    rc = rtLogGetGroupSettingsAddOne(pszName, fGroup, &pszBuf, &cchBuf, &fNotFirst);
+                    if (rc)
+                        break;
+                }
+            }
+        }
+    }
+
+    *pszBuf = '\0';
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTLogGetGroupSettings);
+
+#endif /* !IN_RC */
+
+/**
+ * Updates the flags for the logger instance using the specified
+ * specification string.
+ *
+ * @returns iprt status code.
+ *          Failures can safely be ignored.
+ * @param   pLogger     Logger instance (NULL for default logger).
+ * @param   pszValue    Value to parse.
+ */
+RTDECL(int) RTLogFlags(PRTLOGGER pLogger, const char *pszValue)
+{
+    int rc = VINF_SUCCESS;
+
+    /*
+     * Resolve defaults.
+     */
+    if (!pLogger)
+    {
+        pLogger = RTLogDefaultInstance();
+        if (!pLogger)
+            return VINF_SUCCESS;
+    }
+
+    /*
+     * Iterate the string.
+     */
+    while (*pszValue)
+    {
+        /* check no prefix. */
+        bool fNo = false;
+        char ch;
+        unsigned i;
+
+        /* skip blanks. */
+        while (RT_C_IS_SPACE(*pszValue))
+            pszValue++;
+        if (!*pszValue)
+            return rc;
+
+        while ((ch = *pszValue) != '\0')
+        {
+            if (ch == 'n' && pszValue[1] == 'o')
+            {
+                pszValue += 2;
+                fNo = !fNo;
+            }
+            else if (ch == '+')
+            {
+                pszValue++;
+                fNo = true;
+            }
+            else if (ch == '-' || ch == '!' || ch == '~')
+            {
+                pszValue++;
+                fNo = !fNo;
+            }
+            else
+                break;
+        }
+
+        /* instruction. */
+        for (i = 0; i < RT_ELEMENTS(g_aLogFlags); i++)
+        {
+            if (!strncmp(pszValue, g_aLogFlags[i].pszInstr, g_aLogFlags[i].cchInstr))
+            {
+                if (fNo == g_aLogFlags[i].fInverted)
+                    pLogger->fFlags |= g_aLogFlags[i].fFlag;
+                else
+                    pLogger->fFlags &= ~g_aLogFlags[i].fFlag;
+                pszValue += g_aLogFlags[i].cchInstr;
+                break;
+            }
+        }
+
+        /* unknown instruction? */
+        if (i >= RT_ELEMENTS(g_aLogFlags))
+        {
+            AssertMsgFailed(("Invalid flags! unknown instruction %.20s\n", pszValue));
+            pszValue++;
+        }
+
+        /* skip blanks and delimiters. */
+        while (RT_C_IS_SPACE(*pszValue) || *pszValue == ';')
+            pszValue++;
+    } /* while more environment variable value left */
+
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTLogFlags);
+
+
+/**
+ * Changes the buffering setting of the specified logger.
+ *
+ * This can be used for optimizing longish logging sequences.
+ *
+ * @returns The old state.
+ * @param   pLogger         The logger instance (NULL is an alias for the
+ *                          default logger).
+ * @param   fBuffered       The new state.
+ */
+RTDECL(bool) RTLogSetBuffering(PRTLOGGER pLogger, bool fBuffered)
+{
+    bool fOld;
+
+    /*
+     * Resolve the logger instance.
+     */
+    if (!pLogger)
+    {
+        pLogger = RTLogDefaultInstance();
+        if (!pLogger)
+            return false;
+    }
+
+    rtlogLock(pLogger);
+    fOld  = !!(pLogger->fFlags & RTLOGFLAGS_BUFFERED);
+    if (fBuffered)
+        pLogger->fFlags |= RTLOGFLAGS_BUFFERED;
+    else
+        pLogger->fFlags &= ~RTLOGFLAGS_BUFFERED;
+    rtlogUnlock(pLogger);
+
+    return fOld;
+}
+RT_EXPORT_SYMBOL(RTLogSetBuffering);
+
+
+#ifdef IN_RING3
+RTDECL(uint32_t) RTLogSetGroupLimit(PRTLOGGER pLogger, uint32_t cMaxEntriesPerGroup)
+{
+    /*
+     * Resolve the logger instance.
+     */
+    if (!pLogger)
+    {
+        pLogger = RTLogDefaultInstance();
+        if (!pLogger)
+            return UINT32_MAX;
+    }
+
+    rtlogLock(pLogger);
+    uint32_t cOld = pLogger->pInt->cMaxEntriesPerGroup;
+    pLogger->pInt->cMaxEntriesPerGroup = cMaxEntriesPerGroup;
+    rtlogUnlock(pLogger);
+
+    return cOld;
+}
+#endif
+
+#ifndef IN_RC
+
+/**
+ * Get the current log flags as a string.
+ *
+ * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
+ * @param   pLogger             Logger instance (NULL for default logger).
+ * @param   pszBuf              The output buffer.
+ * @param   cchBuf              The size of the output buffer. Must be greater
+ *                              than zero.
+ */
+RTDECL(int) RTLogGetFlags(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf)
+{
+    bool        fNotFirst = false;
+    int         rc        = VINF_SUCCESS;
+    uint32_t    fFlags;
+    unsigned    i;
+
+    Assert(cchBuf);
+
+    /*
+     * Resolve defaults.
+     */
+    if (!pLogger)
+    {
+        pLogger = RTLogDefaultInstance();
+        if (!pLogger)
+        {
+            *pszBuf = '\0';
+            return VINF_SUCCESS;
+        }
+    }
+
+    /*
+     * Add the flags in the list.
+     */
+    fFlags = pLogger->fFlags;
+    for (i = 0; i < RT_ELEMENTS(g_aLogFlags); i++)
+        if (    !g_aLogFlags[i].fInverted
+            ?   (g_aLogFlags[i].fFlag & fFlags)
+            :   !(g_aLogFlags[i].fFlag & fFlags))
+        {
+            size_t cchInstr = g_aLogFlags[i].cchInstr;
+            if (cchInstr + fNotFirst + 1 > cchBuf)
+            {
+                rc = VERR_BUFFER_OVERFLOW;
+                break;
+            }
+            if (fNotFirst)
+            {
+                *pszBuf++ = ' ';
+                cchBuf--;
+            }
+            memcpy(pszBuf, g_aLogFlags[i].pszInstr, cchInstr);
+            pszBuf += cchInstr;
+            cchBuf -= cchInstr;
+            fNotFirst = true;
+        }
+    *pszBuf = '\0';
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTLogGetFlags);
+
+
+/**
+ * Finds the end of a destination value.
+ *
+ * The value ends when we counter a ';' or a free standing word (space on both
+ * from the g_aLogDst table.  (If this is problematic for someone, we could
+ * always do quoting and escaping.)
+ *
+ * @returns Value length in chars.
+ * @param   pszValue            The first char after '=' or ':'.
+ */
+static size_t rtLogDestFindValueLength(const char *pszValue)
+{
+    size_t off = 0;
+    char   ch;
+    while ((ch = pszValue[off]) != '\0' && ch != ';')
+    {
+        if (!RT_C_IS_SPACE(ch))
+            off++;
+        else
+        {
+            unsigned i;
+            size_t   cchThusFar = off;
+            do
+                off++;
+            while ((ch = pszValue[off]) != '\0' && RT_C_IS_SPACE(ch));
+            if (ch == ';')
+                return cchThusFar;
+
+            if (ch == 'n' && pszValue[off + 1] == 'o')
+                off += 2;
+            for (i = 0; i < RT_ELEMENTS(g_aLogDst); i++)
+                if (!strncmp(&pszValue[off], g_aLogDst[i].pszInstr, g_aLogDst[i].cchInstr))
+                {
+                    ch = pszValue[off + g_aLogDst[i].cchInstr];
+                    if (ch == '\0' || RT_C_IS_SPACE(ch) || ch == '=' || ch == ':' || ch == ';')
+                        return cchThusFar;
+                }
+        }
+    }
+    return off;
+}
+
+
+/**
+ * Updates the logger destination using the specified string.
+ *
+ * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
+ * @param   pLogger             Logger instance (NULL for default logger).
+ * @param   pszValue            The value to parse.
+ */
+RTDECL(int) RTLogDestinations(PRTLOGGER pLogger, char const *pszValue)
+{
+    /*
+     * Resolve defaults.
+     */
+    if (!pLogger)
+    {
+        pLogger = RTLogDefaultInstance();
+        if (!pLogger)
+            return VINF_SUCCESS;
+    }
+
+    /*
+     * Do the parsing.
+     */
+    while (*pszValue)
+    {
+        bool fNo;
+        unsigned i;
+
+        /* skip blanks. */
+        while (RT_C_IS_SPACE(*pszValue))
+            pszValue++;
+        if (!*pszValue)
+            break;
+
+        /* check no prefix. */
+        fNo = false;
+        if (pszValue[0] == 'n' && pszValue[1] == 'o')
+        {
+            fNo = true;
+            pszValue += 2;
+        }
+
+        /* instruction. */
+        for (i = 0; i < RT_ELEMENTS(g_aLogDst); i++)
+        {
+            size_t cchInstr = strlen(g_aLogDst[i].pszInstr);
+            if (!strncmp(pszValue, g_aLogDst[i].pszInstr, cchInstr))
+            {
+                if (!fNo)
+                    pLogger->fDestFlags |= g_aLogDst[i].fFlag;
+                else
+                    pLogger->fDestFlags &= ~g_aLogDst[i].fFlag;
+                pszValue += cchInstr;
+
+                /* check for value. */
+                while (RT_C_IS_SPACE(*pszValue))
+                    pszValue++;
+                if (*pszValue == '=' || *pszValue == ':')
+                {
+                    pszValue++;
+                    size_t cch = rtLogDestFindValueLength(pszValue);
+                    const char *pszEnd = pszValue + cch;
+
+# ifdef IN_RING3
+                    char szTmp[sizeof(pLogger->pInt->szFilename)];
+# else
+                    char szTmp[32];
+# endif
+                    if (0)
+                    { /* nothing */ }
+#ifdef IN_RING3
+
+                    /* log file name */
+                    else if (i == 0 /* file */ && !fNo)
+                    {
+                        AssertReturn(cch < sizeof(pLogger->pInt->szFilename), VERR_OUT_OF_RANGE);
+                        memcpy(pLogger->pInt->szFilename, pszValue, cch);
+                        pLogger->pInt->szFilename[cch] = '\0';
+                        /** @todo reopen log file if pLogger->pInt->fCreated is true ... */
+                    }
+                    /* log directory */
+                    else if (i == 1 /* dir */ && !fNo)
+                    {
+                        const char *pszFile = RTPathFilename(pLogger->pInt->szFilename);
+                        size_t      cchFile = pszFile ? strlen(pszFile) : 0;
+                        AssertReturn(cchFile + cch + 1 < sizeof(pLogger->pInt->szFilename), VERR_OUT_OF_RANGE);
+                        memcpy(szTmp, cchFile ? pszFile : "", cchFile + 1);
+
+                        memcpy(pLogger->pInt->szFilename, pszValue, cch);
+                        pLogger->pInt->szFilename[cch] = '\0';
+                        RTPathStripTrailingSlash(pLogger->pInt->szFilename);
+
+                        cch = strlen(pLogger->pInt->szFilename);
+                        pLogger->pInt->szFilename[cch++] = '/';
+                        memcpy(&pLogger->pInt->szFilename[cch], szTmp, cchFile);
+                        pLogger->pInt->szFilename[cch + cchFile] = '\0';
+                        /** @todo reopen log file if pLogger->pInt->fCreated is true ... */
+                    }
+                    else if (i == 2 /* history */)
+                    {
+                        if (!fNo)
+                        {
+                            uint32_t cHistory = 0;
+                            int rc = RTStrCopyEx(szTmp, sizeof(szTmp), pszValue, cch);
+                            if (RT_SUCCESS(rc))
+                                rc = RTStrToUInt32Full(szTmp, 0, &cHistory);
+                            AssertMsgReturn(RT_SUCCESS(rc) && cHistory < _1M, ("Invalid history value %s (%Rrc)!\n", szTmp, rc), rc);
+                            pLogger->pInt->cHistory = cHistory;
+                        }
+                        else
+                            pLogger->pInt->cHistory = 0;
+                    }
+                    else if (i == 3 /* histsize */)
+                    {
+                        if (!fNo)
+                        {
+                            int rc = RTStrCopyEx(szTmp, sizeof(szTmp), pszValue, cch);
+                            if (RT_SUCCESS(rc))
+                                rc = RTStrToUInt64Full(szTmp, 0, &pLogger->pInt->cbHistoryFileMax);
+                            AssertMsgRCReturn(rc, ("Invalid history file size value %s (%Rrc)!\n", szTmp, rc), rc);
+                            if (pLogger->pInt->cbHistoryFileMax == 0)
+                                pLogger->pInt->cbHistoryFileMax = UINT64_MAX;
+                        }
+                        else
+                            pLogger->pInt->cbHistoryFileMax = UINT64_MAX;
+                    }
+                    else if (i == 4 /* histtime */)
+                    {
+                        if (!fNo)
+                        {
+                            int rc = RTStrCopyEx(szTmp, sizeof(szTmp), pszValue, cch);
+                            if (RT_SUCCESS(rc))
+                                rc = RTStrToUInt32Full(szTmp, 0, &pLogger->pInt->cSecsHistoryTimeSlot);
+                            AssertMsgRCReturn(rc, ("Invalid history time slot value %s (%Rrc)!\n", szTmp, rc), rc);
+                            if (pLogger->pInt->cSecsHistoryTimeSlot == 0)
+                                pLogger->pInt->cSecsHistoryTimeSlot = UINT32_MAX;
+                        }
+                        else
+                            pLogger->pInt->cSecsHistoryTimeSlot = UINT32_MAX;
+                    }
+# endif /* IN_RING3 */
+                    else if (i == 5 /* ringbuf */ && !fNo)
+                    {
+                        int rc = RTStrCopyEx(szTmp, sizeof(szTmp), pszValue, cch);
+                        uint32_t cbRingBuf = 0;
+                        if (RT_SUCCESS(rc))
+                            rc = RTStrToUInt32Full(szTmp, 0, &cbRingBuf);
+                        AssertMsgRCReturn(rc, ("Invalid ring buffer size value '%s' (%Rrc)!\n", szTmp, rc), rc);
+
+                        if (cbRingBuf == 0)
+                            cbRingBuf = RTLOG_RINGBUF_DEFAULT_SIZE;
+                        else if (cbRingBuf < RTLOG_RINGBUF_MIN_SIZE)
+                            cbRingBuf = RTLOG_RINGBUF_MIN_SIZE;
+                        else if (cbRingBuf > RTLOG_RINGBUF_MAX_SIZE)
+                            cbRingBuf = RTLOG_RINGBUF_MAX_SIZE;
+                        else
+                            cbRingBuf = RT_ALIGN_32(cbRingBuf, 64);
+                        rc = rtLogRingBufAdjust(pLogger, cbRingBuf, false /*fForce*/);
+                        if (RT_FAILURE(rc))
+                            return rc;
+                    }
+                    else
+                        AssertMsgFailedReturn(("Invalid destination value! %s%s doesn't take a value!\n",
+                                               fNo ? "no" : "", g_aLogDst[i].pszInstr),
+                                              VERR_INVALID_PARAMETER);
+
+                    pszValue = pszEnd + (*pszEnd != '\0');
+                }
+                else if (i == 5 /* ringbuf */ && !fNo && !pLogger->pInt->pszRingBuf)
+                {
+                    int rc = rtLogRingBufAdjust(pLogger, pLogger->pInt->cbRingBuf, false /*fForce*/);
+                    if (RT_FAILURE(rc))
+                        return rc;
+                }
+                break;
+            }
+        }
+
+        /* assert known instruction */
+        AssertMsgReturn(i < RT_ELEMENTS(g_aLogDst),
+                        ("Invalid destination value! unknown instruction %.20s\n", pszValue),
+                        VERR_INVALID_PARAMETER);
+
+        /* skip blanks and delimiters. */
+        while (RT_C_IS_SPACE(*pszValue) || *pszValue == ';')
+            pszValue++;
+    } /* while more environment variable value left */
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTLogDestinations);
+
+
+/**
+ * Get the current log destinations as a string.
+ *
+ * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
+ * @param   pLogger             Logger instance (NULL for default logger).
+ * @param   pszBuf              The output buffer.
+ * @param   cchBuf              The size of the output buffer. Must be greater
+ *                              than 0.
+ */
+RTDECL(int) RTLogGetDestinations(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf)
+{
+    bool        fNotFirst = false;
+    int         rc        = VINF_SUCCESS;
+    uint32_t    fDestFlags;
+    unsigned    i;
+
+    AssertReturn(cchBuf, VERR_INVALID_PARAMETER);
+    *pszBuf = '\0';
+
+    /*
+     * Resolve defaults.
+     */
+    if (!pLogger)
+    {
+        pLogger = RTLogDefaultInstance();
+        if (!pLogger)
+            return VINF_SUCCESS;
+    }
+
+    /*
+     * Add the flags in the list.
+     */
+    fDestFlags = pLogger->fDestFlags;
+    for (i = 6; i < RT_ELEMENTS(g_aLogDst); i++)
+        if (g_aLogDst[i].fFlag & fDestFlags)
+        {
+            if (fNotFirst)
+            {
+                rc = RTStrCopyP(&pszBuf, &cchBuf, " ");
+                if (RT_FAILURE(rc))
+                    return rc;
+            }
+            rc = RTStrCopyP(&pszBuf, &cchBuf, g_aLogDst[i].pszInstr);
+            if (RT_FAILURE(rc))
+                return rc;
+            fNotFirst = true;
+        }
+
+    char szNum[32];
+
+# ifdef IN_RING3
+    /*
+     * Add the filename.
+     */
+    if (fDestFlags & RTLOGDEST_FILE)
+    {
+        rc = RTStrCopyP(&pszBuf, &cchBuf, fNotFirst ? " file=" : "file=");
+        if (RT_FAILURE(rc))
+            return rc;
+        rc = RTStrCopyP(&pszBuf, &cchBuf, pLogger->pInt->szFilename);
+        if (RT_FAILURE(rc))
+            return rc;
+        fNotFirst = true;
+
+        if (pLogger->pInt->cHistory)
+        {
+            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? " history=%u" : "history=%u", pLogger->pInt->cHistory);
+            rc = RTStrCopyP(&pszBuf, &cchBuf, szNum);
+            if (RT_FAILURE(rc))
+                return rc;
+            fNotFirst = true;
+        }
+        if (pLogger->pInt->cbHistoryFileMax != UINT64_MAX)
+        {
+            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? " histsize=%llu" : "histsize=%llu", pLogger->pInt->cbHistoryFileMax);
+            rc = RTStrCopyP(&pszBuf, &cchBuf, szNum);
+            if (RT_FAILURE(rc))
+                return rc;
+            fNotFirst = true;
+        }
+        if (pLogger->pInt->cSecsHistoryTimeSlot != UINT32_MAX)
+        {
+            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? " histtime=%llu" : "histtime=%llu", pLogger->pInt->cSecsHistoryTimeSlot);
+            rc = RTStrCopyP(&pszBuf, &cchBuf, szNum);
+            if (RT_FAILURE(rc))
+                return rc;
+            fNotFirst = true;
+        }
+    }
+# endif /* IN_RING3 */
+
+    /*
+     * Add the ring buffer.
+     */
+    if (fDestFlags & RTLOGDEST_RINGBUF)
+    {
+        if (pLogger->pInt->cbRingBuf == RTLOG_RINGBUF_DEFAULT_SIZE)
+            rc = RTStrCopyP(&pszBuf, &cchBuf, fNotFirst ? " ringbuf" : "ringbuf");
+        else
+        {
+            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? " ringbuf=%#x" : "ringbuf=%#x", pLogger->pInt->cbRingBuf);
+            rc = RTStrCopyP(&pszBuf, &cchBuf, szNum);
+        }
+        if (RT_FAILURE(rc))
+            return rc;
+        fNotFirst = true;
+    }
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTLogGetDestinations);
+
+#endif /* !IN_RC */
+
+/**
+ * Flushes the specified logger.
+ *
+ * @param   pLogger     The logger instance to flush.
+ *                      If NULL the default instance is used. The default instance
+ *                      will not be initialized by this call.
+ */
+RTDECL(void) RTLogFlush(PRTLOGGER pLogger)
+{
+    /*
+     * Resolve defaults.
+     */
+    if (!pLogger)
+    {
+#ifdef IN_RC
+        pLogger = &g_Logger;
+#else
+        pLogger = g_pLogger;
+#endif
+        if (!pLogger)
+            return;
+    }
+
+    /*
+     * Any thing to flush?
+     */
+    if (   pLogger->offScratch
+#ifndef IN_RC
+        || (pLogger->fDestFlags & RTLOGDEST_RINGBUF)
+#endif
+       )
+    {
+#ifndef IN_RC
+        /*
+         * Acquire logger instance sem.
+         */
+        int rc = rtlogLock(pLogger);
+        if (RT_FAILURE(rc))
+            return;
+#endif
+        /*
+         * Call worker.
+         */
+        rtlogFlush(pLogger);
+
+#ifndef IN_RC
+        /*
+         * Since this is an explicit flush call, the ring buffer content should
+         * be flushed to the other destinations if active.
+         */
+        if (   (pLogger->fDestFlags & RTLOGDEST_RINGBUF)
+            && pLogger->pInt->pszRingBuf /* paranoia */)
+            rtLogRingBufFlush(pLogger);
+
+        /*
+         * Release the semaphore.
+         */
+        rtlogUnlock(pLogger);
+#endif
+    }
+}
+RT_EXPORT_SYMBOL(RTLogFlush);
+
+
+/**
+ * Common worker for RTLogDefaultInstance and RTLogDefaultInstanceEx.
+ */
+DECL_FORCE_INLINE(PRTLOGGER) rtLogDefaultInstanceCommon(void)
+{
+#ifdef IN_RC
+    return &g_Logger;
+
+#else /* !IN_RC */
+# ifdef IN_RING0
+    /*
+     * Check per thread loggers first.
+     */
+    if (g_cPerThreadLoggers)
+    {
+        const RTNATIVETHREAD Self = RTThreadNativeSelf();
+        int32_t i = RT_ELEMENTS(g_aPerThreadLoggers);
+        while (i-- > 0)
+            if (g_aPerThreadLoggers[i].NativeThread == Self)
+                return g_aPerThreadLoggers[i].pLogger;
+    }
+# endif /* IN_RING0 */
+
+    /*
+     * If no per thread logger, use the default one.
+     */
+    if (!g_pLogger)
+        g_pLogger = RTLogDefaultInit();
+    return g_pLogger;
+#endif /* !IN_RC */
+}
+
+
+RTDECL(PRTLOGGER)   RTLogDefaultInstance(void)
+{
+    return rtLogDefaultInstanceCommon();
+}
+RT_EXPORT_SYMBOL(RTLogDefaultInstance);
+
+
+RTDECL(PRTLOGGER)   RTLogDefaultInstanceEx(uint32_t fFlagsAndGroup)
+{
+    PRTLOGGER pLogger = rtLogDefaultInstanceCommon();
+    if (pLogger)
+    {
+        if (pLogger->fFlags & RTLOGFLAGS_DISABLED)
+            pLogger = NULL;
+        else
+        {
+            uint16_t const fFlags = RT_LO_U16(fFlagsAndGroup);
+            uint16_t const iGroup = RT_HI_U16(fFlagsAndGroup);
+            if (   iGroup != UINT16_MAX
+                 && (   (pLogger->afGroups[iGroup < pLogger->cGroups ? iGroup : 0] & (fFlags | (uint32_t)RTLOGGRPFLAGS_ENABLED))
+                     != (fFlags | (uint32_t)RTLOGGRPFLAGS_ENABLED)))
+            pLogger = NULL;
+        }
+    }
+    return pLogger;
+}
+RT_EXPORT_SYMBOL(RTLogDefaultInstanceEx);
+
+
+/**
+ * Common worker for RTLogGetDefaultInstance and RTLogGetDefaultInstanceEx.
+ */
+DECL_FORCE_INLINE(PRTLOGGER) rtLogGetDefaultInstanceCommon(void)
+{
+#ifdef IN_RC
+    return &g_Logger;
+#else
+# ifdef IN_RING0
+    /*
+     * Check per thread loggers first.
+     */
+    if (g_cPerThreadLoggers)
+    {
+        const RTNATIVETHREAD Self = RTThreadNativeSelf();
+        int32_t i = RT_ELEMENTS(g_aPerThreadLoggers);
+        while (i-- > 0)
+            if (g_aPerThreadLoggers[i].NativeThread == Self)
+                return g_aPerThreadLoggers[i].pLogger;
+    }
+# endif /* IN_RING0 */
+
+    return g_pLogger;
+#endif
+}
+
+
+RTDECL(PRTLOGGER) RTLogGetDefaultInstance(void)
+{
+    return rtLogGetDefaultInstanceCommon();
+}
+RT_EXPORT_SYMBOL(RTLogGetDefaultInstance);
+
+
+RTDECL(PRTLOGGER) RTLogGetDefaultInstanceEx(uint32_t fFlagsAndGroup)
+{
+    PRTLOGGER pLogger = rtLogGetDefaultInstanceCommon();
+    if (pLogger)
+    {
+        if (pLogger->fFlags & RTLOGFLAGS_DISABLED)
+            pLogger = NULL;
+        else
+        {
+            uint32_t const fFlags = RT_LO_U16(fFlagsAndGroup);
+            uint16_t const iGroup = RT_HI_U16(fFlagsAndGroup);
+            if (   iGroup != UINT16_MAX
+                 && (   (pLogger->afGroups[iGroup < pLogger->cGroups ? iGroup : 0] & (fFlags | RTLOGGRPFLAGS_ENABLED))
+                     != (fFlags | RTLOGGRPFLAGS_ENABLED)))
+            pLogger = NULL;
+        }
+    }
+    return pLogger;
+}
+RT_EXPORT_SYMBOL(RTLogGetDefaultInstanceEx);
+
+
+#ifndef IN_RC
+/**
+ * Sets the default logger instance.
+ *
+ * @returns iprt status code.
+ * @param   pLogger     The new default logger instance.
+ */
+RTDECL(PRTLOGGER) RTLogSetDefaultInstance(PRTLOGGER pLogger)
+{
+    return ASMAtomicXchgPtrT(&g_pLogger, pLogger, PRTLOGGER);
+}
+RT_EXPORT_SYMBOL(RTLogSetDefaultInstance);
+#endif /* !IN_RC */
+
+
+#ifdef IN_RING0
+/**
+ * Changes the default logger instance for the current thread.
+ *
+ * @returns IPRT status code.
+ * @param   pLogger     The logger instance. Pass NULL for deregistration.
+ * @param   uKey        Associated key for cleanup purposes. If pLogger is NULL,
+ *                      all instances with this key will be deregistered. So in
+ *                      order to only deregister the instance associated with the
+ *                      current thread use 0.
+ */
+RTDECL(int) RTLogSetDefaultInstanceThread(PRTLOGGER pLogger, uintptr_t uKey)
+{
+    int             rc;
+    RTNATIVETHREAD  Self = RTThreadNativeSelf();
+    if (pLogger)
+    {
+        int32_t i;
+        unsigned j;
+
+        AssertReturn(pLogger->u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
+
+        /*
+         * Iterate the table to see if there is already an entry for this thread.
+         */
+        i = RT_ELEMENTS(g_aPerThreadLoggers);
+        while (i-- > 0)
+            if (g_aPerThreadLoggers[i].NativeThread == Self)
+            {
+                ASMAtomicWritePtr((void * volatile *)&g_aPerThreadLoggers[i].uKey, (void *)uKey);
+                g_aPerThreadLoggers[i].pLogger = pLogger;
+                return VINF_SUCCESS;
+            }
+
+        /*
+         * Allocate a new table entry.
+         */
+        i = ASMAtomicIncS32(&g_cPerThreadLoggers);
+        if (i > (int32_t)RT_ELEMENTS(g_aPerThreadLoggers))
+        {
+            ASMAtomicDecS32(&g_cPerThreadLoggers);
+            return VERR_BUFFER_OVERFLOW; /* horrible error code! */
+        }
+
+        for (j = 0; j < 10; j++)
+        {
+            i = RT_ELEMENTS(g_aPerThreadLoggers);
+            while (i-- > 0)
+            {
+                AssertCompile(sizeof(RTNATIVETHREAD) == sizeof(void*));
+                if (    g_aPerThreadLoggers[i].NativeThread == NIL_RTNATIVETHREAD
+                    &&  ASMAtomicCmpXchgPtr((void * volatile *)&g_aPerThreadLoggers[i].NativeThread, (void *)Self, (void *)NIL_RTNATIVETHREAD))
+                {
+                    ASMAtomicWritePtr((void * volatile *)&g_aPerThreadLoggers[i].uKey, (void *)uKey);
+                    ASMAtomicWritePtr(&g_aPerThreadLoggers[i].pLogger, pLogger);
+                    return VINF_SUCCESS;
+                }
+            }
+        }
+
+        ASMAtomicDecS32(&g_cPerThreadLoggers);
+        rc = VERR_INTERNAL_ERROR;
+    }
+    else
+    {
+        /*
+         * Search the array for the current thread.
+         */
+        int32_t i = RT_ELEMENTS(g_aPerThreadLoggers);
+        while (i-- > 0)
+            if (    g_aPerThreadLoggers[i].NativeThread == Self
+                ||  g_aPerThreadLoggers[i].uKey == uKey)
+            {
+                ASMAtomicWriteNullPtr((void * volatile *)&g_aPerThreadLoggers[i].uKey);
+                ASMAtomicWriteNullPtr(&g_aPerThreadLoggers[i].pLogger);
+                ASMAtomicWriteHandle(&g_aPerThreadLoggers[i].NativeThread, NIL_RTNATIVETHREAD);
+                ASMAtomicDecS32(&g_cPerThreadLoggers);
+            }
+
+        rc = VINF_SUCCESS;
+    }
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTLogSetDefaultInstanceThread);
+#endif /* IN_RING0 */
+
+
+/**
+ * Write to a logger instance.
+ *
+ * @param   pLogger     Pointer to logger instance.
+ * @param   pszFormat   Format string.
+ * @param   args        Format arguments.
+ */
+RTDECL(void) RTLogLoggerV(PRTLOGGER pLogger, const char *pszFormat, va_list args)
+{
+    RTLogLoggerExV(pLogger, 0, ~0U, pszFormat, args);
+}
+RT_EXPORT_SYMBOL(RTLogLoggerV);
+
+
+/**
+ * Write to a logger instance.
+ *
+ * This function will check whether the instance, group and flags makes up a
+ * logging kind which is currently enabled before writing anything to the log.
+ *
+ * @param   pLogger     Pointer to logger instance. If NULL the default logger instance will be attempted.
+ * @param   fFlags      The logging flags.
+ * @param   iGroup      The group.
+ *                      The value ~0U is reserved for compatibility with RTLogLogger[V] and is
+ *                      only for internal usage!
+ * @param   pszFormat   Format string.
+ * @param   args        Format arguments.
+ */
+RTDECL(void) RTLogLoggerExV(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, va_list args)
+{
+    int rc;
+
+    /*
+     * A NULL logger means default instance.
+     */
+    if (!pLogger)
+    {
+        pLogger = RTLogDefaultInstance();
+        if (!pLogger)
+            return;
+    }
+
+    /*
+     * Validate and correct iGroup.
+     */
+    if (iGroup != ~0U && iGroup >= pLogger->cGroups)
+        iGroup = 0;
+
+    /*
+     * If no output, then just skip it.
+     */
+    if (    (pLogger->fFlags & RTLOGFLAGS_DISABLED)
+#ifndef IN_RC
+        || !pLogger->fDestFlags
+#endif
+        || !pszFormat || !*pszFormat)
+        return;
+    if (    iGroup != ~0U
+        &&  (pLogger->afGroups[iGroup] & (fFlags | RTLOGGRPFLAGS_ENABLED)) != (fFlags | RTLOGGRPFLAGS_ENABLED))
+        return;
+
+    /*
+     * Acquire logger instance sem.
+     */
+    rc = rtlogLock(pLogger);
+    if (RT_FAILURE(rc))
+    {
+#ifdef IN_RING0
+        if (pLogger->fDestFlags & ~RTLOGDEST_FILE)
+            rtR0LogLoggerExFallback(pLogger->fDestFlags, pLogger->fFlags, pLogger->pInt, pszFormat, args);
+#endif
+        return;
+    }
+
+    /*
+     * Check restrictions and call worker.
+     */
+#ifndef IN_RC
+    if (RT_UNLIKELY(   (pLogger->fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
+                    && iGroup < pLogger->cGroups
+                    && (pLogger->afGroups[iGroup] & RTLOGGRPFLAGS_RESTRICT)
+                    && ++pLogger->pInt->pacEntriesPerGroup[iGroup] >= pLogger->pInt->cMaxEntriesPerGroup ))
+    {
+        uint32_t cEntries = pLogger->pInt->pacEntriesPerGroup[iGroup];
+        if (cEntries > pLogger->pInt->cMaxEntriesPerGroup)
+            pLogger->pInt->pacEntriesPerGroup[iGroup] = cEntries - 1;
+        else
+        {
+            rtlogLoggerExVLocked(pLogger, fFlags, iGroup, pszFormat, args);
+            if (   pLogger->pInt->papszGroups
+                && pLogger->pInt->papszGroups[iGroup])
+                rtlogLoggerExFLocked(pLogger, fFlags, iGroup, "%u messages from group %s (#%u), muting it.\n",
+                                     cEntries, pLogger->pInt->papszGroups[iGroup], iGroup);
+            else
+                rtlogLoggerExFLocked(pLogger, fFlags, iGroup, "%u messages from group #%u, muting it.\n",
+                                     cEntries, iGroup);
+        }
+    }
+    else
+#endif
+        rtlogLoggerExVLocked(pLogger, fFlags, iGroup, pszFormat, args);
+
+    /*
+     * Release the semaphore.
+     */
+    rtlogUnlock(pLogger);
+}
+RT_EXPORT_SYMBOL(RTLogLoggerExV);
+
+
+#ifdef IN_RING0
+/**
+ * For rtR0LogLoggerExFallbackOutput and rtR0LogLoggerExFallbackFlush.
+ */
+typedef struct RTR0LOGLOGGERFALLBACK
+{
+    /** The current scratch buffer offset. */
+    uint32_t            offScratch;
+    /** The destination flags. */
+    uint32_t            fDestFlags;
+    /** For ring buffer output. */
+    PRTLOGGERINTERNAL   pInt;
+    /** The scratch buffer. */
+    char                achScratch[80];
+} RTR0LOGLOGGERFALLBACK;
+/** Pointer to RTR0LOGLOGGERFALLBACK which is used by
+ * rtR0LogLoggerExFallbackOutput. */
+typedef RTR0LOGLOGGERFALLBACK *PRTR0LOGLOGGERFALLBACK;
+
+
+/**
+ * Flushes the fallback buffer.
+ *
+ * @param   pThis       The scratch buffer.
+ */
+static void rtR0LogLoggerExFallbackFlush(PRTR0LOGLOGGERFALLBACK pThis)
+{
+    if (!pThis->offScratch)
+        return;
+
+    if (   (pThis->fDestFlags & RTLOGDEST_RINGBUF)
+        && pThis->pInt
+        && pThis->pInt->pszRingBuf /* paranoia */)
+        rtLogRingBufWrite(pThis->pInt, pThis->achScratch, pThis->offScratch);
+    else
+    {
+        if (pThis->fDestFlags & RTLOGDEST_USER)
+            RTLogWriteUser(pThis->achScratch, pThis->offScratch);
+
+        if (pThis->fDestFlags & RTLOGDEST_DEBUGGER)
+            RTLogWriteDebugger(pThis->achScratch, pThis->offScratch);
+
+        if (pThis->fDestFlags & RTLOGDEST_STDOUT)
+            RTLogWriteStdOut(pThis->achScratch, pThis->offScratch);
+
+        if (pThis->fDestFlags & RTLOGDEST_STDERR)
+            RTLogWriteStdErr(pThis->achScratch, pThis->offScratch);
+
+# ifndef LOG_NO_COM
+        if (pThis->fDestFlags & RTLOGDEST_COM)
+            RTLogWriteCom(pThis->achScratch, pThis->offScratch);
+# endif
+    }
+
+    /* empty the buffer. */
+    pThis->offScratch = 0;
+}
+
+
+/**
+ * Callback for RTLogFormatV used by rtR0LogLoggerExFallback.
+ * See PFNLOGOUTPUT() for details.
+ */
+static DECLCALLBACK(size_t) rtR0LogLoggerExFallbackOutput(void *pv, const char *pachChars, size_t cbChars)
+{
+    PRTR0LOGLOGGERFALLBACK pThis = (PRTR0LOGLOGGERFALLBACK)pv;
+    if (cbChars)
+    {
+        size_t cbRet = 0;
+        for (;;)
+        {
+            /* how much */
+            uint32_t cb = sizeof(pThis->achScratch) - pThis->offScratch - 1; /* minus 1 - for the string terminator. */
+            if (cb > cbChars)
+                cb = (uint32_t)cbChars;
+
+            /* copy */
+            memcpy(&pThis->achScratch[pThis->offScratch], pachChars, cb);
+
+            /* advance */
+            pThis->offScratch += cb;
+            cbRet += cb;
+            cbChars -= cb;
+
+            /* done? */
+            if (cbChars <= 0)
+                return cbRet;
+
+            pachChars += cb;
+
+            /* flush */
+            pThis->achScratch[pThis->offScratch] = '\0';
+            rtR0LogLoggerExFallbackFlush(pThis);
+        }
+
+        /* won't ever get here! */
+    }
+    else
+    {
+        /*
+         * Termination call, flush the log.
+         */
+        pThis->achScratch[pThis->offScratch] = '\0';
+        rtR0LogLoggerExFallbackFlush(pThis);
+        return 0;
+    }
+}
+
+
+/**
+ * Ring-0 fallback for cases where we're unable to grab the lock.
+ *
+ * This will happen when we're at a too high IRQL on Windows for instance and
+ * needs to be dealt with or we'll drop a lot of log output. This fallback will
+ * only output to some of the log destinations as a few of them may be doing
+ * dangerous things. We won't be doing any prefixing here either, at least not
+ * for the present, because it's too much hassle.
+ *
+ * @param   fDestFlags  The destination flags.
+ * @param   fFlags      The logger flags.
+ * @param   pInt        The internal logger data, for ring buffer output.
+ * @param   pszFormat   The format string.
+ * @param   va          The format arguments.
+ */
+static void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, PRTLOGGERINTERNAL pInt,
+                                    const char *pszFormat, va_list va)
+{
+    RTR0LOGLOGGERFALLBACK This;
+    This.fDestFlags = fDestFlags;
+    This.pInt = pInt;
+
+    /* fallback indicator. */
+    This.offScratch = 2;
+    This.achScratch[0] = '[';
+    This.achScratch[1] = 'F';
+
+    /* selected prefixes */
+    if (fFlags & RTLOGFLAGS_PREFIX_PID)
+    {
+        RTPROCESS Process = RTProcSelf();
+        This.achScratch[This.offScratch++] = ' ';
+        This.offScratch += RTStrFormatNumber(&This.achScratch[This.offScratch], Process, 16, sizeof(RTPROCESS) * 2, 0, RTSTR_F_ZEROPAD);
+    }
+    if (fFlags & RTLOGFLAGS_PREFIX_TID)
+    {
+        RTNATIVETHREAD Thread = RTThreadNativeSelf();
+        This.achScratch[This.offScratch++] = ' ';
+        This.offScratch += RTStrFormatNumber(&This.achScratch[This.offScratch], Thread, 16, sizeof(RTNATIVETHREAD) * 2, 0, RTSTR_F_ZEROPAD);
+    }
+
+    This.achScratch[This.offScratch++] = ']';
+    This.achScratch[This.offScratch++] = ' ';
+
+    RTLogFormatV(rtR0LogLoggerExFallbackOutput, &This, pszFormat, va);
+}
+#endif /* IN_RING0 */
+
+
+/**
+ * vprintf like function for writing to the default log.
+ *
+ * @param   pszFormat   Printf like format string.
+ * @param   va          Optional arguments as specified in pszFormat.
+ *
+ * @remark The API doesn't support formatting of floating point numbers at the moment.
+ */
+RTDECL(void) RTLogPrintfV(const char *pszFormat, va_list va)
+{
+    RTLogLoggerV(NULL, pszFormat, va);
+}
+RT_EXPORT_SYMBOL(RTLogPrintfV);
+
+
+/**
+ * Dumper vprintf-like function outputting to a logger.
+ *
+ * @param   pvUser          Pointer to the logger instance to use, NULL for
+ *                          default instance.
+ * @param   pszFormat       Format string.
+ * @param   va              Format arguments.
+ */
+RTDECL(void) RTLogDumpPrintfV(void *pvUser, const char *pszFormat, va_list va)
+{
+    RTLogLoggerV((PRTLOGGER)pvUser, pszFormat, va);
+}
+RT_EXPORT_SYMBOL(RTLogDumpPrintfV);
+
+
+#ifdef IN_RING3
+
+/**
+ * Opens/creates the log file.
+ *
+ * @param   pLogger         The logger instance to update. NULL is not allowed!
+ * @param   pszErrorMsg     A buffer which is filled with an error message if
+ *                          something fails.  May be NULL.
+ * @param   cchErrorMsg     The size of the error message buffer.
+ */
+static int rtlogFileOpen(PRTLOGGER pLogger, char *pszErrorMsg, size_t cchErrorMsg)
+{
+    uint32_t fOpen = RTFILE_O_WRITE | RTFILE_O_DENY_NONE;
+    if (pLogger->fFlags & RTLOGFLAGS_APPEND)
+        fOpen |= RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND;
+    else
+        fOpen |= RTFILE_O_CREATE_REPLACE;
+    if (pLogger->fFlags & RTLOGFLAGS_WRITE_THROUGH)
+        fOpen |= RTFILE_O_WRITE_THROUGH;
+
+    unsigned cBackoff = 0;
+    int rc = RTFileOpen(&pLogger->pInt->hFile, pLogger->pInt->szFilename, fOpen);
+    while (   rc == VERR_SHARING_VIOLATION
+           && cBackoff < RT_ELEMENTS(g_acMsLogBackoff))
+    {
+        RTThreadSleep(g_acMsLogBackoff[cBackoff++]);
+        rc = RTFileOpen(&pLogger->pInt->hFile, pLogger->pInt->szFilename, fOpen);
+    }
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTFileGetSize(pLogger->pInt->hFile, &pLogger->pInt->cbHistoryFileWritten);
+        if (RT_FAILURE(rc))
+        {
+            /* Don't complain if this fails, assume the file is empty. */
+            pLogger->pInt->cbHistoryFileWritten = 0;
+            rc = VINF_SUCCESS;
+        }
+    }
+    else
+    {
+        pLogger->pInt->hFile = NIL_RTFILE;
+        if (pszErrorMsg)
+            RTStrPrintf(pszErrorMsg, cchErrorMsg, N_("could not open file '%s' (fOpen=%#x)"), pLogger->pInt->szFilename, fOpen);
+    }
+    return rc;
+}
+
+
+/**
+ * Closes, rotates and opens the log files if necessary.
+ *
+ * Used by the rtlogFlush() function as well as RTLogCreateExV.
+ *
+ * @param   pLogger     The logger instance to update. NULL is not allowed!
+ * @param   uTimeSlot   Current time slot (for tikme based rotation).
+ * @param   fFirst      Flag whether this is the beginning of logging, i.e.
+ *                      called from RTLogCreateExV.  Prevents pfnPhase from
+ *                      being called.
+ */
+static void rtlogRotate(PRTLOGGER pLogger, uint32_t uTimeSlot, bool fFirst)
+{
+    /* Suppress rotating empty log files simply because the time elapsed. */
+    if (RT_UNLIKELY(!pLogger->pInt->cbHistoryFileWritten))
+        pLogger->pInt->uHistoryTimeSlotStart = uTimeSlot;
+
+    /* Check rotation condition: file still small enough and not too old? */
+    if (RT_LIKELY(   pLogger->pInt->cbHistoryFileWritten < pLogger->pInt->cbHistoryFileMax
+                  && uTimeSlot == pLogger->pInt->uHistoryTimeSlotStart))
+        return;
+
+    /*
+     * Save "disabled" log flag and make sure logging is disabled.
+     * The logging in the functions called during log file history
+     * rotation would cause severe trouble otherwise.
+     */
+    uint32_t const fSavedFlags = pLogger->fFlags;
+    pLogger->fFlags |= RTLOGFLAGS_DISABLED;
+
+    /*
+     * Disable log rotation temporarily, otherwise with extreme settings and
+     * chatty phase logging we could run into endless rotation.
+     */
+    uint32_t const cSavedHistory = pLogger->pInt->cHistory;
+    pLogger->pInt->cHistory = 0;
+
+    /*
+     * Close the old log file.
+     */
+    if (pLogger->pInt->hFile != NIL_RTFILE)
+    {
+        /* Use the callback to generate some final log contents, but only if
+         * this is a rotation with a fully set up logger. Leave the other case
+         * to the RTLogCreateExV function. */
+        if (pLogger->pInt->pfnPhase && !fFirst)
+        {
+            uint32_t fODestFlags = pLogger->fDestFlags;
+            pLogger->fDestFlags &= RTLOGDEST_FILE;
+            pLogger->pInt->pfnPhase(pLogger, RTLOGPHASE_PREROTATE, rtlogPhaseMsgLocked);
+            pLogger->fDestFlags = fODestFlags;
+        }
+        RTFileClose(pLogger->pInt->hFile);
+        pLogger->pInt->hFile = NIL_RTFILE;
+    }
+
+    if (cSavedHistory)
+    {
+        /*
+         * Rotate the log files.
+         */
+        for (uint32_t i = cSavedHistory - 1; i + 1 > 0; i--)
+        {
+            char szOldName[sizeof(pLogger->pInt->szFilename) + 32];
+            if (i > 0)
+                RTStrPrintf(szOldName, sizeof(szOldName), "%s.%u", pLogger->pInt->szFilename, i);
+            else
+                RTStrCopy(szOldName, sizeof(szOldName), pLogger->pInt->szFilename);
+
+            char szNewName[sizeof(pLogger->pInt->szFilename) + 32];
+            RTStrPrintf(szNewName, sizeof(szNewName), "%s.%u", pLogger->pInt->szFilename, i + 1);
+
+            unsigned cBackoff = 0;
+            int rc = RTFileRename(szOldName, szNewName, RTFILEMOVE_FLAGS_REPLACE);
+            while (   rc == VERR_SHARING_VIOLATION
+                   && cBackoff < RT_ELEMENTS(g_acMsLogBackoff))
+            {
+                RTThreadSleep(g_acMsLogBackoff[cBackoff++]);
+                rc = RTFileRename(szOldName, szNewName, RTFILEMOVE_FLAGS_REPLACE);
+            }
+
+            if (rc == VERR_FILE_NOT_FOUND)
+                RTFileDelete(szNewName);
+        }
+
+        /*
+         * Delete excess log files.
+         */
+        for (uint32_t i = cSavedHistory + 1; ; i++)
+        {
+            char szExcessName[sizeof(pLogger->pInt->szFilename) + 32];
+            RTStrPrintf(szExcessName, sizeof(szExcessName), "%s.%u", pLogger->pInt->szFilename, i);
+            int rc = RTFileDelete(szExcessName);
+            if (RT_FAILURE(rc))
+                break;
+        }
+    }
+
+    /*
+     * Update logger state and create new log file.
+     */
+    pLogger->pInt->cbHistoryFileWritten = 0;
+    pLogger->pInt->uHistoryTimeSlotStart = uTimeSlot;
+    rtlogFileOpen(pLogger, NULL, 0);
+
+    /*
+     * Use the callback to generate some initial log contents, but only if this
+     * is a rotation with a fully set up logger.  Leave the other case to the
+     * RTLogCreateExV function.
+     */
+    if (pLogger->pInt->pfnPhase && !fFirst)
+    {
+        uint32_t const fSavedDestFlags = pLogger->fDestFlags;
+        pLogger->fDestFlags &= RTLOGDEST_FILE;
+        pLogger->pInt->pfnPhase(pLogger, RTLOGPHASE_POSTROTATE, rtlogPhaseMsgLocked);
+        pLogger->fDestFlags = fSavedDestFlags;
+    }
+
+    /* Restore saved values. */
+    pLogger->pInt->cHistory = cSavedHistory;
+    pLogger->fFlags         = fSavedFlags;
+}
+
+#endif /* IN_RING3 */
+
+
+/**
+ * Writes the buffer to the given log device without checking for buffered
+ * data or anything.
+ * Used by the RTLogFlush() function.
+ *
+ * @param   pLogger     The logger instance to write to. NULL is not allowed!
+ */
+static void rtlogFlush(PRTLOGGER pLogger)
+{
+    uint32_t const cchScratch = pLogger->offScratch;
+    if (cchScratch == 0)
+        return; /* nothing to flush. */
+
+#ifndef IN_RC
+    /*
+     * If the ring buffer is active, the other destinations are only written
+     * to when the ring buffer is flushed by RTLogFlush().
+     */
+    if (   (pLogger->fDestFlags & RTLOGDEST_RINGBUF)
+        && pLogger->pInt
+        && pLogger->pInt->pszRingBuf /* paraoia */)
+    {
+        rtLogRingBufWrite(pLogger->pInt, pLogger->achScratch, pLogger->offScratch);
+        pLogger->offScratch = 0; /* empty the buffer. */
+    }
+    else
+#endif
+    {
+        /* Make sure the string is terminated.  On Windows, RTLogWriteDebugger
+           will get upset if it isn't. */
+        if (RT_LIKELY(cchScratch < sizeof(pLogger->achScratch)))
+            pLogger->achScratch[cchScratch] = '\0';
+        else
+            AssertFailed();
+
+#ifndef IN_RC
+        if (pLogger->fDestFlags & RTLOGDEST_USER)
+            RTLogWriteUser(pLogger->achScratch, cchScratch);
+
+        if (pLogger->fDestFlags & RTLOGDEST_DEBUGGER)
+            RTLogWriteDebugger(pLogger->achScratch, cchScratch);
+
+# ifdef IN_RING3
+        if ((pLogger->fDestFlags & (RTLOGDEST_FILE | RTLOGDEST_RINGBUF)) == RTLOGDEST_FILE)
+        {
+            if (pLogger->pInt->hFile != NIL_RTFILE)
+            {
+                RTFileWrite(pLogger->pInt->hFile, pLogger->achScratch, cchScratch, NULL);
+                if (pLogger->fFlags & RTLOGFLAGS_FLUSH)
+                    RTFileFlush(pLogger->pInt->hFile);
+            }
+            if (pLogger->pInt->cHistory)
+                pLogger->pInt->cbHistoryFileWritten += cchScratch;
+        }
+# endif
+
+        if (pLogger->fDestFlags & RTLOGDEST_STDOUT)
+            RTLogWriteStdOut(pLogger->achScratch, cchScratch);
+
+        if (pLogger->fDestFlags & RTLOGDEST_STDERR)
+            RTLogWriteStdErr(pLogger->achScratch, cchScratch);
+
+# if (defined(IN_RING0) || defined(IN_RC)) && !defined(LOG_NO_COM)
+        if (pLogger->fDestFlags & RTLOGDEST_COM)
+            RTLogWriteCom(pLogger->achScratch, cchScratch);
+# endif
+#endif /* !IN_RC */
+
+#ifdef IN_RC
+        if (pLogger->pfnFlush)
+            pLogger->pfnFlush(pLogger);
+#else
+        if (pLogger->pInt->pfnFlush)
+            pLogger->pInt->pfnFlush(pLogger);
+#endif
+
+        /* empty the buffer. */
+        pLogger->offScratch = 0;
+
+#ifdef IN_RING3
+        /*
+         * Rotate the log file if configured.  Must be done after everything is
+         * flushed, since this will also use logging/flushing to write the header
+         * and footer messages.
+         */
+        if (   (pLogger->fDestFlags & RTLOGDEST_FILE)
+            && pLogger->pInt->cHistory)
+            rtlogRotate(pLogger, RTTimeProgramSecTS() / pLogger->pInt->cSecsHistoryTimeSlot, false /* fFirst */);
+#endif
+    }
+}
+
+
+/**
+ * Callback for RTLogFormatV which writes to the com port.
+ * See PFNLOGOUTPUT() for details.
+ */
+static DECLCALLBACK(size_t) rtLogOutput(void *pv, const char *pachChars, size_t cbChars)
+{
+    PRTLOGGER pLogger = (PRTLOGGER)pv;
+    if (cbChars)
+    {
+        size_t cbRet = 0;
+        for (;;)
+        {
+#if defined(DEBUG) && defined(IN_RING3)
+            /* sanity */
+            if (pLogger->offScratch >= sizeof(pLogger->achScratch))
+            {
+                fprintf(stderr, "pLogger->offScratch >= sizeof(pLogger->achScratch) (%#x >= %#x)\n",
+                        pLogger->offScratch, (unsigned)sizeof(pLogger->achScratch));
+                AssertBreakpoint(); AssertBreakpoint();
+            }
+#endif
+
+            /* how much */
+            size_t cb = sizeof(pLogger->achScratch) - pLogger->offScratch - 1;
+            if (cb > cbChars)
+                cb = cbChars;
+
+            /* copy */
+            memcpy(&pLogger->achScratch[pLogger->offScratch], pachChars, cb);
+
+            /* advance */
+            pLogger->offScratch += (uint32_t)cb;
+            cbRet += cb;
+            cbChars -= cb;
+
+            /* done? */
+            if (cbChars <= 0)
+                return cbRet;
+
+            pachChars += cb;
+
+            /* flush */
+            rtlogFlush(pLogger);
+        }
+
+        /* won't ever get here! */
+    }
+    else
+    {
+        /*
+         * Termination call.
+         * There's always space for a terminator, and it's not counted.
+         */
+        pLogger->achScratch[pLogger->offScratch] = '\0';
+        return 0;
+    }
+}
+
+
+/**
+ * stpncpy implementation for use in rtLogOutputPrefixed w/ padding.
+ *
+ * @returns Pointer to the destination buffer byte following the copied string.
+ * @param   pszDst              The destination buffer.
+ * @param   pszSrc              The source string.
+ * @param   cchSrcMax           The maximum number of characters to copy from
+ *                              the string.
+ * @param   cchMinWidth         The minimum field with, padd with spaces to
+ *                              reach this.
+ */
+DECLINLINE(char *) rtLogStPNCpyPad(char *pszDst, const char *pszSrc, size_t cchSrcMax, size_t cchMinWidth)
+{
+    size_t cchSrc = 0;
+    if (pszSrc)
+    {
+        cchSrc = strlen(pszSrc);
+        if (cchSrc > cchSrcMax)
+            cchSrc = cchSrcMax;
+
+        memcpy(pszDst, pszSrc, cchSrc);
+        pszDst += cchSrc;
+    }
+    do
+        *pszDst++ = ' ';
+    while (cchSrc++ < cchMinWidth);
+
+    return pszDst;
+}
+
+
+
+/**
+ * Callback for RTLogFormatV which writes to the logger instance.
+ * This version supports prefixes.
+ *
+ * See PFNLOGOUTPUT() for details.
+ */
+static DECLCALLBACK(size_t) rtLogOutputPrefixed(void *pv, const char *pachChars, size_t cbChars)
+{
+    PRTLOGOUTPUTPREFIXEDARGS    pArgs = (PRTLOGOUTPUTPREFIXEDARGS)pv;
+    PRTLOGGER                   pLogger = pArgs->pLogger;
+    if (cbChars)
+    {
+        size_t cbRet = 0;
+        for (;;)
+        {
+            size_t      cb = sizeof(pLogger->achScratch) - pLogger->offScratch - 1;
+            const char *pszNewLine;
+            char       *psz;
+#ifdef IN_RC
+            bool       *pfPendingPrefix = &pLogger->fPendingPrefix;
+#else
+            bool       *pfPendingPrefix = &pLogger->pInt->fPendingPrefix;
+#endif
+
+            /*
+             * Pending prefix?
+             */
+            if (*pfPendingPrefix)
+            {
+                *pfPendingPrefix = false;
+
+#if defined(DEBUG) && defined(IN_RING3)
+                /* sanity */
+                if (pLogger->offScratch >= sizeof(pLogger->achScratch))
+                {
+                    fprintf(stderr, "pLogger->offScratch >= sizeof(pLogger->achScratch) (%#x >= %#x)\n",
+                            pLogger->offScratch, (unsigned)sizeof(pLogger->achScratch));
+                    AssertBreakpoint(); AssertBreakpoint();
+                }
+#endif
+
+                /*
+                 * Flush the buffer if there isn't enough room for the maximum prefix config.
+                 * Max is 256, add a couple of extra bytes.  See CCH_PREFIX check way below.
+                 */
+                if (cb < 256 + 16)
+                {
+                    rtlogFlush(pLogger);
+                    cb = sizeof(pLogger->achScratch) - pLogger->offScratch - 1;
+                }
+
+                /*
+                 * Write the prefixes.
+                 * psz is pointing to the current position.
+                 */
+                psz = &pLogger->achScratch[pLogger->offScratch];
+                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_TS)
+                {
+                    uint64_t     u64    = RTTimeNanoTS();
+                    int          iBase  = 16;
+                    unsigned int fFlags = RTSTR_F_ZEROPAD;
+                    if (pLogger->fFlags & RTLOGFLAGS_DECIMAL_TS)
+                    {
+                        iBase = 10;
+                        fFlags = 0;
+                    }
+                    if (pLogger->fFlags & RTLOGFLAGS_REL_TS)
+                    {
+                        static volatile uint64_t s_u64LastTs;
+                        uint64_t        u64DiffTs = u64 - s_u64LastTs;
+                        s_u64LastTs = u64;
+                        /* We could have been preempted just before reading of s_u64LastTs by
+                         * another thread which wrote s_u64LastTs. In that case the difference
+                         * is negative which we simply ignore. */
+                        u64         = (int64_t)u64DiffTs < 0 ? 0 : u64DiffTs;
+                    }
+                    /* 1E15 nanoseconds = 11 days */
+                    psz += RTStrFormatNumber(psz, u64, iBase, 16, 0, fFlags);
+                    *psz++ = ' ';
+                }
+#define CCH_PREFIX_01   0 + 17
+
+                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_TSC)
+                {
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+                    uint64_t     u64    = ASMReadTSC();
+#else
+                    uint64_t     u64    = RTTimeNanoTS();
+#endif
+                    int          iBase  = 16;
+                    unsigned int fFlags = RTSTR_F_ZEROPAD;
+                    if (pLogger->fFlags & RTLOGFLAGS_DECIMAL_TS)
+                    {
+                        iBase = 10;
+                        fFlags = 0;
+                    }
+                    if (pLogger->fFlags & RTLOGFLAGS_REL_TS)
+                    {
+                        static volatile uint64_t s_u64LastTsc;
+                        int64_t        i64DiffTsc = u64 - s_u64LastTsc;
+                        s_u64LastTsc = u64;
+                        /* We could have been preempted just before reading of s_u64LastTsc by
+                         * another thread which wrote s_u64LastTsc. In that case the difference
+                         * is negative which we simply ignore. */
+                        u64          = i64DiffTsc < 0 ? 0 : i64DiffTsc;
+                    }
+                    /* 1E15 ticks at 4GHz = 69 hours */
+                    psz += RTStrFormatNumber(psz, u64, iBase, 16, 0, fFlags);
+                    *psz++ = ' ';
+                }
+#define CCH_PREFIX_02   CCH_PREFIX_01 + 17
+
+                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_MS_PROG)
+                {
+#if defined(IN_RING3) || defined(IN_RC)
+                    uint64_t u64 = RTTimeProgramMilliTS();
+#else
+                    uint64_t u64 = 0;
+#endif
+                    /* 1E8 milliseconds = 27 hours */
+                    psz += RTStrFormatNumber(psz, u64, 10, 9, 0, RTSTR_F_ZEROPAD);
+                    *psz++ = ' ';
+                }
+#define CCH_PREFIX_03   CCH_PREFIX_02 + 21
+
+                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_TIME)
+                {
+#if defined(IN_RING3) || defined(IN_RING0)
+                    RTTIMESPEC TimeSpec;
+                    RTTIME Time;
+                    RTTimeExplode(&Time, RTTimeNow(&TimeSpec));
+                    psz += RTStrFormatNumber(psz, Time.u8Hour, 10, 2, 0, RTSTR_F_ZEROPAD);
+                    *psz++ = ':';
+                    psz += RTStrFormatNumber(psz, Time.u8Minute, 10, 2, 0, RTSTR_F_ZEROPAD);
+                    *psz++ = ':';
+                    psz += RTStrFormatNumber(psz, Time.u8Second, 10, 2, 0, RTSTR_F_ZEROPAD);
+                    *psz++ = '.';
+                    psz += RTStrFormatNumber(psz, Time.u32Nanosecond / 1000, 10, 6, 0, RTSTR_F_ZEROPAD);
+                    *psz++ = ' ';
+#else
+                    memset(psz, ' ', 16);
+                    psz += 16;
+#endif
+                }
+#define CCH_PREFIX_04   CCH_PREFIX_03 + (3+1+3+1+3+1+7+1)
+
+                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_TIME_PROG)
+                {
+
+#if defined(IN_RING3) || defined(IN_RC)
+                    uint64_t u64 = RTTimeProgramMicroTS();
+                    psz += RTStrFormatNumber(psz, (uint32_t)(u64 / RT_US_1HOUR), 10, 2, 0, RTSTR_F_ZEROPAD);
+                    *psz++ = ':';
+                    uint32_t u32 = (uint32_t)(u64 % RT_US_1HOUR);
+                    psz += RTStrFormatNumber(psz, u32 / RT_US_1MIN, 10, 2, 0, RTSTR_F_ZEROPAD);
+                    *psz++ = ':';
+                    u32 %= RT_US_1MIN;
+
+                    psz += RTStrFormatNumber(psz, u32 / RT_US_1SEC, 10, 2, 0, RTSTR_F_ZEROPAD);
+                    *psz++ = '.';
+                    psz += RTStrFormatNumber(psz, u32 % RT_US_1SEC, 10, 6, 0, RTSTR_F_ZEROPAD);
+                    *psz++ = ' ';
+#else
+                    memset(psz, ' ', 16);
+                    psz += 16;
+#endif
+                }
+#define CCH_PREFIX_05   CCH_PREFIX_04 + (9+1+2+1+2+1+6+1)
+
+# if 0
+                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_DATETIME)
+                {
+                    char szDate[32];
+                    RTTIMESPEC Time;
+                    RTTimeSpecToString(RTTimeNow(&Time), szDate, sizeof(szDate));
+                    size_t cch = strlen(szDate);
+                    memcpy(psz, szDate, cch);
+                    psz += cch;
+                    *psz++ = ' ';
+                }
+#  define CCH_PREFIX_06   CCH_PREFIX_05 + 32
+# else
+#  define CCH_PREFIX_06   CCH_PREFIX_05 + 0
+# endif
+
+                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_PID)
+                {
+#ifndef IN_RC
+                    RTPROCESS Process = RTProcSelf();
+#else
+                    RTPROCESS Process = NIL_RTPROCESS;
+#endif
+                    psz += RTStrFormatNumber(psz, Process, 16, sizeof(RTPROCESS) * 2, 0, RTSTR_F_ZEROPAD);
+                    *psz++ = ' ';
+                }
+#define CCH_PREFIX_07   CCH_PREFIX_06 + 9
+
+                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_TID)
+                {
+#ifndef IN_RC
+                    RTNATIVETHREAD Thread = RTThreadNativeSelf();
+#else
+                    RTNATIVETHREAD Thread = NIL_RTNATIVETHREAD;
+#endif
+                    psz += RTStrFormatNumber(psz, Thread, 16, sizeof(RTNATIVETHREAD) * 2, 0, RTSTR_F_ZEROPAD);
+                    *psz++ = ' ';
+                }
+#define CCH_PREFIX_08   CCH_PREFIX_07 + 17
+
+                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_THREAD)
+                {
+#ifdef IN_RING3
+                    const char *pszName = RTThreadSelfName();
+#elif defined IN_RC
+                    const char *pszName = "EMT-RC";
+#else
+                    const char *pszName = "R0";
+#endif
+                    psz = rtLogStPNCpyPad(psz, pszName, 16, 8);
+                }
+#define CCH_PREFIX_09   CCH_PREFIX_08 + 17
+
+                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_CPUID)
+                {
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+                    const uint8_t idCpu = ASMGetApicId();
+#else
+                    const RTCPUID idCpu = RTMpCpuId();
+#endif
+                    psz += RTStrFormatNumber(psz, idCpu, 16, sizeof(idCpu) * 2, 0, RTSTR_F_ZEROPAD);
+                    *psz++ = ' ';
+                }
+#define CCH_PREFIX_10   CCH_PREFIX_09 + 17
+
+#ifndef IN_RC
+                if (    (pLogger->fFlags & RTLOGFLAGS_PREFIX_CUSTOM)
+                    &&  pLogger->pInt->pfnPrefix)
+                {
+                    psz += pLogger->pInt->pfnPrefix(pLogger, psz, 31, pLogger->pInt->pvPrefixUserArg);
+                    *psz++ = ' ';                                                               /* +32 */
+                }
+#endif
+#define CCH_PREFIX_11   CCH_PREFIX_10 + 32
+
+                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_LOCK_COUNTS)
+                {
+#ifdef IN_RING3 /** @todo implement these counters in ring-0 too? */
+                    RTTHREAD Thread = RTThreadSelf();
+                    if (Thread != NIL_RTTHREAD)
+                    {
+                        uint32_t cReadLocks  = RTLockValidatorReadLockGetCount(Thread);
+                        uint32_t cWriteLocks = RTLockValidatorWriteLockGetCount(Thread) - g_cLoggerLockCount;
+                        cReadLocks  = RT_MIN(0xfff, cReadLocks);
+                        cWriteLocks = RT_MIN(0xfff, cWriteLocks);
+                        psz += RTStrFormatNumber(psz, cReadLocks,  16, 1, 0, RTSTR_F_ZEROPAD);
+                        *psz++ = '/';
+                        psz += RTStrFormatNumber(psz, cWriteLocks, 16, 1, 0, RTSTR_F_ZEROPAD);
+                    }
+                    else
+#endif
+                    {
+                        *psz++ = '?';
+                        *psz++ = '/';
+                        *psz++ = '?';
+                    }
+                    *psz++ = ' ';
+                }
+#define CCH_PREFIX_12   CCH_PREFIX_11 + 8
+
+                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_FLAG_NO)
+                {
+                    psz += RTStrFormatNumber(psz, pArgs->fFlags, 16, 8, 0, RTSTR_F_ZEROPAD);
+                    *psz++ = ' ';
+                }
+#define CCH_PREFIX_13   CCH_PREFIX_12 + 9
+
+                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_FLAG)
+                {
+#ifdef IN_RING3
+                    const char *pszGroup = pArgs->iGroup != ~0U ? pLogger->pInt->papszGroups[pArgs->iGroup] : NULL;
+#else
+                    const char *pszGroup = NULL;
+#endif
+                    psz = rtLogStPNCpyPad(psz, pszGroup, 16, 8);
+                }
+#define CCH_PREFIX_14   CCH_PREFIX_13 + 17
+
+                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_GROUP_NO)
+                {
+                    if (pArgs->iGroup != ~0U)
+                    {
+                        psz += RTStrFormatNumber(psz, pArgs->iGroup, 16, 3, 0, RTSTR_F_ZEROPAD);
+                        *psz++ = ' ';
+                    }
+                    else
+                    {
+                        memcpy(psz, "-1  ", sizeof("-1  ") - 1);
+                        psz += sizeof("-1  ") - 1;
+                    }                                                                           /* +9 */
+                }
+#define CCH_PREFIX_15   CCH_PREFIX_14 + 9
+
+                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_GROUP)
+                {
+                    const unsigned fGrp = pLogger->afGroups[pArgs->iGroup != ~0U ? pArgs->iGroup : 0];
+                    const char *pszGroup;
+                    size_t cch;
+                    switch (pArgs->fFlags & fGrp)
+                    {
+                        case 0:                         pszGroup = "--------";  cch = sizeof("--------") - 1; break;
+                        case RTLOGGRPFLAGS_ENABLED:     pszGroup = "enabled" ;  cch = sizeof("enabled" ) - 1; break;
+                        case RTLOGGRPFLAGS_LEVEL_1:     pszGroup = "level 1" ;  cch = sizeof("level 1" ) - 1; break;
+                        case RTLOGGRPFLAGS_LEVEL_2:     pszGroup = "level 2" ;  cch = sizeof("level 2" ) - 1; break;
+                        case RTLOGGRPFLAGS_LEVEL_3:     pszGroup = "level 3" ;  cch = sizeof("level 3" ) - 1; break;
+                        case RTLOGGRPFLAGS_LEVEL_4:     pszGroup = "level 4" ;  cch = sizeof("level 4" ) - 1; break;
+                        case RTLOGGRPFLAGS_LEVEL_5:     pszGroup = "level 5" ;  cch = sizeof("level 5" ) - 1; break;
+                        case RTLOGGRPFLAGS_LEVEL_6:     pszGroup = "level 6" ;  cch = sizeof("level 6" ) - 1; break;
+                        case RTLOGGRPFLAGS_LEVEL_7:     pszGroup = "level 7" ;  cch = sizeof("level 7" ) - 1; break;
+                        case RTLOGGRPFLAGS_LEVEL_8:     pszGroup = "level 8" ;  cch = sizeof("level 8" ) - 1; break;
+                        case RTLOGGRPFLAGS_LEVEL_9:     pszGroup = "level 9" ;  cch = sizeof("level 9" ) - 1; break;
+                        case RTLOGGRPFLAGS_LEVEL_10:    pszGroup = "level 10";  cch = sizeof("level 10") - 1; break;
+                        case RTLOGGRPFLAGS_LEVEL_11:    pszGroup = "level 11";  cch = sizeof("level 11") - 1; break;
+                        case RTLOGGRPFLAGS_LEVEL_12:    pszGroup = "level 12";  cch = sizeof("level 12") - 1; break;
+                        case RTLOGGRPFLAGS_FLOW:        pszGroup = "flow"    ;  cch = sizeof("flow"    ) - 1; break;
+                        case RTLOGGRPFLAGS_WARN:        pszGroup = "warn"    ;  cch = sizeof("warn"    ) - 1; break;
+                        default:                        pszGroup = "????????";  cch = sizeof("????????") - 1; break;
+                    }
+                    psz = rtLogStPNCpyPad(psz, pszGroup, 16, 8);
+                }
+#define CCH_PREFIX_16   CCH_PREFIX_15 + 17
+
+#define CCH_PREFIX      ( CCH_PREFIX_16 )
+                { AssertCompile(CCH_PREFIX < 256); }
+
+                /*
+                 * Done, figure what we've used and advance the buffer and free size.
+                 */
+                cb = psz - &pLogger->achScratch[pLogger->offScratch];
+                AssertMsg(cb <= 223, ("%#zx (%zd) - fFlags=%#x\n", cb, cb, pLogger->fFlags));
+                pLogger->offScratch += (uint32_t)cb;
+                cb = sizeof(pLogger->achScratch) - pLogger->offScratch - 1;
+            }
+            else if (cb <= 0)
+            {
+                rtlogFlush(pLogger);
+                cb = sizeof(pLogger->achScratch) - pLogger->offScratch - 1;
+            }
+
+#if defined(DEBUG) && defined(IN_RING3)
+            /* sanity */
+            if (pLogger->offScratch >= sizeof(pLogger->achScratch))
+            {
+                fprintf(stderr, "pLogger->offScratch >= sizeof(pLogger->achScratch) (%#x >= %#x)\n",
+                        pLogger->offScratch, (unsigned)sizeof(pLogger->achScratch));
+                AssertBreakpoint(); AssertBreakpoint();
+            }
+#endif
+
+            /* how much */
+            if (cb > cbChars)
+                cb = cbChars;
+
+            /* have newline? */
+            pszNewLine = (const char *)memchr(pachChars, '\n', cb);
+            if (pszNewLine)
+            {
+                if (pLogger->fFlags & RTLOGFLAGS_USECRLF)
+                    cb = pszNewLine - pachChars;
+                else
+                {
+                    cb = pszNewLine - pachChars + 1;
+                    *pfPendingPrefix = true;
+                }
+            }
+
+            /* copy */
+            memcpy(&pLogger->achScratch[pLogger->offScratch], pachChars, cb);
+
+            /* advance */
+            pLogger->offScratch += (uint32_t)cb;
+            cbRet += cb;
+            cbChars -= cb;
+
+            if (    pszNewLine
+                &&  (pLogger->fFlags & RTLOGFLAGS_USECRLF)
+                &&  pLogger->offScratch + 2 < sizeof(pLogger->achScratch))
+            {
+                memcpy(&pLogger->achScratch[pLogger->offScratch], "\r\n", 2);
+                pLogger->offScratch += 2;
+                cbRet++;
+                cbChars--;
+                cb++;
+                *pfPendingPrefix = true;
+            }
+
+            /* done? */
+            if (cbChars <= 0)
+                return cbRet;
+            pachChars += cb;
+        }
+
+        /* won't ever get here! */
+    }
+    else
+    {
+        /*
+         * Termination call.
+         * There's always space for a terminator, and it's not counted.
+         */
+        pLogger->achScratch[pLogger->offScratch] = '\0';
+        return 0;
+    }
+}
+
+
+/**
+ * Write to a logger instance (worker function).
+ *
+ * This function will check whether the instance, group and flags makes up a
+ * logging kind which is currently enabled before writing anything to the log.
+ *
+ * @param   pLogger     Pointer to logger instance. Must be non-NULL.
+ * @param   fFlags      The logging flags.
+ * @param   iGroup      The group.
+ *                      The value ~0U is reserved for compatibility with RTLogLogger[V] and is
+ *                      only for internal usage!
+ * @param   pszFormat   Format string.
+ * @param   args        Format arguments.
+ */
+static void rtlogLoggerExVLocked(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, va_list args)
+{
+    /*
+     * Format the message and perhaps flush it.
+     */
+    if (pLogger->fFlags & (RTLOGFLAGS_PREFIX_MASK | RTLOGFLAGS_USECRLF))
+    {
+        RTLOGOUTPUTPREFIXEDARGS OutputArgs;
+        OutputArgs.pLogger = pLogger;
+        OutputArgs.iGroup  = iGroup;
+        OutputArgs.fFlags  = fFlags;
+        RTLogFormatV(rtLogOutputPrefixed, &OutputArgs, pszFormat, args);
+    }
+    else
+        RTLogFormatV(rtLogOutput, pLogger, pszFormat, args);
+    if (    !(pLogger->fFlags & RTLOGFLAGS_BUFFERED)
+        &&  pLogger->offScratch)
+        rtlogFlush(pLogger);
+}
+
+
+#ifndef IN_RC
+/**
+ * For calling rtlogLoggerExVLocked.
+ *
+ * @param   pLogger     The logger.
+ * @param   fFlags      The logging flags.
+ * @param   iGroup      The group.
+ *                      The value ~0U is reserved for compatibility with RTLogLogger[V] and is
+ *                      only for internal usage!
+ * @param   pszFormat   Format string.
+ * @param   ...         Format arguments.
+ */
+static void rtlogLoggerExFLocked(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, ...)
+{
+    va_list va;
+    va_start(va, pszFormat);
+    rtlogLoggerExVLocked(pLogger, fFlags, iGroup, pszFormat, va);
+    va_end(va);
+}
+#endif /* !IN_RC */
+
diff --git a/ubuntu/vbox/vboxguest/common/log/logcom.c b/ubuntu/vbox/vboxguest/common/log/logcom.c
new file mode 100644 (file)
index 0000000..7e13cf5
--- /dev/null
@@ -0,0 +1,146 @@
+/* $Id: logcom.cpp $ */
+/** @file
+ * IPRT - Logging to Serial Port.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+#ifndef IPRT_UART_BASE
+/** The port address of the COM port to log to.
+ *
+ * To override the default (COM1) append IPRT_UART_BASE=0xWXYZ to DEFS in your
+ * LocalConfig.kmk. Alternatively you can edit this file, but the don't forget
+ * to also update the default found in VBox/asmdefs.h.
+ *
+ * Standard port assignments are: COM1=0x3f8, COM2=0x2f8, COM3=0x3e8, COM4=0x2e8.
+ */
+# define IPRT_UART_BASE 0x3f8
+#endif
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/log.h>
+#include "internal/iprt.h"
+
+#include <iprt/asm.h>
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) /** @todo consider fixing the config instead. */
+# include <iprt/asm-amd64-x86.h>
+#endif
+#include <iprt/stdarg.h>
+#include <iprt/string.h>
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+static DECLCALLBACK(size_t) rtLogComOutput(void *pv, const char *pachChars, size_t cbChars);
+
+
+/**
+ * Prints a formatted string to the serial port used for logging.
+ *
+ * @returns Number of bytes written.
+ * @param   pszFormat   Format string.
+ * @param   ...         Optional arguments specified in the format string.
+ */
+RTDECL(size_t) RTLogComPrintf(const char *pszFormat, ...)
+{
+    va_list     args;
+    size_t      cb;
+    va_start(args, pszFormat);
+    cb = RTLogComPrintfV(pszFormat, args);
+    va_end(args);
+
+    return cb;
+}
+RT_EXPORT_SYMBOL(RTLogComPrintf);
+
+
+/**
+ * Prints a formatted string to the serial port used for logging.
+ *
+ * @returns Number of bytes written.
+ * @param   pszFormat   Format string.
+ * @param   args        Optional arguments specified in the format string.
+ */
+RTDECL(size_t) RTLogComPrintfV(const char *pszFormat, va_list args)
+{
+    return RTLogFormatV(rtLogComOutput, NULL, pszFormat, args);
+}
+RT_EXPORT_SYMBOL(RTLogComPrintfV);
+
+
+/**
+ * Callback for RTLogFormatV which writes to the com port.
+ * See PFNLOGOUTPUT() for details.
+ */
+static DECLCALLBACK(size_t) rtLogComOutput(void *pv, const char *pachChars, size_t cbChars)
+{
+    NOREF(pv);
+    if (cbChars)
+        RTLogWriteCom(pachChars, cbChars);
+    return cbChars;
+}
+
+
+/**
+ * Write log buffer to COM port.
+ *
+ * @param   pach        Pointer to the buffer to write.
+ * @param   cb          Number of bytes to write.
+ */
+RTDECL(void) RTLogWriteCom(const char *pach, size_t cb)
+{
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+    const uint8_t *pu8;
+    for (pu8 = (const uint8_t *)pach; cb-- > 0; pu8++)
+    {
+        register unsigned cMaxWait;
+        register uint8_t  u8;
+
+        /* expand \n -> \r\n */
+        if (*pu8 == '\n')
+            RTLogWriteCom("\r", 1);
+
+        /* Check if port is ready. */
+        cMaxWait = ~0U;
+        do
+        {
+            u8 = ASMInU8(IPRT_UART_BASE + 5);
+            cMaxWait--;
+        } while (!(u8 & 0x20) && u8 != 0xff && cMaxWait);
+
+        /* write */
+        ASMOutU8(IPRT_UART_BASE, *pu8);
+    }
+#else
+    /* PORTME? */
+#endif
+}
+RT_EXPORT_SYMBOL(RTLogWriteCom);
+
diff --git a/ubuntu/vbox/vboxguest/common/log/logellipsis.c b/ubuntu/vbox/vboxguest/common/log/logellipsis.c
new file mode 100644 (file)
index 0000000..81f8ab1
--- /dev/null
@@ -0,0 +1,105 @@
+/* $Id: logellipsis.cpp $ */
+/** @file
+ * Runtime VBox - Logger, the ellipsis variants.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/log.h>
+#include "internal/iprt.h"
+
+#include <iprt/asm.h>
+#include <iprt/stdarg.h>
+
+
+/**
+ * Write to a logger instance.
+ *
+ * @param   pLogger     Pointer to logger instance.
+ * @param   pvCallerRet Ignored.
+ * @param   pszFormat   Format string.
+ * @param   ...         Format arguments.
+ */
+RTDECL(void) RTLogLogger(PRTLOGGER pLogger, void *pvCallerRet, const char *pszFormat, ...)
+{
+    va_list args;
+    va_start(args, pszFormat);
+#if defined(RT_OS_DARWIN) && defined(RT_ARCH_X86) && defined(IN_RING3)
+    /* manually align the stack before doing the call.
+     * We boldly assume that there is a stack frame here! */
+    __asm__ __volatile__("andl $-32, %%esp\t\n" ::: "%esp");
+    RTLogLoggerExV(pLogger, 0, ~0U, pszFormat, args);
+#else
+    RTLogLoggerExV(pLogger, 0, ~0U, pszFormat, args);
+#endif
+    va_end(args);
+    NOREF(pvCallerRet);
+}
+RT_EXPORT_SYMBOL(RTLogLogger);
+
+
+/**
+ * Write to a logger instance.
+ *
+ * This function will check whether the instance, group and flags makes up a
+ * logging kind which is currently enabled before writing anything to the log.
+ *
+ * @param   pLogger     Pointer to logger instance. If NULL the default logger instance will be attempted.
+ * @param   fFlags      The logging flags.
+ * @param   iGroup      The group.
+ *                      The value ~0U is reserved for compatibility with RTLogLogger[V] and is
+ *                      only for internal usage!
+ * @param   pszFormat   Format string.
+ * @param   ...         Format arguments.
+ * @remark  This is a worker function of LogIt.
+ */
+RTDECL(void) RTLogLoggerEx(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, ...)
+{
+    va_list args;
+    va_start(args, pszFormat);
+    RTLogLoggerExV(pLogger, fFlags, iGroup, pszFormat, args);
+    va_end(args);
+}
+RT_EXPORT_SYMBOL(RTLogLoggerEx);
+
+
+/**
+ * printf like function for writing to the default log.
+ *
+ * @param   pszFormat   Printf like format string.
+ * @param   ...         Optional arguments as specified in pszFormat.
+ *
+ * @remark The API doesn't support formatting of floating point numbers at the moment.
+ */
+RTDECL(void) RTLogPrintf(const char *pszFormat, ...)
+{
+    va_list args;
+    va_start(args, pszFormat);
+    RTLogPrintfV(pszFormat, args);
+    va_end(args);
+}
+RT_EXPORT_SYMBOL(RTLogPrintf);
+
diff --git a/ubuntu/vbox/vboxguest/common/log/logformat.c b/ubuntu/vbox/vboxguest/common/log/logformat.c
new file mode 100644 (file)
index 0000000..813074b
--- /dev/null
@@ -0,0 +1,100 @@
+/* $Id: logformat.cpp $ */
+/** @file
+ * IPRT - Log Formatter.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/log.h>
+#include "internal/iprt.h"
+
+#include <iprt/string.h>
+#include <iprt/assert.h>
+#ifdef IN_RING3
+# include <iprt/thread.h>
+# include <iprt/err.h>
+#endif
+
+#include <iprt/stdarg.h>
+#include <iprt/string.h>
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+static DECLCALLBACK(size_t) rtlogFormatStr(void *pvArg, PFNRTSTROUTPUT pfnOutput,
+                                           void *pvArgOutput, const char **ppszFormat,
+                                           va_list *pArgs, int cchWidth, int cchPrecision,
+                                           unsigned fFlags, char chArgSize);
+
+
+/**
+ * Partial vsprintf worker implementation.
+ *
+ * @returns number of bytes formatted.
+ * @param   pfnOutput   Output worker.
+ *                      Called in two ways. Normally with a string an it's length.
+ *                      For termination, it's called with NULL for string, 0 for length.
+ * @param   pvArg       Argument to output worker.
+ * @param   pszFormat   Format string.
+ * @param   args        Argument list.
+ */
+RTDECL(size_t) RTLogFormatV(PFNRTSTROUTPUT pfnOutput, void *pvArg, const char *pszFormat, va_list args)
+{
+    return RTStrFormatV(pfnOutput, pvArg, rtlogFormatStr, NULL, pszFormat, args);
+}
+RT_EXPORT_SYMBOL(RTLogFormatV);
+
+
+/**
+ * Callback to format VBox formatting extentions.
+ * See @ref pg_rt_str_format for a reference on the format types.
+ *
+ * @returns The number of bytes formatted.
+ * @param   pvArg           Formatter argument.
+ * @param   pfnOutput       Pointer to output function.
+ * @param   pvArgOutput     Argument for the output function.
+ * @param   ppszFormat      Pointer to the format string pointer. Advance this till the char
+ *                          after the format specifier.
+ * @param   pArgs           Pointer to the argument list. Use this to fetch the arguments.
+ * @param   cchWidth        Format Width. -1 if not specified.
+ * @param   cchPrecision    Format Precision. -1 if not specified.
+ * @param   fFlags          Flags (RTSTR_NTFS_*).
+ * @param   chArgSize       The argument size specifier, 'l' or 'L'.
+ */
+static DECLCALLBACK(size_t) rtlogFormatStr(void *pvArg, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
+                                           const char **ppszFormat, va_list *pArgs, int cchWidth,
+                                           int cchPrecision, unsigned fFlags, char chArgSize)
+{
+    char ch = *(*ppszFormat)++;
+
+    AssertMsgFailed(("Invalid logger format type '%%%c%.10s'!\n", ch, *ppszFormat)); NOREF(ch);
+
+    NOREF(pvArg); NOREF(pfnOutput); NOREF(pvArgOutput); NOREF(pArgs); NOREF(cchWidth);
+    NOREF(cchPrecision); NOREF(fFlags); NOREF(chArgSize);
+    return 0;
+}
+
diff --git a/ubuntu/vbox/vboxguest/common/log/logrel.c b/ubuntu/vbox/vboxguest/common/log/logrel.c
new file mode 100644 (file)
index 0000000..b029339
--- /dev/null
@@ -0,0 +1,185 @@
+/* $Id: logrel.cpp $ */
+/** @file
+ * Runtime VBox - Release Logger.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/log.h>
+#include "internal/iprt.h"
+
+#ifndef IN_RC
+# include <iprt/alloc.h>
+# include <iprt/process.h>
+# include <iprt/semaphore.h>
+# include <iprt/thread.h>
+# include <iprt/mp.h>
+#endif
+#ifdef IN_RING3
+# include <iprt/file.h>
+# include <iprt/path.h>
+#endif
+#include <iprt/time.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/param.h>
+
+#include <iprt/stdarg.h>
+#include <iprt/string.h>
+#include <iprt/ctype.h>
+#ifdef IN_RING3
+# include <iprt/alloca.h>
+# include <stdio.h>
+#endif
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+#ifdef IN_RC
+/** Default release logger instance. */
+extern "C" DECLIMPORT(RTLOGGERRC)   g_RelLogger;
+#else /* !IN_RC */
+/** Default release logger instance. */
+static PRTLOGGER                    g_pRelLogger;
+#endif /* !IN_RC */
+
+
+RTDECL(PRTLOGGER)   RTLogRelGetDefaultInstance(void)
+{
+#ifdef IN_RC
+    return &g_RelLogger;
+#else /* !IN_RC */
+    return g_pRelLogger;
+#endif /* !IN_RC */
+}
+RT_EXPORT_SYMBOL(RTLogRelGetDefaultInstance);
+
+
+RTDECL(PRTLOGGER)   RTLogRelGetDefaultInstanceEx(uint32_t fFlagsAndGroup)
+{
+#ifdef IN_RC
+    PRTLOGGER pLogger = &g_RelLogger;
+#else /* !IN_RC */
+    PRTLOGGER pLogger = g_pRelLogger;
+#endif /* !IN_RC */
+    if (pLogger)
+    {
+        if (pLogger->fFlags & RTLOGFLAGS_DISABLED)
+            pLogger = NULL;
+        else
+        {
+            uint16_t const fFlags = RT_LO_U16(fFlagsAndGroup);
+            uint16_t const iGroup = RT_HI_U16(fFlagsAndGroup);
+            if (   iGroup != UINT16_MAX
+                 && (   (pLogger->afGroups[iGroup < pLogger->cGroups ? iGroup : 0] & (fFlags | (uint32_t)RTLOGGRPFLAGS_ENABLED))
+                     != (fFlags | (uint32_t)RTLOGGRPFLAGS_ENABLED)))
+            pLogger = NULL;
+        }
+    }
+    return pLogger;
+}
+RT_EXPORT_SYMBOL(RTLogRelGetDefaultInstanceEx);
+
+
+#ifndef IN_RC
+/**
+ * Sets the default logger instance.
+ *
+ * @returns iprt status code.
+ * @param   pLogger     The new default release logger instance.
+ */
+RTDECL(PRTLOGGER) RTLogRelSetDefaultInstance(PRTLOGGER pLogger)
+{
+    return ASMAtomicXchgPtrT(&g_pRelLogger, pLogger, PRTLOGGER);
+}
+RT_EXPORT_SYMBOL(RTLogRelSetDefaultInstance);
+#endif /* !IN_RC */
+
+
+/**
+ * Write to a logger instance, defaulting to the release one.
+ *
+ * This function will check whether the instance, group and flags makes up a
+ * logging kind which is currently enabled before writing anything to the log.
+ *
+ * @param   pLogger     Pointer to logger instance. If NULL the default release instance is attempted.
+ * @param   fFlags      The logging flags.
+ * @param   iGroup      The group.
+ *                      The value ~0U is reserved for compatibility with RTLogLogger[V] and is
+ *                      only for internal usage!
+ * @param   pszFormat   Format string.
+ * @param   args        Format arguments.
+ */
+RTDECL(void) RTLogRelLoggerV(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, va_list args)
+{
+    /*
+     * A NULL logger means default instance.
+     */
+    if (!pLogger)
+    {
+        pLogger = RTLogRelGetDefaultInstance();
+        if (!pLogger)
+            return;
+    }
+    RTLogLoggerExV(pLogger, fFlags, iGroup, pszFormat, args);
+}
+RT_EXPORT_SYMBOL(RTLogRelLoggerV);
+
+
+/**
+ * vprintf like function for writing to the default release log.
+ *
+ * @param   pszFormat   Printf like format string.
+ * @param   args        Optional arguments as specified in pszFormat.
+ *
+ * @remark The API doesn't support formatting of floating point numbers at the moment.
+ */
+RTDECL(void) RTLogRelPrintfV(const char *pszFormat, va_list args)
+{
+    RTLogRelLoggerV(NULL, 0, ~0U, pszFormat, args);
+}
+RT_EXPORT_SYMBOL(RTLogRelPrintfV);
+
+
+/**
+ * Changes the buffering setting of the default release logger.
+ *
+ * This can be used for optimizing longish logging sequences.
+ *
+ * @returns The old state.
+ * @param   fBuffered       The new state.
+ */
+RTDECL(bool) RTLogRelSetBuffering(bool fBuffered)
+{
+    PRTLOGGER pLogger = RTLogRelGetDefaultInstance();
+    if (pLogger)
+        return RTLogSetBuffering(pLogger, fBuffered);
+    return false;
+}
+RT_EXPORT_SYMBOL(RTLogRelSetBuffering);
+
diff --git a/ubuntu/vbox/vboxguest/common/log/logrelellipsis.c b/ubuntu/vbox/vboxguest/common/log/logrelellipsis.c
new file mode 100644 (file)
index 0000000..91a42e6
--- /dev/null
@@ -0,0 +1,78 @@
+/* $Id: logrelellipsis.cpp $ */
+/** @file
+ * Runtime VBox - Logger, the release ellipsis variants.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/log.h>
+#include "internal/iprt.h"
+
+#include <iprt/stdarg.h>
+
+
+/**
+ * Write to a logger instance, defaulting to the release one.
+ *
+ * This function will check whether the instance, group and flags makes up a
+ * logging kind which is currently enabled before writing anything to the log.
+ *
+ * @param   pLogger     Pointer to logger instance.
+ * @param   fFlags      The logging flags.
+ * @param   iGroup      The group.
+ *                      The value ~0U is reserved for compatibility with RTLogLogger[V] and is
+ *                      only for internal usage!
+ * @param   pszFormat   Format string.
+ * @param   ...         Format arguments.
+ * @remark  This is a worker function for LogRelIt.
+ */
+RTDECL(void) RTLogRelLogger(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, ...)
+{
+    va_list args;
+    va_start(args, pszFormat);
+    RTLogRelLoggerV(pLogger, fFlags, iGroup, pszFormat, args);
+    va_end(args);
+}
+RT_EXPORT_SYMBOL(RTLogRelLogger);
+
+
+/**
+ * printf like function for writing to the default release log.
+ *
+ * @param   pszFormat   Printf like format string.
+ * @param   ...         Optional arguments as specified in pszFormat.
+ *
+ * @remark The API doesn't support formatting of floating point numbers at the moment.
+ */
+RTDECL(void) RTLogRelPrintf(const char *pszFormat, ...)
+{
+    va_list args;
+    va_start(args, pszFormat);
+    RTLogRelPrintfV(pszFormat, args);
+    va_end(args);
+}
+RT_EXPORT_SYMBOL(RTLogRelPrintf);
+
diff --git a/ubuntu/vbox/vboxguest/common/math/gcc/divdi3.c b/ubuntu/vbox/vboxguest/common/math/gcc/divdi3.c
new file mode 100644 (file)
index 0000000..eecc17a
--- /dev/null
@@ -0,0 +1,70 @@
+/*     $NetBSD: divdi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $      */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)divdi3.c   8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: divdi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $");
+#endif
+#endif*/ /* LIBC_SCCS and not lint */
+
+#include "quad.h"
+
+/*
+ * Divide two signed quads.
+ * ??? if -1/2 should produce -1 on this machine, this code is wrong
+ */
+quad_t
+__divdi3(a, b)
+       quad_t a, b;
+{
+       u_quad_t ua, ub, uq;
+       int neg = 0;
+
+       ua = a;
+       ub = b;
+
+       if (a < 0)
+               ua = -ua, neg ^= 1;
+       if (b < 0)
+               ub = -ub, neg ^= 1;
+
+       uq = __qdivrem(ua, ub, (u_quad_t *)0);
+       if (neg)
+               uq = - uq;
+       return uq;
+}
diff --git a/ubuntu/vbox/vboxguest/common/math/gcc/moddi3.c b/ubuntu/vbox/vboxguest/common/math/gcc/moddi3.c
new file mode 100644 (file)
index 0000000..764ea01
--- /dev/null
@@ -0,0 +1,70 @@
+/*     $NetBSD: moddi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $      */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)moddi3.c   8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: moddi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $");
+#endif
+#endif*/ /* LIBC_SCCS and not lint */
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two signed quads.
+ *
+ * XXX we assume a % b < 0 iff a < 0, but this is actually machine-dependent.
+ */
+quad_t
+__moddi3(a, b)
+       quad_t a, b;
+{
+       u_quad_t ua, ub, ur;
+       int neg = 0;
+
+       ua = a;
+       ub = b;
+
+       if (a < 0)
+               ua = -ua, neg ^= 1;
+       if (b < 0)
+               ub = -ub;
+       (void)__qdivrem(ua, ub, &ur);
+       if (neg)
+               ur = -ur;
+       return (ur);
+}
diff --git a/ubuntu/vbox/vboxguest/common/math/gcc/qdivrem.c b/ubuntu/vbox/vboxguest/common/math/gcc/qdivrem.c
new file mode 100644 (file)
index 0000000..7ca2d38
--- /dev/null
@@ -0,0 +1,285 @@
+/*     $NetBSD: qdivrem.c,v 1.12 2005/12/11 12:24:37 christos Exp $    */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)qdivrem.c  8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: qdivrem.c,v 1.12 2005/12/11 12:24:37 christos Exp $");
+#endif
+#endif*/ /* LIBC_SCCS and not lint */
+
+/*
+ * Multiprecision divide.  This algorithm is from Knuth vol. 2 (2nd ed),
+ * section 4.3.1, pp. 257--259.
+ */
+
+#include "quad.h"
+
+#define        B       ((int)1 << HALF_BITS)   /* digit base */
+
+/* Combine two `digits' to make a single two-digit number. */
+#define        COMBINE(a, b) (((u_int)(a) << HALF_BITS) | (b))
+
+/* select a type for digits in base B: use unsigned short if they fit */
+#if UINT_MAX == 0xffffffffU && USHRT_MAX >= 0xffff
+typedef unsigned short digit;
+#else
+typedef u_int digit;
+#endif
+
+static void shl __P((digit *p, int len, int sh));
+
+/*
+ * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
+ *
+ * We do this in base 2-sup-HALF_BITS, so that all intermediate products
+ * fit within u_int.  As a consequence, the maximum length dividend and
+ * divisor are 4 `digits' in this base (they are shorter if they have
+ * leading zeros).
+ */
+u_quad_t
+__qdivrem(uq, vq, arq)
+       u_quad_t uq, vq, *arq;
+{
+       union uu tmp;
+       digit *u, *v, *q;
+       digit v1, v2;
+       u_int qhat, rhat, t;
+       int m, n, d, j, i;
+       digit uspace[5], vspace[5], qspace[5];
+
+       /*
+        * Take care of special cases: divide by zero, and u < v.
+        */
+       if (vq == 0) {
+               /* divide by zero. */
+               static volatile const unsigned int zero = 0;
+
+               tmp.ul[H] = tmp.ul[L] = 1 / zero;
+               if (arq)
+                       *arq = uq;
+               return (tmp.q);
+       }
+       if (uq < vq) {
+               if (arq)
+                       *arq = uq;
+               return (0);
+       }
+       u = &uspace[0];
+       v = &vspace[0];
+       q = &qspace[0];
+
+       /*
+        * Break dividend and divisor into digits in base B, then
+        * count leading zeros to determine m and n.  When done, we
+        * will have:
+        *      u = (u[1]u[2]...u[m+n]) sub B
+        *      v = (v[1]v[2]...v[n]) sub B
+        *      v[1] != 0
+        *      1 < n <= 4 (if n = 1, we use a different division algorithm)
+        *      m >= 0 (otherwise u < v, which we already checked)
+        *      m + n = 4
+        * and thus
+        *      m = 4 - n <= 2
+        */
+       tmp.uq = uq;
+       u[0] = 0;
+       u[1] = (digit)HHALF(tmp.ul[H]);
+       u[2] = (digit)LHALF(tmp.ul[H]);
+       u[3] = (digit)HHALF(tmp.ul[L]);
+       u[4] = (digit)LHALF(tmp.ul[L]);
+       tmp.uq = vq;
+       v[1] = (digit)HHALF(tmp.ul[H]);
+       v[2] = (digit)LHALF(tmp.ul[H]);
+       v[3] = (digit)HHALF(tmp.ul[L]);
+       v[4] = (digit)LHALF(tmp.ul[L]);
+       for (n = 4; v[1] == 0; v++) {
+               if (--n == 1) {
+                       u_int rbj;      /* r*B+u[j] (not root boy jim) */
+                       digit q1, q2, q3, q4;
+
+                       /*
+                        * Change of plan, per exercise 16.
+                        *      r = 0;
+                        *      for j = 1..4:
+                        *              q[j] = floor((r*B + u[j]) / v),
+                        *              r = (r*B + u[j]) % v;
+                        * We unroll this completely here.
+                        */
+                       t = v[2];       /* nonzero, by definition */
+                       q1 = (digit)(u[1] / t);
+                       rbj = COMBINE(u[1] % t, u[2]);
+                       q2 = (digit)(rbj / t);
+                       rbj = COMBINE(rbj % t, u[3]);
+                       q3 = (digit)(rbj / t);
+                       rbj = COMBINE(rbj % t, u[4]);
+                       q4 = (digit)(rbj / t);
+                       if (arq)
+                               *arq = rbj % t;
+                       tmp.ul[H] = COMBINE(q1, q2);
+                       tmp.ul[L] = COMBINE(q3, q4);
+                       return (tmp.q);
+               }
+       }
+
+       /*
+        * By adjusting q once we determine m, we can guarantee that
+        * there is a complete four-digit quotient at &qspace[1] when
+        * we finally stop.
+        */
+       for (m = 4 - n; u[1] == 0; u++)
+               m--;
+       for (i = 4 - m; --i >= 0;)
+               q[i] = 0;
+       q += 4 - m;
+
+       /*
+        * Here we run Program D, translated from MIX to C and acquiring
+        * a few minor changes.
+        *
+        * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
+        */
+       d = 0;
+       for (t = v[1]; t < B / 2; t <<= 1)
+               d++;
+       if (d > 0) {
+               shl(&u[0], m + n, d);           /* u <<= d */
+               shl(&v[1], n - 1, d);           /* v <<= d */
+       }
+       /*
+        * D2: j = 0.
+        */
+       j = 0;
+       v1 = v[1];      /* for D3 -- note that v[1..n] are constant */
+       v2 = v[2];      /* for D3 */
+       do {
+               digit uj0, uj1, uj2;
+
+               /*
+                * D3: Calculate qhat (\^q, in TeX notation).
+                * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
+                * let rhat = (u[j]*B + u[j+1]) mod v[1].
+                * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
+                * decrement qhat and increase rhat correspondingly.
+                * Note that if rhat >= B, v[2]*qhat < rhat*B.
+                */
+               uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
+               uj1 = u[j + 1]; /* for D3 only */
+               uj2 = u[j + 2]; /* for D3 only */
+               if (uj0 == v1) {
+                       qhat = B;
+                       rhat = uj1;
+                       goto qhat_too_big;
+               } else {
+                       u_int nn = COMBINE(uj0, uj1);
+                       qhat = nn / v1;
+                       rhat = nn % v1;
+               }
+               while (v2 * qhat > COMBINE(rhat, uj2)) {
+       qhat_too_big:
+                       qhat--;
+                       if ((rhat += v1) >= B)
+                               break;
+               }
+               /*
+                * D4: Multiply and subtract.
+                * The variable `t' holds any borrows across the loop.
+                * We split this up so that we do not require v[0] = 0,
+                * and to eliminate a final special case.
+                */
+               for (t = 0, i = n; i > 0; i--) {
+                       t = u[i + j] - v[i] * qhat - t;
+                       u[i + j] = (digit)LHALF(t);
+                       t = (B - HHALF(t)) & (B - 1);
+               }
+               t = u[j] - t;
+               u[j] = (digit)LHALF(t);
+               /*
+                * D5: test remainder.
+                * There is a borrow if and only if HHALF(t) is nonzero;
+                * in that (rare) case, qhat was too large (by exactly 1).
+                * Fix it by adding v[1..n] to u[j..j+n].
+                */
+               if (HHALF(t)) {
+                       qhat--;
+                       for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
+                               t += u[i + j] + v[i];
+                               u[i + j] = (digit)LHALF(t);
+                               t = HHALF(t);
+                       }
+                       u[j] = (digit)LHALF(u[j] + t);
+               }
+               q[j] = (digit)qhat;
+       } while (++j <= m);             /* D7: loop on j. */
+
+       /*
+        * If caller wants the remainder, we have to calculate it as
+        * u[m..m+n] >> d (this is at most n digits and thus fits in
+        * u[m+1..m+n], but we may need more source digits).
+        */
+       if (arq) {
+               if (d) {
+                       for (i = m + n; i > m; --i)
+                               u[i] = (digit)(((u_int)u[i] >> d) |
+                                   LHALF((u_int)u[i - 1] << (HALF_BITS - d)));
+                       u[i] = 0;
+               }
+               tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
+               tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
+               *arq = tmp.q;
+       }
+
+       tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
+       tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
+       return (tmp.q);
+}
+
+/*
+ * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
+ * `fall out' the left (there never will be any such anyway).
+ * We may assume len >= 0.  NOTE THAT THIS WRITES len+1 DIGITS.
+ */
+static void
+shl(digit *p, int len, int sh)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               p[i] = (digit)(LHALF((u_int)p[i] << sh) |
+                   ((u_int)p[i + 1] >> (HALF_BITS - sh)));
+       p[i] = (digit)(LHALF((u_int)p[i] << sh));
+}
diff --git a/ubuntu/vbox/vboxguest/common/math/gcc/quad.h b/ubuntu/vbox/vboxguest/common/math/gcc/quad.h
new file mode 100644 (file)
index 0000000..ea9eb73
--- /dev/null
@@ -0,0 +1,165 @@
+/*     $NetBSD: quad.h,v 1.17 2005/12/11 12:24:37 christos Exp $       */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)quad.h      8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * Quad arithmetic.
+ *
+ * This library makes the following assumptions:
+ *
+ *  - The type long long (aka quad_t) exists.
+ *
+ *  - A quad variable is exactly twice as long as `int'.
+ *
+ *  - The machine's arithmetic is two's complement.
+ *
+ * This library can provide 128-bit arithmetic on a machine with 128-bit
+ * quads and 64-bit ints, for instance, or 96-bit arithmetic on machines
+ * with 48-bit ints.
+ */
+
+#if 0 /* iprt */
+#include <sys/types.h>
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#include <limits.h>
+#else
+#include <machine/limits.h>
+#endif
+#else /* iprt */
+# include <iprt/types.h>
+# include <iprt/nocrt/limits.h>
+# undef __P
+# define __P(a) a
+# undef __GNUC_PREREQ__
+# define __GNUC_PREREQ__(m1,m2) 1
+# if 1 /* ASSUMES: little endian */
+#  define _QUAD_HIGHWORD        1
+#  define _QUAD_LOWWORD         0
+# else
+#  define _QUAD_HIGHWORD        0
+#  define _QUAD_LOWWORD         1
+# endif
+# if !defined(RT_OS_LINUX) || !defined(__KERNEL__) /* (linux/types.h defines u_int) */
+   typedef unsigned int        u_int;
+# endif
+# if !defined(RT_OS_SOLARIS)
+   typedef int64_t quad_t;
+# else
+#  define quad_t int64_t
+# endif
+   typedef uint64_t u_quad_t;
+   typedef quad_t *qaddr_t;
+#endif /* iprt */
+
+/*
+ * Depending on the desired operation, we view a `long long' (aka quad_t) in
+ * one or more of the following formats.
+ */
+union uu {
+       quad_t  q;              /* as a (signed) quad */
+       u_quad_t uq;            /* as an unsigned quad */
+       int     sl[2];          /* as two signed ints */
+       u_int   ul[2];          /* as two unsigned ints */
+};
+
+/*
+ * Define high and low parts of a quad_t.
+ */
+#define        H               _QUAD_HIGHWORD
+#define        L               _QUAD_LOWWORD
+
+/*
+ * Total number of bits in a quad_t and in the pieces that make it up.
+ * These are used for shifting, and also below for halfword extraction
+ * and assembly.
+ */
+#define        QUAD_BITS       (sizeof(quad_t) * CHAR_BIT)
+#define        INT_BITS        (sizeof(int) * CHAR_BIT)
+#define        HALF_BITS       (sizeof(int) * CHAR_BIT / 2)
+
+/*
+ * Extract high and low shortwords from longword, and move low shortword of
+ * longword to upper half of long, i.e., produce the upper longword of
+ * ((quad_t)(x) << (number_of_bits_in_int/2)).  (`x' must actually be u_int.)
+ *
+ * These are used in the multiply code, to split a longword into upper
+ * and lower halves, and to reassemble a product as a quad_t, shifted left
+ * (sizeof(int)*CHAR_BIT/2).
+ */
+#define        HHALF(x)        ((u_int)(x) >> HALF_BITS)
+#define        LHALF(x)        ((u_int)(x) & (((int)1 << HALF_BITS) - 1))
+#define        LHUP(x)         ((u_int)(x) << HALF_BITS)
+
+/*
+ * XXX
+ * Compensate for gcc 1 vs gcc 2.  Gcc 1 defines ?sh?di3's second argument
+ * as u_quad_t, while gcc 2 correctly uses int.  Unfortunately, we still use
+ * both compilers.
+ */
+#if __GNUC_PREREQ__(2, 0) || defined(lint)
+typedef unsigned int   qshift_t;
+#else
+typedef u_quad_t       qshift_t;
+#endif
+
+RT_C_DECLS_BEGIN
+quad_t __adddi3 __P((quad_t, quad_t));
+quad_t __anddi3 __P((quad_t, quad_t));
+quad_t __ashldi3 __P((quad_t, qshift_t));
+quad_t __ashrdi3 __P((quad_t, qshift_t));
+int __cmpdi2 __P((quad_t, quad_t ));
+quad_t __divdi3 __P((quad_t, quad_t));
+quad_t __fixdfdi __P((double));
+quad_t __fixsfdi __P((float));
+u_quad_t __fixunsdfdi __P((double));
+u_quad_t __fixunssfdi __P((float));
+double __floatdidf __P((quad_t));
+float __floatdisf __P((quad_t));
+double __floatunsdidf __P((u_quad_t));
+quad_t __iordi3 __P((quad_t, quad_t));
+quad_t __lshldi3 __P((quad_t, qshift_t));
+quad_t __lshrdi3 __P((quad_t, qshift_t));
+quad_t __moddi3 __P((quad_t, quad_t));
+quad_t __muldi3 __P((quad_t, quad_t));
+quad_t __negdi2 __P((quad_t));
+quad_t __one_cmpldi2 __P((quad_t));
+u_quad_t __qdivrem __P((u_quad_t, u_quad_t, u_quad_t *));
+quad_t __subdi3 __P((quad_t, quad_t));
+int __ucmpdi2 __P((u_quad_t, u_quad_t));
+u_quad_t __udivdi3 __P((u_quad_t, u_quad_t ));
+u_quad_t __umoddi3 __P((u_quad_t, u_quad_t ));
+quad_t __xordi3 __P((quad_t, quad_t));
+RT_C_DECLS_END
diff --git a/ubuntu/vbox/vboxguest/common/math/gcc/udivdi3.c b/ubuntu/vbox/vboxguest/common/math/gcc/udivdi3.c
new file mode 100644 (file)
index 0000000..9069f4d
--- /dev/null
@@ -0,0 +1,56 @@
+/*     $NetBSD: udivdi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $     */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)udivdi3.c  8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: udivdi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $");
+#endif
+#endif*/ /* LIBC_SCCS and not lint */
+
+#include "quad.h"
+
+/*
+ * Divide two unsigned quads.
+ */
+u_quad_t
+__udivdi3(a, b)
+       u_quad_t a, b;
+{
+
+       return (__qdivrem(a, b, (u_quad_t *)0));
+}
diff --git a/ubuntu/vbox/vboxguest/common/math/gcc/udivmoddi4.c b/ubuntu/vbox/vboxguest/common/math/gcc/udivmoddi4.c
new file mode 100644 (file)
index 0000000..09b3f2b
--- /dev/null
@@ -0,0 +1,53 @@
+/* $Id: udivmoddi4.c $ */
+/** @file
+ * IPRT - __udivmoddi4 implementation
+ */
+
+/*
+ * 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.
+ */
+
+#include <iprt/stdint.h>
+#include <iprt/uint64.h>
+
+uint64_t __udivmoddi4(uint64_t u64A, uint64_t u64B, uint64_t *pu64R);
+
+/**
+ * __udivmoddi4() implementation to satisfy external references from 32-bit
+ * code generated by gcc-7 or later.
+ *
+ * @param   u64A        The divident value.
+ * @param   u64B        The divisor value.
+ * @param   pu64R       A pointer to the reminder. May be NULL.
+ * @returns u64A / u64B
+ */
+uint64_t __udivmoddi4(uint64_t u64A, uint64_t u64B, uint64_t *pu64R)
+{
+    RTUINT64U Divident;
+    RTUINT64U Divisor;
+    RTUINT64U Quotient;
+    RTUINT64U Reminder;
+    Divident.u = u64A;
+    Divisor.u  = u64B;
+    RTUInt64DivRem(&Quotient, &Reminder, &Divident, &Divisor);
+    if (pu64R)
+        *pu64R = Reminder.u;
+    return Quotient.u;
+}
diff --git a/ubuntu/vbox/vboxguest/common/math/gcc/umoddi3.c b/ubuntu/vbox/vboxguest/common/math/gcc/umoddi3.c
new file mode 100644 (file)
index 0000000..2e65eca
--- /dev/null
@@ -0,0 +1,58 @@
+/*     $NetBSD: umoddi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $     */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)umoddi3.c  8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: umoddi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $");
+#endif
+#endif*/ /* LIBC_SCCS and not lint */
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two unsigned quads.
+ */
+u_quad_t
+__umoddi3(a, b)
+       u_quad_t a, b;
+{
+       u_quad_t r;
+
+       (void)__qdivrem(a, b, &r);
+       return (r);
+}
diff --git a/ubuntu/vbox/vboxguest/common/misc/RTAssertMsg1Weak.c b/ubuntu/vbox/vboxguest/common/misc/RTAssertMsg1Weak.c
new file mode 100644 (file)
index 0000000..645e5e6
--- /dev/null
@@ -0,0 +1,42 @@
+/* $Id: RTAssertMsg1Weak.cpp $ */
+/** @file
+ * IPRT - RTAssertMsg1Weak.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/assert.h>
+#include "internal/iprt.h"
+
+#include <iprt/stdarg.h>
+
+
+RTDECL(void) RTAssertMsg1Weak(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction)
+{
+    RTAssertMsg1(pszExpr, uLine, pszFile, pszFunction);
+}
+RT_EXPORT_SYMBOL(RTAssertMsg1Weak);
+
diff --git a/ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2.c b/ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2.c
new file mode 100644 (file)
index 0000000..9fe1fb8
--- /dev/null
@@ -0,0 +1,45 @@
+/* $Id: RTAssertMsg2.cpp $ */
+/** @file
+ * IPRT - RTAssertMsg2.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/assert.h>
+#include "internal/iprt.h"
+
+#include <iprt/stdarg.h>
+
+
+RTDECL(void) RTAssertMsg2(const char *pszFormat, ...)
+{
+    va_list va;
+    va_start(va, pszFormat);
+    RTAssertMsg2V(pszFormat, va);
+    va_end(va);
+}
+RT_EXPORT_SYMBOL(RTAssertMsg2);
+
diff --git a/ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2Add.c b/ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2Add.c
new file mode 100644 (file)
index 0000000..2a22505
--- /dev/null
@@ -0,0 +1,45 @@
+/* $Id: RTAssertMsg2Add.cpp $ */
+/** @file
+ * IPRT - RTAssertMsg2Add.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/assert.h>
+#include "internal/iprt.h"
+
+#include <iprt/stdarg.h>
+
+
+RTDECL(void) RTAssertMsg2Add(const char *pszFormat, ...)
+{
+    va_list va;
+    va_start(va, pszFormat);
+    RTAssertMsg2AddV(pszFormat, va);
+    va_end(va);
+}
+RT_EXPORT_SYMBOL(RTAssertMsg2Add);
+
diff --git a/ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2AddWeak.c b/ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2AddWeak.c
new file mode 100644 (file)
index 0000000..72b55b5
--- /dev/null
@@ -0,0 +1,45 @@
+/* $Id: RTAssertMsg2AddWeak.cpp $ */
+/** @file
+ * IPRT - RTAssertMsg2AddWeak.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/assert.h>
+#include "internal/iprt.h"
+
+#include <iprt/stdarg.h>
+
+
+RTDECL(void) RTAssertMsg2AddWeak(const char *pszFormat, ...)
+{
+    va_list va;
+    va_start(va, pszFormat);
+    RTAssertMsg2AddWeakV(pszFormat, va);
+    va_end(va);
+}
+RT_EXPORT_SYMBOL(RTAssertMsg2AddWeak);
+
diff --git a/ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2AddWeakV.c b/ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2AddWeakV.c
new file mode 100644 (file)
index 0000000..e1c35a7
--- /dev/null
@@ -0,0 +1,40 @@
+/* $Id: RTAssertMsg2AddWeakV.cpp $ */
+/** @file
+ * IPRT - RTAssertMsg2AddWeakV.
+ */
+
+/*
+ * Copyright (C) 2009-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/assert.h>
+#include "internal/iprt.h"
+
+
+RTDECL(void) RTAssertMsg2AddWeakV(const char *pszFormat, va_list va)
+{
+    RTAssertMsg2AddV(pszFormat, va);
+}
+RT_EXPORT_SYMBOL(RTAssertMsg2AddWeakV);
+
diff --git a/ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2Weak.c b/ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2Weak.c
new file mode 100644 (file)
index 0000000..b342fdf
--- /dev/null
@@ -0,0 +1,45 @@
+/* $Id: RTAssertMsg2Weak.cpp $ */
+/** @file
+ * IPRT - RTAssertMsg2Weak.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/assert.h>
+#include "internal/iprt.h"
+
+#include <iprt/stdarg.h>
+
+
+RTDECL(void) RTAssertMsg2Weak(const char *pszFormat, ...)
+{
+    va_list va;
+    va_start(va, pszFormat);
+    RTAssertMsg2WeakV(pszFormat, va);
+    va_end(va);
+}
+RT_EXPORT_SYMBOL(RTAssertMsg2Weak);
+
diff --git a/ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2WeakV.c b/ubuntu/vbox/vboxguest/common/misc/RTAssertMsg2WeakV.c
new file mode 100644 (file)
index 0000000..2a1a99d
--- /dev/null
@@ -0,0 +1,40 @@
+/* $Id: RTAssertMsg2WeakV.cpp $ */
+/** @file
+ * IPRT - RTAssertMsg2WeakV.
+ */
+
+/*
+ * Copyright (C) 2009-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/assert.h>
+#include "internal/iprt.h"
+
+
+RTDECL(void) RTAssertMsg2WeakV(const char *pszFormat, va_list va)
+{
+    RTAssertMsg2V(pszFormat, va);
+}
+RT_EXPORT_SYMBOL(RTAssertMsg2WeakV);
+
diff --git a/ubuntu/vbox/vboxguest/common/misc/assert.c b/ubuntu/vbox/vboxguest/common/misc/assert.c
new file mode 100644 (file)
index 0000000..ab0ec89
--- /dev/null
@@ -0,0 +1,307 @@
+/* $Id: assert.cpp $ */
+/** @file
+ * IPRT - Assertions, common code.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/assert.h>
+#include "internal/iprt.h"
+
+#include <iprt/asm.h>
+#include <iprt/err.h>
+#include <iprt/log.h>
+#include <iprt/string.h>
+#include <iprt/stdarg.h>
+#ifdef IN_RING3
+# include <stdio.h>
+#endif
+#include "internal/assert.h"
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** The last assert message, 1st part. */
+RTDATADECL(char)                    g_szRTAssertMsg1[1024];
+RT_EXPORT_SYMBOL(g_szRTAssertMsg1);
+/** The last assert message, 2nd part. */
+RTDATADECL(char)                    g_szRTAssertMsg2[4096];
+RT_EXPORT_SYMBOL(g_szRTAssertMsg2);
+/** The length of the g_szRTAssertMsg2 content.
+ * @remarks Race.  */
+static uint32_t volatile            g_cchRTAssertMsg2;
+/** The last assert message, expression. */
+RTDATADECL(const char * volatile)   g_pszRTAssertExpr;
+RT_EXPORT_SYMBOL(g_pszRTAssertExpr);
+/** The last assert message, function name. */
+RTDATADECL(const char *  volatile)  g_pszRTAssertFunction;
+RT_EXPORT_SYMBOL(g_pszRTAssertFunction);
+/** The last assert message, file name. */
+RTDATADECL(const char * volatile)   g_pszRTAssertFile;
+RT_EXPORT_SYMBOL(g_pszRTAssertFile);
+/** The last assert message, line number. */
+RTDATADECL(uint32_t volatile)       g_u32RTAssertLine;
+RT_EXPORT_SYMBOL(g_u32RTAssertLine);
+
+
+/** Set if assertions are quiet. */
+static bool volatile                g_fQuiet = false;
+/** Set if assertions may panic. */
+static bool volatile                g_fMayPanic = true;
+
+
+RTDECL(bool) RTAssertSetQuiet(bool fQuiet)
+{
+    return ASMAtomicXchgBool(&g_fQuiet, fQuiet);
+}
+RT_EXPORT_SYMBOL(RTAssertSetQuiet);
+
+
+RTDECL(bool) RTAssertAreQuiet(void)
+{
+    return ASMAtomicUoReadBool(&g_fQuiet);
+}
+RT_EXPORT_SYMBOL(RTAssertAreQuiet);
+
+
+RTDECL(bool) RTAssertSetMayPanic(bool fMayPanic)
+{
+    return ASMAtomicXchgBool(&g_fMayPanic, fMayPanic);
+}
+RT_EXPORT_SYMBOL(RTAssertSetMayPanic);
+
+
+RTDECL(bool) RTAssertMayPanic(void)
+{
+    return ASMAtomicUoReadBool(&g_fMayPanic);
+}
+RT_EXPORT_SYMBOL(RTAssertMayPanic);
+
+
+RTDECL(void) RTAssertMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction)
+{
+    /*
+     * Fill in the globals.
+     */
+    ASMAtomicUoWritePtr(&g_pszRTAssertExpr, pszExpr);
+    ASMAtomicUoWritePtr(&g_pszRTAssertFile, pszFile);
+    ASMAtomicUoWritePtr(&g_pszRTAssertFunction, pszFunction);
+    ASMAtomicUoWriteU32(&g_u32RTAssertLine, uLine);
+    RTStrPrintf(g_szRTAssertMsg1, sizeof(g_szRTAssertMsg1),
+                "\n!!Assertion Failed!!\n"
+                "Expression: %s\n"
+                "Location  : %s(%d) %s\n",
+                pszExpr, pszFile, uLine, pszFunction);
+
+    /*
+     * If not quiet, make noise.
+     */
+    if (!RTAssertAreQuiet())
+    {
+        RTERRVARS SavedErrVars;
+        RTErrVarsSave(&SavedErrVars);
+
+#ifdef IN_RING0
+# ifdef IN_GUEST_R0
+        RTLogBackdoorPrintf("\n!!Assertion Failed!!\n"
+                            "Expression: %s\n"
+                            "Location  : %s(%d) %s\n",
+                            pszExpr, pszFile, uLine, pszFunction);
+# endif
+        /** @todo fully integrate this with the logger... play safe a bit for now.  */
+        rtR0AssertNativeMsg1(pszExpr, uLine, pszFile, pszFunction);
+
+#else  /* !IN_RING0 */
+# if !defined(IN_RING3) && !defined(LOG_NO_COM)
+#  if 0 /* Enable this iff you have a COM port and really want this debug info. */
+        RTLogComPrintf("\n!!Assertion Failed!!\n"
+                       "Expression: %s\n"
+                       "Location  : %s(%d) %s\n",
+                       pszExpr, pszFile, uLine, pszFunction);
+#  endif
+# endif
+
+        PRTLOGGER pLog = RTLogRelGetDefaultInstance();
+        if (pLog)
+        {
+            RTLogRelPrintf("\n!!Assertion Failed!!\n"
+                           "Expression: %s\n"
+                           "Location  : %s(%d) %s\n",
+                           pszExpr, pszFile, uLine, pszFunction);
+# ifndef IN_RC /* flushing is done automatically in RC */
+            RTLogFlush(pLog);
+# endif
+        }
+
+# ifndef LOG_ENABLED
+        if (!pLog)
+# endif
+        {
+            pLog = RTLogDefaultInstance();
+            if (pLog)
+            {
+                RTLogPrintf("\n!!Assertion Failed!!\n"
+                            "Expression: %s\n"
+                            "Location  : %s(%d) %s\n",
+                            pszExpr, pszFile, uLine, pszFunction);
+# ifndef IN_RC /* flushing is done automatically in RC */
+                RTLogFlush(pLog);
+# endif
+            }
+        }
+
+# ifdef IN_RING3
+        /* print to stderr, helps user and gdb debugging. */
+        fprintf(stderr,
+                "\n!!Assertion Failed!!\n"
+                "Expression: %s\n"
+                "Location  : %s(%d) %s\n",
+                VALID_PTR(pszExpr) ? pszExpr : "<none>",
+                VALID_PTR(pszFile) ? pszFile : "<none>",
+                uLine,
+                VALID_PTR(pszFunction) ? pszFunction : "");
+        fflush(stderr);
+# endif
+#endif /* !IN_RING0 */
+
+        RTErrVarsRestore(&SavedErrVars);
+    }
+}
+RT_EXPORT_SYMBOL(RTAssertMsg1);
+
+
+/**
+ * Worker for RTAssertMsg2V and RTAssertMsg2AddV
+ *
+ * @param   fInitial            True if it's RTAssertMsg2V, otherwise false.
+ * @param   pszFormat           The message format string.
+ * @param   va                  The format arguments.
+ */
+static void rtAssertMsg2Worker(bool fInitial, const char *pszFormat, va_list va)
+{
+    va_list vaCopy;
+    size_t  cch;
+
+    /*
+     * The global first.
+     */
+    if (fInitial)
+    {
+        va_copy(vaCopy, va);
+        cch = RTStrPrintfV(g_szRTAssertMsg2, sizeof(g_szRTAssertMsg2), pszFormat, vaCopy);
+        ASMAtomicWriteU32(&g_cchRTAssertMsg2, (uint32_t)cch);
+        va_end(vaCopy);
+    }
+    else
+    {
+        cch = ASMAtomicReadU32(&g_cchRTAssertMsg2);
+        if (cch < sizeof(g_szRTAssertMsg2) - 4)
+        {
+            va_copy(vaCopy, va);
+            cch += RTStrPrintfV(&g_szRTAssertMsg2[cch], sizeof(g_szRTAssertMsg2) - cch, pszFormat, vaCopy);
+            ASMAtomicWriteU32(&g_cchRTAssertMsg2, (uint32_t)cch);
+            va_end(vaCopy);
+        }
+    }
+
+    /*
+     * If not quiet, make some noise.
+     */
+    if (!RTAssertAreQuiet())
+    {
+        RTERRVARS SavedErrVars;
+        RTErrVarsSave(&SavedErrVars);
+
+#ifdef IN_RING0
+# ifdef IN_GUEST_R0
+        va_copy(vaCopy, va);
+        RTLogBackdoorPrintfV(pszFormat, vaCopy);
+        va_end(vaCopy);
+# endif
+        /** @todo fully integrate this with the logger... play safe a bit for now.  */
+        rtR0AssertNativeMsg2V(fInitial, pszFormat, va);
+
+#else  /* !IN_RING0 */
+# if !defined(IN_RING3) && !defined(LOG_NO_COM)
+#  if 0 /* Enable this iff you have a COM port and really want this debug info. */
+        va_copy(vaCopy, va);
+        RTLogComPrintfV(pszFormat, vaCopy);
+        va_end(vaCopy);
+#  endif
+# endif
+
+        PRTLOGGER pLog = RTLogRelGetDefaultInstance();
+        if (pLog)
+        {
+            va_copy(vaCopy, va);
+            RTLogRelPrintfV(pszFormat, vaCopy);
+            va_end(vaCopy);
+# ifndef IN_RC /* flushing is done automatically in RC */
+            RTLogFlush(pLog);
+# endif
+        }
+
+        pLog = RTLogDefaultInstance();
+        if (pLog)
+        {
+            va_copy(vaCopy, va);
+            RTLogPrintfV(pszFormat, vaCopy);
+            va_end(vaCopy);
+# ifndef IN_RC /* flushing is done automatically in RC */
+            RTLogFlush(pLog);
+#endif
+        }
+
+# ifdef IN_RING3
+        /* print to stderr, helps user and gdb debugging. */
+        char szMsg[sizeof(g_szRTAssertMsg2)];
+        va_copy(vaCopy, va);
+        RTStrPrintfV(szMsg, sizeof(szMsg), pszFormat, vaCopy);
+        va_end(vaCopy);
+        fprintf(stderr, "%s", szMsg);
+        fflush(stderr);
+# endif
+#endif /* !IN_RING0 */
+
+        RTErrVarsRestore(&SavedErrVars);
+    }
+}
+
+
+RTDECL(void) RTAssertMsg2V(const char *pszFormat, va_list va)
+{
+    rtAssertMsg2Worker(true /*fInitial*/, pszFormat, va);
+}
+RT_EXPORT_SYMBOL(RTAssertMsg2V);
+
+
+RTDECL(void) RTAssertMsg2AddV(const char *pszFormat, va_list va)
+{
+    rtAssertMsg2Worker(false /*fInitial*/, pszFormat, va);
+}
+RT_EXPORT_SYMBOL(RTAssertMsg2AddV);
+
diff --git a/ubuntu/vbox/vboxguest/common/misc/thread.c b/ubuntu/vbox/vboxguest/common/misc/thread.c
new file mode 100644 (file)
index 0000000..3ca5d26
--- /dev/null
@@ -0,0 +1,1587 @@
+/* $Id: thread.cpp $ */
+/** @file
+ * IPRT - Threads, common routines.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_THREAD
+#include <iprt/thread.h>
+#include "internal/iprt.h"
+
+#include <iprt/log.h>
+#include <iprt/avl.h>
+#include <iprt/alloc.h>
+#include <iprt/assert.h>
+#include <iprt/lockvalidator.h>
+#include <iprt/semaphore.h>
+#ifdef IN_RING0
+# include <iprt/spinlock.h>
+#endif
+#include <iprt/asm.h>
+#include <iprt/err.h>
+#include <iprt/string.h>
+#include "internal/magics.h"
+#include "internal/thread.h"
+#include "internal/sched.h"
+#include "internal/process.h"
+#ifdef RT_WITH_ICONV_CACHE
+# include "internal/string.h"
+#endif
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+#ifdef IN_RING0
+# define RT_THREAD_LOCK_RW()        RTSpinlockAcquire(g_ThreadSpinlock)
+# define RT_THREAD_UNLOCK_RW()      RTSpinlockRelease(g_ThreadSpinlock)
+# define RT_THREAD_LOCK_RD()        RTSpinlockAcquire(g_ThreadSpinlock)
+# define RT_THREAD_UNLOCK_RD()      RTSpinlockRelease(g_ThreadSpinlock)
+#else
+# define RT_THREAD_LOCK_RW()        rtThreadLockRW()
+# define RT_THREAD_UNLOCK_RW()      rtThreadUnLockRW()
+# define RT_THREAD_LOCK_RD()        rtThreadLockRD()
+# define RT_THREAD_UNLOCK_RD()      rtThreadUnLockRD()
+#endif
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** The AVL thread containing the threads. */
+static PAVLPVNODECORE       g_ThreadTree;
+/** The number of threads in the tree (for ring-0 termination kludge). */
+static uint32_t volatile    g_cThreadInTree;
+#ifdef IN_RING3
+/** The RW lock protecting the tree. */
+static RTSEMRW          g_ThreadRWSem = NIL_RTSEMRW;
+#else
+/** The spinlocks protecting the tree. */
+static RTSPINLOCK       g_ThreadSpinlock = NIL_RTSPINLOCK;
+#endif
+/** Indicates whether we've been initialized or not. */
+static bool             g_frtThreadInitialized;
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+static void rtThreadDestroy(PRTTHREADINT pThread);
+#ifdef IN_RING3
+static int rtThreadAdopt(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntFlags, const char *pszName);
+#endif
+static void rtThreadRemoveLocked(PRTTHREADINT pThread);
+static PRTTHREADINT rtThreadAlloc(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntFlags, const char *pszName);
+
+
+/** @page pg_rt_thread  IPRT Thread Internals
+ *
+ * IPRT provides interface to whatever native threading that the host provides,
+ * preferably using a CRT level interface to better integrate with other libraries.
+ *
+ * Internally IPRT keeps track of threads by means of the RTTHREADINT structure.
+ * All the RTTHREADINT structures are kept in a AVL tree which is protected by a
+ * read/write lock for efficient access. A thread is inserted into the tree in
+ * three places in the code. The main thread is 'adopted' by IPRT on rtR3Init()
+ * by rtThreadAdopt(). When creating a new thread there the child and the parent
+ * race inserting the thread, this is rtThreadMain() and RTThreadCreate.
+ *
+ * RTTHREADINT objects are using reference counting as a mean of sticking around
+ * till no-one needs them any longer. Waitable threads is created with one extra
+ * reference so they won't go away until they are waited on. This introduces a
+ * major problem if we use the host thread identifier as key in the AVL tree - the
+ * host may reuse the thread identifier before the thread was waited on. So, on
+ * most platforms we are using the RTTHREADINT pointer as key and not the
+ * thread id. RTThreadSelf() then have to be implemented using a pointer stored
+ * in thread local storage (TLS).
+ *
+ * In Ring-0 we only try keep track of kernel threads created by RTThreadCreate
+ * at the moment. There we really only need the 'join' feature, but doing things
+ * the same way allow us to name threads and similar stuff.
+ */
+
+
+/**
+ * Initializes the thread database.
+ *
+ * @returns iprt status code.
+ */
+DECLHIDDEN(int) rtThreadInit(void)
+{
+#ifdef IN_RING3
+    int rc = VINF_ALREADY_INITIALIZED;
+    if (g_ThreadRWSem == NIL_RTSEMRW)
+    {
+        /*
+         * We assume the caller is the 1st thread, which we'll call 'main'.
+         * But first, we'll create the semaphore.
+         */
+        rc = RTSemRWCreateEx(&g_ThreadRWSem, RTSEMRW_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
+        if (RT_SUCCESS(rc))
+        {
+            rc = rtThreadNativeInit();
+            if (RT_SUCCESS(rc))
+                rc = rtThreadAdopt(RTTHREADTYPE_DEFAULT, 0, RTTHREADINT_FLAGS_MAIN, "main");
+            if (RT_SUCCESS(rc))
+                rc = rtSchedNativeCalcDefaultPriority(RTTHREADTYPE_DEFAULT);
+            if (RT_SUCCESS(rc))
+            {
+                g_frtThreadInitialized = true;
+                return VINF_SUCCESS;
+            }
+
+            /* failed, clear out */
+            RTSemRWDestroy(g_ThreadRWSem);
+            g_ThreadRWSem = NIL_RTSEMRW;
+        }
+    }
+
+#elif defined(IN_RING0)
+    int rc;
+    /*
+     * Create the spinlock and to native init.
+     */
+    Assert(g_ThreadSpinlock == NIL_RTSPINLOCK);
+    rc = RTSpinlockCreate(&g_ThreadSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "RTThread");
+    if (RT_SUCCESS(rc))
+    {
+        rc = rtThreadNativeInit();
+        if (RT_SUCCESS(rc))
+        {
+            g_frtThreadInitialized = true;
+            return VINF_SUCCESS;
+        }
+
+        /* failed, clear out */
+        RTSpinlockDestroy(g_ThreadSpinlock);
+        g_ThreadSpinlock = NIL_RTSPINLOCK;
+    }
+#else
+# error "!IN_RING0 && !IN_RING3"
+#endif
+    return rc;
+}
+
+
+#ifdef IN_RING3
+/**
+ * Called when IPRT was first initialized in unobtrusive mode and later changed
+ * to obtrustive.
+ *
+ * This is only applicable in ring-3.
+ */
+DECLHIDDEN(void) rtThreadReInitObtrusive(void)
+{
+    rtThreadNativeReInitObtrusive();
+}
+#endif
+
+
+/**
+ * Terminates the thread database.
+ */
+DECLHIDDEN(void) rtThreadTerm(void)
+{
+#ifdef IN_RING3
+    /* we don't cleanup here yet */
+
+#elif defined(IN_RING0)
+    /* just destroy the spinlock and assume the thread is fine... */
+    RTSpinlockDestroy(g_ThreadSpinlock);
+    g_ThreadSpinlock = NIL_RTSPINLOCK;
+    if (g_ThreadTree != NULL)
+        RTAssertMsg2Weak("WARNING: g_ThreadTree=%p\n", g_ThreadTree);
+#endif
+}
+
+
+#ifdef IN_RING3
+
+DECLINLINE(void) rtThreadLockRW(void)
+{
+    if (g_ThreadRWSem == NIL_RTSEMRW)
+        rtThreadInit();
+    int rc = RTSemRWRequestWrite(g_ThreadRWSem, RT_INDEFINITE_WAIT);
+    AssertReleaseRC(rc);
+}
+
+
+DECLINLINE(void) rtThreadLockRD(void)
+{
+    if (g_ThreadRWSem == NIL_RTSEMRW)
+        rtThreadInit();
+    int rc = RTSemRWRequestRead(g_ThreadRWSem, RT_INDEFINITE_WAIT);
+    AssertReleaseRC(rc);
+}
+
+
+DECLINLINE(void) rtThreadUnLockRW(void)
+{
+    int rc = RTSemRWReleaseWrite(g_ThreadRWSem);
+    AssertReleaseRC(rc);
+}
+
+
+DECLINLINE(void) rtThreadUnLockRD(void)
+{
+    int rc = RTSemRWReleaseRead(g_ThreadRWSem);
+    AssertReleaseRC(rc);
+}
+
+
+/**
+ * Adopts the calling thread.
+ * No locks are taken or released by this function.
+ */
+static int rtThreadAdopt(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntFlags, const char *pszName)
+{
+    int rc;
+    PRTTHREADINT pThread;
+    Assert(!(fFlags & RTTHREADFLAGS_WAITABLE));
+    fFlags &= ~RTTHREADFLAGS_WAITABLE;
+
+    /*
+     * Allocate and insert the thread.
+     * (It is vital that rtThreadNativeAdopt updates the TLS before
+     * we try inserting the thread because of locking.)
+     */
+    rc = VERR_NO_MEMORY;
+    pThread = rtThreadAlloc(enmType, fFlags, RTTHREADINT_FLAGS_ALIEN | fIntFlags, pszName);
+    if (pThread)
+    {
+        RTNATIVETHREAD NativeThread = RTThreadNativeSelf();
+        rc = rtThreadNativeAdopt(pThread);
+        if (RT_SUCCESS(rc))
+        {
+            rtThreadInsert(pThread, NativeThread);
+            rtThreadSetState(pThread, RTTHREADSTATE_RUNNING);
+            rtThreadRelease(pThread);
+        }
+    }
+    return rc;
+}
+
+/**
+ * Adopts a non-IPRT thread.
+ *
+ * @returns IPRT status code.
+ * @param   enmType         The thread type.
+ * @param   fFlags          The thread flags. RTTHREADFLAGS_WAITABLE is not currently allowed.
+ * @param   pszName         The thread name. Optional.
+ * @param   pThread         Where to store the thread handle. Optional.
+ */
+RTDECL(int) RTThreadAdopt(RTTHREADTYPE enmType, unsigned fFlags, const char *pszName, PRTTHREAD pThread)
+{
+    int      rc;
+    RTTHREAD Thread;
+
+    AssertReturn(!(fFlags & RTTHREADFLAGS_WAITABLE), VERR_INVALID_PARAMETER);
+    AssertReturn(!pszName || VALID_PTR(pszName), VERR_INVALID_POINTER);
+    AssertReturn(!pThread || VALID_PTR(pThread), VERR_INVALID_POINTER);
+
+    rc = VINF_SUCCESS;
+    Thread = RTThreadSelf();
+    if (Thread == NIL_RTTHREAD)
+    {
+        /* generate a name if none was given. */
+        char szName[RTTHREAD_NAME_LEN];
+        if (!pszName || !*pszName)
+        {
+            static uint32_t s_i32AlienId = 0;
+            uint32_t i32Id = ASMAtomicIncU32(&s_i32AlienId);
+            RTStrPrintf(szName, sizeof(szName), "ALIEN-%RX32", i32Id);
+            pszName = szName;
+        }
+
+        /* try adopt it */
+        rc = rtThreadAdopt(enmType, fFlags, 0, pszName);
+        Thread = RTThreadSelf();
+        Log(("RTThreadAdopt: %RTthrd %RTnthrd '%s' enmType=%d fFlags=%#x rc=%Rrc\n",
+             Thread, RTThreadNativeSelf(), pszName, enmType, fFlags, rc));
+    }
+    else
+        Log(("RTThreadAdopt: %RTthrd %RTnthrd '%s' enmType=%d fFlags=%#x - already adopted!\n",
+             Thread, RTThreadNativeSelf(), pszName, enmType, fFlags));
+
+    if (pThread)
+        *pThread = Thread;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTThreadAdopt);
+
+
+/**
+ * Get the thread handle of the current thread, automatically adopting alien
+ * threads.
+ *
+ * @returns Thread handle.
+ */
+RTDECL(RTTHREAD) RTThreadSelfAutoAdopt(void)
+{
+    RTTHREAD hSelf = RTThreadSelf();
+    if (RT_UNLIKELY(hSelf == NIL_RTTHREAD))
+        RTThreadAdopt(RTTHREADTYPE_DEFAULT, 0, NULL, &hSelf);
+    return hSelf;
+}
+RT_EXPORT_SYMBOL(RTThreadSelfAutoAdopt);
+
+#endif /* IN_RING3 */
+
+/**
+ * Allocates a per thread data structure and initializes the basic fields.
+ *
+ * @returns Pointer to per thread data structure.
+ *          This is reference once.
+ * @returns NULL on failure.
+ * @param   enmType     The thread type.
+ * @param   fFlags      The thread flags.
+ * @param   fIntFlags   The internal thread flags.
+ * @param   pszName     Pointer to the thread name.
+ */
+PRTTHREADINT rtThreadAlloc(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntFlags, const char *pszName)
+{
+    PRTTHREADINT pThread = (PRTTHREADINT)RTMemAllocZ(sizeof(RTTHREADINT));
+    if (pThread)
+    {
+        size_t cchName;
+        int rc;
+
+        pThread->Core.Key   = (void*)NIL_RTTHREAD;
+        pThread->u32Magic   = RTTHREADINT_MAGIC;
+        cchName = strlen(pszName);
+        if (cchName >= RTTHREAD_NAME_LEN)
+            cchName = RTTHREAD_NAME_LEN - 1;
+        memcpy(pThread->szName, pszName, cchName);
+        pThread->szName[cchName] = '\0';
+        pThread->cRefs           = 2 + !!(fFlags & RTTHREADFLAGS_WAITABLE); /* And extra reference if waitable. */
+        pThread->rc              = VERR_PROCESS_RUNNING; /** @todo get a better error code! */
+        pThread->enmType         = enmType;
+        pThread->fFlags          = fFlags;
+        pThread->fIntFlags       = fIntFlags;
+        pThread->enmState        = RTTHREADSTATE_INITIALIZING;
+        pThread->fReallySleeping = false;
+#ifdef IN_RING3
+        rtLockValidatorInitPerThread(&pThread->LockValidator);
+#endif
+#ifdef RT_WITH_ICONV_CACHE
+        rtStrIconvCacheInit(pThread);
+#endif
+        rc = RTSemEventMultiCreate(&pThread->EventUser);
+        if (RT_SUCCESS(rc))
+        {
+            rc = RTSemEventMultiCreate(&pThread->EventTerminated);
+            if (RT_SUCCESS(rc))
+                return pThread;
+            RTSemEventMultiDestroy(pThread->EventUser);
+        }
+        RTMemFree(pThread);
+    }
+    return NULL;
+}
+
+
+/**
+ * Insert the per thread data structure into the tree.
+ *
+ * This can be called from both the thread it self and the parent,
+ * thus it must handle insertion failures in a nice manner.
+ *
+ * @param   pThread         Pointer to thread structure allocated by rtThreadAlloc().
+ * @param   NativeThread    The native thread id.
+ */
+DECLHIDDEN(void) rtThreadInsert(PRTTHREADINT pThread, RTNATIVETHREAD NativeThread)
+{
+    Assert(pThread);
+    Assert(pThread->u32Magic == RTTHREADINT_MAGIC);
+
+    {
+        RT_THREAD_LOCK_RW();
+
+        /*
+         * Do not insert a terminated thread.
+         *
+         * This may happen if the thread finishes before the RTThreadCreate call
+         * gets this far. Since the OS may quickly reuse the native thread ID
+         * it should not be reinserted at this point.
+         */
+        if (rtThreadGetState(pThread) != RTTHREADSTATE_TERMINATED)
+        {
+            /*
+             * Before inserting we must check if there is a thread with this id
+             * in the tree already. We're racing parent and child on insert here
+             * so that the handle is valid in both ends when they return / start.
+             *
+             * If it's not ourself we find, it's a dead alien thread and we will
+             * unlink it from the tree. Alien threads will be released at this point.
+             */
+            PRTTHREADINT pThreadOther = (PRTTHREADINT)RTAvlPVGet(&g_ThreadTree, (void *)NativeThread);
+            if (pThreadOther != pThread)
+            {
+                bool fRc;
+                /* remove dead alien if any */
+                if (pThreadOther)
+                {
+                    AssertMsg(pThreadOther->fIntFlags & RTTHREADINT_FLAGS_ALIEN, ("%p:%s; %p:%s\n", pThread, pThread->szName, pThreadOther, pThreadOther->szName));
+                    ASMAtomicBitClear(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE_BIT);
+                    rtThreadRemoveLocked(pThreadOther);
+                    if (pThreadOther->fIntFlags & RTTHREADINT_FLAGS_ALIEN)
+                    rtThreadRelease(pThreadOther);
+                }
+
+                /* insert the thread */
+                ASMAtomicWritePtr(&pThread->Core.Key, (void *)NativeThread);
+                fRc = RTAvlPVInsert(&g_ThreadTree, &pThread->Core);
+                ASMAtomicOrU32(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE);
+                if (fRc)
+                    ASMAtomicIncU32(&g_cThreadInTree);
+
+                AssertReleaseMsg(fRc, ("Lock problem? %p (%RTnthrd) %s\n", pThread, NativeThread, pThread->szName));
+                NOREF(fRc);
+            }
+        }
+
+        RT_THREAD_UNLOCK_RW();
+    }
+}
+
+
+/**
+ * Removes the thread from the AVL tree, call owns the tree lock
+ * and has cleared the RTTHREADINT_FLAG_IN_TREE bit.
+ *
+ * @param   pThread     The thread to remove.
+ */
+static void rtThreadRemoveLocked(PRTTHREADINT pThread)
+{
+    PRTTHREADINT pThread2 = (PRTTHREADINT)RTAvlPVRemove(&g_ThreadTree, pThread->Core.Key);
+#if !defined(RT_OS_OS2) /** @todo this asserts for threads created by NSPR */
+    AssertMsg(pThread2 == pThread, ("%p(%s) != %p (%p/%s)\n", pThread2, pThread2  ? pThread2->szName : "<null>",
+                                    pThread, pThread->Core.Key, pThread->szName));
+#endif
+    if (pThread2)
+        ASMAtomicDecU32(&g_cThreadInTree);
+}
+
+
+/**
+ * Removes the thread from the AVL tree.
+ *
+ * @param   pThread     The thread to remove.
+ */
+static void rtThreadRemove(PRTTHREADINT pThread)
+{
+    RT_THREAD_LOCK_RW();
+    if (ASMAtomicBitTestAndClear(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE_BIT))
+        rtThreadRemoveLocked(pThread);
+    RT_THREAD_UNLOCK_RW();
+}
+
+
+/**
+ * Checks if a thread is alive or not.
+ *
+ * @returns true if the thread is alive (or we don't really know).
+ * @returns false if the thread has surely terminate.
+ */
+DECLINLINE(bool) rtThreadIsAlive(PRTTHREADINT pThread)
+{
+    return !(pThread->fIntFlags & RTTHREADINT_FLAGS_TERMINATED);
+}
+
+
+/**
+ * Gets a thread by it's native ID.
+ *
+ * @returns pointer to the thread structure.
+ * @returns NULL if not a thread IPRT knows.
+ * @param   NativeThread    The native thread id.
+ */
+DECLHIDDEN(PRTTHREADINT) rtThreadGetByNative(RTNATIVETHREAD NativeThread)
+{
+    PRTTHREADINT pThread;
+    /*
+     * Simple tree lookup.
+     */
+    RT_THREAD_LOCK_RD();
+    pThread = (PRTTHREADINT)RTAvlPVGet(&g_ThreadTree, (void *)NativeThread);
+    RT_THREAD_UNLOCK_RD();
+    return pThread;
+}
+
+
+/**
+ * Gets the per thread data structure for a thread handle.
+ *
+ * @returns Pointer to the per thread data structure for Thread.
+ *          The caller must release the thread using rtThreadRelease().
+ * @returns NULL if Thread was not found.
+ * @param   Thread      Thread id which structure is to be returned.
+ */
+DECLHIDDEN(PRTTHREADINT) rtThreadGet(RTTHREAD Thread)
+{
+    if (    Thread != NIL_RTTHREAD
+        &&  VALID_PTR(Thread))
+    {
+        PRTTHREADINT pThread = (PRTTHREADINT)Thread;
+        if (    pThread->u32Magic == RTTHREADINT_MAGIC
+            &&  pThread->cRefs > 0)
+        {
+            ASMAtomicIncU32(&pThread->cRefs);
+            return pThread;
+        }
+    }
+
+    AssertMsgFailed(("Thread=%RTthrd\n", Thread));
+    return NULL;
+}
+
+/**
+ * Release a per thread data structure.
+ *
+ * @returns New reference count.
+ * @param   pThread     The thread structure to release.
+ */
+DECLHIDDEN(uint32_t) rtThreadRelease(PRTTHREADINT pThread)
+{
+    uint32_t cRefs;
+
+    Assert(pThread);
+    if (pThread->cRefs >= 1)
+    {
+        cRefs = ASMAtomicDecU32(&pThread->cRefs);
+        if (!cRefs)
+            rtThreadDestroy(pThread);
+    }
+    else
+    {
+        cRefs = 0;
+        AssertFailed();
+    }
+    return cRefs;
+}
+
+
+/**
+ * Destroys the per thread data.
+ *
+ * @param   pThread     The thread to destroy.
+ */
+static void rtThreadDestroy(PRTTHREADINT pThread)
+{
+    RTSEMEVENTMULTI hEvt1, hEvt2;
+    /*
+     * Remove it from the tree and mark it as dead.
+     *
+     * Threads that has seen rtThreadTerminate and should already have been
+     * removed from the tree. There is probably no thread that  should
+     * require removing here. However, be careful making sure that cRefs
+     * isn't 0 if we do or we'll blow up because the strict locking code
+     * will be calling us back.
+     */
+    if (ASMBitTest(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE_BIT))
+    {
+        ASMAtomicIncU32(&pThread->cRefs);
+        rtThreadRemove(pThread);
+        ASMAtomicDecU32(&pThread->cRefs);
+    }
+
+    /*
+     * Invalidate the thread structure.
+     */
+#ifdef IN_RING3
+    rtLockValidatorSerializeDestructEnter();
+
+    rtLockValidatorDeletePerThread(&pThread->LockValidator);
+#endif
+#ifdef RT_WITH_ICONV_CACHE
+    rtStrIconvCacheDestroy(pThread);
+#endif
+    ASMAtomicXchgU32(&pThread->u32Magic, RTTHREADINT_MAGIC_DEAD);
+    ASMAtomicWritePtr(&pThread->Core.Key, (void *)NIL_RTTHREAD);
+    pThread->enmType         = RTTHREADTYPE_INVALID;
+    hEvt1    = pThread->EventUser;
+    pThread->EventUser       = NIL_RTSEMEVENTMULTI;
+    hEvt2    = pThread->EventTerminated;
+    pThread->EventTerminated = NIL_RTSEMEVENTMULTI;
+
+#ifdef IN_RING3
+    rtLockValidatorSerializeDestructLeave();
+#endif
+
+    /*
+     * Destroy semaphore resources and free the bugger.
+     */
+    RTSemEventMultiDestroy(hEvt1);
+    if (hEvt2 != NIL_RTSEMEVENTMULTI)
+        RTSemEventMultiDestroy(hEvt2);
+
+    rtThreadNativeDestroy(pThread);
+    RTMemFree(pThread);
+}
+
+
+/**
+ * Terminates the thread.
+ * Called by the thread wrapper function when the thread terminates.
+ *
+ * @param   pThread     The thread structure.
+ * @param   rc          The thread result code.
+ */
+DECLHIDDEN(void) rtThreadTerminate(PRTTHREADINT pThread, int rc)
+{
+    Assert(pThread->cRefs >= 1);
+
+#ifdef IPRT_WITH_GENERIC_TLS
+    /*
+     * Destroy TLS entries.
+     */
+    rtThreadTlsDestruction(pThread);
+#endif /* IPRT_WITH_GENERIC_TLS */
+
+    /*
+     * Set the rc, mark it terminated and signal anyone waiting.
+     */
+    pThread->rc = rc;
+    rtThreadSetState(pThread, RTTHREADSTATE_TERMINATED);
+    ASMAtomicOrU32(&pThread->fIntFlags, RTTHREADINT_FLAGS_TERMINATED);
+    if (pThread->EventTerminated != NIL_RTSEMEVENTMULTI)
+        RTSemEventMultiSignal(pThread->EventTerminated);
+
+    /*
+     * Remove the thread from the tree so that there will be no
+     * key clashes in the AVL tree and release our reference to ourself.
+     */
+    rtThreadRemove(pThread);
+    rtThreadRelease(pThread);
+}
+
+
+/**
+ * The common thread main function.
+ * This is called by rtThreadNativeMain().
+ *
+ * @returns The status code of the thread.
+ *          pThread is dereference by the thread before returning!
+ * @param   pThread         The thread structure.
+ * @param   NativeThread    The native thread id.
+ * @param   pszThreadName   The name of the thread (purely a dummy for backtrace).
+ */
+DECLCALLBACK(DECLHIDDEN(int)) rtThreadMain(PRTTHREADINT pThread, RTNATIVETHREAD NativeThread, const char *pszThreadName)
+{
+    int rc;
+    NOREF(pszThreadName);
+    rtThreadInsert(pThread, NativeThread);
+    Log(("rtThreadMain: Starting: pThread=%p NativeThread=%RTnthrd Name=%s pfnThread=%p pvUser=%p\n",
+         pThread, NativeThread, pThread->szName, pThread->pfnThread, pThread->pvUser));
+
+    /*
+     * Change the priority.
+     */
+    rc = rtThreadNativeSetPriority(pThread, pThread->enmType);
+#ifdef IN_RING3
+    AssertMsgRC(rc, ("Failed to set priority of thread %p (%RTnthrd / %s) to enmType=%d enmPriority=%d rc=%Rrc\n",
+                     pThread, NativeThread, pThread->szName, pThread->enmType, g_enmProcessPriority, rc));
+#else
+    AssertMsgRC(rc, ("Failed to set priority of thread %p (%RTnthrd / %s) to enmType=%d rc=%Rrc\n",
+                     pThread, NativeThread, pThread->szName, pThread->enmType, rc));
+#endif
+
+    /*
+     * Call thread function and terminate when it returns.
+     */
+    rtThreadSetState(pThread, RTTHREADSTATE_RUNNING);
+    rc = pThread->pfnThread(pThread, pThread->pvUser);
+
+    /*
+     * Paranoia checks for leftover resources.
+     */
+#ifdef RTSEMRW_STRICT
+    int32_t cWrite = ASMAtomicReadS32(&pThread->cWriteLocks);
+    Assert(!cWrite);
+    int32_t cRead = ASMAtomicReadS32(&pThread->cReadLocks);
+    Assert(!cRead);
+#endif
+
+    Log(("rtThreadMain: Terminating: rc=%d pThread=%p NativeThread=%RTnthrd Name=%s pfnThread=%p pvUser=%p\n",
+         rc, pThread, NativeThread, pThread->szName, pThread->pfnThread, pThread->pvUser));
+    rtThreadTerminate(pThread, rc);
+    return rc;
+}
+
+
+/**
+ * Create a new thread.
+ *
+ * @returns iprt status code.
+ * @param   pThread     Where to store the thread handle to the new thread. (optional)
+ * @param   pfnThread   The thread function.
+ * @param   pvUser      User argument.
+ * @param   cbStack     The size of the stack for the new thread.
+ *                      Use 0 for the default stack size.
+ * @param   enmType     The thread type. Used for deciding scheduling attributes
+ *                      of the thread.
+ * @param   fFlags      Flags of the RTTHREADFLAGS type (ORed together).
+ * @param   pszName     Thread name.
+ */
+RTDECL(int) RTThreadCreate(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack,
+                           RTTHREADTYPE enmType, unsigned fFlags, const char *pszName)
+{
+    int             rc;
+    PRTTHREADINT    pThreadInt;
+
+    LogFlow(("RTThreadCreate: pThread=%p pfnThread=%p pvUser=%p cbStack=%#x enmType=%d fFlags=%#x pszName=%p:{%s}\n",
+             pThread, pfnThread, pvUser, cbStack, enmType, fFlags, pszName, pszName));
+
+    /*
+     * Validate input.
+     */
+    if (!VALID_PTR(pThread) && pThread)
+    {
+        Assert(VALID_PTR(pThread));
+        return VERR_INVALID_PARAMETER;
+    }
+    if (!VALID_PTR(pfnThread))
+    {
+        Assert(VALID_PTR(pfnThread));
+        return VERR_INVALID_PARAMETER;
+    }
+    if (!pszName || !*pszName || strlen(pszName) >= RTTHREAD_NAME_LEN)
+    {
+        AssertMsgFailed(("pszName=%s (max len is %d because of logging)\n", pszName, RTTHREAD_NAME_LEN - 1));
+        return VERR_INVALID_PARAMETER;
+    }
+    if (fFlags & ~RTTHREADFLAGS_MASK)
+    {
+        AssertMsgFailed(("fFlags=%#x\n", fFlags));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    /*
+     * Allocate thread argument.
+     */
+    pThreadInt = rtThreadAlloc(enmType, fFlags, 0, pszName);
+    if (pThreadInt)
+    {
+        RTNATIVETHREAD NativeThread;
+
+        pThreadInt->pfnThread = pfnThread;
+        pThreadInt->pvUser    = pvUser;
+        pThreadInt->cbStack   = cbStack;
+
+        rc = rtThreadNativeCreate(pThreadInt, &NativeThread);
+        if (RT_SUCCESS(rc))
+        {
+            rtThreadInsert(pThreadInt, NativeThread);
+            rtThreadRelease(pThreadInt);
+            Log(("RTThreadCreate: Created thread %p (%p) %s\n", pThreadInt, NativeThread, pszName));
+            if (pThread)
+                *pThread = pThreadInt;
+            return VINF_SUCCESS;
+        }
+
+        pThreadInt->cRefs = 1;
+        rtThreadRelease(pThreadInt);
+    }
+    else
+        rc = VERR_NO_TMP_MEMORY;
+    LogFlow(("RTThreadCreate: Failed to create thread, rc=%Rrc\n", rc));
+    AssertReleaseRC(rc);
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTThreadCreate);
+
+
+/**
+ * Create a new thread.
+ *
+ * Same as RTThreadCreate except the name is given in the RTStrPrintfV form.
+ *
+ * @returns iprt status code.
+ * @param   pThread     See RTThreadCreate.
+ * @param   pfnThread   See RTThreadCreate.
+ * @param   pvUser      See RTThreadCreate.
+ * @param   cbStack     See RTThreadCreate.
+ * @param   enmType     See RTThreadCreate.
+ * @param   fFlags      See RTThreadCreate.
+ * @param   pszNameFmt  Thread name format.
+ * @param   va          Format arguments.
+ */
+RTDECL(int) RTThreadCreateV(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack,
+                            RTTHREADTYPE enmType, uint32_t fFlags, const char *pszNameFmt, va_list va)
+{
+    char szName[RTTHREAD_NAME_LEN * 2];
+    RTStrPrintfV(szName, sizeof(szName), pszNameFmt, va);
+    return RTThreadCreate(pThread, pfnThread, pvUser, cbStack, enmType, fFlags, szName);
+}
+RT_EXPORT_SYMBOL(RTThreadCreateV);
+
+
+/**
+ * Create a new thread.
+ *
+ * Same as RTThreadCreate except the name is given in the RTStrPrintf form.
+ *
+ * @returns iprt status code.
+ * @param   pThread     See RTThreadCreate.
+ * @param   pfnThread   See RTThreadCreate.
+ * @param   pvUser      See RTThreadCreate.
+ * @param   cbStack     See RTThreadCreate.
+ * @param   enmType     See RTThreadCreate.
+ * @param   fFlags      See RTThreadCreate.
+ * @param   pszNameFmt  Thread name format.
+ * @param   ...         Format arguments.
+ */
+RTDECL(int) RTThreadCreateF(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack,
+                            RTTHREADTYPE enmType, uint32_t fFlags, const char *pszNameFmt, ...)
+{
+    va_list va;
+    int rc;
+    va_start(va, pszNameFmt);
+    rc = RTThreadCreateV(pThread, pfnThread, pvUser, cbStack, enmType, fFlags, pszNameFmt, va);
+    va_end(va);
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTThreadCreateF);
+
+
+/**
+ * Gets the native thread id of a IPRT thread.
+ *
+ * @returns The native thread id.
+ * @param   Thread      The IPRT thread.
+ */
+RTDECL(RTNATIVETHREAD) RTThreadGetNative(RTTHREAD Thread)
+{
+    PRTTHREADINT pThread = rtThreadGet(Thread);
+    if (pThread)
+    {
+        RTNATIVETHREAD NativeThread = (RTNATIVETHREAD)pThread->Core.Key;
+        rtThreadRelease(pThread);
+        return NativeThread;
+    }
+    return NIL_RTNATIVETHREAD;
+}
+RT_EXPORT_SYMBOL(RTThreadGetNative);
+
+
+/**
+ * Gets the IPRT thread of a native thread.
+ *
+ * @returns The IPRT thread handle
+ * @returns NIL_RTTHREAD if not a thread known to IPRT.
+ * @param   NativeThread        The native thread handle/id.
+ */
+RTDECL(RTTHREAD) RTThreadFromNative(RTNATIVETHREAD NativeThread)
+{
+    PRTTHREADINT pThread = rtThreadGetByNative(NativeThread);
+    if (pThread)
+        return pThread;
+    return NIL_RTTHREAD;
+}
+RT_EXPORT_SYMBOL(RTThreadFromNative);
+
+
+/**
+ * Gets the name of the current thread thread.
+ *
+ * @returns Pointer to readonly name string.
+ * @returns NULL on failure.
+ */
+RTDECL(const char *) RTThreadSelfName(void)
+{
+    RTTHREAD Thread = RTThreadSelf();
+    if (Thread != NIL_RTTHREAD)
+    {
+        PRTTHREADINT pThread = rtThreadGet(Thread);
+        if (pThread)
+        {
+            const char *szName = pThread->szName;
+            rtThreadRelease(pThread);
+            return szName;
+        }
+    }
+    return NULL;
+}
+RT_EXPORT_SYMBOL(RTThreadSelfName);
+
+
+/**
+ * Gets the name of a thread.
+ *
+ * @returns Pointer to readonly name string.
+ * @returns NULL on failure.
+ * @param   Thread      Thread handle of the thread to query the name of.
+ */
+RTDECL(const char *) RTThreadGetName(RTTHREAD Thread)
+{
+    PRTTHREADINT pThread;
+    if (Thread == NIL_RTTHREAD)
+        return NULL;
+    pThread = rtThreadGet(Thread);
+    if (pThread)
+    {
+        const char *szName = pThread->szName;
+        rtThreadRelease(pThread);
+        return szName;
+    }
+    return NULL;
+}
+RT_EXPORT_SYMBOL(RTThreadGetName);
+
+
+/**
+ * Sets the name of a thread.
+ *
+ * @returns iprt status code.
+ * @param   Thread      Thread handle of the thread to query the name of.
+ * @param   pszName     The thread name.
+ */
+RTDECL(int) RTThreadSetName(RTTHREAD Thread, const char *pszName)
+{
+    /*
+     * Validate input.
+     */
+    PRTTHREADINT pThread;
+    size_t cchName = strlen(pszName);
+    if (cchName >= RTTHREAD_NAME_LEN)
+    {
+        AssertMsgFailed(("pszName=%s is too long, max is %d\n", pszName, RTTHREAD_NAME_LEN - 1));
+        return VERR_INVALID_PARAMETER;
+    }
+    pThread = rtThreadGet(Thread);
+    if (!pThread)
+        return VERR_INVALID_HANDLE;
+
+    /*
+     * Update the name.
+     */
+    pThread->szName[cchName] = '\0';    /* paranoia */
+    memcpy(pThread->szName, pszName, cchName);
+    rtThreadRelease(pThread);
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTThreadSetName);
+
+
+/**
+ * Checks if the specified thread is the main thread.
+ *
+ * @returns true if it is, false if it isn't.
+ *
+ * @param   hThread     The thread handle.
+ *
+ * @remarks This function may not return the correct value when rtR3Init was
+ *          called on a thread of the than the main one.  This could for
+ *          instance happen when the DLL/DYLIB/SO containing IPRT is dynamically
+ *          loaded at run time by a different thread.
+ */
+RTDECL(bool) RTThreadIsMain(RTTHREAD hThread)
+{
+    PRTTHREADINT pThread = rtThreadGet(hThread);
+    if (pThread)
+    {
+        bool fRc = !!(pThread->fIntFlags & RTTHREADINT_FLAGS_MAIN);
+        rtThreadRelease(pThread);
+        return fRc;
+    }
+    return false;
+}
+RT_EXPORT_SYMBOL(RTThreadIsMain);
+
+
+RTDECL(bool) RTThreadIsSelfAlive(void)
+{
+    if (g_frtThreadInitialized)
+    {
+        RTTHREAD hSelf = RTThreadSelf();
+        if (hSelf != NIL_RTTHREAD)
+        {
+            /*
+             * Inspect the thread state.  ASSUMES thread state order.
+             */
+            RTTHREADSTATE enmState = rtThreadGetState(hSelf);
+            if (   enmState >= RTTHREADSTATE_RUNNING
+                && enmState <= RTTHREADSTATE_END)
+                return true;
+        }
+    }
+    return false;
+}
+RT_EXPORT_SYMBOL(RTThreadIsSelfAlive);
+
+
+RTDECL(bool) RTThreadIsSelfKnown(void)
+{
+    if (g_frtThreadInitialized)
+    {
+        RTTHREAD hSelf = RTThreadSelf();
+        if (hSelf != NIL_RTTHREAD)
+            return true;
+    }
+    return false;
+}
+RT_EXPORT_SYMBOL(RTThreadIsSelfKnown);
+
+
+RTDECL(bool) RTThreadIsInitialized(void)
+{
+    return g_frtThreadInitialized;
+}
+RT_EXPORT_SYMBOL(RTThreadIsInitialized);
+
+
+/**
+ * Signal the user event.
+ *
+ * @returns     iprt status code.
+ */
+RTDECL(int) RTThreadUserSignal(RTTHREAD Thread)
+{
+    int             rc;
+    PRTTHREADINT    pThread = rtThreadGet(Thread);
+    if (pThread)
+    {
+        rc = RTSemEventMultiSignal(pThread->EventUser);
+        rtThreadRelease(pThread);
+    }
+    else
+        rc = VERR_INVALID_HANDLE;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTThreadUserSignal);
+
+
+/**
+ * Wait for the user event, resume on interruption.
+ *
+ * @returns     iprt status code.
+ * @param       Thread          The thread to wait for.
+ * @param       cMillies        The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
+ *                              an indefinite wait.
+ */
+RTDECL(int) RTThreadUserWait(RTTHREAD Thread, RTMSINTERVAL cMillies)
+{
+    int             rc;
+    PRTTHREADINT    pThread = rtThreadGet(Thread);
+    if (pThread)
+    {
+        rc = RTSemEventMultiWait(pThread->EventUser, cMillies);
+        rtThreadRelease(pThread);
+    }
+    else
+        rc = VERR_INVALID_HANDLE;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTThreadUserWait);
+
+
+/**
+ * Wait for the user event, return on interruption.
+ *
+ * @returns     iprt status code.
+ * @param       Thread          The thread to wait for.
+ * @param       cMillies        The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
+ *                              an indefinite wait.
+ */
+RTDECL(int) RTThreadUserWaitNoResume(RTTHREAD Thread, RTMSINTERVAL cMillies)
+{
+    int             rc;
+    PRTTHREADINT    pThread = rtThreadGet(Thread);
+    if (pThread)
+    {
+        rc = RTSemEventMultiWaitNoResume(pThread->EventUser, cMillies);
+        rtThreadRelease(pThread);
+    }
+    else
+        rc = VERR_INVALID_HANDLE;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTThreadUserWaitNoResume);
+
+
+/**
+ * Reset the user event.
+ *
+ * @returns     iprt status code.
+ * @param       Thread          The thread to reset.
+ */
+RTDECL(int) RTThreadUserReset(RTTHREAD Thread)
+{
+    int     rc;
+    PRTTHREADINT  pThread = rtThreadGet(Thread);
+    if (pThread)
+    {
+        rc = RTSemEventMultiReset(pThread->EventUser);
+        rtThreadRelease(pThread);
+    }
+    else
+        rc = VERR_INVALID_HANDLE;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTThreadUserReset);
+
+
+/**
+ * Wait for the thread to terminate.
+ *
+ * @returns     iprt status code.
+ * @param       Thread          The thread to wait for.
+ * @param       cMillies        The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
+ *                              an indefinite wait.
+ * @param       prc             Where to store the return code of the thread. Optional.
+ * @param       fAutoResume     Whether or not to resume the wait on VERR_INTERRUPTED.
+ */
+static int rtThreadWait(RTTHREAD Thread, RTMSINTERVAL cMillies, int *prc, bool fAutoResume)
+{
+    int rc = VERR_INVALID_HANDLE;
+    if (Thread != NIL_RTTHREAD)
+    {
+        PRTTHREADINT pThread = rtThreadGet(Thread);
+        if (pThread)
+        {
+            if (pThread->fFlags & RTTHREADFLAGS_WAITABLE)
+            {
+                if (fAutoResume)
+                    rc = RTSemEventMultiWait(pThread->EventTerminated, cMillies);
+                else
+                    rc = RTSemEventMultiWaitNoResume(pThread->EventTerminated, cMillies);
+                if (RT_SUCCESS(rc))
+                {
+                    if (prc)
+                        *prc = pThread->rc;
+
+                    /*
+                     * If the thread is marked as waitable, we'll do one additional
+                     * release in order to free up the thread structure (see how we
+                     * init cRef in rtThreadAlloc()).
+                     */
+                    if (ASMAtomicBitTestAndClear(&pThread->fFlags, RTTHREADFLAGS_WAITABLE_BIT))
+                    {
+                        rtThreadRelease(pThread);
+#ifdef IN_RING0
+                        /*
+                         * IPRT termination kludge. Call native code to make sure
+                         * the last thread is really out of IPRT to prevent it from
+                         * crashing after we destroyed the spinlock in rtThreadTerm.
+                         */
+                        if (   ASMAtomicReadU32(&g_cThreadInTree) == 1
+                            && ASMAtomicReadU32(&pThread->cRefs) > 1)
+                            rtThreadNativeWaitKludge(pThread);
+#endif
+                    }
+                }
+            }
+            else
+            {
+                rc = VERR_THREAD_NOT_WAITABLE;
+                AssertRC(rc);
+            }
+            rtThreadRelease(pThread);
+        }
+    }
+    return rc;
+}
+
+
+/**
+ * Wait for the thread to terminate, resume on interruption.
+ *
+ * @returns     iprt status code.
+ *              Will not return VERR_INTERRUPTED.
+ * @param       Thread          The thread to wait for.
+ * @param       cMillies        The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
+ *                              an indefinite wait.
+ * @param       prc             Where to store the return code of the thread. Optional.
+ */
+RTDECL(int) RTThreadWait(RTTHREAD Thread, RTMSINTERVAL cMillies, int *prc)
+{
+    int rc = rtThreadWait(Thread, cMillies, prc, true);
+    Assert(rc != VERR_INTERRUPTED);
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTThreadWait);
+
+
+/**
+ * Wait for the thread to terminate, return on interruption.
+ *
+ * @returns     iprt status code.
+ * @param       Thread          The thread to wait for.
+ * @param       cMillies        The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
+ *                              an indefinite wait.
+ * @param       prc             Where to store the return code of the thread. Optional.
+ */
+RTDECL(int) RTThreadWaitNoResume(RTTHREAD Thread, RTMSINTERVAL cMillies, int *prc)
+{
+    return rtThreadWait(Thread, cMillies, prc, false);
+}
+RT_EXPORT_SYMBOL(RTThreadWaitNoResume);
+
+
+/**
+ * Changes the type of the specified thread.
+ *
+ * @returns iprt status code.
+ * @param   Thread      The thread which type should be changed.
+ * @param   enmType     The new thread type.
+ */
+RTDECL(int) RTThreadSetType(RTTHREAD Thread, RTTHREADTYPE enmType)
+{
+    /*
+     * Validate input.
+     */
+    int     rc;
+    if (    enmType > RTTHREADTYPE_INVALID
+        &&  enmType < RTTHREADTYPE_END)
+    {
+        PRTTHREADINT pThread = rtThreadGet(Thread);
+        if (pThread)
+        {
+            if (rtThreadIsAlive(pThread))
+            {
+                /*
+                 * Do the job.
+                 */
+                RT_THREAD_LOCK_RW();
+                rc = rtThreadNativeSetPriority(pThread, enmType);
+                if (RT_SUCCESS(rc))
+                    ASMAtomicXchgSize(&pThread->enmType, enmType);
+                RT_THREAD_UNLOCK_RW();
+                if (RT_FAILURE(rc))
+                    Log(("RTThreadSetType: failed on thread %p (%s), rc=%Rrc!!!\n", Thread, pThread->szName, rc));
+            }
+            else
+                rc = VERR_THREAD_IS_DEAD;
+            rtThreadRelease(pThread);
+        }
+        else
+            rc = VERR_INVALID_HANDLE;
+    }
+    else
+    {
+        AssertMsgFailed(("enmType=%d\n", enmType));
+        rc = VERR_INVALID_PARAMETER;
+    }
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTThreadSetType);
+
+
+/**
+ * Gets the type of the specified thread.
+ *
+ * @returns The thread type.
+ * @returns RTTHREADTYPE_INVALID if the thread handle is invalid.
+ * @param   Thread      The thread in question.
+ */
+RTDECL(RTTHREADTYPE) RTThreadGetType(RTTHREAD Thread)
+{
+    RTTHREADTYPE enmType = RTTHREADTYPE_INVALID;
+    PRTTHREADINT pThread = rtThreadGet(Thread);
+    if (pThread)
+    {
+        enmType = pThread->enmType;
+        rtThreadRelease(pThread);
+    }
+    return enmType;
+}
+RT_EXPORT_SYMBOL(RTThreadGetType);
+
+#ifdef IN_RING3
+
+/**
+ * Recalculates scheduling attributes for the default process
+ * priority using the specified priority type for the calling thread.
+ *
+ * The scheduling attributes are targeted at threads and they are protected
+ * by the thread read-write semaphore, that's why RTProc is forwarding the
+ * operation to RTThread.
+ *
+ * @returns iprt status code.
+ * @remarks Will only work for strict builds.
+ */
+int rtThreadDoCalcDefaultPriority(RTTHREADTYPE enmType)
+{
+    RT_THREAD_LOCK_RW();
+    int rc = rtSchedNativeCalcDefaultPriority(enmType);
+    RT_THREAD_UNLOCK_RW();
+    return rc;
+}
+
+
+/**
+ * Thread enumerator - sets the priority of one thread.
+ *
+ * @returns 0 to continue.
+ * @returns !0 to stop. In our case a VERR_ code.
+ * @param   pNode   The thread node.
+ * @param   pvUser  The new priority.
+ */
+static DECLCALLBACK(int) rtThreadSetPriorityOne(PAVLPVNODECORE pNode, void *pvUser)
+{
+    PRTTHREADINT pThread = (PRTTHREADINT)pNode;
+    if (!rtThreadIsAlive(pThread))
+        return VINF_SUCCESS;
+    int rc = rtThreadNativeSetPriority(pThread, pThread->enmType);
+    if (RT_SUCCESS(rc)) /* hide any warnings */
+        return VINF_SUCCESS;
+    NOREF(pvUser);
+    return rc;
+}
+
+
+/**
+ * Attempts to alter the priority of the current process.
+ *
+ * The scheduling attributes are targeted at threads and they are protected
+ * by the thread read-write semaphore, that's why RTProc is forwarding the
+ * operation to RTThread. This operation also involves updating all thread
+ * which is much faster done from RTThread.
+ *
+ * @returns iprt status code.
+ * @param   enmPriority     The new priority.
+ */
+DECLHIDDEN(int) rtThreadDoSetProcPriority(RTPROCPRIORITY enmPriority)
+{
+    LogFlow(("rtThreadDoSetProcPriority: enmPriority=%d\n", enmPriority));
+
+    /*
+     * First validate that we're allowed by the OS to use all the
+     * scheduling attributes defined by the specified process priority.
+     */
+    RT_THREAD_LOCK_RW();
+    int rc = rtProcNativeSetPriority(enmPriority);
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Update the priority of existing thread.
+         */
+        rc = RTAvlPVDoWithAll(&g_ThreadTree, true, rtThreadSetPriorityOne, NULL);
+        if (RT_SUCCESS(rc))
+            ASMAtomicXchgSize(&g_enmProcessPriority, enmPriority);
+        else
+        {
+            /*
+             * Failed, restore the priority.
+             */
+            rtProcNativeSetPriority(g_enmProcessPriority);
+            RTAvlPVDoWithAll(&g_ThreadTree, true, rtThreadSetPriorityOne, NULL);
+        }
+    }
+    RT_THREAD_UNLOCK_RW();
+    LogFlow(("rtThreadDoSetProcPriority: returns %Rrc\n", rc));
+    return rc;
+}
+
+
+/**
+ * Change the thread state to blocking.
+ *
+ * @param   hThread         The current thread.
+ * @param   enmState        The sleep state.
+ * @param   fReallySleeping Really going to sleep now.
+ */
+RTDECL(void) RTThreadBlocking(RTTHREAD hThread, RTTHREADSTATE enmState, bool fReallySleeping)
+{
+    Assert(RTTHREAD_IS_SLEEPING(enmState));
+    PRTTHREADINT pThread = hThread;
+    if (pThread != NIL_RTTHREAD)
+    {
+        Assert(pThread == RTThreadSelf());
+        if (rtThreadGetState(pThread) == RTTHREADSTATE_RUNNING)
+            rtThreadSetState(pThread, enmState);
+        ASMAtomicWriteBool(&pThread->fReallySleeping, fReallySleeping);
+    }
+}
+RT_EXPORT_SYMBOL(RTThreadBlocking);
+
+
+/**
+ * Unblocks a thread.
+ *
+ * This function is paired with rtThreadBlocking.
+ *
+ * @param   hThread     The current thread.
+ * @param   enmCurState The current state, used to check for nested blocking.
+ *                      The new state will be running.
+ */
+RTDECL(void) RTThreadUnblocked(RTTHREAD hThread, RTTHREADSTATE enmCurState)
+{
+    PRTTHREADINT pThread = hThread;
+    if (pThread != NIL_RTTHREAD)
+    {
+        Assert(pThread == RTThreadSelf());
+        ASMAtomicWriteBool(&pThread->fReallySleeping, false);
+
+        RTTHREADSTATE enmActualState = rtThreadGetState(pThread);
+        if (enmActualState == enmCurState)
+        {
+            rtThreadSetState(pThread, RTTHREADSTATE_RUNNING);
+            if (   pThread->LockValidator.pRec
+                && pThread->LockValidator.enmRecState == enmCurState)
+                ASMAtomicWriteNullPtr(&pThread->LockValidator.pRec);
+        }
+        /* This is a bit ugly... :-/ */
+        else if (   (   enmActualState == RTTHREADSTATE_TERMINATED
+                     || enmActualState == RTTHREADSTATE_INITIALIZING)
+                 && pThread->LockValidator.pRec)
+            ASMAtomicWriteNullPtr(&pThread->LockValidator.pRec);
+        Assert(   pThread->LockValidator.pRec == NULL
+               || RTTHREAD_IS_SLEEPING(enmActualState));
+    }
+}
+RT_EXPORT_SYMBOL(RTThreadUnblocked);
+
+
+/**
+ * Get the current thread state.
+ *
+ * @returns The thread state.
+ * @param   hThread         The thread.
+ */
+RTDECL(RTTHREADSTATE) RTThreadGetState(RTTHREAD hThread)
+{
+    RTTHREADSTATE   enmState = RTTHREADSTATE_INVALID;
+    PRTTHREADINT    pThread  = rtThreadGet(hThread);
+    if (pThread)
+    {
+        enmState = rtThreadGetState(pThread);
+        rtThreadRelease(pThread);
+    }
+    return enmState;
+}
+RT_EXPORT_SYMBOL(RTThreadGetState);
+
+
+RTDECL(RTTHREADSTATE) RTThreadGetReallySleeping(RTTHREAD hThread)
+{
+    RTTHREADSTATE   enmState = RTTHREADSTATE_INVALID;
+    PRTTHREADINT    pThread  = rtThreadGet(hThread);
+    if (pThread)
+    {
+        enmState = rtThreadGetState(pThread);
+        if (!ASMAtomicUoReadBool(&pThread->fReallySleeping))
+            enmState = RTTHREADSTATE_RUNNING;
+        rtThreadRelease(pThread);
+    }
+    return enmState;
+}
+RT_EXPORT_SYMBOL(RTThreadGetReallySleeping);
+
+
+/**
+ * Translate a thread state into a string.
+ *
+ * @returns Pointer to a read-only string containing the state name.
+ * @param   enmState            The state.
+ */
+RTDECL(const char *) RTThreadStateName(RTTHREADSTATE enmState)
+{
+    switch (enmState)
+    {
+        case RTTHREADSTATE_INVALID:         return "INVALID";
+        case RTTHREADSTATE_INITIALIZING:    return "INITIALIZING";
+        case RTTHREADSTATE_TERMINATED:      return "TERMINATED";
+        case RTTHREADSTATE_RUNNING:         return "RUNNING";
+        case RTTHREADSTATE_CRITSECT:        return "CRITSECT";
+        case RTTHREADSTATE_EVENT:           return "EVENT";
+        case RTTHREADSTATE_EVENT_MULTI:     return "EVENT_MULTI";
+        case RTTHREADSTATE_FAST_MUTEX:      return "FAST_MUTEX";
+        case RTTHREADSTATE_MUTEX:           return "MUTEX";
+        case RTTHREADSTATE_RW_READ:         return "RW_READ";
+        case RTTHREADSTATE_RW_WRITE:        return "RW_WRITE";
+        case RTTHREADSTATE_SLEEP:           return "SLEEP";
+        case RTTHREADSTATE_SPIN_MUTEX:      return "SPIN_MUTEX";
+        default:                            return "UnknownThreadState";
+    }
+}
+RT_EXPORT_SYMBOL(RTThreadStateName);
+
+#endif /* IN_RING3 */
+#ifdef IPRT_WITH_GENERIC_TLS
+
+/**
+ * Thread enumerator - clears a TLS entry.
+ *
+ * @returns 0.
+ * @param   pNode   The thread node.
+ * @param   pvUser  The TLS index.
+ */
+static DECLCALLBACK(int) rtThreadClearTlsEntryCallback(PAVLPVNODECORE pNode, void *pvUser)
+{
+    PRTTHREADINT pThread = (PRTTHREADINT)pNode;
+    RTTLS iTls = (RTTLS)(uintptr_t)pvUser;
+    ASMAtomicWriteNullPtr(&pThread->apvTlsEntries[iTls]);
+    return 0;
+}
+
+
+/**
+ * Helper for the generic TLS implementation that clears a given TLS
+ * entry on all threads.
+ *
+ * @param   iTls        The TLS entry. (valid)
+ */
+DECLHIDDEN(void) rtThreadClearTlsEntry(RTTLS iTls)
+{
+    RT_THREAD_LOCK_RD();
+    RTAvlPVDoWithAll(&g_ThreadTree, true /* fFromLeft*/, rtThreadClearTlsEntryCallback, (void *)(uintptr_t)iTls);
+    RT_THREAD_UNLOCK_RD();
+}
+
+#endif /* IPRT_WITH_GENERIC_TLS */
+
+
+#if defined(RT_OS_WINDOWS) && defined(IN_RING3)
+
+/**
+ * Thread enumeration callback for RTThreadNameThreads
+ */
+static DECLCALLBACK(int) rtThreadNameThreadCallback(PAVLPVNODECORE pNode, void *pvUser)
+{
+    PRTTHREADINT pThread = (PRTTHREADINT)pNode;
+    rtThreadNativeInformDebugger(pThread);
+    RT_NOREF_PV(pvUser);
+    return 0;
+}
+
+/**
+ * A function that can be called from the windows debugger to get the names of
+ * all threads when attaching to a process.
+ *
+ * Usage: .call VBoxRT!RTThreadNameThreads()
+ *
+ * @returns 0
+ * @remarks Do not call from source code as it skips locks.
+ */
+extern "C" RTDECL(int) RTThreadNameThreads(void);
+RTDECL(int) RTThreadNameThreads(void)
+{
+    return RTAvlPVDoWithAll(&g_ThreadTree, true /* fFromLeft*/, rtThreadNameThreadCallback, NULL);
+}
+
+#endif
diff --git a/ubuntu/vbox/vboxguest/common/string/RTStrCopy.c b/ubuntu/vbox/vboxguest/common/string/RTStrCopy.c
new file mode 100644 (file)
index 0000000..74e3116
--- /dev/null
@@ -0,0 +1,52 @@
+/* $Id: RTStrCopy.cpp $ */
+/** @file
+ * IPRT - RTStrCopy.
+ */
+
+/*
+ * Copyright (C) 2010-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/string.h>
+#include "internal/iprt.h"
+
+
+RTDECL(int) RTStrCopy(char *pszDst, size_t cbDst, const char *pszSrc)
+{
+    size_t cchSrc = strlen(pszSrc);
+    if (RT_LIKELY(cchSrc < cbDst))
+    {
+        memcpy(pszDst, pszSrc, cchSrc + 1);
+        return VINF_SUCCESS;
+    }
+
+    if (cbDst != 0)
+    {
+        memcpy(pszDst, pszSrc, cbDst - 1);
+        pszDst[cbDst - 1] = '\0';
+    }
+    return VERR_BUFFER_OVERFLOW;
+}
+RT_EXPORT_SYMBOL(RTStrCopy);
+
diff --git a/ubuntu/vbox/vboxguest/common/string/RTStrCopyEx.c b/ubuntu/vbox/vboxguest/common/string/RTStrCopyEx.c
new file mode 100644 (file)
index 0000000..eac00f5
--- /dev/null
@@ -0,0 +1,54 @@
+/* $Id: RTStrCopyEx.cpp $ */
+/** @file
+ * IPRT - RTStrCopyEx.
+ */
+
+/*
+ * Copyright (C) 2010-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/string.h>
+#include "internal/iprt.h"
+
+
+RTDECL(int) RTStrCopyEx(char *pszDst, size_t cbDst, const char *pszSrc, size_t cchMaxSrc)
+{
+    const char *pszSrcEol = RTStrEnd(pszSrc, cchMaxSrc);
+    size_t      cchSrc    = pszSrcEol ? (size_t)(pszSrcEol - pszSrc) : cchMaxSrc;
+    if (RT_LIKELY(cchSrc < cbDst))
+    {
+        memcpy(pszDst, pszSrc, cchSrc);
+        pszDst[cchSrc] = '\0';
+        return VINF_SUCCESS;
+    }
+
+    if (cbDst != 0)
+    {
+        memcpy(pszDst, pszSrc, cbDst - 1);
+        pszDst[cbDst - 1] = '\0';
+    }
+    return VERR_BUFFER_OVERFLOW;
+}
+RT_EXPORT_SYMBOL(RTStrCopyEx);
+
diff --git a/ubuntu/vbox/vboxguest/common/string/RTStrCopyP.c b/ubuntu/vbox/vboxguest/common/string/RTStrCopyP.c
new file mode 100644 (file)
index 0000000..b850390
--- /dev/null
@@ -0,0 +1,58 @@
+/* $Id: RTStrCopyP.cpp $ */
+/** @file
+ * IPRT - RTStrCopyP.
+ */
+
+/*
+ * Copyright (C) 2010-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/string.h>
+#include "internal/iprt.h"
+
+
+RTDECL(int) RTStrCopyP(char **ppszDst, size_t *pcbDst, const char *pszSrc)
+{
+    size_t const    cchSrc = strlen(pszSrc);
+    size_t const    cbDst  = *pcbDst;
+    char           *pszDst = *ppszDst;
+    if (RT_LIKELY(cchSrc < cbDst))
+    {
+        memcpy(pszDst, pszSrc, cchSrc + 1);
+        *ppszDst = pszDst += cchSrc;
+        *pcbDst -= cchSrc;
+        return VINF_SUCCESS;
+    }
+
+    if (cbDst != 0)
+    {
+        memcpy(*ppszDst, pszSrc, cbDst - 1);
+        *ppszDst = pszDst += cbDst - 1;
+        *pszDst  = '\0';
+        *pcbDst  = 1;
+    }
+    return VERR_BUFFER_OVERFLOW;
+}
+RT_EXPORT_SYMBOL(RTStrCopyP);
+
diff --git a/ubuntu/vbox/vboxguest/common/string/strformat.c b/ubuntu/vbox/vboxguest/common/string/strformat.c
new file mode 100644 (file)
index 0000000..a09ed6a
--- /dev/null
@@ -0,0 +1,857 @@
+/* $Id: strformat.cpp $ */
+/** @file
+ * IPRT - String Formatter.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Defined Constants                                                                                                            *
+*********************************************************************************************************************************/
+#define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
+/*#define MAX(a, b)  ((a) >= (b) ? (a) : (b))
+#define MIN(a, b)  ((a) < (b) ? (a) : (b)) */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_STRING
+#include <iprt/string.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#ifdef IN_RING3
+# include <iprt/alloc.h>
+# include <iprt/err.h>
+# include <iprt/uni.h>
+#endif
+#include <iprt/string.h>
+#include <iprt/stdarg.h>
+#include "internal/string.h"
+
+/* Wrappers for converting to iprt facilities. */
+#define SSToDS(ptr)     ptr
+#define kASSERT         Assert
+#define KENDIAN_LITTLE  1
+#define KENDIAN         KENDIAN_LITTLE
+#define KSIZE           size_t
+typedef struct
+{
+    uint32_t    ulLo;
+    uint32_t    ulHi;
+} KSIZE64;
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+static unsigned _strnlen(const char *psz, unsigned cchMax);
+static unsigned _strnlenUtf16(PCRTUTF16 pwsz, unsigned cchMax);
+static int rtStrFormatNumber(char *psz, KSIZE64 ullValue, unsigned int uiBase, signed int cchWidth, signed int cchPrecision, unsigned int fFlags);
+
+
+/**
+ * Finds the length of a string up to cchMax.
+ * @returns   Length.
+ * @param     psz     Pointer to string.
+ * @param     cchMax  Max length.
+ */
+static unsigned _strnlen(const char *psz, unsigned cchMax)
+{
+    const char *pszC = psz;
+
+    while (cchMax-- > 0 &&  *psz != '\0')
+        psz++;
+
+    return (unsigned)(psz - pszC);
+}
+
+
+/**
+ * Finds the length of a string up to cchMax.
+ * @returns   Length.
+ * @param     pwsz    Pointer to string.
+ * @param     cchMax  Max length.
+ */
+static unsigned _strnlenUtf16(PCRTUTF16 pwsz, unsigned cchMax)
+{
+#ifdef IN_RING3
+    unsigned cwc = 0;
+    while (cchMax-- > 0)
+    {
+        RTUNICP cp;
+        int rc = RTUtf16GetCpEx(&pwsz, &cp);
+        AssertRC(rc);
+        if (RT_FAILURE(rc) || !cp)
+            break;
+        cwc++;
+    }
+    return cwc;
+#else   /* !IN_RING3 */
+    PCRTUTF16    pwszC = pwsz;
+
+    while (cchMax-- > 0 &&  *pwsz != '\0')
+        pwsz++;
+
+    return (unsigned)(pwsz - pwszC);
+#endif  /* !IN_RING3 */
+}
+
+
+/**
+ * Finds the length of a string up to cchMax.
+ * @returns   Length.
+ * @param     pusz    Pointer to string.
+ * @param     cchMax  Max length.
+ */
+static unsigned _strnlenUni(PCRTUNICP pusz, unsigned cchMax)
+{
+    PCRTUNICP   puszC = pusz;
+
+    while (cchMax-- > 0 && *pusz != '\0')
+        pusz++;
+
+    return (unsigned)(pusz - puszC);
+}
+
+
+/**
+ * Formats an integer number according to the parameters.
+ *
+ * @returns   Length of the formatted number.
+ * @param     psz            Pointer to output string buffer of sufficient size.
+ * @param     u64Value       Value to format.
+ * @param     uiBase         Number representation base.
+ * @param     cchWidth       Width.
+ * @param     cchPrecision   Precision.
+ * @param     fFlags         Flags (NTFS_*).
+ */
+RTDECL(int) RTStrFormatNumber(char *psz, uint64_t u64Value, unsigned int uiBase, signed int cchWidth, signed int cchPrecision,
+                              unsigned int fFlags)
+{
+    return rtStrFormatNumber(psz, *(KSIZE64 *)(void *)&u64Value, uiBase, cchWidth, cchPrecision, fFlags);
+}
+RT_EXPORT_SYMBOL(RTStrFormatNumber);
+
+
+
+/**
+ * Formats an integer number according to the parameters.
+ *
+ * @returns   Length of the number.
+ * @param     psz            Pointer to output string.
+ * @param     ullValue       Value. Using the high part is optional.
+ * @param     uiBase         Number representation base.
+ * @param     cchWidth       Width
+ * @param     cchPrecision   Precision.
+ * @param     fFlags         Flags (NTFS_*).
+ */
+static int rtStrFormatNumber(char *psz, KSIZE64 ullValue, unsigned int uiBase, signed int cchWidth, signed int cchPrecision,
+                             unsigned int fFlags)
+{
+    const char     *pachDigits = "0123456789abcdef";
+    char           *pszStart = psz;
+    int             cchMax;
+    int             cchValue;
+    unsigned long   ul;
+    int             i;
+    int             j;
+
+    /*
+     * Validate and adjust input...
+     */
+    Assert(uiBase >= 2 && uiBase <= 16);
+    if (fFlags & RTSTR_F_CAPITAL)
+        pachDigits = "0123456789ABCDEF";
+    if (fFlags & RTSTR_F_LEFT)
+        fFlags &= ~RTSTR_F_ZEROPAD;
+    if (    (fFlags & RTSTR_F_THOUSAND_SEP)
+        &&  (   uiBase != 10
+             || (fFlags & RTSTR_F_ZEROPAD))) /** @todo implement RTSTR_F_ZEROPAD + RTSTR_F_THOUSAND_SEP. */
+        fFlags &= ~RTSTR_F_THOUSAND_SEP;
+
+    /*
+     * Determine value length
+     */
+    cchValue = 0;
+    if (ullValue.ulHi || (fFlags & RTSTR_F_64BIT))
+    {
+        uint64_t    u64 = *(uint64_t *)(void *)&ullValue;
+        if ((fFlags & RTSTR_F_VALSIGNED) && (ullValue.ulHi & 0x80000000))
+            u64 = -(int64_t)u64;
+        do
+        {
+            cchValue++;
+            u64 /= uiBase;
+        } while (u64);
+    }
+    else
+    {
+        ul = (fFlags & RTSTR_F_VALSIGNED) && (ullValue.ulLo & 0x80000000) ? -(int32_t)ullValue.ulLo : ullValue.ulLo;
+        do
+        {
+            cchValue++;
+            ul /= uiBase;
+        } while (ul);
+    }
+    if (fFlags & RTSTR_F_THOUSAND_SEP)
+    {
+        if (cchValue <= 3)
+            fFlags &= ~RTSTR_F_THOUSAND_SEP;
+        else
+            cchValue += cchValue / 3 - (cchValue % 3 == 0);
+    }
+
+    /*
+     * Sign (+/-).
+     */
+    i = 0;
+    if (fFlags & RTSTR_F_VALSIGNED)
+    {
+        if ((ullValue.ulHi || (fFlags & RTSTR_F_64BIT) ? ullValue.ulHi : ullValue.ulLo) & 0x80000000)
+        {
+            ullValue.ulLo = -(int32_t)ullValue.ulLo;
+            if (ullValue.ulHi)
+                ullValue.ulHi = ~ullValue.ulHi;
+            psz[i++] = '-';
+        }
+        else if (fFlags & (RTSTR_F_PLUS | RTSTR_F_BLANK))
+            psz[i++] = (char)(fFlags & RTSTR_F_PLUS ? '+' : ' ');
+    }
+
+    /*
+     * Special (0/0x).
+     */
+    if ((fFlags & RTSTR_F_SPECIAL) && (uiBase % 8) == 0)
+    {
+        psz[i++] = '0';
+        if (uiBase == 16)
+            psz[i++] = (char)(fFlags & RTSTR_F_CAPITAL ? 'X' : 'x');
+    }
+
+    /*
+     * width - only if ZEROPAD
+     */
+    cchMax    = 64 - (cchValue + i + 1);   /* HACK! 64 bytes seems to be the usual buffer size... */
+    cchWidth -= i + cchValue;
+    if (fFlags & RTSTR_F_ZEROPAD)
+        while (--cchWidth >= 0 && i < cchMax)
+        {
+            AssertBreak(i < cchMax);
+            psz[i++] = '0';
+            cchPrecision--;
+        }
+    else if (!(fFlags & RTSTR_F_LEFT) && cchWidth > 0)
+    {
+        AssertStmt(cchWidth < cchMax, cchWidth = cchMax - 1);
+        for (j = i - 1; j >= 0; j--)
+            psz[cchWidth + j] = psz[j];
+        for (j = 0; j < cchWidth; j++)
+            psz[j] = ' ';
+        i += cchWidth;
+    }
+
+    /*
+     * precision
+     */
+    while (--cchPrecision >= cchValue)
+    {
+        AssertBreak(i < cchMax);
+        psz[i++] = '0';
+    }
+
+    psz += i;
+
+    /*
+     * write number - not good enough but it works
+     */
+    psz += cchValue;
+    i = -1;
+    if (ullValue.ulHi || (fFlags & RTSTR_F_64BIT))
+    {
+        uint64_t    u64 = *(uint64_t *)(void *)&ullValue;
+        if (fFlags & RTSTR_F_THOUSAND_SEP)
+        {
+            do
+            {
+                if ((-i - 1) % 4 == 3)
+                    psz[i--] = ' ';
+                psz[i--] = pachDigits[u64 % uiBase];
+                u64 /= uiBase;
+            } while (u64);
+        }
+        else
+        {
+            do
+            {
+                psz[i--] = pachDigits[u64 % uiBase];
+                u64 /= uiBase;
+            } while (u64);
+        }
+    }
+    else
+    {
+        ul = (fFlags & RTSTR_F_VALSIGNED) && (ullValue.ulLo & 0x80000000) ? -(int32_t)ullValue.ulLo : ullValue.ulLo;
+        if (fFlags & RTSTR_F_THOUSAND_SEP)
+        {
+            do
+            {
+                if ((-i - 1) % 4 == 3)
+                    psz[i--] = ' ';
+                psz[i--] = pachDigits[ul % uiBase];
+                ul /= uiBase;
+            } while (ul);
+        }
+        else
+        {
+            do
+            {
+                psz[i--] = pachDigits[ul % uiBase];
+                ul /= uiBase;
+            } while (ul);
+        }
+    }
+
+    /*
+     * width if RTSTR_F_LEFT
+     */
+    if (fFlags & RTSTR_F_LEFT)
+        while (--cchWidth >= 0)
+            *psz++ = ' ';
+
+    *psz = '\0';
+    return (unsigned)(psz - pszStart);
+}
+
+
+/**
+ * Partial implementation of a printf like formatter.
+ * It doesn't do everything correct, and there is no floating point support.
+ * However, it supports custom formats by the means of a format callback.
+ *
+ * @returns number of bytes formatted.
+ * @param   pfnOutput   Output worker.
+ *                      Called in two ways. Normally with a string an it's length.
+ *                      For termination, it's called with NULL for string, 0 for length.
+ * @param   pvArgOutput Argument to the output worker.
+ * @param   pfnFormat   Custom format worker.
+ * @param   pvArgFormat Argument to the format worker.
+ * @param   pszFormat   Format string.
+ * @param   InArgs      Argument list.
+ */
+RTDECL(size_t) RTStrFormatV(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, PFNSTRFORMAT pfnFormat, void *pvArgFormat,
+                            const char *pszFormat, va_list InArgs)
+{
+    char        szTmp[64]; /* Worker functions assumes 64 byte buffer! Ugly but faster. */
+    va_list     args;
+    KSIZE       cch = 0;
+    const char *pszStartOutput = pszFormat;
+
+    va_copy(args, InArgs); /* make a copy so we can reference it (AMD64 / gcc). */
+
+    while (*pszFormat != '\0')
+    {
+        if (*pszFormat == '%')
+        {
+            /* output pending string. */
+            if (pszStartOutput != pszFormat)
+                cch += pfnOutput(pvArgOutput, pszStartOutput, pszFormat - pszStartOutput);
+
+            /* skip '%' */
+            pszFormat++;
+            if (*pszFormat == '%')    /* '%%'-> '%' */
+                pszStartOutput = pszFormat++;
+            else
+            {
+                unsigned int fFlags = 0;
+                int          cchWidth = -1;
+                int          cchPrecision = -1;
+                unsigned int uBase = 10;
+                char         chArgSize;
+
+                /* flags */
+                for (;;)
+                {
+                    switch (*pszFormat++)
+                    {
+                        case '#':   fFlags |= RTSTR_F_SPECIAL;      continue;
+                        case '-':   fFlags |= RTSTR_F_LEFT;         continue;
+                        case '+':   fFlags |= RTSTR_F_PLUS;         continue;
+                        case ' ':   fFlags |= RTSTR_F_BLANK;        continue;
+                        case '0':   fFlags |= RTSTR_F_ZEROPAD;      continue;
+                        case '\'':  fFlags |= RTSTR_F_THOUSAND_SEP; continue;
+                    }
+                    pszFormat--;
+                    break;
+                }
+
+                /* width */
+                if (ISDIGIT(*pszFormat))
+                {
+                    for (cchWidth = 0; ISDIGIT(*pszFormat); pszFormat++)
+                    {
+                        cchWidth *= 10;
+                        cchWidth += *pszFormat - '0';
+                    }
+                    fFlags |= RTSTR_F_WIDTH;
+                }
+                else if (*pszFormat == '*')
+                {
+                    pszFormat++;
+                    cchWidth = va_arg(args, int);
+                    if (cchWidth < 0)
+                    {
+                        cchWidth = -cchWidth;
+                        fFlags |= RTSTR_F_LEFT;
+                    }
+                    fFlags |= RTSTR_F_WIDTH;
+                }
+
+                /* precision */
+                if (*pszFormat == '.')
+                {
+                    pszFormat++;
+                    if (ISDIGIT(*pszFormat))
+                    {
+                        for (cchPrecision = 0; ISDIGIT(*pszFormat); pszFormat++)
+                        {
+                            cchPrecision *= 10;
+                            cchPrecision += *pszFormat - '0';
+                        }
+
+                    }
+                    else if (*pszFormat == '*')
+                    {
+                        pszFormat++;
+                        cchPrecision = va_arg(args, int);
+                    }
+                    if (cchPrecision < 0)
+                        cchPrecision = 0;
+                    fFlags |= RTSTR_F_PRECISION;
+                }
+
+                /*
+                 * Argument size.
+                 */
+                chArgSize = *pszFormat;
+                switch (chArgSize)
+                {
+                    default:
+                        chArgSize = 0;
+                        break;
+
+                    case 'z':
+                    case 'L':
+                    case 'j':
+                    case 't':
+                        pszFormat++;
+                        break;
+
+                    case 'l':
+                        pszFormat++;
+                        if (*pszFormat == 'l')
+                        {
+                            chArgSize = 'L';
+                            pszFormat++;
+                        }
+                        break;
+
+                    case 'h':
+                        pszFormat++;
+                        if (*pszFormat == 'h')
+                        {
+                            chArgSize = 'H';
+                            pszFormat++;
+                        }
+                        break;
+
+                    case 'I': /* Used by Win32/64 compilers. */
+                        if (   pszFormat[1] == '6'
+                            && pszFormat[2] == '4')
+                        {
+                            pszFormat += 3;
+                            chArgSize = 'L';
+                        }
+                        else if (   pszFormat[1] == '3'
+                                 && pszFormat[2] == '2')
+                        {
+                            pszFormat += 3;
+                            chArgSize = 0;
+                        }
+                        else
+                        {
+                            pszFormat += 1;
+                            chArgSize = 'j';
+                        }
+                        break;
+
+                    case 'q': /* Used on BSD platforms. */
+                        pszFormat++;
+                        chArgSize = 'L';
+                        break;
+                }
+
+                /*
+                 * The type.
+                 */
+                switch (*pszFormat++)
+                {
+                    /* char */
+                    case 'c':
+                    {
+                        if (!(fFlags & RTSTR_F_LEFT))
+                            while (--cchWidth > 0)
+                                cch += pfnOutput(pvArgOutput, " ", 1);
+
+                        szTmp[0] = (char)va_arg(args, int);
+                        szTmp[1] = '\0';                     /* Some output functions wants terminated strings. */
+                        cch += pfnOutput(pvArgOutput, SSToDS(&szTmp[0]), 1);
+
+                        while (--cchWidth > 0)
+                            cch += pfnOutput(pvArgOutput, " ", 1);
+                        break;
+                    }
+
+                    case 'S':   /* Legacy, conversion done by streams now. */
+                    case 's':
+                    {
+                        if (chArgSize == 'l')
+                        {
+                            /* utf-16 -> utf-8 */
+                            int         cchStr;
+                            PCRTUTF16   pwszStr = va_arg(args, PRTUTF16);
+
+                            if (!VALID_PTR(pwszStr))
+                            {
+                                static RTUTF16  s_wszNull[] = {'<', 'N', 'U', 'L', 'L', '>', '\0' };
+                                pwszStr = s_wszNull;
+                            }
+                            cchStr = _strnlenUtf16(pwszStr, (unsigned)cchPrecision);
+                            if (!(fFlags & RTSTR_F_LEFT))
+                                while (--cchWidth >= cchStr)
+                                    cch += pfnOutput(pvArgOutput, " ", 1);
+                            cchWidth -= cchStr;
+                            while (cchStr-- > 0)
+                            {
+/** @todo \#ifndef IN_RC*/
+#ifdef IN_RING3
+                                RTUNICP Cp;
+                                RTUtf16GetCpEx(&pwszStr, &Cp);
+                                char *pszEnd = RTStrPutCp(szTmp, Cp);
+                                *pszEnd = '\0';
+                                cch += pfnOutput(pvArgOutput, szTmp, pszEnd - szTmp);
+#else
+                                char ch = (char)*pwszStr++;
+                                cch += pfnOutput(pvArgOutput, &ch, 1);
+#endif
+                            }
+                            while (--cchWidth >= 0)
+                                cch += pfnOutput(pvArgOutput, " ", 1);
+                        }
+                        else if (chArgSize == 'L')
+                        {
+                            /* unicp -> utf8 */
+                            int         cchStr;
+                            PCRTUNICP   puszStr = va_arg(args, PCRTUNICP);
+
+                            if (!VALID_PTR(puszStr))
+                            {
+                                static RTUNICP s_uszNull[] = {'<', 'N', 'U', 'L', 'L', '>', '\0' };
+                                puszStr = s_uszNull;
+                            }
+                            cchStr = _strnlenUni(puszStr, (unsigned)cchPrecision);
+                            if (!(fFlags & RTSTR_F_LEFT))
+                                while (--cchWidth >= cchStr)
+                                    cch += pfnOutput(pvArgOutput, " ", 1);
+
+                            cchWidth -= cchStr;
+                            while (cchStr-- > 0)
+                            {
+/** @todo \#ifndef IN_RC*/
+#ifdef IN_RING3
+                                char *pszEnd = RTStrPutCp(szTmp, *puszStr++);
+                                cch += pfnOutput(pvArgOutput, szTmp, pszEnd - szTmp);
+#else
+                                char ch = (char)*puszStr++;
+                                cch += pfnOutput(pvArgOutput, &ch, 1);
+#endif
+                            }
+                            while (--cchWidth >= 0)
+                                cch += pfnOutput(pvArgOutput, " ", 1);
+                        }
+                        else
+                        {
+                            int   cchStr;
+                            const char *pszStr = va_arg(args, char*);
+
+                            if (!VALID_PTR(pszStr))
+                                pszStr = "<NULL>";
+                            cchStr = _strnlen(pszStr, (unsigned)cchPrecision);
+                            if (!(fFlags & RTSTR_F_LEFT))
+                                while (--cchWidth >= cchStr)
+                                    cch += pfnOutput(pvArgOutput, " ", 1);
+
+                            cch += pfnOutput(pvArgOutput, pszStr, cchStr);
+
+                            while (--cchWidth >= cchStr)
+                                cch += pfnOutput(pvArgOutput, " ", 1);
+                        }
+                        break;
+                    }
+
+                    /*-----------------*/
+                    /* integer/pointer */
+                    /*-----------------*/
+                    case 'd':
+                    case 'i':
+                    case 'o':
+                    case 'p':
+                    case 'u':
+                    case 'x':
+                    case 'X':
+                    {
+                        int         cchNum;
+                        uint64_t    u64Value;
+
+                        switch (pszFormat[-1])
+                        {
+                            case 'd': /* signed decimal integer */
+                            case 'i':
+                                fFlags |= RTSTR_F_VALSIGNED;
+                                break;
+
+                            case 'o':
+                                uBase = 8;
+                                break;
+
+                            case 'p':
+                                fFlags |= RTSTR_F_ZEROPAD; /* Note not standard behaviour (but I like it this way!) */
+                                uBase = 16;
+                                if (cchWidth < 0)
+                                    cchWidth = sizeof(char *) * 2;
+                                break;
+
+                            case 'u':
+                                uBase = 10;
+                                break;
+
+                            case 'X':
+                                fFlags |= RTSTR_F_CAPITAL;
+                                /* fall thru */
+                            case 'x':
+                                uBase = 16;
+                                break;
+                        }
+
+                        if (pszFormat[-1] == 'p')
+                            u64Value = va_arg(args, uintptr_t);
+                        else if (fFlags & RTSTR_F_VALSIGNED)
+                        {
+                            if (chArgSize == 'L')
+                            {
+                                u64Value = va_arg(args, int64_t);
+                                fFlags |= RTSTR_F_64BIT;
+                            }
+                            else if (chArgSize == 'l')
+                            {
+                                u64Value = va_arg(args, signed long);
+                                fFlags |= RTSTR_GET_BIT_FLAG(unsigned long);
+                            }
+                            else if (chArgSize == 'h')
+                            {
+                                u64Value = va_arg(args, /* signed short */ int);
+                                fFlags |= RTSTR_GET_BIT_FLAG(signed short);
+                            }
+                            else if (chArgSize == 'H')
+                            {
+                                u64Value = va_arg(args, /* int8_t */ int);
+                                fFlags |= RTSTR_GET_BIT_FLAG(int8_t);
+                            }
+                            else if (chArgSize == 'j')
+                            {
+                                u64Value = va_arg(args, /*intmax_t*/ int64_t);
+                                fFlags |= RTSTR_F_64BIT;
+                            }
+                            else if (chArgSize == 'z')
+                            {
+                                u64Value = va_arg(args, size_t);
+                                fFlags |= RTSTR_GET_BIT_FLAG(size_t);
+                            }
+                            else if (chArgSize == 't')
+                            {
+                                u64Value = va_arg(args, ptrdiff_t);
+                                fFlags |= RTSTR_GET_BIT_FLAG(ptrdiff_t);
+                            }
+                            else
+                            {
+                                u64Value = va_arg(args, signed int);
+                                fFlags |= RTSTR_GET_BIT_FLAG(signed int);
+                            }
+                        }
+                        else
+                        {
+                            if (chArgSize == 'L')
+                            {
+                                u64Value = va_arg(args, uint64_t);
+                                fFlags |= RTSTR_F_64BIT;
+                            }
+                            else if (chArgSize == 'l')
+                            {
+                                u64Value = va_arg(args, unsigned long);
+                                fFlags |= RTSTR_GET_BIT_FLAG(unsigned long);
+                            }
+                            else if (chArgSize == 'h')
+                            {
+                                u64Value = va_arg(args, /* unsigned short */ int);
+                                fFlags |= RTSTR_GET_BIT_FLAG(unsigned short);
+                            }
+                            else if (chArgSize == 'H')
+                            {
+                                u64Value = va_arg(args, /* uint8_t */ int);
+                                fFlags |= RTSTR_GET_BIT_FLAG(uint8_t);
+                            }
+                            else if (chArgSize == 'j')
+                            {
+                                u64Value = va_arg(args, /*uintmax_t*/ int64_t);
+                                fFlags |= RTSTR_F_64BIT;
+                            }
+                            else if (chArgSize == 'z')
+                            {
+                                u64Value = va_arg(args, size_t);
+                                fFlags |= RTSTR_GET_BIT_FLAG(size_t);
+                            }
+                            else if (chArgSize == 't')
+                            {
+                                u64Value = va_arg(args, ptrdiff_t);
+                                fFlags |= RTSTR_GET_BIT_FLAG(ptrdiff_t);
+                            }
+                            else
+                            {
+                                u64Value = va_arg(args, unsigned int);
+                                fFlags |= RTSTR_GET_BIT_FLAG(unsigned int);
+                            }
+                        }
+                        cchNum = RTStrFormatNumber((char *)SSToDS(&szTmp), u64Value, uBase, cchWidth, cchPrecision, fFlags);
+                        cch += pfnOutput(pvArgOutput, (char *)SSToDS(&szTmp), cchNum);
+                        break;
+                    }
+
+                    /*
+                     * Nested extensions.
+                     */
+                    case 'M': /* replace the format string (not stacked yet). */
+                    {
+                        pszStartOutput = pszFormat = va_arg(args, const char *);
+                        AssertPtr(pszStartOutput);
+                        break;
+                    }
+
+                    case 'N': /* real nesting. */
+                    {
+                        const char *pszFormatNested = va_arg(args, const char *);
+                        va_list    *pArgsNested     = va_arg(args, va_list *);
+                        va_list     ArgsNested;
+                        va_copy(ArgsNested, *pArgsNested);
+                        Assert(pszFormatNested);
+                        cch += RTStrFormatV(pfnOutput, pvArgOutput, pfnFormat, pvArgFormat, pszFormatNested, ArgsNested);
+                        va_end(ArgsNested);
+                        break;
+                    }
+
+                    /*
+                     * IPRT Extensions.
+                     */
+                    case 'R':
+                    {
+                        if (*pszFormat != '[')
+                        {
+                            pszFormat--;
+                            cch += rtstrFormatRt(pfnOutput, pvArgOutput, &pszFormat, &args, cchWidth, cchPrecision, fFlags, chArgSize);
+                        }
+                        else
+                        {
+                            pszFormat--;
+                            cch += rtstrFormatType(pfnOutput, pvArgOutput, &pszFormat, &args, cchWidth, cchPrecision, fFlags, chArgSize);
+                        }
+                        break;
+                    }
+
+                    /*
+                     * Custom format.
+                     */
+                    default:
+                    {
+                        if (pfnFormat)
+                        {
+                            pszFormat--;
+                            cch += pfnFormat(pvArgFormat, pfnOutput, pvArgOutput, &pszFormat, &args, cchWidth, cchPrecision, fFlags, chArgSize);
+                        }
+                        break;
+                    }
+                }
+                pszStartOutput = pszFormat;
+            }
+        }
+        else
+            pszFormat++;
+    }
+
+    /* output pending string. */
+    if (pszStartOutput != pszFormat)
+        cch += pfnOutput(pvArgOutput, pszStartOutput, pszFormat - pszStartOutput);
+
+    /* terminate the output */
+    pfnOutput(pvArgOutput, NULL, 0);
+
+    return cch;
+}
+RT_EXPORT_SYMBOL(RTStrFormatV);
+
+
+/**
+ * Partial implementation of a printf like formatter.
+ * It doesn't do everything correct, and there is no floating point support.
+ * However, it supports custom formats by the means of a format callback.
+ *
+ * @returns number of bytes formatted.
+ * @param   pfnOutput   Output worker.
+ *                      Called in two ways. Normally with a string an it's length.
+ *                      For termination, it's called with NULL for string, 0 for length.
+ * @param   pvArgOutput Argument to the output worker.
+ * @param   pfnFormat   Custom format worker.
+ * @param   pvArgFormat Argument to the format worker.
+ * @param   pszFormat   Format string.
+ * @param   ...         Argument list.
+ */
+RTDECL(size_t) RTStrFormat(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, PFNSTRFORMAT pfnFormat, void *pvArgFormat, const char *pszFormat, ...)
+{
+    size_t cch;
+    va_list args;
+    va_start(args, pszFormat);
+    cch = RTStrFormatV(pfnOutput, pvArgOutput, pfnFormat, pvArgFormat, pszFormat, args);
+    va_end(args);
+    return cch;
+}
+RT_EXPORT_SYMBOL(RTStrFormat);
+
diff --git a/ubuntu/vbox/vboxguest/common/string/strformatrt.c b/ubuntu/vbox/vboxguest/common/string/strformatrt.c
new file mode 100644 (file)
index 0000000..fdc48bb
--- /dev/null
@@ -0,0 +1,1265 @@
+/* $Id: strformatrt.cpp $ */
+/** @file
+ * IPRT - IPRT String Formatter Extensions.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_STRING
+#include <iprt/string.h>
+#ifndef RT_NO_EXPORT_SYMBOL
+# define RT_NO_EXPORT_SYMBOL /* don't slurp <linux/module.h> which then again
+                                slurps arch-specific headers defining symbols */
+#endif
+#include "internal/iprt.h"
+
+#include <iprt/log.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <iprt/stdarg.h>
+#ifdef IN_RING3
+# include <iprt/thread.h>
+# include <iprt/err.h>
+#endif
+#include <iprt/ctype.h>
+#include <iprt/time.h>
+#include <iprt/net.h>
+#include <iprt/path.h>
+#include <iprt/asm.h>
+#define STRFORMAT_WITH_X86
+#ifdef STRFORMAT_WITH_X86
+# include <iprt/x86.h>
+#endif
+#include "internal/string.h"
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+static char g_szHexDigits[17] = "0123456789abcdef";
+
+
+/**
+ * Helper that formats a 16-bit hex word in a IPv6 address.
+ *
+ * @returns Length in chars.
+ * @param   pszDst      The output buffer.  Written from the start.
+ * @param   uWord       The word to format as hex.
+ */
+static size_t rtstrFormatIPv6HexWord(char *pszDst, uint16_t uWord)
+{
+    size_t   off;
+    uint16_t cDigits;
+
+    if (uWord & UINT16_C(0xff00))
+        cDigits = uWord & UINT16_C(0xf000) ? 4 : 3;
+    else
+        cDigits = uWord & UINT16_C(0x00f0) ? 2 : 1;
+
+    off = 0;
+    switch (cDigits)
+    {
+        case 4: pszDst[off++] = g_szHexDigits[(uWord >> 12) & 0xf]; /* fall thru */
+        case 3: pszDst[off++] = g_szHexDigits[(uWord >>  8) & 0xf]; /* fall thru */
+        case 2: pszDst[off++] = g_szHexDigits[(uWord >>  4) & 0xf]; /* fall thru */
+        case 1: pszDst[off++] = g_szHexDigits[(uWord >>  0) & 0xf];
+            break;
+    }
+    pszDst[off] = '\0';
+    return off;
+}
+
+
+/**
+ * Helper function to format IPv6 address according to RFC 5952.
+ *
+ * @returns The number of bytes formatted.
+ * @param   pfnOutput       Pointer to output function.
+ * @param   pvArgOutput     Argument for the output function.
+ * @param   pIpv6Addr       IPv6 address
+ */
+static size_t rtstrFormatIPv6(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, PCRTNETADDRIPV6 pIpv6Addr)
+{
+    size_t cch; /* result */
+    bool   fEmbeddedIpv4;
+    size_t cwHexPart;
+    size_t cwLongestZeroRun;
+    size_t iLongestZeroStart;
+    size_t idx;
+    char   szHexWord[8];
+
+    Assert(pIpv6Addr != NULL);
+
+    /*
+     * Check for embedded IPv4 address.
+     *
+     * IPv4-compatible - ::11.22.33.44 (obsolete)
+     * IPv4-mapped     - ::ffff:11.22.33.44
+     * IPv4-translated - ::ffff:0:11.22.33.44 (RFC 2765)
+     */
+    fEmbeddedIpv4 = false;
+    cwHexPart = RT_ELEMENTS(pIpv6Addr->au16);
+    if (   pIpv6Addr->au64[0] == 0
+        && (   (   pIpv6Addr->au32[2] == 0
+                && pIpv6Addr->au32[3] != 0
+                && pIpv6Addr->au32[3] != RT_H2BE_U32_C(1) )
+            || pIpv6Addr->au32[2] == RT_H2BE_U32_C(0x0000ffff)
+            || pIpv6Addr->au32[2] == RT_H2BE_U32_C(0xffff0000) ) )
+    {
+        fEmbeddedIpv4 = true;
+        cwHexPart -= 2;
+    }
+
+    /*
+     * Find the longest sequences of two or more zero words.
+     */
+    cwLongestZeroRun  = 0;
+    iLongestZeroStart = 0;
+    for (idx = 0; idx < cwHexPart; idx++)
+        if (pIpv6Addr->au16[idx] == 0)
+        {
+            size_t iZeroStart = idx;
+            size_t cwZeroRun;
+            do
+                idx++;
+            while (idx < cwHexPart && pIpv6Addr->au16[idx] == 0);
+            cwZeroRun = idx - iZeroStart;
+            if (cwZeroRun > 1 && cwZeroRun > cwLongestZeroRun)
+            {
+                cwLongestZeroRun  = cwZeroRun;
+                iLongestZeroStart = iZeroStart;
+                if (cwZeroRun >= cwHexPart - idx)
+                    break;
+            }
+        }
+
+    /*
+     * Do the formatting.
+     */
+    cch = 0;
+    if (cwLongestZeroRun == 0)
+    {
+        for (idx = 0; idx < cwHexPart; ++idx)
+        {
+            if (idx > 0)
+                cch += pfnOutput(pvArgOutput, ":", 1);
+            cch += pfnOutput(pvArgOutput, szHexWord, rtstrFormatIPv6HexWord(szHexWord, RT_BE2H_U16(pIpv6Addr->au16[idx])));
+        }
+
+        if (fEmbeddedIpv4)
+            cch += pfnOutput(pvArgOutput, ":", 1);
+    }
+    else
+    {
+        const size_t iLongestZeroEnd = iLongestZeroStart + cwLongestZeroRun;
+
+        if (iLongestZeroStart == 0)
+            cch += pfnOutput(pvArgOutput, ":", 1);
+        else
+            for (idx = 0; idx < iLongestZeroStart; ++idx)
+            {
+                cch += pfnOutput(pvArgOutput, szHexWord, rtstrFormatIPv6HexWord(szHexWord, RT_BE2H_U16(pIpv6Addr->au16[idx])));
+                cch += pfnOutput(pvArgOutput, ":", 1);
+            }
+
+        if (iLongestZeroEnd == cwHexPart)
+            cch += pfnOutput(pvArgOutput, ":", 1);
+        else
+        {
+            for (idx = iLongestZeroEnd; idx < cwHexPart; ++idx)
+            {
+                cch += pfnOutput(pvArgOutput, ":", 1);
+                cch += pfnOutput(pvArgOutput, szHexWord, rtstrFormatIPv6HexWord(szHexWord, RT_BE2H_U16(pIpv6Addr->au16[idx])));
+            }
+
+            if (fEmbeddedIpv4)
+                cch += pfnOutput(pvArgOutput, ":", 1);
+        }
+    }
+
+    if (fEmbeddedIpv4)
+        cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+                           "%u.%u.%u.%u",
+                           pIpv6Addr->au8[12],
+                           pIpv6Addr->au8[13],
+                           pIpv6Addr->au8[14],
+                           pIpv6Addr->au8[15]);
+
+    return cch;
+}
+
+
+/**
+ * Callback to format iprt formatting extentions.
+ * See @ref pg_rt_str_format for a reference on the format types.
+ *
+ * @returns The number of bytes formatted.
+ * @param   pfnOutput       Pointer to output function.
+ * @param   pvArgOutput     Argument for the output function.
+ * @param   ppszFormat      Pointer to the format string pointer. Advance this till the char
+ *                          after the format specifier.
+ * @param   pArgs           Pointer to the argument list. Use this to fetch the arguments.
+ * @param   cchWidth        Format Width. -1 if not specified.
+ * @param   cchPrecision    Format Precision. -1 if not specified.
+ * @param   fFlags          Flags (RTSTR_NTFS_*).
+ * @param   chArgSize       The argument size specifier, 'l' or 'L'.
+ */
+DECLHIDDEN(size_t) rtstrFormatRt(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, const char **ppszFormat, va_list *pArgs,
+                                 int cchWidth, int cchPrecision, unsigned fFlags, char chArgSize)
+{
+    const char *pszFormatOrg = *ppszFormat;
+    char        ch = *(*ppszFormat)++;
+    size_t      cch;
+    char        szBuf[80];
+
+    if (ch == 'R')
+    {
+        ch = *(*ppszFormat)++;
+        switch (ch)
+        {
+            /*
+             * Groups 1 and 2.
+             */
+            case 'T':
+            case 'G':
+            case 'H':
+            case 'R':
+            case 'C':
+            case 'I':
+            case 'X':
+            case 'U':
+            case 'K':
+            {
+                /*
+                 * Interpret the type.
+                 */
+                typedef enum
+                {
+                    RTSF_INT,
+                    RTSF_INTW,
+                    RTSF_BOOL,
+                    RTSF_FP16,
+                    RTSF_FP32,
+                    RTSF_FP64,
+                    RTSF_IPV4,
+                    RTSF_IPV6,
+                    RTSF_MAC,
+                    RTSF_NETADDR,
+                    RTSF_UUID
+                } RTSF;
+                static const struct
+                {
+                    uint8_t     cch;        /**< the length of the string. */
+                    char        sz[10];     /**< the part following 'R'. */
+                    uint8_t     cb;         /**< the size of the type. */
+                    uint8_t     u8Base;     /**< the size of the type. */
+                    RTSF        enmFormat;  /**< The way to format it. */
+                    uint16_t    fFlags;     /**< additional RTSTR_F_* flags. */
+                }
+                /** Sorted array of types, looked up using binary search! */
+                s_aTypes[] =
+                {
+#define STRMEM(str) sizeof(str) - 1, str
+                    { STRMEM("Ci"),      sizeof(RTINT),          10, RTSF_INT,   RTSTR_F_VALSIGNED },
+                    { STRMEM("Cp"),      sizeof(RTCCPHYS),       16, RTSF_INTW,  0 },
+                    { STRMEM("Cr"),      sizeof(RTCCUINTREG),    16, RTSF_INTW,  0 },
+                    { STRMEM("Cu"),      sizeof(RTUINT),         10, RTSF_INT,   0 },
+                    { STRMEM("Cv"),      sizeof(void *),         16, RTSF_INTW,  0 },
+                    { STRMEM("Cx"),      sizeof(RTUINT),         16, RTSF_INT,   0 },
+                    { STRMEM("Gi"),      sizeof(RTGCINT),        10, RTSF_INT,   RTSTR_F_VALSIGNED },
+                    { STRMEM("Gp"),      sizeof(RTGCPHYS),       16, RTSF_INTW,  0 },
+                    { STRMEM("Gr"),      sizeof(RTGCUINTREG),    16, RTSF_INTW,  0 },
+                    { STRMEM("Gu"),      sizeof(RTGCUINT),       10, RTSF_INT,   0 },
+                    { STRMEM("Gv"),      sizeof(RTGCPTR),        16, RTSF_INTW,  0 },
+                    { STRMEM("Gx"),      sizeof(RTGCUINT),       16, RTSF_INT,   0 },
+                    { STRMEM("Hi"),      sizeof(RTHCINT),        10, RTSF_INT,   RTSTR_F_VALSIGNED },
+                    { STRMEM("Hp"),      sizeof(RTHCPHYS),       16, RTSF_INTW,  0 },
+                    { STRMEM("Hr"),      sizeof(RTHCUINTREG),    16, RTSF_INTW,  0 },
+                    { STRMEM("Hu"),      sizeof(RTHCUINT),       10, RTSF_INT,   0 },
+                    { STRMEM("Hv"),      sizeof(RTHCPTR),        16, RTSF_INTW,  0 },
+                    { STRMEM("Hx"),      sizeof(RTHCUINT),       16, RTSF_INT,   0 },
+                    { STRMEM("I16"),     sizeof(int16_t),        10, RTSF_INT,   RTSTR_F_VALSIGNED },
+                    { STRMEM("I32"),     sizeof(int32_t),        10, RTSF_INT,   RTSTR_F_VALSIGNED },
+                    { STRMEM("I64"),     sizeof(int64_t),        10, RTSF_INT,   RTSTR_F_VALSIGNED },
+                    { STRMEM("I8"),      sizeof(int8_t),         10, RTSF_INT,   RTSTR_F_VALSIGNED },
+                    { STRMEM("Kv"),      sizeof(RTHCPTR),        16, RTSF_INT,   RTSTR_F_OBFUSCATE_PTR },
+                    { STRMEM("Rv"),      sizeof(RTRCPTR),        16, RTSF_INTW,  0 },
+                    { STRMEM("Tbool"),   sizeof(bool),           10, RTSF_BOOL,  0 },
+                    { STRMEM("Tfile"),   sizeof(RTFILE),         10, RTSF_INT,   0 },
+                    { STRMEM("Tfmode"),  sizeof(RTFMODE),        16, RTSF_INTW,  0 },
+                    { STRMEM("Tfoff"),   sizeof(RTFOFF),         10, RTSF_INT,   RTSTR_F_VALSIGNED },
+                    { STRMEM("Tfp16"),   sizeof(RTFAR16),        16, RTSF_FP16,  RTSTR_F_ZEROPAD },
+                    { STRMEM("Tfp32"),   sizeof(RTFAR32),        16, RTSF_FP32,  RTSTR_F_ZEROPAD },
+                    { STRMEM("Tfp64"),   sizeof(RTFAR64),        16, RTSF_FP64,  RTSTR_F_ZEROPAD },
+                    { STRMEM("Tgid"),    sizeof(RTGID),          10, RTSF_INT,   RTSTR_F_VALSIGNED },
+                    { STRMEM("Tino"),    sizeof(RTINODE),        16, RTSF_INTW,  0 },
+                    { STRMEM("Tint"),    sizeof(RTINT),          10, RTSF_INT,   RTSTR_F_VALSIGNED },
+                    { STRMEM("Tiop"),    sizeof(RTIOPORT),       16, RTSF_INTW,  0 },
+                    { STRMEM("Tldrm"),   sizeof(RTLDRMOD),       16, RTSF_INTW,  0 },
+                    { STRMEM("Tmac"),    sizeof(PCRTMAC),        16, RTSF_MAC,   0 },
+                    { STRMEM("Tnaddr"),  sizeof(PCRTNETADDR),    10, RTSF_NETADDR,0 },
+                    { STRMEM("Tnaipv4"), sizeof(RTNETADDRIPV4),  10, RTSF_IPV4,  0 },
+                    { STRMEM("Tnaipv6"), sizeof(PCRTNETADDRIPV6),16, RTSF_IPV6,  0 },
+                    { STRMEM("Tnthrd"),  sizeof(RTNATIVETHREAD), 16, RTSF_INTW,  0 },
+                    { STRMEM("Tproc"),   sizeof(RTPROCESS),      16, RTSF_INTW,  0 },
+                    { STRMEM("Tptr"),    sizeof(RTUINTPTR),      16, RTSF_INTW,  0 },
+                    { STRMEM("Treg"),    sizeof(RTCCUINTREG),    16, RTSF_INTW,  0 },
+                    { STRMEM("Tsel"),    sizeof(RTSEL),          16, RTSF_INTW,  0 },
+                    { STRMEM("Tsem"),    sizeof(RTSEMEVENT),     16, RTSF_INTW,  0 },
+                    { STRMEM("Tsock"),   sizeof(RTSOCKET),       10, RTSF_INT,   0 },
+                    { STRMEM("Tthrd"),   sizeof(RTTHREAD),       16, RTSF_INTW,  0 },
+                    { STRMEM("Tuid"),    sizeof(RTUID),          10, RTSF_INT,   RTSTR_F_VALSIGNED },
+                    { STRMEM("Tuint"),   sizeof(RTUINT),         10, RTSF_INT,   0 },
+                    { STRMEM("Tunicp"),  sizeof(RTUNICP),        16, RTSF_INTW,  RTSTR_F_ZEROPAD },
+                    { STRMEM("Tutf16"),  sizeof(RTUTF16),        16, RTSF_INTW,  RTSTR_F_ZEROPAD },
+                    { STRMEM("Tuuid"),   sizeof(PCRTUUID),       16, RTSF_UUID,  0 },
+                    { STRMEM("Txint"),   sizeof(RTUINT),         16, RTSF_INT,   0 },
+                    { STRMEM("U16"),     sizeof(uint16_t),       10, RTSF_INT,   0 },
+                    { STRMEM("U32"),     sizeof(uint32_t),       10, RTSF_INT,   0 },
+                    { STRMEM("U64"),     sizeof(uint64_t),       10, RTSF_INT,   0 },
+                    { STRMEM("U8"),      sizeof(uint8_t),        10, RTSF_INT,   0 },
+                    { STRMEM("X16"),     sizeof(uint16_t),       16, RTSF_INT,   0 },
+                    { STRMEM("X32"),     sizeof(uint32_t),       16, RTSF_INT,   0 },
+                    { STRMEM("X64"),     sizeof(uint64_t),       16, RTSF_INT,   0 },
+                    { STRMEM("X8"),      sizeof(uint8_t),        16, RTSF_INT,   0 },
+#undef STRMEM
+                };
+                static const char s_szNull[] = "<NULL>";
+
+                const char *pszType = *ppszFormat - 1;
+                int         iStart  = 0;
+                int         iEnd    = RT_ELEMENTS(s_aTypes) - 1;
+                int         i       = RT_ELEMENTS(s_aTypes) / 2;
+
+                union
+                {
+                    uint8_t             u8;
+                    uint16_t            u16;
+                    uint32_t            u32;
+                    uint64_t            u64;
+                    int8_t              i8;
+                    int16_t             i16;
+                    int32_t             i32;
+                    int64_t             i64;
+                    RTR0INTPTR          uR0Ptr;
+                    RTFAR16             fp16;
+                    RTFAR32             fp32;
+                    RTFAR64             fp64;
+                    bool                fBool;
+                    PCRTMAC             pMac;
+                    RTNETADDRIPV4       Ipv4Addr;
+                    PCRTNETADDRIPV6     pIpv6Addr;
+                    PCRTNETADDR         pNetAddr;
+                    PCRTUUID            pUuid;
+                } u;
+
+                AssertMsg(!chArgSize, ("Not argument size '%c' for RT types! '%.10s'\n", chArgSize, pszFormatOrg));
+                RT_NOREF_PV(chArgSize);
+
+                /*
+                 * Lookup the type - binary search.
+                 */
+                for (;;)
+                {
+                    int iDiff = strncmp(pszType, s_aTypes[i].sz, s_aTypes[i].cch);
+                    if (!iDiff)
+                        break;
+                    if (iEnd == iStart)
+                    {
+                        AssertMsgFailed(("Invalid format type '%.10s'!\n", pszFormatOrg));
+                        return 0;
+                    }
+                    if (iDiff < 0)
+                        iEnd = i - 1;
+                    else
+                        iStart = i + 1;
+                    if (iEnd < iStart)
+                    {
+                        AssertMsgFailed(("Invalid format type '%.10s'!\n", pszFormatOrg));
+                        return 0;
+                    }
+                    i = iStart + (iEnd - iStart) / 2;
+                }
+
+                /*
+                 * Advance the format string and merge flags.
+                 */
+                *ppszFormat += s_aTypes[i].cch - 1;
+                fFlags |= s_aTypes[i].fFlags;
+
+                /*
+                 * Fetch the argument.
+                 * It's important that a signed value gets sign-extended up to 64-bit.
+                 */
+                RT_ZERO(u);
+                if (fFlags & RTSTR_F_VALSIGNED)
+                {
+                    switch (s_aTypes[i].cb)
+                    {
+                        case sizeof(int8_t):
+                            u.i64 = va_arg(*pArgs, /*int8_t*/int);
+                            fFlags |= RTSTR_F_8BIT;
+                            break;
+                        case sizeof(int16_t):
+                            u.i64 = va_arg(*pArgs, /*int16_t*/int);
+                            fFlags |= RTSTR_F_16BIT;
+                            break;
+                        case sizeof(int32_t):
+                            u.i64 = va_arg(*pArgs, int32_t);
+                            fFlags |= RTSTR_F_32BIT;
+                            break;
+                        case sizeof(int64_t):
+                            u.i64 = va_arg(*pArgs, int64_t);
+                            fFlags |= RTSTR_F_64BIT;
+                            break;
+                        default:
+                            AssertMsgFailed(("Invalid format error, size %d'!\n", s_aTypes[i].cb));
+                            break;
+                    }
+                }
+                else
+                {
+                    switch (s_aTypes[i].cb)
+                    {
+                        case sizeof(uint8_t):
+                            u.u8 = va_arg(*pArgs, /*uint8_t*/unsigned);
+                            fFlags |= RTSTR_F_8BIT;
+                            break;
+                        case sizeof(uint16_t):
+                            u.u16 = va_arg(*pArgs, /*uint16_t*/unsigned);
+                            fFlags |= RTSTR_F_16BIT;
+                            break;
+                        case sizeof(uint32_t):
+                            u.u32 = va_arg(*pArgs, uint32_t);
+                            fFlags |= RTSTR_F_32BIT;
+                            break;
+                        case sizeof(uint64_t):
+                            u.u64 = va_arg(*pArgs, uint64_t);
+                            fFlags |= RTSTR_F_64BIT;
+                            break;
+                        case sizeof(RTFAR32):
+                            u.fp32 = va_arg(*pArgs, RTFAR32);
+                            break;
+                        case sizeof(RTFAR64):
+                            u.fp64 = va_arg(*pArgs, RTFAR64);
+                            break;
+                        default:
+                            AssertMsgFailed(("Invalid format error, size %d'!\n", s_aTypes[i].cb));
+                            break;
+                    }
+                }
+
+#ifndef DEBUG
+                /*
+                 * For now don't show the address.
+                 */
+                if (fFlags & RTSTR_F_OBFUSCATE_PTR)
+                {
+                    cch = rtStrFormatKernelAddress(szBuf, sizeof(szBuf), u.uR0Ptr, cchWidth, cchPrecision, fFlags);
+                    return pfnOutput(pvArgOutput, szBuf, cch);
+                }
+#endif
+
+                /*
+                 * Format the output.
+                 */
+                switch (s_aTypes[i].enmFormat)
+                {
+                    case RTSF_INT:
+                    {
+                        cch = RTStrFormatNumber(szBuf, u.u64, s_aTypes[i].u8Base, cchWidth, cchPrecision, fFlags);
+                        break;
+                    }
+
+                    /* hex which defaults to max width. */
+                    case RTSF_INTW:
+                    {
+                        Assert(s_aTypes[i].u8Base == 16);
+                        if (cchWidth < 0)
+                        {
+                            cchWidth = s_aTypes[i].cb * 2 + (fFlags & RTSTR_F_SPECIAL ? 2 : 0);
+                            fFlags |= RTSTR_F_ZEROPAD;
+                        }
+                        cch = RTStrFormatNumber(szBuf, u.u64, s_aTypes[i].u8Base, cchWidth, cchPrecision, fFlags);
+                        break;
+                    }
+
+                    case RTSF_BOOL:
+                    {
+                        static const char s_szTrue[]  = "true ";
+                        static const char s_szFalse[] = "false";
+                        if (u.u64 == 1)
+                            return pfnOutput(pvArgOutput, s_szTrue,  sizeof(s_szTrue) - 1);
+                        if (u.u64 == 0)
+                            return pfnOutput(pvArgOutput, s_szFalse, sizeof(s_szFalse) - 1);
+                        /* invalid boolean value */
+                        return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "!%lld!", u.u64);
+                    }
+
+                    case RTSF_FP16:
+                    {
+                        fFlags &= ~(RTSTR_F_VALSIGNED | RTSTR_F_BIT_MASK | RTSTR_F_WIDTH | RTSTR_F_PRECISION | RTSTR_F_THOUSAND_SEP);
+                        cch = RTStrFormatNumber(&szBuf[0], u.fp16.sel, 16, 4, -1, fFlags | RTSTR_F_16BIT);
+                        Assert(cch == 4);
+                        szBuf[4] = ':';
+                        cch = RTStrFormatNumber(&szBuf[5], u.fp16.off, 16, 4, -1, fFlags | RTSTR_F_16BIT);
+                        Assert(cch == 4);
+                        cch = 4 + 1 + 4;
+                        break;
+                    }
+                    case RTSF_FP32:
+                    {
+                        fFlags &= ~(RTSTR_F_VALSIGNED | RTSTR_F_BIT_MASK | RTSTR_F_WIDTH | RTSTR_F_PRECISION | RTSTR_F_THOUSAND_SEP);
+                        cch = RTStrFormatNumber(&szBuf[0], u.fp32.sel, 16, 4, -1, fFlags | RTSTR_F_16BIT);
+                        Assert(cch == 4);
+                        szBuf[4] = ':';
+                        cch = RTStrFormatNumber(&szBuf[5], u.fp32.off, 16, 8, -1, fFlags | RTSTR_F_32BIT);
+                        Assert(cch == 8);
+                        cch = 4 + 1 + 8;
+                        break;
+                    }
+                    case RTSF_FP64:
+                    {
+                        fFlags &= ~(RTSTR_F_VALSIGNED | RTSTR_F_BIT_MASK | RTSTR_F_WIDTH | RTSTR_F_PRECISION | RTSTR_F_THOUSAND_SEP);
+                        cch = RTStrFormatNumber(&szBuf[0], u.fp64.sel, 16, 4, -1, fFlags | RTSTR_F_16BIT);
+                        Assert(cch == 4);
+                        szBuf[4] = ':';
+                        cch = RTStrFormatNumber(&szBuf[5], u.fp64.off, 16, 16, -1, fFlags | RTSTR_F_64BIT);
+                        Assert(cch == 16);
+                        cch = 4 + 1 + 16;
+                        break;
+                    }
+
+                    case RTSF_IPV4:
+                        return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+                                           "%u.%u.%u.%u",
+                                           u.Ipv4Addr.au8[0],
+                                           u.Ipv4Addr.au8[1],
+                                           u.Ipv4Addr.au8[2],
+                                           u.Ipv4Addr.au8[3]);
+
+                    case RTSF_IPV6:
+                    {
+                        if (VALID_PTR(u.pIpv6Addr))
+                            return rtstrFormatIPv6(pfnOutput, pvArgOutput, u.pIpv6Addr);
+                        return pfnOutput(pvArgOutput, s_szNull, sizeof(s_szNull) - 1);
+                    }
+
+                    case RTSF_MAC:
+                    {
+                        if (VALID_PTR(u.pMac))
+                            return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+                                               "%02x:%02x:%02x:%02x:%02x:%02x",
+                                               u.pMac->au8[0],
+                                               u.pMac->au8[1],
+                                               u.pMac->au8[2],
+                                               u.pMac->au8[3],
+                                               u.pMac->au8[4],
+                                               u.pMac->au8[5]);
+                        return pfnOutput(pvArgOutput, s_szNull, sizeof(s_szNull) - 1);
+                    }
+
+                    case RTSF_NETADDR:
+                    {
+                        if (VALID_PTR(u.pNetAddr))
+                        {
+                            switch (u.pNetAddr->enmType)
+                            {
+                                case RTNETADDRTYPE_IPV4:
+                                    if (u.pNetAddr->uPort == RTNETADDR_PORT_NA)
+                                        return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+                                                           "%u.%u.%u.%u",
+                                                           u.pNetAddr->uAddr.IPv4.au8[0],
+                                                           u.pNetAddr->uAddr.IPv4.au8[1],
+                                                           u.pNetAddr->uAddr.IPv4.au8[2],
+                                                           u.pNetAddr->uAddr.IPv4.au8[3]);
+                                    return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+                                                       "%u.%u.%u.%u:%u",
+                                                       u.pNetAddr->uAddr.IPv4.au8[0],
+                                                       u.pNetAddr->uAddr.IPv4.au8[1],
+                                                       u.pNetAddr->uAddr.IPv4.au8[2],
+                                                       u.pNetAddr->uAddr.IPv4.au8[3],
+                                                       u.pNetAddr->uPort);
+
+                                case RTNETADDRTYPE_IPV6:
+                                    if (u.pNetAddr->uPort == RTNETADDR_PORT_NA)
+                                        return rtstrFormatIPv6(pfnOutput, pvArgOutput, &u.pNetAddr->uAddr.IPv6);
+
+                                    return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+                                                       "[%RTnaipv6]:%u",
+                                                       &u.pNetAddr->uAddr.IPv6,
+                                                       u.pNetAddr->uPort);
+
+                                case RTNETADDRTYPE_MAC:
+                                    return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+                                                       "%02x:%02x:%02x:%02x:%02x:%02x",
+                                                       u.pNetAddr->uAddr.Mac.au8[0],
+                                                       u.pNetAddr->uAddr.Mac.au8[1],
+                                                       u.pNetAddr->uAddr.Mac.au8[2],
+                                                       u.pNetAddr->uAddr.Mac.au8[3],
+                                                       u.pNetAddr->uAddr.Mac.au8[4],
+                                                       u.pNetAddr->uAddr.Mac.au8[5]);
+
+                                default:
+                                    return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+                                                       "unsupported-netaddr-type=%u", u.pNetAddr->enmType);
+
+                            }
+                        }
+                        return pfnOutput(pvArgOutput, s_szNull, sizeof(s_szNull) - 1);
+                    }
+
+                    case RTSF_UUID:
+                    {
+                        if (VALID_PTR(u.pUuid))
+                        {
+                            /* cannot call RTUuidToStr because of GC/R0. */
+                            return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+                                               "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+                                               RT_H2LE_U32(u.pUuid->Gen.u32TimeLow),
+                                               RT_H2LE_U16(u.pUuid->Gen.u16TimeMid),
+                                               RT_H2LE_U16(u.pUuid->Gen.u16TimeHiAndVersion),
+                                               u.pUuid->Gen.u8ClockSeqHiAndReserved,
+                                               u.pUuid->Gen.u8ClockSeqLow,
+                                               u.pUuid->Gen.au8Node[0],
+                                               u.pUuid->Gen.au8Node[1],
+                                               u.pUuid->Gen.au8Node[2],
+                                               u.pUuid->Gen.au8Node[3],
+                                               u.pUuid->Gen.au8Node[4],
+                                               u.pUuid->Gen.au8Node[5]);
+                        }
+                        return pfnOutput(pvArgOutput, s_szNull, sizeof(s_szNull) - 1);
+                    }
+
+                    default:
+                        AssertMsgFailed(("Internal error %d\n", s_aTypes[i].enmFormat));
+                        return 0;
+                }
+
+                /*
+                 * Finally, output the formatted string and return.
+                 */
+                return pfnOutput(pvArgOutput, szBuf, cch);
+            }
+
+
+            /* Group 3 */
+
+            /*
+             * Base name printing.
+             */
+            case 'b':
+            {
+                switch (*(*ppszFormat)++)
+                {
+                    case 'n':
+                    {
+                        const char *pszLastSep;
+                        const char *psz = pszLastSep = va_arg(*pArgs, const char *);
+                        if (!VALID_PTR(psz))
+                            return pfnOutput(pvArgOutput, RT_STR_TUPLE("<null>"));
+
+                        while ((ch = *psz) != '\0')
+                        {
+                            if (RTPATH_IS_SEP(ch))
+                            {
+                                do
+                                    psz++;
+                                while ((ch = *psz) != '\0' && RTPATH_IS_SEP(ch));
+                                if (!ch)
+                                    break;
+                                pszLastSep = psz;
+                            }
+                            psz++;
+                        }
+
+                        return pfnOutput(pvArgOutput, pszLastSep, psz - pszLastSep);
+                    }
+
+                    default:
+                        AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
+                        break;
+                }
+                break;
+            }
+
+
+            /*
+             * Pretty function / method name printing.
+             */
+            case 'f':
+            {
+                switch (*(*ppszFormat)++)
+                {
+                    /*
+                     * Pretty function / method name printing.
+                     * This isn't 100% right (see classic signal prototype) and it assumes
+                     * standardized names, but it'll do for today.
+                     */
+                    case 'n':
+                    {
+                        const char *pszStart;
+                        const char *psz = pszStart = va_arg(*pArgs, const char *);
+                        int cAngle = 0;
+
+                        if (!VALID_PTR(psz))
+                            return pfnOutput(pvArgOutput, RT_STR_TUPLE("<null>"));
+
+                        while ((ch = *psz) != '\0' && ch != '(')
+                        {
+                            if (RT_C_IS_BLANK(ch))
+                            {
+                                psz++;
+                                while ((ch = *psz) != '\0' && (RT_C_IS_BLANK(ch) || ch == '('))
+                                    psz++;
+                                if (ch && cAngle == 0)
+                                    pszStart = psz;
+                            }
+                            else if (ch == '(')
+                                break;
+                            else if (ch == '<')
+                            {
+                                cAngle++;
+                                psz++;
+                            }
+                            else if (ch == '>')
+                            {
+                                cAngle--;
+                                psz++;
+                            }
+                            else
+                                psz++;
+                        }
+
+                        return pfnOutput(pvArgOutput, pszStart, psz - pszStart);
+                    }
+
+                    default:
+                        AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
+                        break;
+                }
+                break;
+            }
+
+
+            /*
+             * hex dumping and COM/XPCOM.
+             */
+            case 'h':
+            {
+                switch (*(*ppszFormat)++)
+                {
+                    /*
+                     * Hex stuff.
+                     */
+                    case 'x':
+                    {
+                        uint8_t *pu8 = va_arg(*pArgs, uint8_t *);
+                        if (cchPrecision < 0)
+                            cchPrecision = 16;
+                        if (pu8)
+                        {
+                            switch (*(*ppszFormat)++)
+                            {
+                                /*
+                                 * Regular hex dump.
+                                 */
+                                case 'd':
+                                {
+                                    int off = 0;
+                                    cch = 0;
+
+                                    if (cchWidth <= 0)
+                                        cchWidth = 16;
+
+                                    while (off < cchPrecision)
+                                    {
+                                        int i;
+                                        cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%s%0*p %04x:", off ? "\n" : "", sizeof(pu8) * 2, (uintptr_t)pu8, off);
+                                        for (i = 0; i < cchWidth && off + i < cchPrecision ; i++)
+                                            cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+                                                               off + i < cchPrecision ? !(i & 7) && i ? "-%02x" : " %02x" : "   ", pu8[i]);
+                                        while (i++ < cchWidth)
+                                            cch += pfnOutput(pvArgOutput, "   ", 3);
+
+                                        cch += pfnOutput(pvArgOutput, " ", 1);
+
+                                        for (i = 0; i < cchWidth && off + i < cchPrecision; i++)
+                                        {
+                                            uint8_t u8 = pu8[i];
+                                            cch += pfnOutput(pvArgOutput, u8 < 127 && u8 >= 32 ? (const char *)&u8 : ".", 1);
+                                        }
+
+                                        /* next */
+                                        pu8 += cchWidth;
+                                        off += cchWidth;
+                                    }
+                                    return cch;
+                                }
+
+                                /*
+                                 * Hex string.
+                                 */
+                                case 's':
+                                {
+                                    if (cchPrecision-- > 0)
+                                    {
+                                        cch = RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%02x", *pu8++);
+                                        for (; cchPrecision > 0; cchPrecision--, pu8++)
+                                            cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, " %02x", *pu8);
+                                        return cch;
+                                    }
+                                    break;
+                                }
+
+                                default:
+                                    AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
+                                    break;
+                            }
+                        }
+                        else
+                            return pfnOutput(pvArgOutput, RT_STR_TUPLE("<null>"));
+                        break;
+                    }
+
+
+#ifdef IN_RING3
+                    /*
+                     * XPCOM / COM status code: %Rhrc, %Rhrf, %Rhra
+                     * ASSUMES: If Windows Then COM else XPCOM.
+                     */
+                    case 'r':
+                    {
+                        uint32_t hrc = va_arg(*pArgs, uint32_t);
+                        PCRTCOMERRMSG pMsg = RTErrCOMGet(hrc);
+                        switch (*(*ppszFormat)++)
+                        {
+                            case 'c':
+                                return pfnOutput(pvArgOutput, pMsg->pszDefine, strlen(pMsg->pszDefine));
+                            case 'f':
+                                return pfnOutput(pvArgOutput, pMsg->pszMsgFull,strlen(pMsg->pszMsgFull));
+                            case 'a':
+                                return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%s (0x%08X) - %s", pMsg->pszDefine, hrc, pMsg->pszMsgFull);
+                            default:
+                                AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
+                                return 0;
+                        }
+                        break;
+                    }
+#endif /* IN_RING3 */
+
+                    default:
+                        AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
+                        return 0;
+
+                }
+                break;
+            }
+
+            /*
+             * iprt status code: %Rrc, %Rrs, %Rrf, %Rra.
+             */
+            case 'r':
+            {
+                int rc = va_arg(*pArgs, int);
+#ifdef IN_RING3                         /* we don't want this anywhere else yet. */
+                PCRTSTATUSMSG pMsg = RTErrGet(rc);
+                switch (*(*ppszFormat)++)
+                {
+                    case 'c':
+                        return pfnOutput(pvArgOutput, pMsg->pszDefine,    strlen(pMsg->pszDefine));
+                    case 's':
+                        return pfnOutput(pvArgOutput, pMsg->pszMsgShort,  strlen(pMsg->pszMsgShort));
+                    case 'f':
+                        return pfnOutput(pvArgOutput, pMsg->pszMsgFull,   strlen(pMsg->pszMsgFull));
+                    case 'a':
+                        return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%s (%d) - %s", pMsg->pszDefine, rc, pMsg->pszMsgFull);
+                    default:
+                        AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
+                        return 0;
+                }
+#else /* !IN_RING3 */
+                switch (*(*ppszFormat)++)
+                {
+                    case 'c':
+                    case 's':
+                    case 'f':
+                    case 'a':
+                        return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%d", rc);
+                    default:
+                        AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
+                        return 0;
+                }
+#endif /* !IN_RING3 */
+                break;
+            }
+
+#if defined(IN_RING3)
+            /*
+             * Windows status code: %Rwc, %Rwf, %Rwa
+             */
+            case 'w':
+            {
+                long rc = va_arg(*pArgs, long);
+# if defined(RT_OS_WINDOWS)
+                PCRTWINERRMSG pMsg = RTErrWinGet(rc);
+# endif
+                switch (*(*ppszFormat)++)
+                {
+# if defined(RT_OS_WINDOWS)
+                    case 'c':
+                        return pfnOutput(pvArgOutput, pMsg->pszDefine, strlen(pMsg->pszDefine));
+                    case 'f':
+                        return pfnOutput(pvArgOutput, pMsg->pszMsgFull,strlen(pMsg->pszMsgFull));
+                    case 'a':
+                        return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%s (0x%08X) - %s", pMsg->pszDefine, rc, pMsg->pszMsgFull);
+# else
+                    case 'c':
+                    case 'f':
+                    case 'a':
+                        return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "0x%08X", rc);
+# endif
+                    default:
+                        AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
+                        return 0;
+                }
+                break;
+            }
+#endif /* IN_RING3 */
+
+            /*
+             * Group 4, structure dumpers.
+             */
+            case 'D':
+            {
+                /*
+                 * Interpret the type.
+                 */
+                typedef enum
+                {
+                    RTST_TIMESPEC
+                } RTST;
+/** Set if it's a pointer */
+#define RTST_FLAGS_POINTER  RT_BIT(0)
+                static const struct
+                {
+                    uint8_t     cch;        /**< the length of the string. */
+                    char        sz[16-2];   /**< the part following 'R'. */
+                    uint8_t     cb;         /**< the size of the argument. */
+                    uint8_t     fFlags;     /**< RTST_FLAGS_* */
+                    RTST        enmType;    /**< The structure type. */
+                }
+                /** Sorted array of types, looked up using binary search! */
+                s_aTypes[] =
+                {
+#define STRMEM(str) sizeof(str) - 1, str
+                    { STRMEM("Dtimespec"),   sizeof(PCRTTIMESPEC),  RTST_FLAGS_POINTER, RTST_TIMESPEC},
+#undef STRMEM
+                };
+                const char *pszType = *ppszFormat - 1;
+                int         iStart  = 0;
+                int         iEnd    = RT_ELEMENTS(s_aTypes) - 1;
+                int         i       = RT_ELEMENTS(s_aTypes) / 2;
+
+                union
+                {
+                    const void     *pv;
+                    uint64_t        u64;
+                    PCRTTIMESPEC    pTimeSpec;
+                } u;
+
+                AssertMsg(!chArgSize, ("Not argument size '%c' for RT types! '%.10s'\n", chArgSize, pszFormatOrg));
+
+                /*
+                 * Lookup the type - binary search.
+                 */
+                for (;;)
+                {
+                    int iDiff = strncmp(pszType, s_aTypes[i].sz, s_aTypes[i].cch);
+                    if (!iDiff)
+                        break;
+                    if (iEnd == iStart)
+                    {
+                        AssertMsgFailed(("Invalid format type '%.10s'!\n", pszFormatOrg));
+                        return 0;
+                    }
+                    if (iDiff < 0)
+                        iEnd = i - 1;
+                    else
+                        iStart = i + 1;
+                    if (iEnd < iStart)
+                    {
+                        AssertMsgFailed(("Invalid format type '%.10s'!\n", pszFormatOrg));
+                        return 0;
+                    }
+                    i = iStart + (iEnd - iStart) / 2;
+                }
+                *ppszFormat += s_aTypes[i].cch - 1;
+
+                /*
+                 * Fetch the argument.
+                 */
+                u.u64 = 0;
+                switch (s_aTypes[i].cb)
+                {
+                    case sizeof(const void *):
+                        u.pv = va_arg(*pArgs, const void *);
+                        break;
+                    default:
+                        AssertMsgFailed(("Invalid format error, size %d'!\n", s_aTypes[i].cb));
+                        break;
+                }
+
+                /*
+                 * If it's a pointer, we'll check if it's valid before going on.
+                 */
+                if ((s_aTypes[i].fFlags & RTST_FLAGS_POINTER) && !VALID_PTR(u.pv))
+                    return pfnOutput(pvArgOutput, RT_STR_TUPLE("<null>"));
+
+                /*
+                 * Format the output.
+                 */
+                switch (s_aTypes[i].enmType)
+                {
+                    case RTST_TIMESPEC:
+                        return RTStrFormat(pfnOutput, pvArgOutput, NULL, NULL, "%'lld ns", RTTimeSpecGetNano(u.pTimeSpec));
+
+                    default:
+                        AssertMsgFailed(("Invalid/unhandled enmType=%d\n", s_aTypes[i].enmType));
+                        break;
+                }
+                break;
+            }
+
+#ifdef IN_RING3
+            /*
+             * Group 5, XML / HTML escapers.
+             */
+            case 'M':
+            {
+                char chWhat = (*ppszFormat)[0];
+                bool fAttr  = chWhat == 'a';
+                char chType = (*ppszFormat)[1];
+                AssertMsgBreak(chWhat == 'a' || chWhat == 'e', ("Invalid IPRT format type '%.10s'!\n", pszFormatOrg));
+                *ppszFormat += 2;
+                switch (chType)
+                {
+                    case 's':
+                    {
+                        static const char   s_szElemEscape[] = "<>&\"'";
+                        static const char   s_szAttrEscape[] = "<>&\"\n\r"; /* more? */
+                        const char * const  pszEscape =  fAttr ?             s_szAttrEscape  :             s_szElemEscape;
+                        size_t       const  cchEscape = (fAttr ? RT_ELEMENTS(s_szAttrEscape) : RT_ELEMENTS(s_szElemEscape)) - 1;
+                        size_t      cchOutput = 0;
+                        const char *pszStr    = va_arg(*pArgs, char *);
+                        ssize_t     cchStr;
+                        ssize_t     offCur;
+                        ssize_t     offLast;
+
+                        if (!VALID_PTR(pszStr))
+                            pszStr = "<NULL>";
+                        cchStr = RTStrNLen(pszStr, (unsigned)cchPrecision);
+
+                        if (fAttr)
+                            cchOutput += pfnOutput(pvArgOutput, "\"", 1);
+                        if (!(fFlags & RTSTR_F_LEFT))
+                            while (--cchWidth >= cchStr)
+                                cchOutput += pfnOutput(pvArgOutput, " ", 1);
+
+                        offLast = offCur = 0;
+                        while (offCur < cchStr)
+                        {
+                            if (memchr(pszEscape, pszStr[offCur], cchEscape))
+                            {
+                                if (offLast < offCur)
+                                    cchOutput += pfnOutput(pvArgOutput, &pszStr[offLast], offCur - offLast);
+                                switch (pszStr[offCur])
+                                {
+                                    case '<':   cchOutput += pfnOutput(pvArgOutput, "&lt;", 4); break;
+                                    case '>':   cchOutput += pfnOutput(pvArgOutput, "&gt;", 4); break;
+                                    case '&':   cchOutput += pfnOutput(pvArgOutput, "&amp;", 5); break;
+                                    case '\'':  cchOutput += pfnOutput(pvArgOutput, "&apos;", 6); break;
+                                    case '"':   cchOutput += pfnOutput(pvArgOutput, "&quot;", 6); break;
+                                    case '\n':  cchOutput += pfnOutput(pvArgOutput, "&#xA;", 5); break;
+                                    case '\r':  cchOutput += pfnOutput(pvArgOutput, "&#xD;", 5); break;
+                                    default:
+                                        AssertFailed();
+                                }
+                                offLast = offCur + 1;
+                            }
+                            offCur++;
+                        }
+                        if (offLast < offCur)
+                            cchOutput += pfnOutput(pvArgOutput, &pszStr[offLast], offCur - offLast);
+
+                        while (--cchWidth >= cchStr)
+                            cchOutput += pfnOutput(pvArgOutput, " ", 1);
+                        if (fAttr)
+                            cchOutput += pfnOutput(pvArgOutput, "\"", 1);
+                        return cchOutput;
+                    }
+
+                    default:
+                        AssertMsgFailed(("Invalid IPRT format type '%.10s'!\n", pszFormatOrg));
+                }
+                break;
+            }
+#endif /* IN_RING3 */
+
+
+            /*
+             * Groups 6 - CPU Architecture Register Formatters.
+             *            "%RAarch[reg]"
+             */
+            case 'A':
+            {
+                char const * const  pszArch   = *ppszFormat;
+                const char         *pszReg    = pszArch;
+                size_t              cchOutput = 0;
+                int                 cPrinted  = 0;
+                size_t              cchReg;
+
+                /* Parse out the */
+                while ((ch = *pszReg++) && ch != '[')
+                {   /* nothing */   }
+                AssertMsgBreak(ch == '[', ("Malformed IPRT architecture register format type '%.10s'!\n", pszFormatOrg));
+
+                cchReg = 0;
+                while ((ch = pszReg[cchReg]) && ch != ']')
+                    cchReg++;
+                AssertMsgBreak(ch == ']', ("Malformed IPRT architecture register format type '%.10s'!\n", pszFormatOrg));
+
+                *ppszFormat = &pszReg[cchReg + 1];
+
+
+#define REG_EQUALS(a_szReg)  (sizeof(a_szReg) - 1 == cchReg && !strncmp(a_szReg, pszReg, sizeof(a_szReg) - 1))
+#define REG_OUT_BIT(a_uVal, a_fBitMask, a_szName) \
+    do { \
+        if ((a_uVal) & (a_fBitMask)) \
+        { \
+            if (!cPrinted++) \
+                cchOutput += pfnOutput(pvArgOutput, "{" a_szName, sizeof(a_szName)); \
+            else \
+                cchOutput += pfnOutput(pvArgOutput, "," a_szName, sizeof(a_szName)); \
+           (a_uVal) &= ~(a_fBitMask); \
+        } \
+    } while (0)
+#define REG_OUT_CLOSE(a_uVal) \
+    do { \
+        if ((a_uVal)) \
+        { \
+            cchOutput += pfnOutput(pvArgOutput, !cPrinted ? "{unkn=" : ",unkn=", 6); \
+            cch = RTStrFormatNumber(&szBuf[0], (a_uVal), 16, 1, -1, fFlags); \
+            cchOutput += pfnOutput(pvArgOutput, szBuf, cch); \
+            cPrinted++; \
+        } \
+        if (cPrinted) \
+            cchOutput += pfnOutput(pvArgOutput, "}", 1); \
+    } while (0)
+
+
+                if (0)
+                { /* dummy */ }
+#ifdef STRFORMAT_WITH_X86
+                /*
+                 * X86 & AMD64.
+                 */
+                else if (   pszReg - pszArch == 3 + 1
+                         && pszArch[0] == 'x'
+                         && pszArch[1] == '8'
+                         && pszArch[2] == '6')
+                {
+                    if (REG_EQUALS("cr0"))
+                    {
+                        uint64_t cr0 = va_arg(*pArgs, uint64_t);
+                        fFlags |= RTSTR_F_64BIT;
+                        cch = RTStrFormatNumber(&szBuf[0], cr0, 16, 8, -1, fFlags | RTSTR_F_ZEROPAD);
+                        cchOutput += pfnOutput(pvArgOutput, szBuf, cch);
+                        REG_OUT_BIT(cr0, X86_CR0_PE, "PE");
+                        REG_OUT_BIT(cr0, X86_CR0_MP, "MP");
+                        REG_OUT_BIT(cr0, X86_CR0_EM, "EM");
+                        REG_OUT_BIT(cr0, X86_CR0_TS, "DE");
+                        REG_OUT_BIT(cr0, X86_CR0_ET, "ET");
+                        REG_OUT_BIT(cr0, X86_CR0_NE, "NE");
+                        REG_OUT_BIT(cr0, X86_CR0_WP, "WP");
+                        REG_OUT_BIT(cr0, X86_CR0_AM, "AM");
+                        REG_OUT_BIT(cr0, X86_CR0_NW, "NW");
+                        REG_OUT_BIT(cr0, X86_CR0_CD, "CD");
+                        REG_OUT_BIT(cr0, X86_CR0_PG, "PG");
+                        REG_OUT_CLOSE(cr0);
+                    }
+                    else if (REG_EQUALS("cr4"))
+                    {
+                        uint64_t cr4 = va_arg(*pArgs, uint64_t);
+                        fFlags |= RTSTR_F_64BIT;
+                        cch = RTStrFormatNumber(&szBuf[0], cr4, 16, 8, -1, fFlags | RTSTR_F_ZEROPAD);
+                        cchOutput += pfnOutput(pvArgOutput, szBuf, cch);
+                        REG_OUT_BIT(cr4, X86_CR4_VME, "VME");
+                        REG_OUT_BIT(cr4, X86_CR4_PVI, "PVI");
+                        REG_OUT_BIT(cr4, X86_CR4_TSD, "TSD");
+                        REG_OUT_BIT(cr4, X86_CR4_DE,  "DE");
+                        REG_OUT_BIT(cr4, X86_CR4_PSE, "PSE");
+                        REG_OUT_BIT(cr4, X86_CR4_PAE, "PAE");
+                        REG_OUT_BIT(cr4, X86_CR4_MCE, "MCE");
+                        REG_OUT_BIT(cr4, X86_CR4_PGE, "PGE");
+                        REG_OUT_BIT(cr4, X86_CR4_PCE, "PCE");
+                        REG_OUT_BIT(cr4, X86_CR4_OSFXSR, "OSFXSR");
+                        REG_OUT_BIT(cr4, X86_CR4_OSXMMEEXCPT, "OSXMMEEXCPT");
+                        REG_OUT_BIT(cr4, X86_CR4_VMXE, "VMXE");
+                        REG_OUT_BIT(cr4, X86_CR4_SMXE, "SMXE");
+                        REG_OUT_BIT(cr4, X86_CR4_PCIDE, "PCIDE");
+                        REG_OUT_BIT(cr4, X86_CR4_OSXSAVE, "OSXSAVE");
+                        REG_OUT_BIT(cr4, X86_CR4_SMEP, "SMEP");
+                        REG_OUT_BIT(cr4, X86_CR4_SMAP, "SMAP");
+                        REG_OUT_CLOSE(cr4);
+                    }
+                    else
+                        AssertMsgFailed(("Unknown x86 register specified in '%.10s'!\n", pszFormatOrg));
+                }
+#endif
+                else
+                    AssertMsgFailed(("Unknown architecture specified in '%.10s'!\n", pszFormatOrg));
+#undef REG_OUT_BIT
+#undef REG_OUT_CLOSE
+#undef REG_EQUALS
+                return cchOutput;
+            }
+
+            /*
+             * Invalid/Unknown. Bitch about it.
+             */
+            default:
+                AssertMsgFailed(("Invalid IPRT format type '%.10s'!\n", pszFormatOrg));
+                break;
+        }
+    }
+    else
+        AssertMsgFailed(("Invalid IPRT format type '%.10s'!\n", pszFormatOrg));
+
+    NOREF(pszFormatOrg);
+    return 0;
+}
+
diff --git a/ubuntu/vbox/vboxguest/common/string/strformattype.c b/ubuntu/vbox/vboxguest/common/string/strformattype.c
new file mode 100644 (file)
index 0000000..def13a7
--- /dev/null
@@ -0,0 +1,476 @@
+/* $Id: strformattype.cpp $ */
+/** @file
+ * IPRT - IPRT String Formatter Extensions, Dynamic Types.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_STRING
+#include <iprt/string.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/stdarg.h>
+#include <iprt/asm.h>
+#include "internal/string.h"
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+#ifdef RT_STRICT
+# define RTSTRFORMATTYPE_WITH_LOCKING
+#endif
+#ifdef RTSTRFORMATTYPE_WITH_LOCKING
+# define RTSTRFORMATTYPE_LOCK_OFFSET    0x7fff0000
+#endif
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * Description of a registered formatting type.
+ *
+ * In GC we'll be using offsets instead of pointers just to try avoid having to
+ * do the bothersome relocating. This of course assumes that all the relevant
+ * code stays within the same mapping.
+ */
+typedef struct RTSTRDYNFMT
+{
+    /** The length of the type. */
+    uint8_t             cchType;
+    /** The type name. */
+    char                szType[47];
+    /** The handler function.
+     * In GC the offset is relative to g_aTypes[0], so that &g_aTypes[0] + offHandler
+     * gives the actual address. */
+#ifdef IN_RC
+    int32_t             offHandler;
+#else
+    PFNRTSTRFORMATTYPE  pfnHandler;
+#endif
+    /** Callback argument. */
+    void * volatile     pvUser;
+#if ARCH_BITS == 32
+    /** Size alignment padding. */
+    char                abPadding[8];
+#endif
+} RTSTRDYNFMT;
+AssertCompileSizeAlignment(RTSTRDYNFMT, 32);
+typedef RTSTRDYNFMT *PRTSTRDYNFMT;
+typedef RTSTRDYNFMT const *PCRTSTRDYNFMT;
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** The registered types, sorted for binary lookup.
+ * We use a static array here because it avoids RTMemAlloc dependencies+leaks. */
+static RTSTRDYNFMT      g_aTypes[64];
+/** The number of registered types. */
+static uint32_t         g_cTypes = 0;
+#ifdef RTSTRFORMATTYPE_WITH_LOCKING
+/** This is just a thing we assert/spin on.
+ * Zero == unlocked, negative == write locked, positive == read locked.
+ *
+ * The user should do all the serialization and we'll smack his fingers in
+ * strict builds if he doesn't. */
+static int32_t volatile g_i32Spinlock = 0;
+#endif
+
+
+/**
+ * Locks the stuff for updating.
+ *
+ * Mostly for check that the caller is doing his job.
+ */
+DECLINLINE(void) rtstrFormatTypeWriteLock(void)
+{
+#if defined(RTSTRFORMATTYPE_WITH_LOCKING)
+    if (RT_UNLIKELY(!ASMAtomicCmpXchgS32(&g_i32Spinlock, -RTSTRFORMATTYPE_LOCK_OFFSET, 0)))
+    {
+        unsigned volatile i;
+
+        AssertFailed();
+        for (i = 0;; i++)
+            if (    !g_i32Spinlock
+                &&  ASMAtomicCmpXchgS32(&g_i32Spinlock, -RTSTRFORMATTYPE_LOCK_OFFSET, 0))
+                break;
+    }
+#endif
+}
+
+
+/**
+ * Undoing rtstrFormatTypeWriteLock.
+ */
+DECLINLINE(void) rtstrFormatTypeWriteUnlock(void)
+{
+#if defined(RTSTRFORMATTYPE_WITH_LOCKING)
+    Assert(g_i32Spinlock < 0);
+    ASMAtomicAddS32(&g_i32Spinlock, RTSTRFORMATTYPE_LOCK_OFFSET);
+#endif
+}
+
+
+/**
+ * Locks the stuff for reading.
+ *
+ * This is just cheap stuff to make sure the caller is doing the right thing.
+ */
+DECLINLINE(void) rtstrFormatTypeReadLock(void)
+{
+#if defined(RTSTRFORMATTYPE_WITH_LOCKING)
+    if (RT_UNLIKELY(ASMAtomicIncS32(&g_i32Spinlock) < 0))
+    {
+        unsigned volatile i;
+
+        AssertFailed();
+        for (i = 0;; i++)
+            if (ASMAtomicUoReadS32(&g_i32Spinlock) > 0)
+                break;
+    }
+#endif
+}
+
+
+/**
+ * Undoing rtstrFormatTypeReadLock.
+ */
+DECLINLINE(void) rtstrFormatTypeReadUnlock(void)
+{
+#if defined(RTSTRFORMATTYPE_WITH_LOCKING)
+    Assert(g_i32Spinlock > 0);
+    ASMAtomicDecS32(&g_i32Spinlock);
+#endif
+}
+
+
+/**
+ * Compares a type string with a type entry, the string doesn't need to be terminated.
+ *
+ * @returns Same as memcmp.
+ * @param   pszType     The type string, doesn't need to be terminated.
+ * @param   cchType     The number of chars in @a pszType to compare.
+ * @param   pType       The type entry to compare with.
+ */
+DECLINLINE(int) rtstrFormatTypeCompare(const char *pszType, size_t cchType, PCRTSTRDYNFMT pType)
+{
+    size_t cch = RT_MIN(cchType, pType->cchType);
+    int iDiff = memcmp(pszType, pType->szType, cch);
+    if (!iDiff)
+    {
+        if (cchType == pType->cchType)
+            return 0;
+        iDiff = cchType < pType->cchType ? -1 : 1;
+    }
+    return iDiff;
+}
+
+
+/**
+ * Looks up a type entry.
+ *
+ * @returns The type index, -1 on failure.
+ * @param   pszType     The type to look up. This doesn't have to be terminated.
+ * @param   cchType     The length of the type.
+ */
+DECLINLINE(int32_t) rtstrFormatTypeLookup(const char *pszType, size_t cchType)
+{
+    /*
+     * Lookup the type - binary search.
+     */
+    int32_t iStart = 0;
+    int32_t iEnd   = g_cTypes - 1;
+    int32_t i      = iEnd / 2;
+    for (;;)
+    {
+        int iDiff = rtstrFormatTypeCompare(pszType, cchType, &g_aTypes[i]);
+        if (!iDiff)
+            return i;
+        if (iEnd == iStart)
+            break;
+        if (iDiff < 0)
+            iEnd = i - 1;
+        else
+            iStart = i + 1;
+        if (iEnd < iStart)
+            break;
+        i = iStart + (iEnd - iStart) / 2;
+    }
+    return -1;
+}
+
+
+/**
+ * Register a format handler for a type.
+ *
+ * The format handler is used to handle '%R[type]' format types, where the argument
+ * in the vector is a pointer value (a bit restrictive, but keeps it simple).
+ *
+ * The caller must ensure that no other thread will be making use of any of
+ * the dynamic formatting type facilities simultaneously with this call.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_ALREADY_EXISTS if the type has already been registered.
+ * @retval  VERR_TOO_MANY_OPEN_FILES if all the type slots has been allocated already.
+ *
+ * @param   pszType         The type name.
+ * @param   pfnHandler      The handler address. See FNRTSTRFORMATTYPE for details.
+ * @param   pvUser          The user argument to pass to the handler. See RTStrFormatTypeSetUser
+ *                          for how to update this later.
+ */
+RTDECL(int) RTStrFormatTypeRegister(const char *pszType, PFNRTSTRFORMATTYPE pfnHandler, void *pvUser)
+{
+    int rc;
+    size_t cchType;
+    uint32_t cTypes;
+
+    /*
+     * Validate input.
+     */
+    AssertPtr(pfnHandler);
+    AssertPtr(pszType);
+    cchType = strlen(pszType);
+    AssertReturn(cchType < RT_SIZEOFMEMB(RTSTRDYNFMT, szType), VERR_INVALID_PARAMETER);
+
+    /*
+     * Try add it.
+     */
+    rtstrFormatTypeWriteLock();
+
+    /* check that there are empty slots. */
+    cTypes = g_cTypes;
+    if (cTypes < RT_ELEMENTS(g_aTypes))
+    {
+        /* find where to insert it. */
+        uint32_t i = 0;
+        rc = VINF_SUCCESS;
+        while (i < cTypes)
+        {
+            int iDiff = rtstrFormatTypeCompare(pszType, cchType, &g_aTypes[i]);
+            if (!iDiff)
+            {
+                rc = VERR_ALREADY_EXISTS;
+                break;
+            }
+            if (iDiff < 0)
+                break;
+            i++;
+        }
+        if (RT_SUCCESS(rc))
+        {
+            /* make room. */
+            uint32_t cToMove = cTypes - i;
+            if (cToMove)
+                memmove(&g_aTypes[i + 1], &g_aTypes[i], cToMove * sizeof(g_aTypes[i]));
+
+            /* insert the new entry. */
+            memset(&g_aTypes[i], 0, sizeof(g_aTypes[i]));
+            memcpy(&g_aTypes[i].szType[0], pszType, cchType + 1);
+            g_aTypes[i].cchType = (uint8_t)cchType;
+            g_aTypes[i].pvUser = pvUser;
+#ifdef IN_RC
+            g_aTypes[i].offHandler = (intptr_t)pfnHandler - (intptr_t)&g_aTypes[0];
+#else
+            g_aTypes[i].pfnHandler = pfnHandler;
+#endif
+            ASMAtomicIncU32(&g_cTypes);
+            rc = VINF_SUCCESS;
+        }
+    }
+    else
+        rc = VERR_TOO_MANY_OPEN_FILES; /** @todo fix error code */
+
+    rtstrFormatTypeWriteUnlock();
+
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrFormatTypeRegister);
+
+
+/**
+ * Deregisters a format type.
+ *
+ * The caller must ensure that no other thread will be making use of any of
+ * the dynamic formatting type facilities simultaneously with this call.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_FILE_NOT_FOUND if not found.
+ *
+ * @param   pszType     The type to deregister.
+ */
+RTDECL(int) RTStrFormatTypeDeregister(const char *pszType)
+{
+    int32_t i;
+
+    /*
+     * Validate input.
+     */
+    AssertPtr(pszType);
+
+    /*
+     * Locate the entry and remove it.
+     */
+    rtstrFormatTypeWriteLock();
+    i = rtstrFormatTypeLookup(pszType, strlen(pszType));
+    if (i >= 0)
+    {
+        const uint32_t cTypes = g_cTypes;
+        int32_t cToMove = cTypes - i - 1;
+        if (cToMove > 0)
+            memmove(&g_aTypes[i], &g_aTypes[i + 1], cToMove * sizeof(g_aTypes[i]));
+        memset(&g_aTypes[cTypes - 1], 0, sizeof(g_aTypes[0]));
+        ASMAtomicDecU32(&g_cTypes);
+    }
+    rtstrFormatTypeWriteUnlock();
+
+    Assert(i >= 0);
+    return i >= 0
+         ? VINF_SUCCESS
+         : VERR_FILE_NOT_FOUND; /** @todo fix status code */
+}
+RT_EXPORT_SYMBOL(RTStrFormatTypeDeregister);
+
+
+/**
+ * Sets the user argument for a type.
+ *
+ * This can be used if a user argument needs relocating in GC.
+ *
+ * @returns IPRT status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_FILE_NOT_FOUND if not found.
+ *
+ * @param   pszType     The type to update.
+ * @param   pvUser      The new user argument value.
+ */
+RTDECL(int) RTStrFormatTypeSetUser(const char *pszType, void *pvUser)
+{
+    int32_t i;
+
+    /*
+     * Validate input.
+     */
+    AssertPtr(pszType);
+
+    /*
+     * Locate the entry and update it.
+     */
+    rtstrFormatTypeReadLock();
+
+    i = rtstrFormatTypeLookup(pszType, strlen(pszType));
+    if (i >= 0)
+        ASMAtomicWritePtr(&g_aTypes[i].pvUser, pvUser);
+
+    rtstrFormatTypeReadUnlock();
+
+    Assert(i >= 0);
+    return i >= 0
+         ? VINF_SUCCESS
+         : VERR_FILE_NOT_FOUND; /** @todo fix status code */
+}
+RT_EXPORT_SYMBOL(RTStrFormatTypeSetUser);
+
+
+/**
+ * Formats a type using a registered callback handler.
+ *
+ * This will handle %R[type].
+ *
+ * @returns The number of bytes formatted.
+ * @param   pfnOutput       Pointer to output function.
+ * @param   pvArgOutput     Argument for the output function.
+ * @param   ppszFormat      Pointer to the format string pointer. Advance this till the char
+ *                          after the format specifier.
+ * @param   pArgs           Pointer to the argument list. Use this to fetch the arguments.
+ * @param   cchWidth        Format Width. -1 if not specified.
+ * @param   cchPrecision    Format Precision. -1 if not specified.
+ * @param   fFlags          Flags (RTSTR_NTFS_*).
+ * @param   chArgSize       The argument size specifier, 'l' or 'L'.
+ */
+DECLHIDDEN(size_t) rtstrFormatType(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, const char **ppszFormat,
+                                   va_list *pArgs, int cchWidth, int cchPrecision, unsigned fFlags, char chArgSize)
+{
+    size_t      cch;
+    int32_t     i;
+    char const *pszTypeEnd;
+    char const *pszType;
+    char        ch;
+    void       *pvValue = va_arg(*pArgs, void *);
+    NOREF(chArgSize);
+
+    /*
+     * Parse out the type.
+     */
+    pszType = *ppszFormat + 2;
+    *ppszFormat = pszType;
+    Assert(pszType[-1] == '[');
+    Assert(pszType[-2] == 'R');
+    pszTypeEnd = pszType;
+    while ((ch = *pszTypeEnd) != ']')
+    {
+        AssertReturn(ch != '\0', 0);
+        AssertReturn(ch != '%', 0);
+        AssertReturn(ch != '[', 0);
+        pszTypeEnd++;
+    }
+    *ppszFormat = pszTypeEnd + 1;
+
+    /*
+     * Locate the entry and call the handler.
+     */
+    rtstrFormatTypeReadLock();
+
+    i = rtstrFormatTypeLookup(pszType, pszTypeEnd - pszType);
+    if (RT_LIKELY(i >= 0))
+    {
+#ifdef IN_RC
+        PFNRTSTRFORMATTYPE pfnHandler = (PFNRTSTRFORMATTYPE)((intptr_t)&g_aTypes[0] + g_aTypes[i].offHandler);
+#else
+        PFNRTSTRFORMATTYPE pfnHandler = g_aTypes[i].pfnHandler;
+#endif
+        void *pvUser = ASMAtomicReadPtr(&g_aTypes[i].pvUser);
+
+        rtstrFormatTypeReadUnlock();
+
+        cch = pfnHandler(pfnOutput, pvArgOutput, g_aTypes[i].szType, pvValue, cchWidth, cchPrecision, fFlags, pvUser);
+    }
+    else
+    {
+        rtstrFormatTypeReadUnlock();
+
+        cch  = pfnOutput(pvArgOutput, RT_STR_TUPLE("<missing:%R["));
+        cch += pfnOutput(pvArgOutput, pszType, pszTypeEnd - pszType);
+        cch += pfnOutput(pvArgOutput, RT_STR_TUPLE("]>"));
+    }
+
+    return cch;
+}
+
diff --git a/ubuntu/vbox/vboxguest/common/string/strprintf.c b/ubuntu/vbox/vboxguest/common/string/strprintf.c
new file mode 100644 (file)
index 0000000..741b7ba
--- /dev/null
@@ -0,0 +1,149 @@
+/* $Id: strprintf.cpp $ */
+/** @file
+ * IPRT - String Formatters.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/string.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/** strbufoutput() argument structure. */
+typedef struct STRBUFARG
+{
+    /** Pointer to current buffer position. */
+    char   *psz;
+    /** Number of bytes left in the buffer - not including the trailing zero. */
+    size_t  cch;
+} STRBUFARG;
+/** Pointer to a strbufoutput() argument structure. */
+typedef STRBUFARG *PSTRBUFARG;
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+static DECLCALLBACK(size_t) strbufoutput(void *pvArg, const char *pachChars, size_t cbChars);
+
+
+/**
+ * Output callback.
+ *
+ * @returns number of bytes written.
+ * @param   pvArg       Pointer to a STRBUFARG structure.
+ * @param   pachChars   Pointer to an array of utf-8 characters.
+ * @param   cbChars     Number of bytes in the character array pointed to by pachChars.
+ */
+static DECLCALLBACK(size_t) strbufoutput(void *pvArg, const char *pachChars, size_t cbChars)
+{
+    PSTRBUFARG  pArg = (PSTRBUFARG)pvArg;
+    char *pszCur = pArg->psz; /* We actually have to spell this out for VS2010, or it will load for each case. */
+
+    cbChars = RT_MIN(pArg->cch, cbChars);
+    if (cbChars)
+    {
+        pArg->cch -= cbChars;
+
+        /* Note! For VS2010/64 we need at least 7 case statements before it generates a jump table. */
+        switch (cbChars)
+        {
+            default:
+                memcpy(pszCur, pachChars, cbChars);
+                break;
+            case 8: pszCur[7] = pachChars[7]; /* fall thru */
+            case 7: pszCur[6] = pachChars[6]; /* fall thru */
+            case 6: pszCur[5] = pachChars[5]; /* fall thru */
+            case 5: pszCur[4] = pachChars[4]; /* fall thru */
+            case 4: pszCur[3] = pachChars[3]; /* fall thru */
+            case 3: pszCur[2] = pachChars[2]; /* fall thru */
+            case 2: pszCur[1] = pachChars[1]; /* fall thru */
+            case 1: pszCur[0] = pachChars[0]; /* fall thru */
+            case 0:
+                break;
+        }
+        pArg->psz = pszCur += cbChars;
+    }
+    *pszCur = '\0';
+
+    return cbChars;
+}
+
+
+RTDECL(size_t) RTStrPrintf(char *pszBuffer, size_t cchBuffer, const char *pszFormat, ...)
+{
+    /* Explicitly inline RTStrPrintfV + RTStrPrintfExV here because this is a frequently use API. */
+    STRBUFARG Arg;
+    va_list args;
+    size_t cbRet;
+
+    AssertMsgReturn(cchBuffer, ("Excellent idea! Format a string with no space for the output!\n"), 0);
+    Arg.psz = pszBuffer;
+    Arg.cch = cchBuffer - 1;
+
+    va_start(args, pszFormat);
+    cbRet = RTStrFormatV(strbufoutput, &Arg, NULL, NULL, pszFormat, args);
+    va_end(args);
+
+    return cbRet;
+}
+RT_EXPORT_SYMBOL(RTStrPrintf);
+
+
+RTDECL(size_t) RTStrPrintfExV(PFNSTRFORMAT pfnFormat, void *pvArg, char *pszBuffer, size_t cchBuffer, const char *pszFormat, va_list args)
+{
+    STRBUFARG Arg;
+    AssertMsgReturn(cchBuffer, ("Excellent idea! Format a string with no space for the output!\n"), 0);
+    Arg.psz = pszBuffer;
+    Arg.cch = cchBuffer - 1;
+    return RTStrFormatV(strbufoutput, &Arg, pfnFormat, pvArg, pszFormat, args);
+}
+RT_EXPORT_SYMBOL(RTStrPrintfExV);
+
+
+RTDECL(size_t) RTStrPrintfV(char *pszBuffer, size_t cchBuffer, const char *pszFormat, va_list args)
+{
+    return RTStrPrintfExV(NULL, NULL, pszBuffer, cchBuffer, pszFormat, args);
+}
+RT_EXPORT_SYMBOL(RTStrPrintfV);
+
+
+RTDECL(size_t) RTStrPrintfEx(PFNSTRFORMAT pfnFormat, void *pvArg, char *pszBuffer, size_t cchBuffer, const char *pszFormat, ...)
+{
+    va_list args;
+    size_t cbRet;
+    va_start(args, pszFormat);
+    cbRet = RTStrPrintfExV(pfnFormat, pvArg, pszBuffer, cchBuffer, pszFormat, args);
+    va_end(args);
+    return cbRet;
+}
+RT_EXPORT_SYMBOL(RTStrPrintfEx);
+
diff --git a/ubuntu/vbox/vboxguest/common/string/strtonum.c b/ubuntu/vbox/vboxguest/common/string/strtonum.c
new file mode 100644 (file)
index 0000000..66c958a
--- /dev/null
@@ -0,0 +1,1013 @@
+/* $Id: strtonum.cpp $ */
+/** @file
+ * IPRT - String To Number Conversion.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/string.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/ctype.h> /* needed for RT_C_IS_DIGIT */
+#include <iprt/err.h>
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** 8-bit char -> digit. */
+static const unsigned char g_auchDigits[256] =
+{
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,255,255,255,255,255,255,
+    255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,255,255,255,255,255,
+    255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
+};
+/** Approximated overflow shift checks. */
+static const char g_auchShift[36] =
+{
+  /*  0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35 */
+     64, 64, 63, 63, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59
+};
+
+/*
+#include <stdio.h>
+int main()
+{
+    int i;
+    printf("static const unsigned char g_auchDigits[256] =\n"
+           "{");
+    for (i = 0; i < 256; i++)
+    {
+        int ch = 255;
+        if (i >= '0' && i <= '9')
+            ch = i - '0';
+        else if (i >= 'a' && i <= 'z')
+            ch = i - 'a' + 10;
+        else if (i >= 'A' && i <= 'Z')
+            ch = i - 'A' + 10;
+        if (i == 0)
+            printf("\n    %3d", ch);
+        else if ((i % 32) == 0)
+            printf(",\n    %3d", ch);
+        else
+            printf(",%3d", ch);
+    }
+    printf("\n"
+           "};\n");
+    return 0;
+}
+*/
+
+
+/**
+ * Converts a string representation of a number to a 64-bit unsigned number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pu64        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt64Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint64_t *pu64)
+{
+    const char   *psz = pszValue;
+    int           iShift;
+    int           rc;
+    uint64_t      u64;
+    unsigned char uch;
+
+    /*
+     * Positive/Negative stuff.
+     */
+    bool fPositive = true;
+    for (;; psz++)
+    {
+        if (*psz == '+')
+            fPositive = true;
+        else if (*psz == '-')
+            fPositive = !fPositive;
+        else
+            break;
+    }
+
+    /*
+     * Check for hex prefix.
+     */
+    if (!uBase)
+    {
+        if (    psz[0] == '0'
+            &&  (psz[1] == 'x' || psz[1] == 'X')
+            &&  g_auchDigits[(unsigned char)psz[2]] < 16)
+        {
+            uBase = 16;
+            psz += 2;
+        }
+        else if (   psz[0] == '0'
+                 && g_auchDigits[(unsigned char)psz[1]] < 8)
+        {
+            uBase = 8;
+            psz++;
+        }
+        else
+            uBase = 10;
+    }
+    else if (   uBase == 16
+             && psz[0] == '0'
+             && (psz[1] == 'x' || psz[1] == 'X')
+             && g_auchDigits[(unsigned char)psz[2]] < 16)
+        psz += 2;
+
+    /*
+     * Interpret the value.
+     * Note: We only support ascii digits at this time... :-)
+     */
+    iShift = g_auchShift[uBase];
+    pszValue = psz; /* (Prefix and sign doesn't count in the digit counting.) */
+    rc = VINF_SUCCESS;
+    u64 = 0;
+    while ((uch = (unsigned char)*psz) != 0)
+    {
+        unsigned char chDigit = g_auchDigits[uch];
+        uint64_t u64Prev;
+
+        if (chDigit >= uBase)
+            break;
+
+        u64Prev = u64;
+        u64 *= uBase;
+        u64 += chDigit;
+        if (u64Prev > u64 || (u64Prev >> iShift))
+            rc = VWRN_NUMBER_TOO_BIG;
+        psz++;
+    }
+
+    if (!fPositive)
+    {
+        if (rc == VINF_SUCCESS)
+            rc = VWRN_NEGATIVE_UNSIGNED;
+        u64 = -(int64_t)u64;
+    }
+
+    if (pu64)
+        *pu64 = u64;
+
+    if (psz == pszValue)
+        rc = VERR_NO_DIGITS;
+
+    if (ppszNext)
+        *ppszNext = (char *)psz;
+
+    /*
+     * Warn about trailing chars/spaces.
+     */
+    if (    rc == VINF_SUCCESS
+        &&  *psz)
+    {
+        while (*psz == ' ' || *psz == '\t')
+            psz++;
+        rc = *psz ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES;
+    }
+
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToUInt64Ex);
+
+
+/**
+ * Converts a string representation of a number to a 64-bit unsigned number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_TRAILING_CHARS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pu64        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt64Full(const char *pszValue, unsigned uBase, uint64_t *pu64)
+{
+    char *psz;
+    int rc = RTStrToUInt64Ex(pszValue, &psz, uBase, pu64);
+    if (RT_SUCCESS(rc) && *psz)
+    {
+        if (rc == VWRN_TRAILING_CHARS || rc == VWRN_TRAILING_SPACES)
+            rc = -rc;
+        else
+        {
+            while (*psz == ' ' || *psz == '\t')
+                psz++;
+            rc = *psz ? VERR_TRAILING_CHARS : VERR_TRAILING_SPACES;
+        }
+    }
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToUInt64Full);
+
+
+/**
+ * Converts a string representation of a number to a 64-bit unsigned number.
+ * The base is guessed.
+ *
+ * @returns 64-bit unsigned number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(uint64_t) RTStrToUInt64(const char *pszValue)
+{
+    uint64_t u64;
+    int rc = RTStrToUInt64Ex(pszValue, NULL, 0, &u64);
+    if (RT_SUCCESS(rc))
+        return u64;
+    return 0;
+}
+RT_EXPORT_SYMBOL(RTStrToUInt64);
+
+
+/**
+ * Converts a string representation of a number to a 32-bit unsigned number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pu32        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint32_t *pu32)
+{
+    uint64_t u64;
+    int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBase, &u64);
+    if (RT_SUCCESS(rc))
+    {
+        if (u64 & ~0xffffffffULL)
+            rc = VWRN_NUMBER_TOO_BIG;
+    }
+    if (pu32)
+        *pu32 = (uint32_t)u64;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToUInt32Ex);
+
+
+/**
+ * Converts a string representation of a number to a 32-bit unsigned number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_TRAILING_CHARS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pu32        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt32Full(const char *pszValue, unsigned uBase, uint32_t *pu32)
+{
+    uint64_t u64;
+    int rc = RTStrToUInt64Full(pszValue, uBase, &u64);
+    if (RT_SUCCESS(rc))
+    {
+        if (u64 & ~0xffffffffULL)
+            rc = VWRN_NUMBER_TOO_BIG;
+    }
+    if (pu32)
+        *pu32 = (uint32_t)u64;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToUInt32Full);
+
+
+/**
+ * Converts a string representation of a number to a 64-bit unsigned number.
+ * The base is guessed.
+ *
+ * @returns 32-bit unsigned number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(uint32_t) RTStrToUInt32(const char *pszValue)
+{
+    uint32_t u32;
+    int rc = RTStrToUInt32Ex(pszValue, NULL, 0, &u32);
+    if (RT_SUCCESS(rc))
+        return u32;
+    return 0;
+}
+RT_EXPORT_SYMBOL(RTStrToUInt32);
+
+
+/**
+ * Converts a string representation of a number to a 16-bit unsigned number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pu16        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint16_t *pu16)
+{
+    uint64_t u64;
+    int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBase, &u64);
+    if (RT_SUCCESS(rc))
+    {
+        if (u64 & ~0xffffULL)
+            rc = VWRN_NUMBER_TOO_BIG;
+    }
+    if (pu16)
+        *pu16 = (uint16_t)u64;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToUInt16Ex);
+
+
+/**
+ * Converts a string representation of a number to a 16-bit unsigned number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_TRAILING_CHARS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pu16        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt16Full(const char *pszValue, unsigned uBase, uint16_t *pu16)
+{
+    uint64_t u64;
+    int rc = RTStrToUInt64Full(pszValue, uBase, &u64);
+    if (RT_SUCCESS(rc))
+    {
+        if (u64 & ~0xffffULL)
+            rc = VWRN_NUMBER_TOO_BIG;
+    }
+    if (pu16)
+        *pu16 = (uint16_t)u64;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToUInt16Full);
+
+
+/**
+ * Converts a string representation of a number to a 16-bit unsigned number.
+ * The base is guessed.
+ *
+ * @returns 16-bit unsigned number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(uint16_t) RTStrToUInt16(const char *pszValue)
+{
+    uint16_t u16;
+    int rc = RTStrToUInt16Ex(pszValue, NULL, 0, &u16);
+    if (RT_SUCCESS(rc))
+        return u16;
+    return 0;
+}
+RT_EXPORT_SYMBOL(RTStrToUInt16);
+
+
+/**
+ * Converts a string representation of a number to a 8-bit unsigned number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pu8         Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint8_t *pu8)
+{
+    uint64_t u64;
+    int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBase, &u64);
+    if (RT_SUCCESS(rc))
+    {
+        if (u64 & ~0xffULL)
+            rc = VWRN_NUMBER_TOO_BIG;
+    }
+    if (pu8)
+        *pu8 = (uint8_t)u64;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToUInt8Ex);
+
+
+/**
+ * Converts a string representation of a number to a 8-bit unsigned number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_NEGATIVE_UNSIGNED
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_TRAILING_CHARS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pu8         Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt8Full(const char *pszValue, unsigned uBase, uint8_t *pu8)
+{
+    uint64_t u64;
+    int rc = RTStrToUInt64Full(pszValue, uBase, &u64);
+    if (RT_SUCCESS(rc))
+    {
+        if (u64 & ~0xffULL)
+            rc = VWRN_NUMBER_TOO_BIG;
+    }
+    if (pu8)
+        *pu8 = (uint8_t)u64;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToUInt8Full);
+
+
+/**
+ * Converts a string representation of a number to a 8-bit unsigned number.
+ * The base is guessed.
+ *
+ * @returns 8-bit unsigned number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(uint8_t) RTStrToUInt8(const char *pszValue)
+{
+    uint8_t u8;
+    int rc = RTStrToUInt8Ex(pszValue, NULL, 0, &u8);
+    if (RT_SUCCESS(rc))
+        return u8;
+    return 0;
+}
+RT_EXPORT_SYMBOL(RTStrToUInt8);
+
+
+
+
+
+
+
+/**
+ * Converts a string representation of a number to a 64-bit signed number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pi64        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt64Ex(const char *pszValue, char **ppszNext, unsigned uBase, int64_t *pi64)
+{
+    const char   *psz = pszValue;
+    int           iShift;
+    int           rc;
+    int64_t       i64;
+    unsigned char uch;
+
+    /*
+     * Positive/Negative stuff.
+     */
+    bool fPositive = true;
+    for (;; psz++)
+    {
+        if (*psz == '+')
+            fPositive = true;
+        else if (*psz == '-')
+            fPositive = !fPositive;
+        else
+            break;
+    }
+
+    /*
+     * Check for hex prefix.
+     */
+    if (!uBase)
+    {
+        if (    *psz == '0'
+            &&  (psz[1] == 'x' || psz[1] == 'X')
+            &&  g_auchDigits[(unsigned char)psz[2]] < 16)
+        {
+            uBase = 16;
+            psz += 2;
+        }
+        else if (   *psz == '0'
+                 && g_auchDigits[(unsigned char)psz[1]] < 8)
+        {
+            uBase = 8;
+            psz++;
+        }
+        else
+            uBase = 10;
+    }
+    else if (   uBase == 16
+             && *psz == '0'
+             && (psz[1] == 'x' || psz[1] == 'X')
+             && g_auchDigits[(unsigned char)psz[2]] < 16)
+        psz += 2;
+
+    /*
+     * Interpret the value.
+     * Note: We only support ascii digits at this time... :-)
+     */
+    iShift = g_auchShift[uBase]; /** @todo test this, it's probably not 100% right yet. */
+    pszValue = psz; /* (Prefix and sign doesn't count in the digit counting.) */
+    rc = VINF_SUCCESS;
+    i64 = 0;
+    while ((uch = (unsigned char)*psz) != 0)
+    {
+        unsigned char chDigit = g_auchDigits[uch];
+        int64_t i64Prev;
+
+        if (chDigit >= uBase)
+            break;
+
+        i64Prev = i64;
+        i64 *= uBase;
+        i64 += chDigit;
+        if (i64Prev > i64 || (i64Prev >> iShift))
+            rc = VWRN_NUMBER_TOO_BIG;
+        psz++;
+    }
+
+    if (!fPositive)
+        i64 = -i64;
+
+    if (pi64)
+        *pi64 = i64;
+
+    if (psz == pszValue)
+        rc = VERR_NO_DIGITS;
+
+    if (ppszNext)
+        *ppszNext = (char *)psz;
+
+    /*
+     * Warn about trailing chars/spaces.
+     */
+    if (    rc == VINF_SUCCESS
+        &&  *psz)
+    {
+        while (*psz == ' ' || *psz == '\t')
+            psz++;
+        rc = *psz ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES;
+    }
+
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToInt64Ex);
+
+
+/**
+ * Converts a string representation of a number to a 64-bit signed number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_TRAILING_CHARS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pi64        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt64Full(const char *pszValue, unsigned uBase, int64_t *pi64)
+{
+    char *psz;
+    int rc = RTStrToInt64Ex(pszValue, &psz, uBase, pi64);
+    if (RT_SUCCESS(rc) && *psz)
+    {
+        if (rc == VWRN_TRAILING_CHARS || rc == VWRN_TRAILING_SPACES)
+            rc = -rc;
+        else
+        {
+            while (*psz == ' ' || *psz == '\t')
+                psz++;
+            rc = *psz ? VERR_TRAILING_CHARS : VERR_TRAILING_SPACES;
+        }
+    }
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToInt64Full);
+
+
+/**
+ * Converts a string representation of a number to a 64-bit signed number.
+ * The base is guessed.
+ *
+ * @returns 64-bit signed number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(int64_t) RTStrToInt64(const char *pszValue)
+{
+    int64_t i64;
+    int rc = RTStrToInt64Ex(pszValue, NULL, 0, &i64);
+    if (RT_SUCCESS(rc))
+        return i64;
+    return 0;
+}
+RT_EXPORT_SYMBOL(RTStrToInt64);
+
+
+/**
+ * Converts a string representation of a number to a 32-bit signed number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pi32        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, int32_t *pi32)
+{
+    int64_t i64;
+    int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase, &i64);
+    if (RT_SUCCESS(rc))
+    {
+        int32_t i32 = (int32_t)i64;
+        if (i64 != (int64_t)i32)
+            rc = VWRN_NUMBER_TOO_BIG;
+    }
+    if (pi32)
+        *pi32 = (int32_t)i64;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToInt32Ex);
+
+
+/**
+ * Converts a string representation of a number to a 32-bit signed number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_TRAILING_CHARS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pi32        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt32Full(const char *pszValue, unsigned uBase, int32_t *pi32)
+{
+    int64_t i64;
+    int rc = RTStrToInt64Full(pszValue, uBase, &i64);
+    if (RT_SUCCESS(rc))
+    {
+        int32_t i32 = (int32_t)i64;
+        if (i64 != (int64_t)i32)
+            rc = VWRN_NUMBER_TOO_BIG;
+    }
+    if (pi32)
+        *pi32 = (int32_t)i64;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToInt32Full);
+
+
+/**
+ * Converts a string representation of a number to a 32-bit signed number.
+ * The base is guessed.
+ *
+ * @returns 32-bit signed number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(int32_t) RTStrToInt32(const char *pszValue)
+{
+    int32_t i32;
+    int rc = RTStrToInt32Ex(pszValue, NULL, 0, &i32);
+    if (RT_SUCCESS(rc))
+        return i32;
+    return 0;
+}
+RT_EXPORT_SYMBOL(RTStrToInt32);
+
+
+/**
+ * Converts a string representation of a number to a 16-bit signed number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pi16        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, int16_t *pi16)
+{
+    int64_t i64;
+    int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase, &i64);
+    if (RT_SUCCESS(rc))
+    {
+        int16_t i16 = (int16_t)i64;
+        if (i64 != (int64_t)i16)
+            rc = VWRN_NUMBER_TOO_BIG;
+    }
+    if (pi16)
+        *pi16 = (int16_t)i64;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToInt16Ex);
+
+
+/**
+ * Converts a string representation of a number to a 16-bit signed number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_TRAILING_CHARS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pi16        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt16Full(const char *pszValue, unsigned uBase, int16_t *pi16)
+{
+    int64_t i64;
+    int rc = RTStrToInt64Full(pszValue, uBase, &i64);
+    if (RT_SUCCESS(rc))
+    {
+        int16_t i16 = (int16_t)i64;
+        if (i64 != (int64_t)i16)
+            rc = VWRN_NUMBER_TOO_BIG;
+    }
+    if (pi16)
+        *pi16 = (int16_t)i64;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToInt16Full);
+
+
+/**
+ * Converts a string representation of a number to a 16-bit signed number.
+ * The base is guessed.
+ *
+ * @returns 16-bit signed number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(int16_t) RTStrToInt16(const char *pszValue)
+{
+    int16_t i16;
+    int rc = RTStrToInt16Ex(pszValue, NULL, 0, &i16);
+    if (RT_SUCCESS(rc))
+        return i16;
+    return 0;
+}
+RT_EXPORT_SYMBOL(RTStrToInt16);
+
+
+/**
+ * Converts a string representation of a number to a 8-bit signed number.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VWRN_TRAILING_CHARS
+ * @retval  VWRN_TRAILING_SPACES
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   ppszNext    Where to store the pointer to the first char following the number. (Optional)
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pi8        Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, int8_t *pi8)
+{
+    int64_t i64;
+    int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase, &i64);
+    if (RT_SUCCESS(rc))
+    {
+        int8_t i8 = (int8_t)i64;
+        if (i64 != (int64_t)i8)
+            rc = VWRN_NUMBER_TOO_BIG;
+    }
+    if (pi8)
+        *pi8 = (int8_t)i64;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToInt8Ex);
+
+
+/**
+ * Converts a string representation of a number to a 8-bit signed number,
+ * making sure the full string is converted.
+ *
+ * @returns iprt status code.
+ *          Warnings are used to indicate conversion problems.
+ * @retval  VWRN_NUMBER_TOO_BIG
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_TRAILING_CHARS
+ * @retval  VERR_TRAILING_SPACES
+ * @retval  VERR_NO_DIGITS
+ *
+ * @param   pszValue    Pointer to the string value.
+ * @param   uBase       The base of the representation used.
+ *                      If the function will look for known prefixes before defaulting to 10.
+ * @param   pi8         Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt8Full(const char *pszValue, unsigned uBase, int8_t *pi8)
+{
+    int64_t i64;
+    int rc = RTStrToInt64Full(pszValue, uBase, &i64);
+    if (RT_SUCCESS(rc))
+    {
+        int8_t i8 = (int8_t)i64;
+        if (i64 != (int64_t)i8)
+            rc = VWRN_NUMBER_TOO_BIG;
+    }
+    if (pi8)
+        *pi8 = (int8_t)i64;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTStrToInt8Full);
+
+
+/**
+ * Converts a string representation of a number to a 8-bit signed number.
+ * The base is guessed.
+ *
+ * @returns 8-bit signed number on success.
+ * @returns 0 on failure.
+ * @param   pszValue    Pointer to the string value.
+ */
+RTDECL(int8_t) RTStrToInt8(const char *pszValue)
+{
+    int8_t i8;
+    int rc = RTStrToInt8Ex(pszValue, NULL, 0, &i8);
+    if (RT_SUCCESS(rc))
+        return i8;
+    return 0;
+}
+RT_EXPORT_SYMBOL(RTStrToInt8);
+
+
+RTDECL(int) RTStrConvertHexBytes(char const *pszHex, void *pv, size_t cb, uint32_t fFlags)
+{
+    size_t      cbDst;
+    uint8_t    *pbDst;
+    const char *pszSrc;
+
+    AssertPtrReturn(pszHex, VERR_INVALID_POINTER);
+    AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
+
+    cbDst  = cb;
+    pbDst  = (uint8_t *)pv;
+    pszSrc = pszHex;
+    for (;;)
+    {
+        /* Pick the next two digit from the string. */
+        char ch = *pszSrc++;
+        unsigned char uchDigit1 = g_auchDigits[(unsigned char)ch];
+        unsigned char uchDigit2;
+        if (uchDigit1 >= 16)
+        {
+            if (!ch)
+                return cbDst == 0 ? VINF_SUCCESS : VERR_BUFFER_UNDERFLOW;
+
+            while (ch == ' ' || ch == '\t')
+                ch = *pszSrc++;
+            return ch ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES;
+        }
+
+        ch = *pszSrc++;
+        uchDigit2 = g_auchDigits[(unsigned char)ch];
+        if (uchDigit2 >= 16)
+            return VERR_UNEVEN_INPUT;
+
+        /* Add the byte to the output buffer. */
+        if (!cbDst)
+            return VERR_BUFFER_OVERFLOW;
+        cbDst--;
+        *pbDst++ = (uchDigit1 << 4) | uchDigit2;
+    }
+}
+RT_EXPORT_SYMBOL(RTStrConvertHexBytes);
+
diff --git a/ubuntu/vbox/vboxguest/common/table/avl_Base.cpp.h b/ubuntu/vbox/vboxguest/common/table/avl_Base.cpp.h
new file mode 100644 (file)
index 0000000..5ed5e9d
--- /dev/null
@@ -0,0 +1,460 @@
+/* $Id: avl_Base.cpp.h $ */
+/** @file
+ * kAVLBase - basic routines for all AVL trees.
+ */
+
+/*
+ * Copyright (C) 2006-2017 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.
+ */
+
+#ifndef _kAVLBase_h_
+#define _kAVLBase_h_
+
+
+/** @page   pg_rt_kAVL kAVL Template configuration.
+ * @internal
+ *
+ *  This is a template made to implement multiple AVL trees. The differences
+ *  among the implementations are related to the key used.
+ *
+ *  \#define KAVL_FN
+ *  Use this to alter the names of the AVL functions.
+ *  Must be defined.
+ *
+ *  \#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 pList in the KAVLNODECORE.
+ *  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 number of stack entries the stack will use when inserting
+ *  and removing nodes from the tree. I think the size should be about
+ *      log2(<max nodes>) + 3
+ *  Must be defined.
+ *
+ */
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+#define AVL_HEIGHTOF(pNode) ((unsigned char)((pNode) != NULL ? pNode->uchHeight : 0))
+
+/** @def KAVL_GET_POINTER
+ * Reads a 'pointer' value.
+ *
+ * @returns The native pointer.
+ * @param   pp      Pointer to the pointer to read.
+ */
+
+/** @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.
+ */
+
+/** @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.
+ */
+
+/** @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
+ */
+
+#ifndef KAVL_GET_POINTER
+# ifdef KAVL_OFFSET
+#  define KAVL_GET_POINTER(pp)              ( (PKAVLNODECORE)((intptr_t)(pp) + *(pp)) )
+#  define KAVL_GET_POINTER_NULL(pp)         ( *(pp) != KAVL_NULL ? KAVL_GET_POINTER(pp) : NULL )
+#  define KAVL_SET_POINTER(pp, p)           ( (*(pp)) = ((intptr_t)(p) - (intptr_t)(pp)) )
+#  define KAVL_SET_POINTER_NULL(pp, pp2)    ( (*(pp)) = *(pp2) != KAVL_NULL ? (intptr_t)KAVL_GET_POINTER(pp2) - (intptr_t)(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
+#endif
+
+
+/** @def KAVL_NULL
+ * The NULL 'pointer' equivalent.
+ */
+#ifndef KAVL_NULL
+# ifdef KAVL_OFFSET
+#  define KAVL_NULL     0
+# else
+#  define KAVL_NULL     NULL
+# 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
+
+/** @def KAVL_DECL
+ * Function declation macro in the RTDECL tradition.
+ * @param   a_Type      The function return type.  */
+#ifndef KAVL_DECL
+# define KAVL_DECL(a_Type)  RTDECL(a_Type)
+#endif
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/*
+ * A stack used to avoid recursive calls...
+ */
+typedef struct _kAvlStack
+{
+    unsigned        cEntries;
+    PPKAVLNODECORE  aEntries[KAVL_MAX_STACK];
+} KAVLSTACK, *PKAVLSTACK;
+
+typedef struct _kAvlStack2
+{
+    unsigned        cEntries;
+    PKAVLNODECORE   aEntries[KAVL_MAX_STACK];
+    char            achFlags[KAVL_MAX_STACK];
+} KAVLSTACK2, *PLAVLSTACK2;
+
+
+
+/**
+ * Rewinds a stack of pointers to pointers to nodes, 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
+ */
+DECLINLINE(void) KAVL_FN(Rebalance)(PKAVLSTACK pStack)
+{
+    while (pStack->cEntries > 0)
+    {
+        /** @todo Perhaps some of these KAVL_SET_POINTER_NULL() cases could be optimized away.. */
+        PPKAVLNODECORE   ppNode = pStack->aEntries[--pStack->cEntries];
+        PKAVLNODECORE    pNode = KAVL_GET_POINTER(ppNode);
+        PKAVLNODECORE    pLeftNode = KAVL_GET_POINTER_NULL(&pNode->pLeft);
+        unsigned char    uchLeftHeight = AVL_HEIGHTOF(pLeftNode);
+        PKAVLNODECORE    pRightNode = KAVL_GET_POINTER_NULL(&pNode->pRight);
+        unsigned char    uchRightHeight = AVL_HEIGHTOF(pRightNode);
+
+        if (uchRightHeight + 1 < uchLeftHeight)
+        {
+            PKAVLNODECORE    pLeftLeftNode = KAVL_GET_POINTER_NULL(&pLeftNode->pLeft);
+            PKAVLNODECORE    pLeftRightNode = KAVL_GET_POINTER_NULL(&pLeftNode->pRight);
+            unsigned char    uchLeftRightHeight = AVL_HEIGHTOF(pLeftRightNode);
+
+            if (AVL_HEIGHTOF(pLeftLeftNode) >= uchLeftRightHeight)
+            {
+                KAVL_SET_POINTER_NULL(&pNode->pLeft, &pLeftNode->pRight);
+                KAVL_SET_POINTER(&pLeftNode->pRight, pNode);
+                pLeftNode->uchHeight = (unsigned char)(1 + (pNode->uchHeight = (unsigned char)(1 + uchLeftRightHeight)));
+                KAVL_SET_POINTER(ppNode, pLeftNode);
+            }
+            else
+            {
+                KAVL_SET_POINTER_NULL(&pLeftNode->pRight, &pLeftRightNode->pLeft);
+                KAVL_SET_POINTER_NULL(&pNode->pLeft, &pLeftRightNode->pRight);
+                KAVL_SET_POINTER(&pLeftRightNode->pLeft, pLeftNode);
+                KAVL_SET_POINTER(&pLeftRightNode->pRight, pNode);
+                pLeftNode->uchHeight = pNode->uchHeight = uchLeftRightHeight;
+                pLeftRightNode->uchHeight = uchLeftHeight;
+                KAVL_SET_POINTER(ppNode, pLeftRightNode);
+            }
+        }
+        else if (uchLeftHeight + 1 < uchRightHeight)
+        {
+            PKAVLNODECORE    pRightLeftNode = KAVL_GET_POINTER_NULL(&pRightNode->pLeft);
+            unsigned char    uchRightLeftHeight = AVL_HEIGHTOF(pRightLeftNode);
+            PKAVLNODECORE    pRightRightNode = KAVL_GET_POINTER_NULL(&pRightNode->pRight);
+
+            if (AVL_HEIGHTOF(pRightRightNode) >= uchRightLeftHeight)
+            {
+                KAVL_SET_POINTER_NULL(&pNode->pRight, &pRightNode->pLeft);
+                KAVL_SET_POINTER(&pRightNode->pLeft, pNode);
+                pRightNode->uchHeight = (unsigned char)(1 + (pNode->uchHeight = (unsigned char)(1 + uchRightLeftHeight)));
+                KAVL_SET_POINTER(ppNode, pRightNode);
+            }
+            else
+            {
+                KAVL_SET_POINTER_NULL(&pRightNode->pLeft, &pRightLeftNode->pRight);
+                KAVL_SET_POINTER_NULL(&pNode->pRight, &pRightLeftNode->pLeft);
+                KAVL_SET_POINTER(&pRightLeftNode->pRight, pRightNode);
+                KAVL_SET_POINTER(&pRightLeftNode->pLeft, pNode);
+                pRightNode->uchHeight = pNode->uchHeight = uchRightLeftHeight;
+                pRightLeftNode->uchHeight = uchRightHeight;
+                KAVL_SET_POINTER(ppNode, pRightLeftNode);
+            }
+        }
+        else
+        {
+            register unsigned char uchHeight = (unsigned char)(KMAX(uchLeftHeight, uchRightHeight) + 1);
+            if (uchHeight == pNode->uchHeight)
+                break;
+            pNode->uchHeight = uchHeight;
+        }
+    }
+
+}
+
+
+
+
+/**
+ * Inserts a node into the AVL-tree.
+ * @returns   TRUE if inserted.
+ *            FALSE if node exists in tree.
+ * @param     ppTree  Pointer to the AVL-tree root node pointer.
+ * @param     pNode   Pointer to the node which is to be added.
+ * @sketch    Find the location of the node (using binary tree algorithm.):
+ *            LOOP until KAVL_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(bool) KAVL_FN(Insert)(PPKAVLNODECORE ppTree, PKAVLNODECORE pNode)
+{
+    KAVLSTACK               AVLStack;
+    PPKAVLNODECORE          ppCurNode = ppTree;
+    register PKAVLNODECORE  pCurNode;
+    register KAVLKEY        Key = pNode->Key; NOREF(Key);
+#ifdef KAVL_RANGE
+    register KAVLKEY        KeyLast = pNode->KeyLast; NOREF(KeyLast);
+#endif
+
+    AVLStack.cEntries = 0;
+
+#ifdef KAVL_RANGE
+    if (Key > KeyLast)
+        return false;
+#endif
+
+    for (;;)
+    {
+        if (*ppCurNode != KAVL_NULL)
+            pCurNode = KAVL_GET_POINTER(ppCurNode);
+        else
+            break;
+
+        kASSERT(AVLStack.cEntries < KAVL_MAX_STACK);
+        AVLStack.aEntries[AVLStack.cEntries++] = ppCurNode;
+#ifdef KAVL_EQUAL_ALLOWED
+        if (KAVL_R_IS_IDENTICAL(pCurNode->Key, Key, pCurNode->KeyLast, KeyLast))
+        {
+            /*
+             * If equal then we'll use a list of equal nodes.
+             */
+            pNode->pLeft = pNode->pRight = KAVL_NULL;
+            pNode->uchHeight = 0;
+            KAVL_SET_POINTER_NULL(&pNode->pList, &pCurNode->pList);
+            KAVL_SET_POINTER(&pCurNode->pList, pNode);
+            return true;
+        }
+#endif
+#ifdef KAVL_CHECK_FOR_EQUAL_INSERT
+        if (KAVL_R_IS_INTERSECTING(pCurNode->Key, Key, pCurNode->KeyLast, KeyLast))
+            return false;
+#endif
+        if (KAVL_G(pCurNode->Key, Key))
+            ppCurNode = &pCurNode->pLeft;
+        else
+            ppCurNode = &pCurNode->pRight;
+    }
+
+    pNode->pLeft = pNode->pRight = KAVL_NULL;
+#ifdef KAVL_EQUAL_ALLOWED
+    pNode->pList = KAVL_NULL;
+#endif
+    pNode->uchHeight = 1;
+    KAVL_SET_POINTER(ppCurNode, pNode);
+
+    KAVL_FN(Rebalance)(SSToDS(&AVLStack));
+    return true;
+}
+
+
+/**
+ * Removes a node from the AVL-tree.
+ * @returns   Pointer to the node.
+ * @param     ppTree  Pointer to the AVL-tree root node pointer.
+ * @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(PKAVLNODECORE) KAVL_FN(Remove)(PPKAVLNODECORE ppTree, KAVLKEY Key)
+{
+    KAVLSTACK                AVLStack;
+    PPKAVLNODECORE           ppDeleteNode = ppTree;
+    register PKAVLNODECORE   pDeleteNode;
+
+    AVLStack.cEntries = 0;
+
+    for (;;)
+    {
+        if (*ppDeleteNode != KAVL_NULL)
+            pDeleteNode = KAVL_GET_POINTER(ppDeleteNode);
+        else
+            return NULL;
+
+        kASSERT(AVLStack.cEntries < KAVL_MAX_STACK);
+        AVLStack.aEntries[AVLStack.cEntries++] = ppDeleteNode;
+        if (KAVL_E(pDeleteNode->Key, Key))
+            break;
+
+        if (KAVL_G(pDeleteNode->Key, Key))
+            ppDeleteNode = &pDeleteNode->pLeft;
+        else
+            ppDeleteNode = &pDeleteNode->pRight;
+    }
+
+    if (pDeleteNode->pLeft != KAVL_NULL)
+    {
+        /* find the rightmost node in the left tree. */
+        const unsigned          iStackEntry = AVLStack.cEntries;
+        PPKAVLNODECORE          ppLeftLeast = &pDeleteNode->pLeft;
+        register PKAVLNODECORE  pLeftLeast = KAVL_GET_POINTER(ppLeftLeast);
+
+        while (pLeftLeast->pRight != KAVL_NULL)
+        {
+            kASSERT(AVLStack.cEntries < KAVL_MAX_STACK);
+            AVLStack.aEntries[AVLStack.cEntries++] = ppLeftLeast;
+            ppLeftLeast = &pLeftLeast->pRight;
+            pLeftLeast  = KAVL_GET_POINTER(ppLeftLeast);
+        }
+
+        /* link out pLeftLeast */
+        KAVL_SET_POINTER_NULL(ppLeftLeast, &pLeftLeast->pLeft);
+
+        /* link it in place of the delete node. */
+        KAVL_SET_POINTER_NULL(&pLeftLeast->pLeft, &pDeleteNode->pLeft);
+        KAVL_SET_POINTER_NULL(&pLeftLeast->pRight, &pDeleteNode->pRight);
+        pLeftLeast->uchHeight = pDeleteNode->uchHeight;
+        KAVL_SET_POINTER(ppDeleteNode, pLeftLeast);
+        AVLStack.aEntries[iStackEntry] = &pLeftLeast->pLeft;
+    }
+    else
+    {
+        KAVL_SET_POINTER_NULL(ppDeleteNode, &pDeleteNode->pRight);
+        AVLStack.cEntries--;
+    }
+
+    KAVL_FN(Rebalance)(SSToDS(&AVLStack));
+    return pDeleteNode;
+}
+
+#endif
diff --git a/ubuntu/vbox/vboxguest/common/table/avl_Destroy.cpp.h b/ubuntu/vbox/vboxguest/common/table/avl_Destroy.cpp.h
new file mode 100644 (file)
index 0000000..ba42216
--- /dev/null
@@ -0,0 +1,110 @@
+/* $Id: avl_Destroy.cpp.h $ */
+/** @file
+ * kAVLDestroy - Walk the tree calling a callback to destroy all the nodes.
+ */
+
+/*
+ * Copyright (C) 2006-2017 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.
+ */
+
+#ifndef _kAVLDestroy_h_
+#define _kAVLDestroy_h_
+
+
+/**
+ * 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   ppTree          Pointer to the AVL-tree root node pointer.
+ * @param   pfnCallBack     Pointer to callback function.
+ * @param   pvUser          User parameter passed on to the callback function.
+ */
+KAVL_DECL(int) KAVL_FN(Destroy)(PPKAVLNODECORE ppTree, PKAVLCALLBACK pfnCallBack, void *pvUser)
+{
+    unsigned        cEntries;
+    PKAVLNODECORE   apEntries[KAVL_MAX_STACK];
+    int             rc;
+
+    if (*ppTree == KAVL_NULL)
+        return VINF_SUCCESS;
+
+    cEntries = 1;
+    apEntries[0] = KAVL_GET_POINTER(ppTree);
+    while (cEntries > 0)
+    {
+        /*
+         * Process the subtrees first.
+         */
+        PKAVLNODECORE pNode = apEntries[cEntries - 1];
+        if (pNode->pLeft != KAVL_NULL)
+            apEntries[cEntries++] = KAVL_GET_POINTER(&pNode->pLeft);
+        else if (pNode->pRight != KAVL_NULL)
+            apEntries[cEntries++] = KAVL_GET_POINTER(&pNode->pRight);
+        else
+        {
+#ifdef KAVL_EQUAL_ALLOWED
+            /*
+             * Process nodes with the same key.
+             */
+            while (pNode->pList != KAVL_NULL)
+            {
+                PKAVLNODECORE 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 != VINF_SUCCESS)
+                    return rc;
+            }
+#endif
+
+            /*
+             * Unlink the node.
+             */
+            if (--cEntries > 0)
+            {
+                PKAVLNODECORE pParent = apEntries[cEntries - 1];
+                if (KAVL_GET_POINTER(&pParent->pLeft) == pNode)
+                    pParent->pLeft = KAVL_NULL;
+                else
+                    pParent->pRight = KAVL_NULL;
+            }
+            else
+                *ppTree = KAVL_NULL;
+
+            kASSERT(pNode->pLeft == KAVL_NULL);
+            kASSERT(pNode->pRight == KAVL_NULL);
+            rc = pfnCallBack(pNode, pvUser);
+            if (rc != VINF_SUCCESS)
+                return rc;
+        }
+    } /* while */
+
+    kASSERT(*ppTree == KAVL_NULL);
+
+    return VINF_SUCCESS;
+}
+
+#endif
+
diff --git a/ubuntu/vbox/vboxguest/common/table/avl_DoWithAll.cpp.h b/ubuntu/vbox/vboxguest/common/table/avl_DoWithAll.cpp.h
new file mode 100644 (file)
index 0000000..199a0bc
--- /dev/null
@@ -0,0 +1,142 @@
+/* $Id: avl_DoWithAll.cpp.h $ */
+/** @file
+ * kAVLDoWithAll - Do with all nodes routine for AVL trees.
+ */
+
+/*
+ * Copyright (C) 2006-2017 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.
+ */
+
+#ifndef _kAVLDoWithAll_h_
+#define _kAVLDoWithAll_h_
+
+
+/**
+ * Iterates thru all nodes in the given tree.
+ * @returns   0 on success. Return from callback on failure.
+ * @param     ppTree   Pointer to the AVL-tree root node pointer.
+ * @param     fFromLeft    TRUE:  Left to right.
+ *                         FALSE: Right to left.
+ * @param     pfnCallBack  Pointer to callback function.
+ * @param     pvParam      Userparameter passed on to the callback function.
+ */
+KAVL_DECL(int) KAVL_FN(DoWithAll)(PPKAVLNODECORE ppTree, int fFromLeft, PKAVLCALLBACK pfnCallBack, void * pvParam)
+{
+    KAVLSTACK2      AVLStack;
+    PKAVLNODECORE   pNode;
+#ifdef KAVL_EQUAL_ALLOWED
+    PKAVLNODECORE   pEqual;
+#endif
+    int             rc;
+
+    if (*ppTree == KAVL_NULL)
+        return VINF_SUCCESS;
+
+    AVLStack.cEntries = 1;
+    AVLStack.achFlags[0] = 0;
+    AVLStack.aEntries[0] = KAVL_GET_POINTER(ppTree);
+
+    if (fFromLeft)
+    {   /* from left */
+        while (AVLStack.cEntries > 0)
+        {
+            pNode = AVLStack.aEntries[AVLStack.cEntries - 1];
+
+            /* left */
+            if (!AVLStack.achFlags[AVLStack.cEntries - 1]++)
+            {
+                if (pNode->pLeft != KAVL_NULL)
+                {
+                    AVLStack.achFlags[AVLStack.cEntries] = 0; /* 0 first, 1 last */
+                    AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->pLeft);
+                    continue;
+                }
+            }
+
+            /* center */
+            rc = pfnCallBack(pNode, pvParam);
+            if (rc != VINF_SUCCESS)
+                return rc;
+#ifdef KAVL_EQUAL_ALLOWED
+            if (pNode->pList != KAVL_NULL)
+                for (pEqual = KAVL_GET_POINTER(&pNode->pList); pEqual; pEqual = KAVL_GET_POINTER_NULL(&pEqual->pList))
+                {
+                    rc = pfnCallBack(pEqual, pvParam);
+                    if (rc != VINF_SUCCESS)
+                        return rc;
+                }
+#endif
+
+            /* right */
+            AVLStack.cEntries--;
+            if (pNode->pRight != KAVL_NULL)
+            {
+                AVLStack.achFlags[AVLStack.cEntries] = 0;
+                AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->pRight);
+            }
+        } /* while */
+    }
+    else
+    {   /* from right */
+        while (AVLStack.cEntries > 0)
+        {
+            pNode = AVLStack.aEntries[AVLStack.cEntries - 1];
+
+            /* right */
+            if (!AVLStack.achFlags[AVLStack.cEntries - 1]++)
+            {
+                if (pNode->pRight != KAVL_NULL)
+                {
+                    AVLStack.achFlags[AVLStack.cEntries] = 0;  /* 0 first, 1 last */
+                    AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->pRight);
+                    continue;
+                }
+            }
+
+            /* center */
+            rc = pfnCallBack(pNode, pvParam);
+            if (rc != VINF_SUCCESS)
+                return rc;
+#ifdef KAVL_EQUAL_ALLOWED
+            if (pNode->pList != KAVL_NULL)
+                for (pEqual = KAVL_GET_POINTER(&pNode->pList); pEqual; pEqual = KAVL_GET_POINTER_NULL(&pEqual->pList))
+                {
+                    rc = pfnCallBack(pEqual, pvParam);
+                    if (rc != VINF_SUCCESS)
+                        return rc;
+                }
+#endif
+
+            /* left */
+            AVLStack.cEntries--;
+            if (pNode->pLeft != KAVL_NULL)
+            {
+                AVLStack.achFlags[AVLStack.cEntries] = 0;
+                AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->pLeft);
+            }
+        } /* while */
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+#endif
+
diff --git a/ubuntu/vbox/vboxguest/common/table/avl_Get.cpp.h b/ubuntu/vbox/vboxguest/common/table/avl_Get.cpp.h
new file mode 100644 (file)
index 0000000..77d0b5b
--- /dev/null
@@ -0,0 +1,67 @@
+/* $Id: avl_Get.cpp.h $ */
+/** @file
+ * kAVLGet - get routine for AVL trees.
+ */
+
+/*
+ * Copyright (C) 2006-2017 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.
+ */
+
+#ifndef _kAVLGet_h_
+#define _kAVLGet_h_
+
+
+/**
+ * Gets a node from the tree (does not remove it!)
+ * @returns   Pointer to the node holding the given key.
+ * @param     ppTree  Pointer to the AVL-tree root node pointer.
+ * @param     Key     Key value of the node which is to be found.
+ * @author    knut st. osmundsen
+ */
+KAVL_DECL(PKAVLNODECORE) KAVL_FN(Get)(PPKAVLNODECORE ppTree, KAVLKEY Key)
+{
+    register PKAVLNODECORE  pNode = KAVL_GET_POINTER_NULL(ppTree);
+
+    if (pNode)
+    {
+        while (KAVL_NE(pNode->Key, Key))
+        {
+            if (KAVL_G(pNode->Key, Key))
+            {
+                if (pNode->pLeft != KAVL_NULL)
+                    pNode = KAVL_GET_POINTER(&pNode->pLeft);
+                else
+                    return NULL;
+            }
+            else
+            {
+                if (pNode->pRight != KAVL_NULL)
+                    pNode = KAVL_GET_POINTER(&pNode->pRight);
+                else
+                    return NULL;
+            }
+        }
+    }
+
+    return pNode;
+}
+
+
+#endif
diff --git a/ubuntu/vbox/vboxguest/common/table/avl_GetBestFit.cpp.h b/ubuntu/vbox/vboxguest/common/table/avl_GetBestFit.cpp.h
new file mode 100644 (file)
index 0000000..f383804
--- /dev/null
@@ -0,0 +1,103 @@
+/* $Id: avl_GetBestFit.cpp.h $ */
+/** @file
+ * kAVLGetBestFit - Get Best Fit routine for AVL trees.
+ *                  Intended specially on heaps. The tree should allow duplicate keys.
+ *
+ */
+
+/*
+ * Copyright (C) 2006-2017 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.
+ */
+
+#ifndef _kAVLGetBestFit_h_
+#define _kAVLGetBestFit_h_
+
+
+/**
+ * Finds the best fitting node in the tree for the given Key value.
+ * @returns   Pointer to the best fitting node found.
+ * @param     ppTree  Pointer to Pointer to the tree root node.
+ * @param     Key     The Key of which is to be found a best fitting match for..
+ * @param     fAbove  TRUE:  Returned node is have the closest key to Key from above.
+ *                    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(PKAVLNODECORE) KAVL_FN(GetBestFit)(PPKAVLNODECORE ppTree, KAVLKEY Key, bool fAbove)
+{
+    register PKAVLNODECORE  pNode = KAVL_GET_POINTER_NULL(ppTree);
+    if (pNode)
+    {
+        PKAVLNODECORE           pNodeLast = NULL;
+        if (fAbove)
+        {   /* pNode->Key >= Key */
+            while (KAVL_NE(pNode->Key, Key))
+            {
+                if (KAVL_G(pNode->Key, Key))
+                {
+                    if (pNode->pLeft != KAVL_NULL)
+                    {
+                        pNodeLast = pNode;
+                        pNode = KAVL_GET_POINTER(&pNode->pLeft);
+                    }
+                    else
+                        return pNode;
+                }
+                else
+                {
+                    if (pNode->pRight != KAVL_NULL)
+                        pNode = KAVL_GET_POINTER(&pNode->pRight);
+                    else
+                        return pNodeLast;
+                }
+            }
+        }
+        else
+        {   /* pNode->Key <= Key */
+            while (KAVL_NE(pNode->Key, Key))
+            {
+                if (KAVL_G(pNode->Key, Key))
+                {
+                    if (pNode->pLeft != KAVL_NULL)
+                        pNode = KAVL_GET_POINTER(&pNode->pLeft);
+                    else
+                        return pNodeLast;
+                }
+                else
+                {
+                    if (pNode->pRight != KAVL_NULL)
+                    {
+                        pNodeLast = pNode;
+                        pNode = KAVL_GET_POINTER(&pNode->pRight);
+                    }
+                    else
+                        return pNode;
+                }
+            }
+        }
+    }
+
+    /* perfect match or nothing. */
+    return pNode;
+}
+
+
+#endif
diff --git a/ubuntu/vbox/vboxguest/common/table/avl_RemoveBestFit.cpp.h b/ubuntu/vbox/vboxguest/common/table/avl_RemoveBestFit.cpp.h
new file mode 100644 (file)
index 0000000..7416855
--- /dev/null
@@ -0,0 +1,70 @@
+/* $Id: avl_RemoveBestFit.cpp.h $ */
+/** @file
+ * kAVLRemoveBestFit - Remove Best Fit routine for AVL trees.
+ *                     Intended specially on heaps. The tree should allow duplicate keys.
+ *
+ */
+
+/*
+ * Copyright (C) 2006-2017 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.
+ */
+
+#ifndef _kAVLRemoveBestFit_h_
+#define _kAVLRemoveBestFit_h_
+
+
+/**
+ * Finds the best fitting node in the tree for the given Key value.
+ * And removes it.
+ * @returns   Pointer to the best fitting node found.
+ * @param     ppTree  Pointer to Pointer to the tree root node.
+ * @param     Key     The Key of which is to be found a best fitting match for..
+ * @param     fAbove  TRUE:  Returned node is have the closest key to Key from above.
+ *                    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.
+ * @remark    This implementation should be speeded up slightly!
+ */
+KAVL_DECL(PKAVLNODECORE) KAVL_FN(RemoveBestFit)(PPKAVLNODECORE ppTree, KAVLKEY Key, bool fAbove)
+{
+    /*
+     * If we find anything we'll have to remove the node and return it.
+     * But, if duplicate keys are allowed we'll have to check for multiple
+     * nodes first and return one of them before doing an expensive remove+insert.
+     */
+    PKAVLNODECORE   pNode = KAVL_FN(GetBestFit)(ppTree, Key, fAbove);
+    if (pNode != NULL)
+    {
+#ifdef KAVL_EQUAL_ALLOWED
+        if (pNode->pList != KAVL_NULL)
+        {
+            PKAVLNODECORE pRet = KAVL_GET_POINTER(&pNode->pList);
+            KAVL_SET_POINTER_NULL(&pNode->pList, &pRet->pList);
+            return pRet;
+        }
+#endif
+        pNode = KAVL_FN(Remove)(ppTree, pNode->Key);
+    }
+    return pNode;
+}
+
+
+#endif
diff --git a/ubuntu/vbox/vboxguest/common/table/avlpv.c b/ubuntu/vbox/vboxguest/common/table/avlpv.c
new file mode 100644 (file)
index 0000000..1aea277
--- /dev/null
@@ -0,0 +1,78 @@
+/* $Id: avlpv.cpp $ */
+/** @file
+ * IPRT - AVL tree, void *, unique keys.
+ */
+
+/*
+ * Copyright (C) 2006-2017 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.
+ */
+
+#ifndef NOFILEID
+static const char szFileId[] = "Id: kAVLPVInt.c,v 1.5 2003/02/13 02:02:35 bird Exp $";
+#endif
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+/*
+ * AVL configuration.
+ */
+#define KAVL_FN(a)                  RTAvlPV##a
+#define KAVL_MAX_STACK              27  /* Up to 2^24 nodes. */
+#define KAVL_CHECK_FOR_EQUAL_INSERT 1   /* No duplicate keys! */
+#define KAVLNODECORE                AVLPVNODECORE
+#define PKAVLNODECORE               PAVLPVNODECORE
+#define PPKAVLNODECORE              PPAVLPVNODECORE
+#define KAVLKEY                     AVLPVKEY
+#define PKAVLKEY                    PAVLPVKEY
+#define KAVLENUMDATA                AVLPVENUMDATA
+#define PKAVLENUMDATA               PAVLPVENUMDATA
+#define PKAVLCALLBACK               PAVLPVCALLBACK
+
+
+/*
+ * AVL Compare macros
+ */
+#define KAVL_G(key1, key2)          ( (const char*)(key1) >  (const char*)(key2) )
+#define KAVL_E(key1, key2)          ( (const char*)(key1) == (const char*)(key2) )
+#define KAVL_NE(key1, key2)         ( (const char*)(key1) != (const char*)(key2) )
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/avl.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+
+/*
+ * Include the code.
+ */
+#define SSToDS(ptr) ptr
+#define KMAX RT_MAX
+#define kASSERT Assert
+#include "avl_Base.cpp.h"
+#include "avl_Get.cpp.h"
+#include "avl_GetBestFit.cpp.h"
+#include "avl_RemoveBestFit.cpp.h"
+#include "avl_DoWithAll.cpp.h"
+#include "avl_Destroy.cpp.h"
+
diff --git a/ubuntu/vbox/vboxguest/common/time/time.c b/ubuntu/vbox/vboxguest/common/time/time.c
new file mode 100644 (file)
index 0000000..ee02cb0
--- /dev/null
@@ -0,0 +1,907 @@
+/* $Id: time.cpp $ */
+/** @file
+ * IPRT - Time.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_TIME
+#include <iprt/time.h>
+#include "internal/iprt.h"
+
+#include <iprt/ctype.h>
+#include <iprt/string.h>
+#include <iprt/assert.h>
+#include "internal/time.h"
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+/** The max year we possibly could implode. */
+#define RTTIME_MAX_YEAR         (292 + 1970)
+/** The min year we possibly could implode. */
+#define RTTIME_MIN_YEAR         (-293 + 1970)
+
+/** The max day supported by our time representation. (2262-04-11T23-47-16.854775807) */
+#define RTTIME_MAX_DAY          (365*292+71 + 101-1)
+/** The min day supported by our time representation. (1677-09-21T00-12-43.145224192) */
+#define RTTIME_MIN_DAY          (365*-293-70 + 264-1)
+
+/** The max nano second into the max day.             (2262-04-11T23-47-16.854775807) */
+#define RTTIME_MAX_DAY_NANO     ( INT64_C(1000000000) * (23*3600 + 47*60 + 16) + 854775807 )
+/** The min nano second into the min day.             (1677-09-21T00-12-43.145224192) */
+#define RTTIME_MIN_DAY_NANO     ( INT64_C(1000000000) * (00*3600 + 12*60 + 43) + 145224192 )
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/**
+ * Days per month in a common year.
+ */
+static const uint8_t g_acDaysInMonths[12] =
+{
+  /*Jan Feb Mar Arp May Jun Jul Aug Sep Oct Nov Dec */
+    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+/**
+ * Days per month in a leap year.
+ */
+static const uint8_t g_acDaysInMonthsLeap[12] =
+{
+  /*Jan Feb Mar Arp May Jun Jul Aug Sep Oct Nov Dec */
+    31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+/**
+ * The day of year for each month in a common year.
+ */
+static const uint16_t g_aiDayOfYear[12 + 1] =
+{
+    1,                                  /* Jan */
+    1+31,                               /* Feb */
+    1+31+28,                            /* Mar */
+    1+31+28+31,                         /* Apr */
+    1+31+28+31+30,                      /* May */
+    1+31+28+31+30+31,                   /* Jun */
+    1+31+28+31+30+31+30,                /* Jul */
+    1+31+28+31+30+31+30+31,             /* Aug */
+    1+31+28+31+30+31+30+31+31,          /* Sep */
+    1+31+28+31+30+31+30+31+31+30,       /* Oct */
+    1+31+28+31+30+31+30+31+31+30+31,    /* Nov */
+    1+31+28+31+30+31+30+31+31+30+31+30, /* Dec */
+    1+31+28+31+30+31+30+31+31+30+31+30+31
+};
+
+/**
+ * The day of year for each month in a leap year.
+ */
+static const uint16_t g_aiDayOfYearLeap[12 + 1] =
+{
+    1,                                  /* Jan */
+    1+31,                               /* Feb */
+    1+31+29,                            /* Mar */
+    1+31+29+31,                         /* Apr */
+    1+31+29+31+30,                      /* May */
+    1+31+29+31+30+31,                   /* Jun */
+    1+31+29+31+30+31+30,                /* Jul */
+    1+31+29+31+30+31+30+31,             /* Aug */
+    1+31+29+31+30+31+30+31+31,          /* Sep */
+    1+31+29+31+30+31+30+31+31+30,       /* Oct */
+    1+31+29+31+30+31+30+31+31+30+31,    /* Nov */
+    1+31+29+31+30+31+30+31+31+30+31+30, /* Dec */
+    1+31+29+31+30+31+30+31+31+30+31+30+31
+};
+
+/** The index of 1970 in g_aoffYear */
+#define OFF_YEAR_IDX_EPOCH  300
+/** The year of the first index. */
+#define OFF_YEAR_IDX_0_YEAR 1670
+
+/**
+ * The number of days the 1st of January a year is offseted from 1970-01-01.
+ */
+static const int32_t g_aoffYear[] =
+{
+/*1670:*/ 365*-300+-72, 365*-299+-72, 365*-298+-72, 365*-297+-71, 365*-296+-71, 365*-295+-71, 365*-294+-71, 365*-293+-70, 365*-292+-70, 365*-291+-70,
+/*1680:*/ 365*-290+-70, 365*-289+-69, 365*-288+-69, 365*-287+-69, 365*-286+-69, 365*-285+-68, 365*-284+-68, 365*-283+-68, 365*-282+-68, 365*-281+-67,
+/*1690:*/ 365*-280+-67, 365*-279+-67, 365*-278+-67, 365*-277+-66, 365*-276+-66, 365*-275+-66, 365*-274+-66, 365*-273+-65, 365*-272+-65, 365*-271+-65,
+/*1700:*/ 365*-270+-65, 365*-269+-65, 365*-268+-65, 365*-267+-65, 365*-266+-65, 365*-265+-64, 365*-264+-64, 365*-263+-64, 365*-262+-64, 365*-261+-63,
+/*1710:*/ 365*-260+-63, 365*-259+-63, 365*-258+-63, 365*-257+-62, 365*-256+-62, 365*-255+-62, 365*-254+-62, 365*-253+-61, 365*-252+-61, 365*-251+-61,
+/*1720:*/ 365*-250+-61, 365*-249+-60, 365*-248+-60, 365*-247+-60, 365*-246+-60, 365*-245+-59, 365*-244+-59, 365*-243+-59, 365*-242+-59, 365*-241+-58,
+/*1730:*/ 365*-240+-58, 365*-239+-58, 365*-238+-58, 365*-237+-57, 365*-236+-57, 365*-235+-57, 365*-234+-57, 365*-233+-56, 365*-232+-56, 365*-231+-56,
+/*1740:*/ 365*-230+-56, 365*-229+-55, 365*-228+-55, 365*-227+-55, 365*-226+-55, 365*-225+-54, 365*-224+-54, 365*-223+-54, 365*-222+-54, 365*-221+-53,
+/*1750:*/ 365*-220+-53, 365*-219+-53, 365*-218+-53, 365*-217+-52, 365*-216+-52, 365*-215+-52, 365*-214+-52, 365*-213+-51, 365*-212+-51, 365*-211+-51,
+/*1760:*/ 365*-210+-51, 365*-209+-50, 365*-208+-50, 365*-207+-50, 365*-206+-50, 365*-205+-49, 365*-204+-49, 365*-203+-49, 365*-202+-49, 365*-201+-48,
+/*1770:*/ 365*-200+-48, 365*-199+-48, 365*-198+-48, 365*-197+-47, 365*-196+-47, 365*-195+-47, 365*-194+-47, 365*-193+-46, 365*-192+-46, 365*-191+-46,
+/*1780:*/ 365*-190+-46, 365*-189+-45, 365*-188+-45, 365*-187+-45, 365*-186+-45, 365*-185+-44, 365*-184+-44, 365*-183+-44, 365*-182+-44, 365*-181+-43,
+/*1790:*/ 365*-180+-43, 365*-179+-43, 365*-178+-43, 365*-177+-42, 365*-176+-42, 365*-175+-42, 365*-174+-42, 365*-173+-41, 365*-172+-41, 365*-171+-41,
+/*1800:*/ 365*-170+-41, 365*-169+-41, 365*-168+-41, 365*-167+-41, 365*-166+-41, 365*-165+-40, 365*-164+-40, 365*-163+-40, 365*-162+-40, 365*-161+-39,
+/*1810:*/ 365*-160+-39, 365*-159+-39, 365*-158+-39, 365*-157+-38, 365*-156+-38, 365*-155+-38, 365*-154+-38, 365*-153+-37, 365*-152+-37, 365*-151+-37,
+/*1820:*/ 365*-150+-37, 365*-149+-36, 365*-148+-36, 365*-147+-36, 365*-146+-36, 365*-145+-35, 365*-144+-35, 365*-143+-35, 365*-142+-35, 365*-141+-34,
+/*1830:*/ 365*-140+-34, 365*-139+-34, 365*-138+-34, 365*-137+-33, 365*-136+-33, 365*-135+-33, 365*-134+-33, 365*-133+-32, 365*-132+-32, 365*-131+-32,
+/*1840:*/ 365*-130+-32, 365*-129+-31, 365*-128+-31, 365*-127+-31, 365*-126+-31, 365*-125+-30, 365*-124+-30, 365*-123+-30, 365*-122+-30, 365*-121+-29,
+/*1850:*/ 365*-120+-29, 365*-119+-29, 365*-118+-29, 365*-117+-28, 365*-116+-28, 365*-115+-28, 365*-114+-28, 365*-113+-27, 365*-112+-27, 365*-111+-27,
+/*1860:*/ 365*-110+-27, 365*-109+-26, 365*-108+-26, 365*-107+-26, 365*-106+-26, 365*-105+-25, 365*-104+-25, 365*-103+-25, 365*-102+-25, 365*-101+-24,
+/*1870:*/ 365*-100+-24, 365* -99+-24, 365* -98+-24, 365* -97+-23, 365* -96+-23, 365* -95+-23, 365* -94+-23, 365* -93+-22, 365* -92+-22, 365* -91+-22,
+/*1880:*/ 365* -90+-22, 365* -89+-21, 365* -88+-21, 365* -87+-21, 365* -86+-21, 365* -85+-20, 365* -84+-20, 365* -83+-20, 365* -82+-20, 365* -81+-19,
+/*1890:*/ 365* -80+-19, 365* -79+-19, 365* -78+-19, 365* -77+-18, 365* -76+-18, 365* -75+-18, 365* -74+-18, 365* -73+-17, 365* -72+-17, 365* -71+-17,
+/*1900:*/ 365* -70+-17, 365* -69+-17, 365* -68+-17, 365* -67+-17, 365* -66+-17, 365* -65+-16, 365* -64+-16, 365* -63+-16, 365* -62+-16, 365* -61+-15,
+/*1910:*/ 365* -60+-15, 365* -59+-15, 365* -58+-15, 365* -57+-14, 365* -56+-14, 365* -55+-14, 365* -54+-14, 365* -53+-13, 365* -52+-13, 365* -51+-13,
+/*1920:*/ 365* -50+-13, 365* -49+-12, 365* -48+-12, 365* -47+-12, 365* -46+-12, 365* -45+-11, 365* -44+-11, 365* -43+-11, 365* -42+-11, 365* -41+-10,
+/*1930:*/ 365* -40+-10, 365* -39+-10, 365* -38+-10, 365* -37+-9 , 365* -36+-9 , 365* -35+-9 , 365* -34+-9 , 365* -33+-8 , 365* -32+-8 , 365* -31+-8 ,
+/*1940:*/ 365* -30+-8 , 365* -29+-7 , 365* -28+-7 , 365* -27+-7 , 365* -26+-7 , 365* -25+-6 , 365* -24+-6 , 365* -23+-6 , 365* -22+-6 , 365* -21+-5 ,
+/*1950:*/ 365* -20+-5 , 365* -19+-5 , 365* -18+-5 , 365* -17+-4 , 365* -16+-4 , 365* -15+-4 , 365* -14+-4 , 365* -13+-3 , 365* -12+-3 , 365* -11+-3 ,
+/*1960:*/ 365* -10+-3 , 365*  -9+-2 , 365*  -8+-2 , 365*  -7+-2 , 365*  -6+-2 , 365*  -5+-1 , 365*  -4+-1 , 365*  -3+-1 , 365*  -2+-1 , 365*  -1+0  ,
+/*1970:*/ 365*   0+0  , 365*   1+0  , 365*   2+0  , 365*   3+1  , 365*   4+1  , 365*   5+1  , 365*   6+1  , 365*   7+2  , 365*   8+2  , 365*   9+2  ,
+/*1980:*/ 365*  10+2  , 365*  11+3  , 365*  12+3  , 365*  13+3  , 365*  14+3  , 365*  15+4  , 365*  16+4  , 365*  17+4  , 365*  18+4  , 365*  19+5  ,
+/*1990:*/ 365*  20+5  , 365*  21+5  , 365*  22+5  , 365*  23+6  , 365*  24+6  , 365*  25+6  , 365*  26+6  , 365*  27+7  , 365*  28+7  , 365*  29+7  ,
+/*2000:*/ 365*  30+7  , 365*  31+8  , 365*  32+8  , 365*  33+8  , 365*  34+8  , 365*  35+9  , 365*  36+9  , 365*  37+9  , 365*  38+9  , 365*  39+10 ,
+/*2010:*/ 365*  40+10 , 365*  41+10 , 365*  42+10 , 365*  43+11 , 365*  44+11 , 365*  45+11 , 365*  46+11 , 365*  47+12 , 365*  48+12 , 365*  49+12 ,
+/*2020:*/ 365*  50+12 , 365*  51+13 , 365*  52+13 , 365*  53+13 , 365*  54+13 , 365*  55+14 , 365*  56+14 , 365*  57+14 , 365*  58+14 , 365*  59+15 ,
+/*2030:*/ 365*  60+15 , 365*  61+15 , 365*  62+15 , 365*  63+16 , 365*  64+16 , 365*  65+16 , 365*  66+16 , 365*  67+17 , 365*  68+17 , 365*  69+17 ,
+/*2040:*/ 365*  70+17 , 365*  71+18 , 365*  72+18 , 365*  73+18 , 365*  74+18 , 365*  75+19 , 365*  76+19 , 365*  77+19 , 365*  78+19 , 365*  79+20 ,
+/*2050:*/ 365*  80+20 , 365*  81+20 , 365*  82+20 , 365*  83+21 , 365*  84+21 , 365*  85+21 , 365*  86+21 , 365*  87+22 , 365*  88+22 , 365*  89+22 ,
+/*2060:*/ 365*  90+22 , 365*  91+23 , 365*  92+23 , 365*  93+23 , 365*  94+23 , 365*  95+24 , 365*  96+24 , 365*  97+24 , 365*  98+24 , 365*  99+25 ,
+/*2070:*/ 365* 100+25 , 365* 101+25 , 365* 102+25 , 365* 103+26 , 365* 104+26 , 365* 105+26 , 365* 106+26 , 365* 107+27 , 365* 108+27 , 365* 109+27 ,
+/*2080:*/ 365* 110+27 , 365* 111+28 , 365* 112+28 , 365* 113+28 , 365* 114+28 , 365* 115+29 , 365* 116+29 , 365* 117+29 , 365* 118+29 , 365* 119+30 ,
+/*2090:*/ 365* 120+30 , 365* 121+30 , 365* 122+30 , 365* 123+31 , 365* 124+31 , 365* 125+31 , 365* 126+31 , 365* 127+32 , 365* 128+32 , 365* 129+32 ,
+/*2100:*/ 365* 130+32 , 365* 131+32 , 365* 132+32 , 365* 133+32 , 365* 134+32 , 365* 135+33 , 365* 136+33 , 365* 137+33 , 365* 138+33 , 365* 139+34 ,
+/*2110:*/ 365* 140+34 , 365* 141+34 , 365* 142+34 , 365* 143+35 , 365* 144+35 , 365* 145+35 , 365* 146+35 , 365* 147+36 , 365* 148+36 , 365* 149+36 ,
+/*2120:*/ 365* 150+36 , 365* 151+37 , 365* 152+37 , 365* 153+37 , 365* 154+37 , 365* 155+38 , 365* 156+38 , 365* 157+38 , 365* 158+38 , 365* 159+39 ,
+/*2130:*/ 365* 160+39 , 365* 161+39 , 365* 162+39 , 365* 163+40 , 365* 164+40 , 365* 165+40 , 365* 166+40 , 365* 167+41 , 365* 168+41 , 365* 169+41 ,
+/*2140:*/ 365* 170+41 , 365* 171+42 , 365* 172+42 , 365* 173+42 , 365* 174+42 , 365* 175+43 , 365* 176+43 , 365* 177+43 , 365* 178+43 , 365* 179+44 ,
+/*2150:*/ 365* 180+44 , 365* 181+44 , 365* 182+44 , 365* 183+45 , 365* 184+45 , 365* 185+45 , 365* 186+45 , 365* 187+46 , 365* 188+46 , 365* 189+46 ,
+/*2160:*/ 365* 190+46 , 365* 191+47 , 365* 192+47 , 365* 193+47 , 365* 194+47 , 365* 195+48 , 365* 196+48 , 365* 197+48 , 365* 198+48 , 365* 199+49 ,
+/*2170:*/ 365* 200+49 , 365* 201+49 , 365* 202+49 , 365* 203+50 , 365* 204+50 , 365* 205+50 , 365* 206+50 , 365* 207+51 , 365* 208+51 , 365* 209+51 ,
+/*2180:*/ 365* 210+51 , 365* 211+52 , 365* 212+52 , 365* 213+52 , 365* 214+52 , 365* 215+53 , 365* 216+53 , 365* 217+53 , 365* 218+53 , 365* 219+54 ,
+/*2190:*/ 365* 220+54 , 365* 221+54 , 365* 222+54 , 365* 223+55 , 365* 224+55 , 365* 225+55 , 365* 226+55 , 365* 227+56 , 365* 228+56 , 365* 229+56 ,
+/*2200:*/ 365* 230+56 , 365* 231+56 , 365* 232+56 , 365* 233+56 , 365* 234+56 , 365* 235+57 , 365* 236+57 , 365* 237+57 , 365* 238+57 , 365* 239+58 ,
+/*2210:*/ 365* 240+58 , 365* 241+58 , 365* 242+58 , 365* 243+59 , 365* 244+59 , 365* 245+59 , 365* 246+59 , 365* 247+60 , 365* 248+60 , 365* 249+60 ,
+/*2220:*/ 365* 250+60 , 365* 251+61 , 365* 252+61 , 365* 253+61 , 365* 254+61 , 365* 255+62 , 365* 256+62 , 365* 257+62 , 365* 258+62 , 365* 259+63 ,
+/*2230:*/ 365* 260+63 , 365* 261+63 , 365* 262+63 , 365* 263+64 , 365* 264+64 , 365* 265+64 , 365* 266+64 , 365* 267+65 , 365* 268+65 , 365* 269+65 ,
+/*2240:*/ 365* 270+65 , 365* 271+66 , 365* 272+66 , 365* 273+66 , 365* 274+66 , 365* 275+67 , 365* 276+67 , 365* 277+67 , 365* 278+67 , 365* 279+68 ,
+/*2250:*/ 365* 280+68 , 365* 281+68 , 365* 282+68 , 365* 283+69 , 365* 284+69 , 365* 285+69 , 365* 286+69 , 365* 287+70 , 365* 288+70 , 365* 289+70 ,
+/*2260:*/ 365* 290+70 , 365* 291+71 , 365* 292+71 , 365* 293+71 , 365* 294+71 , 365* 295+72 , 365* 296+72 , 365* 297+72 , 365* 298+72 , 365* 299+73
+};
+
+/* generator code:
+#include <stdio.h>
+bool isLeapYear(int iYear)
+{
+    return iYear % 4 == 0 && (iYear % 100 != 0 || iYear % 400 == 0);
+}
+void printYear(int iYear, int iLeap)
+{
+    if (!(iYear % 10))
+        printf("\n/" "*%d:*" "/", iYear + 1970);
+    printf(" 365*%4d+%-3d,", iYear, iLeap);
+}
+int main()
+{
+    int iYear = 0;
+    int iLeap = 0;
+    while (iYear > -300)
+        iLeap -= isLeapYear(1970 + --iYear);
+    while (iYear < 300)
+    {
+        printYear(iYear, iLeap);
+        iLeap += isLeapYear(1970 + iYear++);
+    }
+    printf("\n");
+    return 0;
+}
+*/
+
+
+/**
+ * Checks if a year is a leap year or not.
+ *
+ * @returns true if it's a leap year.
+ * @returns false if it's a common year.
+ * @param   i32Year     The year in question.
+ */
+DECLINLINE(bool) rtTimeIsLeapYear(int32_t i32Year)
+{
+    return i32Year % 4 == 0
+        && (    i32Year % 100 != 0
+            ||  i32Year % 400 == 0);
+}
+
+
+/**
+ * Checks if a year is a leap year or not.
+ *
+ * @returns true if it's a leap year.
+ * @returns false if it's a common year.
+ * @param   i32Year     The year in question.
+ */
+RTDECL(bool) RTTimeIsLeapYear(int32_t i32Year)
+{
+    return rtTimeIsLeapYear(i32Year);
+}
+RT_EXPORT_SYMBOL(RTTimeIsLeapYear);
+
+
+/**
+ * Explodes a time spec (UTC).
+ *
+ * @returns pTime.
+ * @param   pTime       Where to store the exploded time.
+ * @param   pTimeSpec   The time spec to exploded.
+ */
+RTDECL(PRTTIME) RTTimeExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec)
+{
+    int64_t         i64Div;
+    int32_t         i32Div;
+    int32_t         i32Rem;
+    unsigned        iYear;
+    const uint16_t *paiDayOfYear;
+    int             iMonth;
+
+    AssertMsg(VALID_PTR(pTime), ("%p\n", pTime));
+    AssertMsg(VALID_PTR(pTimeSpec), ("%p\n", pTime));
+
+    /*
+     * The simple stuff first.
+     */
+    pTime->fFlags = RTTIME_FLAGS_TYPE_UTC;
+    i64Div = pTimeSpec->i64NanosecondsRelativeToUnixEpoch;
+    i32Rem = (int32_t)(i64Div % 1000000000);
+    i64Div /= 1000000000;
+    if (i32Rem < 0)
+    {
+        i32Rem += 1000000000;
+        i64Div--;
+    }
+    pTime->u32Nanosecond = i32Rem;
+
+    /* second */
+    i32Rem = (int32_t)(i64Div % 60);
+    i64Div /= 60;
+    if (i32Rem < 0)
+    {
+        i32Rem += 60;
+        i64Div--;
+    }
+    pTime->u8Second      = i32Rem;
+
+    /* minute */
+    i32Div = (int32_t)i64Div;   /* 60,000,000,000 > 33bit, so 31bit suffices. */
+    i32Rem = i32Div % 60;
+    i32Div /= 60;
+    if (i32Rem < 0)
+    {
+        i32Rem += 60;
+        i32Div--;
+    }
+    pTime->u8Minute      = i32Rem;
+
+    /* hour */
+    i32Rem = i32Div % 24;
+    i32Div /= 24;                       /* days relative to 1970-01-01 */
+    if (i32Rem < 0)
+    {
+        i32Rem += 24;
+        i32Div--;
+    }
+    pTime->u8Hour        = i32Rem;
+
+    /* weekday - 1970-01-01 was a Thursday (3) */
+    pTime->u8WeekDay     = ((int)(i32Div % 7) + 3 + 7) % 7;
+
+    /*
+     * We've now got a number of days relative to 1970-01-01.
+     * To get the correct year number we have to mess with leap years. Fortunately,
+     * the representation we've got only supports a few hundred years, so we can
+     * generate a table and perform a simple two way search from the modulus 365 derived.
+     */
+    iYear = OFF_YEAR_IDX_EPOCH + i32Div / 365;
+    while (g_aoffYear[iYear + 1] <= i32Div)
+        iYear++;
+    while (g_aoffYear[iYear] > i32Div)
+        iYear--;
+    pTime->i32Year       = iYear + OFF_YEAR_IDX_0_YEAR;
+    i32Div -= g_aoffYear[iYear];
+    pTime->u16YearDay    = i32Div + 1;
+
+    /*
+     * Figuring out the month is done in a manner similar to the year, only here we
+     * ensure that the index is matching or too small.
+     */
+    if (rtTimeIsLeapYear(pTime->i32Year))
+    {
+        pTime->fFlags   |= RTTIME_FLAGS_LEAP_YEAR;
+        paiDayOfYear = &g_aiDayOfYearLeap[0];
+    }
+    else
+    {
+        pTime->fFlags   |= RTTIME_FLAGS_COMMON_YEAR;
+        paiDayOfYear = &g_aiDayOfYear[0];
+    }
+    iMonth = i32Div / 32;
+    i32Div++;
+    while (paiDayOfYear[iMonth + 1] <= i32Div)
+        iMonth++;
+    pTime->u8Month       = iMonth + 1;
+    i32Div -= paiDayOfYear[iMonth];
+    pTime->u8MonthDay    = i32Div + 1;
+
+    /* This is for UTC timespecs, so, no offset. */
+    pTime->offUTC        = 0;
+
+    return pTime;
+}
+RT_EXPORT_SYMBOL(RTTimeExplode);
+
+
+/**
+ * Implodes exploded time to a time spec (UTC).
+ *
+ * @returns pTime on success.
+ * @returns NULL if the pTime data is invalid.
+ * @param   pTimeSpec   Where to store the imploded UTC time.
+ *                      If pTime specifies a time which outside the range, maximum or
+ *                      minimum values will be returned.
+ * @param   pTime       Pointer to the exploded time to implode.
+ *                      The fields u8Month, u8WeekDay and u8MonthDay are not used,
+ *                      and all the other fields are expected to be within their
+ *                      bounds. Use RTTimeNormalize() to calculate u16YearDay and
+ *                      normalize the ranges of the fields.
+ */
+RTDECL(PRTTIMESPEC) RTTimeImplode(PRTTIMESPEC pTimeSpec, PCRTTIME pTime)
+{
+    int32_t     i32Days;
+    uint32_t    u32Secs;
+    int64_t     i64Nanos;
+
+    /*
+     * Validate input.
+     */
+    AssertReturn(VALID_PTR(pTimeSpec), NULL);
+    AssertReturn(VALID_PTR(pTime), NULL);
+    AssertReturn(pTime->u32Nanosecond < 1000000000, NULL);
+    AssertReturn(pTime->u8Second < 60, NULL);
+    AssertReturn(pTime->u8Minute < 60, NULL);
+    AssertReturn(pTime->u8Hour < 24, NULL);
+    AssertReturn(pTime->u16YearDay >= 1, NULL);
+    AssertReturn(pTime->u16YearDay <= (rtTimeIsLeapYear(pTime->i32Year) ? 366 : 365), NULL);
+    AssertMsgReturn(pTime->i32Year <= RTTIME_MAX_YEAR && pTime->i32Year >= RTTIME_MIN_YEAR, ("%RI32\n", pTime->i32Year), NULL);
+
+    /*
+     * Do the conversion to nanoseconds.
+     */
+    i32Days  = g_aoffYear[pTime->i32Year - OFF_YEAR_IDX_0_YEAR]
+             + pTime->u16YearDay - 1;
+    AssertMsgReturn(i32Days <= RTTIME_MAX_DAY && i32Days >= RTTIME_MIN_DAY, ("%RI32\n", i32Days), NULL);
+
+    u32Secs  = pTime->u8Second
+             + pTime->u8Minute * 60
+             + pTime->u8Hour   * 3600;
+    i64Nanos = (uint64_t)pTime->u32Nanosecond
+             + u32Secs * UINT64_C(1000000000);
+    AssertMsgReturn(i32Days != RTTIME_MAX_DAY || i64Nanos <= RTTIME_MAX_DAY_NANO, ("%RI64\n", i64Nanos), NULL);
+    AssertMsgReturn(i32Days != RTTIME_MIN_DAY || i64Nanos >= RTTIME_MIN_DAY_NANO, ("%RI64\n", i64Nanos), NULL);
+
+    i64Nanos += i32Days * UINT64_C(86400000000000);
+
+    pTimeSpec->i64NanosecondsRelativeToUnixEpoch = i64Nanos;
+    return pTimeSpec;
+}
+RT_EXPORT_SYMBOL(RTTimeImplode);
+
+
+/**
+ * Internal worker for RTTimeNormalize and RTTimeLocalNormalize.
+ * It doesn't adjust the UCT offset but leaves that for RTTimeLocalNormalize.
+ */
+static PRTTIME rtTimeNormalizeInternal(PRTTIME pTime)
+{
+    unsigned    uSecond;
+    unsigned    uMinute;
+    unsigned    uHour;
+    bool        fLeapYear;
+
+    /*
+     * Fix the YearDay and Month/MonthDay.
+     */
+    fLeapYear = rtTimeIsLeapYear(pTime->i32Year);
+    if (!pTime->u16YearDay)
+    {
+        /*
+         * The Month+MonthDay must present, overflow adjust them and calc the year day.
+         */
+        AssertMsgReturn(    pTime->u8Month
+                        &&  pTime->u8MonthDay,
+                        ("date=%d-%d-%d\n", pTime->i32Year, pTime->u8Month, pTime->u8MonthDay),
+                        NULL);
+        while (pTime->u8Month > 12)
+        {
+            pTime->u8Month -= 12;
+            pTime->i32Year++;
+            fLeapYear = rtTimeIsLeapYear(pTime->i32Year);
+            pTime->fFlags &= ~(RTTIME_FLAGS_COMMON_YEAR | RTTIME_FLAGS_LEAP_YEAR);
+        }
+
+        for (;;)
+        {
+            unsigned cDaysInMonth = fLeapYear
+                                  ? g_acDaysInMonthsLeap[pTime->u8Month - 1]
+                                  : g_acDaysInMonths[pTime->u8Month - 1];
+            if (pTime->u8MonthDay <= cDaysInMonth)
+                break;
+            pTime->u8MonthDay -= cDaysInMonth;
+            if (pTime->u8Month != 12)
+                pTime->u8Month++;
+            else
+            {
+                pTime->u8Month = 1;
+                pTime->i32Year++;
+                fLeapYear = rtTimeIsLeapYear(pTime->i32Year);
+                pTime->fFlags &= ~(RTTIME_FLAGS_COMMON_YEAR | RTTIME_FLAGS_LEAP_YEAR);
+            }
+        }
+
+        pTime->u16YearDay  = pTime->u8MonthDay - 1
+                           + (fLeapYear
+                              ? g_aiDayOfYearLeap[pTime->u8Month - 1]
+                              : g_aiDayOfYear[pTime->u8Month - 1]);
+    }
+    else
+    {
+        /*
+         * Are both YearDay and Month/MonthDay valid?
+         * Check that they don't overflow and match, if not use YearDay (simpler).
+         */
+        bool fRecalc = true;
+        if (    pTime->u8Month
+            &&  pTime->u8MonthDay)
+        {
+            do
+            {
+                uint16_t u16YearDay;
+
+                /* If you change one, zero the other to make clear what you mean. */
+                AssertBreak(pTime->u8Month <= 12);
+                AssertBreak(pTime->u8MonthDay <= (fLeapYear
+                                                  ? g_acDaysInMonthsLeap[pTime->u8Month - 1]
+                                                  : g_acDaysInMonths[pTime->u8Month - 1]));
+                u16YearDay = pTime->u8MonthDay - 1
+                           + (fLeapYear
+                              ? g_aiDayOfYearLeap[pTime->u8Month - 1]
+                              : g_aiDayOfYear[pTime->u8Month - 1]);
+                AssertBreak(u16YearDay == pTime->u16YearDay);
+                fRecalc = false;
+            } while (0);
+        }
+        if (fRecalc)
+        {
+            const uint16_t *paiDayOfYear;
+
+            /* overflow adjust YearDay */
+            while (pTime->u16YearDay > (fLeapYear ? 366 : 365))
+            {
+                pTime->u16YearDay -= fLeapYear ? 366 : 365;
+                pTime->i32Year++;
+                fLeapYear = rtTimeIsLeapYear(pTime->i32Year);
+                pTime->fFlags &= ~(RTTIME_FLAGS_COMMON_YEAR | RTTIME_FLAGS_LEAP_YEAR);
+            }
+
+            /* calc Month and MonthDay */
+            paiDayOfYear = fLeapYear
+                         ? &g_aiDayOfYearLeap[0]
+                         : &g_aiDayOfYear[0];
+            pTime->u8Month = 1;
+            while (pTime->u16YearDay > paiDayOfYear[pTime->u8Month])
+                pTime->u8Month++;
+            Assert(pTime->u8Month >= 1 && pTime->u8Month <= 12);
+            pTime->u8MonthDay = pTime->u16YearDay - paiDayOfYear[pTime->u8Month - 1] + 1;
+        }
+    }
+
+    /*
+     * Fixup time overflows.
+     * Use unsigned int values internally to avoid overflows.
+     */
+    uSecond = pTime->u8Second;
+    uMinute = pTime->u8Minute;
+    uHour   = pTime->u8Hour;
+
+    while (pTime->u32Nanosecond >= 1000000000)
+    {
+        pTime->u32Nanosecond -= 1000000000;
+        uSecond++;
+    }
+
+    while (uSecond >= 60)
+    {
+        uSecond -= 60;
+        uMinute++;
+    }
+
+    while (uMinute >= 60)
+    {
+        uMinute -= 60;
+        uHour++;
+    }
+
+    while (uHour >= 24)
+    {
+        uHour -= 24;
+
+        /* This is really a RTTimeIncDay kind of thing... */
+        if (pTime->u16YearDay + 1 != (fLeapYear ? g_aiDayOfYearLeap[pTime->u8Month] : g_aiDayOfYear[pTime->u8Month]))
+        {
+            pTime->u16YearDay++;
+            pTime->u8MonthDay++;
+        }
+        else if (pTime->u8Month != 12)
+        {
+            pTime->u16YearDay++;
+            pTime->u8Month++;
+            pTime->u8MonthDay = 1;
+        }
+        else
+        {
+            pTime->i32Year++;
+            fLeapYear = rtTimeIsLeapYear(pTime->i32Year);
+            pTime->fFlags &= ~(RTTIME_FLAGS_COMMON_YEAR | RTTIME_FLAGS_LEAP_YEAR);
+            pTime->u16YearDay = 1;
+            pTime->u8Month = 1;
+            pTime->u8MonthDay = 1;
+        }
+    }
+
+    pTime->u8Second = uSecond;
+    pTime->u8Minute = uMinute;
+    pTime->u8Hour = uHour;
+
+    /*
+     * Correct the leap year flag.
+     * Assert if it's wrong, but ignore if unset.
+     */
+    if (fLeapYear)
+    {
+        Assert(!(pTime->fFlags & RTTIME_FLAGS_COMMON_YEAR));
+        pTime->fFlags &= ~RTTIME_FLAGS_COMMON_YEAR;
+        pTime->fFlags |= RTTIME_FLAGS_LEAP_YEAR;
+    }
+    else
+    {
+        Assert(!(pTime->fFlags & RTTIME_FLAGS_LEAP_YEAR));
+        pTime->fFlags &= ~RTTIME_FLAGS_LEAP_YEAR;
+        pTime->fFlags |= RTTIME_FLAGS_COMMON_YEAR;
+    }
+
+
+    /*
+     * Calc week day.
+     *
+     * 1970-01-01 was a Thursday (3), so find the number of days relative to
+     * that point. We use the table when possible and a slow+stupid+brute-force
+     * algorithm for points outside it. Feel free to optimize the latter by
+     * using some clever formula.
+     */
+    if (    pTime->i32Year >= OFF_YEAR_IDX_0_YEAR
+        &&  pTime->i32Year <  OFF_YEAR_IDX_0_YEAR + (int32_t)RT_ELEMENTS(g_aoffYear))
+    {
+        int32_t offDays = g_aoffYear[pTime->i32Year - OFF_YEAR_IDX_0_YEAR]
+                        + pTime->u16YearDay -1;
+        pTime->u8WeekDay = ((offDays % 7) + 3 + 7) % 7;
+    }
+    else
+    {
+        int32_t i32Year = pTime->i32Year;
+        if (i32Year >= 1970)
+        {
+            uint64_t offDays = pTime->u16YearDay - 1;
+            while (--i32Year >= 1970)
+                offDays += rtTimeIsLeapYear(i32Year) ? 366 : 365;
+            pTime->u8WeekDay = (uint8_t)((offDays + 3) % 7);
+        }
+        else
+        {
+            int64_t offDays = (fLeapYear ? -366 - 1 : -365 - 1) + pTime->u16YearDay;
+            while (++i32Year < 1970)
+                offDays -= rtTimeIsLeapYear(i32Year) ? 366 : 365;
+            pTime->u8WeekDay = ((int)(offDays % 7) + 3 + 7) % 7;
+        }
+    }
+    return pTime;
+}
+
+
+/**
+ * Normalizes the fields of a time structure.
+ *
+ * It is possible to calculate year-day from month/day and vice
+ * versa. If you adjust any of these, make sure to zero the
+ * other so you make it clear which of the fields to use. If
+ * it's ambiguous, the year-day field is used (and you get
+ * assertions in debug builds).
+ *
+ * All the time fields and the year-day or month/day fields will
+ * be adjusted for overflows. (Since all fields are unsigned, there
+ * is no underflows.) It is possible to exploit this for simple
+ * date math, though the recommended way of doing that to implode
+ * the time into a timespec and do the math on that.
+ *
+ * @returns pTime on success.
+ * @returns NULL if the data is invalid.
+ *
+ * @param   pTime       The time structure to normalize.
+ *
+ * @remarks This function doesn't work with local time, only with UTC time.
+ */
+RTDECL(PRTTIME) RTTimeNormalize(PRTTIME pTime)
+{
+    /*
+     * Validate that we've got the minimum of stuff handy.
+     */
+    AssertReturn(VALID_PTR(pTime), NULL);
+    AssertMsgReturn(!(pTime->fFlags & ~RTTIME_FLAGS_MASK), ("%#x\n", pTime->fFlags), NULL);
+    AssertMsgReturn((pTime->fFlags & RTTIME_FLAGS_TYPE_MASK) != RTTIME_FLAGS_TYPE_LOCAL, ("Use RTTimeLocalNormalize!\n"), NULL);
+    AssertMsgReturn(pTime->offUTC == 0, ("%d; Use RTTimeLocalNormalize!\n", pTime->offUTC), NULL);
+
+    pTime = rtTimeNormalizeInternal(pTime);
+    if (pTime)
+        pTime->fFlags |= RTTIME_FLAGS_TYPE_UTC;
+    return pTime;
+}
+RT_EXPORT_SYMBOL(RTTimeNormalize);
+
+
+/**
+ * Converts a time spec to a ISO date string.
+ *
+ * @returns psz on success.
+ * @returns NULL on buffer underflow.
+ * @param   pTime       The time. Caller should've normalized this.
+ * @param   psz         Where to store the string.
+ * @param   cb          The size of the buffer.
+ */
+RTDECL(char *) RTTimeToString(PCRTTIME pTime, char *psz, size_t cb)
+{
+    size_t cch;
+
+    /* (Default to UTC if not specified) */
+    if (    (pTime->fFlags & RTTIME_FLAGS_TYPE_MASK) == RTTIME_FLAGS_TYPE_LOCAL
+        &&  pTime->offUTC)
+    {
+        int32_t offUTCHour   = pTime->offUTC / 60;
+        int32_t offUTCMinute = pTime->offUTC % 60;
+        char    chSign;
+        Assert(pTime->offUTC <= 840 && pTime->offUTC >= -840);
+        if (pTime->offUTC >= 0)
+            chSign = '+';
+        else
+        {
+            chSign = '-';
+            offUTCMinute = -offUTCMinute;
+            offUTCHour = -offUTCHour;
+        }
+        cch = RTStrPrintf(psz, cb,
+                          "%RI32-%02u-%02uT%02u:%02u:%02u.%09RU32%c%02d%02d",
+                          pTime->i32Year, pTime->u8Month, pTime->u8MonthDay,
+                          pTime->u8Hour, pTime->u8Minute, pTime->u8Second, pTime->u32Nanosecond,
+                          chSign, offUTCHour, offUTCMinute);
+        if (    cch <= 15
+            ||  psz[cch - 5] != chSign)
+            return NULL;
+    }
+    else
+    {
+        cch = RTStrPrintf(psz, cb, "%RI32-%02u-%02uT%02u:%02u:%02u.%09RU32Z",
+                          pTime->i32Year, pTime->u8Month, pTime->u8MonthDay,
+                          pTime->u8Hour, pTime->u8Minute, pTime->u8Second, pTime->u32Nanosecond);
+        if (    cch <= 15
+            ||  psz[cch - 1] != 'Z')
+            return NULL;
+    }
+    return psz;
+}
+RT_EXPORT_SYMBOL(RTTimeToString);
+
+
+/**
+ * Converts a time spec to a ISO date string.
+ *
+ * @returns psz on success.
+ * @returns NULL on buffer underflow.
+ * @param   pTime       The time spec.
+ * @param   psz         Where to store the string.
+ * @param   cb          The size of the buffer.
+ */
+RTDECL(char *) RTTimeSpecToString(PCRTTIMESPEC pTime, char *psz, size_t cb)
+{
+    RTTIME Time;
+    return RTTimeToString(RTTimeExplode(&Time, pTime), psz, cb);
+}
+RT_EXPORT_SYMBOL(RTTimeSpecToString);
+
+
+
+/**
+ * Attempts to convert an ISO date string to a time structure.
+ *
+ * We're a little forgiving with zero padding, unspecified parts, and leading
+ * and trailing spaces.
+ *
+ * @retval  pTime on success,
+ * @retval  NULL on failure.
+ * @param   pTime       Where to store the time on success.
+ * @param   pszString   The ISO date string to convert.
+ */
+RTDECL(PRTTIME) RTTimeFromString(PRTTIME pTime, const char *pszString)
+{
+    /* Ignore leading spaces. */
+    while (RT_C_IS_SPACE(*pszString))
+        pszString++;
+
+    /*
+     * Init non date & time parts.
+     */
+    pTime->fFlags = RTTIME_FLAGS_TYPE_LOCAL;
+    pTime->offUTC = 0;
+
+    /*
+     * The day part.
+     */
+
+    /* Year */
+    int rc = RTStrToInt32Ex(pszString, (char **)&pszString, 10, &pTime->i32Year);
+    if (rc != VWRN_TRAILING_CHARS)
+        return NULL;
+
+    bool const fLeapYear = rtTimeIsLeapYear(pTime->i32Year);
+    if (fLeapYear)
+        pTime->fFlags |= RTTIME_FLAGS_LEAP_YEAR;
+
+    if (*pszString++ != '-')
+        return NULL;
+
+    /* Month of the year. */
+    rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Month);
+    if (rc != VWRN_TRAILING_CHARS)
+        return NULL;
+    if (pTime->u8Month == 0 || pTime->u8Month > 12)
+        return NULL;
+    if (*pszString++ != '-')
+        return NULL;
+
+    /* Day of month.*/
+    rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8MonthDay);
+    if (rc != VWRN_TRAILING_CHARS && rc != VINF_SUCCESS)
+        return NULL;
+    unsigned const cDaysInMonth = fLeapYear
+                                ? g_acDaysInMonthsLeap[pTime->u8Month - 1]
+                                : g_acDaysInMonths[pTime->u8Month - 1];
+    if (pTime->u8MonthDay == 0 || pTime->u8MonthDay > cDaysInMonth)
+        return NULL;
+
+    /* Calculate year day. */
+    pTime->u16YearDay = pTime->u8MonthDay - 1
+                      + (fLeapYear
+                         ? g_aiDayOfYearLeap[pTime->u8Month - 1]
+                         : g_aiDayOfYear[pTime->u8Month - 1]);
+
+    /*
+     * The time part.
+     */
+    if (*pszString++ != 'T')
+        return NULL;
+
+    /* Hour. */
+    rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Hour);
+    if (rc != VWRN_TRAILING_CHARS)
+        return NULL;
+    if (pTime->u8Hour > 23)
+        return NULL;
+    if (*pszString++ != ':')
+        return NULL;
+
+    /* Minute. */
+    rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Minute);
+    if (rc != VWRN_TRAILING_CHARS)
+        return NULL;
+    if (pTime->u8Minute > 59)
+        return NULL;
+    if (*pszString++ != ':')
+        return NULL;
+
+    /* Second. */
+    rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Minute);
+    if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS && rc != VWRN_TRAILING_SPACES)
+        return NULL;
+    if (pTime->u8Second > 59)
+        return NULL;
+
+    /* Nanoseconds is optional and probably non-standard. */
+    if (*pszString == '.')
+    {
+        rc = RTStrToUInt32Ex(pszString + 1, (char **)&pszString, 10, &pTime->u32Nanosecond);
+        if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS && rc != VWRN_TRAILING_SPACES)
+            return NULL;
+        if (pTime->u32Nanosecond >= 1000000000)
+            return NULL;
+    }
+    else
+        pTime->u32Nanosecond = 0;
+
+    /*
+     * Time zone.
+     */
+    if (*pszString == 'Z')
+    {
+        pszString++;
+        pTime->fFlags &= ~RTTIME_FLAGS_TYPE_MASK;
+        pTime->fFlags |= ~RTTIME_FLAGS_TYPE_UTC;
+        pTime->offUTC = 0;
+    }
+    else if (   *pszString == '+'
+             || *pszString == '-')
+    {
+        rc = RTStrToInt32Ex(pszString, (char **)&pszString, 10, &pTime->offUTC);
+        if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS && rc != VWRN_TRAILING_SPACES)
+            return NULL;
+    }
+    /* else: No time zone given, local with offUTC = 0. */
+
+    /*
+     * The rest of the string should be blanks.
+     */
+    char ch;
+    while ((ch = *pszString++) != '\0')
+        if (!RT_C_IS_BLANK(ch))
+            return NULL;
+
+    return pTime;
+}
+RT_EXPORT_SYMBOL(RTTimeFromString);
+
+
+/**
+ * Attempts to convert an ISO date string to a time structure.
+ *
+ * We're a little forgiving with zero padding, unspecified parts, and leading
+ * and trailing spaces.
+ *
+ * @retval  pTime on success,
+ * @retval  NULL on failure.
+ * @param   pTime       The time spec.
+ * @param   pszString   The ISO date string to convert.
+ */
+RTDECL(PRTTIMESPEC) RTTimeSpecFromString(PRTTIMESPEC pTime, const char *pszString)
+{
+    RTTIME Time;
+    if (RTTimeFromString(&Time, pszString))
+        return RTTimeImplode(pTime, &Time);
+    return NULL;
+}
+RT_EXPORT_SYMBOL(RTTimeSpecFromString);
+
diff --git a/ubuntu/vbox/vboxguest/generic/RTAssertShouldPanic-generic.c b/ubuntu/vbox/vboxguest/generic/RTAssertShouldPanic-generic.c
new file mode 100644 (file)
index 0000000..3e0550a
--- /dev/null
@@ -0,0 +1,44 @@
+/* $Id: RTAssertShouldPanic-generic.cpp $ */
+/** @file
+ * IPRT - Assertions, generic RTAssertShouldPanic.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/assert.h>
+#include "internal/iprt.h"
+
+
+RTDECL(bool) RTAssertShouldPanic(void)
+{
+#if 0 /* Enable this to not panic on assertions. (Make sure this code is used!) */
+    return false;
+#else
+    return RTAssertMayPanic();
+#endif
+}
+RT_EXPORT_SYMBOL(RTAssertShouldPanic);
+
diff --git a/ubuntu/vbox/vboxguest/generic/RTLogWriteStdErr-stub-generic.c b/ubuntu/vbox/vboxguest/generic/RTLogWriteStdErr-stub-generic.c
new file mode 100644 (file)
index 0000000..ad91639
--- /dev/null
@@ -0,0 +1,42 @@
+/* $Id: RTLogWriteStdErr-stub-generic.cpp $ */
+/** @file
+ * IPRT - Log To StdErr, Generic Dummy.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/log.h>
+#include "internal/iprt.h"
+
+
+RTDECL(void) RTLogWriteStdErr(const char *pch, size_t cb)
+{
+    NOREF(pch);
+    NOREF(cb);
+    return;
+}
+RT_EXPORT_SYMBOL(RTLogWriteStdErr);
+
diff --git a/ubuntu/vbox/vboxguest/generic/RTLogWriteStdOut-stub-generic.c b/ubuntu/vbox/vboxguest/generic/RTLogWriteStdOut-stub-generic.c
new file mode 100644 (file)
index 0000000..642be3d
--- /dev/null
@@ -0,0 +1,42 @@
+/* $Id: RTLogWriteStdOut-stub-generic.cpp $ */
+/** @file
+ * IPRT - Log To StdOut, Generic Dummy.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/log.h>
+#include "internal/iprt.h"
+
+
+RTDECL(void) RTLogWriteStdOut(const char *pch, size_t cb)
+{
+    NOREF(pch);
+    NOREF(cb);
+    return;
+}
+RT_EXPORT_SYMBOL(RTLogWriteStdOut);
+
diff --git a/ubuntu/vbox/vboxguest/generic/RTMpGetCoreCount-generic.c b/ubuntu/vbox/vboxguest/generic/RTMpGetCoreCount-generic.c
new file mode 100644 (file)
index 0000000..ab6ac55
--- /dev/null
@@ -0,0 +1,40 @@
+/* $Id: RTMpGetCoreCount-generic.cpp $ */
+/** @file
+ * IPRT - Multiprocessor, Generic RTMpGetCoreCount.
+ */
+
+/*
+ * Copyright (C) 2013-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/mp.h>
+#include "internal/iprt.h"
+
+
+RTDECL(RTCPUID) RTMpGetCoreCount(void)
+{
+    return RTMpGetCount();
+}
+RT_EXPORT_SYMBOL(RTMpGetCoreCount);
+
diff --git a/ubuntu/vbox/vboxguest/generic/RTSemEventMultiWait-2-ex-generic.c b/ubuntu/vbox/vboxguest/generic/RTSemEventMultiWait-2-ex-generic.c
new file mode 100644 (file)
index 0000000..b853d0b
--- /dev/null
@@ -0,0 +1,53 @@
+/* $Id: RTSemEventMultiWait-2-ex-generic.cpp $ */
+/** @file
+ * IPRT - RTSemEventMultiWait, implementation based on RTSemEventMultiWaitEx.
+ */
+
+/*
+ * Copyright (C) 2010-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_SEM
+#define RTSEMEVENTMULTI_WITHOUT_REMAPPING
+#include <iprt/semaphore.h>
+#include "internal/iprt.h"
+
+#include <iprt/err.h>
+#include <iprt/assert.h>
+
+
+RTDECL(int)  RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
+{
+    int rc;
+    if (cMillies == RT_INDEFINITE_WAIT)
+        rc = RTSemEventMultiWaitEx(hEventMultiSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0);
+    else
+        rc = RTSemEventMultiWaitEx(hEventMultiSem,
+                                   RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS,
+                                   cMillies);
+    Assert(rc != VERR_INTERRUPTED);
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTSemEventMultiWait);
+
diff --git a/ubuntu/vbox/vboxguest/generic/RTSemEventMultiWaitNoResume-2-ex-generic.c b/ubuntu/vbox/vboxguest/generic/RTSemEventMultiWaitNoResume-2-ex-generic.c
new file mode 100644 (file)
index 0000000..1ae3400
--- /dev/null
@@ -0,0 +1,53 @@
+/* $Id: RTSemEventMultiWaitNoResume-2-ex-generic.cpp $ */
+/** @file
+ * IPRT - RTSemEventMultiWaitNoResume, generic implementation based
+ *        on RTSemEventMultiWaitEx.
+ */
+
+/*
+ * Copyright (C) 2010-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_SEM
+#define RTSEMEVENTMULTI_WITHOUT_REMAPPING
+#include <iprt/semaphore.h>
+#include "internal/iprt.h"
+
+#include <iprt/err.h>
+#include <iprt/assert.h>
+
+
+RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
+{
+    int rc;
+    if (cMillies == RT_INDEFINITE_WAIT)
+        rc = RTSemEventMultiWaitEx(hEventMultiSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0);
+    else
+        rc = RTSemEventMultiWaitEx(hEventMultiSem,
+                                   RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS,
+                                   cMillies);
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTSemEventMultiWaitNoResume);
+
diff --git a/ubuntu/vbox/vboxguest/generic/RTSemEventWait-2-ex-generic.c b/ubuntu/vbox/vboxguest/generic/RTSemEventWait-2-ex-generic.c
new file mode 100644 (file)
index 0000000..a6ffe93
--- /dev/null
@@ -0,0 +1,53 @@
+/* $Id: RTSemEventWait-2-ex-generic.cpp $ */
+/** @file
+ * IPRT - RTSemEventWait, implementation based on RTSemEventWaitEx.
+ */
+
+/*
+ * Copyright (C) 2010-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_SEM
+#define RTSEMEVENT_WITHOUT_REMAPPING
+#include <iprt/semaphore.h>
+#include "internal/iprt.h"
+
+#include <iprt/err.h>
+#include <iprt/assert.h>
+
+
+RTDECL(int)  RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
+{
+    int rc;
+    if (cMillies == RT_INDEFINITE_WAIT)
+        rc = RTSemEventWaitEx(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0);
+    else
+        rc = RTSemEventWaitEx(hEventSem,
+                              RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS,
+                              cMillies);
+    Assert(rc != VERR_INTERRUPTED);
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTSemEventWait);
+
diff --git a/ubuntu/vbox/vboxguest/generic/RTSemEventWaitNoResume-2-ex-generic.c b/ubuntu/vbox/vboxguest/generic/RTSemEventWaitNoResume-2-ex-generic.c
new file mode 100644 (file)
index 0000000..b62afc9
--- /dev/null
@@ -0,0 +1,53 @@
+/* $Id: RTSemEventWaitNoResume-2-ex-generic.cpp $ */
+/** @file
+ * IPRT - RTSemEventWaitNoResume, generic implementation based
+ *        on RTSemEventWaitEx.
+ */
+
+/*
+ * Copyright (C) 2010-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_SEM
+#define RTSEMEVENT_WITHOUT_REMAPPING
+#include <iprt/semaphore.h>
+#include "internal/iprt.h"
+
+#include <iprt/err.h>
+#include <iprt/assert.h>
+
+
+RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
+{
+    int rc;
+    if (cMillies == RT_INDEFINITE_WAIT)
+        rc = RTSemEventWaitEx(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0);
+    else
+        rc = RTSemEventWaitEx(hEventSem,
+                              RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS,
+                              cMillies);
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTSemEventWaitNoResume);
+
diff --git a/ubuntu/vbox/vboxguest/generic/errvars-generic.c b/ubuntu/vbox/vboxguest/generic/errvars-generic.c
new file mode 100644 (file)
index 0000000..d013bf7
--- /dev/null
@@ -0,0 +1,68 @@
+/* $Id: errvars-generic.cpp $ */
+/** @file
+ * IPRT - Save and Restore Error Variables, generic stub implementation.
+ */
+
+/*
+ * Copyright (C) 2011-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/err.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include "internal/magics.h"
+
+
+
+RTDECL(PRTERRVARS) RTErrVarsSave(PRTERRVARS pVars)
+{
+    pVars->ai32Vars[0] = RTERRVARS_MAGIC;
+    return pVars;
+}
+
+
+RTDECL(void) RTErrVarsRestore(PCRTERRVARS pVars)
+{
+    Assert(pVars->ai32Vars[0] == RTERRVARS_MAGIC);
+    RT_NOREF_PV(pVars);
+}
+
+
+RTDECL(bool) RTErrVarsAreEqual(PCRTERRVARS pVars1, PCRTERRVARS pVars2)
+{
+    Assert(pVars1->ai32Vars[0] == RTERRVARS_MAGIC);
+    Assert(pVars2->ai32Vars[0] == RTERRVARS_MAGIC);
+
+    return pVars1->ai32Vars[0] == pVars2->ai32Vars[0];
+}
+
+
+RTDECL(bool) RTErrVarsHaveChanged(PCRTERRVARS pVars)
+{
+    Assert(pVars->ai32Vars[0] == RTERRVARS_MAGIC);
+    RT_NOREF_PV(pVars);
+    return false;
+}
+
diff --git a/ubuntu/vbox/vboxguest/generic/mppresent-generic.c b/ubuntu/vbox/vboxguest/generic/mppresent-generic.c
new file mode 100644 (file)
index 0000000..1112696
--- /dev/null
@@ -0,0 +1,61 @@
+/* $Id: mppresent-generic.cpp $ */
+/** @file
+ * IPRT - Multiprocessor, Stubs for the RTMp*Present* API.
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/mp.h>
+#include "internal/iprt.h"
+
+
+RTDECL(PRTCPUSET) RTMpGetPresentSet(PRTCPUSET pSet)
+{
+    return RTMpGetSet(pSet);
+}
+RT_EXPORT_SYMBOL(RTMpGetPresentSet);
+
+
+RTDECL(RTCPUID) RTMpGetPresentCount(void)
+{
+    return RTMpGetCount();
+}
+RT_EXPORT_SYMBOL(RTMpGetPresentCount);
+
+
+RTDECL(RTCPUID) RTMpGetPresentCoreCount(void)
+{
+    return RTMpGetCoreCount();
+}
+RT_EXPORT_SYMBOL(RTMpGetPresentCoreCount);
+
+
+RTDECL(bool) RTMpIsCpuPresent(RTCPUID idCpu)
+{
+    return RTMpIsCpuPossible(idCpu);
+}
+RT_EXPORT_SYMBOL(RTMpIsCpuPresent);
+
diff --git a/ubuntu/vbox/vboxguest/generic/rtStrFormatKernelAddress-generic.c b/ubuntu/vbox/vboxguest/generic/rtStrFormatKernelAddress-generic.c
new file mode 100644 (file)
index 0000000..481d325
--- /dev/null
@@ -0,0 +1,74 @@
+/* $Id: rtStrFormatKernelAddress-generic.cpp $ */
+/** @file
+ * IPRT - IPRT String Formatter, ring-0 addresses.
+ */
+
+/*
+ * Copyright (C) 2006-2017 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_STRING
+#include <iprt/string.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/string.h>
+
+#include "internal/string.h"
+
+
+
+DECLHIDDEN(size_t) rtStrFormatKernelAddress(char *pszBuf, size_t cbBuf, RTR0INTPTR uPtr, signed int cchWidth,
+                                            signed int cchPrecision, unsigned int fFlags)
+{
+#ifndef DEBUG
+    RT_NOREF(uPtr, cchWidth, cchPrecision);
+# if R0_ARCH_BITS == 64
+    static const char s_szObfuscated[] = "0xXXXXXXXXXXXXXXXX";
+# else
+    static const char s_szObfuscated[] = "0xXXXXXXXX";
+# endif
+    size_t      cbSrc  = sizeof(s_szObfuscated);
+    const char *pszSrc = s_szObfuscated;
+    if (!(fFlags & RTSTR_F_SPECIAL))
+    {
+        pszSrc += 2;
+        cbSrc  -= 2;
+    }
+    if (cbSrc <= cbBuf)
+    {
+        memcpy(pszBuf, pszSrc, cbSrc);
+        return cbSrc - 1;
+    }
+    AssertFailed();
+    memcpy(pszBuf, pszSrc, cbBuf);
+    pszBuf[cbBuf - 1] = '\0';
+    return cbBuf - 1;
+
+#else  /* DEBUG */
+    Assert(cbBuf >= 64);
+    return RTStrFormatNumber(pszBuf, uPtr, 16, cchWidth, cchPrecision, fFlags);
+#endif /* DEBUG */
+}
+
diff --git a/ubuntu/vbox/vboxguest/include b/ubuntu/vbox/vboxguest/include
new file mode 120000 (symlink)
index 0000000..f5030fe
--- /dev/null
@@ -0,0 +1 @@
+../include
\ No newline at end of file
diff --git a/ubuntu/vbox/vboxguest/product-generated.h b/ubuntu/vbox/vboxguest/product-generated.h
new file mode 100644 (file)
index 0000000..3fbe34a
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef ___product_generated_h___
+#define ___product_generated_h___
+
+#define VBOX_VENDOR "Oracle Corporation"
+#define VBOX_VENDOR_SHORT "Oracle"
+#define VBOX_PRODUCT "Oracle VM VirtualBox"
+#define VBOX_BUILD_PUBLISHER "_Ubuntu"
+#define VBOX_C_YEAR "2017"
+
+#endif
diff --git a/ubuntu/vbox/vboxguest/r0drv b/ubuntu/vbox/vboxguest/r0drv
new file mode 120000 (symlink)
index 0000000..f93dcc2
--- /dev/null
@@ -0,0 +1 @@
+../r0drv
\ No newline at end of file
diff --git a/ubuntu/vbox/vboxguest/revision-generated.h b/ubuntu/vbox/vboxguest/revision-generated.h
new file mode 100644 (file)
index 0000000..74247d9
--- /dev/null
@@ -0,0 +1 @@
+#define VBOX_SVN_REV 117968
diff --git a/ubuntu/vbox/vboxguest/version-generated.h b/ubuntu/vbox/vboxguest/version-generated.h
new file mode 100644 (file)
index 0000000..24cdc17
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef ___version_generated_h___
+#define ___version_generated_h___
+
+#define VBOX_VERSION_MAJOR 5
+#define VBOX_VERSION_MINOR 1
+#define VBOX_VERSION_BUILD 28
+#define VBOX_VERSION_STRING_RAW "5.1.28"
+#define VBOX_VERSION_STRING "5.1.28_Ubuntu"
+#define VBOX_API_VERSION_STRING "5_1"
+
+#define VBOX_PRIVATE_BUILD_DESC "Private build by buildd"
+
+#endif
diff --git a/ubuntu/vbox/vboxsf/GenericRequest.c b/ubuntu/vbox/vboxsf/GenericRequest.c
new file mode 100644 (file)
index 0000000..22397fd
--- /dev/null
@@ -0,0 +1,170 @@
+/* $Id: GenericRequest.cpp $ */
+/** @file
+ * VBoxGuestLibR0 - Generic VMMDev request management.
+ */
+
+/*
+ * 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.
+ */
+
+#include "VBGLInternal.h"
+#include <iprt/asm.h>
+#include <iprt/asm-amd64-x86.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+
+
+DECLVBGL(int) VbglGRVerify(const VMMDevRequestHeader *pReq, size_t cbReq)
+{
+    size_t cbReqExpected;
+
+    if (RT_UNLIKELY(!pReq || cbReq < sizeof(VMMDevRequestHeader)))
+    {
+        dprintf(("VbglGRVerify: Invalid parameter: pReq = %p, cbReq = %zu\n", pReq, cbReq));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    if (RT_UNLIKELY(pReq->size > cbReq))
+    {
+        dprintf(("VbglGRVerify: request size %u > buffer size %zu\n", pReq->size, cbReq));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    /* The request size must correspond to the request type. */
+    cbReqExpected = vmmdevGetRequestSize(pReq->requestType);
+    if (RT_UNLIKELY(cbReq < cbReqExpected))
+    {
+        dprintf(("VbglGRVerify: buffer size %zu < expected size %zu\n", cbReq, cbReqExpected));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    if (cbReqExpected == cbReq)
+    {
+        /*
+         * This is most likely a fixed size request, and in this case the
+         * request size must be also equal to the expected size.
+         */
+        if (RT_UNLIKELY(pReq->size != cbReqExpected))
+        {
+            dprintf(("VbglGRVerify: request size %u != expected size %zu\n", pReq->size, cbReqExpected));
+            return VERR_INVALID_PARAMETER;
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    /*
+     * This can be a variable size request. Check the request type and limit the size
+     * to VMMDEV_MAX_VMMDEVREQ_SIZE, which is max size supported by the host.
+     *
+     * Note: Keep this list sorted for easier human lookup!
+     */
+    if (   pReq->requestType == VMMDevReq_ChangeMemBalloon
+#ifdef VBOX_WITH_64_BITS_GUESTS
+        || pReq->requestType == VMMDevReq_HGCMCall32
+        || pReq->requestType == VMMDevReq_HGCMCall64
+#else
+        || pReq->requestType == VMMDevReq_HGCMCall
+#endif
+        || pReq->requestType == VMMDevReq_RegisterSharedModule
+        || pReq->requestType == VMMDevReq_ReportGuestUserState
+        || pReq->requestType == VMMDevReq_LogString
+        || pReq->requestType == VMMDevReq_SetPointerShape
+        || pReq->requestType == VMMDevReq_VideoSetVisibleRegion)
+    {
+        if (RT_UNLIKELY(cbReq > VMMDEV_MAX_VMMDEVREQ_SIZE))
+        {
+            dprintf(("VbglGRVerify: VMMDevReq_LogString: buffer size %zu too big\n", cbReq));
+            return VERR_BUFFER_OVERFLOW; /** @todo is this error code ok? */
+        }
+    }
+    else
+    {
+        dprintf(("VbglGRVerify: request size %u > buffer size %zu\n", pReq->size, cbReq));
+        return VERR_IO_BAD_LENGTH; /** @todo is this error code ok? */
+    }
+
+    return VINF_SUCCESS;
+}
+
+DECLVBGL(int) VbglGRAlloc(VMMDevRequestHeader **ppReq, size_t cbReq, VMMDevRequestType enmReqType)
+{
+    int rc = vbglR0Enter();
+    if (RT_SUCCESS(rc))
+    {
+        if (   ppReq
+            && cbReq >= sizeof(VMMDevRequestHeader)
+            && cbReq == (uint32_t)cbReq)
+        {
+            VMMDevRequestHeader *pReq = (VMMDevRequestHeader *)VbglPhysHeapAlloc((uint32_t)cbReq);
+            AssertMsgReturn(pReq, ("VbglGRAlloc: no memory (cbReq=%u)\n", cbReq), VERR_NO_MEMORY);
+            memset(pReq, 0xAA, cbReq);
+
+            pReq->size        = (uint32_t)cbReq;
+            pReq->version     = VMMDEV_REQUEST_HEADER_VERSION;
+            pReq->requestType = enmReqType;
+            pReq->rc          = VERR_GENERAL_FAILURE;
+            pReq->reserved1   = 0;
+            pReq->reserved2   = 0;
+
+            *ppReq = pReq;
+            rc = VINF_SUCCESS;
+        }
+        else
+        {
+            dprintf(("VbglGRAlloc: Invalid parameter: ppReq=%p cbReq=%u\n", ppReq, cbReq));
+            rc = VERR_INVALID_PARAMETER;
+        }
+    }
+    return rc;
+}
+
+DECLVBGL(int) VbglGRPerform(VMMDevRequestHeader *pReq)
+{
+    int rc = vbglR0Enter();
+    if (RT_SUCCESS(rc))
+    {
+        if (pReq)
+        {
+            RTCCPHYS PhysAddr = VbglPhysHeapGetPhysAddr(pReq);
+            if (   PhysAddr != 0
+                && PhysAddr < _4G) /* Port IO is 32 bit. */
+            {
+                ASMOutU32(g_vbgldata.portVMMDev + VMMDEV_PORT_OFF_REQUEST, (uint32_t)PhysAddr);
+                /* Make the compiler aware that the host has changed memory. */
+                ASMCompilerBarrier();
+                rc = pReq->rc;
+            }
+            else
+                rc = VERR_VBGL_INVALID_ADDR;
+        }
+        else
+            rc = VERR_INVALID_PARAMETER;
+    }
+    return rc;
+}
+
+DECLVBGL(void) VbglGRFree(VMMDevRequestHeader *pReq)
+{
+    int rc = vbglR0Enter();
+    if (RT_SUCCESS(rc))
+        VbglPhysHeapFree(pReq);
+}
+
diff --git a/ubuntu/vbox/vboxsf/HGCM.c b/ubuntu/vbox/vboxsf/HGCM.c
new file mode 100644 (file)
index 0000000..ba6fdd1
--- /dev/null
@@ -0,0 +1,195 @@
+/* $Id: HGCM.cpp $ */
+/** @file
+ * VBoxGuestLib - Host-Guest Communication Manager.
+ *
+ * These public functions can be only used by other drivers. They all
+ * do an IOCTL to VBoxGuest via IDC.
+ */
+
+/*
+ * 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.
+ */
+
+/* Entire file is ifdef'ed with !VBGL_VBOXGUEST */
+#ifndef VBGL_VBOXGUEST
+
+#include "VBGLInternal.h"
+
+#include <iprt/assert.h>
+#include <iprt/semaphore.h>
+#include <iprt/string.h>
+
+#define VBGL_HGCM_ASSERT_MSG AssertReleaseMsg
+
+/**
+ * Initializes the HGCM VBGL bits.
+ *
+ * @return VBox status code.
+ */
+int vbglR0HGCMInit(void)
+{
+    return RTSemFastMutexCreate(&g_vbgldata.mutexHGCMHandle);
+}
+
+/**
+ * Initializes the HGCM VBGL bits.
+ *
+ * @return VBox status code.
+ */
+int vbglR0HGCMTerminate(void)
+{
+    RTSemFastMutexDestroy(g_vbgldata.mutexHGCMHandle);
+    g_vbgldata.mutexHGCMHandle = NIL_RTSEMFASTMUTEX;
+
+    return VINF_SUCCESS;
+}
+
+DECLINLINE(int) vbglHandleHeapEnter(void)
+{
+    int rc = RTSemFastMutexRequest(g_vbgldata.mutexHGCMHandle);
+
+    VBGL_HGCM_ASSERT_MSG(RT_SUCCESS(rc), ("Failed to request handle heap mutex, rc = %Rrc\n", rc));
+
+    return rc;
+}
+
+DECLINLINE(void) vbglHandleHeapLeave(void)
+{
+    RTSemFastMutexRelease(g_vbgldata.mutexHGCMHandle);
+}
+
+struct VBGLHGCMHANDLEDATA *vbglHGCMHandleAlloc(void)
+{
+    struct VBGLHGCMHANDLEDATA *p = NULL;
+    int rc = vbglHandleHeapEnter();
+    if (RT_SUCCESS(rc))
+    {
+        uint32_t i;
+
+        /* Simple linear search in array. This will be called not so often, only connect/disconnect. */
+        /** @todo bitmap for faster search and other obvious optimizations. */
+        for (i = 0; i < RT_ELEMENTS(g_vbgldata.aHGCMHandleData); i++)
+        {
+            if (!g_vbgldata.aHGCMHandleData[i].fAllocated)
+            {
+                p = &g_vbgldata.aHGCMHandleData[i];
+                p->fAllocated = 1;
+                break;
+            }
+        }
+
+        vbglHandleHeapLeave();
+
+        VBGL_HGCM_ASSERT_MSG(p != NULL, ("Not enough HGCM handles.\n"));
+    }
+    return p;
+}
+
+void vbglHGCMHandleFree(struct VBGLHGCMHANDLEDATA *pHandle)
+{
+    if (pHandle)
+    {
+        int rc = vbglHandleHeapEnter();
+        if (RT_SUCCESS(rc))
+        {
+            VBGL_HGCM_ASSERT_MSG(pHandle->fAllocated, ("Freeing not allocated handle.\n"));
+
+            RT_ZERO(*pHandle);
+            vbglHandleHeapLeave();
+        }
+    }
+}
+
+DECLVBGL(int) VbglHGCMConnect(VBGLHGCMHANDLE *pHandle, VBoxGuestHGCMConnectInfo *pData)
+{
+    int rc;
+    if (pHandle && pData)
+    {
+        struct VBGLHGCMHANDLEDATA *pHandleData = vbglHGCMHandleAlloc();
+        if (pHandleData)
+        {
+            rc = vbglDriverOpen(&pHandleData->driver);
+            if (RT_SUCCESS(rc))
+            {
+                rc = vbglDriverIOCtl(&pHandleData->driver, VBOXGUEST_IOCTL_HGCM_CONNECT, pData, sizeof(*pData));
+                if (RT_SUCCESS(rc))
+                    rc = pData->result;
+                if (RT_SUCCESS(rc))
+                {
+                    *pHandle = pHandleData;
+                    return rc;
+                }
+
+                vbglDriverClose(&pHandleData->driver);
+            }
+
+            vbglHGCMHandleFree(pHandleData);
+        }
+        else
+            rc = VERR_NO_MEMORY;
+    }
+    else
+        rc = VERR_INVALID_PARAMETER;
+    return rc;
+}
+
+DECLVBGL(int) VbglHGCMDisconnect(VBGLHGCMHANDLE handle, VBoxGuestHGCMDisconnectInfo *pData)
+{
+    int rc = vbglDriverIOCtl(&handle->driver, VBOXGUEST_IOCTL_HGCM_DISCONNECT, pData, sizeof(*pData));
+
+    vbglDriverClose(&handle->driver);
+
+    vbglHGCMHandleFree(handle);
+
+    return rc;
+}
+
+DECLVBGL(int) VbglHGCMCall(VBGLHGCMHANDLE handle, VBoxGuestHGCMCallInfo *pData, uint32_t cbData)
+{
+    VBGL_HGCM_ASSERT_MSG(cbData >= sizeof(VBoxGuestHGCMCallInfo) + pData->cParms * sizeof(HGCMFunctionParameter),
+                         ("cbData = %d, cParms = %d (calculated size %d)\n", cbData, pData->cParms,
+                          sizeof(VBoxGuestHGCMCallInfo) + pData->cParms * sizeof(VBoxGuestHGCMCallInfo)));
+
+    return vbglDriverIOCtl(&handle->driver, VBOXGUEST_IOCTL_HGCM_CALL(cbData), pData, cbData);
+}
+
+DECLVBGL(int) VbglHGCMCallUserData (VBGLHGCMHANDLE handle, VBoxGuestHGCMCallInfo *pData, uint32_t cbData)
+{
+    VBGL_HGCM_ASSERT_MSG(cbData >= sizeof(VBoxGuestHGCMCallInfo) + pData->cParms * sizeof(HGCMFunctionParameter),
+                         ("cbData = %d, cParms = %d (calculated size %d)\n", cbData, pData->cParms,
+                          sizeof(VBoxGuestHGCMCallInfo) + pData->cParms * sizeof(VBoxGuestHGCMCallInfo)));
+
+    return vbglDriverIOCtl(&handle->driver, VBOXGUEST_IOCTL_HGCM_CALL_USERDATA(cbData), pData, cbData);
+}
+
+
+DECLVBGL(int) VbglHGCMCallTimed(VBGLHGCMHANDLE handle, VBoxGuestHGCMCallInfoTimed *pData, uint32_t cbData)
+{
+    uint32_t cbExpected = sizeof(VBoxGuestHGCMCallInfoTimed)
+                        + pData->info.cParms * sizeof(HGCMFunctionParameter);
+    VBGL_HGCM_ASSERT_MSG(cbData >= cbExpected,
+                         ("cbData = %d, cParms = %d (calculated size %d)\n", cbData, pData->info.cParms, cbExpected));
+    NOREF(cbExpected);
+
+    return vbglDriverIOCtl(&handle->driver, VBOXGUEST_IOCTL_HGCM_CALL_TIMED(cbData), pData, cbData);
+}
+
+#endif /* !VBGL_VBOXGUEST */
+
diff --git a/ubuntu/vbox/vboxsf/Init.c b/ubuntu/vbox/vboxsf/Init.c
new file mode 100644 (file)
index 0000000..e8c985e
--- /dev/null
@@ -0,0 +1,310 @@
+/* $Id: Init.cpp $ */
+/** @file
+ * VBoxGuestLibR0 - Library initialization.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define VBGL_DECL_DATA
+#include "VBGLInternal.h"
+
+#include <iprt/string.h>
+#include <iprt/assert.h>
+#include <iprt/semaphore.h>
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** The global VBGL instance data.  */
+VBGLDATA g_vbgldata;
+
+/**
+ * Used by vbglQueryDriverInfo and VbglInit to try get the host feature mask and
+ * version information (g_vbgldata::hostVersion).
+ *
+ * This was first implemented by the host in 3.1 and we quietly ignore failures
+ * for that reason.
+ */
+static void vbglR0QueryHostVersion (void)
+{
+    VMMDevReqHostVersion *pReq;
+
+    int rc = VbglGRAlloc ((VMMDevRequestHeader **) &pReq, sizeof (*pReq), VMMDevReq_GetHostVersion);
+
+    if (RT_SUCCESS (rc))
+    {
+        rc = VbglGRPerform (&pReq->header);
+
+        if (RT_SUCCESS (rc))
+        {
+            g_vbgldata.hostVersion = *pReq;
+            Log (("vbglR0QueryHostVersion: %u.%u.%ur%u %#x\n",
+                  pReq->major, pReq->minor, pReq->build, pReq->revision, pReq->features));
+        }
+
+        VbglGRFree (&pReq->header);
+    }
+}
+
+#ifndef VBGL_VBOXGUEST
+/**
+ * The guest library uses lazy initialization for VMMDev port and memory,
+ * because these values are provided by the VBoxGuest driver and it might
+ * be loaded later than other drivers.
+ *
+ * The VbglEnter checks the current library status, tries to retrieve these
+ * values and fails if they are unavailable.
+ *
+ */
+static void vbglQueryDriverInfo (void)
+{
+    int rc = VINF_SUCCESS;
+
+    rc = RTSemMutexRequest(g_vbgldata.mutexDriverInit, RT_INDEFINITE_WAIT);
+
+    if (RT_FAILURE(rc))
+        return;
+
+    if (g_vbgldata.status == VbglStatusReady)
+    {
+        RTSemMutexRelease(g_vbgldata.mutexDriverInit);
+        return;
+    }
+
+    rc = vbglDriverOpen(&g_vbgldata.driver);
+
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Try query the port info.
+         */
+        VBoxGuestPortInfo port;
+
+        rc = vbglDriverIOCtl (&g_vbgldata.driver,
+                              VBOXGUEST_IOCTL_GETVMMDEVPORT, &port,
+                              sizeof (port));
+
+        if (RT_SUCCESS (rc))
+        {
+            dprintf (("port = 0x%04X, mem = %p\n", port.portAddress, port.pVMMDevMemory));
+
+            g_vbgldata.portVMMDev = (RTIOPORT)port.portAddress;
+            g_vbgldata.pVMMDevMemory = port.pVMMDevMemory;
+
+            g_vbgldata.status = VbglStatusReady;
+
+            vbglR0QueryHostVersion();
+        }
+    }
+    RTSemMutexRelease(g_vbgldata.mutexDriverInit);
+    dprintf (("vbglQueryDriverInfo rc = %d\n", rc));
+}
+#endif /* !VBGL_VBOXGUEST */
+
+/**
+ * Checks if VBGL has been initialized.
+ *
+ * The client library, this will lazily complete the initialization.
+ *
+ * @return VINF_SUCCESS or VERR_VBGL_NOT_INITIALIZED.
+ */
+int vbglR0Enter (void)
+{
+    int rc;
+
+#ifndef VBGL_VBOXGUEST
+    if (g_vbgldata.status == VbglStatusInitializing)
+    {
+        vbglQueryDriverInfo ();
+    }
+#endif
+
+    rc = g_vbgldata.status == VbglStatusReady? VINF_SUCCESS: VERR_VBGL_NOT_INITIALIZED;
+
+    // dprintf(("VbglEnter: rc = %d\n", rc));
+
+    return rc;
+}
+
+int vbglInitCommon (void)
+{
+    int rc = VINF_SUCCESS;
+
+    RT_ZERO(g_vbgldata);
+
+    g_vbgldata.status = VbglStatusInitializing;
+
+    rc = VbglPhysHeapInit ();
+
+    if (RT_SUCCESS(rc))
+    {
+        /* other subsystems, none yet */
+        ;
+    }
+    else
+    {
+        LogRel(("vbglInitCommon: VbglPhysHeapInit failed. rc=%Rrc\n", rc));
+        g_vbgldata.status = VbglStatusNotInitialized;
+    }
+
+    dprintf(("vbglInitCommon: rc = %d\n", rc));
+
+    return rc;
+}
+
+DECLVBGL(void) vbglTerminateCommon (void)
+{
+    VbglPhysHeapTerminate ();
+    g_vbgldata.status = VbglStatusNotInitialized;
+
+    return;
+}
+
+#ifdef VBGL_VBOXGUEST
+
+DECLVBGL(int) VbglInitPrimary(RTIOPORT portVMMDev, VMMDevMemory *pVMMDevMemory)
+{
+    int rc = VINF_SUCCESS;
+
+# ifdef RT_OS_WINDOWS /** @todo r=bird: this doesn't make sense. Is there something special going on on windows? */
+    dprintf(("vbglInit: starts g_vbgldata.status %d\n", g_vbgldata.status));
+
+    if (   g_vbgldata.status == VbglStatusInitializing
+        || g_vbgldata.status == VbglStatusReady)
+    {
+        /* Initialization is already in process. */
+        return rc;
+    }
+# else
+    dprintf(("vbglInit: starts\n"));
+# endif
+
+    rc = vbglInitCommon ();
+
+    if (RT_SUCCESS(rc))
+    {
+        g_vbgldata.portVMMDev = portVMMDev;
+        g_vbgldata.pVMMDevMemory = pVMMDevMemory;
+
+        g_vbgldata.status = VbglStatusReady;
+
+        vbglR0QueryHostVersion();
+    }
+    else
+    {
+        g_vbgldata.status = VbglStatusNotInitialized;
+    }
+
+    return rc;
+}
+
+DECLVBGL(void) VbglTerminate (void)
+{
+    vbglTerminateCommon ();
+
+    return;
+}
+
+
+#else /* !VBGL_VBOXGUEST */
+
+DECLVBGL(int) VbglInitClient(void)
+{
+    int rc = VINF_SUCCESS;
+
+    if (   g_vbgldata.status == VbglStatusInitializing
+        || g_vbgldata.status == VbglStatusReady)
+    {
+        /* Initialization is already in process. */
+        return rc;
+    }
+
+    rc = vbglInitCommon ();
+
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTSemMutexCreate(&g_vbgldata.mutexDriverInit);
+        if (RT_SUCCESS(rc))
+        {
+            /* Try to obtain VMMDev port via IOCTL to VBoxGuest main driver. */
+            vbglQueryDriverInfo ();
+
+# ifdef VBOX_WITH_HGCM
+            rc = vbglR0HGCMInit ();
+# endif /* VBOX_WITH_HGCM */
+
+            if (RT_FAILURE(rc))
+            {
+                RTSemMutexDestroy(g_vbgldata.mutexDriverInit);
+                g_vbgldata.mutexDriverInit = NIL_RTSEMMUTEX;
+            }
+        }
+
+        if (RT_FAILURE(rc))
+        {
+            vbglTerminateCommon ();
+        }
+
+    }
+
+    return rc;
+}
+
+DECLVBGL(void) VbglTerminate (void)
+{
+# ifdef VBOX_WITH_HGCM
+    vbglR0HGCMTerminate ();
+# endif
+
+    /* driver open could fail, which does not prevent VbglInit from succeeding,
+     * close the driver only if it is opened */
+    if (vbglDriverIsOpened(&g_vbgldata.driver))
+        vbglDriverClose(&g_vbgldata.driver);
+    RTSemMutexDestroy(g_vbgldata.mutexDriverInit);
+    g_vbgldata.mutexDriverInit = NIL_RTSEMMUTEX;
+
+    /* note: do vbglTerminateCommon as a last step since it zeroez up the g_vbgldata
+     * conceptually, doing vbglTerminateCommon last is correct
+     * since this is the reverse order to how init is done */
+    vbglTerminateCommon ();
+
+    return;
+}
+
+int vbglGetDriver(VBGLDRIVER **ppDriver)
+{
+    if (g_vbgldata.status != VbglStatusReady)
+    {
+        vbglQueryDriverInfo();
+        if (g_vbgldata.status != VbglStatusReady)
+            return VERR_TRY_AGAIN;
+    }
+    *ppDriver = &g_vbgldata.driver;
+    return VINF_SUCCESS;
+}
+
+#endif /* !VBGL_VBOXGUEST */
diff --git a/ubuntu/vbox/vboxsf/Makefile b/ubuntu/vbox/vboxsf/Makefile
new file mode 100644 (file)
index 0000000..95923b5
--- /dev/null
@@ -0,0 +1,93 @@
+KBUILD_EXTMOD=${srctree}/ubuntu/vbox
+#
+# VirtualBox Guest Additions Module Makefile.
+#
+# (For 2.6.x this file must be 'Makefile'!)
+#
+# Copyright (C) 2006-2011 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.
+#
+
+# Linux kbuild sets this to our source directory if we are called from there
+obj ?= $(CURDIR)
+include $(obj)/Makefile.include.header
+
+MOD_NAME = vboxsf
+MOD_OBJS   = \
+       vfsmod.o \
+       dirops.o \
+       lnkops.o \
+       regops.o \
+       utils.o \
+       GenericRequest.o \
+       SysHlp.o \
+       PhysHeap.o \
+       Init.o \
+       VMMDev.o \
+       HGCM.o \
+       VBoxGuestR0LibSharedFolders.o \
+       VbglR0CanUsePhysPageList.o
+ifeq ($(BUILD_TARGET_ARCH),x86)
+MOD_OBJS  += \
+       divdi3.o \
+       moddi3.o \
+       udivdi3.o \
+       udivmoddi4.o \
+       umoddi3.o \
+       qdivrem.o
+endif
+
+MOD_INCL = \
+    $(addprefix -I$(KBUILD_EXTMOD),/ /include /r0drv/linux) \
+    $(addprefix -I$(KBUILD_EXTMOD)/vboxsf,/ /include /r0drv/linux)
+
+ifneq ($(wildcard $(KBUILD_EXTMOD)/vboxsf),)
+ MANGLING := $(KBUILD_EXTMOD)/vboxsf/include/VBox/VBoxGuestMangling.h
+else
+ MANGLING := $(KBUILD_EXTMOD)/include/VBox/VBoxGuestMangling.h
+endif
+
+MOD_DEFS   = -DRT_OS_LINUX -DIN_RING0 -DIN_RT_R0 \
+           -DIN_SUP_R0 -DVBOX -DVBOX_WITH_HGCM -DIN_MODULE -DIN_GUEST_R0
+# our module does not export any symbol
+MOD_DEFS  += -DRT_NO_EXPORT_SYMBOL
+ifeq ($(BUILD_TARGET_ARCH),amd64)
+ MOD_DEFS += -DRT_ARCH_AMD64 -DVBOX_WITH_64_BITS_GUESTS
+else
+ MOD_DEFS += -DRT_ARCH_X86
+endif
+
+ifeq ($(KERN_VERSION), 24)
+ MOD_CFLAGS =
+else
+ MOD_CFLAGS = -Wno-declaration-after-statement -fshort-wchar -include $(MANGLING) -fno-pie
+
+# special hack for Fedora Core 6 2.6.18 (fc6), rhel5 2.6.18 (el5),
+# ClarkConnect 4.3 (cc4) and ClarkConnect 5 (v5)
+ ifeq ($(KERNELRELEASE),)
+  MOD_EXTRA += $(foreach inc,$(KERN_INCL),\
+              $(if $(wildcard $(inc)/linux/utsrelease.h),\
+                $(if $(shell grep '"2.6.18.*fc6.*"' $(inc)/linux/utsrelease.h; \
+                           grep '"2.6.18.*el5.*"' $(inc)/linux/utsrelease.h; \
+                           grep '"2.6.18.*v5.*"'  $(inc)/linux/utsrelease.h; \
+                           grep '"2.6.18.*cc4.*"' $(inc)/linux/utsrelease.h),\
+               -DKERNEL_FC6,),))
+ else
+  MOD_EXTRA += $(if $(shell echo "$(KERNELRELEASE)"|grep '2.6.18.*fc6.*';\
+                       echo "$(KERNELRELEASE)"|grep '2.6.18.*el5.*';\
+                       echo "$(KERNELRELEASE)"|grep '2.6.18.*v5.*';\
+                       echo "$(KERNELRELEASE)"|grep '2.6.18.*cc4.*'),\
+               -DKERNEL_FC6,)
+ endif
+endif
+
+MOD_CLEAN = . linux r0drv r0drv/linux
+
+include $(obj)/Makefile.include.footer
diff --git a/ubuntu/vbox/vboxsf/Makefile.include.footer b/ubuntu/vbox/vboxsf/Makefile.include.footer
new file mode 100644 (file)
index 0000000..7830bfd
--- /dev/null
@@ -0,0 +1,101 @@
+#
+# VirtualBox Guest Additions kernel module Makefile, common parts.
+#
+# See Makefile.include.header for details of how to use this.
+#
+# Copyright (C) 2006-2015 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.
+#
+
+# override is required by the Debian guys
+override MODULE = $(MOD_NAME)
+OBJS   = $(MOD_OBJS)
+
+ifneq ($(MAKECMDGOALS),clean)
+
+KBUILD_VERBOSE ?= 1
+
+#
+# Compiler options
+#
+ifndef INCL
+ INCL    := $(addprefix -I,$(KERN_INCL) $(EXTRA_INCL))
+ ifndef KBUILD_EXTMOD
+  KBUILD_EXTMOD := $(shell pwd)
+ endif
+ INCL    += $(MOD_INCL)
+ export INCL
+endif
+KFLAGS   := -D__KERNEL__ -DMODULE $(MOD_DEFS)
+ifeq ($(BUILD_TYPE),debug)
+ KFLAGS  += -DDEBUG -DDEBUG_$(subst $(subst _, ,_),_,$(USERNAME)) -DDEBUG_USERNAME=$(subst $(subst _, ,_),_,$(USERNAME))
+endif
+
+ifeq ($(KERN_VERSION), 24)
+#
+# 2.4
+#
+
+ifeq ($(BUILD_TARGET_ARCH),amd64)
+ KFLAGS  += -mcmodel=kernel
+endif
+
+CFLAGS := -O2 -DVBOX_LINUX_2_4 $(MOD_CFLAGS) $(INCL) $(KFLAGS) $(MOD_EXTRA) $(KDEBUG)
+MODULE_EXT := o
+
+# 2.4 Module linking
+$(MODULE).o: $(OBJS)
+       $(LD) -o $@ -r $(OBJS)
+
+.PHONY: $(MODULE)
+all: $(MODULE)
+$(MODULE): $(MODULE).o
+
+else
+#
+# 2.6 and later
+#
+
+MODULE_EXT := ko
+
+$(MODULE)-y  := $(OBJS)
+
+# build defs
+EXTRA_CFLAGS += $(MOD_CFLAGS) $(INCL) $(KFLAGS) $(MOD_EXTRA) $(KDEBUG)
+
+.PHONY: $(MODULE)
+all: $(MODULE)
+
+obj-m += $(MODULE).o
+
+JOBS := $(shell (getconf _NPROCESSORS_ONLN || grep -Ec '^processor|^CPU[0-9]' /proc/cpuinfo) 2>/dev/null)
+ifeq ($(JOBS),0)
+  JOBS := 1
+endif
+
+# OL/UEK: disable module signing for external modules -- we don't have any private key
+$(MODULE):
+       $(MAKE) KBUILD_VERBOSE=$(KBUILD_VERBOSE) CONFIG_MODULE_SIG= -C $(KERN_DIR) SUBDIRS=$(CURDIR) SRCROOT=$(CURDIR) -j$(JOBS) modules
+
+modules_install:
+       $(MAKE) KBUILD_VERBOSE=$(KBUILD_VERBOSE) CONFIG_MODULE_SIG= -C $(KERN_DIR) SUBDIRS=$(CURDIR) SRCROOT=$(CURDIR) modules_install
+
+endif
+
+install: $(MODULE)
+       @mkdir -p $(MODULE_DIR); \
+       install -m 0644 -o root -g root $(MODULE).$(MODULE_EXT) $(MODULE_DIR); \
+       PATH="$(PATH):/bin:/sbin" depmod -a;
+
+endif # eq($(MAKECMDGOALS),clean)
+
+clean:
+       for f in $(MOD_CLEAN); do rm -f $$f/*.o $$f/.*.cmd $$f/.*.flags; done
+       rm -rf .$(MOD_NAME)* .tmp_ver* $(MOD_NAME).* Modules.symvers modules.order
diff --git a/ubuntu/vbox/vboxsf/Makefile.include.header b/ubuntu/vbox/vboxsf/Makefile.include.header
new file mode 100644 (file)
index 0000000..1c4fb9a
--- /dev/null
@@ -0,0 +1,188 @@
+#
+# VirtualBox Guest Additions kernel module Makefile, common parts.
+#
+# (For 2.6.x, the main file must be called 'Makefile'!)
+#
+# Copyright (C) 2006-2015 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.
+#
+
+# Testing:
+# * Building with KERN_VER set to an installed but non-current kernel works and
+#   installs to the right location.
+# * Building with KERN_DIR and/or MODULE_DIR set uses the value specified and
+#   the default value for the unspecified one if any.
+
+#
+# These file should be included by the Makefiles for any kernel modules we
+# build as part of the Guest Additions.  The intended way of doing this is as
+# follows:
+#
+# # Linux kbuild sets this to our source directory if we are called from
+# # there
+# obj ?= $(CURDIR)
+# include $(obj)/Makefile.include.header
+# MOD_NAME = <name of the module to be built, without extension>
+# MOD_OBJS = <list of object files which should be included>
+# MOD_DEFS = <any additional defines which this module needs>
+# MOD_INCL = <any additional include paths which this module needs>
+# MOD_CFLAGS = <any additional CFLAGS which this module needs>
+# MOD_CLEAN = <list of directories that the clean target should look at>
+# include $(obj)/Makefile.include.footer
+#
+# The kmk kBuild define KBUILD_TARGET_ARCH is available.
+#
+
+
+#
+# First, figure out which architecture we're targeting and the build type.
+# (We have to support basic cross building (ARCH=i386|x86_64).)
+# While at it, warn about BUILD_* vars found to help with user problems.
+#
+ifeq ($(filter-out x86_64 amd64 AMD64,$(shell uname -m)),)
+ BUILD_TARGET_ARCH_DEF := amd64
+else
+ BUILD_TARGET_ARCH_DEF := x86
+endif
+ifneq ($(filter-out amd64 x86,$(BUILD_TARGET_ARCH)),)
+ $(warning Ignoring unknown BUILD_TARGET_ARCH value '$(BUILD_TARGET_ARCH)'.)
+ BUILD_TARGET_ARCH :=
+endif
+ifeq ($(BUILD_TARGET_ARCH),)
+ ifeq ($(ARCH),x86_64)
+  BUILD_TARGET_ARCH := amd64
+ else
+  ifeq ($(ARCH),i386)
+   ifeq ($(CONFIG_X86_32),y)
+     BUILD_TARGET_ARCH := x86
+   else
+     BUILD_TARGET_ARCH := amd64
+   endif
+  else
+    ifeq ($(ARCH),x86)
+      ifeq ($(CONFIG_X86_32),y)
+        BUILD_TARGET_ARCH := x86
+      else
+        BUILD_TARGET_ARCH := amd64
+      endif
+    else
+      BUILD_TARGET_ARCH := $(BUILD_TARGET_ARCH_DEF)
+    endif
+  endif
+ endif
+else
+ ifneq ($(BUILD_TARGET_ARCH),$(BUILD_TARGET_ARCH_DEF))
+  $(warning Using BUILD_TARGET_ARCH='$(BUILD_TARGET_ARCH)' from the $(origin BUILD_TARGET_ARCH).)
+ endif
+endif
+
+ifneq ($(filter-out release profile debug strict,$(BUILD_TYPE)),)
+ $(warning Ignoring unknown BUILD_TYPE value '$(BUILD_TYPE)'.)
+ BUILD_TYPE :=
+endif
+ifeq ($(BUILD_TYPE),)
+ BUILD_TYPE := release
+else
+ ifneq ($(BUILD_TYPE),release)
+  $(warning Using BUILD_TYPE='$(BUILD_TYPE)' from the $(origin BUILD_TYPE).)
+ endif
+endif
+ifeq ($(USERNAME),)
+ USERNAME := noname
+endif
+
+ifneq ($(MAKECMDGOALS),clean)
+
+ifeq ($(KERNELRELEASE),)
+
+ #
+ # building from this directory
+ #
+
+ # target kernel version
+ ifndef KERN_VER
+  KERN_VER := $(shell uname -r)
+ else
+  ifneq ($(shell if test -d /lib/modules/$(KERN_VER)/build; then echo yes; fi),yes)
+   KERN_VER := $(shell uname -r)
+  endif
+ endif
+
+ # kernel base directory
+ ifndef KERN_DIR
+  KERN_DIR := /lib/modules/$(KERN_VER)/build
+  ifneq ($(shell if test -d $(KERN_DIR); then echo yes; fi),yes)
+   KERN_DIR := /usr/src/linux
+   ifneq ($(shell if test -d $(KERN_DIR); then echo yes; fi),yes)
+    $(error Error: unable to find the sources of your current Linux kernel. \
+                  Specify KERN_DIR=<directory> and run Make again)
+   endif
+   $(warning Warning: using /usr/src/linux as the source directory of your \
+                      Linux kernel. If this is not correct, specify \
+                     KERN_DIR=<directory> and run Make again.)
+  endif
+ else
+  ifneq ($(shell if test -d $(KERN_DIR); then echo yes; fi),yes)
+   $(error Error: KERN_DIR does not point to a directory)
+  endif
+ endif
+
+ # includes
+ ifndef KERN_INCL
+  KERN_INCL = $(KERN_DIR)/include
+ endif
+ ifneq ($(shell if test -d $(KERN_INCL); then echo yes; fi),yes)
+  $(error Error: unable to find the include directory for your current Linux \
+                 kernel. Specify KERN_INCL=<directory> and run Make again)
+ endif
+
+ # module install dir, only for current kernel
+ ifneq ($(filter install install_rpm,$(MAKECMDGOALS)),)
+  ifndef MODULE_DIR
+   MODULE_DIR_TST := /lib/modules/$(KERN_VER)
+   ifeq ($(shell if test -d $(MODULE_DIR_TST); then echo yes; fi),yes)
+    MODULE_DIR := $(MODULE_DIR_TST)/misc
+   else
+    $(error Unable to find the folder to install the module to)
+   endif
+  endif # MODULE_DIR unspecified
+ endif
+
+ # guess kernel version (24 or 26)
+ ifeq ($(shell if grep '"2\.4\.' $(KERN_INCL)/linux/version.h > /dev/null; then echo yes; fi),yes)
+  KERN_VERSION := 24
+ else
+  KERN_VERSION := 26
+ endif
+
+else # neq($(KERNELRELEASE),)
+
+ #
+ # building from kbuild (make -C <kernel_directory> M=`pwd`)
+ #
+
+ # guess kernel version (24 or 26)
+ ifeq ($(shell if echo "$(VERSION).$(PATCHLEVEL)." | grep '2\.4\.' > /dev/null; then echo yes; fi),yes)
+  KERN_VERSION := 24
+ else
+  KERN_VERSION := 26
+ endif
+
+endif # neq($(KERNELRELEASE),)
+
+# debug - show guesses.
+ifdef DEBUG
+$(warning dbg: KERN_DIR     = $(KERN_DIR))
+$(warning dbg: KERN_INCL    = $(KERN_INCL))
+$(warning dbg: MODULE_DIR   = $(MODULE_DIR))
+$(warning dbg: KERN_VERSION = $(KERN_VERSION))
+endif
+
+endif # eq($(MAKECMDGOALS),clean)
diff --git a/ubuntu/vbox/vboxsf/PhysHeap.c b/ubuntu/vbox/vboxsf/PhysHeap.c
new file mode 100644 (file)
index 0000000..7ba42a4
--- /dev/null
@@ -0,0 +1,636 @@
+/* $Id: PhysHeap.cpp $ */
+/** @file
+ * VBoxGuestLibR0 - Physical memory heap.
+ */
+
+/*
+ * 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.
+ */
+
+#include "VBGLInternal.h"
+
+#include <iprt/assert.h>
+#include <iprt/semaphore.h>
+#include <iprt/alloc.h>
+
+/* Physical memory heap consists of double linked list
+ * of chunks. Memory blocks are allocated inside these chunks
+ * and are members of Allocated and Free double linked lists.
+ *
+ * When allocating a block, we search in Free linked
+ * list for a suitable free block. If there is no such block,
+ * a new chunk is allocated and the new block is taken from
+ * the new chunk as the only chunk-sized free block.
+ * Allocated block is excluded from the Free list and goes to
+ * Alloc list.
+ *
+ * When freeing block, we check the pointer and then
+ * exclude block from Alloc list and move it to free list.
+ *
+ * For each chunk we maintain the allocated blocks counter.
+ * if 2 (or more) entire chunks are free they are immediately
+ * deallocated, so we always have at most 1 free chunk.
+ *
+ * When freeing blocks, two subsequent free blocks are always
+ * merged together. Current implementation merges blocks only
+ * when there is a block after the just freed one.
+ *
+ */
+
+#define VBGL_PH_ASSERT      Assert
+#define VBGL_PH_ASSERTMsg   AssertMsg
+
+// #define DUMPHEAP
+
+#ifdef DUMPHEAP
+# define VBGL_PH_dprintf(a) RTAssertMsg2Weak a
+#else
+# define VBGL_PH_dprintf(a)
+#endif
+
+/* Heap block signature */
+#define VBGL_PH_BLOCKSIGNATURE (0xADDBBBBB)
+
+
+/* Heap chunk signature */
+#define VBGL_PH_CHUNKSIGNATURE (0xADDCCCCC)
+/* Heap chunk allocation unit */
+#define VBGL_PH_CHUNKSIZE (0x10000)
+
+/* Heap block bit flags */
+#define VBGL_PH_BF_ALLOCATED (0x1)
+
+struct _VBGLPHYSHEAPBLOCK
+{
+    uint32_t u32Signature;
+
+    /* Size of user data in the block. Does not include the block header. */
+    uint32_t cbDataSize;
+
+    uint32_t fu32Flags;
+
+    struct _VBGLPHYSHEAPBLOCK *pNext;
+    struct _VBGLPHYSHEAPBLOCK *pPrev;
+
+    struct _VBGLPHYSHEAPCHUNK *pChunk;
+};
+
+struct _VBGLPHYSHEAPCHUNK
+{
+    uint32_t u32Signature;
+
+    /* Size of the chunk. Includes the chunk header. */
+    uint32_t cbSize;
+
+    /* Physical address of the chunk */
+    uint32_t physAddr;
+
+    /* Number of allocated blocks in the chunk */
+    int32_t cAllocatedBlocks;
+
+    struct _VBGLPHYSHEAPCHUNK *pNext;
+    struct _VBGLPHYSHEAPCHUNK *pPrev;
+};
+
+
+#ifndef DUMPHEAP
+#define dumpheap(a)
+#else
+void dumpheap (char *point)
+{
+   VBGL_PH_dprintf(("VBGL_PH dump at '%s'\n", point));
+
+   VBGL_PH_dprintf(("Chunks:\n"));
+
+   VBGLPHYSHEAPCHUNK *pChunk = g_vbgldata.pChunkHead;
+
+   while (pChunk)
+   {
+       VBGL_PH_dprintf(("%p: pNext = %p, pPrev = %p, sign = %08X, size = %8d, allocated = %8d, phys = %08X\n",
+                        pChunk, pChunk->pNext, pChunk->pPrev, pChunk->u32Signature, pChunk->cbSize, pChunk->cAllocatedBlocks, pChunk->physAddr));
+
+       pChunk = pChunk->pNext;
+   }
+
+   VBGL_PH_dprintf(("Allocated blocks:\n"));
+
+   VBGLPHYSHEAPBLOCK *pBlock = g_vbgldata.pAllocBlocksHead;
+
+   while (pBlock)
+   {
+       VBGL_PH_dprintf(("%p: pNext = %p, pPrev = %p, sign = %08X, size = %8d, flags = %08X, pChunk = %p\n",
+                        pBlock, pBlock->pNext, pBlock->pPrev, pBlock->u32Signature, pBlock->cbDataSize, pBlock->fu32Flags, pBlock->pChunk));
+
+       pBlock = pBlock->pNext;
+   }
+
+   VBGL_PH_dprintf(("Free blocks:\n"));
+
+   pBlock = g_vbgldata.pFreeBlocksHead;
+
+   while (pBlock)
+   {
+       VBGL_PH_dprintf(("%p: pNext = %p, pPrev = %p, sign = %08X, size = %8d, flags = %08X, pChunk = %p\n",
+                        pBlock, pBlock->pNext, pBlock->pPrev, pBlock->u32Signature, pBlock->cbDataSize, pBlock->fu32Flags, pBlock->pChunk));
+
+       pBlock = pBlock->pNext;
+   }
+
+   VBGL_PH_dprintf(("VBGL_PH dump at '%s' done\n", point));
+}
+#endif
+
+
+DECLINLINE(void *) vbglPhysHeapBlock2Data (VBGLPHYSHEAPBLOCK *pBlock)
+{
+    return (void *)(pBlock? (char *)pBlock + sizeof (VBGLPHYSHEAPBLOCK): NULL);
+}
+
+DECLINLINE(VBGLPHYSHEAPBLOCK *) vbglPhysHeapData2Block (void *p)
+{
+    VBGLPHYSHEAPBLOCK *pBlock = (VBGLPHYSHEAPBLOCK *)(p? (char *)p - sizeof (VBGLPHYSHEAPBLOCK): NULL);
+
+    VBGL_PH_ASSERTMsg(pBlock == NULL || pBlock->u32Signature == VBGL_PH_BLOCKSIGNATURE,
+                     ("pBlock->u32Signature = %08X\n", pBlock->u32Signature));
+
+    return pBlock;
+}
+
+DECLINLINE(int) vbglPhysHeapEnter (void)
+{
+    int rc = RTSemFastMutexRequest(g_vbgldata.mutexHeap);
+
+    VBGL_PH_ASSERTMsg(RT_SUCCESS(rc),
+                     ("Failed to request heap mutex, rc = %Rrc\n", rc));
+
+    return rc;
+}
+
+DECLINLINE(void) vbglPhysHeapLeave (void)
+{
+    RTSemFastMutexRelease(g_vbgldata.mutexHeap);
+}
+
+
+static void vbglPhysHeapInitBlock (VBGLPHYSHEAPBLOCK *pBlock, VBGLPHYSHEAPCHUNK *pChunk, uint32_t cbDataSize)
+{
+    VBGL_PH_ASSERT(pBlock != NULL);
+    VBGL_PH_ASSERT(pChunk != NULL);
+
+    pBlock->u32Signature = VBGL_PH_BLOCKSIGNATURE;
+    pBlock->cbDataSize   = cbDataSize;
+    pBlock->fu32Flags    = 0;
+    pBlock->pNext        = NULL;
+    pBlock->pPrev        = NULL;
+    pBlock->pChunk       = pChunk;
+}
+
+
+static void vbglPhysHeapInsertBlock (VBGLPHYSHEAPBLOCK *pInsertAfter, VBGLPHYSHEAPBLOCK *pBlock)
+{
+    VBGL_PH_ASSERTMsg(pBlock->pNext == NULL,
+                     ("pBlock->pNext = %p\n", pBlock->pNext));
+    VBGL_PH_ASSERTMsg(pBlock->pPrev == NULL,
+                     ("pBlock->pPrev = %p\n", pBlock->pPrev));
+
+    if (pInsertAfter)
+    {
+        pBlock->pNext = pInsertAfter->pNext;
+        pBlock->pPrev = pInsertAfter;
+
+        if (pInsertAfter->pNext)
+        {
+            pInsertAfter->pNext->pPrev = pBlock;
+        }
+
+        pInsertAfter->pNext = pBlock;
+    }
+    else
+    {
+        /* inserting to head of list */
+        pBlock->pPrev = NULL;
+
+        if (pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED)
+        {
+            pBlock->pNext = g_vbgldata.pAllocBlocksHead;
+
+            if (g_vbgldata.pAllocBlocksHead)
+            {
+                g_vbgldata.pAllocBlocksHead->pPrev = pBlock;
+            }
+
+            g_vbgldata.pAllocBlocksHead = pBlock;
+        }
+        else
+        {
+            pBlock->pNext = g_vbgldata.pFreeBlocksHead;
+
+            if (g_vbgldata.pFreeBlocksHead)
+            {
+                g_vbgldata.pFreeBlocksHead->pPrev = pBlock;
+            }
+
+            g_vbgldata.pFreeBlocksHead = pBlock;
+        }
+    }
+}
+
+static void vbglPhysHeapExcludeBlock (VBGLPHYSHEAPBLOCK *pBlock)
+{
+    if (pBlock->pNext)
+    {
+        pBlock->pNext->pPrev = pBlock->pPrev;
+    }
+    else
+    {
+        /* this is tail of list but we do not maintain tails of block lists.
+         * so do nothing.
+         */
+        ;
+    }
+
+    if (pBlock->pPrev)
+    {
+        pBlock->pPrev->pNext = pBlock->pNext;
+    }
+    else
+    {
+        /* this is head of list but we do not maintain tails of block lists. */
+        if (pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED)
+        {
+            g_vbgldata.pAllocBlocksHead = pBlock->pNext;
+        }
+        else
+        {
+            g_vbgldata.pFreeBlocksHead = pBlock->pNext;
+        }
+    }
+
+    pBlock->pNext = NULL;
+    pBlock->pPrev = NULL;
+}
+
+static VBGLPHYSHEAPBLOCK *vbglPhysHeapChunkAlloc (uint32_t cbSize)
+{
+    RTCCPHYS physAddr;
+    VBGLPHYSHEAPCHUNK *pChunk;
+    VBGLPHYSHEAPBLOCK *pBlock;
+    VBGL_PH_dprintf(("Allocating new chunk of size %d\n", cbSize));
+
+    /* Compute chunk size to allocate */
+    if (cbSize < VBGL_PH_CHUNKSIZE)
+    {
+        /* Includes case of block size 0 during initialization */
+        cbSize = VBGL_PH_CHUNKSIZE;
+    }
+    else
+    {
+        /* Round up to next chunk size, which must be power of 2 */
+        cbSize = (cbSize + (VBGL_PH_CHUNKSIZE - 1)) & ~(VBGL_PH_CHUNKSIZE - 1);
+    }
+
+    physAddr = 0;
+    /* This function allocates physical contiguous memory (below 4GB) according to the IPRT docs.
+     * Address < 4G is required for the port IO.
+     */
+    pChunk = (VBGLPHYSHEAPCHUNK *)RTMemContAlloc (&physAddr, cbSize);
+
+    if (!pChunk)
+    {
+        LogRel(("vbglPhysHeapChunkAlloc: failed to alloc %u contiguous bytes.\n", cbSize));
+        return NULL;
+    }
+
+    AssertRelease(physAddr < _4G && physAddr + cbSize <= _4G);
+
+    pChunk->u32Signature     = VBGL_PH_CHUNKSIGNATURE;
+    pChunk->cbSize           = cbSize;
+    pChunk->physAddr         = (uint32_t)physAddr;
+    pChunk->cAllocatedBlocks = 0;
+    pChunk->pNext            = g_vbgldata.pChunkHead;
+    pChunk->pPrev            = NULL;
+
+    /* Initialize the free block, which now occupies entire chunk. */
+    pBlock = (VBGLPHYSHEAPBLOCK *)((char *)pChunk + sizeof (VBGLPHYSHEAPCHUNK));
+
+    vbglPhysHeapInitBlock (pBlock, pChunk, cbSize - sizeof (VBGLPHYSHEAPCHUNK) - sizeof (VBGLPHYSHEAPBLOCK));
+
+    vbglPhysHeapInsertBlock (NULL, pBlock);
+
+    g_vbgldata.pChunkHead = pChunk;
+
+    VBGL_PH_dprintf(("Allocated chunk %p, block = %p size=%x\n", pChunk, pBlock, cbSize));
+
+    return pBlock;
+}
+
+
+void vbglPhysHeapChunkDelete (VBGLPHYSHEAPCHUNK *pChunk)
+{
+    char *p;
+    VBGL_PH_ASSERT(pChunk != NULL);
+    VBGL_PH_ASSERTMsg(pChunk->u32Signature == VBGL_PH_CHUNKSIGNATURE,
+                     ("pChunk->u32Signature = %08X\n", pChunk->u32Signature));
+
+    VBGL_PH_dprintf(("Deleting chunk %p size %x\n", pChunk, pChunk->cbSize));
+
+    /* first scan the chunk and exclude all blocks from lists */
+
+    p = (char *)pChunk + sizeof (VBGLPHYSHEAPCHUNK);
+
+    while (p < (char *)pChunk + pChunk->cbSize)
+    {
+        VBGLPHYSHEAPBLOCK *pBlock = (VBGLPHYSHEAPBLOCK *)p;
+
+        p += pBlock->cbDataSize + sizeof (VBGLPHYSHEAPBLOCK);
+
+        vbglPhysHeapExcludeBlock (pBlock);
+    }
+
+    VBGL_PH_ASSERTMsg(p == (char *)pChunk + pChunk->cbSize,
+                      ("p = %p, (char *)pChunk + pChunk->cbSize = %p, pChunk->cbSize = %08X\n",
+                       p, (char *)pChunk + pChunk->cbSize, pChunk->cbSize));
+
+    /* Exclude chunk from the chunk list */
+    if (pChunk->pNext)
+    {
+        pChunk->pNext->pPrev = pChunk->pPrev;
+    }
+    else
+    {
+        /* we do not maintain tail */
+        ;
+    }
+
+    if (pChunk->pPrev)
+    {
+        pChunk->pPrev->pNext = pChunk->pNext;
+    }
+    else
+    {
+        /* the chunk was head */
+        g_vbgldata.pChunkHead = pChunk->pNext;
+    }
+
+    RTMemContFree (pChunk, pChunk->cbSize);
+}
+
+
+DECLVBGL(void *) VbglPhysHeapAlloc (uint32_t cbSize)
+{
+    VBGLPHYSHEAPBLOCK *pBlock, *iter;
+    int rc = vbglPhysHeapEnter ();
+
+    if (RT_FAILURE(rc))
+        return NULL;
+
+    dumpheap ("pre alloc");
+
+    pBlock = NULL;
+
+    /* If there are free blocks in the heap, look at them. */
+    iter = g_vbgldata.pFreeBlocksHead;
+
+    /* There will be not many blocks in the heap, so
+     * linear search would be fast enough.
+     */
+
+    while (iter)
+    {
+        if (iter->cbDataSize == cbSize)
+        {
+            /* exact match */
+            pBlock = iter;
+            break;
+        }
+
+        /* Looking for a free block with nearest size */
+        if (iter->cbDataSize > cbSize)
+        {
+            if (pBlock)
+            {
+                if (iter->cbDataSize < pBlock->cbDataSize)
+                {
+                    pBlock = iter;
+                }
+            }
+            else
+            {
+                pBlock = iter;
+            }
+        }
+
+        iter = iter->pNext;
+    }
+
+    if (!pBlock)
+    {
+        /* No free blocks, allocate a new chunk,
+         * the only free block of the chunk will
+         * be returned.
+         */
+        pBlock = vbglPhysHeapChunkAlloc (cbSize);
+    }
+
+    if (pBlock)
+    {
+        VBGL_PH_ASSERTMsg(pBlock->u32Signature == VBGL_PH_BLOCKSIGNATURE,
+                         ("pBlock = %p, pBlock->u32Signature = %08X\n", pBlock, pBlock->u32Signature));
+        VBGL_PH_ASSERTMsg((pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED) == 0,
+                         ("pBlock = %p, pBlock->fu32Flags = %08X\n", pBlock, pBlock->fu32Flags));
+
+        /* We have a free block, either found or allocated. */
+
+        if (pBlock->cbDataSize > 2*(cbSize + sizeof (VBGLPHYSHEAPBLOCK)))
+        {
+            /* Data will occupy less than a half of the block,
+             * the block should be split.
+             */
+            iter = (VBGLPHYSHEAPBLOCK *)((char *)pBlock + sizeof (VBGLPHYSHEAPBLOCK) + cbSize);
+
+            /* Init the new 'iter' block, initialized blocks are always marked as free. */
+            vbglPhysHeapInitBlock (iter, pBlock->pChunk, pBlock->cbDataSize - cbSize - sizeof (VBGLPHYSHEAPBLOCK));
+
+            pBlock->cbDataSize = cbSize;
+
+            /* Insert the new 'iter' block after the 'pBlock' in the free list */
+            vbglPhysHeapInsertBlock (pBlock, iter);
+        }
+
+        /* Exclude pBlock from free list */
+        vbglPhysHeapExcludeBlock (pBlock);
+
+        /* Mark as allocated */
+        pBlock->fu32Flags |= VBGL_PH_BF_ALLOCATED;
+
+        /* Insert to allocated list */
+        vbglPhysHeapInsertBlock (NULL, pBlock);
+
+        /* Adjust the chunk allocated blocks counter */
+        pBlock->pChunk->cAllocatedBlocks++;
+    }
+
+    dumpheap ("post alloc");
+
+    vbglPhysHeapLeave ();
+    VBGL_PH_dprintf(("VbglPhysHeapAlloc %x size %x\n", vbglPhysHeapBlock2Data (pBlock), pBlock->cbDataSize));
+
+    return vbglPhysHeapBlock2Data (pBlock);
+}
+
+DECLVBGL(uint32_t) VbglPhysHeapGetPhysAddr (void *p)
+{
+    uint32_t physAddr = 0;
+    VBGLPHYSHEAPBLOCK *pBlock = vbglPhysHeapData2Block (p);
+
+    if (pBlock)
+    {
+        VBGL_PH_ASSERTMsg((pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED) != 0,
+                         ("pBlock = %p, pBlock->fu32Flags = %08X\n", pBlock, pBlock->fu32Flags));
+
+        if (pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED)
+            physAddr = pBlock->pChunk->physAddr + (uint32_t)((uintptr_t)p - (uintptr_t)pBlock->pChunk);
+    }
+
+    return physAddr;
+}
+
+DECLVBGL(void) VbglPhysHeapFree(void *p)
+{
+    VBGLPHYSHEAPBLOCK *pBlock;
+    VBGLPHYSHEAPBLOCK *pNeighbour;
+
+    int rc = vbglPhysHeapEnter ();
+    if (RT_FAILURE(rc))
+        return;
+
+    dumpheap ("pre free");
+
+    pBlock = vbglPhysHeapData2Block (p);
+
+    if (!pBlock)
+    {
+        vbglPhysHeapLeave ();
+        return;
+    }
+
+    VBGL_PH_ASSERTMsg((pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED) != 0,
+                     ("pBlock = %p, pBlock->fu32Flags = %08X\n", pBlock, pBlock->fu32Flags));
+
+    /* Exclude from allocated list */
+    vbglPhysHeapExcludeBlock (pBlock);
+
+    dumpheap ("post exclude");
+
+    VBGL_PH_dprintf(("VbglPhysHeapFree %x size %x\n", p, pBlock->cbDataSize));
+
+    /* Mark as free */
+    pBlock->fu32Flags &= ~VBGL_PH_BF_ALLOCATED;
+
+    /* Insert to free list */
+    vbglPhysHeapInsertBlock (NULL, pBlock);
+
+    dumpheap ("post insert");
+
+    /* Adjust the chunk allocated blocks counter */
+    pBlock->pChunk->cAllocatedBlocks--;
+
+    VBGL_PH_ASSERT(pBlock->pChunk->cAllocatedBlocks >= 0);
+
+    /* Check if we can merge 2 free blocks. To simplify heap maintenance,
+     * we will look at block after the just freed one.
+     * This will not prevent us from detecting free memory chunks.
+     * Also in most cases blocks are deallocated in reverse allocation order
+     * and in that case the merging will work.
+     */
+
+    pNeighbour = (VBGLPHYSHEAPBLOCK *)((char *)p + pBlock->cbDataSize);
+
+    if ((char *)pNeighbour < (char *)pBlock->pChunk + pBlock->pChunk->cbSize
+        && (pNeighbour->fu32Flags & VBGL_PH_BF_ALLOCATED) == 0)
+    {
+        /* The next block is free as well. */
+
+        /* Adjust size of current memory block */
+        pBlock->cbDataSize += pNeighbour->cbDataSize + sizeof (VBGLPHYSHEAPBLOCK);
+
+        /* Exclude the next neighbour */
+        vbglPhysHeapExcludeBlock (pNeighbour);
+    }
+
+    dumpheap ("post merge");
+
+    /* now check if there are 2 or more free chunks */
+    if (pBlock->pChunk->cAllocatedBlocks == 0)
+    {
+        VBGLPHYSHEAPCHUNK *pChunk = g_vbgldata.pChunkHead;
+
+        uint32_t u32FreeChunks = 0;
+
+        while (pChunk)
+        {
+            if (pChunk->cAllocatedBlocks == 0)
+            {
+                u32FreeChunks++;
+            }
+
+            pChunk = pChunk->pNext;
+        }
+
+        if (u32FreeChunks > 1)
+        {
+            /* Delete current chunk, it will also exclude all free blocks
+             * remaining in the chunk from the free list, so the pBlock
+             * will also be invalid after this.
+             */
+            vbglPhysHeapChunkDelete (pBlock->pChunk);
+        }
+    }
+
+    dumpheap ("post free");
+
+    vbglPhysHeapLeave ();
+}
+
+DECLVBGL(int) VbglPhysHeapInit (void)
+{
+    int rc = VINF_SUCCESS;
+
+    /* Allocate the first chunk of the heap. */
+    VBGLPHYSHEAPBLOCK *pBlock = vbglPhysHeapChunkAlloc (0);
+
+    if (!pBlock)
+        rc = VERR_NO_MEMORY;
+
+    RTSemFastMutexCreate(&g_vbgldata.mutexHeap);
+
+    return rc;
+}
+
+DECLVBGL(void) VbglPhysHeapTerminate (void)
+{
+    while (g_vbgldata.pChunkHead)
+    {
+        vbglPhysHeapChunkDelete (g_vbgldata.pChunkHead);
+    }
+
+    RTSemFastMutexDestroy(g_vbgldata.mutexHeap);
+}
+
diff --git a/ubuntu/vbox/vboxsf/SysHlp.c b/ubuntu/vbox/vboxsf/SysHlp.c
new file mode 100644 (file)
index 0000000..1485af2
--- /dev/null
@@ -0,0 +1,345 @@
+/* $Id: SysHlp.cpp $ */
+/** @file
+ * VBoxGuestLibR0 - IDC with VBoxGuest and HGCM helpers.
+ */
+
+/*
+ * 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.
+ */
+
+#define LOG_GROUP LOG_GROUP_HGCM
+#include <VBox/log.h>
+
+#include <VBox/VBoxGuestLib.h>
+#include "SysHlp.h"
+
+#include <iprt/assert.h>
+
+#ifdef VBGL_VBOXGUEST
+
+#if !defined (RT_OS_WINDOWS)
+# include <iprt/memobj.h>
+# include <iprt/mem.h>
+#endif
+
+
+/**
+ * Internal worker for locking a range of linear addresses.
+ *
+ * @returns VBox status code.
+ * @param   ppvCtx          Where to store context data.
+ * @param   pv              The start of the range.
+ * @param   u32Size         The size of the range.
+ * @param   fWriteAccess    Lock for read-write (true) or readonly (false).
+ * @param   fFlags          HGCM call flags, VBGLR0_HGCM_F_XXX.
+ */
+int vbglLockLinear(void **ppvCtx, void *pv, uint32_t u32Size, bool fWriteAccess, uint32_t fFlags)
+{
+    int         rc      = VINF_SUCCESS;
+#ifndef RT_OS_WINDOWS
+    RTR0MEMOBJ  MemObj  = NIL_RTR0MEMOBJ;
+    uint32_t    fAccess = RTMEM_PROT_READ | (fWriteAccess ? RTMEM_PROT_WRITE : 0);
+#endif
+
+    /* Zero size buffers shouldn't be locked. */
+    if (u32Size == 0)
+    {
+        Assert(pv == NULL);
+#ifdef RT_OS_WINDOWS
+        *ppvCtx = NULL;
+#else
+        *ppvCtx = NIL_RTR0MEMOBJ;
+#endif
+        return VINF_SUCCESS;
+    }
+
+    /** @todo just use IPRT here. the extra allocation shouldn't matter much...
+     *        Then we can move all this up one level even. */
+#ifdef RT_OS_WINDOWS
+    PMDL pMdl = IoAllocateMdl(pv, u32Size, FALSE, FALSE, NULL);
+
+    if (pMdl == NULL)
+    {
+        rc = VERR_NOT_SUPPORTED;
+        AssertMsgFailed(("IoAllocateMdl %p %x failed!!\n", pv, u32Size));
+    }
+    else
+    {
+        __try {
+            /* Calls to MmProbeAndLockPages must be enclosed in a try/except block. */
+            RT_NOREF1(fFlags);  /** @todo fFlags on windows */
+            MmProbeAndLockPages(pMdl,
+                                /** @todo (fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER? UserMode: KernelMode */
+                                KernelMode,
+                                (fWriteAccess) ? IoModifyAccess : IoReadAccess);
+
+            *ppvCtx = pMdl;
+
+        } __except(EXCEPTION_EXECUTE_HANDLER) {
+
+            IoFreeMdl(pMdl);
+            /** @todo  */
+            rc = VERR_INVALID_PARAMETER;
+            AssertMsgFailed(("MmProbeAndLockPages %p %x failed!!\n", pv, u32Size));
+        }
+    }
+
+#else
+    /*
+     * Lock depending on context.
+     *
+     * Note: We will later use the memory object here to convert the HGCM
+     *       linear buffer parameter into a physical page list. This is why
+     *       we lock both kernel pages on all systems, even those where we
+     *       know they aren't pageable.
+     */
+    if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER)
+        rc = RTR0MemObjLockUser(&MemObj, (RTR3PTR)pv, u32Size, fAccess, NIL_RTR0PROCESS);
+    else
+        rc = RTR0MemObjLockKernel(&MemObj, pv, u32Size, fAccess);
+    if (RT_SUCCESS(rc))
+        *ppvCtx = MemObj;
+    else
+        *ppvCtx = NIL_RTR0MEMOBJ;
+
+#endif
+
+    return rc;
+}
+
+void vbglUnlockLinear(void *pvCtx, void *pv, uint32_t u32Size)
+{
+#ifdef RT_OS_WINDOWS
+    PMDL pMdl = (PMDL)pvCtx;
+
+    Assert(pMdl);
+    if (pMdl != NULL)
+    {
+        MmUnlockPages(pMdl);
+        IoFreeMdl(pMdl);
+    }
+
+#else
+    RTR0MEMOBJ MemObj = (RTR0MEMOBJ)pvCtx;
+    int rc = RTR0MemObjFree(MemObj, false);
+    AssertRC(rc);
+
+#endif
+
+    NOREF(pv);
+    NOREF(u32Size);
+}
+
+#else  /* !VBGL_VBOXGUEST */
+
+# ifdef RT_OS_OS2
+#  include <VBox/VBoxGuest.h> /* for VBOXGUESTOS2IDCCONNECT */
+RT_C_DECLS_BEGIN
+/*
+ * On OS/2 we'll do the connecting in the assembly code of the
+ * client driver, exporting a g_VBoxGuestIDC symbol containing
+ * the connection information obtained from the 16-bit IDC.
+ */
+extern VBOXGUESTOS2IDCCONNECT g_VBoxGuestIDC;
+RT_C_DECLS_END
+# endif
+
+# if !defined(RT_OS_OS2) \
+  && !defined(RT_OS_WINDOWS)
+RT_C_DECLS_BEGIN
+extern DECLVBGL(void *) VBoxGuestIDCOpen(uint32_t *pu32Version);
+extern DECLVBGL(void)   VBoxGuestIDCClose(void *pvOpaque);
+extern DECLVBGL(int)    VBoxGuestIDCCall(void *pvOpaque, unsigned int iCmd, void *pvData, size_t cbSize, size_t *pcbReturn);
+RT_C_DECLS_END
+# endif
+
+bool vbglDriverIsOpened(VBGLDRIVER *pDriver)
+{
+# ifdef RT_OS_WINDOWS
+    return pDriver->pFileObject != NULL;
+# elif defined (RT_OS_OS2)
+    return pDriver->u32Session != UINT32_MAX && pDriver->u32Session != 0;
+# else
+    return pDriver->pvOpaque != NULL;
+# endif
+}
+
+int vbglDriverOpen(VBGLDRIVER *pDriver)
+{
+# ifdef RT_OS_WINDOWS
+    UNICODE_STRING uszDeviceName;
+    RtlInitUnicodeString(&uszDeviceName, L"\\Device\\VBoxGuest");
+
+    PDEVICE_OBJECT pDeviceObject = NULL;
+    PFILE_OBJECT pFileObject = NULL;
+
+    NTSTATUS rc = IoGetDeviceObjectPointer(&uszDeviceName, FILE_ALL_ACCESS, &pFileObject, &pDeviceObject);
+    if (NT_SUCCESS(rc))
+    {
+        Log(("vbglDriverOpen VBoxGuest successful pDeviceObject=%x\n", pDeviceObject));
+        pDriver->pDeviceObject = pDeviceObject;
+        pDriver->pFileObject = pFileObject;
+        return VINF_SUCCESS;
+    }
+    /** @todo return RTErrConvertFromNtStatus(rc)! */
+    Log(("vbglDriverOpen VBoxGuest failed with ntstatus=%x\n", rc));
+    return rc;
+
+# elif defined (RT_OS_OS2)
+    /*
+     * Just check whether the connection was made or not.
+     */
+    if (   g_VBoxGuestIDC.u32Version == VMMDEV_VERSION
+        && RT_VALID_PTR(g_VBoxGuestIDC.u32Session)
+        && RT_VALID_PTR(g_VBoxGuestIDC.pfnServiceEP))
+    {
+        pDriver->u32Session = g_VBoxGuestIDC.u32Session;
+        return VINF_SUCCESS;
+    }
+    pDriver->u32Session = UINT32_MAX;
+    Log(("vbglDriverOpen: failed\n"));
+    return VERR_FILE_NOT_FOUND;
+
+# else
+    uint32_t u32VMMDevVersion;
+    pDriver->pvOpaque = VBoxGuestIDCOpen(&u32VMMDevVersion);
+    if (   pDriver->pvOpaque
+        && u32VMMDevVersion == VMMDEV_VERSION)
+        return VINF_SUCCESS;
+
+    Log(("vbglDriverOpen: failed\n"));
+    return VERR_FILE_NOT_FOUND;
+# endif
+}
+
+# ifdef RT_OS_WINDOWS
+static NTSTATUS vbglDriverIOCtlCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
+{
+    RT_NOREF2(DeviceObject, Irp);
+    Log(("VBGL completion %x\n", Irp));
+
+    KEVENT *pEvent = (KEVENT *)Context;
+    KeSetEvent(pEvent, IO_NO_INCREMENT, FALSE);
+
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+# endif
+
+int vbglDriverIOCtl(VBGLDRIVER *pDriver, uint32_t u32Function, void *pvData, uint32_t cbData)
+{
+    Log(("vbglDriverIOCtl: pDriver: %p, Func: %x, pvData: %p, cbData: %d\n", pDriver, u32Function, pvData, cbData));
+
+# ifdef RT_OS_WINDOWS
+    KEVENT Event;
+
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+    /* Have to use the IoAllocateIRP method because this code is generic and
+     * must work in any thread context.
+     * The IoBuildDeviceIoControlRequest, which was used here, does not work
+     * when APCs are disabled, for example.
+     */
+    PIRP irp = IoAllocateIrp(pDriver->pDeviceObject->StackSize, FALSE);
+
+    Log(("vbglDriverIOCtl: irp %p, IRQL = %d\n", irp, KeGetCurrentIrql()));
+
+    if (irp == NULL)
+    {
+        Log(("vbglDriverIOCtl: IRP allocation failed!\n"));
+        return VERR_NO_MEMORY;
+    }
+
+    /*
+     * Setup the IRP_MJ_DEVICE_CONTROL IRP.
+     */
+
+    PIO_STACK_LOCATION nextStack = IoGetNextIrpStackLocation(irp);
+
+    nextStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
+    nextStack->MinorFunction = 0;
+    nextStack->DeviceObject = pDriver->pDeviceObject;
+    nextStack->Parameters.DeviceIoControl.OutputBufferLength = cbData;
+    nextStack->Parameters.DeviceIoControl.InputBufferLength = cbData;
+    nextStack->Parameters.DeviceIoControl.IoControlCode = u32Function;
+    nextStack->Parameters.DeviceIoControl.Type3InputBuffer = pvData;
+
+    irp->AssociatedIrp.SystemBuffer = pvData; /* Output buffer. */
+    irp->MdlAddress = NULL;
+
+    /* A completion routine is required to signal the Event. */
+    IoSetCompletionRoutine(irp, vbglDriverIOCtlCompletion, &Event, TRUE, TRUE, TRUE);
+
+    NTSTATUS rc = IoCallDriver(pDriver->pDeviceObject, irp);
+
+    if (NT_SUCCESS (rc))
+    {
+        /* Wait the event to be signalled by the completion routine. */
+        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+
+        rc = irp->IoStatus.Status;
+
+        Log(("vbglDriverIOCtl: wait completed IRQL = %d\n", KeGetCurrentIrql()));
+    }
+
+    IoFreeIrp(irp);
+
+    if (rc != STATUS_SUCCESS)
+        Log(("vbglDriverIOCtl: ntstatus=%x\n", rc));
+
+    if (NT_SUCCESS(rc))
+        return VINF_SUCCESS;
+    if (rc == STATUS_INVALID_PARAMETER)
+        return VERR_INVALID_PARAMETER;
+    if (rc == STATUS_INVALID_BUFFER_SIZE)
+        return VERR_OUT_OF_RANGE;
+    return VERR_VBGL_IOCTL_FAILED;
+
+# elif defined (RT_OS_OS2)
+    if (    pDriver->u32Session
+        &&  pDriver->u32Session == g_VBoxGuestIDC.u32Session)
+        return g_VBoxGuestIDC.pfnServiceEP(pDriver->u32Session, u32Function, pvData, cbData, NULL);
+
+    Log(("vbglDriverIOCtl: No connection\n"));
+    return VERR_WRONG_ORDER;
+
+# else
+    return VBoxGuestIDCCall(pDriver->pvOpaque, u32Function, pvData, cbData, NULL);
+# endif
+}
+
+void vbglDriverClose(VBGLDRIVER *pDriver)
+{
+# ifdef RT_OS_WINDOWS
+    Log(("vbglDriverClose pDeviceObject=%x\n", pDriver->pDeviceObject));
+    ObDereferenceObject(pDriver->pFileObject);
+    pDriver->pFileObject = NULL;
+    pDriver->pDeviceObject = NULL;
+
+# elif defined (RT_OS_OS2)
+    pDriver->u32Session = 0;
+
+# else
+    VBoxGuestIDCClose(pDriver->pvOpaque);
+    pDriver->pvOpaque = NULL;
+# endif
+}
+
+#endif /* !VBGL_VBOXGUEST */
+
diff --git a/ubuntu/vbox/vboxsf/SysHlp.h b/ubuntu/vbox/vboxsf/SysHlp.h
new file mode 100644 (file)
index 0000000..3d0d444
--- /dev/null
@@ -0,0 +1,103 @@
+/* $Id: SysHlp.h $ */
+/** @file
+ * VBoxGuestLibR0 - System dependent helpers internal header.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBoxGuestLib_SysHlp_h
+#define ___VBoxGuestLib_SysHlp_h
+
+#include <iprt/types.h>
+
+#ifdef RT_OS_WINDOWS
+# undef PAGE_SIZE
+# undef PAGE_SHIFT
+# include <iprt/nt/ntddk.h>
+/* XP DDK #defines ExFreePool to ExFreePoolWithTag. The latter does not exist on NT4, so...
+ * The same for ExAllocatePool.
+ */
+# undef ExAllocatePool
+# undef ExFreePool
+#endif
+
+typedef struct _VBGLDRIVER
+{
+#ifdef RT_OS_WINDOWS
+    PDEVICE_OBJECT pDeviceObject;
+    PFILE_OBJECT pFileObject;
+#elif defined (RT_OS_OS2)
+    uint32_t u32Session; /**< just for sanity checking. */
+#else /* PORTME */
+    void *pvOpaque;
+#endif
+} VBGLDRIVER;
+
+int  vbglLockLinear(void **ppvCtx, void *pv, uint32_t cb, bool fWriteAccess, uint32_t fFlags);
+void vbglUnlockLinear(void *pvCtx, void *pv, uint32_t cb);
+
+
+#ifndef VBGL_VBOXGUEST
+
+/**
+ * Open VBoxGuest driver.
+ *
+ * @param pDriver      Pointer to the driver structure.
+ *
+ * @return VBox status code
+ */
+int vbglDriverOpen(VBGLDRIVER *pDriver);
+
+/**
+ * Answers whether the VBoxGuest driver is opened
+ *
+ * @param pDriver      Pointer to the driver structure.
+ *
+ * @return true - if opened, false - otherwise
+ */
+bool vbglDriverIsOpened(VBGLDRIVER *pDriver);
+
+/**
+ * Call VBoxGuest driver.
+ *
+ * @param pDriver      Pointer to the driver structure.
+ * @param u32Function  Function code.
+ * @param pvData       Pointer to supplied in/out data buffer.
+ * @param cbData       Size of data buffer.
+ *
+ * @returns VBox status code
+ */
+int vbglDriverIOCtl(VBGLDRIVER *pDriver, uint32_t u32Function, void *pvData, uint32_t cbData);
+
+/**
+ * Close VBoxGuest driver.
+ *
+ * @param pDriver      Pointer to the driver structure.
+ *
+ * @returns VBox status code
+ */
+void vbglDriverClose(VBGLDRIVER *pDriver);
+
+#endif
+
+#endif
+
diff --git a/ubuntu/vbox/vboxsf/VBGLInternal.h b/ubuntu/vbox/vboxsf/VBGLInternal.h
new file mode 100644 (file)
index 0000000..14208f6
--- /dev/null
@@ -0,0 +1,169 @@
+/* $Id: VBGLInternal.h $ */
+/** @file
+ * VBoxGuestLibR0 - Internal header.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___VBoxGuestLib_VBGLInternal_h
+#define ___VBoxGuestLib_VBGLInternal_h
+
+#include <VBox/VMMDev.h>
+#include <VBox/VBoxGuest.h>
+#include <VBox/VBoxGuestLib.h>
+
+#include <VBox/log.h>
+
+
+#ifdef RT_OS_WINDOWS /** @todo dprintf() -> Log() */
+# if (defined(DEBUG) && !defined(NO_LOGGING)) || defined(LOG_ENABLED)
+#  define dprintf(a) RTLogBackdoorPrintf a
+# else
+#  define dprintf(a) do {} while (0)
+# endif
+#else
+# define dprintf(a) Log(a)
+#endif
+
+#include "SysHlp.h"
+
+struct _VBGLPHYSHEAPBLOCK;
+typedef struct _VBGLPHYSHEAPBLOCK VBGLPHYSHEAPBLOCK;
+struct _VBGLPHYSHEAPCHUNK;
+typedef struct _VBGLPHYSHEAPCHUNK VBGLPHYSHEAPCHUNK;
+
+#ifndef VBGL_VBOXGUEST
+struct VBGLHGCMHANDLEDATA
+{
+    uint32_t fAllocated;
+    VBGLDRIVER driver;
+};
+#endif
+
+enum VbglLibStatus
+{
+    VbglStatusNotInitialized = 0,
+    VbglStatusInitializing,
+    VbglStatusReady
+};
+
+/**
+ * Global VBGL ring-0 data.
+ * Lives in VbglR0Init.cpp.
+ */
+typedef struct VBGLDATA
+{
+    enum VbglLibStatus status;
+
+    RTIOPORT portVMMDev;
+
+    VMMDevMemory *pVMMDevMemory;
+
+    /**
+     * Physical memory heap data.
+     * @{
+     */
+
+    VBGLPHYSHEAPBLOCK *pFreeBlocksHead;
+    VBGLPHYSHEAPBLOCK *pAllocBlocksHead;
+    VBGLPHYSHEAPCHUNK *pChunkHead;
+
+    RTSEMFASTMUTEX mutexHeap;
+    /** @} */
+
+    /**
+     * The host version data.
+     */
+    VMMDevReqHostVersion hostVersion;
+
+
+#ifndef VBGL_VBOXGUEST
+    /**
+     * Handle for the main driver instance.
+     * @{
+     */
+
+    RTSEMMUTEX mutexDriverInit;
+
+    VBGLDRIVER driver;
+
+    /** @} */
+
+    /**
+     * Fast heap for HGCM handles data.
+     * @{
+     */
+
+    RTSEMFASTMUTEX mutexHGCMHandle;
+
+    struct VBGLHGCMHANDLEDATA aHGCMHandleData[64];
+
+    /** @} */
+#endif
+} VBGLDATA;
+
+
+#ifndef VBGL_DECL_DATA
+extern VBGLDATA g_vbgldata;
+#endif
+
+/**
+ * Internal macro for checking whether we can pass physical page lists to the
+ * host.
+ *
+ * ASSUMES that vbglR0Enter has been called already.
+ *
+ * @param   a_fLocked       For the windows shared folders workarounds.
+ *
+ * @remarks Disabled the PageList feature for locked memory on Windows,
+ *          because a new MDL is created by VBGL to get the page addresses
+ *          and the pages from the MDL are marked as dirty when they should not.
+ */
+#if defined(RT_OS_WINDOWS)
+# define VBGLR0_CAN_USE_PHYS_PAGE_LIST(a_fLocked) \
+    ( !(a_fLocked) && (g_vbgldata.hostVersion.features & VMMDEV_HVF_HGCM_PHYS_PAGE_LIST) )
+#else
+# define VBGLR0_CAN_USE_PHYS_PAGE_LIST(a_fLocked) \
+    ( !!(g_vbgldata.hostVersion.features & VMMDEV_HVF_HGCM_PHYS_PAGE_LIST) )
+#endif
+
+int vbglR0Enter (void);
+
+#ifdef VBOX_WITH_HGCM
+# ifndef VBGL_VBOXGUEST
+int                         vbglR0HGCMInit(void);
+int                         vbglR0HGCMTerminate(void);
+# endif
+struct VBGLHGCMHANDLEDATA  *vbglHGCMHandleAlloc(void);
+void                        vbglHGCMHandleFree(struct VBGLHGCMHANDLEDATA *pHandle);
+#endif /* VBOX_WITH_HGCM */
+
+#ifndef VBGL_VBOXGUEST
+/**
+ * Get a handle to the main VBoxGuest driver.
+ * @returns VERR_TRY_AGAIN if the main driver has not yet been loaded.
+ */
+int vbglGetDriver(VBGLDRIVER **ppDriver);
+#endif
+
+#endif /* !___VBoxGuestLib_VBGLInternal_h */
+
diff --git a/ubuntu/vbox/vboxsf/VBoxGuestLog.h b/ubuntu/vbox/vboxsf/VBoxGuestLog.h
new file mode 100644 (file)
index 0000000..26feeb7
--- /dev/null
@@ -0,0 +1,59 @@
+/* $Id: VBoxGuestLog.h $ */
+/** @file
+ * VBoxGuestLibR0 - Guest Logging facility.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef __VBOXGUESTLOG__H
+#define __VBOXGUESTLOG__H
+
+#ifndef RT_OS_WINDOWS
+# error "Don't include this file."
+#else  /* RT_OS_WINDOWS */
+/* Save LOG_ENABLED state, because "VBox/rt/log.h"
+ * may undefine it for IN_RING0 code.
+ */
+# if (defined(DEBUG) && !defined(NO_LOGGING)) || defined(LOG_ENABLED)
+#  define __LOG_ENABLED_SAVED__
+# endif
+
+# if (defined(DEBUG) && !defined(NO_LOGGING)) || defined(LOG_ENABLED)
+#  ifdef VBOX_GUEST
+#   include <VBox/log.h>
+#   undef Log
+#   define Log(a)  RTLogBackdoorPrintf a
+#  else
+#   define Log(a)  DbgPrint a
+#  endif
+# else
+#  define Log(a)
+# endif
+
+# ifdef __LOG_ENABLED_SAVED__
+#  define LOG_ENABLED
+#  undef __LOG_ENABLED_SAVED__
+# endif
+
+#endif  /* RT_OS_WINDOWS */
+
+#endif /* !__VBOXGUESTLOG__H */
diff --git a/ubuntu/vbox/vboxsf/VBoxGuestR0LibSharedFolders.c b/ubuntu/vbox/vboxsf/VBoxGuestR0LibSharedFolders.c
new file mode 100644 (file)
index 0000000..26fcb2b
--- /dev/null
@@ -0,0 +1,750 @@
+/* $Id: VBoxGuestR0LibSharedFolders.c $ */
+/** @file
+ * VBoxGuestR0LibSharedFolders - Ring 0 Shared Folders calls.
+ */
+
+/*
+ * 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.
+ */
+
+/* Entire file is ifdef'ed with !VBGL_VBOXGUEST */
+#ifndef VBGL_VBOXGUEST
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_SHARED_FOLDERS
+#include <VBox/VBoxGuestLibSharedFolders.h>
+#include <VBox/log.h>
+#include <iprt/time.h>
+#include <iprt/mem.h>
+#include <iprt/path.h>
+#include <iprt/string.h>
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+#define SHFL_CPARMS_SET_UTF8 0
+#define SHFL_CPARMS_SET_SYMLINKS 0
+
+#define VBOX_INIT_CALL(a, b, c) \
+    LogFunc(("%s, idClient=%d\n", "SHFL_FN_" # b, (c)->idClient)); \
+    (a)->result      = VINF_SUCCESS; \
+    (a)->u32ClientID = (c)->idClient; \
+    (a)->u32Function = SHFL_FN_##b; \
+    (a)->cParms      = SHFL_CPARMS_##b
+
+
+
+DECLVBGL(int) VbglR0SfInit(void)
+{
+    return VbglInitClient();
+}
+
+DECLVBGL(void) VbglR0SfTerm(void)
+{
+    VbglTerminate();
+}
+
+DECLVBGL(int) VbglR0SfConnect(PVBGLSFCLIENT pClient)
+{
+    int rc;
+    VBoxGuestHGCMConnectInfo data;
+
+    pClient->handle = NULL;
+
+    RT_ZERO(data);
+    data.result   = VINF_SUCCESS;
+    data.Loc.type = VMMDevHGCMLoc_LocalHost_Existing;
+#if defined(RT_OS_LINUX)
+    strcpy(data.Loc.u.host.achName, "VBoxSharedFolders");
+#else
+    RTStrCopy(data.Loc.u.host.achName, sizeof(data.Loc.u.host.achName), "VBoxSharedFolders");
+#endif
+
+    rc = VbglHGCMConnect(&pClient->handle, &data);
+/*    Log(("VBOXSF: VbglR0SfConnect: VbglHGCMConnect rc = %#x, result = %#x\n", rc, data.result)); */
+    if (RT_SUCCESS(rc))
+        rc = data.result;
+    if (RT_SUCCESS(rc))
+    {
+        pClient->idClient = data.u32ClientID;
+        LogFunc(("idClient=%d\n", pClient->idClient));
+    }
+    return rc;
+}
+
+DECLVBGL(void) VbglR0SfDisconnect(PVBGLSFCLIENT pClient)
+{
+    int rc;
+    VBoxGuestHGCMDisconnectInfo data;
+
+    LogFunc(("u32ClientID=%d\n", pClient->idClient));
+    if (pClient->handle == NULL)
+        return;                 /* not connected */
+
+    RT_ZERO(data);
+    data.result      = VINF_SUCCESS;
+    data.u32ClientID = pClient->idClient;
+
+    rc = VbglHGCMDisconnect(pClient->handle, &data);
+    NOREF(rc);
+/*    Log(("VBOXSF: VbglR0SfDisconnect: VbglHGCMDisconnect rc = %#x, result = %#x\n", rc, data.result)); */
+    return;
+}
+
+DECLVBGL(int) VbglR0SfQueryMappings(PVBGLSFCLIENT pClient, SHFLMAPPING paMappings[], uint32_t *pcMappings)
+{
+    int rc;
+    VBoxSFQueryMappings data;
+
+    VBOX_INIT_CALL(&data.callInfo, QUERY_MAPPINGS, pClient);
+
+    data.flags.type                      = VMMDevHGCMParmType_32bit;
+    data.flags.u.value32                 = SHFL_MF_UCS2;
+
+    data.numberOfMappings.type           = VMMDevHGCMParmType_32bit;
+    data.numberOfMappings.u.value32      = *pcMappings;
+
+    data.mappings.type                   = VMMDevHGCMParmType_LinAddr;
+    data.mappings.u.Pointer.size         = sizeof(SHFLMAPPING) * *pcMappings;
+    data.mappings.u.Pointer.u.linearAddr = (uintptr_t)&paMappings[0];
+
+/*    Log(("VBOXSF: in ifs difference %d\n", (char *)&data.flags.type - (char *)&data.callInfo.cParms)); */
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfQueryMappings: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+        rc = data.callInfo.result;
+    if (RT_SUCCESS(rc))
+        *pcMappings = data.numberOfMappings.u.value32;
+
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfQueryMapName(PVBGLSFCLIENT pClient, SHFLROOT root, SHFLSTRING *pString, uint32_t size)
+{
+    int rc;
+    VBoxSFQueryMapName data;
+
+    VBOX_INIT_CALL(&data.callInfo, QUERY_MAP_NAME, pClient);
+
+    data.root.type                   = VMMDevHGCMParmType_32bit;
+    data.root.u.value32              = root;
+
+    data.name.type                   = VMMDevHGCMParmType_LinAddr;
+    data.name.u.Pointer.size         = size;
+    data.name.u.Pointer.u.linearAddr = (uintptr_t)pString;
+
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfQueryMapName: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+        rc = data.callInfo.result;
+
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfMapFolder(PVBGLSFCLIENT pClient, PSHFLSTRING szFolderName, PVBGLSFMAP pMap)
+{
+    int rc;
+    VBoxSFMapFolder data;
+
+    VBOX_INIT_CALL(&data.callInfo, MAP_FOLDER, pClient);
+
+    data.path.type                    = VMMDevHGCMParmType_LinAddr;
+    data.path.u.Pointer.size          = ShflStringSizeOfBuffer(szFolderName);
+    data.path.u.Pointer.u.linearAddr  = (uintptr_t)szFolderName;
+
+    data.root.type                    = VMMDevHGCMParmType_32bit;
+    data.root.u.value32               = 0;
+
+    data.delimiter.type               = VMMDevHGCMParmType_32bit;
+    data.delimiter.u.value32          = RTPATH_DELIMITER;
+
+    data.fCaseSensitive.type          = VMMDevHGCMParmType_32bit;
+#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
+    data.fCaseSensitive.u.value32     = 0;
+#else
+    data.fCaseSensitive.u.value32     = 1;
+#endif
+
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfMapFolder: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+    {
+        pMap->root = data.root.u.value32;
+        rc         = data.callInfo.result;
+    }
+    else if (rc == VERR_NOT_IMPLEMENTED)
+    {
+        /* try the legacy interface too; temporary to assure backwards compatibility */
+        VBoxSFMapFolder_Old OldData;
+
+        VBOX_INIT_CALL(&OldData.callInfo, MAP_FOLDER_OLD, pClient);
+
+        OldData.path.type                    = VMMDevHGCMParmType_LinAddr;
+        OldData.path.u.Pointer.size          = ShflStringSizeOfBuffer (szFolderName);
+        OldData.path.u.Pointer.u.linearAddr  = (uintptr_t)szFolderName;
+
+        OldData.root.type                    = VMMDevHGCMParmType_32bit;
+        OldData.root.u.value32               = 0;
+
+        OldData.delimiter.type               = VMMDevHGCMParmType_32bit;
+        OldData.delimiter.u.value32          = RTPATH_DELIMITER;
+
+        rc = VbglHGCMCall(pClient->handle, &OldData.callInfo, sizeof(OldData));
+        if (RT_SUCCESS(rc))
+        {
+            pMap->root = OldData.root.u.value32;
+            rc         = OldData.callInfo.result;
+        }
+    }
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfUnmapFolder(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap)
+{
+    int rc;
+    VBoxSFUnmapFolder data;
+
+    VBOX_INIT_CALL(&data.callInfo, UNMAP_FOLDER, pClient);
+
+    data.root.type                      = VMMDevHGCMParmType_32bit;
+    data.root.u.value32                 = pMap->root;
+
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfUnmapFolder: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+        rc = data.callInfo.result;
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfCreate(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, PSHFLSTRING pParsedPath, PSHFLCREATEPARMS pCreateParms)
+{
+    /** @todo copy buffers to physical or mapped memory. */
+    int rc;
+    VBoxSFCreate data;
+
+    VBOX_INIT_CALL(&data.callInfo, CREATE, pClient);
+
+    data.root.type                    = VMMDevHGCMParmType_32bit;
+    data.root.u.value32               = pMap->root;
+
+    data.path.type                    = VMMDevHGCMParmType_LinAddr;
+    data.path.u.Pointer.size          = ShflStringSizeOfBuffer (pParsedPath);
+    data.path.u.Pointer.u.linearAddr  = (uintptr_t)pParsedPath;
+
+    data.parms.type                   = VMMDevHGCMParmType_LinAddr;
+    data.parms.u.Pointer.size         = sizeof(SHFLCREATEPARMS);
+    data.parms.u.Pointer.u.linearAddr = (uintptr_t)pCreateParms;
+
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfCreate: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+        rc = data.callInfo.result;
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfClose(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE Handle)
+{
+    int rc;
+    VBoxSFClose data;
+
+    VBOX_INIT_CALL(&data.callInfo, CLOSE, pClient);
+
+    data.root.type                      = VMMDevHGCMParmType_32bit;
+    data.root.u.value32                 = pMap->root;
+
+    data.handle.type                    = VMMDevHGCMParmType_64bit;
+    data.handle.u.value64               = Handle;
+
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfClose: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+        rc = data.callInfo.result;
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfRemove(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, PSHFLSTRING pParsedPath, uint32_t flags)
+{
+    int rc = VINF_SUCCESS;
+
+    VBoxSFRemove data;
+
+    VBOX_INIT_CALL(&data.callInfo, REMOVE, pClient);
+
+    data.root.type                      = VMMDevHGCMParmType_32bit;
+    data.root.u.value32                 = pMap->root;
+
+    data.path.type                      = VMMDevHGCMParmType_LinAddr_In;
+    data.path.u.Pointer.size            = ShflStringSizeOfBuffer(pParsedPath);
+    data.path.u.Pointer.u.linearAddr    = (uintptr_t)pParsedPath;
+
+    data.flags.type                     = VMMDevHGCMParmType_32bit;
+    data.flags.u.value32                = flags;
+
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfRemove: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS (rc))
+        rc = data.callInfo.result;
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfRename(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, PSHFLSTRING pSrcPath, PSHFLSTRING pDestPath, uint32_t flags)
+{
+    int rc;
+    VBoxSFRename data;
+
+    VBOX_INIT_CALL(&data.callInfo, RENAME, pClient);
+
+    data.root.type                      = VMMDevHGCMParmType_32bit;
+    data.root.u.value32                 = pMap->root;
+
+    data.src.type                       = VMMDevHGCMParmType_LinAddr_In;
+    data.src.u.Pointer.size             = ShflStringSizeOfBuffer(pSrcPath);
+    data.src.u.Pointer.u.linearAddr     = (uintptr_t)pSrcPath;
+
+    data.dest.type                      = VMMDevHGCMParmType_LinAddr_In;
+    data.dest.u.Pointer.size            = ShflStringSizeOfBuffer(pDestPath);
+    data.dest.u.Pointer.u.linearAddr    = (uintptr_t)pDestPath;
+
+    data.flags.type                     = VMMDevHGCMParmType_32bit;
+    data.flags.u.value32                = flags;
+
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfRename: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS (rc))
+        rc = data.callInfo.result;
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfRead(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
+                           uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer, bool fLocked)
+{
+    int rc;
+    VBoxSFRead data;
+
+    VBOX_INIT_CALL(&data.callInfo, READ, pClient);
+
+    data.root.type                      = VMMDevHGCMParmType_32bit;
+    data.root.u.value32                 = pMap->root;
+
+    data.handle.type                    = VMMDevHGCMParmType_64bit;
+    data.handle.u.value64               = hFile;
+    data.offset.type                    = VMMDevHGCMParmType_64bit;
+    data.offset.u.value64               = offset;
+    data.cb.type                        = VMMDevHGCMParmType_32bit;
+    data.cb.u.value32                   = *pcbBuffer;
+    data.buffer.type                    = (fLocked) ? VMMDevHGCMParmType_LinAddr_Locked_Out : VMMDevHGCMParmType_LinAddr_Out;
+    data.buffer.u.Pointer.size          = *pcbBuffer;
+    data.buffer.u.Pointer.u.linearAddr  = (uintptr_t)pBuffer;
+
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfRead: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+    {
+        rc = data.callInfo.result;
+        *pcbBuffer = data.cb.u.value32;
+    }
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfReadPageList(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile, uint64_t offset, uint32_t *pcbBuffer,
+                                   uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages)
+{
+    uint32_t            cbToRead  = *pcbBuffer;
+    uint32_t            cbData    = (uint32_t)(sizeof(VBoxSFRead) + RT_UOFFSETOF(HGCMPageListInfo, aPages[cPages]));
+    VBoxSFRead         *pData     = (VBoxSFRead *)RTMemTmpAlloc(cbData);
+    HGCMPageListInfo   *pPgLst    = (HGCMPageListInfo *)(pData + 1);
+    uint16_t            iPage;
+    int                 rc;
+
+    if (RT_UNLIKELY(!pData))
+        return VERR_NO_TMP_MEMORY;
+
+    VBOX_INIT_CALL(&pData->callInfo, READ, pClient);
+
+    pData->root.type                      = VMMDevHGCMParmType_32bit;
+    pData->root.u.value32                 = pMap->root;
+
+    pData->handle.type                    = VMMDevHGCMParmType_64bit;
+    pData->handle.u.value64               = hFile;
+    pData->offset.type                    = VMMDevHGCMParmType_64bit;
+    pData->offset.u.value64               = offset;
+    pData->cb.type                        = VMMDevHGCMParmType_32bit;
+    pData->cb.u.value32                   = cbToRead;
+    pData->buffer.type                    = VMMDevHGCMParmType_PageList;
+    pData->buffer.u.PageList.size         = cbToRead;
+    pData->buffer.u.PageList.offset       = sizeof(VBoxSFRead);
+
+    pPgLst->flags = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
+    pPgLst->offFirstPage = offFirstPage;
+    pPgLst->cPages = cPages;
+    for (iPage = 0; iPage < cPages; iPage++)
+        pPgLst->aPages[iPage] = paPages[iPage];
+
+    rc = VbglHGCMCall(pClient->handle, &pData->callInfo, cbData);
+/*    Log(("VBOXSF: VbglR0SfReadPageList: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+    {
+        rc = pData->callInfo.result;
+        *pcbBuffer = pData->cb.u.value32;
+    }
+
+    RTMemTmpFree(pData);
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfWrite(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
+                            uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer, bool fLocked)
+{
+    int rc;
+    VBoxSFWrite data;
+
+    VBOX_INIT_CALL(&data.callInfo, WRITE, pClient);
+
+    data.root.type                      = VMMDevHGCMParmType_32bit;
+    data.root.u.value32                 = pMap->root;
+
+    data.handle.type                    = VMMDevHGCMParmType_64bit;
+    data.handle.u.value64               = hFile;
+    data.offset.type                    = VMMDevHGCMParmType_64bit;
+    data.offset.u.value64               = offset;
+    data.cb.type                        = VMMDevHGCMParmType_32bit;
+    data.cb.u.value32                   = *pcbBuffer;
+    data.buffer.type                    = fLocked ? VMMDevHGCMParmType_LinAddr_Locked_In : VMMDevHGCMParmType_LinAddr_In;
+    data.buffer.u.Pointer.size          = *pcbBuffer;
+    data.buffer.u.Pointer.u.linearAddr  = (uintptr_t)pBuffer;
+
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfWrite: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+    {
+        rc = data.callInfo.result;
+        *pcbBuffer = data.cb.u.value32;
+    }
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfWritePhysCont(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile, uint64_t offset,
+                                    uint32_t *pcbBuffer, RTCCPHYS PhysBuffer)
+{
+    uint32_t            cbToWrite = *pcbBuffer;
+    uint32_t            cPages    = RT_ALIGN_32((PhysBuffer & PAGE_OFFSET_MASK) + cbToWrite, PAGE_SIZE) >> PAGE_SHIFT;
+    uint32_t            cbData    = (uint32_t)(sizeof(VBoxSFWrite) + RT_UOFFSETOF(HGCMPageListInfo, aPages[cPages]));
+    VBoxSFWrite        *pData     = (VBoxSFWrite *)RTMemTmpAlloc(cbData);
+    HGCMPageListInfo   *pPgLst    = (HGCMPageListInfo *)(pData + 1);
+    uint32_t            iPage;
+    int                 rc;
+
+    if (RT_UNLIKELY(!pData))
+        return VERR_NO_TMP_MEMORY;
+
+    VBOX_INIT_CALL(&pData->callInfo, WRITE, pClient);
+
+    pData->root.type                      = VMMDevHGCMParmType_32bit;
+    pData->root.u.value32                 = pMap->root;
+
+    pData->handle.type                    = VMMDevHGCMParmType_64bit;
+    pData->handle.u.value64               = hFile;
+    pData->offset.type                    = VMMDevHGCMParmType_64bit;
+    pData->offset.u.value64               = offset;
+    pData->cb.type                        = VMMDevHGCMParmType_32bit;
+    pData->cb.u.value32                   = cbToWrite;
+    pData->buffer.type                    = VMMDevHGCMParmType_PageList;
+    pData->buffer.u.PageList.size         = cbToWrite;
+    pData->buffer.u.PageList.offset       = sizeof(VBoxSFWrite);
+
+    pPgLst->flags = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+    pPgLst->offFirstPage = (uint16_t)(PhysBuffer & PAGE_OFFSET_MASK);
+    pPgLst->cPages = cPages;
+    PhysBuffer &= ~(RTCCPHYS)PAGE_OFFSET_MASK;
+    for (iPage = 0; iPage < cPages; iPage++, PhysBuffer += PAGE_SIZE)
+        pPgLst->aPages[iPage] = PhysBuffer;
+
+    rc = VbglHGCMCall(pClient->handle, &pData->callInfo, cbData);
+/*    Log(("VBOXSF: VbglR0SfWritePhysCont: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+    {
+        rc = pData->callInfo.result;
+        *pcbBuffer = pData->cb.u.value32;
+    }
+
+    RTMemTmpFree(pData);
+    return rc;
+
+}
+
+DECLVBGL(int) VbglR0SfWritePageList(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile, uint64_t offset, uint32_t *pcbBuffer,
+                                    uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages)
+{
+    uint32_t            cbToWrite = *pcbBuffer;
+    uint32_t            cbData    = (uint32_t)(sizeof(VBoxSFWrite) + RT_UOFFSETOF(HGCMPageListInfo, aPages[cPages]));
+    VBoxSFWrite        *pData     = (VBoxSFWrite *)RTMemTmpAlloc(cbData);
+    HGCMPageListInfo   *pPgLst    = (HGCMPageListInfo *)(pData + 1);
+    uint16_t            iPage;
+    int                 rc;
+
+    if (RT_UNLIKELY(!pData))
+        return VERR_NO_TMP_MEMORY;
+
+    VBOX_INIT_CALL(&pData->callInfo, WRITE, pClient);
+
+    pData->root.type                      = VMMDevHGCMParmType_32bit;
+    pData->root.u.value32                 = pMap->root;
+
+    pData->handle.type                    = VMMDevHGCMParmType_64bit;
+    pData->handle.u.value64               = hFile;
+    pData->offset.type                    = VMMDevHGCMParmType_64bit;
+    pData->offset.u.value64               = offset;
+    pData->cb.type                        = VMMDevHGCMParmType_32bit;
+    pData->cb.u.value32                   = cbToWrite;
+    pData->buffer.type                    = VMMDevHGCMParmType_PageList;
+    pData->buffer.u.PageList.size         = cbToWrite;
+    pData->buffer.u.PageList.offset       = sizeof(VBoxSFWrite);
+
+    pPgLst->flags = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+    pPgLst->offFirstPage = offFirstPage;
+    pPgLst->cPages = cPages;
+    for (iPage = 0; iPage < cPages; iPage++)
+        pPgLst->aPages[iPage] = paPages[iPage];
+
+    rc = VbglHGCMCall(pClient->handle, &pData->callInfo, cbData);
+/*    Log(("VBOXSF: VbglR0SfWritePageList: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+    {
+        rc = pData->callInfo.result;
+        *pcbBuffer = pData->cb.u.value32;
+    }
+
+    RTMemTmpFree(pData);
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfFlush(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile)
+{
+    int rc;
+    VBoxSFFlush data;
+
+    VBOX_INIT_CALL(&data.callInfo, FLUSH, pClient);
+
+    data.root.type                      = VMMDevHGCMParmType_32bit;
+    data.root.u.value32                 = pMap->root;
+
+    data.handle.type                    = VMMDevHGCMParmType_64bit;
+    data.handle.u.value64               = hFile;
+
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfFlush: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+        rc = data.callInfo.result;
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfDirInfo(
+    PVBGLSFCLIENT pClient,
+    PVBGLSFMAP pMap,
+    SHFLHANDLE hFile,
+    PSHFLSTRING ParsedPath,
+    uint32_t flags,
+    uint32_t index,
+    uint32_t *pcbBuffer,
+    PSHFLDIRINFO pBuffer,
+    uint32_t *pcFiles)
+{
+    int rc;
+    VBoxSFList data;
+
+    VBOX_INIT_CALL(&data.callInfo, LIST, pClient);
+
+    data.root.type                      = VMMDevHGCMParmType_32bit;
+    data.root.u.value32                 = pMap->root;
+
+    data.handle.type                    = VMMDevHGCMParmType_64bit;
+    data.handle.u.value64               = hFile;
+    data.flags.type                     = VMMDevHGCMParmType_32bit;
+    data.flags.u.value32                = flags;
+    data.cb.type                        = VMMDevHGCMParmType_32bit;
+    data.cb.u.value32                   = *pcbBuffer;
+    data.path.type                      = VMMDevHGCMParmType_LinAddr_In;
+    data.path.u.Pointer.size            = ParsedPath ? ShflStringSizeOfBuffer(ParsedPath) : 0;
+    data.path.u.Pointer.u.linearAddr    = (uintptr_t) ParsedPath;
+
+    data.buffer.type                    = VMMDevHGCMParmType_LinAddr_Out;
+    data.buffer.u.Pointer.size          = *pcbBuffer;
+    data.buffer.u.Pointer.u.linearAddr  = (uintptr_t)pBuffer;
+
+    data.resumePoint.type               = VMMDevHGCMParmType_32bit;
+    data.resumePoint.u.value32          = index;
+    data.cFiles.type                    = VMMDevHGCMParmType_32bit;
+    data.cFiles.u.value32               = 0; /* out parameters only */
+
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfDirInfo: rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+        rc = data.callInfo.result;
+    *pcbBuffer = data.cb.u.value32;
+    *pcFiles   = data.cFiles.u.value32;
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfFsInfo(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
+                             uint32_t flags, uint32_t *pcbBuffer, PSHFLDIRINFO pBuffer)
+{
+    int rc;
+    VBoxSFInformation data;
+
+    VBOX_INIT_CALL(&data.callInfo, INFORMATION, pClient);
+
+    data.root.type                      = VMMDevHGCMParmType_32bit;
+    data.root.u.value32                 = pMap->root;
+
+    data.handle.type                    = VMMDevHGCMParmType_64bit;
+    data.handle.u.value64               = hFile;
+    data.flags.type                     = VMMDevHGCMParmType_32bit;
+    data.flags.u.value32                = flags;
+    data.cb.type                        = VMMDevHGCMParmType_32bit;
+    data.cb.u.value32                   = *pcbBuffer;
+    data.info.type                      = VMMDevHGCMParmType_LinAddr;
+    data.info.u.Pointer.size            = *pcbBuffer;
+    data.info.u.Pointer.u.linearAddr    = (uintptr_t)pBuffer;
+
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfFsInfo: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+    {
+        rc = data.callInfo.result;
+        *pcbBuffer = data.cb.u.value32;
+    }
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfLock(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
+                           uint64_t offset, uint64_t cbSize, uint32_t fLock)
+{
+    int rc;
+    VBoxSFLock data;
+
+    VBOX_INIT_CALL(&data.callInfo, LOCK, pClient);
+
+    data.root.type                      = VMMDevHGCMParmType_32bit;
+    data.root.u.value32                 = pMap->root;
+
+    data.handle.type                    = VMMDevHGCMParmType_64bit;
+    data.handle.u.value64               = hFile;
+    data.offset.type                    = VMMDevHGCMParmType_64bit;
+    data.offset.u.value64               = offset;
+    data.length.type                    = VMMDevHGCMParmType_64bit;
+    data.length.u.value64               = cbSize;
+
+    data.flags.type                     = VMMDevHGCMParmType_32bit;
+    data.flags.u.value32                = fLock;
+
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfLock: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS (rc))
+        rc = data.callInfo.result;
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfSetUtf8(PVBGLSFCLIENT pClient)
+{
+    int rc;
+    VBoxGuestHGCMCallInfo callInfo;
+
+    VBOX_INIT_CALL(&callInfo, SET_UTF8, pClient);
+    rc = VbglHGCMCall(pClient->handle, &callInfo, sizeof(callInfo));
+/*    Log(("VBOXSF: VbglR0SfSetUtf8: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+        rc = callInfo.result;
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfReadLink(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, PSHFLSTRING pParsedPath, uint32_t cbBuffer, uint8_t *pBuffer)
+{
+    int rc;
+    VBoxSFReadLink data;
+
+    VBOX_INIT_CALL(&data.callInfo, READLINK, pClient);
+
+    data.root.type                      = VMMDevHGCMParmType_32bit;
+    data.root.u.value32                 = pMap->root;
+
+    data.path.type                      = VMMDevHGCMParmType_LinAddr_In;
+    data.path.u.Pointer.size            = ShflStringSizeOfBuffer (pParsedPath);
+    data.path.u.Pointer.u.linearAddr    = (uintptr_t)pParsedPath;
+
+    data.buffer.type                    = VMMDevHGCMParmType_LinAddr_Out;
+    data.buffer.u.Pointer.size          = cbBuffer;
+    data.buffer.u.Pointer.u.linearAddr  = (uintptr_t)pBuffer;
+
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfReadLink: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS (rc))
+        rc = data.callInfo.result;
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfSymlink(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, PSHFLSTRING pNewPath, PSHFLSTRING pOldPath,
+                              PSHFLFSOBJINFO pBuffer)
+{
+    int rc;
+    VBoxSFSymlink data;
+
+    VBOX_INIT_CALL(&data.callInfo, SYMLINK, pClient);
+
+    data.root.type                      = VMMDevHGCMParmType_32bit;
+    data.root.u.value32                 = pMap->root;
+
+    data.newPath.type                   = VMMDevHGCMParmType_LinAddr_In;
+    data.newPath.u.Pointer.size         = ShflStringSizeOfBuffer (pNewPath);
+    data.newPath.u.Pointer.u.linearAddr = (uintptr_t)pNewPath;
+
+    data.oldPath.type                   = VMMDevHGCMParmType_LinAddr_In;
+    data.oldPath.u.Pointer.size         = ShflStringSizeOfBuffer (pOldPath);
+    data.oldPath.u.Pointer.u.linearAddr = (uintptr_t)pOldPath;
+
+    data.info.type                      = VMMDevHGCMParmType_LinAddr_Out;
+    data.info.u.Pointer.size            = sizeof(SHFLFSOBJINFO);
+    data.info.u.Pointer.u.linearAddr    = (uintptr_t)pBuffer;
+
+    rc = VbglHGCMCall(pClient->handle, &data.callInfo, sizeof(data));
+/*    Log(("VBOXSF: VbglR0SfSymlink: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS (rc))
+        rc = data.callInfo.result;
+    return rc;
+}
+
+DECLVBGL(int) VbglR0SfSetSymlinks(PVBGLSFCLIENT pClient)
+{
+    int rc;
+    VBoxGuestHGCMCallInfo callInfo;
+
+    VBOX_INIT_CALL(&callInfo, SET_SYMLINKS, pClient);
+    rc = VbglHGCMCall(pClient->handle, &callInfo, sizeof(callInfo));
+/*    Log(("VBOXSF: VbglR0SfSetSymlinks: VbglHGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.result)); */
+    if (RT_SUCCESS(rc))
+        rc = callInfo.result;
+    return rc;
+}
+
+
+#endif /* !VBGL_VBOXGUEST */
diff --git a/ubuntu/vbox/vboxsf/VMMDev.c b/ubuntu/vbox/vboxsf/VMMDev.c
new file mode 100644 (file)
index 0000000..cbd9326
--- /dev/null
@@ -0,0 +1,43 @@
+/* $Id: VMMDev.cpp $ */
+/** @file
+ * VBoxGuestLibR0 - VMMDev device related functions.
+ */
+
+/*
+ * 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.
+ */
+
+#include "VBGLInternal.h"
+
+
+DECLVBGL(int) VbglQueryVMMDevMemory(VMMDevMemory **ppVMMDevMemory)
+{
+    int rc = vbglR0Enter();
+    if (RT_FAILURE(rc))
+        return rc;
+
+    /* If the memory was not found, return an error. */
+    if (!g_vbgldata.pVMMDevMemory)
+        return VERR_NOT_SUPPORTED;
+
+    *ppVMMDevMemory = g_vbgldata.pVMMDevMemory;
+    return rc;
+}
+
diff --git a/ubuntu/vbox/vboxsf/VbglR0CanUsePhysPageList.c b/ubuntu/vbox/vboxsf/VbglR0CanUsePhysPageList.c
new file mode 100644 (file)
index 0000000..f8e195c
--- /dev/null
@@ -0,0 +1,44 @@
+/* $Id: VbglR0CanUsePhysPageList.cpp $ */
+/** @file
+ * VBoxGuestLibR0 - Physical memory heap.
+ */
+
+/*
+ * 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.
+ */
+
+#include "VBGLInternal.h"
+
+
+/**
+ * Checks whether the host supports physical page lists or not.
+ *
+ * @returns true if it does, false if it doesn't.
+ */
+DECLR0VBGL(bool) VbglR0CanUsePhysPageList(void)
+{
+    /* a_fLocked is false, because the actual capability of the host is requested.
+     * See VBGLR0_CAN_USE_PHYS_PAGE_LIST definition.
+     */
+    int rc = vbglR0Enter();
+    return RT_SUCCESS(rc)
+        && VBGLR0_CAN_USE_PHYS_PAGE_LIST(/*a_fLocked =*/ false);
+}
+
diff --git a/ubuntu/vbox/vboxsf/dirops.c b/ubuntu/vbox/vboxsf/dirops.c
new file mode 100644 (file)
index 0000000..0267b0b
--- /dev/null
@@ -0,0 +1,903 @@
+/** @file
+ *
+ * vboxsf -- VirtualBox Guest Additions for Linux:
+ * Directory inode and file operations
+ */
+
+/*
+ * 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.
+ */
+
+#include "vfsmod.h"
+
+/**
+ * Open a directory. Read the complete content into a buffer.
+ *
+ * @param inode     inode
+ * @param file      file
+ * @returns 0 on success, Linux error code otherwise
+ */
+static int sf_dir_open(struct inode *inode, struct file *file)
+{
+    int rc;
+    int err;
+    struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
+    struct sf_dir_info *sf_d;
+    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
+    SHFLCREATEPARMS params;
+
+    TRACE();
+    BUG_ON(!sf_g);
+    BUG_ON(!sf_i);
+
+    if (file->private_data)
+    {
+        LogFunc(("sf_dir_open() called on already opened directory '%s'\n",
+                sf_i->path->String.utf8));
+        return 0;
+    }
+
+    sf_d = sf_dir_info_alloc();
+    if (!sf_d)
+    {
+        LogRelFunc(("could not allocate directory info for '%s'\n",
+                    sf_i->path->String.utf8));
+        return -ENOMEM;
+    }
+
+    RT_ZERO(params);
+    params.Handle = SHFL_HANDLE_NIL;
+    params.CreateFlags = 0
+                       | SHFL_CF_DIRECTORY
+                       | SHFL_CF_ACT_OPEN_IF_EXISTS
+                       | SHFL_CF_ACT_FAIL_IF_NEW
+                       | SHFL_CF_ACCESS_READ
+                       ;
+
+    LogFunc(("sf_dir_open(): calling VbglR0SfCreate, folder %s, flags %#x\n",
+             sf_i->path->String.utf8, params.CreateFlags));
+    rc = VbglR0SfCreate(&client_handle, &sf_g->map, sf_i->path, &params);
+    if (RT_SUCCESS(rc))
+    {
+        if (params.Result == SHFL_FILE_EXISTS)
+        {
+            err = sf_dir_read_all(sf_g, sf_i, sf_d, params.Handle);
+            if (!err)
+                file->private_data = sf_d;
+        }
+        else
+            err = -ENOENT;
+
+        rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle);
+        if (RT_FAILURE(rc))
+            LogFunc(("sf_dir_open(): VbglR0SfClose(%s) after err=%d failed rc=%Rrc\n",
+                     sf_i->path->String.utf8, err, rc));
+    }
+    else
+        err = -EPERM;
+
+    if (err)
+        sf_dir_info_free(sf_d);
+
+    return err;
+}
+
+
+/**
+ * This is called when reference count of [file] goes to zero. Notify
+ * the host that it can free whatever is associated with this directory
+ * and deallocate our own internal buffers
+ *
+ * @param inode     inode
+ * @param file      file
+ * returns 0 on success, Linux error code otherwise
+ */
+static int sf_dir_release(struct inode *inode, struct file *file)
+{
+    TRACE();
+
+    if (file->private_data)
+        sf_dir_info_free(file->private_data);
+
+    return 0;
+}
+
+/**
+ * Translate RTFMODE into DT_xxx (in conjunction to rtDirType())
+ * @param fMode     file mode
+ * returns d_type
+ */
+static int sf_get_d_type(RTFMODE fMode)
+{
+    int d_type;
+    switch (fMode & RTFS_TYPE_MASK)
+    {
+        case RTFS_TYPE_FIFO:      d_type = DT_FIFO;    break;
+        case RTFS_TYPE_DEV_CHAR:  d_type = DT_CHR;     break;
+        case RTFS_TYPE_DIRECTORY: d_type = DT_DIR;     break;
+        case RTFS_TYPE_DEV_BLOCK: d_type = DT_BLK;     break;
+        case RTFS_TYPE_FILE:      d_type = DT_REG;     break;
+        case RTFS_TYPE_SYMLINK:   d_type = DT_LNK;     break;
+        case RTFS_TYPE_SOCKET:    d_type = DT_SOCK;    break;
+        case RTFS_TYPE_WHITEOUT:  d_type = DT_WHT;     break;
+        default:                  d_type = DT_UNKNOWN; break;
+    }
+    return d_type;
+}
+
+/**
+ * Extract element ([dir]->f_pos) from the directory [dir] into [d_name].
+ *
+ * @returns 0 for success, 1 for end reached, Linux error code otherwise.
+ */
+static int sf_getdent(struct file *dir, char d_name[NAME_MAX], int *d_type)
+{
+    loff_t cur;
+    struct sf_glob_info *sf_g;
+    struct sf_dir_info *sf_d;
+    struct sf_inode_info *sf_i;
+    struct inode *inode;
+    struct list_head *pos, *list;
+
+    TRACE();
+
+    inode = GET_F_DENTRY(dir)->d_inode;
+    sf_i = GET_INODE_INFO(inode);
+    sf_g = GET_GLOB_INFO(inode->i_sb);
+    sf_d = dir->private_data;
+
+    BUG_ON(!sf_g);
+    BUG_ON(!sf_d);
+    BUG_ON(!sf_i);
+
+    if (sf_i->force_reread)
+    {
+        int rc;
+        int err;
+        SHFLCREATEPARMS params;
+
+        RT_ZERO(params);
+        params.Handle = SHFL_HANDLE_NIL;
+        params.CreateFlags = 0
+                           | SHFL_CF_DIRECTORY
+                           | SHFL_CF_ACT_OPEN_IF_EXISTS
+                           | SHFL_CF_ACT_FAIL_IF_NEW
+                           | SHFL_CF_ACCESS_READ
+                           ;
+
+        LogFunc(("sf_getdent: calling VbglR0SfCreate, folder %s, flags %#x\n",
+                  sf_i->path->String.utf8, params.CreateFlags));
+        rc = VbglR0SfCreate(&client_handle, &sf_g->map, sf_i->path, &params);
+        if (RT_FAILURE(rc))
+        {
+            LogFunc(("VbglR0SfCreate(%s) failed rc=%Rrc\n",
+                        sf_i->path->String.utf8, rc));
+            return -EPERM;
+        }
+
+        if (params.Result != SHFL_FILE_EXISTS)
+        {
+            LogFunc(("directory %s does not exist\n", sf_i->path->String.utf8));
+            sf_dir_info_free(sf_d);
+            return -ENOENT;
+        }
+
+        sf_dir_info_empty(sf_d);
+        err = sf_dir_read_all(sf_g, sf_i, sf_d, params.Handle);
+        rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle);
+        if (RT_FAILURE(rc))
+            LogFunc(("VbglR0SfClose(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc));
+        if (err)
+            return err;
+
+        sf_i->force_reread = 0;
+    }
+
+    cur = 0;
+    list = &sf_d->info_list;
+    list_for_each(pos, list)
+    {
+        struct sf_dir_buf *b;
+        SHFLDIRINFO *info;
+        loff_t i;
+
+        b = list_entry(pos, struct sf_dir_buf, head);
+        if (dir->f_pos >= cur + b->cEntries)
+        {
+            cur += b->cEntries;
+            continue;
+        }
+
+        for (i = 0, info = b->buf; i < dir->f_pos - cur; ++i)
+        {
+            size_t size;
+
+            size = offsetof(SHFLDIRINFO, name.String) + info->name.u16Size;
+            info = (SHFLDIRINFO *) ((uintptr_t) info + size);
+        }
+
+        *d_type = sf_get_d_type(info->Info.Attr.fMode);
+
+        return sf_nlscpy(sf_g, d_name, NAME_MAX,
+                         info->name.String.utf8, info->name.u16Length);
+    }
+
+    return 1;
+}
+
+/**
+ * This is called when vfs wants to populate internal buffers with
+ * directory [dir]s contents. [opaque] is an argument to the
+ * [filldir]. [filldir] magically modifies it's argument - [opaque]
+ * and takes following additional arguments (which i in turn get from
+ * the host via sf_getdent):
+ *
+ * name : name of the entry (i must also supply it's length huh?)
+ * type : type of the entry (FILE | DIR | etc) (i ellect to use DT_UNKNOWN)
+ * pos : position/index of the entry
+ * ino : inode number of the entry (i fake those)
+ *
+ * [dir] contains:
+ * f_pos : cursor into the directory listing
+ * private_data : mean of communication with the host side
+ *
+ * Extract elements from the directory listing (incrementing f_pos
+ * along the way) and feed them to [filldir] until:
+ *
+ * a. there are no more entries (i.e. sf_getdent set done to 1)
+ * b. failure to compute fake inode number
+ * c. filldir returns an error (see comment on that)
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+static int sf_dir_iterate(struct file *dir, struct dir_context *ctx)
+#else
+static int sf_dir_read(struct file *dir, void *opaque, filldir_t filldir)
+#endif
+{
+    TRACE();
+    for (;;)
+    {
+        int err;
+        ino_t fake_ino;
+        loff_t sanity;
+        char d_name[NAME_MAX];
+        int d_type = DT_UNKNOWN;
+
+        err = sf_getdent(dir, d_name, &d_type);
+        switch (err)
+        {
+            case 1:
+                return 0;
+
+            case 0:
+                break;
+
+            case -1:
+            default:
+                /* skip erroneous entry and proceed */
+                LogFunc(("sf_getdent error %d\n", err));
+                dir->f_pos += 1;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+                ctx->pos += 1;
+#endif
+                continue;
+        }
+
+        /* d_name now contains a valid entry name */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+        sanity = ctx->pos + 0xbeef;
+#else
+        sanity = dir->f_pos + 0xbeef;
+#endif
+        fake_ino = sanity;
+        if (sanity - fake_ino)
+        {
+            LogRelFunc(("can not compute ino\n"));
+            return -EINVAL;
+        }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+        if (!dir_emit(ctx, d_name, strlen(d_name), fake_ino, d_type))
+        {
+            LogFunc(("dir_emit failed\n"));
+            return 0;
+        }
+#else
+        err = filldir(opaque, d_name, strlen(d_name), dir->f_pos, fake_ino, d_type);
+        if (err)
+        {
+            LogFunc(("filldir returned error %d\n", err));
+            /* Rely on the fact that filldir returns error
+               only when it runs out of space in opaque */
+            return 0;
+        }
+#endif
+
+        dir->f_pos += 1;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+        ctx->pos += 1;
+#endif
+    }
+
+    BUG();
+}
+
+struct file_operations sf_dir_fops =
+{
+    .open    = sf_dir_open,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+    .iterate = sf_dir_iterate,
+#else
+    .readdir = sf_dir_read,
+#endif
+    .release = sf_dir_release,
+    .read    = generic_read_dir
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+  , .llseek  = generic_file_llseek
+#endif
+};
+
+
+/* iops */
+
+/**
+ * This is called when vfs failed to locate dentry in the cache. The
+ * job of this function is to allocate inode and link it to dentry.
+ * [dentry] contains the name to be looked in the [parent] directory.
+ * Failure to locate the name is not a "hard" error, in this case NULL
+ * inode is added to [dentry] and vfs should proceed trying to create
+ * the entry via other means. NULL(or "positive" pointer) ought to be
+ * returned in case of success and "negative" pointer on error
+ */
+static struct dentry *sf_lookup(struct inode *parent, struct dentry *dentry
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+                                , unsigned int flags
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+                                , struct nameidata *nd
+#endif
+                               )
+{
+    int err;
+    struct sf_inode_info *sf_i, *sf_new_i;
+    struct sf_glob_info *sf_g;
+    SHFLSTRING *path;
+    struct inode *inode;
+    ino_t ino;
+    SHFLFSOBJINFO fsinfo;
+
+    TRACE();
+    sf_g = GET_GLOB_INFO(parent->i_sb);
+    sf_i = GET_INODE_INFO(parent);
+
+    BUG_ON(!sf_g);
+    BUG_ON(!sf_i);
+
+    err = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path);
+    if (err)
+        goto fail0;
+
+    err = sf_stat(__func__, sf_g, path, &fsinfo, 1);
+    if (err)
+    {
+        if (err == -ENOENT)
+        {
+            /* -ENOENT: add NULL inode to dentry so it later can be
+               created via call to create/mkdir/open */
+            kfree(path);
+            inode = NULL;
+        }
+        else
+            goto fail1;
+    }
+    else
+    {
+        sf_new_i = kmalloc(sizeof(*sf_new_i), GFP_KERNEL);
+        if (!sf_new_i)
+        {
+            LogRelFunc(("could not allocate memory for new inode info\n"));
+            err = -ENOMEM;
+            goto fail1;
+        }
+        sf_new_i->handle = SHFL_HANDLE_NIL;
+        sf_new_i->force_reread = 0;
+
+        ino = iunique(parent->i_sb, 1);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
+        inode = iget_locked(parent->i_sb, ino);
+#else
+        inode = iget(parent->i_sb, ino);
+#endif
+        if (!inode)
+        {
+            LogFunc(("iget failed\n"));
+            err = -ENOMEM;          /* XXX: ??? */
+            goto fail2;
+        }
+
+        SET_INODE_INFO(inode, sf_new_i);
+        sf_init_inode(sf_g, inode, &fsinfo);
+        sf_new_i->path = path;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
+        unlock_new_inode(inode);
+#endif
+    }
+
+    sf_i->force_restat = 0;
+    dentry->d_time = jiffies;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+    d_set_d_op(dentry, &sf_dentry_ops);
+#else
+    dentry->d_op = &sf_dentry_ops;
+#endif
+    d_add(dentry, inode);
+    return NULL;
+
+fail2:
+    kfree(sf_new_i);
+
+fail1:
+    kfree(path);
+
+fail0:
+    return ERR_PTR(err);
+}
+
+/**
+ * This should allocate memory for sf_inode_info, compute a unique inode
+ * number, get an inode from vfs, initialize inode info, instantiate
+ * dentry.
+ *
+ * @param parent        inode entry of the directory
+ * @param dentry        directory cache entry
+ * @param path          path name
+ * @param info          file information
+ * @param handle        handle
+ * @returns 0 on success, Linux error code otherwise
+ */
+static int sf_instantiate(struct inode *parent, struct dentry *dentry,
+                          SHFLSTRING *path, PSHFLFSOBJINFO info, SHFLHANDLE handle)
+{
+    int err;
+    ino_t ino;
+    struct inode *inode;
+    struct sf_inode_info *sf_new_i;
+    struct sf_glob_info *sf_g = GET_GLOB_INFO(parent->i_sb);
+
+    TRACE();
+    BUG_ON(!sf_g);
+
+    sf_new_i = kmalloc(sizeof(*sf_new_i), GFP_KERNEL);
+    if (!sf_new_i)
+    {
+        LogRelFunc(("could not allocate inode info.\n"));
+        err = -ENOMEM;
+        goto fail0;
+    }
+
+    ino = iunique(parent->i_sb, 1);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
+    inode = iget_locked(parent->i_sb, ino);
+#else
+    inode = iget(parent->i_sb, ino);
+#endif
+    if (!inode)
+    {
+        LogFunc(("iget failed\n"));
+        err = -ENOMEM;
+        goto fail1;
+    }
+
+    sf_init_inode(sf_g, inode, info);
+    sf_new_i->path = path;
+    SET_INODE_INFO(inode, sf_new_i);
+    sf_new_i->force_restat = 1;
+    sf_new_i->force_reread = 0;
+
+    d_instantiate(dentry, inode);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
+    unlock_new_inode(inode);
+#endif
+
+    /* Store this handle if we leave the handle open. */
+    sf_new_i->handle = handle;
+    return 0;
+
+fail1:
+    kfree(sf_new_i);
+
+fail0:
+    return err;
+
+}
+
+/**
+ * Create a new regular file / directory.
+ *
+ * @param parent        inode of the directory
+ * @param dentry        directory cache entry
+ * @param mode          file mode
+ * @param fDirectory    true if directory, false otherwise
+ * @returns 0 on success, Linux error code otherwise
+ */
+static int sf_create_aux(struct inode *parent, struct dentry *dentry,
+                         umode_t mode, int fDirectory)
+{
+    int rc, err;
+    SHFLCREATEPARMS params;
+    SHFLSTRING *path;
+    struct sf_inode_info *sf_i = GET_INODE_INFO(parent);
+    struct sf_glob_info *sf_g = GET_GLOB_INFO(parent->i_sb);
+
+    TRACE();
+    BUG_ON(!sf_i);
+    BUG_ON(!sf_g);
+
+    err = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path);
+    if (err)
+        goto fail0;
+
+    RT_ZERO(params);
+    params.Handle = SHFL_HANDLE_NIL;
+    params.CreateFlags = 0
+                       | SHFL_CF_ACT_CREATE_IF_NEW
+                       | SHFL_CF_ACT_FAIL_IF_EXISTS
+                       | SHFL_CF_ACCESS_READWRITE
+                       | (fDirectory ? SHFL_CF_DIRECTORY : 0)
+                       ;
+    params.Info.Attr.fMode = 0
+                           | (fDirectory ? RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE)
+                           | (mode & S_IRWXUGO)
+                           ;
+    params.Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING;
+
+    LogFunc(("sf_create_aux: calling VbglR0SfCreate, folder %s, flags %#x\n",
+              path->String.utf8, params.CreateFlags));
+    rc = VbglR0SfCreate(&client_handle, &sf_g->map, path, &params);
+    if (RT_FAILURE(rc))
+    {
+        if (rc == VERR_WRITE_PROTECT)
+        {
+            err = -EROFS;
+            goto fail1;
+        }
+        err = -EPROTO;
+        LogFunc(("(%d): VbglR0SfCreate(%s) failed rc=%Rrc\n",
+                    fDirectory, sf_i->path->String.utf8, rc));
+        goto fail1;
+    }
+
+    if (params.Result != SHFL_FILE_CREATED)
+    {
+        err = -EPERM;
+        LogFunc(("(%d): could not create file %s result=%d\n",
+                    fDirectory, sf_i->path->String.utf8, params.Result));
+        goto fail1;
+    }
+
+    err = sf_instantiate(parent, dentry, path, &params.Info,
+                         fDirectory ? SHFL_HANDLE_NIL : params.Handle);
+    if (err)
+    {
+        LogFunc(("(%d): could not instantiate dentry for %s err=%d\n",
+                    fDirectory, sf_i->path->String.utf8, err));
+        goto fail2;
+    }
+
+    /*
+     * Don't close this handle right now. We assume that the same file is
+     * opened with sf_reg_open() and later closed with sf_reg_close(). Save
+     * the handle in between. Does not apply to directories. True?
+     */
+    if (fDirectory)
+    {
+        rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle);
+        if (RT_FAILURE(rc))
+            LogFunc(("(%d): VbglR0SfClose failed rc=%Rrc\n", fDirectory, rc));
+    }
+
+    sf_i->force_restat = 1;
+    return 0;
+
+fail2:
+    rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle);
+    if (RT_FAILURE(rc))
+        LogFunc(("(%d): VbglR0SfClose failed rc=%Rrc\n", fDirectory, rc));
+
+fail1:
+    kfree(path);
+
+fail0:
+    return err;
+}
+
+/**
+ * Create a new regular file.
+ *
+ * @param parent        inode of the directory
+ * @param dentry        directory cache entry
+ * @param mode          file mode
+ * @param excl          Possible O_EXCL...
+ * @returns 0 on success, Linux error code otherwise
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(DOXYGEN_RUNNING)
+static int sf_create(struct inode *parent, struct dentry *dentry, umode_t mode, bool excl)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+static int sf_create(struct inode *parent, struct dentry *dentry, umode_t mode, struct nameidata *nd)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+static int sf_create(struct inode *parent, struct dentry *dentry, int mode, struct nameidata *nd)
+#else
+static int sf_create(struct inode *parent, struct dentry *dentry, int mode)
+#endif
+{
+    TRACE();
+    return sf_create_aux(parent, dentry, mode, 0);
+}
+
+/**
+ * Create a new directory.
+ *
+ * @param parent        inode of the directory
+ * @param dentry        directory cache entry
+ * @param mode          file mode
+ * @returns 0 on success, Linux error code otherwise
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+static int sf_mkdir(struct inode *parent, struct dentry *dentry, umode_t mode)
+#else
+static int sf_mkdir(struct inode *parent, struct dentry *dentry, int mode)
+#endif
+{
+    TRACE();
+    return sf_create_aux(parent, dentry, mode, 1);
+}
+
+/**
+ * Remove a regular file / directory.
+ *
+ * @param parent        inode of the directory
+ * @param dentry        directory cache entry
+ * @param fDirectory    true if directory, false otherwise
+ * @returns 0 on success, Linux error code otherwise
+ */
+static int sf_unlink_aux(struct inode *parent, struct dentry *dentry, int fDirectory)
+{
+    int rc, err;
+    struct sf_glob_info *sf_g = GET_GLOB_INFO(parent->i_sb);
+    struct sf_inode_info *sf_i = GET_INODE_INFO(parent);
+    SHFLSTRING *path;
+    uint32_t fFlags;
+
+    TRACE();
+    BUG_ON(!sf_g);
+
+    err = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path);
+    if (err)
+        goto fail0;
+
+    fFlags = fDirectory ? SHFL_REMOVE_DIR : SHFL_REMOVE_FILE;
+    if (   dentry
+        && dentry->d_inode
+        && ((dentry->d_inode->i_mode & S_IFLNK) == S_IFLNK))
+        fFlags |= SHFL_REMOVE_SYMLINK;
+    rc = VbglR0SfRemove(&client_handle, &sf_g->map, path, fFlags);
+    if (RT_FAILURE(rc))
+    {
+        LogFunc(("(%d): VbglR0SfRemove(%s) failed rc=%Rrc\n", fDirectory, path->String.utf8, rc));
+        err = -RTErrConvertToErrno(rc);
+        goto fail1;
+    }
+
+    /* directory access/change time changed */
+    sf_i->force_restat = 1;
+    /* directory content changed */
+    sf_i->force_reread = 1;
+
+    err = 0;
+
+fail1:
+    kfree(path);
+
+fail0:
+    return err;
+}
+
+/**
+ * Remove a regular file.
+ *
+ * @param parent        inode of the directory
+ * @param dentry        directory cache entry
+ * @returns 0 on success, Linux error code otherwise
+ */
+static int sf_unlink(struct inode *parent, struct dentry *dentry)
+{
+    TRACE();
+    return sf_unlink_aux(parent, dentry, 0);
+}
+
+/**
+ * Remove a directory.
+ *
+ * @param parent        inode of the directory
+ * @param dentry        directory cache entry
+ * @returns 0 on success, Linux error code otherwise
+ */
+static int sf_rmdir(struct inode *parent, struct dentry *dentry)
+{
+    TRACE();
+    return sf_unlink_aux(parent, dentry, 1);
+}
+
+/**
+ * Rename a regular file / directory.
+ *
+ * @param old_parent    inode of the old parent directory
+ * @param old_dentry    old directory cache entry
+ * @param new_parent    inode of the new parent directory
+ * @param new_dentry    new directory cache entry
+ * @param flags         flags
+ * @returns 0 on success, Linux error code otherwise
+ */
+static int sf_rename(struct inode *old_parent, struct dentry *old_dentry,
+                     struct inode *new_parent, struct dentry *new_dentry
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
+                     , unsigned flags
+#endif
+                     )
+{
+    int err = 0, rc = VINF_SUCCESS;
+    struct sf_glob_info *sf_g = GET_GLOB_INFO(old_parent->i_sb);
+
+    TRACE();
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
+    if (flags)
+    {
+        LogFunc(("rename with flags=%x\n", flags));
+        return -EINVAL;
+    }
+#endif
+
+    if (sf_g != GET_GLOB_INFO(new_parent->i_sb))
+    {
+        LogFunc(("rename with different roots\n"));
+        err = -EINVAL;
+    }
+    else
+    {
+        struct sf_inode_info *sf_old_i = GET_INODE_INFO(old_parent);
+        struct sf_inode_info *sf_new_i = GET_INODE_INFO(new_parent);
+        /* As we save the relative path inside the inode structure, we need to change
+           this if the rename is successful. */
+        struct sf_inode_info *sf_file_i = GET_INODE_INFO(old_dentry->d_inode);
+        SHFLSTRING *old_path;
+        SHFLSTRING *new_path;
+
+        BUG_ON(!sf_old_i);
+        BUG_ON(!sf_new_i);
+        BUG_ON(!sf_file_i);
+
+        old_path = sf_file_i->path;
+        err = sf_path_from_dentry(__func__, sf_g, sf_new_i,
+                                  new_dentry, &new_path);
+        if (err)
+            LogFunc(("failed to create new path\n"));
+        else
+        {
+            int fDir = ((old_dentry->d_inode->i_mode & S_IFDIR) != 0);
+
+            rc = VbglR0SfRename(&client_handle, &sf_g->map, old_path,
+                                new_path, fDir ? 0 : SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS);
+            if (RT_SUCCESS(rc))
+            {
+                kfree(old_path);
+                sf_new_i->force_restat = 1;
+                sf_old_i->force_restat = 1; /* XXX: needed? */
+                /* Set the new relative path in the inode. */
+                sf_file_i->path = new_path;
+            }
+            else
+            {
+                LogFunc(("VbglR0SfRename failed rc=%Rrc\n", rc));
+                err = -RTErrConvertToErrno(rc);
+                kfree(new_path);
+            }
+        }
+    }
+    return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+static int sf_symlink(struct inode *parent, struct dentry *dentry, const char *symname)
+{
+    int err;
+    int rc;
+    struct sf_inode_info *sf_i;
+    struct sf_glob_info *sf_g;
+    SHFLSTRING *path, *ssymname;
+    SHFLFSOBJINFO info;
+    int symname_len = strlen(symname) + 1;
+
+    TRACE();
+    sf_g = GET_GLOB_INFO(parent->i_sb);
+    sf_i = GET_INODE_INFO(parent);
+
+    BUG_ON(!sf_g);
+    BUG_ON(!sf_i);
+
+    err = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path);
+    if (err)
+        goto fail0;
+
+    ssymname = kmalloc(offsetof(SHFLSTRING, String.utf8) + symname_len, GFP_KERNEL);
+    if (!ssymname)
+    {
+        LogRelFunc(("kmalloc failed, caller=sf_symlink\n"));
+        err = -ENOMEM;
+        goto fail1;
+    }
+
+    ssymname->u16Length = symname_len - 1;
+    ssymname->u16Size = symname_len;
+    memcpy(ssymname->String.utf8, symname, symname_len);
+
+    rc = VbglR0SfSymlink(&client_handle, &sf_g->map, path, ssymname, &info);
+    kfree(ssymname);
+
+    if (RT_FAILURE(rc))
+    {
+        if (rc == VERR_WRITE_PROTECT)
+        {
+            err = -EROFS;
+            goto fail1;
+        }
+        LogFunc(("VbglR0SfSymlink(%s) failed rc=%Rrc\n",
+                    sf_i->path->String.utf8, rc));
+        err = -EPROTO;
+        goto fail1;
+    }
+
+    err = sf_instantiate(parent, dentry, path, &info, SHFL_HANDLE_NIL);
+    if (err)
+    {
+        LogFunc(("could not instantiate dentry for %s err=%d\n",
+                 sf_i->path->String.utf8, err));
+        goto fail1;
+    }
+
+    sf_i->force_restat = 1;
+    return 0;
+
+fail1:
+    kfree(path);
+fail0:
+    return err;
+}
+#endif
+
+struct inode_operations sf_dir_iops =
+{
+    .lookup     = sf_lookup,
+    .create     = sf_create,
+    .mkdir      = sf_mkdir,
+    .rmdir      = sf_rmdir,
+    .unlink     = sf_unlink,
+    .rename     = sf_rename,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+    .revalidate = sf_inode_revalidate
+#else
+    .getattr    = sf_getattr,
+    .setattr    = sf_setattr,
+    .symlink    = sf_symlink
+#endif
+};
diff --git a/ubuntu/vbox/vboxsf/divdi3.c b/ubuntu/vbox/vboxsf/divdi3.c
new file mode 100644 (file)
index 0000000..eecc17a
--- /dev/null
@@ -0,0 +1,70 @@
+/*     $NetBSD: divdi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $      */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)divdi3.c   8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: divdi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $");
+#endif
+#endif*/ /* LIBC_SCCS and not lint */
+
+#include "quad.h"
+
+/*
+ * Divide two signed quads.
+ * ??? if -1/2 should produce -1 on this machine, this code is wrong
+ */
+quad_t
+__divdi3(a, b)
+       quad_t a, b;
+{
+       u_quad_t ua, ub, uq;
+       int neg = 0;
+
+       ua = a;
+       ub = b;
+
+       if (a < 0)
+               ua = -ua, neg ^= 1;
+       if (b < 0)
+               ub = -ub, neg ^= 1;
+
+       uq = __qdivrem(ua, ub, (u_quad_t *)0);
+       if (neg)
+               uq = - uq;
+       return uq;
+}
diff --git a/ubuntu/vbox/vboxsf/include b/ubuntu/vbox/vboxsf/include
new file mode 120000 (symlink)
index 0000000..f5030fe
--- /dev/null
@@ -0,0 +1 @@
+../include
\ No newline at end of file
diff --git a/ubuntu/vbox/vboxsf/lnkops.c b/ubuntu/vbox/vboxsf/lnkops.c
new file mode 100644 (file)
index 0000000..e43b84c
--- /dev/null
@@ -0,0 +1,107 @@
+/** @file
+ *
+ * vboxsf -- VirtualBox Guest Additions for Linux:
+ * Operations for symbolic links.
+ */
+
+/*
+ * Copyright (C) 2010-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.
+ */
+
+#include "vfsmod.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+
+# if LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)
+#  if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+static const char *sf_follow_link(struct dentry *dentry, void **cookie)
+#  else
+static void *sf_follow_link(struct dentry *dentry, struct nameidata *nd)
+#  endif
+{
+    struct inode *inode = dentry->d_inode;
+    struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
+    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
+    int error = -ENOMEM;
+    char *path = (char*)get_zeroed_page(GFP_KERNEL);
+    int rc;
+
+    if (path)
+    {
+        error = 0;
+        rc = VbglR0SfReadLink(&client_handle, &sf_g->map, sf_i->path, PATH_MAX, path);
+        if (RT_FAILURE(rc))
+        {
+            LogFunc(("VbglR0SfReadLink failed, caller=%s, rc=%Rrc\n", __func__, rc));
+            free_page((unsigned long)path);
+            error = -EPROTO;
+        }
+    }
+#  if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+    return error ? ERR_PTR(error) : (*cookie = path);
+#  else
+    nd_set_link(nd, error ? ERR_PTR(error) : path);
+    return NULL;
+#  endif
+}
+
+#  if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
+static void sf_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
+{
+    char *page = nd_get_link(nd);
+    if (!IS_ERR(page))
+        free_page((unsigned long)page);
+}
+#  endif
+
+# else /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) */
+static const char *sf_get_link(struct dentry *dentry, struct inode *inode,
+                               struct delayed_call *done)
+{
+    struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
+    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
+    char *path;
+    int rc;
+
+    if (!dentry)
+        return ERR_PTR(-ECHILD);
+    path = kzalloc(PAGE_SIZE, GFP_KERNEL);
+    if (!path)
+        return ERR_PTR(-ENOMEM);
+    rc = VbglR0SfReadLink(&client_handle, &sf_g->map, sf_i->path, PATH_MAX, path);
+    if (RT_FAILURE(rc))
+    {
+        LogFunc(("VbglR0SfReadLink failed, caller=%s, rc=%Rrc\n", __func__, rc));
+        kfree(path);
+        return ERR_PTR(-EPROTO);
+    }
+    set_delayed_call(done, kfree_link, path);
+    return path;
+}
+# endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0) */
+
+struct inode_operations sf_lnk_iops =
+{
+# if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
+    .readlink       = generic_readlink,
+# endif
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+    .get_link       = sf_get_link
+# elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+    .follow_link    = sf_follow_link,
+    .put_link       = free_page_put_link,
+# else
+    .follow_link    = sf_follow_link,
+    .put_link       = sf_put_link
+# endif
+};
+
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */
diff --git a/ubuntu/vbox/vboxsf/moddi3.c b/ubuntu/vbox/vboxsf/moddi3.c
new file mode 100644 (file)
index 0000000..764ea01
--- /dev/null
@@ -0,0 +1,70 @@
+/*     $NetBSD: moddi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $      */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)moddi3.c   8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: moddi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $");
+#endif
+#endif*/ /* LIBC_SCCS and not lint */
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two signed quads.
+ *
+ * XXX we assume a % b < 0 iff a < 0, but this is actually machine-dependent.
+ */
+quad_t
+__moddi3(a, b)
+       quad_t a, b;
+{
+       u_quad_t ua, ub, ur;
+       int neg = 0;
+
+       ua = a;
+       ub = b;
+
+       if (a < 0)
+               ua = -ua, neg ^= 1;
+       if (b < 0)
+               ub = -ub;
+       (void)__qdivrem(ua, ub, &ur);
+       if (neg)
+               ur = -ur;
+       return (ur);
+}
diff --git a/ubuntu/vbox/vboxsf/product-generated.h b/ubuntu/vbox/vboxsf/product-generated.h
new file mode 100644 (file)
index 0000000..3fbe34a
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef ___product_generated_h___
+#define ___product_generated_h___
+
+#define VBOX_VENDOR "Oracle Corporation"
+#define VBOX_VENDOR_SHORT "Oracle"
+#define VBOX_PRODUCT "Oracle VM VirtualBox"
+#define VBOX_BUILD_PUBLISHER "_Ubuntu"
+#define VBOX_C_YEAR "2017"
+
+#endif
diff --git a/ubuntu/vbox/vboxsf/qdivrem.c b/ubuntu/vbox/vboxsf/qdivrem.c
new file mode 100644 (file)
index 0000000..7ca2d38
--- /dev/null
@@ -0,0 +1,285 @@
+/*     $NetBSD: qdivrem.c,v 1.12 2005/12/11 12:24:37 christos Exp $    */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)qdivrem.c  8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: qdivrem.c,v 1.12 2005/12/11 12:24:37 christos Exp $");
+#endif
+#endif*/ /* LIBC_SCCS and not lint */
+
+/*
+ * Multiprecision divide.  This algorithm is from Knuth vol. 2 (2nd ed),
+ * section 4.3.1, pp. 257--259.
+ */
+
+#include "quad.h"
+
+#define        B       ((int)1 << HALF_BITS)   /* digit base */
+
+/* Combine two `digits' to make a single two-digit number. */
+#define        COMBINE(a, b) (((u_int)(a) << HALF_BITS) | (b))
+
+/* select a type for digits in base B: use unsigned short if they fit */
+#if UINT_MAX == 0xffffffffU && USHRT_MAX >= 0xffff
+typedef unsigned short digit;
+#else
+typedef u_int digit;
+#endif
+
+static void shl __P((digit *p, int len, int sh));
+
+/*
+ * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
+ *
+ * We do this in base 2-sup-HALF_BITS, so that all intermediate products
+ * fit within u_int.  As a consequence, the maximum length dividend and
+ * divisor are 4 `digits' in this base (they are shorter if they have
+ * leading zeros).
+ */
+u_quad_t
+__qdivrem(uq, vq, arq)
+       u_quad_t uq, vq, *arq;
+{
+       union uu tmp;
+       digit *u, *v, *q;
+       digit v1, v2;
+       u_int qhat, rhat, t;
+       int m, n, d, j, i;
+       digit uspace[5], vspace[5], qspace[5];
+
+       /*
+        * Take care of special cases: divide by zero, and u < v.
+        */
+       if (vq == 0) {
+               /* divide by zero. */
+               static volatile const unsigned int zero = 0;
+
+               tmp.ul[H] = tmp.ul[L] = 1 / zero;
+               if (arq)
+                       *arq = uq;
+               return (tmp.q);
+       }
+       if (uq < vq) {
+               if (arq)
+                       *arq = uq;
+               return (0);
+       }
+       u = &uspace[0];
+       v = &vspace[0];
+       q = &qspace[0];
+
+       /*
+        * Break dividend and divisor into digits in base B, then
+        * count leading zeros to determine m and n.  When done, we
+        * will have:
+        *      u = (u[1]u[2]...u[m+n]) sub B
+        *      v = (v[1]v[2]...v[n]) sub B
+        *      v[1] != 0
+        *      1 < n <= 4 (if n = 1, we use a different division algorithm)
+        *      m >= 0 (otherwise u < v, which we already checked)
+        *      m + n = 4
+        * and thus
+        *      m = 4 - n <= 2
+        */
+       tmp.uq = uq;
+       u[0] = 0;
+       u[1] = (digit)HHALF(tmp.ul[H]);
+       u[2] = (digit)LHALF(tmp.ul[H]);
+       u[3] = (digit)HHALF(tmp.ul[L]);
+       u[4] = (digit)LHALF(tmp.ul[L]);
+       tmp.uq = vq;
+       v[1] = (digit)HHALF(tmp.ul[H]);
+       v[2] = (digit)LHALF(tmp.ul[H]);
+       v[3] = (digit)HHALF(tmp.ul[L]);
+       v[4] = (digit)LHALF(tmp.ul[L]);
+       for (n = 4; v[1] == 0; v++) {
+               if (--n == 1) {
+                       u_int rbj;      /* r*B+u[j] (not root boy jim) */
+                       digit q1, q2, q3, q4;
+
+                       /*
+                        * Change of plan, per exercise 16.
+                        *      r = 0;
+                        *      for j = 1..4:
+                        *              q[j] = floor((r*B + u[j]) / v),
+                        *              r = (r*B + u[j]) % v;
+                        * We unroll this completely here.
+                        */
+                       t = v[2];       /* nonzero, by definition */
+                       q1 = (digit)(u[1] / t);
+                       rbj = COMBINE(u[1] % t, u[2]);
+                       q2 = (digit)(rbj / t);
+                       rbj = COMBINE(rbj % t, u[3]);
+                       q3 = (digit)(rbj / t);
+                       rbj = COMBINE(rbj % t, u[4]);
+                       q4 = (digit)(rbj / t);
+                       if (arq)
+                               *arq = rbj % t;
+                       tmp.ul[H] = COMBINE(q1, q2);
+                       tmp.ul[L] = COMBINE(q3, q4);
+                       return (tmp.q);
+               }
+       }
+
+       /*
+        * By adjusting q once we determine m, we can guarantee that
+        * there is a complete four-digit quotient at &qspace[1] when
+        * we finally stop.
+        */
+       for (m = 4 - n; u[1] == 0; u++)
+               m--;
+       for (i = 4 - m; --i >= 0;)
+               q[i] = 0;
+       q += 4 - m;
+
+       /*
+        * Here we run Program D, translated from MIX to C and acquiring
+        * a few minor changes.
+        *
+        * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
+        */
+       d = 0;
+       for (t = v[1]; t < B / 2; t <<= 1)
+               d++;
+       if (d > 0) {
+               shl(&u[0], m + n, d);           /* u <<= d */
+               shl(&v[1], n - 1, d);           /* v <<= d */
+       }
+       /*
+        * D2: j = 0.
+        */
+       j = 0;
+       v1 = v[1];      /* for D3 -- note that v[1..n] are constant */
+       v2 = v[2];      /* for D3 */
+       do {
+               digit uj0, uj1, uj2;
+
+               /*
+                * D3: Calculate qhat (\^q, in TeX notation).
+                * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
+                * let rhat = (u[j]*B + u[j+1]) mod v[1].
+                * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
+                * decrement qhat and increase rhat correspondingly.
+                * Note that if rhat >= B, v[2]*qhat < rhat*B.
+                */
+               uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
+               uj1 = u[j + 1]; /* for D3 only */
+               uj2 = u[j + 2]; /* for D3 only */
+               if (uj0 == v1) {
+                       qhat = B;
+                       rhat = uj1;
+                       goto qhat_too_big;
+               } else {
+                       u_int nn = COMBINE(uj0, uj1);
+                       qhat = nn / v1;
+                       rhat = nn % v1;
+               }
+               while (v2 * qhat > COMBINE(rhat, uj2)) {
+       qhat_too_big:
+                       qhat--;
+                       if ((rhat += v1) >= B)
+                               break;
+               }
+               /*
+                * D4: Multiply and subtract.
+                * The variable `t' holds any borrows across the loop.
+                * We split this up so that we do not require v[0] = 0,
+                * and to eliminate a final special case.
+                */
+               for (t = 0, i = n; i > 0; i--) {
+                       t = u[i + j] - v[i] * qhat - t;
+                       u[i + j] = (digit)LHALF(t);
+                       t = (B - HHALF(t)) & (B - 1);
+               }
+               t = u[j] - t;
+               u[j] = (digit)LHALF(t);
+               /*
+                * D5: test remainder.
+                * There is a borrow if and only if HHALF(t) is nonzero;
+                * in that (rare) case, qhat was too large (by exactly 1).
+                * Fix it by adding v[1..n] to u[j..j+n].
+                */
+               if (HHALF(t)) {
+                       qhat--;
+                       for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
+                               t += u[i + j] + v[i];
+                               u[i + j] = (digit)LHALF(t);
+                               t = HHALF(t);
+                       }
+                       u[j] = (digit)LHALF(u[j] + t);
+               }
+               q[j] = (digit)qhat;
+       } while (++j <= m);             /* D7: loop on j. */
+
+       /*
+        * If caller wants the remainder, we have to calculate it as
+        * u[m..m+n] >> d (this is at most n digits and thus fits in
+        * u[m+1..m+n], but we may need more source digits).
+        */
+       if (arq) {
+               if (d) {
+                       for (i = m + n; i > m; --i)
+                               u[i] = (digit)(((u_int)u[i] >> d) |
+                                   LHALF((u_int)u[i - 1] << (HALF_BITS - d)));
+                       u[i] = 0;
+               }
+               tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
+               tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
+               *arq = tmp.q;
+       }
+
+       tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
+       tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
+       return (tmp.q);
+}
+
+/*
+ * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
+ * `fall out' the left (there never will be any such anyway).
+ * We may assume len >= 0.  NOTE THAT THIS WRITES len+1 DIGITS.
+ */
+static void
+shl(digit *p, int len, int sh)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               p[i] = (digit)(LHALF((u_int)p[i] << sh) |
+                   ((u_int)p[i + 1] >> (HALF_BITS - sh)));
+       p[i] = (digit)(LHALF((u_int)p[i] << sh));
+}
diff --git a/ubuntu/vbox/vboxsf/quad.h b/ubuntu/vbox/vboxsf/quad.h
new file mode 100644 (file)
index 0000000..ea9eb73
--- /dev/null
@@ -0,0 +1,165 @@
+/*     $NetBSD: quad.h,v 1.17 2005/12/11 12:24:37 christos Exp $       */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)quad.h      8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * Quad arithmetic.
+ *
+ * This library makes the following assumptions:
+ *
+ *  - The type long long (aka quad_t) exists.
+ *
+ *  - A quad variable is exactly twice as long as `int'.
+ *
+ *  - The machine's arithmetic is two's complement.
+ *
+ * This library can provide 128-bit arithmetic on a machine with 128-bit
+ * quads and 64-bit ints, for instance, or 96-bit arithmetic on machines
+ * with 48-bit ints.
+ */
+
+#if 0 /* iprt */
+#include <sys/types.h>
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#include <limits.h>
+#else
+#include <machine/limits.h>
+#endif
+#else /* iprt */
+# include <iprt/types.h>
+# include <iprt/nocrt/limits.h>
+# undef __P
+# define __P(a) a
+# undef __GNUC_PREREQ__
+# define __GNUC_PREREQ__(m1,m2) 1
+# if 1 /* ASSUMES: little endian */
+#  define _QUAD_HIGHWORD        1
+#  define _QUAD_LOWWORD         0
+# else
+#  define _QUAD_HIGHWORD        0
+#  define _QUAD_LOWWORD         1
+# endif
+# if !defined(RT_OS_LINUX) || !defined(__KERNEL__) /* (linux/types.h defines u_int) */
+   typedef unsigned int        u_int;
+# endif
+# if !defined(RT_OS_SOLARIS)
+   typedef int64_t quad_t;
+# else
+#  define quad_t int64_t
+# endif
+   typedef uint64_t u_quad_t;
+   typedef quad_t *qaddr_t;
+#endif /* iprt */
+
+/*
+ * Depending on the desired operation, we view a `long long' (aka quad_t) in
+ * one or more of the following formats.
+ */
+union uu {
+       quad_t  q;              /* as a (signed) quad */
+       u_quad_t uq;            /* as an unsigned quad */
+       int     sl[2];          /* as two signed ints */
+       u_int   ul[2];          /* as two unsigned ints */
+};
+
+/*
+ * Define high and low parts of a quad_t.
+ */
+#define        H               _QUAD_HIGHWORD
+#define        L               _QUAD_LOWWORD
+
+/*
+ * Total number of bits in a quad_t and in the pieces that make it up.
+ * These are used for shifting, and also below for halfword extraction
+ * and assembly.
+ */
+#define        QUAD_BITS       (sizeof(quad_t) * CHAR_BIT)
+#define        INT_BITS        (sizeof(int) * CHAR_BIT)
+#define        HALF_BITS       (sizeof(int) * CHAR_BIT / 2)
+
+/*
+ * Extract high and low shortwords from longword, and move low shortword of
+ * longword to upper half of long, i.e., produce the upper longword of
+ * ((quad_t)(x) << (number_of_bits_in_int/2)).  (`x' must actually be u_int.)
+ *
+ * These are used in the multiply code, to split a longword into upper
+ * and lower halves, and to reassemble a product as a quad_t, shifted left
+ * (sizeof(int)*CHAR_BIT/2).
+ */
+#define        HHALF(x)        ((u_int)(x) >> HALF_BITS)
+#define        LHALF(x)        ((u_int)(x) & (((int)1 << HALF_BITS) - 1))
+#define        LHUP(x)         ((u_int)(x) << HALF_BITS)
+
+/*
+ * XXX
+ * Compensate for gcc 1 vs gcc 2.  Gcc 1 defines ?sh?di3's second argument
+ * as u_quad_t, while gcc 2 correctly uses int.  Unfortunately, we still use
+ * both compilers.
+ */
+#if __GNUC_PREREQ__(2, 0) || defined(lint)
+typedef unsigned int   qshift_t;
+#else
+typedef u_quad_t       qshift_t;
+#endif
+
+RT_C_DECLS_BEGIN
+quad_t __adddi3 __P((quad_t, quad_t));
+quad_t __anddi3 __P((quad_t, quad_t));
+quad_t __ashldi3 __P((quad_t, qshift_t));
+quad_t __ashrdi3 __P((quad_t, qshift_t));
+int __cmpdi2 __P((quad_t, quad_t ));
+quad_t __divdi3 __P((quad_t, quad_t));
+quad_t __fixdfdi __P((double));
+quad_t __fixsfdi __P((float));
+u_quad_t __fixunsdfdi __P((double));
+u_quad_t __fixunssfdi __P((float));
+double __floatdidf __P((quad_t));
+float __floatdisf __P((quad_t));
+double __floatunsdidf __P((u_quad_t));
+quad_t __iordi3 __P((quad_t, quad_t));
+quad_t __lshldi3 __P((quad_t, qshift_t));
+quad_t __lshrdi3 __P((quad_t, qshift_t));
+quad_t __moddi3 __P((quad_t, quad_t));
+quad_t __muldi3 __P((quad_t, quad_t));
+quad_t __negdi2 __P((quad_t));
+quad_t __one_cmpldi2 __P((quad_t));
+u_quad_t __qdivrem __P((u_quad_t, u_quad_t, u_quad_t *));
+quad_t __subdi3 __P((quad_t, quad_t));
+int __ucmpdi2 __P((u_quad_t, u_quad_t));
+u_quad_t __udivdi3 __P((u_quad_t, u_quad_t ));
+u_quad_t __umoddi3 __P((u_quad_t, u_quad_t ));
+quad_t __xordi3 __P((quad_t, quad_t));
+RT_C_DECLS_END
diff --git a/ubuntu/vbox/vboxsf/r0drv b/ubuntu/vbox/vboxsf/r0drv
new file mode 120000 (symlink)
index 0000000..f93dcc2
--- /dev/null
@@ -0,0 +1 @@
+../r0drv
\ No newline at end of file
diff --git a/ubuntu/vbox/vboxsf/regops.c b/ubuntu/vbox/vboxsf/regops.c
new file mode 100644 (file)
index 0000000..3812462
--- /dev/null
@@ -0,0 +1,738 @@
+/* $Id: regops.c $ */
+/** @file
+ * vboxsf - VBox Linux Shared Folders, Regular file inode and file operations.
+ */
+
+/*
+ * 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.
+ */
+
+/*
+ * Limitations: only COW memory mapping is supported
+ */
+
+#include "vfsmod.h"
+
+static void *alloc_bounce_buffer(size_t *tmp_sizep, PRTCCPHYS physp, size_t
+                                 xfer_size, const char *caller)
+{
+    size_t tmp_size;
+    void *tmp;
+
+    /* try for big first. */
+    tmp_size = RT_ALIGN_Z(xfer_size, PAGE_SIZE);
+    if (tmp_size > 16U*_1K)
+        tmp_size = 16U*_1K;
+    tmp = kmalloc(tmp_size, GFP_KERNEL);
+    if (!tmp)
+    {
+        /* fall back on a page sized buffer. */
+        tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
+        if (!tmp)
+        {
+            LogRel(("%s: could not allocate bounce buffer for xfer_size=%zu %s\n", caller, xfer_size));
+            return NULL;
+        }
+        tmp_size = PAGE_SIZE;
+    }
+
+    *tmp_sizep = tmp_size;
+    *physp = virt_to_phys(tmp);
+    return tmp;
+}
+
+static void free_bounce_buffer(void *tmp)
+{
+    kfree (tmp);
+}
+
+
+/* fops */
+static int sf_reg_read_aux(const char *caller, struct sf_glob_info *sf_g,
+                           struct sf_reg_info *sf_r, void *buf,
+                           uint32_t *nread, uint64_t pos)
+{
+    /** @todo bird: yes, kmap() and kmalloc() input only. Since the buffer is
+     *        contiguous in physical memory (kmalloc or single page), we should
+     *        use a physical address here to speed things up. */
+    int rc = VbglR0SfRead(&client_handle, &sf_g->map, sf_r->handle,
+                          pos, nread, buf, false /* already locked? */);
+    if (RT_FAILURE(rc))
+    {
+        LogFunc(("VbglR0SfRead failed. caller=%s, rc=%Rrc\n", caller, rc));
+        return -EPROTO;
+    }
+    return 0;
+}
+
+static int sf_reg_write_aux(const char *caller, struct sf_glob_info *sf_g,
+                            struct sf_reg_info *sf_r, void *buf,
+                            uint32_t *nwritten, uint64_t pos)
+{
+    /** @todo bird: yes, kmap() and kmalloc() input only. Since the buffer is
+     *        contiguous in physical memory (kmalloc or single page), we should
+     *        use a physical address here to speed things up. */
+    int rc = VbglR0SfWrite(&client_handle, &sf_g->map, sf_r->handle,
+                           pos, nwritten, buf, false /* already locked? */);
+    if (RT_FAILURE(rc))
+    {
+        LogFunc(("VbglR0SfWrite failed. caller=%s, rc=%Rrc\n",
+                    caller, rc));
+        return -EPROTO;
+    }
+    return 0;
+}
+
+/**
+ * Read from a regular file.
+ *
+ * @param file          the file
+ * @param buf           the buffer
+ * @param size          length of the buffer
+ * @param off           offset within the file
+ * @returns the number of read bytes on success, Linux error code otherwise
+ */
+static ssize_t sf_reg_read(struct file *file, char *buf, size_t size, loff_t *off)
+{
+    int err;
+    void *tmp;
+    RTCCPHYS tmp_phys;
+    size_t tmp_size;
+    size_t left = size;
+    ssize_t total_bytes_read = 0;
+    struct inode *inode = GET_F_DENTRY(file)->d_inode;
+    struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
+    struct sf_reg_info *sf_r = file->private_data;
+    loff_t pos = *off;
+
+    TRACE();
+    if (!S_ISREG(inode->i_mode))
+    {
+        LogFunc(("read from non regular file %d\n", inode->i_mode));
+        return -EINVAL;
+    }
+
+    /** XXX Check read permission according to inode->i_mode! */
+
+    if (!size)
+        return 0;
+
+    tmp = alloc_bounce_buffer(&tmp_size, &tmp_phys, size, __PRETTY_FUNCTION__);
+    if (!tmp)
+        return -ENOMEM;
+
+    while (left)
+    {
+        uint32_t to_read, nread;
+
+        to_read = tmp_size;
+        if (to_read > left)
+            to_read = (uint32_t) left;
+
+        nread = to_read;
+
+        err = sf_reg_read_aux(__func__, sf_g, sf_r, tmp, &nread, pos);
+        if (err)
+            goto fail;
+
+        if (copy_to_user(buf, tmp, nread))
+        {
+            err = -EFAULT;
+            goto fail;
+        }
+
+        pos  += nread;
+        left -= nread;
+        buf  += nread;
+        total_bytes_read += nread;
+        if (nread != to_read)
+            break;
+    }
+
+    *off += total_bytes_read;
+    free_bounce_buffer(tmp);
+    return total_bytes_read;
+
+fail:
+    free_bounce_buffer(tmp);
+    return err;
+}
+
+/**
+ * Write to a regular file.
+ *
+ * @param file          the file
+ * @param buf           the buffer
+ * @param size          length of the buffer
+ * @param off           offset within the file
+ * @returns the number of written bytes on success, Linux error code otherwise
+ */
+static ssize_t sf_reg_write(struct file *file, const char *buf, size_t size, loff_t *off)
+{
+    int err;
+    void *tmp;
+    RTCCPHYS tmp_phys;
+    size_t tmp_size;
+    size_t left = size;
+    ssize_t total_bytes_written = 0;
+    struct inode *inode = GET_F_DENTRY(file)->d_inode;
+    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
+    struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
+    struct sf_reg_info *sf_r = file->private_data;
+    loff_t pos;
+
+    TRACE();
+    BUG_ON(!sf_i);
+    BUG_ON(!sf_g);
+    BUG_ON(!sf_r);
+
+    if (!S_ISREG(inode->i_mode))
+    {
+        LogFunc(("write to non regular file %d\n",  inode->i_mode));
+        return -EINVAL;
+    }
+
+    pos = *off;
+    if (file->f_flags & O_APPEND)
+    {
+        pos = inode->i_size;
+        *off = pos;
+    }
+
+    /** XXX Check write permission according to inode->i_mode! */
+
+    if (!size)
+        return 0;
+
+    tmp = alloc_bounce_buffer(&tmp_size, &tmp_phys, size, __PRETTY_FUNCTION__);
+    if (!tmp)
+        return -ENOMEM;
+
+    while (left)
+    {
+        uint32_t to_write, nwritten;
+
+        to_write = tmp_size;
+        if (to_write > left)
+            to_write = (uint32_t) left;
+
+        nwritten = to_write;
+
+        if (copy_from_user(tmp, buf, to_write))
+        {
+            err = -EFAULT;
+            goto fail;
+        }
+
+#if 1
+        if (VbglR0CanUsePhysPageList())
+        {
+            err = VbglR0SfWritePhysCont(&client_handle, &sf_g->map, sf_r->handle,
+                                        pos, &nwritten, tmp_phys);
+            err = RT_FAILURE(err) ? -EPROTO : 0;
+        }
+        else
+#endif
+            err = sf_reg_write_aux(__func__, sf_g, sf_r, tmp, &nwritten, pos);
+        if (err)
+            goto fail;
+
+        pos  += nwritten;
+        left -= nwritten;
+        buf  += nwritten;
+        total_bytes_written += nwritten;
+        if (nwritten != to_write)
+            break;
+    }
+
+    *off += total_bytes_written;
+    if (*off > inode->i_size)
+        inode->i_size = *off;
+
+    sf_i->force_restat = 1;
+    free_bounce_buffer(tmp);
+    return total_bytes_written;
+
+fail:
+    free_bounce_buffer(tmp);
+    return err;
+}
+
+/**
+ * Open a regular file.
+ *
+ * @param inode         the inode
+ * @param file          the file
+ * @returns 0 on success, Linux error code otherwise
+ */
+static int sf_reg_open(struct inode *inode, struct file *file)
+{
+    int rc, rc_linux = 0;
+    struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
+    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
+    struct sf_reg_info *sf_r;
+    SHFLCREATEPARMS params;
+
+    TRACE();
+    BUG_ON(!sf_g);
+    BUG_ON(!sf_i);
+
+    LogFunc(("open %s\n", sf_i->path->String.utf8));
+
+    sf_r = kmalloc(sizeof(*sf_r), GFP_KERNEL);
+    if (!sf_r)
+    {
+        LogRelFunc(("could not allocate reg info\n"));
+        return -ENOMEM;
+    }
+
+    /* Already open? */
+    if (sf_i->handle != SHFL_HANDLE_NIL)
+    {
+        /*
+         * This inode was created with sf_create_aux(). Check the CreateFlags:
+         * O_CREAT, O_TRUNC: inherent true (file was just created). Not sure
+         * about the access flags (SHFL_CF_ACCESS_*).
+         */
+        sf_i->force_restat = 1;
+        sf_r->handle = sf_i->handle;
+        sf_i->handle = SHFL_HANDLE_NIL;
+        sf_i->file = file;
+        file->private_data = sf_r;
+        return 0;
+    }
+
+    RT_ZERO(params);
+    params.Handle = SHFL_HANDLE_NIL;
+    /* We check the value of params.Handle afterwards to find out if
+     * the call succeeded or failed, as the API does not seem to cleanly
+     * distinguish error and informational messages.
+     *
+     * Furthermore, we must set params.Handle to SHFL_HANDLE_NIL to
+     * make the shared folders host service use our fMode parameter */
+
+    if (file->f_flags & O_CREAT)
+    {
+        LogFunc(("O_CREAT set\n"));
+        params.CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW;
+        /* We ignore O_EXCL, as the Linux kernel seems to call create
+           beforehand itself, so O_EXCL should always fail. */
+        if (file->f_flags & O_TRUNC)
+        {
+            LogFunc(("O_TRUNC set\n"));
+            params.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
+        }
+        else
+            params.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS;
+    }
+    else
+    {
+        params.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW;
+        if (file->f_flags & O_TRUNC)
+        {
+            LogFunc(("O_TRUNC set\n"));
+            params.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
+        }
+    }
+
+    switch (file->f_flags & O_ACCMODE)
+    {
+        case O_RDONLY:
+            params.CreateFlags |= SHFL_CF_ACCESS_READ;
+            break;
+
+        case O_WRONLY:
+            params.CreateFlags |= SHFL_CF_ACCESS_WRITE;
+            break;
+
+        case O_RDWR:
+            params.CreateFlags |= SHFL_CF_ACCESS_READWRITE;
+            break;
+
+        default:
+            BUG ();
+    }
+
+    if (file->f_flags & O_APPEND)
+    {
+        LogFunc(("O_APPEND set\n"));
+        params.CreateFlags |= SHFL_CF_ACCESS_APPEND;
+    }
+
+    params.Info.Attr.fMode = inode->i_mode;
+    LogFunc(("sf_reg_open: calling VbglR0SfCreate, file %s, flags=%#x, %#x\n",
+              sf_i->path->String.utf8 , file->f_flags, params.CreateFlags));
+    rc = VbglR0SfCreate(&client_handle, &sf_g->map, sf_i->path, &params);
+    if (RT_FAILURE(rc))
+    {
+        LogFunc(("VbglR0SfCreate failed flags=%d,%#x rc=%Rrc\n",
+                  file->f_flags, params.CreateFlags, rc));
+        kfree(sf_r);
+        return -RTErrConvertToErrno(rc);
+    }
+
+    if (SHFL_HANDLE_NIL == params.Handle)
+    {
+        switch (params.Result)
+        {
+            case SHFL_PATH_NOT_FOUND:
+            case SHFL_FILE_NOT_FOUND:
+                rc_linux = -ENOENT;
+                break;
+            case SHFL_FILE_EXISTS:
+                rc_linux = -EEXIST;
+                break;
+            default:
+                break;
+        }
+    }
+
+    sf_i->force_restat = 1;
+    sf_r->handle = params.Handle;
+    sf_i->file = file;
+    file->private_data = sf_r;
+    return rc_linux;
+}
+
+/**
+ * Close a regular file.
+ *
+ * @param inode         the inode
+ * @param file          the file
+ * @returns 0 on success, Linux error code otherwise
+ */
+static int sf_reg_release(struct inode *inode, struct file *file)
+{
+    int rc;
+    struct sf_reg_info *sf_r;
+    struct sf_glob_info *sf_g;
+    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
+
+    TRACE();
+    sf_g = GET_GLOB_INFO(inode->i_sb);
+    sf_r = file->private_data;
+
+    BUG_ON(!sf_g);
+    BUG_ON(!sf_r);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
+    /* See the smbfs source (file.c). mmap in particular can cause data to be
+     * written to the file after it is closed, which we can't cope with.  We
+     * copy and paste the body of filemap_write_and_wait() here as it was not
+     * defined before 2.6.6 and not exported until quite a bit later. */
+    /* filemap_write_and_wait(inode->i_mapping); */
+    if (   inode->i_mapping->nrpages
+        && filemap_fdatawrite(inode->i_mapping) != -EIO)
+        filemap_fdatawait(inode->i_mapping);
+#endif
+    rc = VbglR0SfClose(&client_handle, &sf_g->map, sf_r->handle);
+    if (RT_FAILURE(rc))
+        LogFunc(("VbglR0SfClose failed rc=%Rrc\n", rc));
+
+    kfree(sf_r);
+    sf_i->file = NULL;
+    sf_i->handle = SHFL_HANDLE_NIL;
+    file->private_data = NULL;
+    return 0;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+static int sf_reg_fault(struct vm_fault *vmf)
+#elif LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
+static int sf_reg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+static struct page *sf_reg_nopage(struct vm_area_struct *vma, unsigned long vaddr, int *type)
+# define SET_TYPE(t) *type = (t)
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */
+static struct page *sf_reg_nopage(struct vm_area_struct *vma, unsigned long vaddr, int unused)
+# define SET_TYPE(t)
+#endif
+{
+    struct page *page;
+    char *buf;
+    loff_t off;
+    uint32_t nread = PAGE_SIZE;
+    int err;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+    struct vm_area_struct *vma = vmf->vma;
+#endif
+    struct file *file = vma->vm_file;
+    struct inode *inode = GET_F_DENTRY(file)->d_inode;
+    struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
+    struct sf_reg_info *sf_r = file->private_data;
+
+    TRACE();
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
+    if (vmf->pgoff > vma->vm_end)
+        return VM_FAULT_SIGBUS;
+#else
+    if (vaddr > vma->vm_end)
+    {
+        SET_TYPE(VM_FAULT_SIGBUS);
+        return NOPAGE_SIGBUS;
+    }
+#endif
+
+    /* Don't use GFP_HIGHUSER as long as sf_reg_read_aux() calls VbglR0SfRead()
+     * which works on virtual addresses. On Linux cannot reliably determine the
+     * physical address for high memory, see rtR0MemObjNativeLockKernel(). */
+    page = alloc_page(GFP_USER);
+    if (!page) {
+        LogRelFunc(("failed to allocate page\n"));
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
+        return VM_FAULT_OOM;
+#else
+        SET_TYPE(VM_FAULT_OOM);
+        return NOPAGE_OOM;
+#endif
+    }
+
+    buf = kmap(page);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
+    off = (vmf->pgoff << PAGE_SHIFT);
+#else
+    off = (vaddr - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
+#endif
+    err = sf_reg_read_aux(__func__, sf_g, sf_r, buf, &nread, off);
+    if (err)
+    {
+        kunmap(page);
+        put_page(page);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
+        return VM_FAULT_SIGBUS;
+#else
+        SET_TYPE(VM_FAULT_SIGBUS);
+        return NOPAGE_SIGBUS;
+#endif
+    }
+
+    BUG_ON (nread > PAGE_SIZE);
+    if (!nread)
+    {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
+        clear_user_page(page_address(page), vmf->pgoff, page);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+        clear_user_page(page_address(page), vaddr, page);
+#else
+        clear_user_page(page_address(page), vaddr);
+#endif
+    }
+    else
+        memset(buf + nread, 0, PAGE_SIZE - nread);
+
+    flush_dcache_page(page);
+    kunmap(page);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
+    vmf->page = page;
+    return 0;
+#else
+    SET_TYPE(VM_FAULT_MAJOR);
+    return page;
+#endif
+}
+
+static struct vm_operations_struct sf_vma_ops =
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
+    .fault = sf_reg_fault
+#else
+    .nopage = sf_reg_nopage
+#endif
+};
+
+static int sf_reg_mmap(struct file *file, struct vm_area_struct *vma)
+{
+    TRACE();
+    if (vma->vm_flags & VM_SHARED)
+    {
+        LogFunc(("shared mmapping not available\n"));
+        return -EINVAL;
+    }
+
+    vma->vm_ops = &sf_vma_ops;
+    return 0;
+}
+
+struct file_operations sf_reg_fops =
+{
+    .read        = sf_reg_read,
+    .open        = sf_reg_open,
+    .write       = sf_reg_write,
+    .release     = sf_reg_release,
+    .mmap        = sf_reg_mmap,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
+    .splice_read = generic_file_splice_read,
+# else
+    .sendfile    = generic_file_sendfile,
+# endif
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+    .read_iter   = generic_file_read_iter,
+    .write_iter  = generic_file_write_iter,
+# else
+    .aio_read    = generic_file_aio_read,
+    .aio_write   = generic_file_aio_write,
+# endif
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+    .fsync       = noop_fsync,
+# else
+    .fsync       = simple_sync_file,
+# endif
+    .llseek      = generic_file_llseek,
+#endif
+};
+
+
+struct inode_operations sf_reg_iops =
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+    .revalidate = sf_inode_revalidate
+#else
+    .getattr    = sf_getattr,
+    .setattr    = sf_setattr
+#endif
+};
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+static int sf_readpage(struct file *file, struct page *page)
+{
+    struct inode *inode = GET_F_DENTRY(file)->d_inode;
+    struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
+    struct sf_reg_info *sf_r = file->private_data;
+    uint32_t nread = PAGE_SIZE;
+    char *buf;
+    loff_t off = ((loff_t)page->index) << PAGE_SHIFT;
+    int ret;
+
+    TRACE();
+
+    buf = kmap(page);
+    ret = sf_reg_read_aux(__func__, sf_g, sf_r, buf, &nread, off);
+    if (ret)
+    {
+        kunmap(page);
+        if (PageLocked(page))
+            unlock_page(page);
+        return ret;
+    }
+    BUG_ON(nread > PAGE_SIZE);
+    memset(&buf[nread], 0, PAGE_SIZE - nread);
+    flush_dcache_page(page);
+    kunmap(page);
+    SetPageUptodate(page);
+    unlock_page(page);
+    return 0;
+}
+
+static int
+sf_writepage(struct page *page, struct writeback_control *wbc)
+{
+    struct address_space *mapping = page->mapping;
+    struct inode *inode = mapping->host;
+    struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
+    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
+    struct file *file = sf_i->file;
+    struct sf_reg_info *sf_r = file->private_data;
+    char *buf;
+    uint32_t nwritten = PAGE_SIZE;
+    int end_index = inode->i_size >> PAGE_SHIFT;
+    loff_t off = ((loff_t) page->index) << PAGE_SHIFT;
+    int err;
+
+    TRACE();
+
+    if (page->index >= end_index)
+        nwritten = inode->i_size & (PAGE_SIZE-1);
+
+    buf = kmap(page);
+
+    err = sf_reg_write_aux(__func__, sf_g, sf_r, buf, &nwritten, off);
+    if (err < 0)
+    {
+        ClearPageUptodate(page);
+        goto out;
+    }
+
+    if (off > inode->i_size)
+        inode->i_size = off;
+
+    if (PageError(page))
+        ClearPageError(page);
+    err = 0;
+
+out:
+    kunmap(page);
+
+    unlock_page(page);
+    return err;
+}
+
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+int sf_write_begin(struct file *file, struct address_space *mapping, loff_t pos,
+                   unsigned len, unsigned flags, struct page **pagep, void **fsdata)
+{
+    TRACE();
+
+    return simple_write_begin(file, mapping, pos, len, flags, pagep, fsdata);
+}
+
+int sf_write_end(struct file *file, struct address_space *mapping, loff_t pos,
+                 unsigned len, unsigned copied, struct page *page, void *fsdata)
+{
+    struct inode *inode = mapping->host;
+    struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
+    struct sf_reg_info *sf_r = file->private_data;
+    void *buf;
+    unsigned from = pos & (PAGE_SIZE - 1);
+    uint32_t nwritten = len;
+    int err;
+
+    TRACE();
+
+    buf = kmap(page);
+    err = sf_reg_write_aux(__func__, sf_g, sf_r, buf+from, &nwritten, pos);
+    kunmap(page);
+
+    if (!PageUptodate(page) && err == PAGE_SIZE)
+        SetPageUptodate(page);
+
+    if (err >= 0) {
+        pos += nwritten;
+        if (pos > inode->i_size)
+            inode->i_size = pos;
+    }
+
+    unlock_page(page);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
+    put_page(page);
+#else
+    page_cache_release(page);
+#endif
+
+    return nwritten;
+}
+
+# endif /* KERNEL_VERSION >= 2.6.24 */
+
+struct address_space_operations sf_reg_aops =
+{
+    .readpage      = sf_readpage,
+    .writepage     = sf_writepage,
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+    .write_begin   = sf_write_begin,
+    .write_end     = sf_write_end,
+# else
+    .prepare_write = simple_prepare_write,
+    .commit_write  = simple_commit_write,
+# endif
+};
+#endif
diff --git a/ubuntu/vbox/vboxsf/revision-generated.h b/ubuntu/vbox/vboxsf/revision-generated.h
new file mode 100644 (file)
index 0000000..74247d9
--- /dev/null
@@ -0,0 +1 @@
+#define VBOX_SVN_REV 117968
diff --git a/ubuntu/vbox/vboxsf/udivdi3.c b/ubuntu/vbox/vboxsf/udivdi3.c
new file mode 100644 (file)
index 0000000..9069f4d
--- /dev/null
@@ -0,0 +1,56 @@
+/*     $NetBSD: udivdi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $     */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)udivdi3.c  8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: udivdi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $");
+#endif
+#endif*/ /* LIBC_SCCS and not lint */
+
+#include "quad.h"
+
+/*
+ * Divide two unsigned quads.
+ */
+u_quad_t
+__udivdi3(a, b)
+       u_quad_t a, b;
+{
+
+       return (__qdivrem(a, b, (u_quad_t *)0));
+}
diff --git a/ubuntu/vbox/vboxsf/udivmoddi4.c b/ubuntu/vbox/vboxsf/udivmoddi4.c
new file mode 100644 (file)
index 0000000..09b3f2b
--- /dev/null
@@ -0,0 +1,53 @@
+/* $Id: udivmoddi4.c $ */
+/** @file
+ * IPRT - __udivmoddi4 implementation
+ */
+
+/*
+ * 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.
+ */
+
+#include <iprt/stdint.h>
+#include <iprt/uint64.h>
+
+uint64_t __udivmoddi4(uint64_t u64A, uint64_t u64B, uint64_t *pu64R);
+
+/**
+ * __udivmoddi4() implementation to satisfy external references from 32-bit
+ * code generated by gcc-7 or later.
+ *
+ * @param   u64A        The divident value.
+ * @param   u64B        The divisor value.
+ * @param   pu64R       A pointer to the reminder. May be NULL.
+ * @returns u64A / u64B
+ */
+uint64_t __udivmoddi4(uint64_t u64A, uint64_t u64B, uint64_t *pu64R)
+{
+    RTUINT64U Divident;
+    RTUINT64U Divisor;
+    RTUINT64U Quotient;
+    RTUINT64U Reminder;
+    Divident.u = u64A;
+    Divisor.u  = u64B;
+    RTUInt64DivRem(&Quotient, &Reminder, &Divident, &Divisor);
+    if (pu64R)
+        *pu64R = Reminder.u;
+    return Quotient.u;
+}
diff --git a/ubuntu/vbox/vboxsf/umoddi3.c b/ubuntu/vbox/vboxsf/umoddi3.c
new file mode 100644 (file)
index 0000000..2e65eca
--- /dev/null
@@ -0,0 +1,58 @@
+/*     $NetBSD: umoddi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $     */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)umoddi3.c  8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: umoddi3.c,v 1.8 2005/12/11 12:24:37 christos Exp $");
+#endif
+#endif*/ /* LIBC_SCCS and not lint */
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two unsigned quads.
+ */
+u_quad_t
+__umoddi3(a, b)
+       u_quad_t a, b;
+{
+       u_quad_t r;
+
+       (void)__qdivrem(a, b, &r);
+       return (r);
+}
diff --git a/ubuntu/vbox/vboxsf/utils.c b/ubuntu/vbox/vboxsf/utils.c
new file mode 100644 (file)
index 0000000..22ff530
--- /dev/null
@@ -0,0 +1,907 @@
+/** @file
+ *
+ * vboxsf -- VirtualBox Guest Additions for Linux:
+ * Utility functions.
+ * Mainly conversion from/to VirtualBox/Linux data structures
+ */
+
+/*
+ * 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.
+ */
+
+#include "vfsmod.h"
+#include <iprt/asm.h>
+#include <linux/nfs_fs.h>
+#include <linux/vfs.h>
+
+/* #define USE_VMALLOC */
+
+/*
+ * sf_reg_aops and sf_backing_dev_info are just quick implementations to make
+ * sendfile work. For more information have a look at
+ *
+ *   http://us1.samba.org/samba/ftp/cifs-cvs/ols2006-fs-tutorial-smf.odp
+ *
+ * and the sample implementation
+ *
+ *   http://pserver.samba.org/samba/ftp/cifs-cvs/samplefs.tar.gz
+ */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+static void sf_ftime_from_timespec(time_t *time, RTTIMESPEC *ts)
+{
+    int64_t t = RTTimeSpecGetNano(ts);
+
+    do_div(t, 1000000000);
+    *time = t;
+}
+
+static void sf_timespec_from_ftime(RTTIMESPEC *ts, time_t *time)
+{
+    int64_t t = 1000000000 * *time;
+    RTTimeSpecSetNano(ts, t);
+}
+#else /* >= 2.6.0 */
+static void sf_ftime_from_timespec(struct timespec *tv, RTTIMESPEC *ts)
+{
+    int64_t t = RTTimeSpecGetNano(ts);
+    int64_t nsec;
+
+    nsec = do_div(t, 1000000000);
+    tv->tv_sec = t;
+    tv->tv_nsec = nsec;
+}
+
+static void sf_timespec_from_ftime(RTTIMESPEC *ts, struct timespec *tv)
+{
+    int64_t t = (int64_t)tv->tv_nsec + (int64_t)tv->tv_sec * 1000000000;
+    RTTimeSpecSetNano(ts, t);
+}
+#endif /* >= 2.6.0 */
+
+/* set [inode] attributes based on [info], uid/gid based on [sf_g] */
+void sf_init_inode(struct sf_glob_info *sf_g, struct inode *inode,
+                   PSHFLFSOBJINFO info)
+{
+    PSHFLFSOBJATTR attr;
+    int mode;
+
+    TRACE();
+
+    attr = &info->Attr;
+
+#define mode_set(r) attr->fMode & (RTFS_UNIX_##r) ? (S_##r) : 0;
+    mode  = mode_set(ISUID);
+    mode |= mode_set(ISGID);
+
+    mode |= mode_set(IRUSR);
+    mode |= mode_set(IWUSR);
+    mode |= mode_set(IXUSR);
+
+    mode |= mode_set(IRGRP);
+    mode |= mode_set(IWGRP);
+    mode |= mode_set(IXGRP);
+
+    mode |= mode_set(IROTH);
+    mode |= mode_set(IWOTH);
+    mode |= mode_set(IXOTH);
+
+#undef mode_set
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+    inode->i_mapping->a_ops = &sf_reg_aops;
+# if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0)
+    /* XXX Was this ever necessary? */
+    inode->i_mapping->backing_dev_info = &sf_g->bdi;
+# endif
+#endif
+
+    if (RTFS_IS_DIRECTORY(attr->fMode))
+    {
+        inode->i_mode  = sf_g->dmode != ~0 ? (sf_g->dmode & 0777) : mode;
+        inode->i_mode &= ~sf_g->dmask;
+        inode->i_mode |= S_IFDIR;
+        inode->i_op    = &sf_dir_iops;
+        inode->i_fop   = &sf_dir_fops;
+        /* XXX: this probably should be set to the number of entries
+           in the directory plus two (. ..) */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+        set_nlink(inode, 1);
+#else
+        inode->i_nlink = 1;
+#endif
+    }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+    else if (RTFS_IS_SYMLINK(attr->fMode))
+    {
+        inode->i_mode  = sf_g->fmode != ~0 ? (sf_g->fmode & 0777): mode;
+        inode->i_mode &= ~sf_g->fmask;
+        inode->i_mode |= S_IFLNK;
+        inode->i_op    = &sf_lnk_iops;
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+        set_nlink(inode, 1);
+# else
+        inode->i_nlink = 1;
+# endif
+    }
+#endif
+    else
+    {
+        inode->i_mode  = sf_g->fmode != ~0 ? (sf_g->fmode & 0777): mode;
+        inode->i_mode &= ~sf_g->fmask;
+        inode->i_mode |= S_IFREG;
+        inode->i_op    = &sf_reg_iops;
+        inode->i_fop   = &sf_reg_fops;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+        set_nlink(inode, 1);
+#else
+        inode->i_nlink = 1;
+#endif
+    }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+    inode->i_uid = make_kuid(current_user_ns(), sf_g->uid);
+    inode->i_gid = make_kgid(current_user_ns(), sf_g->gid);
+#else
+    inode->i_uid = sf_g->uid;
+    inode->i_gid = sf_g->gid;
+#endif
+
+    inode->i_size = info->cbObject;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) && !defined(KERNEL_FC6)
+    inode->i_blksize = 4096;
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 11)
+    inode->i_blkbits = 12;
+#endif
+    /* i_blocks always in units of 512 bytes! */
+    inode->i_blocks = (info->cbAllocated + 511) / 512;
+
+    sf_ftime_from_timespec(&inode->i_atime, &info->AccessTime);
+    sf_ftime_from_timespec(&inode->i_ctime, &info->ChangeTime);
+    sf_ftime_from_timespec(&inode->i_mtime, &info->ModificationTime);
+}
+
+int sf_stat(const char *caller, struct sf_glob_info *sf_g,
+            SHFLSTRING *path, PSHFLFSOBJINFO result, int ok_to_fail)
+{
+    int rc;
+    SHFLCREATEPARMS params;
+    NOREF(caller);
+
+    TRACE();
+
+    RT_ZERO(params);
+    params.Handle = SHFL_HANDLE_NIL;
+    params.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
+    LogFunc(("sf_stat: calling VbglR0SfCreate, file %s, flags %#x\n",
+             path->String.utf8, params.CreateFlags));
+    rc = VbglR0SfCreate(&client_handle, &sf_g->map, path, &params);
+    if (rc == VERR_INVALID_NAME)
+    {
+        /* this can happen for names like 'foo*' on a Windows host */
+        return -ENOENT;
+    }
+    if (RT_FAILURE(rc))
+    {
+        LogFunc(("VbglR0SfCreate(%s) failed.  caller=%s, rc=%Rrc\n",
+                    path->String.utf8, rc, caller));
+        return -EPROTO;
+    }
+    if (params.Result != SHFL_FILE_EXISTS)
+    {
+        if (!ok_to_fail)
+            LogFunc(("VbglR0SfCreate(%s) file does not exist.  caller=%s, result=%d\n",
+                        path->String.utf8, params.Result, caller));
+        return -ENOENT;
+    }
+
+    *result = params.Info;
+    return 0;
+}
+
+/* this is called directly as iop on 2.4, indirectly as dop
+   [sf_dentry_revalidate] on 2.4/2.6, indirectly as iop through
+   [sf_getattr] on 2.6. the job is to find out whether dentry/inode is
+   still valid. the test is failed if [dentry] does not have an inode
+   or [sf_stat] is unsuccessful, otherwise we return success and
+   update inode attributes */
+int sf_inode_revalidate(struct dentry *dentry)
+{
+    int err;
+    struct sf_glob_info *sf_g;
+    struct sf_inode_info *sf_i;
+    SHFLFSOBJINFO info;
+
+    TRACE();
+    if (!dentry || !dentry->d_inode)
+    {
+        LogFunc(("no dentry(%p) or inode(%p)\n", dentry, dentry->d_inode));
+        return -EINVAL;
+    }
+
+    sf_g = GET_GLOB_INFO(dentry->d_inode->i_sb);
+    sf_i = GET_INODE_INFO(dentry->d_inode);
+
+#if 0
+    printk("%s called by %p:%p\n",
+            sf_i->path->String.utf8,
+            __builtin_return_address (0),
+            __builtin_return_address (1));
+#endif
+
+    BUG_ON(!sf_g);
+    BUG_ON(!sf_i);
+
+    if (!sf_i->force_restat)
+    {
+        if (jiffies - dentry->d_time < sf_g->ttl)
+            return 0;
+    }
+
+    err = sf_stat(__func__, sf_g, sf_i->path, &info, 1);
+    if (err)
+        return err;
+
+    dentry->d_time = jiffies;
+    sf_init_inode(sf_g, dentry->d_inode, &info);
+    return 0;
+}
+
+/* this is called during name resolution/lookup to check if the
+   [dentry] in the cache is still valid. the job is handled by
+   [sf_inode_revalidate] */
+static int
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+sf_dentry_revalidate(struct dentry *dentry, unsigned flags)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+sf_dentry_revalidate(struct dentry *dentry, struct nameidata *nd)
+#else
+sf_dentry_revalidate(struct dentry *dentry, int flags)
+#endif
+{
+    TRACE();
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+    if (flags & LOOKUP_RCU)
+        return -ECHILD;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+    /* see Documentation/filesystems/vfs.txt */
+    if (nd && nd->flags & LOOKUP_RCU)
+        return -ECHILD;
+#endif
+
+    if (sf_inode_revalidate(dentry))
+        return 0;
+
+    return 1;
+}
+
+/* on 2.6 this is a proxy for [sf_inode_revalidate] which (as a side
+   effect) updates inode attributes for [dentry] (given that [dentry]
+   has inode at all) from these new attributes we derive [kstat] via
+   [generic_fillattr] */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+int sf_getattr(const struct path *path, struct kstat *kstat, u32 request_mask, unsigned int flags)
+# else
+int sf_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *kstat)
+# endif
+{
+    int err;
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+    struct dentry *dentry = path->dentry;
+# endif
+
+    TRACE();
+    err = sf_inode_revalidate(dentry);
+    if (err)
+        return err;
+
+    generic_fillattr(dentry->d_inode, kstat);
+    return 0;
+}
+
+int sf_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+    struct sf_glob_info *sf_g;
+    struct sf_inode_info *sf_i;
+    SHFLCREATEPARMS params;
+    SHFLFSOBJINFO info;
+    uint32_t cbBuffer;
+    int rc, err;
+
+    TRACE();
+
+    sf_g = GET_GLOB_INFO(dentry->d_inode->i_sb);
+    sf_i = GET_INODE_INFO(dentry->d_inode);
+    err  = 0;
+
+    RT_ZERO(params);
+    params.Handle = SHFL_HANDLE_NIL;
+    params.CreateFlags = SHFL_CF_ACT_OPEN_IF_EXISTS
+                       | SHFL_CF_ACT_FAIL_IF_NEW
+                       | SHFL_CF_ACCESS_ATTR_WRITE;
+
+    /* this is at least required for Posix hosts */
+    if (iattr->ia_valid & ATTR_SIZE)
+        params.CreateFlags |= SHFL_CF_ACCESS_WRITE;
+
+    rc = VbglR0SfCreate(&client_handle, &sf_g->map, sf_i->path, &params);
+    if (RT_FAILURE(rc))
+    {
+        LogFunc(("VbglR0SfCreate(%s) failed rc=%Rrc\n",
+                 sf_i->path->String.utf8, rc));
+        err = -RTErrConvertToErrno(rc);
+        goto fail2;
+    }
+    if (params.Result != SHFL_FILE_EXISTS)
+    {
+        LogFunc(("file %s does not exist\n", sf_i->path->String.utf8));
+        err = -ENOENT;
+        goto fail1;
+    }
+
+    /* Setting the file size and setting the other attributes has to be
+     * handled separately, see implementation of vbsfSetFSInfo() in
+     * vbsf.cpp */
+    if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME))
+    {
+#define mode_set(r) ((iattr->ia_mode & (S_##r)) ? RTFS_UNIX_##r : 0)
+
+        RT_ZERO(info);
+        if (iattr->ia_valid & ATTR_MODE)
+        {
+            info.Attr.fMode  = mode_set(ISUID);
+            info.Attr.fMode |= mode_set(ISGID);
+            info.Attr.fMode |= mode_set(IRUSR);
+            info.Attr.fMode |= mode_set(IWUSR);
+            info.Attr.fMode |= mode_set(IXUSR);
+            info.Attr.fMode |= mode_set(IRGRP);
+            info.Attr.fMode |= mode_set(IWGRP);
+            info.Attr.fMode |= mode_set(IXGRP);
+            info.Attr.fMode |= mode_set(IROTH);
+            info.Attr.fMode |= mode_set(IWOTH);
+            info.Attr.fMode |= mode_set(IXOTH);
+
+            if (iattr->ia_mode & S_IFDIR)
+                info.Attr.fMode |= RTFS_TYPE_DIRECTORY;
+            else
+                info.Attr.fMode |= RTFS_TYPE_FILE;
+        }
+
+        if (iattr->ia_valid & ATTR_ATIME)
+            sf_timespec_from_ftime(&info.AccessTime, &iattr->ia_atime);
+        if (iattr->ia_valid & ATTR_MTIME)
+            sf_timespec_from_ftime(&info.ModificationTime, &iattr->ia_mtime);
+        /* ignore ctime (inode change time) as it can't be set from userland anyway */
+
+        cbBuffer = sizeof(info);
+        rc = VbglR0SfFsInfo(&client_handle, &sf_g->map, params.Handle,
+                            SHFL_INFO_SET | SHFL_INFO_FILE, &cbBuffer,
+                            (PSHFLDIRINFO)&info);
+        if (RT_FAILURE(rc))
+        {
+            LogFunc(("VbglR0SfFsInfo(%s, FILE) failed rc=%Rrc\n",
+                        sf_i->path->String.utf8, rc));
+            err = -RTErrConvertToErrno(rc);
+            goto fail1;
+        }
+    }
+
+    if (iattr->ia_valid & ATTR_SIZE)
+    {
+        RT_ZERO(info);
+        info.cbObject = iattr->ia_size;
+        cbBuffer = sizeof(info);
+        rc = VbglR0SfFsInfo(&client_handle, &sf_g->map, params.Handle,
+                            SHFL_INFO_SET | SHFL_INFO_SIZE, &cbBuffer,
+                            (PSHFLDIRINFO)&info);
+        if (RT_FAILURE(rc))
+        {
+            LogFunc(("VbglR0SfFsInfo(%s, SIZE) failed rc=%Rrc\n",
+                        sf_i->path->String.utf8, rc));
+            err = -RTErrConvertToErrno(rc);
+            goto fail1;
+        }
+    }
+
+    rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle);
+    if (RT_FAILURE(rc))
+        LogFunc(("VbglR0SfClose(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc));
+
+    return sf_inode_revalidate(dentry);
+
+fail1:
+    rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle);
+    if (RT_FAILURE(rc))
+        LogFunc(("VbglR0SfClose(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc));
+
+fail2:
+    return err;
+}
+#endif /* >= 2.6.0 */
+
+static int sf_make_path(const char *caller, struct sf_inode_info *sf_i,
+                        const char *d_name, size_t d_len, SHFLSTRING **result)
+{
+    size_t path_len, shflstring_len;
+    SHFLSTRING *tmp;
+    uint16_t p_len;
+    uint8_t *p_name;
+    int fRoot = 0;
+
+    TRACE();
+    p_len = sf_i->path->u16Length;
+    p_name = sf_i->path->String.utf8;
+
+    if (p_len == 1 && *p_name == '/')
+    {
+        path_len = d_len + 1;
+        fRoot = 1;
+    }
+    else
+    {
+        /* lengths of constituents plus terminating zero plus slash  */
+        path_len = p_len + d_len + 2;
+        if (path_len > 0xffff)
+        {
+            LogFunc(("path too long.  caller=%s, path_len=%zu\n", caller, path_len));
+            return -ENAMETOOLONG;
+        }
+    }
+
+    shflstring_len = offsetof(SHFLSTRING, String.utf8) + path_len;
+    tmp = kmalloc(shflstring_len, GFP_KERNEL);
+    if (!tmp)
+    {
+        LogRelFunc(("kmalloc failed, caller=%s\n", caller));
+        return -ENOMEM;
+    }
+    tmp->u16Length = path_len - 1;
+    tmp->u16Size = path_len;
+
+    if (fRoot)
+        memcpy(&tmp->String.utf8[0], d_name, d_len + 1);
+    else
+    {
+        memcpy(&tmp->String.utf8[0], p_name, p_len);
+        tmp->String.utf8[p_len] = '/';
+        memcpy(&tmp->String.utf8[p_len + 1], d_name, d_len);
+        tmp->String.utf8[p_len + 1 + d_len] = '\0';
+    }
+
+    *result = tmp;
+    return 0;
+}
+
+/**
+ * [dentry] contains string encoded in coding system that corresponds
+ * to [sf_g]->nls, we must convert it to UTF8 here and pass down to
+ * [sf_make_path] which will allocate SHFLSTRING and fill it in
+ */
+int sf_path_from_dentry(const char *caller, struct sf_glob_info *sf_g,
+                        struct sf_inode_info *sf_i, struct dentry *dentry,
+                        SHFLSTRING **result)
+{
+    int err;
+    const char *d_name;
+    size_t d_len;
+    const char *name;
+    size_t len = 0;
+
+    TRACE();
+    d_name = dentry->d_name.name;
+    d_len = dentry->d_name.len;
+
+    if (sf_g->nls)
+    {
+        size_t in_len, i, out_bound_len;
+        const char *in;
+        char *out;
+
+        in = d_name;
+        in_len = d_len;
+
+        out_bound_len = PATH_MAX;
+        out = kmalloc(out_bound_len, GFP_KERNEL);
+        name = out;
+
+        for (i = 0; i < d_len; ++i)
+        {
+            /* We renamed the linux kernel wchar_t type to linux_wchar_t in
+               the-linux-kernel.h, as it conflicts with the C++ type of that name. */
+            linux_wchar_t uni;
+            int nb;
+
+            nb = sf_g->nls->char2uni(in, in_len, &uni);
+            if (nb < 0)
+            {
+                LogFunc(("nls->char2uni failed %x %d\n",
+                            *in, in_len));
+                err = -EINVAL;
+                goto fail1;
+            }
+            in_len -= nb;
+            in += nb;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
+            nb = utf32_to_utf8(uni, out, out_bound_len);
+#else
+            nb = utf8_wctomb(out, uni, out_bound_len);
+#endif
+            if (nb < 0)
+            {
+                LogFunc(("nls->uni2char failed %x %d\n",
+                            uni, out_bound_len));
+                err = -EINVAL;
+                goto fail1;
+            }
+            out_bound_len -= nb;
+            out += nb;
+            len += nb;
+        }
+        if (len >= PATH_MAX - 1)
+        {
+            err = -ENAMETOOLONG;
+            goto fail1;
+        }
+
+        LogFunc(("result(%d) = %.*s\n", len, len, name));
+        *out = 0;
+    }
+    else
+    {
+        name = d_name;
+        len = d_len;
+    }
+
+    err = sf_make_path(caller, sf_i, name, len, result);
+    if (name != d_name)
+        kfree(name);
+
+    return err;
+
+fail1:
+    kfree(name);
+    return err;
+}
+
+int sf_nlscpy(struct sf_glob_info *sf_g,
+              char *name, size_t name_bound_len,
+              const unsigned char *utf8_name, size_t utf8_len)
+{
+    if (sf_g->nls)
+    {
+        const char *in;
+        char *out;
+        size_t out_len;
+        size_t out_bound_len;
+        size_t in_bound_len;
+
+        in = utf8_name;
+        in_bound_len = utf8_len;
+
+        out = name;
+        out_len = 0;
+        out_bound_len = name_bound_len;
+
+        while (in_bound_len)
+        {
+            int nb;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
+            unicode_t uni;
+
+            nb = utf8_to_utf32(in, in_bound_len, &uni);
+#else
+            linux_wchar_t uni;
+
+            nb = utf8_mbtowc(&uni, in, in_bound_len);
+#endif
+            if (nb < 0)
+            {
+                LogFunc(("utf8_mbtowc failed(%s) %x:%d\n",
+                            (const char *) utf8_name, *in, in_bound_len));
+                return -EINVAL;
+            }
+            in += nb;
+            in_bound_len -= nb;
+
+            nb = sf_g->nls->uni2char(uni, out, out_bound_len);
+            if (nb < 0)
+            {
+                LogFunc(("nls->uni2char failed(%s) %x:%d\n",
+                            utf8_name, uni, out_bound_len));
+                return nb;
+            }
+            out += nb;
+            out_bound_len -= nb;
+            out_len += nb;
+        }
+
+        *out = 0;
+    }
+    else
+    {
+        if (utf8_len + 1 > name_bound_len)
+            return -ENAMETOOLONG;
+
+        memcpy(name, utf8_name, utf8_len + 1);
+    }
+    return 0;
+}
+
+static struct sf_dir_buf *sf_dir_buf_alloc(void)
+{
+    struct sf_dir_buf *b;
+
+    TRACE();
+    b = kmalloc(sizeof(*b), GFP_KERNEL);
+    if (!b)
+    {
+        LogRelFunc(("could not alloc directory buffer\n"));
+        return NULL;
+    }
+
+#ifdef USE_VMALLOC
+    b->buf = vmalloc(DIR_BUFFER_SIZE);
+#else
+    b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL);
+#endif
+    if (!b->buf)
+    {
+        kfree(b);
+        LogRelFunc(("could not alloc directory buffer storage\n"));
+        return NULL;
+    }
+
+    INIT_LIST_HEAD(&b->head);
+    b->cEntries = 0;
+    b->cbUsed   = 0;
+    b->cbFree   = DIR_BUFFER_SIZE;
+    return b;
+}
+
+static void sf_dir_buf_free(struct sf_dir_buf *b)
+{
+    BUG_ON(!b || !b->buf);
+
+    TRACE();
+    list_del(&b->head);
+#ifdef USE_VMALLOC
+    vfree(b->buf);
+#else
+    kfree(b->buf);
+#endif
+    kfree(b);
+}
+
+/**
+ * Free the directory buffer.
+ */
+void sf_dir_info_free(struct sf_dir_info *p)
+{
+    struct list_head *list, *pos, *tmp;
+
+    TRACE();
+    list = &p->info_list;
+    list_for_each_safe(pos, tmp, list)
+    {
+        struct sf_dir_buf *b;
+
+        b = list_entry(pos, struct sf_dir_buf, head);
+        sf_dir_buf_free(b);
+    }
+    kfree(p);
+}
+
+/**
+ * Empty (but not free) the directory buffer.
+ */
+void sf_dir_info_empty(struct sf_dir_info *p)
+{
+    struct list_head *list, *pos, *tmp;
+    TRACE();
+    list = &p->info_list;
+    list_for_each_safe(pos, tmp, list)
+    {
+        struct sf_dir_buf *b;
+        b = list_entry(pos, struct sf_dir_buf, head);
+        b->cEntries = 0;
+        b->cbUsed   = 0;
+        b->cbFree = DIR_BUFFER_SIZE;
+    }
+}
+
+/**
+ * Create a new directory buffer descriptor.
+ */
+struct sf_dir_info *sf_dir_info_alloc(void)
+{
+    struct sf_dir_info *p;
+
+    TRACE();
+    p = kmalloc(sizeof(*p), GFP_KERNEL);
+    if (!p)
+    {
+        LogRelFunc(("could not alloc directory info\n"));
+        return NULL;
+    }
+
+    INIT_LIST_HEAD(&p->info_list);
+    return p;
+}
+
+/**
+ * Search for an empty directory content buffer.
+ */
+static struct sf_dir_buf *sf_get_empty_dir_buf(struct sf_dir_info *sf_d)
+{
+    struct list_head *list, *pos;
+
+    list = &sf_d->info_list;
+    list_for_each(pos, list)
+    {
+        struct sf_dir_buf *b;
+
+        b = list_entry(pos, struct sf_dir_buf, head);
+        if (!b)
+            return NULL;
+        else
+        {
+            if (b->cbUsed == 0)
+                return b;
+        }
+    }
+
+    return NULL;
+}
+
+int sf_dir_read_all(struct sf_glob_info *sf_g, struct sf_inode_info *sf_i,
+                    struct sf_dir_info *sf_d, SHFLHANDLE handle)
+{
+    int err;
+    SHFLSTRING *mask;
+    struct sf_dir_buf *b;
+
+    TRACE();
+    err = sf_make_path(__func__, sf_i, "*", 1, &mask);
+    if (err)
+        goto fail0;
+
+    for (;;)
+    {
+        int rc;
+        void *buf;
+        uint32_t cbSize;
+        uint32_t cEntries;
+
+        b = sf_get_empty_dir_buf(sf_d);
+        if (!b)
+        {
+            b = sf_dir_buf_alloc();
+            if (!b)
+            {
+                err = -ENOMEM;
+                LogRelFunc(("could not alloc directory buffer\n"));
+                goto fail1;
+            }
+            list_add(&b->head, &sf_d->info_list);
+        }
+
+        buf = b->buf;
+        cbSize = b->cbFree;
+
+        rc = VbglR0SfDirInfo(&client_handle, &sf_g->map, handle, mask,
+                             0, 0, &cbSize, buf, &cEntries);
+        switch (rc)
+        {
+            case VINF_SUCCESS:
+                /* fallthrough */
+            case VERR_NO_MORE_FILES:
+                break;
+            case VERR_NO_TRANSLATION:
+                LogFunc(("host could not translate entry\n"));
+                /* XXX */
+                break;
+            default:
+                err = -RTErrConvertToErrno(rc);
+                LogFunc(("VbglR0SfDirInfo failed rc=%Rrc\n", rc));
+                goto fail1;
+        }
+
+        b->cEntries += cEntries;
+        b->cbFree   -= cbSize;
+        b->cbUsed   += cbSize;
+
+        if (RT_FAILURE(rc))
+            break;
+    }
+    err = 0;
+
+fail1:
+    kfree(mask);
+
+fail0:
+    return err;
+}
+
+int sf_get_volume_info(struct super_block *sb, STRUCT_STATFS *stat)
+{
+    struct sf_glob_info *sf_g;
+    SHFLVOLINFO SHFLVolumeInfo;
+    uint32_t cbBuffer;
+    int rc;
+
+    sf_g = GET_GLOB_INFO(sb);
+    cbBuffer = sizeof(SHFLVolumeInfo);
+    rc = VbglR0SfFsInfo(&client_handle, &sf_g->map, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME,
+                        &cbBuffer, (PSHFLDIRINFO)&SHFLVolumeInfo);
+    if (RT_FAILURE(rc))
+        return -RTErrConvertToErrno(rc);
+
+    stat->f_type        = NFS_SUPER_MAGIC; /* XXX vboxsf type? */
+    stat->f_bsize       = SHFLVolumeInfo.ulBytesPerAllocationUnit;
+    stat->f_blocks      = SHFLVolumeInfo.ullTotalAllocationBytes
+                        / SHFLVolumeInfo.ulBytesPerAllocationUnit;
+    stat->f_bfree       = SHFLVolumeInfo.ullAvailableAllocationBytes
+                        / SHFLVolumeInfo.ulBytesPerAllocationUnit;
+    stat->f_bavail      = SHFLVolumeInfo.ullAvailableAllocationBytes
+                        / SHFLVolumeInfo.ulBytesPerAllocationUnit;
+    stat->f_files       = 1000;
+    stat->f_ffree       = 1000; /* don't return 0 here since the guest may think
+                                 * that it is not possible to create any more files */
+    stat->f_fsid.val[0] = 0;
+    stat->f_fsid.val[1] = 0;
+    stat->f_namelen     = 255;
+    return 0;
+}
+
+struct dentry_operations sf_dentry_ops =
+{
+    .d_revalidate = sf_dentry_revalidate
+};
+
+int sf_init_backing_dev(struct sf_glob_info *sf_g)
+{
+    int rc = 0;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0)
+    /* Each new shared folder map gets a new uint64_t identifier,
+     * allocated in sequence.  We ASSUME the sequence will not wrap. */
+    static uint64_t s_u64Sequence = 0;
+    uint64_t u64CurrentSequence = ASMAtomicIncU64(&s_u64Sequence);
+
+    sf_g->bdi.ra_pages = 0; /* No readahead */
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12)
+    sf_g->bdi.capabilities  = BDI_CAP_MAP_DIRECT    /* MAP_SHARED */
+                            | BDI_CAP_MAP_COPY      /* MAP_PRIVATE */
+                            | BDI_CAP_READ_MAP      /* can be mapped for reading */
+                            | BDI_CAP_WRITE_MAP     /* can be mapped for writing */
+                            | BDI_CAP_EXEC_MAP;     /* can be mapped for execution */
+# endif /* >= 2.6.12 */
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+    rc = bdi_init(&sf_g->bdi);
+#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+    if (!rc)
+        rc = bdi_register(&sf_g->bdi, NULL, "vboxsf-%llu",
+                          (unsigned long long)u64CurrentSequence);
+#  endif /* >= 2.6.26 */
+# endif /* >= 2.6.24 */
+#endif /* >= 2.6.0 && <= 3.19.0 */
+    return rc;
+}
+
+void sf_done_backing_dev(struct sf_glob_info *sf_g)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0)
+    bdi_destroy(&sf_g->bdi); /* includes bdi_unregister() */
+#endif
+}
diff --git a/ubuntu/vbox/vboxsf/vbsfmount.h b/ubuntu/vbox/vboxsf/vbsfmount.h
new file mode 100644 (file)
index 0000000..632859e
--- /dev/null
@@ -0,0 +1,78 @@
+/** @file
+ * vboxsf -- VirtualBox Guest Additions for Linux: mount(2) parameter structure.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef VBFS_MOUNT_H
+#define VBFS_MOUNT_H
+
+#define MAX_HOST_NAME  256
+#define MAX_NLS_NAME    32
+
+/* Linux constraints the size of data mount argument to PAGE_SIZE - 1. */
+struct vbsf_mount_info_old
+{
+    char name[MAX_HOST_NAME];
+    char nls_name[MAX_NLS_NAME];
+    int  uid;
+    int  gid;
+    int  ttl;
+};
+
+#define VBSF_MOUNT_SIGNATURE_BYTE_0 '\377'
+#define VBSF_MOUNT_SIGNATURE_BYTE_1 '\376'
+#define VBSF_MOUNT_SIGNATURE_BYTE_2 '\375'
+
+struct vbsf_mount_info_new
+{
+    char nullchar;              /* name cannot be '\0' -- we use this field
+                                   to distinguish between the old structure
+                                   and the new structure */
+    char signature[3];          /* signature */
+    int  length;                /* length of the whole structure */
+    char name[MAX_HOST_NAME];   /* share name */
+    char nls_name[MAX_NLS_NAME];/* name of an I/O charset */
+    int  uid;                   /* user ID for all entries, default 0=root */
+    int  gid;                   /* group ID for all entries, default 0=root */
+    int  ttl;                   /* time to live */
+    int  dmode;                 /* mode for directories if != 0xffffffff */
+    int  fmode;                 /* mode for regular files if != 0xffffffff */
+    int  dmask;                 /* umask applied to directories */
+    int  fmask;                 /* umask applied to regular files */
+};
+
+struct vbsf_mount_opts
+{
+    int  uid;
+    int  gid;
+    int  ttl;
+    int  dmode;
+    int  fmode;
+    int  dmask;
+    int  fmask;
+    int  ronly;
+    int  sloppy;
+    int  noexec;
+    int  nodev;
+    int  nosuid;
+    int  remount;
+    char nls_name[MAX_NLS_NAME];
+    char *convertcp;
+};
+
+/** Completes the mount operation by adding the new mount point to mtab if required. */
+int vbsfmount_complete(const char *host_name, const char *mount_point,
+                       unsigned long flags, struct vbsf_mount_opts *opts);
+
+#endif /* vbsfmount.h */
diff --git a/ubuntu/vbox/vboxsf/version-generated.h b/ubuntu/vbox/vboxsf/version-generated.h
new file mode 100644 (file)
index 0000000..24cdc17
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef ___version_generated_h___
+#define ___version_generated_h___
+
+#define VBOX_VERSION_MAJOR 5
+#define VBOX_VERSION_MINOR 1
+#define VBOX_VERSION_BUILD 28
+#define VBOX_VERSION_STRING_RAW "5.1.28"
+#define VBOX_VERSION_STRING "5.1.28_Ubuntu"
+#define VBOX_API_VERSION_STRING "5_1"
+
+#define VBOX_PRIVATE_BUILD_DESC "Private build by buildd"
+
+#endif
diff --git a/ubuntu/vbox/vboxsf/vfsmod.c b/ubuntu/vbox/vboxsf/vfsmod.c
new file mode 100644 (file)
index 0000000..d66bf80
--- /dev/null
@@ -0,0 +1,671 @@
+/** @file
+ *
+ * vboxsf -- VirtualBox Guest Additions for Linux:
+ * Virtual File System for VirtualBox Shared Folders
+ *
+ * Module initialization/finalization
+ * File system registration/deregistration
+ * Superblock reading
+ * Few utility functions
+ */
+
+/*
+ * 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.
+ */
+
+/**
+ * @note Anyone wishing to make changes here might wish to take a look at
+ *  http://www.atnf.csiro.au/people/rgooch/linux/vfs.txt
+ * which seems to be the closest there is to official documentation on
+ * writing filesystem drivers for Linux.
+ */
+
+#include "vfsmod.h"
+#include "version-generated.h"
+#include "revision-generated.h"
+#include "product-generated.h"
+
+MODULE_DESCRIPTION(VBOX_PRODUCT " VFS Module for Host File System Access");
+MODULE_AUTHOR(VBOX_VENDOR);
+MODULE_LICENSE("GPL");
+#ifdef MODULE_ALIAS_FS
+MODULE_ALIAS_FS("vboxsf");
+#endif   
+#ifdef MODULE_VERSION
+MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
+#endif
+
+/* globals */
+VBGLSFCLIENT client_handle;
+
+/* forward declarations */
+static struct super_operations sf_super_ops;
+
+/* allocate global info, try to map host share */
+static int sf_glob_alloc(struct vbsf_mount_info_new *info, struct sf_glob_info **sf_gp)
+{
+    int err, rc;
+    SHFLSTRING *str_name;
+    size_t name_len, str_len;
+    struct sf_glob_info *sf_g;
+
+    TRACE();
+    sf_g = kmalloc(sizeof(*sf_g), GFP_KERNEL);
+    if (!sf_g)
+    {
+        err = -ENOMEM;
+        LogRelFunc(("could not allocate memory for global info\n"));
+        goto fail0;
+    }
+
+    RT_ZERO(*sf_g);
+
+    if (   info->nullchar     != '\0'
+        || info->signature[0] != VBSF_MOUNT_SIGNATURE_BYTE_0
+        || info->signature[1] != VBSF_MOUNT_SIGNATURE_BYTE_1
+        || info->signature[2] != VBSF_MOUNT_SIGNATURE_BYTE_2)
+    {
+        /* An old version of mount.vboxsf made the syscall. Translate the
+         * old parameters to the new structure. */
+        struct vbsf_mount_info_old *info_old = (struct vbsf_mount_info_old *)info;
+        static struct vbsf_mount_info_new info_compat;
+
+        info = &info_compat;
+        memset(info, 0, sizeof(*info));
+        memcpy(&info->name, &info_old->name, MAX_HOST_NAME);
+        memcpy(&info->nls_name, &info_old->nls_name, MAX_NLS_NAME);
+        info->length = offsetof(struct vbsf_mount_info_new, dmode);
+        info->uid    = info_old->uid;
+        info->gid    = info_old->gid;
+        info->ttl    = info_old->ttl;
+    }
+
+    info->name[sizeof(info->name) - 1] = 0;
+    info->nls_name[sizeof(info->nls_name) - 1] = 0;
+
+    name_len = strlen(info->name);
+    if (name_len > 0xfffe)
+    {
+        err = -ENAMETOOLONG;
+        LogFunc(("map name too big\n"));
+        goto fail1;
+    }
+
+    str_len = offsetof(SHFLSTRING, String.utf8) + name_len + 1;
+    str_name = kmalloc(str_len, GFP_KERNEL);
+    if (!str_name)
+    {
+        err = -ENOMEM;
+        LogRelFunc(("could not allocate memory for host name\n"));
+        goto fail1;
+    }
+
+    str_name->u16Length = name_len;
+    str_name->u16Size = name_len + 1;
+    memcpy(str_name->String.utf8, info->name, name_len + 1);
+
+#define _IS_UTF8(_str) \
+    (strcmp(_str, "utf8") == 0)
+#define _IS_EMPTY(_str) \
+    (strcmp(_str, "") == 0)
+
+    /* Check if NLS charset is valid and not points to UTF8 table */
+    if (info->nls_name[0])
+    {
+        if (_IS_UTF8(info->nls_name))
+            sf_g->nls = NULL;
+        else
+        {
+            sf_g->nls = load_nls(info->nls_name);
+            if (!sf_g->nls)
+            {
+                err = -EINVAL;
+                LogFunc(("failed to load nls %s\n", info->nls_name));
+                kfree(str_name);
+                goto fail1;
+            }
+        }
+    }
+    else
+    {
+#ifdef CONFIG_NLS_DEFAULT
+        /* If no NLS charset specified, try to load the default
+         * one if it's not points to UTF8. */
+        if (!_IS_UTF8(CONFIG_NLS_DEFAULT) && !_IS_EMPTY(CONFIG_NLS_DEFAULT))
+            sf_g->nls = load_nls_default();
+        else
+            sf_g->nls = NULL;
+#else
+        sf_g->nls = NULL;
+#endif
+
+#undef _IS_UTF8
+#undef _IS_EMPTY
+    }
+
+    rc = VbglR0SfMapFolder(&client_handle, str_name, &sf_g->map);
+    kfree(str_name);
+
+    if (RT_FAILURE(rc))
+    {
+        err = -EPROTO;
+        LogFunc(("VbglR0SfMapFolder failed rc=%d\n", rc));
+        goto fail2;
+    }
+
+    sf_g->ttl = info->ttl;
+    sf_g->uid = info->uid;
+    sf_g->gid = info->gid;
+
+    if ((unsigned)info->length >= sizeof(struct vbsf_mount_info_new))
+    {
+        /* new fields */
+        sf_g->dmode = info->dmode;
+        sf_g->fmode = info->fmode;
+        sf_g->dmask = info->dmask;
+        sf_g->fmask = info->fmask;
+    }
+    else
+    {
+        sf_g->dmode = ~0;
+        sf_g->fmode = ~0;
+    }
+
+    *sf_gp = sf_g;
+    return 0;
+
+fail2:
+    if (sf_g->nls)
+        unload_nls(sf_g->nls);
+
+fail1:
+    kfree(sf_g);
+
+fail0:
+    return err;
+}
+
+/* unmap the share and free global info [sf_g] */
+static void
+sf_glob_free(struct sf_glob_info *sf_g)
+{
+    int rc;
+
+    TRACE();
+    rc = VbglR0SfUnmapFolder(&client_handle, &sf_g->map);
+    if (RT_FAILURE(rc))
+        LogFunc(("VbglR0SfUnmapFolder failed rc=%d\n", rc));
+
+    if (sf_g->nls)
+        unload_nls(sf_g->nls);
+
+    kfree(sf_g);
+}
+
+/**
+ * This is called (by sf_read_super_[24|26] when vfs mounts the fs and
+ * wants to read super_block.
+ *
+ * calls [sf_glob_alloc] to map the folder and allocate global
+ * information structure.
+ *
+ * initializes [sb], initializes root inode and dentry.
+ *
+ * should respect [flags]
+ */
+static int sf_read_super_aux(struct super_block *sb, void *data, int flags)
+{
+    int err;
+    struct dentry *droot;
+    struct inode *iroot;
+    struct sf_inode_info *sf_i;
+    struct sf_glob_info *sf_g;
+    SHFLFSOBJINFO fsinfo;
+    struct vbsf_mount_info_new *info;
+    bool fInodePut = true;
+
+    TRACE();
+    if (!data)
+    {
+        LogFunc(("no mount info specified\n"));
+        return -EINVAL;
+    }
+
+    info = data;
+
+    if (flags & MS_REMOUNT)
+    {
+        LogFunc(("remounting is not supported\n"));
+        return -ENOSYS;
+    }
+
+    err = sf_glob_alloc(info, &sf_g);
+    if (err)
+        goto fail0;
+
+    sf_i = kmalloc(sizeof (*sf_i), GFP_KERNEL);
+    if (!sf_i)
+    {
+        err = -ENOMEM;
+        LogRelFunc(("could not allocate memory for root inode info\n"));
+        goto fail1;
+    }
+
+    sf_i->handle = SHFL_HANDLE_NIL;
+    sf_i->path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL);
+    if (!sf_i->path)
+    {
+        err = -ENOMEM;
+        LogRelFunc(("could not allocate memory for root inode path\n"));
+        goto fail2;
+    }
+
+    sf_i->path->u16Length = 1;
+    sf_i->path->u16Size = 2;
+    sf_i->path->String.utf8[0] = '/';
+    sf_i->path->String.utf8[1] = 0;
+    sf_i->force_reread = 0;
+
+    err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
+    if (err)
+    {
+        LogFunc(("could not stat root of share\n"));
+        goto fail3;
+    }
+
+    sb->s_magic = 0xface;
+    sb->s_blocksize = 1024;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 3)
+    /* Required for seek/sendfile.
+     *
+     * Must by less than or equal to INT64_MAX despite the fact that the
+     * declaration of this variable is unsigned long long. See determination
+     * of 'loff_t max' in fs/read_write.c / do_sendfile(). I don't know the
+     * correct limit but MAX_LFS_FILESIZE (8TB-1 on 32-bit boxes) takes the
+     * page cache into account and is the suggested limit. */
+# if defined MAX_LFS_FILESIZE
+    sb->s_maxbytes = MAX_LFS_FILESIZE;
+# else
+    sb->s_maxbytes = 0x7fffffffffffffffULL;
+# endif
+#endif
+    sb->s_op = &sf_super_ops;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
+    iroot = iget_locked(sb, 0);
+#else
+    iroot = iget(sb, 0);
+#endif
+    if (!iroot)
+    {
+        err = -ENOMEM;  /* XXX */
+        LogFunc(("could not get root inode\n"));
+        goto fail3;
+    }
+
+    if (sf_init_backing_dev(sf_g))
+    {
+        err = -EINVAL;
+        LogFunc(("could not init bdi\n"));
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
+        unlock_new_inode(iroot);
+#endif
+        goto fail4;
+    }
+
+    sf_init_inode(sf_g, iroot, &fsinfo);
+    SET_INODE_INFO(iroot, sf_i);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
+    unlock_new_inode(iroot);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+    droot = d_make_root(iroot);
+#else
+    droot = d_alloc_root(iroot);
+#endif
+    if (!droot)
+    {
+        err = -ENOMEM;  /* XXX */
+        LogFunc(("d_alloc_root failed\n"));
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+        fInodePut = false;
+#endif
+        goto fail5;
+    }
+
+    sb->s_root = droot;
+    SET_GLOB_INFO(sb, sf_g);
+    return 0;
+
+fail5:
+    sf_done_backing_dev(sf_g);
+
+fail4:
+    if (fInodePut)
+        iput(iroot);
+
+fail3:
+    kfree(sf_i->path);
+
+fail2:
+    kfree(sf_i);
+
+fail1:
+    sf_glob_free(sf_g);
+
+fail0:
+    return err;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+static struct super_block *
+sf_read_super_24(struct super_block *sb, void *data, int flags)
+{
+    int err;
+
+    TRACE();
+    err = sf_read_super_aux(sb, data, flags);
+    if (err)
+        return NULL;
+
+    return sb;
+}
+#endif
+
+/* this is called when vfs is about to destroy the [inode]. all
+   resources associated with this [inode] must be cleared here */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+static void sf_clear_inode(struct inode *inode)
+{
+    struct sf_inode_info *sf_i;
+
+    TRACE();
+    sf_i = GET_INODE_INFO(inode);
+    if (!sf_i)
+        return;
+
+    BUG_ON(!sf_i->path);
+    kfree(sf_i->path);
+    kfree(sf_i);
+    SET_INODE_INFO(inode, NULL);
+}
+#else
+static void sf_evict_inode(struct inode *inode)
+{
+    struct sf_inode_info *sf_i;
+
+    TRACE();
+    truncate_inode_pages(&inode->i_data, 0);
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+    clear_inode(inode);
+# else
+    end_writeback(inode);
+# endif
+
+    sf_i = GET_INODE_INFO(inode);
+    if (!sf_i)
+        return;
+
+    BUG_ON(!sf_i->path);
+    kfree(sf_i->path);
+    kfree(sf_i);
+    SET_INODE_INFO(inode, NULL);
+}
+#endif
+
+/* this is called by vfs when it wants to populate [inode] with data.
+   the only thing that is known about inode at this point is its index
+   hence we can't do anything here, and let lookup/whatever with the
+   job to properly fill then [inode] */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
+static void sf_read_inode(struct inode *inode)
+{
+}
+#endif
+
+/* vfs is done with [sb] (umount called) call [sf_glob_free] to unmap
+   the folder and free [sf_g] */
+static void sf_put_super(struct super_block *sb)
+{
+    struct sf_glob_info *sf_g;
+
+    sf_g = GET_GLOB_INFO(sb);
+    BUG_ON(!sf_g);
+    sf_done_backing_dev(sf_g);
+    sf_glob_free(sf_g);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+static int sf_statfs(struct super_block *sb, STRUCT_STATFS *stat)
+{
+    return sf_get_volume_info(sb, stat);
+}
+#else
+static int sf_statfs(struct dentry *dentry, STRUCT_STATFS *stat)
+{
+    struct super_block *sb = dentry->d_inode->i_sb;
+    return sf_get_volume_info(sb, stat);
+}
+#endif
+
+static int sf_remount_fs(struct super_block *sb, int *flags, char *data)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23)
+    struct sf_glob_info *sf_g;
+    struct sf_inode_info *sf_i;
+    struct inode *iroot;
+    SHFLFSOBJINFO fsinfo;
+    int err;
+
+    sf_g = GET_GLOB_INFO(sb);
+    BUG_ON(!sf_g);
+    if (data && data[0] != 0)
+    {
+        struct vbsf_mount_info_new *info =
+            (struct vbsf_mount_info_new *)data;
+        if (   info->signature[0] == VBSF_MOUNT_SIGNATURE_BYTE_0
+            && info->signature[1] == VBSF_MOUNT_SIGNATURE_BYTE_1
+            && info->signature[2] == VBSF_MOUNT_SIGNATURE_BYTE_2)
+        {
+            sf_g->uid = info->uid;
+            sf_g->gid = info->gid;
+            sf_g->ttl = info->ttl;
+            sf_g->dmode = info->dmode;
+            sf_g->fmode = info->fmode;
+            sf_g->dmask = info->dmask;
+            sf_g->fmask = info->fmask;
+        }
+    }
+
+    iroot = ilookup(sb, 0);
+    if (!iroot)
+        return -ENOSYS;
+
+    sf_i = GET_INODE_INFO(iroot);
+    err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
+    BUG_ON(err != 0);
+    sf_init_inode(sf_g, iroot, &fsinfo);
+    /*unlock_new_inode(iroot);*/
+    return 0;
+#else
+    return -ENOSYS;
+#endif
+}
+
+static struct super_operations sf_super_ops =
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+    .clear_inode = sf_clear_inode,
+#else
+    .evict_inode = sf_evict_inode,
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
+    .read_inode  = sf_read_inode,
+#endif
+    .put_super   = sf_put_super,
+    .statfs      = sf_statfs,
+    .remount_fs  = sf_remount_fs
+};
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+static DECLARE_FSTYPE(vboxsf_fs_type, "vboxsf", sf_read_super_24, 0);
+#else
+static int
+sf_read_super_26(struct super_block *sb, void *data, int flags)
+{
+    int err;
+
+    TRACE();
+    err = sf_read_super_aux(sb, data, flags);
+    if (err)
+        printk(KERN_DEBUG "sf_read_super_aux err=%d\n", err);
+
+    return err;
+}
+
+# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+static struct super_block *sf_get_sb(struct file_system_type *fs_type, int flags,
+                                     const char *dev_name, void *data)
+{
+    TRACE();
+    return get_sb_nodev(fs_type, flags, data, sf_read_super_26);
+}
+# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
+static int sf_get_sb(struct file_system_type *fs_type, int flags,
+                     const char *dev_name, void *data, struct vfsmount *mnt)
+{
+    TRACE();
+    return get_sb_nodev(fs_type, flags, data, sf_read_super_26, mnt);
+}
+# else
+static struct dentry *sf_mount(struct file_system_type *fs_type, int flags,
+                               const char *dev_name, void *data)
+{
+    TRACE();
+    return mount_nodev(fs_type, flags, data, sf_read_super_26);
+}
+# endif
+
+static struct file_system_type vboxsf_fs_type =
+{
+    .owner   = THIS_MODULE,
+    .name    = "vboxsf",
+# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
+    .get_sb  = sf_get_sb,
+# else
+    .mount   = sf_mount,
+# endif
+    .kill_sb = kill_anon_super
+};
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+static int follow_symlinks = 0;
+module_param(follow_symlinks, int, 0);
+MODULE_PARM_DESC(follow_symlinks, "Let host resolve symlinks rather than showing them");
+#endif
+
+/* Module initialization/finalization handlers */
+static int __init init(void)
+{
+    int rcVBox;
+    int rcRet = 0;
+    int err;
+
+    TRACE();
+
+    if (sizeof(struct vbsf_mount_info_new) > PAGE_SIZE)
+    {
+        printk(KERN_ERR
+                "Mount information structure is too large %lu\n"
+                "Must be less than or equal to %lu\n",
+                (unsigned long)sizeof (struct vbsf_mount_info_new),
+                (unsigned long)PAGE_SIZE);
+        return -EINVAL;
+    }
+
+    err = register_filesystem(&vboxsf_fs_type);
+    if (err)
+    {
+        LogFunc(("register_filesystem err=%d\n", err));
+        return err;
+    }
+
+    rcVBox = VbglR0SfInit();
+    if (RT_FAILURE(rcVBox))
+    {
+        LogRelFunc(("VbglR0SfInit failed, rc=%d\n", rcVBox));
+        rcRet = -EPROTO;
+        goto fail0;
+    }
+
+    rcVBox = VbglR0SfConnect(&client_handle);
+    if (RT_FAILURE(rcVBox))
+    {
+        LogRelFunc(("VbglR0SfConnect failed, rc=%d\n", rcVBox));
+        rcRet = -EPROTO;
+        goto fail1;
+    }
+
+    rcVBox = VbglR0SfSetUtf8(&client_handle);
+    if (RT_FAILURE(rcVBox))
+    {
+        LogRelFunc(("VbglR0SfSetUtf8 failed, rc=%d\n", rcVBox));
+        rcRet = -EPROTO;
+        goto fail2;
+    }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+    if (!follow_symlinks)
+    {
+        rcVBox = VbglR0SfSetSymlinks(&client_handle);
+        if (RT_FAILURE(rcVBox))
+        {
+            printk(KERN_WARNING
+                     "vboxsf: Host unable to show symlinks, rc=%d\n",
+                     rcVBox);
+        }
+    }
+#endif
+
+    printk(KERN_DEBUG
+            "vboxsf: Successfully loaded version " VBOX_VERSION_STRING
+            " (interface " RT_XSTR(VMMDEV_VERSION) ")\n");
+
+    return 0;
+
+fail2:
+    VbglR0SfDisconnect(&client_handle);
+
+fail1:
+    VbglR0SfTerm();
+
+fail0:
+    unregister_filesystem(&vboxsf_fs_type);
+    return rcRet;
+}
+
+static void __exit fini(void)
+{
+    TRACE();
+
+    VbglR0SfDisconnect(&client_handle);
+    VbglR0SfTerm();
+    unregister_filesystem(&vboxsf_fs_type);
+}
+
+module_init(init);
+module_exit(fini);
+
+/* C++ hack */
+int __gxx_personality_v0 = 0xdeadbeef;
diff --git a/ubuntu/vbox/vboxsf/vfsmod.h b/ubuntu/vbox/vboxsf/vfsmod.h
new file mode 100644 (file)
index 0000000..2f12206
--- /dev/null
@@ -0,0 +1,168 @@
+/** @file
+ * vboxsf - VirtualBox Guest Additions for Linux.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef VFSMOD_H
+#define VFSMOD_H
+
+#define LOG_GROUP LOG_GROUP_SHARED_FOLDERS
+#include "the-linux-kernel.h"
+#include <VBox/log.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+# include <linux/backing-dev.h>
+#endif
+
+#include <VBox/VBoxGuestLibSharedFolders.h>
+#include "vbsfmount.h"
+
+#define DIR_BUFFER_SIZE (16*_1K)
+
+/* per-shared folder information */
+struct sf_glob_info
+{
+    VBGLSFMAP map;
+    struct nls_table *nls;
+    int ttl;
+    int uid;
+    int gid;
+    int dmode;
+    int fmode;
+    int dmask;
+    int fmask;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+    struct backing_dev_info bdi;
+#endif
+};
+
+/* per-inode information */
+struct sf_inode_info
+{
+    /* which file */
+    SHFLSTRING *path;
+    /* some information was changed, update data on next revalidate */
+    int force_restat;
+    /* directory content changed, update the whole directory on next sf_getdent */
+    int force_reread;
+    /* file structure, only valid between open() and release() */
+    struct file *file;
+    /* handle valid if a file was created with sf_create_aux until it will
+     * be opened with sf_reg_open() */
+    SHFLHANDLE handle;
+};
+
+struct sf_dir_info
+{
+    struct list_head info_list;
+};
+
+struct sf_dir_buf
+{
+    size_t cEntries;
+    size_t cbFree;
+    size_t cbUsed;
+    void   *buf;
+    struct list_head head;
+};
+
+struct sf_reg_info
+{
+    SHFLHANDLE handle;
+};
+
+/* globals */
+extern VBGLSFCLIENT client_handle;
+
+/* forward declarations */
+extern struct inode_operations         sf_dir_iops;
+extern struct inode_operations         sf_lnk_iops;
+extern struct inode_operations         sf_reg_iops;
+extern struct file_operations          sf_dir_fops;
+extern struct file_operations          sf_reg_fops;
+extern struct dentry_operations        sf_dentry_ops;
+extern struct address_space_operations sf_reg_aops;
+
+extern void sf_init_inode(struct sf_glob_info *sf_g, struct inode *inode,
+                          PSHFLFSOBJINFO info);
+extern int  sf_stat(const char *caller, struct sf_glob_info *sf_g,
+                    SHFLSTRING *path, PSHFLFSOBJINFO result, int ok_to_fail);
+extern int  sf_inode_revalidate(struct dentry *dentry);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+extern int  sf_getattr(const struct path *path, struct kstat *kstat,
+                       u32 request_mask, unsigned int query_flags);
+# else
+extern int  sf_getattr(struct vfsmount *mnt, struct dentry *dentry,
+                       struct kstat *kstat);
+#endif
+extern int  sf_setattr(struct dentry *dentry, struct iattr *iattr);
+#endif
+extern int  sf_path_from_dentry(const char *caller, struct sf_glob_info *sf_g,
+                                struct sf_inode_info *sf_i, struct dentry *dentry,
+                                SHFLSTRING **result);
+extern int  sf_nlscpy(struct sf_glob_info *sf_g,
+                      char *name, size_t name_bound_len,
+                      const unsigned char *utf8_name, size_t utf8_len);
+extern void sf_dir_info_free(struct sf_dir_info *p);
+extern void sf_dir_info_empty(struct sf_dir_info *p);
+extern struct sf_dir_info *sf_dir_info_alloc(void);
+extern int  sf_dir_read_all(struct sf_glob_info *sf_g, struct sf_inode_info *sf_i,
+                            struct sf_dir_info *sf_d, SHFLHANDLE handle);
+extern int  sf_init_backing_dev(struct sf_glob_info *sf_g);
+extern void sf_done_backing_dev(struct sf_glob_info *sf_g);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+# define STRUCT_STATFS  struct statfs
+#else
+# define STRUCT_STATFS  struct kstatfs
+#endif
+int sf_get_volume_info(struct super_block *sb,STRUCT_STATFS *stat);
+
+#ifdef __cplusplus
+# define CMC_API __attribute__ ((cdecl, regparm (0)))
+#else
+# define CMC_API __attribute__ ((regparm (0)))
+#endif
+
+#define TRACE() LogFunc(("tracepoint\n"))
+
+/* Following casts are here to prevent assignment of void * to
+   pointers of arbitrary type */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+# define GET_GLOB_INFO(sb)       ((struct sf_glob_info *) (sb)->u.generic_sbp)
+# define SET_GLOB_INFO(sb, sf_g) (sb)->u.generic_sbp = sf_g
+#else
+# define GET_GLOB_INFO(sb)       ((struct sf_glob_info *) (sb)->s_fs_info)
+# define SET_GLOB_INFO(sb, sf_g) (sb)->s_fs_info = sf_g
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) || defined(KERNEL_FC6)
+/* FC6 kernel 2.6.18, vanilla kernel 2.6.19+ */
+# define GET_INODE_INFO(i)       ((struct sf_inode_info *) (i)->i_private)
+# define SET_INODE_INFO(i, sf_i) (i)->i_private = sf_i
+#else
+/* vanilla kernel up to 2.6.18 */
+# define GET_INODE_INFO(i)       ((struct sf_inode_info *) (i)->u.generic_ip)
+# define SET_INODE_INFO(i, sf_i) (i)->u.generic_ip = sf_i
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+# define GET_F_DENTRY(f)        (f->f_path.dentry)
+#else
+# define GET_F_DENTRY(f)        (f->f_dentry)
+#endif
+
+#endif
+
diff --git a/ubuntu/vbox/vboxvideo/HGSMIBase.c b/ubuntu/vbox/vboxvideo/HGSMIBase.c
new file mode 100644 (file)
index 0000000..0e0e6b1
--- /dev/null
@@ -0,0 +1,694 @@
+/* $Id: HGSMIBase.cpp $ */
+/** @file
+ * VirtualBox Video driver, common code - HGSMI initialisation and helper
+ * functions.
+ */
+
+/*
+ * 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.
+ */
+
+#include <VBox/VBoxVideoGuest.h>
+#include <VBox/VBoxVideo.h>
+#include <VBox/VBoxGuest.h>
+#include <VBox/Hardware/VBoxVideoVBE.h>
+#include <VBox/VMMDev.h>
+
+#include <iprt/asm.h>
+#include <iprt/log.h>
+#include <iprt/string.h>
+
+/** Send completion notification to the host for the command located at offset
+ * @a offt into the host command buffer. */
+static void HGSMINotifyHostCmdComplete(PHGSMIHOSTCOMMANDCONTEXT pCtx, HGSMIOFFSET offt)
+{
+    VBoxVideoCmnPortWriteUlong(pCtx->port, offt);
+}
+
+
+/**
+ * Inform the host that a command has been handled.
+ *
+ * @param  pCtx   the context containing the heap to be used
+ * @param  pvMem  pointer into the heap as mapped in @a pCtx to the command to
+ *                be completed
+ */
+DECLHIDDEN(void) VBoxHGSMIHostCmdComplete(PHGSMIHOSTCOMMANDCONTEXT pCtx,
+                                          void *pvMem)
+{
+    HGSMIBUFFERHEADER *pHdr = HGSMIBufferHeaderFromData(pvMem);
+    HGSMIOFFSET offMem = HGSMIPointerToOffset(&pCtx->areaCtx, pHdr);
+    Assert(offMem != HGSMIOFFSET_VOID);
+    if(offMem != HGSMIOFFSET_VOID)
+    {
+        HGSMINotifyHostCmdComplete(pCtx, offMem);
+    }
+}
+
+
+/** Submit an incoming host command to the appropriate handler. */
+static void hgsmiHostCmdProcess(PHGSMIHOSTCOMMANDCONTEXT pCtx,
+                                HGSMIOFFSET offBuffer)
+{
+    int rc = HGSMIBufferProcess(&pCtx->areaCtx, &pCtx->channels, offBuffer);
+    Assert(!RT_FAILURE(rc));
+    if(RT_FAILURE(rc))
+    {
+        /* failure means the command was not submitted to the handler for some reason
+         * it's our responsibility to notify its completion in this case */
+        HGSMINotifyHostCmdComplete(pCtx, offBuffer);
+    }
+    /* if the cmd succeeded it's responsibility of the callback to complete it */
+}
+
+/** Get the next command from the host. */
+static HGSMIOFFSET hgsmiGetHostBuffer(PHGSMIHOSTCOMMANDCONTEXT pCtx)
+{
+    return VBoxVideoCmnPortReadUlong(pCtx->port);
+}
+
+
+/** Get and handle the next command from the host. */
+static void hgsmiHostCommandQueryProcess(PHGSMIHOSTCOMMANDCONTEXT pCtx)
+{
+    HGSMIOFFSET offset = hgsmiGetHostBuffer(pCtx);
+    AssertReturnVoid(offset != HGSMIOFFSET_VOID);
+    hgsmiHostCmdProcess(pCtx, offset);
+}
+
+
+/** Drain the host command queue. */
+DECLHIDDEN(void) VBoxHGSMIProcessHostQueue(PHGSMIHOSTCOMMANDCONTEXT pCtx)
+{
+    while (pCtx->pfHostFlags->u32HostFlags & HGSMIHOSTFLAGS_COMMANDS_PENDING)
+    {
+        if (!ASMAtomicCmpXchgBool(&pCtx->fHostCmdProcessing, true, false))
+            return;
+        hgsmiHostCommandQueryProcess(pCtx);
+        ASMAtomicWriteBool(&pCtx->fHostCmdProcessing, false);
+    }
+}
+
+
+/** Detect whether HGSMI is supported by the host. */
+DECLHIDDEN(bool) VBoxHGSMIIsSupported(void)
+{
+    uint16_t DispiId;
+
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_HGSMI);
+
+    DispiId = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
+
+    return (DispiId == VBE_DISPI_ID_HGSMI);
+}
+
+
+/**
+ * Allocate and initialise a command descriptor in the guest heap for a
+ * guest-to-host command.
+ *
+ * @returns  pointer to the descriptor's command data buffer
+ * @param  pCtx     the context containing the heap to be used
+ * @param  cbData   the size of the command data to go into the descriptor
+ * @param  u8Ch     the HGSMI channel to be used, set to the descriptor
+ * @param  u16Op    the HGSMI command to be sent, set to the descriptor
+ */
+DECLHIDDEN(void *) VBoxHGSMIBufferAlloc(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                        HGSMISIZE cbData,
+                                        uint8_t u8Ch,
+                                        uint16_t u16Op)
+{
+#ifdef VBOX_WDDM_MINIPORT
+    return VBoxSHGSMIHeapAlloc (&pCtx->heapCtx, cbData, u8Ch, u16Op);
+#else
+    return HGSMIHeapAlloc (&pCtx->heapCtx, cbData, u8Ch, u16Op);
+#endif
+}
+
+
+/**
+ * Free a descriptor allocated by @a VBoxHGSMIBufferAlloc.
+ *
+ * @param  pCtx      the context containing the heap used
+ * @param  pvBuffer  the pointer returned by @a VBoxHGSMIBufferAlloc
+ */
+DECLHIDDEN(void) VBoxHGSMIBufferFree(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                     void *pvBuffer)
+{
+#ifdef VBOX_WDDM_MINIPORT
+    VBoxSHGSMIHeapFree (&pCtx->heapCtx, pvBuffer);
+#else
+    HGSMIHeapFree (&pCtx->heapCtx, pvBuffer);
+#endif
+}
+
+
+/**
+ * Submit a command descriptor allocated by @a VBoxHGSMIBufferAlloc.
+ *
+ * @param  pCtx      the context containing the heap used
+ * @param  pvBuffer  the pointer returned by @a VBoxHGSMIBufferAlloc
+ */
+DECLHIDDEN(int) VBoxHGSMIBufferSubmit(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                      void *pvBuffer)
+{
+    /* Initialize the buffer and get the offset for port IO. */
+    HGSMIOFFSET offBuffer = HGSMIHeapBufferOffset (HGSMIGUESTCMDHEAP_GET(&pCtx->heapCtx), pvBuffer);
+
+    Assert(offBuffer != HGSMIOFFSET_VOID);
+    if (offBuffer != HGSMIOFFSET_VOID)
+    {
+        /* Submit the buffer to the host. */
+        VBoxVideoCmnPortWriteUlong(pCtx->port, offBuffer);
+        /* Make the compiler aware that the host has changed memory. */
+        ASMCompilerBarrier();
+        return VINF_SUCCESS;
+    }
+
+    return VERR_INVALID_PARAMETER;
+}
+
+
+/** Inform the host of the location of the host flags in VRAM via an HGSMI
+ * command. */
+static int vboxHGSMIReportFlagsLocation(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                        HGSMIOFFSET offLocation)
+{
+    HGSMIBUFFERLOCATION *p;
+    int rc = VINF_SUCCESS;
+
+    /* Allocate the IO buffer. */
+    p = (HGSMIBUFFERLOCATION *)VBoxHGSMIBufferAlloc(pCtx,
+                                              sizeof(HGSMIBUFFERLOCATION),
+                                              HGSMI_CH_HGSMI,
+                                              HGSMI_CC_HOST_FLAGS_LOCATION);
+    if (p)
+    {
+        /* Prepare data to be sent to the host. */
+        p->offLocation = offLocation;
+        p->cbLocation  = sizeof(HGSMIHOSTFLAGS);
+        rc = VBoxHGSMIBufferSubmit(pCtx, p);
+        /* Free the IO buffer. */
+        VBoxHGSMIBufferFree(pCtx, p);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+    return rc;
+}
+
+
+/**
+ * Inform the host of the location of the host flags in VRAM via an HGSMI
+ * command.
+ * @returns  IPRT status value.
+ * @returns  VERR_NOT_IMPLEMENTED  if the host does not support the command.
+ * @returns  VERR_NO_MEMORY        if a heap allocation fails.
+ * @param    pCtx                  the context of the guest heap to use.
+ * @param    offLocation           the offset chosen for the flags withing guest
+ *                                 VRAM.
+ */
+DECLHIDDEN(int) VBoxHGSMIReportFlagsLocation(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                             HGSMIOFFSET offLocation)
+{
+    return vboxHGSMIReportFlagsLocation(pCtx, offLocation);
+}
+
+
+/** Notify the host of HGSMI-related guest capabilities via an HGSMI command.
+ */
+static int vboxHGSMISendCapsInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                 uint32_t fCaps)
+{
+    VBVACAPS *pCaps;
+    int rc = VINF_SUCCESS;
+
+    /* Allocate the IO buffer. */
+    pCaps = (VBVACAPS *)VBoxHGSMIBufferAlloc(pCtx,
+                                       sizeof(VBVACAPS), HGSMI_CH_VBVA,
+                                       VBVA_INFO_CAPS);
+
+    if (pCaps)
+    {
+        /* Prepare data to be sent to the host. */
+        pCaps->rc    = VERR_NOT_IMPLEMENTED;
+        pCaps->fCaps = fCaps;
+        rc = VBoxHGSMIBufferSubmit(pCtx, pCaps);
+        if (RT_SUCCESS(rc))
+        {
+            AssertRC(pCaps->rc);
+            rc = pCaps->rc;
+        }
+        /* Free the IO buffer. */
+        VBoxHGSMIBufferFree(pCtx, pCaps);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+    return rc;
+}
+
+
+/**
+ * Notify the host of HGSMI-related guest capabilities via an HGSMI command.
+ * @returns  IPRT status value.
+ * @returns  VERR_NOT_IMPLEMENTED  if the host does not support the command.
+ * @returns  VERR_NO_MEMORY        if a heap allocation fails.
+ * @param    pCtx                  the context of the guest heap to use.
+ * @param    fCaps                 the capabilities to report, see VBVACAPS.
+ */
+DECLHIDDEN(int) VBoxHGSMISendCapsInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                      uint32_t fCaps)
+{
+    return vboxHGSMISendCapsInfo(pCtx, fCaps);
+}
+
+
+/** Tell the host about the location of the area of VRAM set aside for the host
+ * heap. */
+static int vboxHGSMIReportHostArea(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                   uint32_t u32AreaOffset, uint32_t u32AreaSize)
+{
+    VBVAINFOHEAP *p;
+    int rc = VINF_SUCCESS;
+
+    /* Allocate the IO buffer. */
+    p = (VBVAINFOHEAP *)VBoxHGSMIBufferAlloc(pCtx,
+                                       sizeof (VBVAINFOHEAP), HGSMI_CH_VBVA,
+                                       VBVA_INFO_HEAP);
+    if (p)
+    {
+        /* Prepare data to be sent to the host. */
+        p->u32HeapOffset = u32AreaOffset;
+        p->u32HeapSize   = u32AreaSize;
+        rc = VBoxHGSMIBufferSubmit(pCtx, p);
+        /* Free the IO buffer. */
+        VBoxHGSMIBufferFree(pCtx, p);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+    return rc;
+}
+
+
+/**
+ * Get the information needed to map the basic communication structures in
+ * device memory into our address space.  All pointer parameters are optional.
+ *
+ * @param  cbVRAM               how much video RAM is allocated to the device
+ * @param  poffVRAMBaseMapping  where to save the offset from the start of the
+ *                              device VRAM of the whole area to map
+ * @param  pcbMapping           where to save the mapping size
+ * @param  poffGuestHeapMemory  where to save the offset into the mapped area
+ *                              of the guest heap backing memory
+ * @param  pcbGuestHeapMemory   where to save the size of the guest heap
+ *                              backing memory
+ * @param  poffHostFlags        where to save the offset into the mapped area
+ *                              of the host flags
+ */
+DECLHIDDEN(void) VBoxHGSMIGetBaseMappingInfo(uint32_t cbVRAM,
+                                             uint32_t *poffVRAMBaseMapping,
+                                             uint32_t *pcbMapping,
+                                             uint32_t *poffGuestHeapMemory,
+                                             uint32_t *pcbGuestHeapMemory,
+                                             uint32_t *poffHostFlags)
+{
+    AssertPtrNullReturnVoid(poffVRAMBaseMapping);
+    AssertPtrNullReturnVoid(pcbMapping);
+    AssertPtrNullReturnVoid(poffGuestHeapMemory);
+    AssertPtrNullReturnVoid(pcbGuestHeapMemory);
+    AssertPtrNullReturnVoid(poffHostFlags);
+    if (poffVRAMBaseMapping)
+        *poffVRAMBaseMapping = cbVRAM - VBVA_ADAPTER_INFORMATION_SIZE;
+    if (pcbMapping)
+        *pcbMapping = VBVA_ADAPTER_INFORMATION_SIZE;
+    if (poffGuestHeapMemory)
+        *poffGuestHeapMemory = 0;
+    if (pcbGuestHeapMemory)
+        *pcbGuestHeapMemory =   VBVA_ADAPTER_INFORMATION_SIZE
+                              - sizeof(HGSMIHOSTFLAGS);
+    if (poffHostFlags)
+        *poffHostFlags =   VBVA_ADAPTER_INFORMATION_SIZE
+                         - sizeof(HGSMIHOSTFLAGS);
+}
+
+
+/**
+ * Set up the HGSMI guest-to-host command context.
+ * @returns iprt status value
+ * @param  pCtx                    the context to set up
+ * @param  pvGuestHeapMemory       a pointer to the mapped backing memory for
+ *                                 the guest heap
+ * @param  cbGuestHeapMemory       the size of the backing memory area
+ * @param  offVRAMGuestHeapMemory  the offset of the memory pointed to by
+ *                                 @a pvGuestHeapMemory within the video RAM
+ */
+DECLHIDDEN(int) VBoxHGSMISetupGuestContext(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                           void *pvGuestHeapMemory,
+                                           uint32_t cbGuestHeapMemory,
+                                           uint32_t offVRAMGuestHeapMemory,
+                                           const HGSMIENV *pEnv)
+{
+    /** @todo should we be using a fixed ISA port value here? */
+    pCtx->port = (RTIOPORT)VGA_PORT_HGSMI_GUEST;
+#ifdef VBOX_WDDM_MINIPORT
+    return VBoxSHGSMIInit(&pCtx->heapCtx, pvGuestHeapMemory,
+                          cbGuestHeapMemory, offVRAMGuestHeapMemory, pEnv);
+#else
+    return HGSMIHeapSetup(&pCtx->heapCtx, pvGuestHeapMemory,
+                          cbGuestHeapMemory, offVRAMGuestHeapMemory, pEnv);
+#endif
+}
+
+
+/**
+ * Get the information needed to map the area used by the host to send back
+ * requests.
+ *
+ * @param  pCtx                the context containing the heap to use
+ * @param  cbVRAM              how much video RAM is allocated to the device
+ * @param  offVRAMBaseMapping  the offset of the basic communication structures
+ *                             into the guest's VRAM
+ * @param  poffVRAMHostArea    where to store the offset into VRAM of the host
+ *                             heap area
+ * @param  pcbHostArea         where to store the size of the host heap area
+ */
+DECLHIDDEN(void) VBoxHGSMIGetHostAreaMapping(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                             uint32_t cbVRAM,
+                                             uint32_t offVRAMBaseMapping,
+                                             uint32_t *poffVRAMHostArea,
+                                             uint32_t *pcbHostArea)
+{
+    uint32_t offVRAMHostArea = offVRAMBaseMapping, cbHostArea = 0;
+
+    AssertPtrReturnVoid(poffVRAMHostArea);
+    AssertPtrReturnVoid(pcbHostArea);
+    VBoxQueryConfHGSMI(pCtx, VBOX_VBVA_CONF32_HOST_HEAP_SIZE, &cbHostArea);
+    if (cbHostArea != 0)
+    {
+        uint32_t cbHostAreaMaxSize = cbVRAM / 4;
+        /** @todo what is the idea of this? */
+        if (cbHostAreaMaxSize >= VBVA_ADAPTER_INFORMATION_SIZE)
+        {
+            cbHostAreaMaxSize -= VBVA_ADAPTER_INFORMATION_SIZE;
+        }
+        if (cbHostArea > cbHostAreaMaxSize)
+        {
+            cbHostArea = cbHostAreaMaxSize;
+        }
+        /* Round up to 4096 bytes. */
+        cbHostArea = (cbHostArea + 0xFFF) & ~0xFFF;
+        offVRAMHostArea = offVRAMBaseMapping - cbHostArea;
+    }
+
+    *pcbHostArea = cbHostArea;
+    *poffVRAMHostArea = offVRAMHostArea;
+    LogFunc(("offVRAMHostArea = 0x%08X, cbHostArea = 0x%08X\n",
+             offVRAMHostArea, cbHostArea));
+}
+
+
+/**
+ * Initialise the host context structure.
+ *
+ * @param  pCtx               the context structure to initialise
+ * @param  pvBaseMapping      where the basic HGSMI structures are mapped at
+ * @param  offHostFlags       the offset of the host flags into the basic HGSMI
+ *                            structures
+ * @param  pvHostAreaMapping  where the area for the host heap is mapped at
+ * @param  offVRAMHostArea    offset of the host heap area into VRAM
+ * @param  cbHostArea         size in bytes of the host heap area
+ */
+DECLHIDDEN(void) VBoxHGSMISetupHostContext(PHGSMIHOSTCOMMANDCONTEXT pCtx,
+                                           void *pvBaseMapping,
+                                           uint32_t offHostFlags,
+                                           void *pvHostAreaMapping,
+                                           uint32_t offVRAMHostArea,
+                                           uint32_t cbHostArea)
+{
+    uint8_t *pu8HostFlags = ((uint8_t *)pvBaseMapping) + offHostFlags;
+    pCtx->pfHostFlags = (HGSMIHOSTFLAGS *)pu8HostFlags;
+    /** @todo should we really be using a fixed ISA port value here? */
+    pCtx->port        = (RTIOPORT)VGA_PORT_HGSMI_HOST;
+    HGSMIAreaInitialize(&pCtx->areaCtx, pvHostAreaMapping, cbHostArea,
+                         offVRAMHostArea);
+}
+
+
+/**
+ * Tell the host about the ways it can use to communicate back to us via an
+ * HGSMI command
+ *
+ * @returns  iprt status value
+ * @param  pCtx                  the context containing the heap to use
+ * @param  offVRAMFlagsLocation  where we wish the host to place its flags
+ *                               relative to the start of the VRAM
+ * @param  fCaps                 additions HGSMI capabilities the guest
+ *                               supports
+ * @param  offVRAMHostArea       offset into VRAM of the host heap area
+ * @param  cbHostArea            size in bytes of the host heap area
+ */
+DECLHIDDEN(int) VBoxHGSMISendHostCtxInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                         HGSMIOFFSET offVRAMFlagsLocation,
+                                         uint32_t fCaps,
+                                         uint32_t offVRAMHostArea,
+                                         uint32_t cbHostArea)
+{
+    Log(("VBoxVideo::vboxSetupAdapterInfo\n"));
+
+    /* setup the flags first to ensure they are initialized by the time the
+     * host heap is ready */
+    int rc = vboxHGSMIReportFlagsLocation(pCtx, offVRAMFlagsLocation);
+    AssertRC(rc);
+    if (RT_SUCCESS(rc) && fCaps)
+    {
+        /* Inform about caps */
+        rc = vboxHGSMISendCapsInfo(pCtx, fCaps);
+        AssertRC(rc);
+    }
+    if (RT_SUCCESS (rc))
+    {
+        /* Report the host heap location. */
+        rc = vboxHGSMIReportHostArea(pCtx, offVRAMHostArea, cbHostArea);
+        AssertRC(rc);
+    }
+    Log(("VBoxVideo::vboxSetupAdapterInfo finished rc = %d\n", rc));
+    return rc;
+}
+
+
+/** Sanity test on first call.  We do not worry about concurrency issues. */
+static int testQueryConf(PHGSMIGUESTCOMMANDCONTEXT pCtx)
+{
+    static bool cOnce = false;
+    uint32_t ulValue = 0;
+    int rc;
+
+    if (cOnce)
+        return VINF_SUCCESS;
+    cOnce = true;
+    rc = VBoxQueryConfHGSMI(pCtx, UINT32_MAX, &ulValue);
+    if (RT_SUCCESS(rc) && ulValue == UINT32_MAX)
+        return VINF_SUCCESS;
+    cOnce = false;
+    if (RT_FAILURE(rc))
+        return rc;
+    return VERR_INTERNAL_ERROR;
+}
+
+
+/**
+ * Query the host for an HGSMI configuration parameter via an HGSMI command.
+ * @returns iprt status value
+ * @param  pCtx      the context containing the heap used
+ * @param  u32Index  the index of the parameter to query,
+ *                   @see VBVACONF32::u32Index
+ * @param  u32DefValue defaut value
+ * @param  pulValue  where to store the value of the parameter on success
+ */
+DECLHIDDEN(int) VBoxQueryConfHGSMIDef(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                      uint32_t u32Index, uint32_t u32DefValue, uint32_t *pulValue)
+{
+    int rc = VINF_SUCCESS;
+    VBVACONF32 *p;
+    LogFunc(("u32Index = %d\n", u32Index));
+
+    rc = testQueryConf(pCtx);
+    if (RT_FAILURE(rc))
+        return rc;
+    /* Allocate the IO buffer. */
+    p = (VBVACONF32 *)VBoxHGSMIBufferAlloc(pCtx,
+                                     sizeof(VBVACONF32), HGSMI_CH_VBVA,
+                                     VBVA_QUERY_CONF32);
+    if (p)
+    {
+        /* Prepare data to be sent to the host. */
+        p->u32Index = u32Index;
+        p->u32Value = u32DefValue;
+        rc = VBoxHGSMIBufferSubmit(pCtx, p);
+        if (RT_SUCCESS(rc))
+        {
+            *pulValue = p->u32Value;
+            LogFunc(("u32Value = %d\n", p->u32Value));
+        }
+        /* Free the IO buffer. */
+        VBoxHGSMIBufferFree(pCtx, p);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+    LogFunc(("rc = %d\n", rc));
+    return rc;
+}
+
+DECLHIDDEN(int) VBoxQueryConfHGSMI(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                   uint32_t u32Index, uint32_t *pulValue)
+{
+    return VBoxQueryConfHGSMIDef(pCtx, u32Index, UINT32_MAX, pulValue);
+}
+
+/**
+ * Pass the host a new mouse pointer shape via an HGSMI command.
+ *
+ * @returns  success or failure
+ * @param  fFlags    cursor flags, @see VMMDevReqMousePointer::fFlags
+ * @param  cHotX     horizontal position of the hot spot
+ * @param  cHotY     vertical position of the hot spot
+ * @param  cWidth    width in pixels of the cursor
+ * @param  cHeight   height in pixels of the cursor
+ * @param  pPixels   pixel data, @see VMMDevReqMousePointer for the format
+ * @param  cbLength  size in bytes of the pixel data
+ */
+DECLHIDDEN(int)  VBoxHGSMIUpdatePointerShape(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                             uint32_t fFlags,
+                                             uint32_t cHotX,
+                                             uint32_t cHotY,
+                                             uint32_t cWidth,
+                                             uint32_t cHeight,
+                                             uint8_t *pPixels,
+                                             uint32_t cbLength)
+{
+    VBVAMOUSEPOINTERSHAPE *p;
+    uint32_t cbData = 0;
+    int rc = VINF_SUCCESS;
+
+    if (fFlags & VBOX_MOUSE_POINTER_SHAPE)
+    {
+        /* Size of the pointer data: sizeof (AND mask) + sizeof (XOR_MASK) */
+        cbData = ((((cWidth + 7) / 8) * cHeight + 3) & ~3)
+                 + cWidth * 4 * cHeight;
+        /* If shape is supplied, then always create the pointer visible.
+         * See comments in 'vboxUpdatePointerShape'
+         */
+        fFlags |= VBOX_MOUSE_POINTER_VISIBLE;
+    }
+    LogFlowFunc(("cbData %d, %dx%d\n", cbData, cWidth, cHeight));
+    if (cbData > cbLength)
+    {
+        LogFunc(("calculated pointer data size is too big (%d bytes, limit %d)\n",
+                 cbData, cbLength));
+        return VERR_INVALID_PARAMETER;
+    }
+    /* Allocate the IO buffer. */
+    p = (VBVAMOUSEPOINTERSHAPE *)VBoxHGSMIBufferAlloc(pCtx,
+                                                  sizeof(VBVAMOUSEPOINTERSHAPE)
+                                                + cbData,
+                                                HGSMI_CH_VBVA,
+                                                VBVA_MOUSE_POINTER_SHAPE);
+    if (p)
+    {
+        /* Prepare data to be sent to the host. */
+        /* Will be updated by the host. */
+        p->i32Result = VINF_SUCCESS;
+        /* We have our custom flags in the field */
+        p->fu32Flags = fFlags;
+        p->u32HotX   = cHotX;
+        p->u32HotY   = cHotY;
+        p->u32Width  = cWidth;
+        p->u32Height = cHeight;
+        if (p->fu32Flags & VBOX_MOUSE_POINTER_SHAPE)
+            /* Copy the actual pointer data. */
+            memcpy (p->au8Data, pPixels, cbData);
+        rc = VBoxHGSMIBufferSubmit(pCtx, p);
+        if (RT_SUCCESS(rc))
+            rc = p->i32Result;
+        /* Free the IO buffer. */
+        VBoxHGSMIBufferFree(pCtx, p);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+    LogFlowFunc(("rc %d\n", rc));
+    return rc;
+}
+
+
+/**
+ * Report the guest cursor position.  The host may wish to use this information
+ * to re-position its own cursor (though this is currently unlikely).  The
+ * current host cursor position is returned.
+ * @param  pCtx             The context containing the heap used.
+ * @param  fReportPosition  Are we reporting a position?
+ * @param  x                Guest cursor X position.
+ * @param  y                Guest cursor Y position.
+ * @param  pxHost           Host cursor X position is stored here.  Optional.
+ * @param  pyHost           Host cursor Y position is stored here.  Optional.
+ * @returns  iprt status code.
+ * @returns  VERR_NO_MEMORY      HGSMI heap allocation failed.
+ */
+DECLHIDDEN(int) VBoxHGSMICursorPosition(PHGSMIGUESTCOMMANDCONTEXT pCtx, bool fReportPosition, uint32_t x, uint32_t y,
+                                        uint32_t *pxHost, uint32_t *pyHost)
+{
+    int rc = VINF_SUCCESS;
+    VBVACURSORPOSITION *p;
+    Log(("%s: x=%u, y=%u\n", __PRETTY_FUNCTION__, (unsigned)x, (unsigned)y));
+
+    /* Allocate the IO buffer. */
+    p = (VBVACURSORPOSITION *)VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVACURSORPOSITION), HGSMI_CH_VBVA, VBVA_CURSOR_POSITION);
+    if (p)
+    {
+        /* Prepare data to be sent to the host. */
+        p->fReportPosition = fReportPosition ? 1 : 0;
+        p->x = x;
+        p->y = y;
+        rc = VBoxHGSMIBufferSubmit(pCtx, p);
+        if (RT_SUCCESS(rc))
+        {
+            if (pxHost)
+                *pxHost = p->x;
+            if (pyHost)
+                *pyHost = p->y;
+            Log(("%s: return: x=%u, y=%u\n", __PRETTY_FUNCTION__, (unsigned)p->x, (unsigned)p->y));
+        }
+        /* Free the IO buffer. */
+        VBoxHGSMIBufferFree(pCtx, p);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+    LogFunc(("rc = %d\n", rc));
+    return rc;
+}
+
+
+/** @todo Mouse pointer position to be read from VMMDev memory, address of the memory region
+ * can be queried from VMMDev via an IOCTL. This VMMDev memory region will contain
+ * host information which is needed by the guest.
+ *
+ * Reading will not cause a switch to the host.
+ *
+ * Have to take into account:
+ *  * synchronization: host must write to the memory only from EMT,
+ *    large structures must be read under flag, which tells the host
+ *    that the guest is currently reading the memory (OWNER flag?).
+ *  * guest writes: may be allocate a page for the host info and make
+ *    the page readonly for the guest.
+ *  * the information should be available only for additions drivers.
+ *  * VMMDev additions driver will inform the host which version of the info it expects,
+ *    host must support all versions.
+ *
+ */
diff --git a/ubuntu/vbox/vboxvideo/HGSMICommon.c b/ubuntu/vbox/vboxvideo/HGSMICommon.c
new file mode 100644 (file)
index 0000000..5d4b06c
--- /dev/null
@@ -0,0 +1,433 @@
+/* $Id: HGSMICommon.cpp $ */
+/** @file
+ * VBox Host Guest Shared Memory Interface (HGSMI) - Functions common to both host and guest.
+ */
+
+/*
+ * 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.
+ */
+
+#define LOG_DISABLED /* Maybe we can enabled it all the time now? */
+#define LOG_GROUP LOG_GROUP_HGSMI
+#include <iprt/heap.h>
+#include <iprt/string.h>
+
+#include <VBox/HGSMI/HGSMI.h>
+#include <VBox/log.h>
+
+
+/* Channel flags. */
+#define HGSMI_CH_F_REGISTERED 0x01
+
+/* Assertions for situations which could happen and normally must be processed properly
+ * but must be investigated during development: guest misbehaving, etc.
+ */
+#ifdef HGSMI_STRICT
+#define HGSMI_STRICT_ASSERT_FAILED() AssertFailed()
+#define HGSMI_STRICT_ASSERT(expr) Assert(expr)
+#else
+#define HGSMI_STRICT_ASSERT_FAILED() do {} while (0)
+#define HGSMI_STRICT_ASSERT(expr) do {} while (0)
+#endif /* !HGSMI_STRICT */
+
+/* One-at-a-Time Hash from
+ * http://www.burtleburtle.net/bob/hash/doobs.html
+ *
+ * ub4 one_at_a_time(char *key, ub4 len)
+ * {
+ *   ub4   hash, i;
+ *   for (hash=0, i=0; i<len; ++i)
+ *   {
+ *     hash += key[i];
+ *     hash += (hash << 10);
+ *     hash ^= (hash >> 6);
+ *   }
+ *   hash += (hash << 3);
+ *   hash ^= (hash >> 11);
+ *   hash += (hash << 15);
+ *   return hash;
+ * }
+ */
+
+static uint32_t hgsmiHashBegin(void)
+{
+    return 0;
+}
+
+static uint32_t hgsmiHashProcess(uint32_t hash,
+                                 const void *pvData,
+                                 size_t cbData)
+{
+    const uint8_t *pu8Data = (const uint8_t *)pvData;
+
+    while (cbData--)
+    {
+        hash += *pu8Data++;
+        hash += (hash << 10);
+        hash ^= (hash >> 6);
+    }
+
+    return hash;
+}
+
+static uint32_t hgsmiHashEnd(uint32_t hash)
+{
+    hash += (hash << 3);
+    hash ^= (hash >> 11);
+    hash += (hash << 15);
+
+    return hash;
+}
+
+uint32_t HGSMIChecksum(HGSMIOFFSET offBuffer,
+                       const HGSMIBUFFERHEADER *pHeader,
+                       const HGSMIBUFFERTAIL *pTail)
+{
+    uint32_t u32Checksum = hgsmiHashBegin();
+
+    u32Checksum = hgsmiHashProcess(u32Checksum, &offBuffer, sizeof(offBuffer));
+    u32Checksum = hgsmiHashProcess(u32Checksum, pHeader, sizeof(HGSMIBUFFERHEADER));
+    u32Checksum = hgsmiHashProcess(u32Checksum, pTail, RT_OFFSETOF(HGSMIBUFFERTAIL, u32Checksum));
+
+    return hgsmiHashEnd(u32Checksum);
+}
+
+int HGSMIAreaInitialize(HGSMIAREA *pArea,
+                        void *pvBase,
+                        HGSMISIZE cbArea,
+                        HGSMIOFFSET offBase)
+{
+    uint8_t *pu8Base = (uint8_t *)pvBase;
+
+    if (  !pArea                                   /* Check that the area: */
+        || cbArea < HGSMIBufferMinimumSize()       /* large enough; */
+        || pu8Base + cbArea < pu8Base              /* no address space wrap; */
+        || offBase > UINT32_C(0xFFFFFFFF) - cbArea /* area within the 32 bit space: offBase + cbMem <= 0xFFFFFFFF. */
+       )
+    {
+        return VERR_INVALID_PARAMETER;
+    }
+
+    pArea->pu8Base = pu8Base;
+    pArea->offBase = offBase;
+    pArea->offLast = cbArea - HGSMIBufferMinimumSize() + offBase;
+    pArea->cbArea = cbArea;
+
+    return VINF_SUCCESS;
+}
+
+void HGSMIAreaClear(HGSMIAREA *pArea)
+{
+    if (pArea)
+    {
+        RT_ZERO(*pArea);
+    }
+}
+
+/* Initialize the memory buffer including its checksum.
+ * No changes alloed to the header and the tail after that.
+ */
+HGSMIOFFSET HGSMIBufferInitializeSingle(const HGSMIAREA *pArea,
+                                        HGSMIBUFFERHEADER *pHeader,
+                                        HGSMISIZE cbBuffer,
+                                        uint8_t u8Channel,
+                                        uint16_t u16ChannelInfo)
+{
+    if (   !pArea
+        || !pHeader
+        || cbBuffer < HGSMIBufferMinimumSize())
+    {
+        return HGSMIOFFSET_VOID;
+    }
+
+    /* Buffer must be within the area:
+     *   * header data size do not exceed the maximum data size;
+     *   * buffer address is greater than the area base address;
+     *   * buffer address is lower than the maximum allowed for the given data size.
+     */
+    HGSMISIZE cbMaximumDataSize = pArea->offLast - pArea->offBase;
+    uint32_t u32DataSize = cbBuffer - HGSMIBufferMinimumSize();
+
+    if (   u32DataSize > cbMaximumDataSize
+        || (uint8_t *)pHeader < pArea->pu8Base
+        || (uint8_t *)pHeader > pArea->pu8Base + cbMaximumDataSize - u32DataSize)
+    {
+        return HGSMIOFFSET_VOID;
+    }
+
+    HGSMIOFFSET offBuffer = HGSMIPointerToOffset(pArea, pHeader);
+
+    pHeader->u8Flags        = HGSMI_BUFFER_HEADER_F_SEQ_SINGLE;
+    pHeader->u32DataSize    = u32DataSize;
+    pHeader->u8Channel      = u8Channel;
+    pHeader->u16ChannelInfo = u16ChannelInfo;
+    RT_ZERO(pHeader->u.au8Union);
+
+    HGSMIBUFFERTAIL *pTail = HGSMIBufferTailFromPtr(pHeader, u32DataSize);
+    pTail->u32Reserved = 0;
+    pTail->u32Checksum = HGSMIChecksum(offBuffer, pHeader, pTail);
+
+    return offBuffer;
+}
+
+int HGSMIHeapSetup(HGSMIHEAP *pHeap,
+                   void *pvBase,
+                   HGSMISIZE cbArea,
+                   HGSMIOFFSET offBase,
+                   const HGSMIENV *pEnv)
+{
+    AssertPtrReturn(pHeap, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pvBase, VERR_INVALID_PARAMETER);
+
+    int rc = HGSMIAreaInitialize(&pHeap->area, pvBase, cbArea, offBase);
+    if (RT_SUCCESS(rc))
+    {
+        rc = HGSMIMAInit(&pHeap->ma, &pHeap->area, NULL, 0, 0, pEnv);
+        if (RT_FAILURE(rc))
+        {
+            HGSMIAreaClear(&pHeap->area);
+        }
+    }
+
+    return rc;
+}
+
+void HGSMIHeapDestroy(HGSMIHEAP *pHeap)
+{
+    if (pHeap)
+    {
+        HGSMIMAUninit(&pHeap->ma);
+        RT_ZERO(*pHeap);
+    }
+}
+
+void *HGSMIHeapAlloc(HGSMIHEAP *pHeap,
+                     HGSMISIZE cbData,
+                     uint8_t u8Channel,
+                     uint16_t u16ChannelInfo)
+{
+    HGSMISIZE cbAlloc = HGSMIBufferRequiredSize(cbData);
+    HGSMIBUFFERHEADER *pHeader = (HGSMIBUFFERHEADER *)HGSMIHeapBufferAlloc(pHeap, cbAlloc);
+    if (pHeader)
+    {
+        HGSMIOFFSET offBuffer = HGSMIBufferInitializeSingle(HGSMIHeapArea(pHeap), pHeader,
+                                                            cbAlloc, u8Channel, u16ChannelInfo);
+        if (offBuffer == HGSMIOFFSET_VOID)
+        {
+            HGSMIHeapBufferFree(pHeap, pHeader);
+            pHeader = NULL;
+        }
+    }
+
+    return pHeader? HGSMIBufferDataFromPtr(pHeader): NULL;
+}
+
+void HGSMIHeapFree(HGSMIHEAP *pHeap,
+                   void *pvData)
+{
+    if (pvData)
+    {
+        HGSMIBUFFERHEADER *pHeader = HGSMIBufferHeaderFromData(pvData);
+        HGSMIHeapBufferFree(pHeap, pHeader);
+    }
+}
+
+void *HGSMIHeapBufferAlloc(HGSMIHEAP *pHeap,
+                           HGSMISIZE cbBuffer)
+{
+    void *pvBuf = HGSMIMAAlloc(&pHeap->ma, cbBuffer);
+    return pvBuf;
+}
+
+void HGSMIHeapBufferFree(HGSMIHEAP *pHeap,
+                         void *pvBuf)
+{
+    HGSMIMAFree(&pHeap->ma, pvBuf);
+}
+
+typedef struct HGSMIBUFFERCONTEXT
+{
+    const HGSMIBUFFERHEADER *pHeader; /* The original buffer header. */
+    void *pvData;                     /* Payload data in the buffer./ */
+    uint32_t cbData;                  /* Size of data  */
+} HGSMIBUFFERCONTEXT;
+
+/** Verify that the given offBuffer points to a valid buffer, which is within the area.
+ *
+ * @returns VBox status and the buffer information in pBufferContext.
+ * @param pArea          Area which supposed to contain the buffer.
+ * @param offBuffer      The buffer location in the area.
+ * @param pBufferContext Where to write information about the buffer.
+ */
+static int hgsmiVerifyBuffer(const HGSMIAREA *pArea,
+                             HGSMIOFFSET offBuffer,
+                             HGSMIBUFFERCONTEXT *pBufferContext)
+{
+    LogFlowFunc(("buffer 0x%x, area %p %x [0x%x;0x%x]\n",
+                 offBuffer, pArea->pu8Base, pArea->cbArea, pArea->offBase, pArea->offLast));
+
+    int rc = VINF_SUCCESS;
+
+    if (   offBuffer < pArea->offBase
+        || offBuffer > pArea->offLast)
+    {
+        LogFunc(("offset 0x%x is outside the area [0x%x;0x%x]!!!\n",
+                 offBuffer, pArea->offBase, pArea->offLast));
+        rc = VERR_INVALID_PARAMETER;
+        HGSMI_STRICT_ASSERT_FAILED();
+    }
+    else
+    {
+        void *pvBuffer = HGSMIOffsetToPointer(pArea, offBuffer);
+        HGSMIBUFFERHEADER header = *HGSMIBufferHeaderFromPtr(pvBuffer);
+
+        /* Quick check of the data size, it should be less than the maximum
+         * data size for the buffer at this offset.
+         */
+        LogFlowFunc(("datasize check: header.u32DataSize = 0x%x pArea->offLast - offBuffer = 0x%x\n",
+                     header.u32DataSize, pArea->offLast - offBuffer));
+
+        if (header.u32DataSize <= pArea->offLast - offBuffer)
+        {
+            HGSMIBUFFERTAIL tail = *HGSMIBufferTailFromPtr(pvBuffer, header.u32DataSize);
+
+            /* At least both header and tail structures are in the area. Check the checksum. */
+            uint32_t u32Checksum = HGSMIChecksum(offBuffer, &header, &tail);
+            LogFlowFunc(("checksum check: u32Checksum = 0x%x pTail->u32Checksum = 0x%x\n",
+                         u32Checksum, tail.u32Checksum));
+            if (u32Checksum == tail.u32Checksum)
+            {
+                /* Success. */
+                pBufferContext->pHeader = HGSMIBufferHeaderFromPtr(pvBuffer);
+                pBufferContext->pvData = HGSMIBufferDataFromPtr(pvBuffer);
+                pBufferContext->cbData = header.u32DataSize;
+            }
+            else
+            {
+                LogFunc(("invalid checksum 0x%x, expected 0x%x!!!\n",
+                         u32Checksum, tail.u32Checksum));
+                rc = VERR_INVALID_STATE;
+                HGSMI_STRICT_ASSERT_FAILED();
+            }
+        }
+        else
+        {
+            LogFunc(("invalid data size 0x%x, maximum is 0x%x!!!\n",
+                     header.u32DataSize, pArea->offLast - offBuffer));
+            rc = VERR_TOO_MUCH_DATA;
+            HGSMI_STRICT_ASSERT_FAILED();
+        }
+    }
+
+    return rc;
+}
+
+/** Helper to convert HGSMI channel index to the channel structure pointer.
+ *
+ * @returns Pointer to the channel data.
+ * @param pChannelInfo The channel pool.
+ * @param u8Channel    The channel index.
+ */
+HGSMICHANNEL *HGSMIChannelFindById(HGSMICHANNELINFO *pChannelInfo,
+                                   uint8_t u8Channel)
+{
+    AssertCompile(RT_ELEMENTS(pChannelInfo->Channels) >= 0x100);
+    HGSMICHANNEL *pChannel = &pChannelInfo->Channels[u8Channel];
+
+    if (pChannel->u8Flags & HGSMI_CH_F_REGISTERED)
+    {
+        return pChannel;
+    }
+
+    return NULL;
+}
+
+/** Process a guest buffer.
+ *
+ * @returns VBox status code.
+ * @param pArea        Area which supposed to contain the buffer.
+ * @param pChannelInfo The channel pool.
+ * @param offBuffer    The buffer location in the area.
+ */
+int HGSMIBufferProcess(const HGSMIAREA *pArea,
+                       HGSMICHANNELINFO *pChannelInfo,
+                       HGSMIOFFSET offBuffer)
+{
+    LogFlowFunc(("pArea %p, offBuffer 0x%x\n", pArea, offBuffer));
+
+    AssertPtrReturn(pArea, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pChannelInfo, VERR_INVALID_PARAMETER);
+
+    /* Guest has prepared a command description at 'offBuffer'. */
+    HGSMIBUFFERCONTEXT bufferContext = { NULL, NULL, 0 }; /* Makes old GCC happier. */
+    int rc = hgsmiVerifyBuffer(pArea, offBuffer, &bufferContext);
+    if (RT_SUCCESS(rc))
+    {
+        /* Pass the command to the appropriate handler registered with this instance.
+         * Start with the handler list head, which is the preallocated HGSMI setup channel.
+         */
+        const HGSMICHANNEL *pChannel = HGSMIChannelFindById(pChannelInfo, bufferContext.pHeader->u8Channel);
+        if (pChannel)
+        {
+            const HGSMICHANNELHANDLER *pHandler = &pChannel->handler;
+            if (pHandler->pfnHandler)
+            {
+                pHandler->pfnHandler(pHandler->pvHandler, bufferContext.pHeader->u16ChannelInfo,
+                                     bufferContext.pvData, bufferContext.cbData);
+            }
+            HGSMI_STRICT_ASSERT(RT_SUCCESS(hgsmiVerifyBuffer(pArea, offBuffer, &bufferContext)));
+        }
+        else
+        {
+            rc = VERR_INVALID_FUNCTION;
+            HGSMI_STRICT_ASSERT_FAILED();
+        }
+    }
+
+    return rc;
+}
+
+/** Register a new HGSMI channel by index.
+ *
+ * @returns VBox status code.
+ * @param pChannelInfo      The channel pool managed by the caller.
+ * @param u8Channel         Index of the channel.
+ * @param pszName           Name of the channel (optional, allocated by the caller).
+ * @param pfnChannelHandler The channel callback.
+ * @param pvChannelHandler  The callback pointer.
+ */
+int HGSMIChannelRegister(HGSMICHANNELINFO *pChannelInfo,
+                         uint8_t u8Channel,
+                         const char *pszName,
+                         PFNHGSMICHANNELHANDLER pfnChannelHandler,
+                         void *pvChannelHandler)
+{
+    /* Check whether the channel is already registered. */
+    HGSMICHANNEL *pChannel = HGSMIChannelFindById(pChannelInfo, u8Channel);
+    if (pChannel)
+    {
+        HGSMI_STRICT_ASSERT_FAILED();
+        return VERR_ALREADY_EXISTS;
+    }
+
+    /* Channel is not yet registered. */
+    pChannel = &pChannelInfo->Channels[u8Channel];
+
+    pChannel->u8Flags = HGSMI_CH_F_REGISTERED;
+    pChannel->u8Channel = u8Channel;
+
+    pChannel->handler.pfnHandler = pfnChannelHandler;
+    pChannel->handler.pvHandler = pvChannelHandler;
+
+    pChannel->pszName = pszName;
+
+    return VINF_SUCCESS;
+}
diff --git a/ubuntu/vbox/vboxvideo/HGSMIMemAlloc.c b/ubuntu/vbox/vboxvideo/HGSMIMemAlloc.c
new file mode 100644 (file)
index 0000000..8997f76
--- /dev/null
@@ -0,0 +1,661 @@
+/* $Id: HGSMIMemAlloc.cpp $ */
+/** @file
+ * VBox Host Guest Shared Memory Interface (HGSMI) - Memory allocator.
+ */
+
+/*
+ * Copyright (C) 2014-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.
+ */
+
+/*
+ * Memory allocator
+ * ----------------
+ *
+ * Area [0; AreaSize) contains only the data, control structures are separate.
+ * Block sizes are power of 2: 32B, ..., 1MB
+ * Area size can be anything and will be divided initially to largest possible free blocks.
+ *
+ * The entire area is described by a list of 32 bit block descriptors:
+ *  * bits 0..3  - order, which is log2 size of the block - 5: 2^(0+5) ... 2^(15+5) == 32B .. 1MB
+ *  * bit  4     - 1 for free blocks.
+ *  * bits 5..31 - block offset.
+ *
+ * 31 ... 5 | 4 | 3 ... 0
+ *  offset    F   order
+ *
+ * There is a sorted collection of all block descriptors
+ * (key is the block offset, bits 0...4 do not interfere with sorting).
+ * Also there are lists of free blocks for each size for fast allocation.
+ *
+ *
+ * Implementation
+ * --------------
+ *
+ * The blocks collection is a sorted linear list.
+ *
+ * Initially the entire area consists of one or more largest blocks followed by smaller blocks:
+ *  * 100B area - 64B block with descriptor: 0x00000011
+ *                32B block with descriptor: 0x00000030
+ *                4B unused
+ *  * 64K area  - one 64K block with descriptor: 0x0000001C
+ *  * 512K area - one 512K block with descriptor: 0x0000001F
+ *
+ * When allocating a new block:
+ *  * larger free blocks are splitted when there are no smaller free blocks;
+ *  * smaller free blocks are merged if they can build a requested larger block.
+ */
+#include <VBox/HGSMI/HGSMIMemAlloc.h>
+#include <VBox/HGSMI/HGSMI.h>
+
+#include <iprt/err.h>
+#include <iprt/string.h>
+
+
+DECLINLINE(HGSMIOFFSET) hgsmiMADescriptor(HGSMIOFFSET off, bool fFree, HGSMIOFFSET order)
+{
+    return (off & HGSMI_MA_DESC_OFFSET_MASK) |
+           (fFree? HGSMI_MA_DESC_FREE_MASK: 0) |
+           (order & HGSMI_MA_DESC_ORDER_MASK);
+}
+
+static void hgsmiMABlockFree(HGSMIMADATA *pMA, HGSMIMABLOCK *pBlock)
+{
+    pMA->env.pfnFree(pMA->env.pvEnv, pBlock);
+}
+
+static int hgsmiMABlockAlloc(HGSMIMADATA *pMA, HGSMIMABLOCK **ppBlock)
+{
+    int rc = VINF_SUCCESS;
+
+    HGSMIMABLOCK *pBlock = (HGSMIMABLOCK *)pMA->env.pfnAlloc(pMA->env.pvEnv, sizeof(HGSMIMABLOCK));
+    if (pBlock)
+    {
+        RT_ZERO(pBlock->nodeBlock);
+        *ppBlock = pBlock;
+    }
+    else
+    {
+        rc = VERR_NO_MEMORY;
+    }
+
+    return rc;
+}
+
+/* Divide entire area to free blocks. */
+static int hgsmiMAFormat(HGSMIMADATA *pMA)
+{
+    int rc = VINF_SUCCESS;
+
+    /* Initial value, it will be updated in the loop below. */
+    pMA->cbMaxBlock = HGSMI_MA_BLOCK_SIZE_MIN;
+    pMA->cBlocks = 0;
+
+    HGSMISIZE cbBlock = HGSMI_MA_BLOCK_SIZE_MAX;
+    HGSMISIZE cbRemaining = pMA->area.cbArea;
+    HGSMIOFFSET off = 0;
+
+    while (cbBlock >= HGSMI_MA_BLOCK_SIZE_MIN)
+    {
+        /* Build a list of free memory blocks with u32BlockSize. */
+        uint32_t cBlocks = cbRemaining / cbBlock;
+        if (cBlocks > 0)
+        {
+            if (pMA->cbMaxBlock < cbBlock)
+            {
+                pMA->cbMaxBlock = cbBlock;
+            }
+
+            HGSMIOFFSET order = HGSMIMASize2Order(cbBlock);
+
+            uint32_t i;
+            for (i = 0; i < cBlocks; ++i)
+            {
+                /* A new free block. */
+                HGSMIMABLOCK *pBlock;
+                rc = hgsmiMABlockAlloc(pMA, &pBlock);
+                if (RT_FAILURE(rc))
+                {
+                    break;
+                }
+
+                pBlock->descriptor = hgsmiMADescriptor(off, true, order);
+                RTListAppend(&pMA->listBlocks, &pBlock->nodeBlock);
+                ++pMA->cBlocks;
+
+                off += cbBlock;
+                cbRemaining -= cbBlock;
+            }
+        }
+
+        if (RT_FAILURE(rc))
+        {
+            break;
+        }
+
+        cbBlock /= 2;
+    }
+
+    return rc;
+}
+
+static int hgsmiMARebuildFreeLists(HGSMIMADATA *pMA)
+{
+    int rc = VINF_SUCCESS;
+
+    HGSMIMABLOCK *pIter;
+    RTListForEach(&pMA->listBlocks, pIter, HGSMIMABLOCK, nodeBlock)
+    {
+        if (HGSMI_MA_DESC_IS_FREE(pIter->descriptor))
+        {
+            HGSMIOFFSET order = HGSMI_MA_DESC_ORDER(pIter->descriptor);
+            RTListAppend(&pMA->aListFreeBlocks[order], &pIter->nodeFree);
+        }
+    }
+
+    return rc;
+}
+
+static int hgsmiMARestore(HGSMIMADATA *pMA, HGSMIOFFSET *paDescriptors, uint32_t cDescriptors, HGSMISIZE cbMaxBlock)
+{
+    int rc = VINF_SUCCESS;
+
+    pMA->cbMaxBlock = cbMaxBlock;
+    pMA->cBlocks = 0;
+
+    HGSMISIZE cbRemaining = pMA->area.cbArea;
+    HGSMIOFFSET off = 0;
+
+    uint32_t i;
+    for (i = 0; i < cDescriptors; ++i)
+    {
+        /* Verify the descriptor. */
+        HGSMISIZE cbBlock = HGSMIMAOrder2Size(HGSMI_MA_DESC_ORDER(paDescriptors[i]));
+        if (   off != HGSMI_MA_DESC_OFFSET(paDescriptors[i])
+            || cbBlock > cbRemaining
+            || cbBlock > pMA->cbMaxBlock)
+        {
+            rc = VERR_INVALID_PARAMETER;
+            break;
+        }
+
+        /* A new free block. */
+        HGSMIMABLOCK *pBlock;
+        rc = hgsmiMABlockAlloc(pMA, &pBlock);
+        if (RT_FAILURE(rc))
+        {
+            break;
+        }
+
+        pBlock->descriptor = paDescriptors[i];
+        RTListAppend(&pMA->listBlocks, &pBlock->nodeBlock);
+        ++pMA->cBlocks;
+
+        off += cbBlock;
+        cbRemaining -= cbBlock;
+    }
+
+    return rc;
+}
+
+static HGSMIMABLOCK *hgsmiMAGetFreeBlock(HGSMIMADATA *pMA, HGSMIOFFSET order)
+{
+    HGSMIMABLOCK *pBlock = NULL;
+
+    HGSMIOFFSET i;
+    for (i = order; i < RT_ELEMENTS(pMA->aListFreeBlocks); ++i)
+    {
+        pBlock = RTListGetFirst(&pMA->aListFreeBlocks[i], HGSMIMABLOCK, nodeFree);
+        if (pBlock)
+        {
+            break;
+        }
+    }
+
+    if (pBlock)
+    {
+        AssertReturn(HGSMI_MA_DESC_IS_FREE(pBlock->descriptor), NULL);
+
+        /* Where the block starts. */
+        HGSMIOFFSET off = HGSMI_MA_DESC_OFFSET(pBlock->descriptor);
+
+        /* 'i' is the order of the block. */
+        while (i != order)
+        {
+            /* A larger block was found and need to be split to 2 smaller blocks. */
+            HGSMIMABLOCK *pBlock2;
+            int rc = hgsmiMABlockAlloc(pMA, &pBlock2);
+            if (RT_FAILURE(rc))
+            {
+                pBlock = NULL;
+                break;
+            }
+
+            /* Create 2 blocks with descreased order. */
+            --i;
+
+            /* Remove from the free list. */
+            RTListNodeRemove(&pBlock->nodeFree);
+
+            pBlock->descriptor = hgsmiMADescriptor(off, true, i);
+            pBlock2->descriptor = hgsmiMADescriptor(off + HGSMIMAOrder2Size(i), true, i);
+
+            /* Update list of all blocks by inserting pBlock2 after pBlock. */
+            RTListNodeInsertAfter(&pBlock->nodeBlock, &pBlock2->nodeBlock);
+            ++pMA->cBlocks;
+
+            /* Update the free list. */
+            RTListAppend(&pMA->aListFreeBlocks[i], &pBlock->nodeFree);
+            RTListAppend(&pMA->aListFreeBlocks[i], &pBlock2->nodeFree);
+        }
+    }
+
+    return pBlock;
+}
+
+static void hgsmiMAReformatFreeBlocks(HGSMIMADATA *pMA, HGSMIOFFSET maxId,
+                                      HGSMIMABLOCK *pStart, HGSMIMABLOCK *pEnd, HGSMISIZE cbBlocks)
+{
+    int rc = VINF_SUCCESS;
+
+    /*
+     * Blocks starting from pStart until pEnd will be replaced with
+     * another set of blocks.
+     *
+     * The new set will include the block with the required order.
+     * Since the required order is larger than any existing block,
+     * it will replace at least two existing blocks.
+     * The new set will also have minimal possible number of blocks.
+     * Therefore the new set will have at least one block less.
+     * Blocks will be updated in place and remaining blocks will be
+     * deallocated.
+     */
+
+    HGSMISIZE u32BlockSize = HGSMIMAOrder2Size(maxId);
+    HGSMISIZE cbRemaining = cbBlocks;
+    HGSMIOFFSET off = HGSMI_MA_DESC_OFFSET(pStart->descriptor);
+    HGSMIMABLOCK *pBlock = pStart;
+
+    while (u32BlockSize >= HGSMI_MA_BLOCK_SIZE_MIN && cbRemaining)
+    {
+        /* Build a list of free memory blocks with u32BlockSize. */
+        uint32_t cBlocks = cbRemaining / u32BlockSize;
+        if (cBlocks > 0)
+        {
+            HGSMIOFFSET order = HGSMIMASize2Order(u32BlockSize);
+
+            uint32_t i;
+            for (i = 0; i < cBlocks; ++i)
+            {
+                if (pBlock == pEnd)
+                {
+                    /* Should never happen because the new set of blocks is supposed to be smaller. */
+                    AssertFailed();
+                    rc = VERR_OUT_OF_RESOURCES;
+                    break;
+                }
+
+                /* Remove from the free list. */
+                RTListNodeRemove(&pBlock->nodeFree);
+
+                pBlock->descriptor = hgsmiMADescriptor(off, true, order);
+
+                RTListAppend(&pMA->aListFreeBlocks[order], &pBlock->nodeFree);
+
+                off += u32BlockSize;
+                cbRemaining -= u32BlockSize;
+
+                pBlock = RTListGetNext(&pMA->listBlocks, pBlock, HGSMIMABLOCK, nodeBlock);
+            }
+        }
+
+        if (RT_FAILURE(rc))
+        {
+            break;
+        }
+
+        u32BlockSize /= 2;
+    }
+
+    Assert(cbRemaining == 0);
+
+    if (RT_SUCCESS(rc))
+    {
+        /* Remove remaining free blocks from pBlock until pEnd */
+        for (;;)
+        {
+            bool fEnd = (pBlock == pEnd);
+            HGSMIMABLOCK *pNext = RTListGetNext(&pMA->listBlocks, pBlock, HGSMIMABLOCK, nodeBlock);
+
+            RTListNodeRemove(&pBlock->nodeFree);
+            RTListNodeRemove(&pBlock->nodeBlock);
+            --pMA->cBlocks;
+
+            hgsmiMABlockFree(pMA, pBlock);
+
+            if (fEnd)
+            {
+                break;
+            }
+
+            pBlock = pNext;
+        }
+    }
+}
+
+static void hgsmiMAQueryFreeRange(HGSMIMADATA *pMA, HGSMIMABLOCK *pBlock, HGSMISIZE cbRequired,
+                                  HGSMIMABLOCK **ppStart, HGSMIMABLOCK **ppEnd, HGSMISIZE *pcbBlocks)
+{
+    Assert(HGSMI_MA_DESC_IS_FREE(pBlock->descriptor));
+
+    *pcbBlocks = HGSMIMAOrder2Size(HGSMI_MA_DESC_ORDER(pBlock->descriptor));
+    *ppStart = pBlock;
+    *ppEnd = pBlock;
+
+    HGSMIMABLOCK *p;
+    for (;;)
+    {
+        p = RTListGetNext(&pMA->listBlocks, *ppEnd, HGSMIMABLOCK, nodeBlock);
+        if (!p || !HGSMI_MA_DESC_IS_FREE(p->descriptor))
+        {
+            break;
+        }
+        *pcbBlocks += HGSMIMAOrder2Size(HGSMI_MA_DESC_ORDER(p->descriptor));
+        *ppEnd = p;
+
+        if (cbRequired && *pcbBlocks >= cbRequired)
+        {
+            return;
+        }
+    }
+    for (;;)
+    {
+        p = RTListGetPrev(&pMA->listBlocks, *ppStart, HGSMIMABLOCK, nodeBlock);
+        if (!p || !HGSMI_MA_DESC_IS_FREE(p->descriptor))
+        {
+            break;
+        }
+        *pcbBlocks += HGSMIMAOrder2Size(HGSMI_MA_DESC_ORDER(p->descriptor));
+        *ppStart = p;
+
+        if (cbRequired && *pcbBlocks >= cbRequired)
+        {
+            return;
+        }
+    }
+}
+
+static void hgsmiMAMergeFreeBlocks(HGSMIMADATA *pMA, HGSMIOFFSET order)
+{
+    /* Try to create a free block with the order from smaller free blocks. */
+    if (order == 0)
+    {
+        /* No smaller blocks. */
+        return;
+    }
+
+    HGSMISIZE cbRequired = HGSMIMAOrder2Size(order);
+
+    /* Scan all free lists of smaller blocks.
+     *
+     * Get the sequence of free blocks before and after each free block.
+     * If possible, re-split the sequence to get the required block and other free block(s).
+     * If not possible, try the next free block.
+     *
+     * Free blocks are scanned from i to 0 orders.
+     */
+    HGSMIOFFSET i = order - 1;
+    for (;;)
+    {
+        HGSMIMABLOCK *pIter;
+        RTListForEach(&pMA->aListFreeBlocks[i], pIter, HGSMIMABLOCK, nodeFree)
+        {
+            Assert(HGSMI_MA_DESC_ORDER(pIter->descriptor) == i);
+
+            HGSMISIZE cbBlocks;
+            HGSMIMABLOCK *pFreeStart;
+            HGSMIMABLOCK *pFreeEnd;
+            hgsmiMAQueryFreeRange(pMA, pIter, cbRequired, &pFreeStart, &pFreeEnd, &cbBlocks);
+
+            Assert((cbBlocks / HGSMI_MA_BLOCK_SIZE_MIN) * HGSMI_MA_BLOCK_SIZE_MIN == cbBlocks);
+
+            /* Verify whether cbBlocks is enough for the requested block. */
+            if (cbBlocks >= cbRequired)
+            {
+                /* Build new free blocks starting from the requested. */
+                hgsmiMAReformatFreeBlocks(pMA, order, pFreeStart, pFreeEnd, cbBlocks);
+                i = 0; /* Leave the loop. */
+                break;
+            }
+        }
+
+        if (i == 0)
+        {
+            break;
+        }
+
+        --i;
+    }
+}
+
+static HGSMIOFFSET hgsmiMAAlloc(HGSMIMADATA *pMA, HGSMISIZE cb)
+{
+    if (cb > pMA->cbMaxBlock)
+    {
+        return HGSMIOFFSET_VOID;
+    }
+
+    if (cb < HGSMI_MA_BLOCK_SIZE_MIN)
+    {
+        cb = HGSMI_MA_BLOCK_SIZE_MIN;
+    }
+
+    HGSMIOFFSET order = HGSMIPopCnt32(cb - 1) - HGSMI_MA_DESC_ORDER_BASE;
+
+    AssertReturn(HGSMIMAOrder2Size(order) >= cb, HGSMIOFFSET_VOID);
+    AssertReturn(order < RT_ELEMENTS(pMA->aListFreeBlocks), HGSMIOFFSET_VOID);
+
+    HGSMIMABLOCK *pBlock = hgsmiMAGetFreeBlock(pMA, order);
+    if (RT_UNLIKELY(pBlock == NULL))
+    {
+        /* No free block with large enough size. Merge smaller free blocks and try again. */
+        hgsmiMAMergeFreeBlocks(pMA, order);
+        pBlock = hgsmiMAGetFreeBlock(pMA, order);
+    }
+
+    if (RT_LIKELY(pBlock != NULL))
+    {
+        RTListNodeRemove(&pBlock->nodeFree);
+        pBlock->descriptor &= ~HGSMI_MA_DESC_FREE_MASK;
+        return HGSMI_MA_DESC_OFFSET(pBlock->descriptor);
+    }
+
+    return HGSMIOFFSET_VOID;
+}
+
+static void hgsmiMAFree(HGSMIMADATA *pMA, HGSMIOFFSET off)
+{
+    if (off == HGSMIOFFSET_VOID)
+    {
+        return;
+    }
+
+    /* Find the block corresponding to the offset. */
+    Assert((off / HGSMI_MA_BLOCK_SIZE_MIN) * HGSMI_MA_BLOCK_SIZE_MIN == off);
+
+    HGSMIMABLOCK *pBlock = HGSMIMASearchOffset(pMA, off);
+    if (pBlock)
+    {
+        if (HGSMI_MA_DESC_OFFSET(pBlock->descriptor) == off)
+        {
+            /* Found the right block, mark it as free. */
+            pBlock->descriptor |= HGSMI_MA_DESC_FREE_MASK;
+            RTListAppend(&pMA->aListFreeBlocks[HGSMI_MA_DESC_ORDER(pBlock->descriptor)], &pBlock->nodeFree);
+            return;
+        }
+    }
+
+    AssertFailed();
+}
+
+int HGSMIMAInit(HGSMIMADATA *pMA, const HGSMIAREA *pArea,
+                HGSMIOFFSET *paDescriptors, uint32_t cDescriptors, HGSMISIZE cbMaxBlock,
+                const HGSMIENV *pEnv)
+{
+    AssertReturn(pArea->cbArea < UINT32_C(0x80000000), VERR_INVALID_PARAMETER);
+    AssertReturn(pArea->cbArea >= HGSMI_MA_BLOCK_SIZE_MIN, VERR_INVALID_PARAMETER);
+
+    RT_ZERO(*pMA);
+
+    HGSMISIZE cb = (pArea->cbArea / HGSMI_MA_BLOCK_SIZE_MIN) * HGSMI_MA_BLOCK_SIZE_MIN;
+
+    int rc = HGSMIAreaInitialize(&pMA->area, pArea->pu8Base, cb, 0);
+    if (RT_SUCCESS(rc))
+    {
+        pMA->env = *pEnv;
+
+        uint32_t i;
+        for (i = 0; i < RT_ELEMENTS(pMA->aListFreeBlocks); ++i)
+        {
+            RTListInit(&pMA->aListFreeBlocks[i]);
+        }
+        RTListInit(&pMA->listBlocks);
+
+        if (cDescriptors)
+        {
+            rc = hgsmiMARestore(pMA, paDescriptors, cDescriptors, cbMaxBlock);
+        }
+        else
+        {
+            rc = hgsmiMAFormat(pMA);
+        }
+
+        if (RT_SUCCESS(rc))
+        {
+            rc = hgsmiMARebuildFreeLists(pMA);
+        }
+    }
+
+    return rc;
+}
+
+void HGSMIMAUninit(HGSMIMADATA *pMA)
+{
+    HGSMIMABLOCK *pIter;
+    HGSMIMABLOCK *pNext;
+
+    RTListForEachSafe(&pMA->listBlocks, pIter, pNext, HGSMIMABLOCK, nodeBlock)
+    {
+        RTListNodeRemove(&pIter->nodeBlock);
+        hgsmiMABlockFree(pMA, pIter);
+    }
+
+    RT_ZERO(*pMA);
+}
+
+HGSMIOFFSET HGSMIMAPointerToOffset(const HGSMIMADATA *pMA, const void *pv)
+{
+    if (HGSMIAreaContainsPointer(&pMA->area, pv))
+    {
+        return HGSMIPointerToOffset(&pMA->area, pv);
+    }
+
+    AssertFailed();
+    return HGSMIOFFSET_VOID;
+}
+
+void *HGSMIMAOffsetToPointer(const HGSMIMADATA *pMA, HGSMIOFFSET off)
+{
+    if (HGSMIAreaContainsOffset(&pMA->area, off))
+    {
+        return HGSMIOffsetToPointer(&pMA->area, off);
+    }
+
+    AssertFailed();
+    return NULL;
+}
+
+void *HGSMIMAAlloc(HGSMIMADATA *pMA, HGSMISIZE cb)
+{
+    HGSMIOFFSET off = hgsmiMAAlloc(pMA, cb);
+    return HGSMIMAOffsetToPointer(pMA, off);
+}
+
+void HGSMIMAFree(HGSMIMADATA *pMA, void *pv)
+{
+    HGSMIOFFSET off = HGSMIMAPointerToOffset(pMA, pv);
+    if (off != HGSMIOFFSET_VOID)
+    {
+        hgsmiMAFree(pMA, off);
+    }
+    else
+    {
+        AssertFailed();
+    }
+}
+
+HGSMIMABLOCK *HGSMIMASearchOffset(HGSMIMADATA *pMA, HGSMIOFFSET off)
+{
+    /* Binary search in the block list for the offset. */
+    HGSMIMABLOCK *pStart = RTListGetFirst(&pMA->listBlocks, HGSMIMABLOCK, nodeBlock);
+    HGSMIMABLOCK *pEnd = RTListGetLast(&pMA->listBlocks, HGSMIMABLOCK, nodeBlock);
+    HGSMIMABLOCK *pMiddle;
+
+    uint32_t iStart = 0;
+    uint32_t iEnd = pMA->cBlocks;
+    uint32_t iMiddle;
+
+    for (;;)
+    {
+        pMiddle = pStart;
+        iMiddle = iStart + (iEnd - iStart) / 2;
+        if (iMiddle == iStart)
+        {
+            break;
+        }
+
+        /* Find the block with the iMiddle index. Never go further than pEnd. */
+        uint32_t i;
+        for (i = iStart; i < iMiddle && pMiddle != pEnd; ++i)
+        {
+            pMiddle = RTListNodeGetNext(&pMiddle->nodeBlock, HGSMIMABLOCK, nodeBlock);
+        }
+
+        HGSMIOFFSET offMiddle = HGSMI_MA_DESC_OFFSET(pMiddle->descriptor);
+        if (offMiddle > off)
+        {
+            pEnd = pMiddle;
+            iEnd = iMiddle;
+        }
+        else
+        {
+            pStart = pMiddle;
+            iStart = iMiddle;
+        }
+    }
+
+    return pMiddle;
+}
+
+
+/*
+ * Helper.
+ */
+
+uint32_t HGSMIPopCnt32(uint32_t u32)
+{
+    uint32_t c = 0;
+    if (u32 > 0xFFFF) { c += 16;  u32 >>= 16; }
+    if (u32 > 0xFF)   { c += 8;   u32 >>= 8;  }
+    if (u32 > 0xF)    { c += 4;   u32 >>= 4;  }
+    if (u32 > 0x3)    { c += 2;   u32 >>= 2;  }
+    if (u32 > 0x1)    { c += 1;   u32 >>= 1;  }
+    return c + u32;
+}
diff --git a/ubuntu/vbox/vboxvideo/Makefile b/ubuntu/vbox/vboxvideo/Makefile
new file mode 100644 (file)
index 0000000..a499fb1
--- /dev/null
@@ -0,0 +1,70 @@
+KBUILD_EXTMOD=${srctree}/ubuntu/vbox
+# $Id: Makefile.module.kms $
+## @file
+# VirtualBox Guest Additions Module Makefile.
+#
+# (For 2.6.x this file must be 'Makefile'!)
+#
+
+#
+# Copyright (C) 2006-2010 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.
+#
+
+# Linux kbuild sets this to our source directory if we are called from there
+obj ?= $(CURDIR)
+include $(obj)/Makefile.include.header
+
+MOD_NAME   = vboxvideo
+
+MY_KERNELRELEASE := $(KERNELRELEASE)
+ifeq ($(MY_KERNELRELEASE),)
+  # as of 2.6.16 KERNELRELEASE is only set if the kernel is configured
+  MY_KERNELRELEASE := $(KERNELVERSION)
+endif
+ifeq ($(KERN_VERSION),24)
+  # sledgehammer, see the 2.4 handling in Makefile.include.footer
+  MY_KERNELRELEASE := 2.4.0
+endif
+ifeq ($(filter 1.% 2.% 3.0.% 3.1.% 3.2.% 3.3.% 3.4.% 3.5.% 3.6.% 3.7.% \
+3.8.% 3.9.%,$(MY_KERNELRELEASE)),)
+MOD_OBJS   = HGSMIBase.o HGSMICommon.o HGSMIMemAlloc.o heapoffset.o \
+             Modesetting.o vbox_drv.o vbox_fb.o vbox_irq.o vbox_main.o \
+             vbox_mode.o vbox_ttm.o VBVABase.o vbox_prime.o
+else
+MOD_OBJS   = vbox_dummy.o
+endif
+
+ifneq ($(wildcard $(KBUILD_EXTMOD)/vboxvideo),)
+ MANGLING := $(KBUILD_EXTMOD)/vboxvideo/include/VBox/VBoxGuestMangling.h
+else
+ MANGLING := $(KBUILD_EXTMOD)/include/VBox/VBoxGuestMangling.h
+endif
+MOD_CFLAGS = -Wno-declaration-after-statement -fshort-wchar -fno-pie
+ifneq ($(KERN_VERSION),24)
+MOD_CFLAGS += -include $(MANGLING)
+endif
+MOD_INCL   = $(addprefix -I$(KBUILD_EXTMOD),/ /include)
+# What on earth is this?
+MOD_INCL  += $(addprefix -I$(KBUILD_EXTMOD)/vboxvideo,/ /include)
+MOD_INCL  += -Iinclude/drm
+MOD_DEFS  := -DRT_OS_LINUX -DIN_RING0 -DIN_RT_R0 \
+            -DIN_SUP_R0 -DVBOX -DVBOX_WITH_HGCM -DLOG_TO_BACKDOOR -DIN_MODULE \
+            -DIN_GUEST_R0
+# our module does not export any symbol
+MOD_DEFS  += -DRT_NO_EXPORT_SYMBOL
+ifeq ($(BUILD_TARGET_ARCH),amd64)
+ MOD_DEFS += -DRT_ARCH_AMD64 -DVBOX_WITH_64_BITS_GUESTS
+else
+ MOD_DEFS += -DRT_ARCH_X86
+endif
+MOD_CLEAN  = . linux r0drv r0drv/linux
+
+include $(obj)/Makefile.include.footer
diff --git a/ubuntu/vbox/vboxvideo/Makefile.include.footer b/ubuntu/vbox/vboxvideo/Makefile.include.footer
new file mode 100644 (file)
index 0000000..7830bfd
--- /dev/null
@@ -0,0 +1,101 @@
+#
+# VirtualBox Guest Additions kernel module Makefile, common parts.
+#
+# See Makefile.include.header for details of how to use this.
+#
+# Copyright (C) 2006-2015 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.
+#
+
+# override is required by the Debian guys
+override MODULE = $(MOD_NAME)
+OBJS   = $(MOD_OBJS)
+
+ifneq ($(MAKECMDGOALS),clean)
+
+KBUILD_VERBOSE ?= 1
+
+#
+# Compiler options
+#
+ifndef INCL
+ INCL    := $(addprefix -I,$(KERN_INCL) $(EXTRA_INCL))
+ ifndef KBUILD_EXTMOD
+  KBUILD_EXTMOD := $(shell pwd)
+ endif
+ INCL    += $(MOD_INCL)
+ export INCL
+endif
+KFLAGS   := -D__KERNEL__ -DMODULE $(MOD_DEFS)
+ifeq ($(BUILD_TYPE),debug)
+ KFLAGS  += -DDEBUG -DDEBUG_$(subst $(subst _, ,_),_,$(USERNAME)) -DDEBUG_USERNAME=$(subst $(subst _, ,_),_,$(USERNAME))
+endif
+
+ifeq ($(KERN_VERSION), 24)
+#
+# 2.4
+#
+
+ifeq ($(BUILD_TARGET_ARCH),amd64)
+ KFLAGS  += -mcmodel=kernel
+endif
+
+CFLAGS := -O2 -DVBOX_LINUX_2_4 $(MOD_CFLAGS) $(INCL) $(KFLAGS) $(MOD_EXTRA) $(KDEBUG)
+MODULE_EXT := o
+
+# 2.4 Module linking
+$(MODULE).o: $(OBJS)
+       $(LD) -o $@ -r $(OBJS)
+
+.PHONY: $(MODULE)
+all: $(MODULE)
+$(MODULE): $(MODULE).o
+
+else
+#
+# 2.6 and later
+#
+
+MODULE_EXT := ko
+
+$(MODULE)-y  := $(OBJS)
+
+# build defs
+EXTRA_CFLAGS += $(MOD_CFLAGS) $(INCL) $(KFLAGS) $(MOD_EXTRA) $(KDEBUG)
+
+.PHONY: $(MODULE)
+all: $(MODULE)
+
+obj-m += $(MODULE).o
+
+JOBS := $(shell (getconf _NPROCESSORS_ONLN || grep -Ec '^processor|^CPU[0-9]' /proc/cpuinfo) 2>/dev/null)
+ifeq ($(JOBS),0)
+  JOBS := 1
+endif
+
+# OL/UEK: disable module signing for external modules -- we don't have any private key
+$(MODULE):
+       $(MAKE) KBUILD_VERBOSE=$(KBUILD_VERBOSE) CONFIG_MODULE_SIG= -C $(KERN_DIR) SUBDIRS=$(CURDIR) SRCROOT=$(CURDIR) -j$(JOBS) modules
+
+modules_install:
+       $(MAKE) KBUILD_VERBOSE=$(KBUILD_VERBOSE) CONFIG_MODULE_SIG= -C $(KERN_DIR) SUBDIRS=$(CURDIR) SRCROOT=$(CURDIR) modules_install
+
+endif
+
+install: $(MODULE)
+       @mkdir -p $(MODULE_DIR); \
+       install -m 0644 -o root -g root $(MODULE).$(MODULE_EXT) $(MODULE_DIR); \
+       PATH="$(PATH):/bin:/sbin" depmod -a;
+
+endif # eq($(MAKECMDGOALS),clean)
+
+clean:
+       for f in $(MOD_CLEAN); do rm -f $$f/*.o $$f/.*.cmd $$f/.*.flags; done
+       rm -rf .$(MOD_NAME)* .tmp_ver* $(MOD_NAME).* Modules.symvers modules.order
diff --git a/ubuntu/vbox/vboxvideo/Makefile.include.header b/ubuntu/vbox/vboxvideo/Makefile.include.header
new file mode 100644 (file)
index 0000000..1c4fb9a
--- /dev/null
@@ -0,0 +1,188 @@
+#
+# VirtualBox Guest Additions kernel module Makefile, common parts.
+#
+# (For 2.6.x, the main file must be called 'Makefile'!)
+#
+# Copyright (C) 2006-2015 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.
+#
+
+# Testing:
+# * Building with KERN_VER set to an installed but non-current kernel works and
+#   installs to the right location.
+# * Building with KERN_DIR and/or MODULE_DIR set uses the value specified and
+#   the default value for the unspecified one if any.
+
+#
+# These file should be included by the Makefiles for any kernel modules we
+# build as part of the Guest Additions.  The intended way of doing this is as
+# follows:
+#
+# # Linux kbuild sets this to our source directory if we are called from
+# # there
+# obj ?= $(CURDIR)
+# include $(obj)/Makefile.include.header
+# MOD_NAME = <name of the module to be built, without extension>
+# MOD_OBJS = <list of object files which should be included>
+# MOD_DEFS = <any additional defines which this module needs>
+# MOD_INCL = <any additional include paths which this module needs>
+# MOD_CFLAGS = <any additional CFLAGS which this module needs>
+# MOD_CLEAN = <list of directories that the clean target should look at>
+# include $(obj)/Makefile.include.footer
+#
+# The kmk kBuild define KBUILD_TARGET_ARCH is available.
+#
+
+
+#
+# First, figure out which architecture we're targeting and the build type.
+# (We have to support basic cross building (ARCH=i386|x86_64).)
+# While at it, warn about BUILD_* vars found to help with user problems.
+#
+ifeq ($(filter-out x86_64 amd64 AMD64,$(shell uname -m)),)
+ BUILD_TARGET_ARCH_DEF := amd64
+else
+ BUILD_TARGET_ARCH_DEF := x86
+endif
+ifneq ($(filter-out amd64 x86,$(BUILD_TARGET_ARCH)),)
+ $(warning Ignoring unknown BUILD_TARGET_ARCH value '$(BUILD_TARGET_ARCH)'.)
+ BUILD_TARGET_ARCH :=
+endif
+ifeq ($(BUILD_TARGET_ARCH),)
+ ifeq ($(ARCH),x86_64)
+  BUILD_TARGET_ARCH := amd64
+ else
+  ifeq ($(ARCH),i386)
+   ifeq ($(CONFIG_X86_32),y)
+     BUILD_TARGET_ARCH := x86
+   else
+     BUILD_TARGET_ARCH := amd64
+   endif
+  else
+    ifeq ($(ARCH),x86)
+      ifeq ($(CONFIG_X86_32),y)
+        BUILD_TARGET_ARCH := x86
+      else
+        BUILD_TARGET_ARCH := amd64
+      endif
+    else
+      BUILD_TARGET_ARCH := $(BUILD_TARGET_ARCH_DEF)
+    endif
+  endif
+ endif
+else
+ ifneq ($(BUILD_TARGET_ARCH),$(BUILD_TARGET_ARCH_DEF))
+  $(warning Using BUILD_TARGET_ARCH='$(BUILD_TARGET_ARCH)' from the $(origin BUILD_TARGET_ARCH).)
+ endif
+endif
+
+ifneq ($(filter-out release profile debug strict,$(BUILD_TYPE)),)
+ $(warning Ignoring unknown BUILD_TYPE value '$(BUILD_TYPE)'.)
+ BUILD_TYPE :=
+endif
+ifeq ($(BUILD_TYPE),)
+ BUILD_TYPE := release
+else
+ ifneq ($(BUILD_TYPE),release)
+  $(warning Using BUILD_TYPE='$(BUILD_TYPE)' from the $(origin BUILD_TYPE).)
+ endif
+endif
+ifeq ($(USERNAME),)
+ USERNAME := noname
+endif
+
+ifneq ($(MAKECMDGOALS),clean)
+
+ifeq ($(KERNELRELEASE),)
+
+ #
+ # building from this directory
+ #
+
+ # target kernel version
+ ifndef KERN_VER
+  KERN_VER := $(shell uname -r)
+ else
+  ifneq ($(shell if test -d /lib/modules/$(KERN_VER)/build; then echo yes; fi),yes)
+   KERN_VER := $(shell uname -r)
+  endif
+ endif
+
+ # kernel base directory
+ ifndef KERN_DIR
+  KERN_DIR := /lib/modules/$(KERN_VER)/build
+  ifneq ($(shell if test -d $(KERN_DIR); then echo yes; fi),yes)
+   KERN_DIR := /usr/src/linux
+   ifneq ($(shell if test -d $(KERN_DIR); then echo yes; fi),yes)
+    $(error Error: unable to find the sources of your current Linux kernel. \
+                  Specify KERN_DIR=<directory> and run Make again)
+   endif
+   $(warning Warning: using /usr/src/linux as the source directory of your \
+                      Linux kernel. If this is not correct, specify \
+                     KERN_DIR=<directory> and run Make again.)
+  endif
+ else
+  ifneq ($(shell if test -d $(KERN_DIR); then echo yes; fi),yes)
+   $(error Error: KERN_DIR does not point to a directory)
+  endif
+ endif
+
+ # includes
+ ifndef KERN_INCL
+  KERN_INCL = $(KERN_DIR)/include
+ endif
+ ifneq ($(shell if test -d $(KERN_INCL); then echo yes; fi),yes)
+  $(error Error: unable to find the include directory for your current Linux \
+                 kernel. Specify KERN_INCL=<directory> and run Make again)
+ endif
+
+ # module install dir, only for current kernel
+ ifneq ($(filter install install_rpm,$(MAKECMDGOALS)),)
+  ifndef MODULE_DIR
+   MODULE_DIR_TST := /lib/modules/$(KERN_VER)
+   ifeq ($(shell if test -d $(MODULE_DIR_TST); then echo yes; fi),yes)
+    MODULE_DIR := $(MODULE_DIR_TST)/misc
+   else
+    $(error Unable to find the folder to install the module to)
+   endif
+  endif # MODULE_DIR unspecified
+ endif
+
+ # guess kernel version (24 or 26)
+ ifeq ($(shell if grep '"2\.4\.' $(KERN_INCL)/linux/version.h > /dev/null; then echo yes; fi),yes)
+  KERN_VERSION := 24
+ else
+  KERN_VERSION := 26
+ endif
+
+else # neq($(KERNELRELEASE),)
+
+ #
+ # building from kbuild (make -C <kernel_directory> M=`pwd`)
+ #
+
+ # guess kernel version (24 or 26)
+ ifeq ($(shell if echo "$(VERSION).$(PATCHLEVEL)." | grep '2\.4\.' > /dev/null; then echo yes; fi),yes)
+  KERN_VERSION := 24
+ else
+  KERN_VERSION := 26
+ endif
+
+endif # neq($(KERNELRELEASE),)
+
+# debug - show guesses.
+ifdef DEBUG
+$(warning dbg: KERN_DIR     = $(KERN_DIR))
+$(warning dbg: KERN_INCL    = $(KERN_INCL))
+$(warning dbg: MODULE_DIR   = $(MODULE_DIR))
+$(warning dbg: KERN_VERSION = $(KERN_VERSION))
+endif
+
+endif # eq($(MAKECMDGOALS),clean)
diff --git a/ubuntu/vbox/vboxvideo/Modesetting.c b/ubuntu/vbox/vboxvideo/Modesetting.c
new file mode 100644 (file)
index 0000000..e13656b
--- /dev/null
@@ -0,0 +1,380 @@
+/* $Id: Modesetting.cpp $ */
+/** @file
+ * VirtualBox Video driver, common code - HGSMI initialisation and helper
+ * functions.
+ */
+
+/*
+ * 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.
+ */
+
+#include <VBox/VBoxVideoGuest.h>
+#include <VBox/VBoxVideo.h>
+#include <VBox/VBoxGuest.h>
+#include <VBox/Hardware/VBoxVideoVBE.h>
+#include <VBox/VMMDev.h>
+
+#include <iprt/asm.h>
+#include <iprt/log.h>
+
+#ifndef VBOX_GUESTR3XF86MOD
+# include <iprt/string.h>
+#endif
+
+/**
+ * Gets the count of virtual monitors attached to the guest via an HGSMI
+ * command
+ *
+ * @returns the right count on success or 1 on failure.
+ * @param  pCtx  the context containing the heap to use
+ */
+DECLHIDDEN(uint32_t) VBoxHGSMIGetMonitorCount(PHGSMIGUESTCOMMANDCONTEXT pCtx)
+{
+    /* Query the configured number of displays. */
+    uint32_t cDisplays = 0;
+    VBoxQueryConfHGSMI(pCtx, VBOX_VBVA_CONF32_MONITOR_COUNT, &cDisplays);
+    LogFunc(("cDisplays = %d\n", cDisplays));
+    if (cDisplays == 0 || cDisplays > VBOX_VIDEO_MAX_SCREENS)
+        /* Host reported some bad value. Continue in the 1 screen mode. */
+        cDisplays = 1;
+    return cDisplays;
+}
+
+
+/**
+ * Returns the size of the video RAM in bytes.
+ *
+ * @returns the size
+ */
+DECLHIDDEN(uint32_t) VBoxVideoGetVRAMSize(void)
+{
+    /** @note A 32bit read on this port returns the VRAM size. */
+    return VBoxVideoCmnPortReadUlong(VBE_DISPI_IOPORT_DATA);
+}
+
+
+/**
+ * Check whether this hardware allows the display width to have non-multiple-
+ * of-eight values.
+ *
+ * @returns true if any width is allowed, false otherwise.
+ */
+DECLHIDDEN(bool) VBoxVideoAnyWidthAllowed(void)
+{
+    unsigned DispiId;
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX);
+    DispiId = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
+    return (DispiId == VBE_DISPI_ID_ANYX);
+}
+
+
+/**
+ * Tell the host about how VRAM is divided up between each screen via an HGSMI
+ * command.  It is acceptable to specifiy identical data for each screen if
+ * they share a single framebuffer.
+ *
+ * @returns iprt status code, either VERR_NO_MEMORY or the status returned by
+ *          @a pfnFill
+ * @todo  What was I thinking of with that callback function?  It
+ *        would be much simpler to just pass in a structure in normal
+ *        memory and copy it.
+ * @param  pCtx      the context containing the heap to use
+ * @param  u32Count  the number of screens we are activating
+ * @param  pfnFill   a callback which initialises the VBVAINFOVIEW structures
+ *                   for all screens
+ * @param  pvData    context data for @a pfnFill
+ */
+DECLHIDDEN(int) VBoxHGSMISendViewInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                      uint32_t u32Count,
+                                      PFNHGSMIFILLVIEWINFO pfnFill,
+                                      void *pvData)
+{
+    int rc;
+    /* Issue the screen info command. */
+    void *p = VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVAINFOVIEW) * u32Count,
+                                   HGSMI_CH_VBVA, VBVA_INFO_VIEW);
+    if (p)
+    {
+        VBVAINFOVIEW *pInfo = (VBVAINFOVIEW *)p;
+        rc = pfnFill(pvData, pInfo, u32Count);
+        if (RT_SUCCESS(rc))
+            VBoxHGSMIBufferSubmit (pCtx, p);
+        VBoxHGSMIBufferFree(pCtx, p);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+    return rc;
+}
+
+
+/**
+ * Set a video mode using port registers.  This must be done for the first
+ * screen before every HGSMI modeset and also works when HGSM is not enabled.
+ * @param  cWidth      the mode width
+ * @param  cHeight     the mode height
+ * @param  cVirtWidth  the mode pitch
+ * @param  cBPP        the colour depth of the mode
+ * @param  fFlags      flags for the mode.  These will be or-ed with the
+ *                     default _ENABLED flag, so unless you are restoring
+ *                     a saved mode or have special requirements you can pass
+ *                     zero here.
+ * @param  cx          the horizontal panning offset
+ * @param  cy          the vertical panning offset
+ */
+DECLHIDDEN(void) VBoxVideoSetModeRegisters(uint16_t cWidth, uint16_t cHeight,
+                                           uint16_t cVirtWidth, uint16_t cBPP,
+                                           uint16_t fFlags, uint16_t cx,
+                                           uint16_t cy)
+{
+    /* set the mode characteristics */
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cWidth);
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cHeight);
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
+                                VBE_DISPI_INDEX_VIRT_WIDTH);
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cVirtWidth);
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cBPP);
+    /* enable the mode */
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
+                                VBE_DISPI_INDEX_ENABLE);
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA,
+                                fFlags | VBE_DISPI_ENABLED);
+    /* Panning registers */
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
+                                VBE_DISPI_INDEX_X_OFFSET);
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cx);
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
+                                VBE_DISPI_INDEX_Y_OFFSET);
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cy);
+    /** @todo read from the port to see if the mode switch was successful */
+}
+
+
+/**
+ * Get the video mode for the first screen using the port registers.  All
+ * parameters are optional
+ * @returns  true if the VBE mode returned is active, false if we are in VGA
+ *           mode
+ * @note  If anyone else needs additional register values just extend the
+ *        function with additional parameters and fix any existing callers.
+ * @param  pcWidth      where to store the mode width
+ * @param  pcHeight     where to store the mode height
+ * @param  pcVirtWidth  where to store the mode pitch
+ * @param  pcBPP        where to store the colour depth of the mode
+ * @param  pfFlags      where to store the flags for the mode
+ */
+DECLHIDDEN(bool) VBoxVideoGetModeRegisters(uint16_t *pcWidth, uint16_t *pcHeight,
+                                           uint16_t *pcVirtWidth, uint16_t *pcBPP,
+                                           uint16_t *pfFlags)
+{
+    uint16_t fFlags;
+
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
+                                VBE_DISPI_INDEX_ENABLE);
+    fFlags = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
+    if (pcWidth)
+    {
+        VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
+                                    VBE_DISPI_INDEX_XRES);
+        *pcWidth = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
+    }
+    if (pcHeight)
+    {
+        VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
+                                    VBE_DISPI_INDEX_YRES);
+        *pcHeight = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
+    }
+    if (pcVirtWidth)
+    {
+        VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
+                                    VBE_DISPI_INDEX_VIRT_WIDTH);
+        *pcVirtWidth = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
+    }
+    if (pcBPP)
+    {
+        VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
+                                    VBE_DISPI_INDEX_BPP);
+        *pcBPP = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
+    }
+    if (pfFlags)
+        *pfFlags = fFlags;
+    return RT_BOOL(fFlags & VBE_DISPI_ENABLED);
+}
+
+
+/**
+ * Disable our extended graphics mode and go back to VGA mode.
+ */
+DECLHIDDEN(void) VBoxVideoDisableVBE(void)
+{
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
+                                VBE_DISPI_INDEX_ENABLE);
+    VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, 0);
+}
+
+
+/**
+ * Set a video mode via an HGSMI request.  The views must have been
+ * initialised first using @a VBoxHGSMISendViewInfo and if the mode is being
+ * set on the first display then it must be set first using registers.
+ * @param  cDisplay  the screen number
+ * @param  cOriginX  the horizontal displacement relative to the first screen
+ * @param  cOriginY  the vertical displacement relative to the first screen
+ * @param  offStart  the offset of the visible area of the framebuffer
+ *                   relative to the framebuffer start
+ * @param  cbPitch   the offset in bytes between the starts of two adjecent
+ *                   scan lines in video RAM
+ * @param  cWidth    the mode width
+ * @param  cHeight   the mode height
+ * @param  cBPP      the colour depth of the mode
+ */
+DECLHIDDEN(void) VBoxHGSMIProcessDisplayInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                             uint32_t cDisplay,
+                                             int32_t  cOriginX,
+                                             int32_t  cOriginY,
+                                             uint32_t offStart,
+                                             uint32_t cbPitch,
+                                             uint32_t cWidth,
+                                             uint32_t cHeight,
+                                             uint16_t cBPP,
+                                             uint16_t fFlags)
+{
+    /* Issue the screen info command. */
+    void *p = VBoxHGSMIBufferAlloc(pCtx,
+                                   sizeof (VBVAINFOSCREEN),
+                                   HGSMI_CH_VBVA,
+                                   VBVA_INFO_SCREEN);
+    if (!p)
+    {
+        LogFunc(("HGSMIHeapAlloc failed\n"));
+    }
+    else
+    {
+        VBVAINFOSCREEN *pScreen = (VBVAINFOSCREEN *)p;
+
+        pScreen->u32ViewIndex    = cDisplay;
+        pScreen->i32OriginX      = cOriginX;
+        pScreen->i32OriginY      = cOriginY;
+        pScreen->u32StartOffset  = offStart;
+        pScreen->u32LineSize     = cbPitch;
+        pScreen->u32Width        = cWidth;
+        pScreen->u32Height       = cHeight;
+        pScreen->u16BitsPerPixel = cBPP;
+        pScreen->u16Flags        = fFlags;
+
+        VBoxHGSMIBufferSubmit(pCtx, p);
+
+        VBoxHGSMIBufferFree(pCtx, p);
+    }
+}
+
+
+/** Report the rectangle relative to which absolute pointer events should be
+ *  expressed.  This information remains valid until the next VBVA resize event
+ *  for any screen, at which time it is reset to the bounding rectangle of all
+ *  virtual screens.
+ * @param  pCtx      The context containing the heap to use.
+ * @param  cOriginX  Upper left X co-ordinate relative to the first screen.
+ * @param  cOriginY  Upper left Y co-ordinate relative to the first screen.
+ * @param  cWidth    Rectangle width.
+ * @param  cHeight   Rectangle height.
+ * @returns  iprt status code.
+ * @returns  VERR_NO_MEMORY      HGSMI heap allocation failed.
+ */
+DECLHIDDEN(int)      VBoxHGSMIUpdateInputMapping(PHGSMIGUESTCOMMANDCONTEXT pCtx, int32_t  cOriginX, int32_t  cOriginY,
+                                                 uint32_t cWidth, uint32_t cHeight)
+{
+    int rc = VINF_SUCCESS;
+    VBVAREPORTINPUTMAPPING *p;
+    Log(("%s: cOriginX=%d, cOriginY=%d, cWidth=%u, cHeight=%u\n", __PRETTY_FUNCTION__, (int)cOriginX, (int)cOriginX,
+         (unsigned)cWidth, (unsigned)cHeight));
+
+    /* Allocate the IO buffer. */
+    p = (VBVAREPORTINPUTMAPPING *)VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVAREPORTINPUTMAPPING), HGSMI_CH_VBVA,
+                                                       VBVA_REPORT_INPUT_MAPPING);
+    if (p)
+    {
+        /* Prepare data to be sent to the host. */
+        p->x  = cOriginX;
+        p->y  = cOriginY;
+        p->cx = cWidth;
+        p->cy = cHeight;
+        rc = VBoxHGSMIBufferSubmit(pCtx, p);
+        /* Free the IO buffer. */
+        VBoxHGSMIBufferFree(pCtx, p);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+    LogFunc(("rc = %d\n", rc));
+    return rc;
+}
+
+
+/**
+ * Get most recent video mode hints.
+ * @param  pCtx      the context containing the heap to use
+ * @param  cScreens  the number of screens to query hints for, starting at 0.
+ * @param  pHints    array of VBVAMODEHINT structures for receiving the hints.
+ * @returns  iprt status code
+ * @returns  VERR_NO_MEMORY      HGSMI heap allocation failed.
+ * @returns  VERR_NOT_SUPPORTED  Host does not support this command.
+ */
+DECLHIDDEN(int) VBoxHGSMIGetModeHints(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                      unsigned cScreens, VBVAMODEHINT *paHints)
+{
+    int rc;
+    AssertPtrReturn(paHints, VERR_INVALID_POINTER);
+    void *p = VBoxHGSMIBufferAlloc(pCtx,   sizeof(VBVAQUERYMODEHINTS)
+                                         + cScreens * sizeof(VBVAMODEHINT),
+                                   HGSMI_CH_VBVA, VBVA_QUERY_MODE_HINTS);
+    if (!p)
+    {
+        LogFunc(("HGSMIHeapAlloc failed\n"));
+        return VERR_NO_MEMORY;
+    }
+    else
+    {
+        VBVAQUERYMODEHINTS *pQuery   = (VBVAQUERYMODEHINTS *)p;
+
+        pQuery->cHintsQueried        = cScreens;
+        pQuery->cbHintStructureGuest = sizeof(VBVAMODEHINT);
+        pQuery->rc                   = VERR_NOT_SUPPORTED;
+
+        VBoxHGSMIBufferSubmit(pCtx, p);
+        rc = pQuery->rc;
+        if (RT_SUCCESS(rc))
+            memcpy(paHints, ((uint8_t *)p) + sizeof(VBVAQUERYMODEHINTS),
+                   cScreens * sizeof(VBVAMODEHINT));
+
+        VBoxHGSMIBufferFree(pCtx, p);
+    }
+    return rc;
+}
+
+
+/**
+ * Query the supported flags in VBVAINFOSCREEN::u16Flags.
+ *
+ * @returns The mask of VBVA_SCREEN_F_* flags or 0 if host does not support the request.
+ * @param  pCtx  the context containing the heap to use
+ */
+DECLHIDDEN(uint16_t) VBoxHGSMIGetScreenFlags(PHGSMIGUESTCOMMANDCONTEXT pCtx)
+{
+    uint32_t u32Flags = 0;
+    int rc = VBoxQueryConfHGSMIDef(pCtx, VBOX_VBVA_CONF32_SCREEN_FLAGS, 0, &u32Flags);
+    LogFunc(("u32Flags = 0x%x rc %Rrc\n", u32Flags, rc));
+    if (RT_FAILURE(rc))
+        u32Flags = 0;
+    return (uint16_t)u32Flags;
+}
diff --git a/ubuntu/vbox/vboxvideo/VBVABase.c b/ubuntu/vbox/vboxvideo/VBVABase.c
new file mode 100644 (file)
index 0000000..cd52de1
--- /dev/null
@@ -0,0 +1,389 @@
+/* $Id: VBVABase.cpp $ */
+/** @file
+ * VirtualBox Video driver, common code - VBVA initialisation and helper
+ * functions.
+ */
+
+/*
+ * 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.
+ */
+
+#include <VBox/VBoxVideoGuest.h>
+#include <VBox/VBoxVideo.h>
+#include <VBox/err.h>
+#include <VBox/log.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+
+/*
+ * There is a hardware ring buffer in the graphics device video RAM, formerly
+ * in the VBox VMMDev PCI memory space.
+ * All graphics commands go there serialized by VBoxVBVABufferBeginUpdate.
+ * and vboxHwBufferEndUpdate.
+ *
+ * off32Free is writing position. off32Data is reading position.
+ * off32Free == off32Data means buffer is empty.
+ * There must be always gap between off32Data and off32Free when data
+ * are in the buffer.
+ * Guest only changes off32Free, host changes off32Data.
+ */
+
+/* Forward declarations of internal functions. */
+static void vboxHwBufferFlush(PHGSMIGUESTCOMMANDCONTEXT pCtx);
+static void vboxHwBufferPlaceDataAt(PVBVABUFFERCONTEXT pCtx, const void *p,
+                                    uint32_t cb, uint32_t offset);
+static bool vboxHwBufferWrite(PVBVABUFFERCONTEXT pCtx,
+                              PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+                              const void *p, uint32_t cb);
+
+
+static bool vboxVBVAInformHost(PVBVABUFFERCONTEXT pCtx,
+                               PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+                               int32_t cScreen, bool bEnable)
+{
+    bool bRc = false;
+
+#if 0  /* All callers check this */
+    if (ppdev->bHGSMISupported)
+#endif
+    {
+        void *p = VBoxHGSMIBufferAlloc(pHGSMICtx,
+                                       sizeof (VBVAENABLE_EX),
+                                       HGSMI_CH_VBVA,
+                                       VBVA_ENABLE);
+        if (!p)
+        {
+            LogFunc(("HGSMIHeapAlloc failed\n"));
+        }
+        else
+        {
+            VBVAENABLE_EX *pEnable = (VBVAENABLE_EX *)p;
+
+            pEnable->Base.u32Flags  = bEnable? VBVA_F_ENABLE: VBVA_F_DISABLE;
+            pEnable->Base.u32Offset = pCtx->offVRAMBuffer;
+            pEnable->Base.i32Result = VERR_NOT_SUPPORTED;
+            if (cScreen >= 0)
+            {
+                pEnable->Base.u32Flags |= VBVA_F_EXTENDED | VBVA_F_ABSOFFSET;
+                pEnable->u32ScreenId    = cScreen;
+            }
+
+            VBoxHGSMIBufferSubmit(pHGSMICtx, p);
+
+            if (bEnable)
+            {
+                bRc = RT_SUCCESS(pEnable->Base.i32Result);
+            }
+            else
+            {
+                bRc = true;
+            }
+
+            VBoxHGSMIBufferFree(pHGSMICtx, p);
+        }
+    }
+
+    return bRc;
+}
+
+/*
+ * Public hardware buffer methods.
+ */
+DECLHIDDEN(bool) VBoxVBVAEnable(PVBVABUFFERCONTEXT pCtx,
+                                PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+                                VBVABUFFER *pVBVA, int32_t cScreen)
+{
+    bool bRc = false;
+
+    LogFlowFunc(("pVBVA %p\n", pVBVA));
+
+#if 0  /* All callers check this */
+    if (ppdev->bHGSMISupported)
+#endif
+    {
+        LogFunc(("pVBVA %p vbva off 0x%x\n", pVBVA, pCtx->offVRAMBuffer));
+
+        pVBVA->hostFlags.u32HostEvents      = 0;
+        pVBVA->hostFlags.u32SupportedOrders = 0;
+        pVBVA->off32Data          = 0;
+        pVBVA->off32Free          = 0;
+        memset(pVBVA->aRecords, 0, sizeof (pVBVA->aRecords));
+        pVBVA->indexRecordFirst   = 0;
+        pVBVA->indexRecordFree    = 0;
+        pVBVA->cbPartialWriteThreshold = 256;
+        pVBVA->cbData             = pCtx->cbBuffer - sizeof (VBVABUFFER) + sizeof (pVBVA->au8Data);
+
+        pCtx->fHwBufferOverflow = false;
+        pCtx->pRecord    = NULL;
+        pCtx->pVBVA      = pVBVA;
+
+        bRc = vboxVBVAInformHost(pCtx, pHGSMICtx, cScreen, true);
+    }
+
+    if (!bRc)
+    {
+        VBoxVBVADisable(pCtx, pHGSMICtx, cScreen);
+    }
+
+    return bRc;
+}
+
+DECLHIDDEN(void) VBoxVBVADisable(PVBVABUFFERCONTEXT pCtx,
+                                 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+                                 int32_t cScreen)
+{
+    LogFlowFunc(("\n"));
+
+    pCtx->fHwBufferOverflow = false;
+    pCtx->pRecord           = NULL;
+    pCtx->pVBVA             = NULL;
+
+    vboxVBVAInformHost(pCtx, pHGSMICtx, cScreen, false);
+
+    return;
+}
+
+DECLHIDDEN(bool) VBoxVBVABufferBeginUpdate(PVBVABUFFERCONTEXT pCtx,
+                                           PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx)
+{
+    bool bRc = false;
+
+    // LogFunc(("flags = 0x%08X\n", pCtx->pVBVA? pCtx->pVBVA->u32HostEvents: -1));
+
+    if (   pCtx->pVBVA
+        && (pCtx->pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
+    {
+        uint32_t indexRecordNext;
+
+        Assert(!pCtx->fHwBufferOverflow);
+        Assert(pCtx->pRecord == NULL);
+
+        indexRecordNext = (pCtx->pVBVA->indexRecordFree + 1) % VBVA_MAX_RECORDS;
+
+        if (indexRecordNext == pCtx->pVBVA->indexRecordFirst)
+        {
+            /* All slots in the records queue are used. */
+            vboxHwBufferFlush (pHGSMICtx);
+        }
+
+        if (indexRecordNext == pCtx->pVBVA->indexRecordFirst)
+        {
+            /* Even after flush there is no place. Fail the request. */
+            LogFunc(("no space in the queue of records!!! first %d, last %d\n",
+                     pCtx->pVBVA->indexRecordFirst, pCtx->pVBVA->indexRecordFree));
+        }
+        else
+        {
+            /* Initialize the record. */
+            VBVARECORD *pRecord = &pCtx->pVBVA->aRecords[pCtx->pVBVA->indexRecordFree];
+
+            pRecord->cbRecord = VBVA_F_RECORD_PARTIAL;
+
+            pCtx->pVBVA->indexRecordFree = indexRecordNext;
+
+            // LogFunc(("indexRecordNext = %d\n", indexRecordNext));
+
+            /* Remember which record we are using. */
+            pCtx->pRecord = pRecord;
+
+            bRc = true;
+        }
+    }
+
+    return bRc;
+}
+
+DECLHIDDEN(void) VBoxVBVABufferEndUpdate(PVBVABUFFERCONTEXT pCtx)
+{
+    VBVARECORD *pRecord;
+
+    // LogFunc(("\n"));
+
+    Assert(pCtx->pVBVA);
+
+    pRecord = pCtx->pRecord;
+    Assert(pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
+
+    /* Mark the record completed. */
+    pRecord->cbRecord &= ~VBVA_F_RECORD_PARTIAL;
+
+    pCtx->fHwBufferOverflow = false;
+    pCtx->pRecord = NULL;
+
+    return;
+}
+
+/*
+ * Private operations.
+ */
+static uint32_t vboxHwBufferAvail (const VBVABUFFER *pVBVA)
+{
+    int32_t i32Diff = pVBVA->off32Data - pVBVA->off32Free;
+
+    return i32Diff > 0? i32Diff: pVBVA->cbData + i32Diff;
+}
+
+static void vboxHwBufferFlush(PHGSMIGUESTCOMMANDCONTEXT pCtx)
+{
+    /* Issue the flush command. */
+    void *p = VBoxHGSMIBufferAlloc(pCtx,
+                                   sizeof (VBVAFLUSH),
+                                   HGSMI_CH_VBVA,
+                                   VBVA_FLUSH);
+    if (!p)
+    {
+        LogFunc(("HGSMIHeapAlloc failed\n"));
+    }
+    else
+    {
+        VBVAFLUSH *pFlush = (VBVAFLUSH *)p;
+
+        pFlush->u32Reserved = 0;
+
+        VBoxHGSMIBufferSubmit(pCtx, p);
+
+        VBoxHGSMIBufferFree(pCtx, p);
+    }
+
+    return;
+}
+
+static void vboxHwBufferPlaceDataAt(PVBVABUFFERCONTEXT pCtx, const void *p,
+                                    uint32_t cb, uint32_t offset)
+{
+    VBVABUFFER *pVBVA = pCtx->pVBVA;
+    uint32_t u32BytesTillBoundary = pVBVA->cbData - offset;
+    uint8_t  *dst                 = &pVBVA->au8Data[offset];
+    int32_t i32Diff               = cb - u32BytesTillBoundary;
+
+    if (i32Diff <= 0)
+    {
+        /* Chunk will not cross buffer boundary. */
+        memcpy (dst, p, cb);
+    }
+    else
+    {
+        /* Chunk crosses buffer boundary. */
+        memcpy (dst, p, u32BytesTillBoundary);
+        memcpy (&pVBVA->au8Data[0], (uint8_t *)p + u32BytesTillBoundary, i32Diff);
+    }
+
+    return;
+}
+
+static bool vboxHwBufferWrite(PVBVABUFFERCONTEXT pCtx,
+                              PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+                              const void *p, uint32_t cb)
+{
+    VBVARECORD *pRecord;
+    uint32_t cbHwBufferAvail;
+
+    uint32_t cbWritten = 0;
+
+    VBVABUFFER *pVBVA = pCtx->pVBVA;
+    Assert(pVBVA);
+
+    if (!pVBVA || pCtx->fHwBufferOverflow)
+    {
+        return false;
+    }
+
+    Assert(pVBVA->indexRecordFirst != pVBVA->indexRecordFree);
+
+    pRecord = pCtx->pRecord;
+    Assert(pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
+
+    // LogFunc(("%d\n", cb));
+
+    cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
+
+    while (cb > 0)
+    {
+        uint32_t cbChunk = cb;
+
+        // LogFunc(("pVBVA->off32Free %d, pRecord->cbRecord 0x%08X, cbHwBufferAvail %d, cb %d, cbWritten %d\n",
+        //             pVBVA->off32Free, pRecord->cbRecord, cbHwBufferAvail, cb, cbWritten));
+
+        if (cbChunk >= cbHwBufferAvail)
+        {
+            LogFunc(("1) avail %d, chunk %d\n", cbHwBufferAvail, cbChunk));
+
+            vboxHwBufferFlush (pHGSMICtx);
+
+            cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
+
+            if (cbChunk >= cbHwBufferAvail)
+            {
+                LogFunc(("no place for %d bytes. Only %d bytes available after flush. Going to partial writes.\n",
+                            cb, cbHwBufferAvail));
+
+                if (cbHwBufferAvail <= pVBVA->cbPartialWriteThreshold)
+                {
+                    LogFunc(("Buffer overflow!!!\n"));
+                    pCtx->fHwBufferOverflow = true;
+                    Assert(false);
+                    return false;
+                }
+
+                cbChunk = cbHwBufferAvail - pVBVA->cbPartialWriteThreshold;
+            }
+        }
+
+        Assert(cbChunk <= cb);
+        Assert(cbChunk <= vboxHwBufferAvail (pVBVA));
+
+        vboxHwBufferPlaceDataAt (pCtx, (uint8_t *)p + cbWritten, cbChunk, pVBVA->off32Free);
+
+        pVBVA->off32Free   = (pVBVA->off32Free + cbChunk) % pVBVA->cbData;
+        pRecord->cbRecord += cbChunk;
+        cbHwBufferAvail -= cbChunk;
+
+        cb        -= cbChunk;
+        cbWritten += cbChunk;
+    }
+
+    return true;
+}
+
+/*
+ * Public writer to the hardware buffer.
+ */
+DECLHIDDEN(bool) VBoxVBVAWrite(PVBVABUFFERCONTEXT pCtx,
+                               PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+                               const void *pv, uint32_t cb)
+{
+    return vboxHwBufferWrite (pCtx, pHGSMICtx, pv, cb);
+}
+
+DECLHIDDEN(bool) VBoxVBVAOrderSupported(PVBVABUFFERCONTEXT pCtx, unsigned code)
+{
+    VBVABUFFER *pVBVA = pCtx->pVBVA;
+
+    if (!pVBVA)
+    {
+        return false;
+    }
+
+    if (pVBVA->hostFlags.u32SupportedOrders & (1 << code))
+    {
+        return true;
+    }
+
+    return false;
+}
+
+DECLHIDDEN(void) VBoxVBVASetupBufferContext(PVBVABUFFERCONTEXT pCtx,
+                                            uint32_t offVRAMBuffer,
+                                            uint32_t cbBuffer)
+{
+    pCtx->offVRAMBuffer = offVRAMBuffer;
+    pCtx->cbBuffer      = cbBuffer;
+}
diff --git a/ubuntu/vbox/vboxvideo/heapoffset.c b/ubuntu/vbox/vboxvideo/heapoffset.c
new file mode 100644 (file)
index 0000000..4962511
--- /dev/null
@@ -0,0 +1,928 @@
+/* $Id: heapoffset.cpp $ */
+/** @file
+ * IPRT - An Offset Based Heap.
+ */
+
+/*
+ * 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_DEFAULT
+#include <iprt/heap.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+#include <iprt/err.h>
+#include <iprt/log.h>
+#include <iprt/param.h>
+#include <iprt/string.h>
+
+#include "internal/magics.h"
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/** Pointer to the heap anchor block. */
+typedef struct RTHEAPOFFSETINTERNAL *PRTHEAPOFFSETINTERNAL;
+/** Pointer to a heap block. */
+typedef struct RTHEAPOFFSETBLOCK *PRTHEAPOFFSETBLOCK;
+/** Pointer to a free heap block. */
+typedef struct RTHEAPOFFSETFREE *PRTHEAPOFFSETFREE;
+
+/**
+ * Structure describing a block in an offset based heap.
+ *
+ * If this block is allocated, it is followed by the user data.
+ * If this block is free, see RTHEAPOFFSETFREE.
+ */
+typedef struct RTHEAPOFFSETBLOCK
+{
+    /** The next block in the global block list. */
+    uint32_t /*PRTHEAPOFFSETBLOCK*/     offNext;
+    /** The previous block in the global block list. */
+    uint32_t /*PRTHEAPOFFSETBLOCK*/     offPrev;
+    /** Offset into the heap of this block. Used to locate the anchor block. */
+    uint32_t /*PRTHEAPOFFSETINTERNAL*/  offSelf;
+    /** Flags + magic. */
+    uint32_t                            fFlags;
+} RTHEAPOFFSETBLOCK;
+AssertCompileSize(RTHEAPOFFSETBLOCK, 16);
+
+/** The block is free if this flag is set. When cleared it's allocated. */
+#define RTHEAPOFFSETBLOCK_FLAGS_FREE        (RT_BIT_32(0))
+/** The magic value. */
+#define RTHEAPOFFSETBLOCK_FLAGS_MAGIC       (UINT32_C(0xabcdef00))
+/** The mask that needs to be applied to RTHEAPOFFSETBLOCK::fFlags to obtain the magic value. */
+#define RTHEAPOFFSETBLOCK_FLAGS_MAGIC_MASK  (~RT_BIT_32(0))
+
+/**
+ * Checks if the specified block is valid or not.
+ * @returns boolean answer.
+ * @param   pBlock      Pointer to a RTHEAPOFFSETBLOCK structure.
+ */
+#define RTHEAPOFFSETBLOCK_IS_VALID(pBlock)  \
+    ( ((pBlock)->fFlags & RTHEAPOFFSETBLOCK_FLAGS_MAGIC_MASK) == RTHEAPOFFSETBLOCK_FLAGS_MAGIC )
+
+/**
+ * Checks if the specified block is valid and in use.
+ * @returns boolean answer.
+ * @param   pBlock      Pointer to a RTHEAPOFFSETBLOCK structure.
+ */
+#define RTHEAPOFFSETBLOCK_IS_VALID_USED(pBlock)  \
+    ( ((pBlock)->fFlags & (RTHEAPOFFSETBLOCK_FLAGS_MAGIC_MASK | RTHEAPOFFSETBLOCK_FLAGS_FREE)) \
+       == RTHEAPOFFSETBLOCK_FLAGS_MAGIC )
+
+/**
+ * Checks if the specified block is valid and free.
+ * @returns boolean answer.
+ * @param   pBlock      Pointer to a RTHEAPOFFSETBLOCK structure.
+ */
+#define RTHEAPOFFSETBLOCK_IS_VALID_FREE(pBlock)  \
+    ( ((pBlock)->fFlags & (RTHEAPOFFSETBLOCK_FLAGS_MAGIC_MASK | RTHEAPOFFSETBLOCK_FLAGS_FREE)) \
+       == (RTHEAPOFFSETBLOCK_FLAGS_MAGIC | RTHEAPOFFSETBLOCK_FLAGS_FREE) )
+
+/**
+ * Checks if the specified block is free or not.
+ * @returns boolean answer.
+ * @param   pBlock      Pointer to a valid RTHEAPOFFSETBLOCK structure.
+ */
+#define RTHEAPOFFSETBLOCK_IS_FREE(pBlock)   (!!((pBlock)->fFlags & RTHEAPOFFSETBLOCK_FLAGS_FREE))
+
+/**
+ * A free heap block.
+ * This is an extended version of RTHEAPOFFSETBLOCK that takes the unused
+ * user data to store free list pointers and a cached size value.
+ */
+typedef struct RTHEAPOFFSETFREE
+{
+    /** Core stuff. */
+    RTHEAPOFFSETBLOCK               Core;
+    /** Pointer to the next free block. */
+    uint32_t /*PRTHEAPOFFSETFREE*/  offNext;
+    /** Pointer to the previous free block. */
+    uint32_t /*PRTHEAPOFFSETFREE*/  offPrev;
+    /** The size of the block (excluding the RTHEAPOFFSETBLOCK part). */
+    uint32_t                        cb;
+    /** An alignment filler to make it a multiple of 16 bytes. */
+    uint32_t                        Alignment;
+} RTHEAPOFFSETFREE;
+AssertCompileSize(RTHEAPOFFSETFREE, 16+16);
+
+
+/**
+ * The heap anchor block.
+ * This structure is placed at the head of the memory block specified to RTHeapOffsetInit(),
+ * which means that the first RTHEAPOFFSETBLOCK appears immediately after this structure.
+ */
+typedef struct RTHEAPOFFSETINTERNAL
+{
+    /** The typical magic (RTHEAPOFFSET_MAGIC). */
+    uint32_t                        u32Magic;
+    /** The heap size. (This structure is included!) */
+    uint32_t                        cbHeap;
+    /** The amount of free memory in the heap. */
+    uint32_t                        cbFree;
+    /** Free head pointer. */
+    uint32_t /*PRTHEAPOFFSETFREE*/  offFreeHead;
+    /** Free tail pointer. */
+    uint32_t /*PRTHEAPOFFSETFREE*/  offFreeTail;
+    /** Make the size of this structure 32 bytes. */
+    uint32_t                        au32Alignment[3];
+} RTHEAPOFFSETINTERNAL;
+AssertCompileSize(RTHEAPOFFSETINTERNAL, 32);
+
+
+/** The minimum allocation size. */
+#define RTHEAPOFFSET_MIN_BLOCK  (sizeof(RTHEAPOFFSETBLOCK))
+AssertCompile(RTHEAPOFFSET_MIN_BLOCK >= sizeof(RTHEAPOFFSETBLOCK));
+AssertCompile(RTHEAPOFFSET_MIN_BLOCK >= sizeof(RTHEAPOFFSETFREE) - sizeof(RTHEAPOFFSETBLOCK));
+
+/** The minimum and default alignment.  */
+#define RTHEAPOFFSET_ALIGNMENT  (sizeof(RTHEAPOFFSETBLOCK))
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+#ifdef RT_STRICT
+# define RTHEAPOFFSET_STRICT 1
+#endif
+
+/**
+ * Converts RTHEAPOFFSETBLOCK::offSelf into a heap anchor block pointer.
+ *
+ * @returns Pointer of given type.
+ * @param   pBlock          The block to find the heap anchor block for.
+ */
+#define RTHEAPOFF_GET_ANCHOR(pBlock)    ( (PRTHEAPOFFSETINTERNAL)((uint8_t *)(pBlock) - (pBlock)->offSelf ) )
+
+
+/**
+ * Converts an offset to a pointer.
+ *
+ * All offsets are relative to the heap to make life simple.
+ *
+ * @returns Pointer of given type.
+ * @param   pHeapInt        Pointer to the heap anchor block.
+ * @param   off             The offset to convert.
+ * @param   type            The desired type.
+ */
+#ifdef RTHEAPOFFSET_STRICT
+# define RTHEAPOFF_TO_PTR_N(pHeapInt, off, type)   ( (type)rtHeapOffCheckedOffToPtr(pHeapInt, off, true /*fNull*/) )
+#else
+# define RTHEAPOFF_TO_PTR_N(pHeapInt, off, type)   ( (type)((off) ? (uint8_t *)(pHeapInt) + (off) : NULL) )
+#endif
+
+/**
+ * Converts an offset to a pointer.
+ *
+ * All offsets are relative to the heap to make life simple.
+ *
+ * @returns Pointer of given type.
+ * @param   pHeapInt        Pointer to the heap anchor block.
+ * @param   off             The offset to convert.
+ * @param   type            The desired type.
+ */
+#ifdef RTHEAPOFFSET_STRICT
+# define RTHEAPOFF_TO_PTR(pHeapInt, off, type)   ( (type)rtHeapOffCheckedOffToPtr(pHeapInt, off, false /*fNull*/) )
+#else
+# define RTHEAPOFF_TO_PTR(pHeapInt, off, type)   ( (type)((uint8_t *)(pHeapInt) + (off)) )
+#endif
+
+/**
+ * Converts a pointer to an offset.
+ *
+ * All offsets are relative to the heap to make life simple.
+ *
+ * @returns Offset into the heap.
+ * @param   pHeapInt        Pointer to the heap anchor block.
+ * @param   ptr             The pointer to convert.
+ */
+#ifdef RTHEAPOFFSET_STRICT
+# define RTHEAPOFF_TO_OFF(pHeapInt, ptr)    rtHeapOffCheckedPtrToOff(pHeapInt, ptr)
+#else
+# define RTHEAPOFF_TO_OFF(pHeapInt, ptr)    ( (uint32_t)((ptr) ? (uintptr_t)(ptr) - (uintptr_t)(pHeapInt) : UINT32_C(0)) )
+#endif
+
+#define ASSERT_L(a, b)    AssertMsg((a) <  (b), ("a=%08x b=%08x\n", (a), (b)))
+#define ASSERT_LE(a, b)   AssertMsg((a) <= (b), ("a=%08x b=%08x\n", (a), (b)))
+#define ASSERT_G(a, b)    AssertMsg((a) >  (b), ("a=%08x b=%08x\n", (a), (b)))
+#define ASSERT_GE(a, b)   AssertMsg((a) >= (b), ("a=%08x b=%08x\n", (a), (b)))
+#define ASSERT_ALIGN(a)   AssertMsg(!((uintptr_t)(a) & (RTHEAPOFFSET_ALIGNMENT - 1)), ("a=%p\n", (uintptr_t)(a)))
+
+#define ASSERT_PREV(pHeapInt, pBlock)  \
+    do { ASSERT_ALIGN((pBlock)->offPrev); \
+         if ((pBlock)->offPrev) \
+         { \
+             ASSERT_L((pBlock)->offPrev, RTHEAPOFF_TO_OFF(pHeapInt, pBlock)); \
+             ASSERT_GE((pBlock)->offPrev, sizeof(RTHEAPOFFSETINTERNAL)); \
+         } \
+         else \
+             Assert((pBlock) == (PRTHEAPOFFSETBLOCK)((pHeapInt) + 1)); \
+    } while (0)
+
+#define ASSERT_NEXT(pHeap, pBlock) \
+    do { ASSERT_ALIGN((pBlock)->offNext); \
+         if ((pBlock)->offNext) \
+         { \
+             ASSERT_L((pBlock)->offNext, (pHeapInt)->cbHeap); \
+             ASSERT_G((pBlock)->offNext, RTHEAPOFF_TO_OFF(pHeapInt, pBlock)); \
+         } \
+    } while (0)
+
+#define ASSERT_BLOCK(pHeapInt, pBlock) \
+    do { AssertMsg(RTHEAPOFFSETBLOCK_IS_VALID(pBlock), ("%#x\n", (pBlock)->fFlags)); \
+         AssertMsg(RTHEAPOFF_GET_ANCHOR(pBlock) == (pHeapInt), ("%p != %p\n", RTHEAPOFF_GET_ANCHOR(pBlock), (pHeapInt))); \
+         ASSERT_GE(RTHEAPOFF_TO_OFF(pHeapInt, pBlock), sizeof(RTHEAPOFFSETINTERNAL)); \
+         ASSERT_L( RTHEAPOFF_TO_OFF(pHeapInt, pBlock), (pHeapInt)->cbHeap); \
+         ASSERT_NEXT(pHeapInt, pBlock); \
+         ASSERT_PREV(pHeapInt, pBlock); \
+    } while (0)
+
+#define ASSERT_BLOCK_USED(pHeapInt, pBlock) \
+    do { AssertMsg(RTHEAPOFFSETBLOCK_IS_VALID_USED((pBlock)), ("%#x\n", (pBlock)->fFlags)); \
+         AssertMsg(RTHEAPOFF_GET_ANCHOR(pBlock) == (pHeapInt), ("%p != %p\n", RTHEAPOFF_GET_ANCHOR(pBlock), (pHeapInt))); \
+         ASSERT_GE(RTHEAPOFF_TO_OFF(pHeapInt, pBlock), sizeof(RTHEAPOFFSETINTERNAL)); \
+         ASSERT_L( RTHEAPOFF_TO_OFF(pHeapInt, pBlock), (pHeapInt)->cbHeap); \
+         ASSERT_NEXT(pHeapInt, pBlock); \
+         ASSERT_PREV(pHeapInt, pBlock); \
+    } while (0)
+
+#define ASSERT_FREE_PREV(pHeapInt, pBlock) \
+    do { ASSERT_ALIGN((pBlock)->offPrev); \
+         if ((pBlock)->offPrev) \
+         { \
+             ASSERT_GE((pBlock)->offPrev, (pHeapInt)->offFreeHead); \
+             ASSERT_L((pBlock)->offPrev, RTHEAPOFF_TO_OFF(pHeapInt, pBlock)); \
+             ASSERT_LE((pBlock)->offPrev, (pBlock)->Core.offPrev); \
+         } \
+         else \
+             Assert((pBlock) == RTHEAPOFF_TO_PTR(pHeapInt, (pHeapInt)->offFreeHead, PRTHEAPOFFSETFREE) ); \
+    } while (0)
+
+#define ASSERT_FREE_NEXT(pHeapInt, pBlock) \
+    do { ASSERT_ALIGN((pBlock)->offNext); \
+         if ((pBlock)->offNext) \
+         { \
+             ASSERT_LE((pBlock)->offNext, (pHeapInt)->offFreeTail); \
+             ASSERT_G((pBlock)->offNext, RTHEAPOFF_TO_OFF(pHeapInt, pBlock)); \
+             ASSERT_GE((pBlock)->offNext, (pBlock)->Core.offNext); \
+         } \
+         else \
+             Assert((pBlock) == RTHEAPOFF_TO_PTR(pHeapInt, (pHeapInt)->offFreeTail, PRTHEAPOFFSETFREE)); \
+    } while (0)
+
+#ifdef RTHEAPOFFSET_STRICT
+# define ASSERT_FREE_CB(pHeapInt, pBlock) \
+    do { size_t cbCalc = ((pBlock)->Core.offNext ? (pBlock)->Core.offNext : (pHeapInt)->cbHeap) \
+                       - RTHEAPOFF_TO_OFF((pHeapInt), (pBlock)) - sizeof(RTHEAPOFFSETBLOCK); \
+         AssertMsg((pBlock)->cb == cbCalc, ("cb=%#zx cbCalc=%#zx\n", (pBlock)->cb, cbCalc)); \
+    } while (0)
+#else
+# define ASSERT_FREE_CB(pHeapInt, pBlock) do {} while (0)
+#endif
+
+/** Asserts that a free block is valid. */
+#define ASSERT_BLOCK_FREE(pHeapInt, pBlock) \
+    do { ASSERT_BLOCK(pHeapInt, &(pBlock)->Core); \
+         Assert(RTHEAPOFFSETBLOCK_IS_VALID_FREE(&(pBlock)->Core)); \
+         ASSERT_GE(RTHEAPOFF_TO_OFF(pHeapInt, pBlock), (pHeapInt)->offFreeHead); \
+         ASSERT_LE(RTHEAPOFF_TO_OFF(pHeapInt, pBlock), (pHeapInt)->offFreeTail); \
+         ASSERT_FREE_NEXT(pHeapInt, pBlock); \
+         ASSERT_FREE_PREV(pHeapInt, pBlock); \
+         ASSERT_FREE_CB(pHeapInt, pBlock); \
+    } while (0)
+
+/** Asserts that the heap anchor block is ok. */
+#define ASSERT_ANCHOR(pHeapInt) \
+    do { AssertPtr(pHeapInt);\
+         Assert((pHeapInt)->u32Magic == RTHEAPOFFSET_MAGIC); \
+    } while (0)
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+#ifdef RTHEAPOFFSET_STRICT
+static void rtHeapOffsetAssertAll(PRTHEAPOFFSETINTERNAL pHeapInt);
+#endif
+static PRTHEAPOFFSETBLOCK rtHeapOffsetAllocBlock(PRTHEAPOFFSETINTERNAL pHeapInt, size_t cb, size_t uAlignment);
+static void rtHeapOffsetFreeBlock(PRTHEAPOFFSETINTERNAL pHeapInt, PRTHEAPOFFSETBLOCK pBlock);
+
+#ifdef RTHEAPOFFSET_STRICT
+
+/** Checked version of RTHEAPOFF_TO_PTR and RTHEAPOFF_TO_PTR_N. */
+static void *rtHeapOffCheckedOffToPtr(PRTHEAPOFFSETINTERNAL pHeapInt, uint32_t off, bool fNull)
+{
+    Assert(off || fNull);
+    if (!off)
+        return NULL;
+    AssertMsg(off < pHeapInt->cbHeap,   ("%#x %#x\n", off, pHeapInt->cbHeap));
+    AssertMsg(off >= sizeof(*pHeapInt), ("%#x %#x\n", off, sizeof(*pHeapInt)));
+    return (uint8_t *)pHeapInt + off;
+}
+
+/** Checked version of RTHEAPOFF_TO_OFF. */
+static uint32_t rtHeapOffCheckedPtrToOff(PRTHEAPOFFSETINTERNAL pHeapInt, void *pv)
+{
+    if (!pv)
+        return 0;
+    uintptr_t off = (uintptr_t)pv - (uintptr_t)pHeapInt;
+    AssertMsg(off < pHeapInt->cbHeap,   ("%#x %#x\n", off, pHeapInt->cbHeap));
+    AssertMsg(off >= sizeof(*pHeapInt), ("%#x %#x\n", off, sizeof(*pHeapInt)));
+    return (uint32_t)off;
+}
+
+#endif /* RTHEAPOFFSET_STRICT */
+
+
+
+RTDECL(int) RTHeapOffsetInit(PRTHEAPOFFSET phHeap, void *pvMemory, size_t cbMemory)
+{
+    PRTHEAPOFFSETINTERNAL pHeapInt;
+    PRTHEAPOFFSETFREE pFree;
+    unsigned i;
+
+    /*
+     * Validate input. The imposed minimum heap size is just a convenient value.
+     */
+    AssertReturn(cbMemory >= PAGE_SIZE, VERR_INVALID_PARAMETER);
+    AssertReturn(cbMemory < UINT32_MAX, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pvMemory, VERR_INVALID_POINTER);
+    AssertReturn((uintptr_t)pvMemory + (cbMemory - 1) > (uintptr_t)cbMemory, VERR_INVALID_PARAMETER);
+
+    /*
+     * Place the heap anchor block at the start of the heap memory,
+     * enforce 32 byte alignment of it. Also align the heap size correctly.
+     */
+    pHeapInt = (PRTHEAPOFFSETINTERNAL)pvMemory;
+    if ((uintptr_t)pvMemory & 31)
+    {
+        const uintptr_t off = 32 - ((uintptr_t)pvMemory & 31);
+        cbMemory -= off;
+        pHeapInt = (PRTHEAPOFFSETINTERNAL)((uintptr_t)pvMemory + off);
+    }
+    cbMemory &= ~(RTHEAPOFFSET_ALIGNMENT - 1);
+
+
+    /* Init the heap anchor block. */
+    pHeapInt->u32Magic = RTHEAPOFFSET_MAGIC;
+    pHeapInt->cbHeap = (uint32_t)cbMemory;
+    pHeapInt->cbFree = (uint32_t)cbMemory
+                     - sizeof(RTHEAPOFFSETBLOCK)
+                     - sizeof(RTHEAPOFFSETINTERNAL);
+    pHeapInt->offFreeTail = pHeapInt->offFreeHead = sizeof(*pHeapInt);
+    for (i = 0; i < RT_ELEMENTS(pHeapInt->au32Alignment); i++)
+        pHeapInt->au32Alignment[i] = UINT32_MAX;
+
+    /* Init the single free block. */
+    pFree = RTHEAPOFF_TO_PTR(pHeapInt, pHeapInt->offFreeHead, PRTHEAPOFFSETFREE);
+    pFree->Core.offNext = 0;
+    pFree->Core.offPrev = 0;
+    pFree->Core.offSelf = pHeapInt->offFreeHead;
+    pFree->Core.fFlags = RTHEAPOFFSETBLOCK_FLAGS_MAGIC | RTHEAPOFFSETBLOCK_FLAGS_FREE;
+    pFree->offNext = 0;
+    pFree->offPrev = 0;
+    pFree->cb = pHeapInt->cbFree;
+
+    *phHeap = pHeapInt;
+
+#ifdef RTHEAPOFFSET_STRICT
+    rtHeapOffsetAssertAll(pHeapInt);
+#endif
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTHeapOffsetInit);
+
+
+RTDECL(void *) RTHeapOffsetAlloc(RTHEAPOFFSET hHeap, size_t cb, size_t cbAlignment)
+{
+    PRTHEAPOFFSETINTERNAL pHeapInt = hHeap;
+    PRTHEAPOFFSETBLOCK pBlock;
+
+    /*
+     * Validate and adjust the input.
+     */
+    AssertPtrReturn(pHeapInt, NULL);
+    if (cb < RTHEAPOFFSET_MIN_BLOCK)
+        cb = RTHEAPOFFSET_MIN_BLOCK;
+    else
+        cb = RT_ALIGN_Z(cb, RTHEAPOFFSET_ALIGNMENT);
+    if (!cbAlignment)
+        cbAlignment = RTHEAPOFFSET_ALIGNMENT;
+    else
+    {
+        Assert(!(cbAlignment & (cbAlignment - 1)));
+        Assert((cbAlignment & ~(cbAlignment - 1)) == cbAlignment);
+        if (cbAlignment < RTHEAPOFFSET_ALIGNMENT)
+            cbAlignment = RTHEAPOFFSET_ALIGNMENT;
+    }
+
+    /*
+     * Do the allocation.
+     */
+    pBlock = rtHeapOffsetAllocBlock(pHeapInt, cb, cbAlignment);
+    if (RT_LIKELY(pBlock))
+    {
+        void *pv = pBlock + 1;
+        return pv;
+    }
+    return NULL;
+}
+RT_EXPORT_SYMBOL(RTHeapOffsetAlloc);
+
+
+RTDECL(void *) RTHeapOffsetAllocZ(RTHEAPOFFSET hHeap, size_t cb, size_t cbAlignment)
+{
+    PRTHEAPOFFSETINTERNAL pHeapInt = hHeap;
+    PRTHEAPOFFSETBLOCK pBlock;
+
+    /*
+     * Validate and adjust the input.
+     */
+    AssertPtrReturn(pHeapInt, NULL);
+    if (cb < RTHEAPOFFSET_MIN_BLOCK)
+        cb = RTHEAPOFFSET_MIN_BLOCK;
+    else
+        cb = RT_ALIGN_Z(cb, RTHEAPOFFSET_ALIGNMENT);
+    if (!cbAlignment)
+        cbAlignment = RTHEAPOFFSET_ALIGNMENT;
+    else
+    {
+        Assert(!(cbAlignment & (cbAlignment - 1)));
+        Assert((cbAlignment & ~(cbAlignment - 1)) == cbAlignment);
+        if (cbAlignment < RTHEAPOFFSET_ALIGNMENT)
+            cbAlignment = RTHEAPOFFSET_ALIGNMENT;
+    }
+
+    /*
+     * Do the allocation.
+     */
+    pBlock = rtHeapOffsetAllocBlock(pHeapInt, cb, cbAlignment);
+    if (RT_LIKELY(pBlock))
+    {
+        void *pv = pBlock + 1;
+        memset(pv, 0, cb);
+        return pv;
+    }
+    return NULL;
+}
+RT_EXPORT_SYMBOL(RTHeapOffsetAllocZ);
+
+
+/**
+ * Allocates a block of memory from the specified heap.
+ *
+ * No parameter validation or adjustment is performed.
+ *
+ * @returns Pointer to the allocated block.
+ * @returns NULL on failure.
+ *
+ * @param   pHeapInt    The heap.
+ * @param   cb          Size of the memory block to allocate.
+ * @param   uAlignment  The alignment specifications for the allocated block.
+ */
+static PRTHEAPOFFSETBLOCK rtHeapOffsetAllocBlock(PRTHEAPOFFSETINTERNAL pHeapInt, size_t cb, size_t uAlignment)
+{
+    PRTHEAPOFFSETBLOCK  pRet = NULL;
+    PRTHEAPOFFSETFREE   pFree;
+
+    AssertReturn((pHeapInt)->u32Magic == RTHEAPOFFSET_MAGIC, NULL);
+#ifdef RTHEAPOFFSET_STRICT
+    rtHeapOffsetAssertAll(pHeapInt);
+#endif
+
+    /*
+     * Search for a fitting block from the lower end of the heap.
+     */
+    for (pFree = RTHEAPOFF_TO_PTR_N(pHeapInt, pHeapInt->offFreeHead, PRTHEAPOFFSETFREE);
+         pFree;
+         pFree = RTHEAPOFF_TO_PTR_N(pHeapInt, pFree->offNext, PRTHEAPOFFSETFREE))
+    {
+        uintptr_t offAlign;
+        ASSERT_BLOCK_FREE(pHeapInt, pFree);
+
+        /*
+         * Match for size and alignment.
+         */
+        if (pFree->cb < cb)
+            continue;
+        offAlign = (uintptr_t)(&pFree->Core + 1) & (uAlignment - 1);
+        if (offAlign)
+        {
+            PRTHEAPOFFSETFREE pPrev;
+
+            offAlign = (uintptr_t)(&pFree[1].Core + 1) & (uAlignment - 1);
+            offAlign = uAlignment - offAlign;
+            if (pFree->cb < cb + offAlign + sizeof(RTHEAPOFFSETFREE))
+                continue;
+
+            /*
+             * Split up the free block into two, so that the 2nd is aligned as
+             * per specification.
+             */
+            pPrev = pFree;
+            pFree = (PRTHEAPOFFSETFREE)((uintptr_t)(pFree + 1) + offAlign);
+            pFree->Core.offPrev = pPrev->Core.offSelf;
+            pFree->Core.offNext = pPrev->Core.offNext;
+            pFree->Core.offSelf = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
+            pFree->Core.fFlags  = RTHEAPOFFSETBLOCK_FLAGS_MAGIC | RTHEAPOFFSETBLOCK_FLAGS_FREE;
+            pFree->offPrev      = pPrev->Core.offSelf;
+            pFree->offNext      = pPrev->offNext;
+            pFree->cb           = (pFree->Core.offNext ? pFree->Core.offNext : pHeapInt->cbHeap)
+                                - pFree->Core.offSelf - sizeof(RTHEAPOFFSETBLOCK);
+
+            pPrev->Core.offNext = pFree->Core.offSelf;
+            pPrev->offNext      = pFree->Core.offSelf;
+            pPrev->cb           = pFree->Core.offSelf - pPrev->Core.offSelf - sizeof(RTHEAPOFFSETBLOCK);
+
+            if (pFree->Core.offNext)
+                RTHEAPOFF_TO_PTR(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETBLOCK)->offPrev = pFree->Core.offSelf;
+            if (pFree->offNext)
+                RTHEAPOFF_TO_PTR(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETFREE)->offPrev = pFree->Core.offSelf;
+            else
+                pHeapInt->offFreeTail = pFree->Core.offSelf;
+
+            pHeapInt->cbFree -= sizeof(RTHEAPOFFSETBLOCK);
+            ASSERT_BLOCK_FREE(pHeapInt, pPrev);
+            ASSERT_BLOCK_FREE(pHeapInt, pFree);
+        }
+
+        /*
+         * Split off a new FREE block?
+         */
+        if (pFree->cb >= cb + RT_ALIGN_Z(sizeof(RTHEAPOFFSETFREE), RTHEAPOFFSET_ALIGNMENT))
+        {
+            /*
+             * Create a new FREE block at then end of this one.
+             */
+            PRTHEAPOFFSETFREE   pNew = (PRTHEAPOFFSETFREE)((uintptr_t)&pFree->Core + cb + sizeof(RTHEAPOFFSETBLOCK));
+
+            pNew->Core.offSelf = RTHEAPOFF_TO_OFF(pHeapInt, pNew);
+            pNew->Core.offNext = pFree->Core.offNext;
+            if (pFree->Core.offNext)
+                RTHEAPOFF_TO_PTR(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETBLOCK)->offPrev = pNew->Core.offSelf;
+            pNew->Core.offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
+            pNew->Core.fFlags = RTHEAPOFFSETBLOCK_FLAGS_MAGIC | RTHEAPOFFSETBLOCK_FLAGS_FREE;
+
+            pNew->offNext = pFree->offNext;
+            if (pNew->offNext)
+                RTHEAPOFF_TO_PTR(pHeapInt, pNew->offNext, PRTHEAPOFFSETFREE)->offPrev = pNew->Core.offSelf;
+            else
+                pHeapInt->offFreeTail = pNew->Core.offSelf;
+            pNew->offPrev = pFree->offPrev;
+            if (pNew->offPrev)
+                RTHEAPOFF_TO_PTR(pHeapInt, pNew->offPrev, PRTHEAPOFFSETFREE)->offNext = pNew->Core.offSelf;
+            else
+                pHeapInt->offFreeHead = pNew->Core.offSelf;
+            pNew->cb    = (pNew->Core.offNext ? pNew->Core.offNext : pHeapInt->cbHeap) \
+                        - pNew->Core.offSelf - sizeof(RTHEAPOFFSETBLOCK);
+            ASSERT_BLOCK_FREE(pHeapInt, pNew);
+
+            /*
+             * Adjust and convert the old FREE node into a USED node.
+             */
+            pFree->Core.fFlags &= ~RTHEAPOFFSETBLOCK_FLAGS_FREE;
+            pFree->Core.offNext = pNew->Core.offSelf;
+            pHeapInt->cbFree -= pFree->cb;
+            pHeapInt->cbFree += pNew->cb;
+            pRet = &pFree->Core;
+            ASSERT_BLOCK_USED(pHeapInt, pRet);
+        }
+        else
+        {
+            /*
+             * Link it out of the free list.
+             */
+            if (pFree->offNext)
+                RTHEAPOFF_TO_PTR(pHeapInt, pFree->offNext, PRTHEAPOFFSETFREE)->offPrev = pFree->offPrev;
+            else
+                pHeapInt->offFreeTail = pFree->offPrev;
+            if (pFree->offPrev)
+                RTHEAPOFF_TO_PTR(pHeapInt, pFree->offPrev, PRTHEAPOFFSETFREE)->offNext = pFree->offNext;
+            else
+                pHeapInt->offFreeHead = pFree->offNext;
+
+            /*
+             * Convert it to a used block.
+             */
+            pHeapInt->cbFree -= pFree->cb;
+            pFree->Core.fFlags &= ~RTHEAPOFFSETBLOCK_FLAGS_FREE;
+            pRet = &pFree->Core;
+            ASSERT_BLOCK_USED(pHeapInt, pRet);
+        }
+        break;
+    }
+
+#ifdef RTHEAPOFFSET_STRICT
+    rtHeapOffsetAssertAll(pHeapInt);
+#endif
+    return pRet;
+}
+
+
+RTDECL(void) RTHeapOffsetFree(RTHEAPOFFSET hHeap, void *pv)
+{
+    PRTHEAPOFFSETINTERNAL pHeapInt;
+    PRTHEAPOFFSETBLOCK pBlock;
+
+    /*
+     * Validate input.
+     */
+    if (!pv)
+        return;
+    AssertPtr(pv);
+    Assert(RT_ALIGN_P(pv, RTHEAPOFFSET_ALIGNMENT) == pv);
+
+    /*
+     * Get the block and heap. If in strict mode, validate these.
+     */
+    pBlock = (PRTHEAPOFFSETBLOCK)pv - 1;
+    pHeapInt = RTHEAPOFF_GET_ANCHOR(pBlock);
+    ASSERT_BLOCK_USED(pHeapInt, pBlock);
+    ASSERT_ANCHOR(pHeapInt);
+    Assert(pHeapInt == (PRTHEAPOFFSETINTERNAL)hHeap || !hHeap); RT_NOREF_PV(hHeap);
+
+#ifdef RTHEAPOFFSET_FREE_POISON
+    /*
+     * Poison the block.
+     */
+    const size_t cbBlock = (pBlock->pNext ? (uintptr_t)pBlock->pNext : (uintptr_t)pHeapInt->pvEnd)
+                         - (uintptr_t)pBlock - sizeof(RTHEAPOFFSETBLOCK);
+    memset(pBlock + 1, RTHEAPOFFSET_FREE_POISON, cbBlock);
+#endif
+
+    /*
+     * Call worker which does the actual job.
+     */
+    rtHeapOffsetFreeBlock(pHeapInt, pBlock);
+}
+RT_EXPORT_SYMBOL(RTHeapOffsetFree);
+
+
+/**
+ * Free a memory block.
+ *
+ * @param   pHeapInt       The heap.
+ * @param   pBlock         The memory block to free.
+ */
+static void rtHeapOffsetFreeBlock(PRTHEAPOFFSETINTERNAL pHeapInt, PRTHEAPOFFSETBLOCK pBlock)
+{
+    PRTHEAPOFFSETFREE   pFree = (PRTHEAPOFFSETFREE)pBlock;
+    PRTHEAPOFFSETFREE   pLeft;
+    PRTHEAPOFFSETFREE   pRight;
+
+#ifdef RTHEAPOFFSET_STRICT
+    rtHeapOffsetAssertAll(pHeapInt);
+#endif
+
+    /*
+     * Look for the closest free list blocks by walking the blocks right
+     * of us (both lists are sorted by address).
+     */
+    pLeft = NULL;
+    pRight = NULL;
+    if (pHeapInt->offFreeTail)
+    {
+        pRight = RTHEAPOFF_TO_PTR_N(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETFREE);
+        while (pRight && !RTHEAPOFFSETBLOCK_IS_FREE(&pRight->Core))
+        {
+            ASSERT_BLOCK(pHeapInt, &pRight->Core);
+            pRight = RTHEAPOFF_TO_PTR_N(pHeapInt, pRight->Core.offNext, PRTHEAPOFFSETFREE);
+        }
+        if (!pRight)
+            pLeft = RTHEAPOFF_TO_PTR_N(pHeapInt, pHeapInt->offFreeTail, PRTHEAPOFFSETFREE);
+        else
+        {
+            ASSERT_BLOCK_FREE(pHeapInt, pRight);
+            pLeft = RTHEAPOFF_TO_PTR_N(pHeapInt, pRight->offPrev, PRTHEAPOFFSETFREE);
+        }
+        if (pLeft)
+            ASSERT_BLOCK_FREE(pHeapInt, pLeft);
+    }
+    AssertMsgReturnVoid(pLeft != pFree, ("Freed twice! pv=%p (pBlock=%p)\n", pBlock + 1, pBlock));
+    ASSERT_L(RTHEAPOFF_TO_OFF(pHeapInt, pLeft), RTHEAPOFF_TO_OFF(pHeapInt, pFree));
+    Assert(!pRight || (uintptr_t)pRight > (uintptr_t)pFree);
+    Assert(!pLeft || RTHEAPOFF_TO_PTR_N(pHeapInt, pLeft->offNext, PRTHEAPOFFSETFREE) == pRight);
+
+    /*
+     * Insert at the head of the free block list?
+     */
+    if (!pLeft)
+    {
+        Assert(pRight == RTHEAPOFF_TO_PTR_N(pHeapInt, pHeapInt->offFreeHead, PRTHEAPOFFSETFREE));
+        pFree->Core.fFlags |= RTHEAPOFFSETBLOCK_FLAGS_FREE;
+        pFree->offPrev = 0;
+        pFree->offNext = RTHEAPOFF_TO_OFF(pHeapInt, pRight);
+        if (pRight)
+            pRight->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
+        else
+            pHeapInt->offFreeTail = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
+        pHeapInt->offFreeHead = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
+    }
+    else
+    {
+        /*
+         * Can we merge with left hand free block?
+         */
+        if (pLeft->Core.offNext == RTHEAPOFF_TO_OFF(pHeapInt, pFree))
+        {
+            pLeft->Core.offNext = pFree->Core.offNext;
+            if (pFree->Core.offNext)
+                RTHEAPOFF_TO_PTR(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETBLOCK)->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pLeft);
+            pHeapInt->cbFree -= pLeft->cb;
+            pFree = pLeft;
+        }
+        /*
+         * No, just link it into the free list then.
+         */
+        else
+        {
+            pFree->Core.fFlags |= RTHEAPOFFSETBLOCK_FLAGS_FREE;
+            pFree->offNext = RTHEAPOFF_TO_OFF(pHeapInt, pRight);
+            pFree->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pLeft);
+            pLeft->offNext = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
+            if (pRight)
+                pRight->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
+            else
+                pHeapInt->offFreeTail = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
+        }
+    }
+
+    /*
+     * Can we merge with right hand free block?
+     */
+    if (    pRight
+        &&  pRight->Core.offPrev == RTHEAPOFF_TO_OFF(pHeapInt, pFree))
+    {
+        /* core */
+        pFree->Core.offNext = pRight->Core.offNext;
+        if (pRight->Core.offNext)
+            RTHEAPOFF_TO_PTR(pHeapInt, pRight->Core.offNext, PRTHEAPOFFSETBLOCK)->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
+
+        /* free */
+        pFree->offNext = pRight->offNext;
+        if (pRight->offNext)
+            RTHEAPOFF_TO_PTR(pHeapInt, pRight->offNext, PRTHEAPOFFSETFREE)->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
+        else
+            pHeapInt->offFreeTail = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
+        pHeapInt->cbFree -= pRight->cb;
+    }
+
+    /*
+     * Calculate the size and update free stats.
+     */
+    pFree->cb = (pFree->Core.offNext ? pFree->Core.offNext : pHeapInt->cbHeap)
+              - RTHEAPOFF_TO_OFF(pHeapInt, pFree) - sizeof(RTHEAPOFFSETBLOCK);
+    pHeapInt->cbFree += pFree->cb;
+    ASSERT_BLOCK_FREE(pHeapInt, pFree);
+
+#ifdef RTHEAPOFFSET_STRICT
+    rtHeapOffsetAssertAll(pHeapInt);
+#endif
+}
+
+
+#ifdef RTHEAPOFFSET_STRICT
+/**
+ * Internal consistency check (relying on assertions).
+ * @param   pHeapInt
+ */
+static void rtHeapOffsetAssertAll(PRTHEAPOFFSETINTERNAL pHeapInt)
+{
+    PRTHEAPOFFSETFREE pPrev = NULL;
+    PRTHEAPOFFSETFREE pPrevFree = NULL;
+    PRTHEAPOFFSETFREE pBlock;
+    for (pBlock = (PRTHEAPOFFSETFREE)(pHeapInt + 1);
+         pBlock;
+         pBlock = RTHEAPOFF_TO_PTR_N(pHeapInt, pBlock->Core.offNext, PRTHEAPOFFSETFREE))
+    {
+        if (RTHEAPOFFSETBLOCK_IS_FREE(&pBlock->Core))
+        {
+            ASSERT_BLOCK_FREE(pHeapInt, pBlock);
+            Assert(pBlock->offPrev == RTHEAPOFF_TO_OFF(pHeapInt, pPrevFree));
+            Assert(pPrevFree || pHeapInt->offFreeHead == RTHEAPOFF_TO_OFF(pHeapInt, pBlock));
+            pPrevFree = pBlock;
+        }
+        else
+            ASSERT_BLOCK_USED(pHeapInt, &pBlock->Core);
+        Assert(!pPrev || RTHEAPOFF_TO_OFF(pHeapInt, pPrev) == pBlock->Core.offPrev);
+        pPrev = pBlock;
+    }
+    Assert(pHeapInt->offFreeTail == RTHEAPOFF_TO_OFF(pHeapInt, pPrevFree));
+}
+#endif
+
+
+RTDECL(size_t) RTHeapOffsetSize(RTHEAPOFFSET hHeap, void *pv)
+{
+    PRTHEAPOFFSETINTERNAL pHeapInt;
+    PRTHEAPOFFSETBLOCK pBlock;
+    size_t cbBlock;
+
+    /*
+     * Validate input.
+     */
+    if (!pv)
+        return 0;
+    AssertPtrReturn(pv, 0);
+    AssertReturn(RT_ALIGN_P(pv, RTHEAPOFFSET_ALIGNMENT) == pv, 0);
+
+    /*
+     * Get the block and heap. If in strict mode, validate these.
+     */
+    pBlock = (PRTHEAPOFFSETBLOCK)pv - 1;
+    pHeapInt = RTHEAPOFF_GET_ANCHOR(pBlock);
+    ASSERT_BLOCK_USED(pHeapInt, pBlock);
+    ASSERT_ANCHOR(pHeapInt);
+    Assert(pHeapInt == (PRTHEAPOFFSETINTERNAL)hHeap || !hHeap); RT_NOREF_PV(hHeap);
+
+    /*
+     * Calculate the block size.
+     */
+    cbBlock = (pBlock->offNext ? pBlock->offNext : pHeapInt->cbHeap)
+            - RTHEAPOFF_TO_OFF(pHeapInt, pBlock) - sizeof(RTHEAPOFFSETBLOCK);
+    return cbBlock;
+}
+RT_EXPORT_SYMBOL(RTHeapOffsetSize);
+
+
+RTDECL(size_t) RTHeapOffsetGetHeapSize(RTHEAPOFFSET hHeap)
+{
+    PRTHEAPOFFSETINTERNAL pHeapInt;
+
+    if (hHeap == NIL_RTHEAPOFFSET)
+        return 0;
+
+    pHeapInt = hHeap;
+    AssertPtrReturn(pHeapInt, 0);
+    ASSERT_ANCHOR(pHeapInt);
+    return pHeapInt->cbHeap;
+}
+RT_EXPORT_SYMBOL(RTHeapOffsetGetHeapSize);
+
+
+RTDECL(size_t) RTHeapOffsetGetFreeSize(RTHEAPOFFSET hHeap)
+{
+    PRTHEAPOFFSETINTERNAL pHeapInt;
+
+    if (hHeap == NIL_RTHEAPOFFSET)
+        return 0;
+
+    pHeapInt = hHeap;
+    AssertPtrReturn(pHeapInt, 0);
+    ASSERT_ANCHOR(pHeapInt);
+    return pHeapInt->cbFree;
+}
+RT_EXPORT_SYMBOL(RTHeapOffsetGetFreeSize);
+
+
+RTDECL(void) RTHeapOffsetDump(RTHEAPOFFSET hHeap, PFNRTHEAPOFFSETPRINTF pfnPrintf)
+{
+    PRTHEAPOFFSETINTERNAL pHeapInt = (PRTHEAPOFFSETINTERNAL)hHeap;
+    PRTHEAPOFFSETFREE pBlock;
+
+    pfnPrintf("**** Dumping Heap %p - cbHeap=%x cbFree=%x ****\n",
+              hHeap, pHeapInt->cbHeap, pHeapInt->cbFree);
+
+    for (pBlock = (PRTHEAPOFFSETFREE)(pHeapInt + 1);
+         pBlock;
+         pBlock = RTHEAPOFF_TO_PTR_N(pHeapInt, pBlock->Core.offNext, PRTHEAPOFFSETFREE))
+    {
+        size_t cb = (pBlock->offNext ? pBlock->Core.offNext : pHeapInt->cbHeap)
+                  - RTHEAPOFF_TO_OFF(pHeapInt, pBlock) - sizeof(RTHEAPOFFSETBLOCK);
+        if (RTHEAPOFFSETBLOCK_IS_FREE(&pBlock->Core))
+            pfnPrintf("%p  %06x FREE offNext=%06x offPrev=%06x fFlags=%#x cb=%#06x : cb=%#06x offNext=%06x offPrev=%06x\n",
+                      pBlock, pBlock->Core.offSelf, pBlock->Core.offNext, pBlock->Core.offPrev, pBlock->Core.fFlags, cb,
+                      pBlock->cb, pBlock->offNext, pBlock->offPrev);
+        else
+            pfnPrintf("%p  %06x USED offNext=%06x offPrev=%06x fFlags=%#x cb=%#06x\n",
+                      pBlock, pBlock->Core.offSelf, pBlock->Core.offNext, pBlock->Core.offPrev, pBlock->Core.fFlags, cb);
+    }
+    pfnPrintf("**** Done dumping Heap %p ****\n", hHeap);
+}
+RT_EXPORT_SYMBOL(RTHeapOffsetDump);
+
diff --git a/ubuntu/vbox/vboxvideo/include b/ubuntu/vbox/vboxvideo/include
new file mode 120000 (symlink)
index 0000000..f5030fe
--- /dev/null
@@ -0,0 +1 @@
+../include
\ No newline at end of file
diff --git a/ubuntu/vbox/vboxvideo/product-generated.h b/ubuntu/vbox/vboxvideo/product-generated.h
new file mode 100644 (file)
index 0000000..3fbe34a
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef ___product_generated_h___
+#define ___product_generated_h___
+
+#define VBOX_VENDOR "Oracle Corporation"
+#define VBOX_VENDOR_SHORT "Oracle"
+#define VBOX_PRODUCT "Oracle VM VirtualBox"
+#define VBOX_BUILD_PUBLISHER "_Ubuntu"
+#define VBOX_C_YEAR "2017"
+
+#endif
diff --git a/ubuntu/vbox/vboxvideo/r0drv b/ubuntu/vbox/vboxvideo/r0drv
new file mode 120000 (symlink)
index 0000000..f93dcc2
--- /dev/null
@@ -0,0 +1 @@
+../r0drv
\ No newline at end of file
diff --git a/ubuntu/vbox/vboxvideo/revision-generated.h b/ubuntu/vbox/vboxvideo/revision-generated.h
new file mode 100644 (file)
index 0000000..74247d9
--- /dev/null
@@ -0,0 +1 @@
+#define VBOX_SVN_REV 117968
diff --git a/ubuntu/vbox/vboxvideo/vbox_drv.c b/ubuntu/vbox/vboxvideo/vbox_drv.c
new file mode 100644 (file)
index 0000000..4458df0
--- /dev/null
@@ -0,0 +1,344 @@
+/*  $Id: vbox_drv.c $ */
+/** @file
+ * VirtualBox Additions Linux kernel video driver
+ */
+
+/*
+ * Copyright (C) 2013-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.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on
+ * ast_drv.c
+ * with the following copyright and permission notice:
+ *
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+/*
+ * Authors: Dave Airlie <airlied@redhat.com>
+ */
+#include "vbox_drv.h"
+
+#include <VBox/VBoxGuest.h>
+#include "version-generated.h"
+#include "revision-generated.h"
+
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/vt_kern.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+
+int vbox_modeset = -1;
+
+MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
+module_param_named(modeset, vbox_modeset, int, 0400);
+
+static struct drm_driver driver;
+
+static const struct pci_device_id pciidlist[] =
+{
+    {0x80ee, 0xbeef, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+    {0, 0, 0},
+};
+
+MODULE_DEVICE_TABLE(pci, pciidlist);
+
+static int vbox_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+    return drm_get_pci_dev(pdev, ent, &driver);
+}
+
+
+static void vbox_pci_remove(struct pci_dev *pdev)
+{
+    struct drm_device *dev = pci_get_drvdata(pdev);
+
+    drm_put_dev(dev);
+}
+
+
+
+static int vbox_drm_freeze(struct drm_device *dev)
+{
+    drm_kms_helper_poll_disable(dev);
+
+    pci_save_state(dev->pdev);
+
+    console_lock();
+    vbox_fbdev_set_suspend(dev, 1);
+    console_unlock();
+    return 0;
+}
+
+static int vbox_drm_thaw(struct drm_device *dev)
+{
+    int error = 0;
+
+    drm_mode_config_reset(dev);
+    drm_helper_resume_force_mode(dev);
+
+    console_lock();
+    vbox_fbdev_set_suspend(dev, 0);
+    console_unlock();
+    return error;
+}
+
+static int vbox_drm_resume(struct drm_device *dev)
+{
+    int ret;
+
+    if (pci_enable_device(dev->pdev))
+        return -EIO;
+
+       ret = vbox_drm_thaw(dev);
+    if (ret)
+       return ret;
+
+    drm_kms_helper_poll_enable(dev);
+    return 0;
+}
+
+static int vbox_pm_suspend(struct device *dev)
+{
+    struct pci_dev *pdev = to_pci_dev(dev);
+    struct drm_device *ddev = pci_get_drvdata(pdev);
+    int error;
+
+    error = vbox_drm_freeze(ddev);
+    if (error)
+        return error;
+
+    pci_disable_device(pdev);
+    pci_set_power_state(pdev, PCI_D3hot);
+    return 0;
+}
+
+static int vbox_pm_resume(struct device *dev)
+{
+    struct pci_dev *pdev = to_pci_dev(dev);
+    struct drm_device *ddev = pci_get_drvdata(pdev);
+    return vbox_drm_resume(ddev);
+}
+
+static int vbox_pm_freeze(struct device *dev)
+{
+    struct pci_dev *pdev = to_pci_dev(dev);
+    struct drm_device *ddev = pci_get_drvdata(pdev);
+
+    if (!ddev || !ddev->dev_private)
+        return -ENODEV;
+    return vbox_drm_freeze(ddev);
+
+}
+
+static int vbox_pm_thaw(struct device *dev)
+{
+    struct pci_dev *pdev = to_pci_dev(dev);
+    struct drm_device *ddev = pci_get_drvdata(pdev);
+    return vbox_drm_thaw(ddev);
+}
+
+static int vbox_pm_poweroff(struct device *dev)
+{
+    struct pci_dev *pdev = to_pci_dev(dev);
+    struct drm_device *ddev = pci_get_drvdata(pdev);
+
+    return vbox_drm_freeze(ddev);
+}
+
+static const struct dev_pm_ops vbox_pm_ops = {
+    .suspend = vbox_pm_suspend,
+    .resume = vbox_pm_resume,
+    .freeze = vbox_pm_freeze,
+    .thaw = vbox_pm_thaw,
+    .poweroff = vbox_pm_poweroff,
+    .restore = vbox_pm_resume,
+};
+
+static struct pci_driver vbox_pci_driver =
+{
+    .name = DRIVER_NAME,
+    .id_table = pciidlist,
+    .probe = vbox_pci_probe,
+    .remove = vbox_pci_remove,
+    .driver.pm = &vbox_pm_ops,
+};
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) && !defined(RHEL_74)
+/* This works around a bug in X servers prior to 1.18.4, which sometimes
+ * submit more dirty rectangles than the kernel is willing to handle and
+ * then disable dirty rectangle handling altogether when they see the
+ * EINVAL error.  I do not want the code to hang around forever, which is
+ * why I am limiting it to certain kernel versions.  We can increase the
+ * limit if some distributions uses old X servers with new kernels. */
+long vbox_ioctl(struct file *filp,
+                unsigned int cmd, unsigned long arg)
+{
+    long rc = drm_ioctl(filp, cmd, arg);
+    if (cmd == DRM_IOCTL_MODE_DIRTYFB && rc == -EINVAL)
+        return -EOVERFLOW;
+    return rc;
+}
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) && !RHEL_74 */
+
+static const struct file_operations vbox_fops =
+{
+    .owner = THIS_MODULE,
+    .open = drm_open,
+    .release = drm_release,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) && !defined(RHEL_74)
+    .unlocked_ioctl = vbox_ioctl,
+#else
+    .unlocked_ioctl = drm_ioctl,
+#endif
+    .mmap = vbox_mmap,
+    .poll = drm_poll,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && !defined(RHEL_73)
+    .fasync = drm_fasync,
+#endif
+#ifdef CONFIG_COMPAT
+    .compat_ioctl = drm_compat_ioctl,
+#endif
+    .read = drm_read,
+};
+
+static int vbox_master_set(struct drm_device *dev,
+                           struct drm_file *file_priv,
+                           bool from_open)
+{
+    struct vbox_private *vbox = dev->dev_private;
+    /* We do not yet know whether the new owner can handle hotplug, so we
+     * do not advertise dynamic modes on the first query and send a
+     * tentative hotplug notification after that to see if they query again. */
+    vbox->initial_mode_queried = false;
+    mutex_lock(&vbox->hw_mutex);
+    /* Disable VBVA when someone releases master in case the next person tries
+     * to do VESA. */
+    /** @todo work out if anyone is likely to and whether it will even work. */
+    /* Update: we also disable it because if the new master does not do dirty
+     * rectangle reporting (e.g. old versions of Plymouth) then at least the
+     * first screen will still be updated.  We enable it as soon as we
+     * receive a dirty rectangle report. */
+    vbox_disable_accel(vbox);
+    mutex_unlock(&vbox->hw_mutex);
+    return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) && !defined(RHEL_74)
+static void vbox_master_drop(struct drm_device *dev,
+                             struct drm_file *file_priv,
+                             bool from_release)
+#else
+static void vbox_master_drop(struct drm_device *dev,
+                             struct drm_file *file_priv)
+#endif
+{
+    struct vbox_private *vbox = dev->dev_private;
+    /* See vbox_master_set() */
+    vbox->initial_mode_queried = false;
+    mutex_lock(&vbox->hw_mutex);
+    vbox_disable_accel(vbox);
+    mutex_unlock(&vbox->hw_mutex);
+}
+
+static struct drm_driver driver =
+{
+    .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_PRIME,
+    .dev_priv_size = 0,
+
+    .load = vbox_driver_load,
+    .unload = vbox_driver_unload,
+    .lastclose = vbox_driver_lastclose,
+    .master_set = vbox_master_set,
+    .master_drop = vbox_master_drop,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) || defined(RHEL_73)
+    .set_busid = drm_pci_set_busid,
+#endif
+
+    .fops = &vbox_fops,
+    .irq_handler = vbox_irq_handler,
+    .name = DRIVER_NAME,
+    .desc = DRIVER_DESC,
+    .date = DRIVER_DATE,
+    .major = DRIVER_MAJOR,
+    .minor = DRIVER_MINOR,
+    .patchlevel = DRIVER_PATCHLEVEL,
+
+    .gem_free_object = vbox_gem_free_object,
+    .dumb_create = vbox_dumb_create,
+    .dumb_map_offset = vbox_dumb_mmap_offset,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && !defined(RHEL_73)
+    .dumb_destroy = vbox_dumb_destroy,
+#else
+    .dumb_destroy = drm_gem_dumb_destroy,
+#endif
+    .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+    .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+    .gem_prime_export = drm_gem_prime_export,
+    .gem_prime_import = drm_gem_prime_import,
+    .gem_prime_pin = vbox_gem_prime_pin,
+    .gem_prime_unpin = vbox_gem_prime_unpin,
+    .gem_prime_get_sg_table = vbox_gem_prime_get_sg_table,
+    .gem_prime_import_sg_table = vbox_gem_prime_import_sg_table,
+    .gem_prime_vmap = vbox_gem_prime_vmap,
+    .gem_prime_vunmap = vbox_gem_prime_vunmap,
+    .gem_prime_mmap = vbox_gem_prime_mmap,
+
+};
+
+static int __init vbox_init(void)
+{
+#ifdef CONFIG_VGA_CONSOLE
+    if (vgacon_text_force() && vbox_modeset == -1)
+        return -EINVAL;
+#endif
+
+    if (vbox_modeset == 0)
+        return -EINVAL;
+
+    return drm_pci_init(&driver, &vbox_pci_driver);
+}
+static void __exit vbox_exit(void)
+{
+    drm_pci_exit(&driver, &vbox_pci_driver);
+}
+
+module_init(vbox_init);
+module_exit(vbox_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
+#ifdef MODULE_VERSION
+MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
+#endif
diff --git a/ubuntu/vbox/vboxvideo/vbox_drv.h b/ubuntu/vbox/vboxvideo/vbox_drv.h
new file mode 100644 (file)
index 0000000..b7c9f4d
--- /dev/null
@@ -0,0 +1,354 @@
+/* $Id: vbox_drv.h $ */
+/** @file
+ * VirtualBox Additions Linux kernel video driver
+ */
+
+/*
+ * Copyright (C) 2013-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.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on
+ * ast_drv.h
+ * with the following copyright and permission notice:
+ *
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+/*
+ * Authors: Dave Airlie <airlied@redhat.com>
+ */
+#ifndef __VBOX_DRV_H__
+#define __VBOX_DRV_H__
+
+#define LOG_GROUP LOG_GROUP_DEV_VGA
+
+#include "the-linux-kernel.h"
+
+#include <VBox/VBoxVideoGuest.h>
+#include <VBox/log.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+
+#include <drm/ttm/ttm_bo_api.h>
+#include <drm/ttm/ttm_bo_driver.h>
+#include <drm/ttm/ttm_placement.h>
+#include <drm/ttm/ttm_memory.h>
+#include <drm/ttm/ttm_module.h>
+
+#if defined(RHEL_MAJOR) && defined(RHEL_MINOR)
+# if RHEL_MAJOR == 7 && RHEL_MINOR >= 4
+#  define RHEL_73
+#  define RHEL_74
+# elif RHEL_MAJOR == 7 && RHEL_MINOR >= 3
+#  define RHEL_73
+# endif
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) || defined(RHEL_73)
+# include <drm/drm_gem.h>
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+# include <drm/drm_encoder.h>
+#endif
+
+/* #include "vboxvideo.h" */
+
+#include "product-generated.h"
+
+#define DRIVER_AUTHOR       VBOX_VENDOR
+
+#define DRIVER_NAME         "vboxvideo"
+#define DRIVER_DESC         VBOX_PRODUCT " Graphics Card"
+#define DRIVER_DATE         "20130823"
+
+#define DRIVER_MAJOR        1
+#define DRIVER_MINOR        0
+#define DRIVER_PATCHLEVEL   0
+
+#define VBOX_MAX_CURSOR_WIDTH  64
+#define VBOX_MAX_CURSOR_HEIGHT 64
+#define CURSOR_PIXEL_COUNT VBOX_MAX_CURSOR_WIDTH * VBOX_MAX_CURSOR_HEIGHT
+#define CURSOR_DATA_SIZE CURSOR_PIXEL_COUNT * 4 + CURSOR_PIXEL_COUNT / 8
+
+#define VBOX_MAX_SCREENS  32
+
+struct vbox_fbdev;
+
+struct vbox_private {
+    struct drm_device *dev;
+
+    uint8_t __iomem *mapped_vram;
+    HGSMIGUESTCOMMANDCONTEXT submit_info;
+    struct VBVABUFFERCONTEXT *vbva_info;
+    bool any_pitch;
+    unsigned num_crtcs;
+    bool vga2_clone;
+    /** Amount of available VRAM, including space used for buffers. */
+    uint32_t full_vram_size;
+    /** Amount of available VRAM, not including space used for buffers. */
+    uint32_t available_vram_size;
+    /** Offset of mapped VRAM area in full VRAM. */
+    uint32_t vram_map_start;
+    /** Offset to the host flags in the VRAM. */
+    uint32_t host_flags_offset;
+    /** Array of structures for receiving mode hints. */
+    VBVAMODEHINT *last_mode_hints;
+
+    struct vbox_fbdev *fbdev;
+
+    int fb_mtrr;
+
+    struct {
+        struct drm_global_reference mem_global_ref;
+        struct ttm_bo_global_ref bo_global_ref;
+        struct ttm_bo_device bdev;
+        bool mm_initialised;
+    } ttm;
+
+    struct mutex hw_mutex;
+    bool isr_installed;
+    /** We decide whether or not user-space supports display hot-plug
+     * depending on whether they react to a hot-plug event after the initial
+     * mode query. */
+    bool initial_mode_queried;
+    struct work_struct hotplug_work;
+    uint32_t input_mapping_width;
+    uint32_t input_mapping_height;
+    uint32_t cursor_width;
+    uint32_t cursor_height;
+    uint32_t cursor_hot_x;
+    uint32_t cursor_hot_y;
+    size_t cursor_data_size;
+    uint8_t cursor_data[CURSOR_DATA_SIZE];
+};
+
+#undef CURSOR_PIXEL_COUNT
+#undef CURSOR_DATA_SIZE
+
+int vbox_driver_load(struct drm_device *dev, unsigned long flags);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+void vbox_driver_unload(struct drm_device *dev);
+#else
+int vbox_driver_unload(struct drm_device *dev);
+#endif
+void vbox_driver_lastclose(struct drm_device *dev);
+
+struct vbox_gem_object;
+
+#ifndef VGA_PORT_HGSMI_HOST
+# define VGA_PORT_HGSMI_HOST             0x3b0
+# define VGA_PORT_HGSMI_GUEST            0x3d0
+#endif
+
+struct vbox_connector {
+    struct drm_connector base;
+    char name[32];
+    struct vbox_crtc *vbox_crtc;
+    struct {
+        uint16_t width;
+        uint16_t height;
+        bool disconnected;
+    } mode_hint;
+};
+
+struct vbox_crtc {
+    struct drm_crtc base;
+    bool blanked;
+    bool disconnected;
+    unsigned crtc_id;
+    uint32_t fb_offset;
+    bool cursor_enabled;
+};
+
+struct vbox_encoder {
+    struct drm_encoder base;
+};
+
+struct vbox_framebuffer {
+    struct drm_framebuffer base;
+    struct drm_gem_object *obj;
+};
+
+struct vbox_fbdev {
+    struct drm_fb_helper helper;
+    struct vbox_framebuffer afb;
+    void *sysram;
+    int size;
+    struct ttm_bo_kmap_obj mapping;
+    int x1, y1, x2, y2; /* dirty rect */
+    spinlock_t dirty_lock;
+};
+
+#define to_vbox_crtc(x) container_of(x, struct vbox_crtc, base)
+#define to_vbox_connector(x) container_of(x, struct vbox_connector, base)
+#define to_vbox_encoder(x) container_of(x, struct vbox_encoder, base)
+#define to_vbox_framebuffer(x) container_of(x, struct vbox_framebuffer, base)
+
+extern int vbox_mode_init(struct drm_device *dev);
+extern void vbox_mode_fini(struct drm_device *dev);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
+# define DRM_MODE_FB_CMD drm_mode_fb_cmd
+#else
+# define DRM_MODE_FB_CMD drm_mode_fb_cmd2
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0) && !defined(RHEL_73)
+# define CRTC_FB(crtc) (crtc)->fb
+#else
+# define CRTC_FB(crtc) (crtc)->primary->fb
+#endif
+
+void vbox_enable_accel(struct vbox_private *vbox);
+void vbox_disable_accel(struct vbox_private *vbox);
+void vbox_report_caps(struct vbox_private *vbox);
+
+void vbox_framebuffer_dirty_rectangles(struct drm_framebuffer *fb,
+                                       struct drm_clip_rect *rects,
+                                       unsigned num_rects);
+
+int vbox_framebuffer_init(struct drm_device *dev,
+             struct vbox_framebuffer *vbox_fb,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) || defined(RHEL_73)
+             const
+#endif
+             struct DRM_MODE_FB_CMD *mode_cmd,
+             struct drm_gem_object *obj);
+
+int vbox_fbdev_init(struct drm_device *dev);
+void vbox_fbdev_fini(struct drm_device *dev);
+void vbox_fbdev_set_suspend(struct drm_device *dev, int state);
+void vbox_fbdev_set_base(struct vbox_private *vbox, unsigned long gpu_addr);
+
+struct vbox_bo {
+    struct ttm_buffer_object bo;
+    struct ttm_placement placement;
+    struct ttm_bo_kmap_obj kmap;
+    struct drm_gem_object gem;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) && !defined(RHEL_73)
+    u32 placements[3];
+#else
+    struct ttm_place placements[3];
+#endif
+    int pin_count;
+};
+#define gem_to_vbox_bo(gobj) container_of((gobj), struct vbox_bo, gem)
+
+static inline struct vbox_bo *
+vbox_bo(struct ttm_buffer_object *bo)
+{
+    return container_of(bo, struct vbox_bo, bo);
+}
+
+
+#define to_vbox_obj(x) container_of(x, struct vbox_gem_object, base)
+
+extern int vbox_dumb_create(struct drm_file *file,
+               struct drm_device *dev,
+               struct drm_mode_create_dumb *args);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && !defined(RHEL_73)
+extern int vbox_dumb_destroy(struct drm_file *file,
+                struct drm_device *dev,
+                uint32_t handle);
+#endif
+
+extern void vbox_gem_free_object(struct drm_gem_object *obj);
+extern int vbox_dumb_mmap_offset(struct drm_file *file,
+                struct drm_device *dev,
+                uint32_t handle,
+                uint64_t *offset);
+
+#define DRM_FILE_PAGE_OFFSET (0x10000000ULL >> PAGE_SHIFT)
+
+int vbox_mm_init(struct vbox_private *vbox);
+void vbox_mm_fini(struct vbox_private *vbox);
+
+int vbox_bo_create(struct drm_device *dev, int size, int align,
+          uint32_t flags, struct vbox_bo **pvboxbo);
+
+int vbox_gem_create(struct drm_device *dev,
+           u32 size, bool iskernel,
+           struct drm_gem_object **obj);
+
+int vbox_bo_pin(struct vbox_bo *bo, u32 pl_flag, u64 *gpu_addr);
+int vbox_bo_unpin(struct vbox_bo *bo);
+
+static inline int vbox_bo_reserve(struct vbox_bo *bo, bool no_wait)
+{
+    int ret;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) || defined(RHEL_74)
+    ret = ttm_bo_reserve(&bo->bo, true, no_wait, NULL);
+#else
+    ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
+#endif
+    if (ret)
+    {
+        if (ret != -ERESTARTSYS && ret != -EBUSY)
+            DRM_ERROR("reserve failed %p\n", bo);
+        return ret;
+    }
+    return 0;
+}
+
+static inline void vbox_bo_unreserve(struct vbox_bo *bo)
+{
+    ttm_bo_unreserve(&bo->bo);
+}
+
+void vbox_ttm_placement(struct vbox_bo *bo, int domain);
+int vbox_bo_push_sysram(struct vbox_bo *bo);
+int vbox_mmap(struct file *filp, struct vm_area_struct *vma);
+
+/*vbox_prime*/
+int vbox_gem_prime_pin(struct drm_gem_object *obj);
+void vbox_gem_prime_unpin(struct drm_gem_object *obj);
+struct sg_table *vbox_gem_prime_get_sg_table(struct drm_gem_object *obj);
+struct drm_gem_object *vbox_gem_prime_import_sg_table(
+        struct drm_device *dev,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) && !defined(RHEL_73)
+        size_t size,
+#else
+        struct dma_buf_attachment *attach,
+#endif
+        struct sg_table *table);
+void *vbox_gem_prime_vmap(struct drm_gem_object *obj);
+void vbox_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
+int vbox_gem_prime_mmap(struct drm_gem_object *obj,
+        struct vm_area_struct *area);
+
+/* vbox_irq.c */
+int vbox_irq_init(struct vbox_private *vbox);
+void vbox_irq_fini(struct vbox_private *vbox);
+void vbox_report_hotplug(struct vbox_private *vbox);
+irqreturn_t vbox_irq_handler(int irq, void *arg);
+#endif
diff --git a/ubuntu/vbox/vboxvideo/vbox_dummy.c b/ubuntu/vbox/vboxvideo/vbox_dummy.c
new file mode 100644 (file)
index 0000000..6d449fc
--- /dev/null
@@ -0,0 +1,34 @@
+/*  $Id: vbox_dummy.c $ */
+/** @file
+ * VirtualBox Additions Linux kernel video driver, dummy driver for
+ * older kernels.
+ */
+
+/*
+ * Copyright (C) 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.
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+static int __init vbox_init(void)
+{
+    return -EINVAL;
+}
+static void __exit vbox_exit(void)
+{
+}
+
+module_init(vbox_init);
+module_exit(vbox_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/ubuntu/vbox/vboxvideo/vbox_fb.c b/ubuntu/vbox/vboxvideo/vbox_fb.c
new file mode 100644 (file)
index 0000000..595c792
--- /dev/null
@@ -0,0 +1,511 @@
+/* $Id: vbox_fb.c $ */
+/** @file
+ * VirtualBox Additions Linux kernel video driver
+ */
+
+/*
+ * Copyright (C) 2013-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.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on
+ * ast_fb.c
+ * with the following copyright and permission notice:
+ *
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+/*
+ * Authors: Dave Airlie <airlied@redhat.com>
+ */
+/* Include from most specific to most general to be able to override things. */
+#include "vbox_drv.h"
+#include <VBox/VBoxVideo.h>
+#include <VBox/VMMDev.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/sysrq.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include "vbox_drv.h"
+
+#define VBOX_DIRTY_DELAY (HZ / 30)
+/**
+ * Tell the host about dirty rectangles to update.
+ */
+static void vbox_dirty_update(struct vbox_fbdev *fbdev,
+                 int x, int y, int width, int height)
+{
+    int i;
+
+    struct drm_gem_object *obj;
+    struct vbox_bo *bo;
+    int src_offset, dst_offset;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+    int bpp = fbdev->afb.base.format->cpp[0];
+#else
+    int bpp = (fbdev->afb.base.bits_per_pixel + 7) / 8;
+#endif
+    int ret = -EBUSY;
+    bool unmap = false;
+    bool store_for_later = false;
+    int x2, y2;
+    unsigned long flags;
+    struct drm_clip_rect rect;
+
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    obj = fbdev->afb.obj;
+    bo = gem_to_vbox_bo(obj);
+
+    /*
+     * try and reserve the BO, if we fail with busy
+     * then the BO is being moved and we should
+     * store up the damage until later.
+     */
+    if (drm_can_sleep())
+        ret = vbox_bo_reserve(bo, true);
+    if (ret) {
+        if (ret != -EBUSY)
+            return;
+
+        store_for_later = true;
+    }
+
+    x2 = x + width - 1;
+    y2 = y + height - 1;
+    spin_lock_irqsave(&fbdev->dirty_lock, flags);
+
+    if (fbdev->y1 < y)
+        y = fbdev->y1;
+    if (fbdev->y2 > y2)
+        y2 = fbdev->y2;
+    if (fbdev->x1 < x)
+        x = fbdev->x1;
+    if (fbdev->x2 > x2)
+        x2 = fbdev->x2;
+
+    if (store_for_later) {
+        fbdev->x1 = x;
+        fbdev->x2 = x2;
+        fbdev->y1 = y;
+        fbdev->y2 = y2;
+        spin_unlock_irqrestore(&fbdev->dirty_lock, flags);
+        LogFunc(("vboxvideo: %d\n", __LINE__));
+        return;
+    }
+
+    fbdev->x1 = fbdev->y1 = INT_MAX;
+    fbdev->x2 = fbdev->y2 = 0;
+    spin_unlock_irqrestore(&fbdev->dirty_lock, flags);
+
+    if (!bo->kmap.virtual) {
+        ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
+        if (ret) {
+            DRM_ERROR("failed to kmap fb updates\n");
+            vbox_bo_unreserve(bo);
+            return;
+        }
+        unmap = true;
+    }
+    for (i = y; i <= y2; i++) {
+        /* assume equal stride for now */
+        src_offset = dst_offset = i * fbdev->afb.base.pitches[0] + (x * bpp);
+        memcpy_toio(bo->kmap.virtual + src_offset, (char *)fbdev->sysram + src_offset, (x2 - x + 1) * bpp);
+    }
+    /* Not sure why the original code subtracted 1 here, but I will keep it that
+     * way to avoid unnecessary differences. */
+    rect.x1 = x;
+    rect.x2 = x2 + 1;
+    rect.y1 = y;
+    rect.y2 = y2 + 1;
+    vbox_framebuffer_dirty_rectangles(&fbdev->afb.base, &rect, 1);
+    LogFunc(("vboxvideo: %d, bo->kmap.virtual=%p, fbdev->sysram=%p, x=%d, y=%d, x2=%d, y2=%d, unmap=%RTbool\n",
+             __LINE__, bo->kmap.virtual, fbdev->sysram, (int)x, (int)y, (int)x2, (int)y2, unmap));
+    if (unmap)
+        ttm_bo_kunmap(&bo->kmap);
+
+    vbox_bo_unreserve(bo);
+}
+
+#ifdef CONFIG_FB_DEFERRED_IO
+static void vbox_deferred_io(struct fb_info *info,
+                             struct list_head *pagelist)
+{
+        struct vbox_fbdev *fbdev = info->par;
+        unsigned long start, end, min, max;
+        struct page *page;
+        int y1, y2;
+
+        min = ULONG_MAX;
+        max = 0;
+        list_for_each_entry(page, pagelist, lru) {
+                start = page->index << PAGE_SHIFT;
+                end = start + PAGE_SIZE - 1;
+                min = min(min, start);
+                max = max(max, end);
+        }
+
+        if (min < max) {
+                y1 = min / info->fix.line_length;
+                y2 = (max / info->fix.line_length) + 1;
+                printk(KERN_INFO "%s: Calling dirty update: 0, %d, %d, %d\n",
+                       __func__, y1, info->var.xres, y2 - y1 - 1);
+                vbox_dirty_update(fbdev, 0, y1, info->var.xres, y2 - y1 - 1);
+        }
+}
+
+static struct fb_deferred_io vbox_defio =
+{
+        .delay          = VBOX_DIRTY_DELAY,
+        .deferred_io    = vbox_deferred_io,
+};
+#endif
+
+static void vbox_fillrect(struct fb_info *info,
+             const struct fb_fillrect *rect)
+{
+    struct vbox_fbdev *fbdev = info->par;
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    sys_fillrect(info, rect);
+    vbox_dirty_update(fbdev, rect->dx, rect->dy, rect->width,
+             rect->height);
+}
+
+static void vbox_copyarea(struct fb_info *info,
+             const struct fb_copyarea *area)
+{
+    struct vbox_fbdev *fbdev = info->par;
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    sys_copyarea(info, area);
+    vbox_dirty_update(fbdev, area->dx, area->dy, area->width,
+             area->height);
+}
+
+static void vbox_imageblit(struct fb_info *info,
+              const struct fb_image *image)
+{
+    struct vbox_fbdev *fbdev = info->par;
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    sys_imageblit(info, image);
+    vbox_dirty_update(fbdev, image->dx, image->dy, image->width,
+             image->height);
+}
+
+static struct fb_ops vboxfb_ops = {
+    .owner = THIS_MODULE,
+    .fb_check_var = drm_fb_helper_check_var,
+    .fb_set_par = drm_fb_helper_set_par,
+    .fb_fillrect = vbox_fillrect,
+    .fb_copyarea = vbox_copyarea,
+    .fb_imageblit = vbox_imageblit,
+    .fb_pan_display = drm_fb_helper_pan_display,
+    .fb_blank = drm_fb_helper_blank,
+    .fb_setcmap = drm_fb_helper_setcmap,
+    .fb_debug_enter = drm_fb_helper_debug_enter,
+    .fb_debug_leave = drm_fb_helper_debug_leave,
+};
+
+static int vboxfb_create_object(struct vbox_fbdev *fbdev,
+                   struct DRM_MODE_FB_CMD *mode_cmd,
+                   struct drm_gem_object **gobj_p)
+{
+    struct drm_device *dev = fbdev->helper.dev;
+    u32 size;
+    struct drm_gem_object *gobj;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
+    __u32 pitch = mode_cmd->pitch;
+#else
+    __u32 pitch = mode_cmd->pitches[0];
+#endif
+
+    int ret = 0;
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+
+    size = pitch * mode_cmd->height;
+    ret = vbox_gem_create(dev, size, true, &gobj);
+    if (ret)
+        return ret;
+
+    *gobj_p = gobj;
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    return ret;
+}
+
+static int vboxfb_create(struct drm_fb_helper *helper,
+            struct drm_fb_helper_surface_size *sizes)
+{
+    struct vbox_fbdev *fbdev =
+            container_of(helper, struct vbox_fbdev, helper);
+    struct drm_device *dev = fbdev->helper.dev;
+    struct DRM_MODE_FB_CMD mode_cmd;
+    struct drm_framebuffer *fb;
+    struct fb_info *info;
+    __u32 pitch;
+    int size, ret;
+    struct device *device = &dev->pdev->dev;
+    void *sysram;
+    struct drm_gem_object *gobj = NULL;
+    struct vbox_bo *bo = NULL;
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    mode_cmd.width = sizes->surface_width;
+    mode_cmd.height = sizes->surface_height;
+    pitch = mode_cmd.width * ((sizes->surface_bpp + 7) / 8);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
+    mode_cmd.bpp = sizes->surface_bpp;
+    mode_cmd.depth = sizes->surface_depth;
+    mode_cmd.pitch = pitch;
+#else
+    mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+                                                      sizes->surface_depth);
+    mode_cmd.pitches[0] = pitch;
+#endif
+
+    size = pitch * mode_cmd.height;
+
+    ret = vboxfb_create_object(fbdev, &mode_cmd, &gobj);
+    if (ret) {
+        DRM_ERROR("failed to create fbcon backing object %d\n", ret);
+        return ret;
+    }
+    bo = gem_to_vbox_bo(gobj);
+
+    sysram = vmalloc(size);
+    if (!sysram)
+        return -ENOMEM;
+
+    info = framebuffer_alloc(0, device);
+    if (!info) {
+        ret = -ENOMEM;
+        goto out;
+    }
+    info->par = fbdev;
+
+    ret = vbox_framebuffer_init(dev, &fbdev->afb, &mode_cmd, gobj);
+    if (ret)
+        goto out;
+
+    fbdev->sysram = sysram;
+    fbdev->size = size;
+
+    fb = &fbdev->afb.base;
+    fbdev->helper.fb = fb;
+    fbdev->helper.fbdev = info;
+
+    strcpy(info->fix.id, "vboxdrmfb");
+
+    /* The last flag forces a mode set on VT switches even if the kernel does
+     * not think it is needed. */
+    info->flags =   FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT
+                  | FBINFO_MISC_ALWAYS_SETPAR;
+    info->fbops = &vboxfb_ops;
+
+    ret = fb_alloc_cmap(&info->cmap, 256, 0);
+    if (ret) {
+        ret = -ENOMEM;
+        goto out;
+    }
+
+    /* This seems to be done for safety checking that the framebuffer is not
+     * registered twice by different drivers. */
+    info->apertures = alloc_apertures(1);
+    if (!info->apertures) {
+        ret = -ENOMEM;
+        goto out;
+    }
+    info->apertures->ranges[0].base = pci_resource_start(dev->pdev, 0);
+    info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+    drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
+#else
+    drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
+#endif
+    drm_fb_helper_fill_var(info, &fbdev->helper, sizes->fb_width, sizes->fb_height);
+
+    info->screen_base = sysram;
+    info->screen_size = size;
+
+#ifdef CONFIG_FB_DEFERRED_IO
+    info->fbdefio = &vbox_defio;
+    fb_deferred_io_init(info);
+#endif
+
+    info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+    DRM_DEBUG_KMS("allocated %dx%d\n",
+              fb->width, fb->height);
+
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    return 0;
+out:
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    return ret;
+}
+
+static void vbox_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+                   u16 blue, int regno)
+{
+
+}
+
+static void vbox_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+                   u16 *blue, int regno)
+{
+    *red = regno;
+    *green = regno;
+    *blue = regno;
+}
+
+static struct drm_fb_helper_funcs vbox_fb_helper_funcs = {
+    .gamma_set = vbox_fb_gamma_set,
+    .gamma_get = vbox_fb_gamma_get,
+    .fb_probe = vboxfb_create,
+};
+
+static void vbox_fbdev_destroy(struct drm_device *dev,
+                  struct vbox_fbdev *fbdev)
+{
+    struct fb_info *info;
+    struct vbox_framebuffer *afb = &fbdev->afb;
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    if (fbdev->helper.fbdev) {
+        info = fbdev->helper.fbdev;
+        unregister_framebuffer(info);
+        if (info->cmap.len)
+            fb_dealloc_cmap(&info->cmap);
+        framebuffer_release(info);
+    }
+
+    if (afb->obj) {
+        drm_gem_object_unreference_unlocked(afb->obj);
+        afb->obj = NULL;
+    }
+    drm_fb_helper_fini(&fbdev->helper);
+
+    vfree(fbdev->sysram);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+    drm_framebuffer_unregister_private(&afb->base);
+#endif
+    drm_framebuffer_cleanup(&afb->base);
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+}
+
+int vbox_fbdev_init(struct drm_device *dev)
+{
+    struct vbox_private *vbox = dev->dev_private;
+    struct vbox_fbdev *fbdev;
+    int ret;
+
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    fbdev = kzalloc(sizeof(struct vbox_fbdev), GFP_KERNEL);
+    if (!fbdev)
+        return -ENOMEM;
+
+    vbox->fbdev = fbdev;
+    spin_lock_init(&fbdev->dirty_lock);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) && !defined(RHEL_73)
+    fbdev->helper.funcs = &vbox_fb_helper_funcs;
+#else
+    drm_fb_helper_prepare(dev, &fbdev->helper, &vbox_fb_helper_funcs);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+    ret = drm_fb_helper_init(dev, &fbdev->helper, vbox->num_crtcs);
+#else
+    ret = drm_fb_helper_init(dev, &fbdev->helper, vbox->num_crtcs, vbox->num_crtcs);
+#endif
+    if (ret)
+        goto free;
+
+    ret = drm_fb_helper_single_add_all_connectors(&fbdev->helper);
+    if (ret)
+        goto fini;
+
+    /* disable all the possible outputs/crtcs before entering KMS mode */
+    drm_helper_disable_unused_functions(dev);
+
+    ret = drm_fb_helper_initial_config(&fbdev->helper, 32);
+    if (ret)
+        goto fini;
+
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    return 0;
+fini:
+    drm_fb_helper_fini(&fbdev->helper);
+free:
+    kfree(fbdev);
+    vbox->fbdev = NULL;
+    LogFunc(("vboxvideo: %d, ret=%d\n", __LINE__, ret));
+    return ret;
+}
+
+void vbox_fbdev_fini(struct drm_device *dev)
+{
+    struct vbox_private *vbox = dev->dev_private;
+
+    if (!vbox->fbdev)
+        return;
+
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    vbox_fbdev_destroy(dev, vbox->fbdev);
+    kfree(vbox->fbdev);
+    vbox->fbdev = NULL;
+}
+
+void vbox_fbdev_set_suspend(struct drm_device *dev, int state)
+{
+    struct vbox_private *vbox = dev->dev_private;
+
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    if (!vbox->fbdev)
+        return;
+
+    fb_set_suspend(vbox->fbdev->helper.fbdev, state);
+}
+
+void vbox_fbdev_set_base(struct vbox_private *vbox, unsigned long gpu_addr)
+{
+        vbox->fbdev->helper.fbdev->fix.smem_start =
+                vbox->fbdev->helper.fbdev->apertures->ranges[0].base +
+                gpu_addr;
+        vbox->fbdev->helper.fbdev->fix.smem_len = vbox->available_vram_size - gpu_addr;
+}
diff --git a/ubuntu/vbox/vboxvideo/vbox_irq.c b/ubuntu/vbox/vboxvideo/vbox_irq.c
new file mode 100644 (file)
index 0000000..2ea3a04
--- /dev/null
@@ -0,0 +1,187 @@
+/* $Id: vbox_irq.c $ */
+/** @file
+ * VirtualBox Additions Linux kernel video driver
+ */
+
+/*
+ * Copyright (C) 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.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on
+ * qxl_irq.c
+ * with the following copyright and permission notice:
+ *
+ * Copyright 2013 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Dave Airlie
+ *          Alon Levy
+ */
+
+#include "vbox_drv.h"
+
+#include <VBox/VBoxVideo.h>
+
+#include <drm/drm_crtc_helper.h>
+
+static void vbox_clear_irq(void)
+{
+    outl((uint32_t)~0, VGA_PORT_HGSMI_HOST);
+}
+
+static uint32_t vbox_get_flags(struct vbox_private *vbox)
+{
+    return (uint32_t)readl(vbox->mapped_vram + vbox->host_flags_offset);
+}
+
+void vbox_report_hotplug(struct vbox_private *vbox)
+{
+    schedule_work(&vbox->hotplug_work);
+}
+
+irqreturn_t vbox_irq_handler(int irq, void *arg)
+{
+    struct drm_device *dev = (struct drm_device *) arg;
+    struct vbox_private *vbox = (struct vbox_private *)dev->dev_private;
+    uint32_t host_flags = vbox_get_flags(vbox);
+
+    if (!(host_flags & HGSMIHOSTFLAGS_IRQ))
+        return IRQ_NONE;
+
+    /* Due to a bug in the initial host implementation of hot-plug interrupts,
+     * the hot-plug and cursor capability flags were never cleared.  Fortunately
+     * we can tell when they would have been set by checking that the VSYNC flag
+     * is not set. */
+    if (   host_flags & (HGSMIHOSTFLAGS_HOTPLUG | HGSMIHOSTFLAGS_CURSOR_CAPABILITIES)
+        && !(host_flags & HGSMIHOSTFLAGS_VSYNC))
+        vbox_report_hotplug(vbox);
+    vbox_clear_irq();
+    return IRQ_HANDLED;
+}
+
+/**
+ * Query the host for
+ */
+static void vbox_update_mode_hints(struct vbox_private *vbox)
+{
+    struct drm_device *dev = vbox->dev;
+    struct drm_connector *connector;
+    struct vbox_connector *vbox_connector;
+    struct VBVAMODEHINT *hints;
+    uint16_t flags;
+    bool disconnected;
+    unsigned crtc_id;
+    int rc;
+
+    rc = VBoxHGSMIGetModeHints(&vbox->submit_info, vbox->num_crtcs,
+                               vbox->last_mode_hints);
+    AssertMsgRCReturnVoid(rc, ("VBoxHGSMIGetModeHints failed, rc=%Rrc.\n", rc));
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+    drm_modeset_lock_all(dev);
+#else
+    mutex_lock(&dev->mode_config.mutex);
+#endif
+    list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+        vbox_connector = to_vbox_connector(connector);
+        hints = &vbox->last_mode_hints[vbox_connector->vbox_crtc->crtc_id];
+        if (hints->magic == VBVAMODEHINT_MAGIC) {
+            LogFunc(("vboxvideo: %d: crtc_id=%u, mode %hdx%hd(enabled:%d),%hdx%hd\n",
+                     __LINE__, (unsigned)vbox_connector->vbox_crtc->crtc_id,
+                     (short)hints->cx, (short)hints->cy, (int)hints->fEnabled,
+                     (short)hints->dx, (short)hints->dy));
+            disconnected = !(hints->fEnabled);
+            crtc_id = vbox_connector->vbox_crtc->crtc_id;
+            flags =   VBVA_SCREEN_F_ACTIVE
+                    | (disconnected ? VBVA_SCREEN_F_DISABLED : VBVA_SCREEN_F_BLANK);
+            vbox_connector->mode_hint.width = hints->cx & 0x8fff;
+            vbox_connector->mode_hint.height = hints->cy & 0x8fff;
+            vbox_connector->mode_hint.disconnected = disconnected;
+            if (vbox_connector->vbox_crtc->disconnected != disconnected) {
+                VBoxHGSMIProcessDisplayInfo(&vbox->submit_info, crtc_id,
+                                            0, 0, 0, hints->cx * 4, hints->cx,
+                                            hints->cy, 0, flags);
+                vbox_connector->vbox_crtc->disconnected = disconnected;
+            }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) || defined(RHEL_73)
+            if ((hints->dx < 0xffff) && (hints->dy < 0xffff)) {
+                drm_object_property_set_value(&connector->base,
+                    dev->mode_config.suggested_x_property, hints->dx & 0x8fff);
+                drm_object_property_set_value(&connector->base,
+                    dev->mode_config.suggested_y_property, hints->dy & 0x8fff);
+            }
+#endif
+        }
+    }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+    drm_modeset_unlock_all(dev);
+#else
+    mutex_unlock(&dev->mode_config.mutex);
+#endif
+}
+
+static void vbox_hotplug_worker(struct work_struct *work)
+{
+    struct vbox_private *vbox = container_of(work, struct vbox_private,
+                                             hotplug_work);
+
+    LogFunc(("vboxvideo: %d: vbox=%p\n", __LINE__, vbox));
+    vbox_update_mode_hints(vbox);
+    drm_kms_helper_hotplug_event(vbox->dev);
+}
+
+int vbox_irq_init(struct vbox_private *vbox)
+{
+    int ret;
+
+    LogFunc(("vboxvideo: %d: vbox=%p\n", __LINE__, vbox));
+    vbox_update_mode_hints(vbox);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) || defined(RHEL_73)
+    ret = drm_irq_install(vbox->dev, vbox->dev->pdev->irq);
+#else
+    ret = drm_irq_install(vbox->dev);
+#endif
+    if (unlikely(ret != 0)) {
+        vbox_irq_fini(vbox);
+        DRM_ERROR("Failed installing irq: %d\n", ret);
+        return 1;
+    }
+    INIT_WORK(&vbox->hotplug_work, vbox_hotplug_worker);
+    vbox->isr_installed = true;
+    LogFunc(("vboxvideo: %d: vbox=%p\n", __LINE__, vbox));
+    return 0;
+}
+
+void vbox_irq_fini(struct vbox_private *vbox)
+{
+    LogFunc(("vboxvideo: %d: vbox=%p\n", __LINE__, vbox));
+    if (vbox->isr_installed) {
+        drm_irq_uninstall(vbox->dev);
+        flush_work(&vbox->hotplug_work);
+        vbox->isr_installed = false;
+    }
+}
diff --git a/ubuntu/vbox/vboxvideo/vbox_main.c b/ubuntu/vbox/vboxvideo/vbox_main.c
new file mode 100644 (file)
index 0000000..302c5fb
--- /dev/null
@@ -0,0 +1,591 @@
+/* $Id: vbox_main.c $ */
+/** @file
+ * VirtualBox Additions Linux kernel video driver
+ */
+
+/*
+ * Copyright (C) 2013-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.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on
+ * ast_main.c
+ * with the following copyright and permission notice:
+ *
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+/*
+ * Authors: Dave Airlie <airlied@redhat.com>
+ */
+#include "vbox_drv.h"
+
+#include <VBox/VBoxVideoGuest.h>
+#include <VBox/VBoxVideo.h>
+
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_crtc_helper.h>
+
+static void vbox_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+    struct vbox_framebuffer *vbox_fb = to_vbox_framebuffer(fb);
+    if (vbox_fb->obj)
+        drm_gem_object_unreference_unlocked(vbox_fb->obj);
+
+    LogFunc(("vboxvideo: %d: vbox_fb=%p, vbox_fb->obj=%p\n", __LINE__,
+             vbox_fb, vbox_fb->obj));
+    drm_framebuffer_cleanup(fb);
+    kfree(fb);
+}
+
+void vbox_enable_accel(struct vbox_private *vbox)
+{
+    unsigned i;
+    struct VBVABUFFER *vbva;
+    uint32_t vram_map_offset = vbox->available_vram_size - vbox->vram_map_start;
+
+    AssertLogRelReturnVoid(vbox->vbva_info != NULL);
+    for (i = 0; i < vbox->num_crtcs; ++i) {
+        if (vbox->vbva_info[i].pVBVA == NULL) {
+            LogFunc(("vboxvideo: enabling VBVA.\n"));
+            vbva = (struct VBVABUFFER *) (  ((uint8_t *)vbox->mapped_vram)
+                                           + vram_map_offset
+                                           + i * VBVA_MIN_BUFFER_SIZE);
+            if (!VBoxVBVAEnable(&vbox->vbva_info[i], &vbox->submit_info, vbva, i))
+                AssertReleaseMsgFailed(("VBoxVBVAEnable failed - heap allocation error, very old host or driver error.\n"));
+        }
+    }
+}
+
+void vbox_disable_accel(struct vbox_private *vbox)
+{
+    unsigned i;
+
+    for (i = 0; i < vbox->num_crtcs; ++i)
+        VBoxVBVADisable(&vbox->vbva_info[i], &vbox->submit_info, i);
+}
+
+void vbox_report_caps(struct vbox_private *vbox)
+{
+    uint32_t caps =    VBVACAPS_DISABLE_CURSOR_INTEGRATION
+                     | VBVACAPS_IRQ
+                     | VBVACAPS_USE_VBVA_ONLY;
+    if (vbox->initial_mode_queried)
+        caps |= VBVACAPS_VIDEO_MODE_HINTS;
+    VBoxHGSMISendCapsInfo(&vbox->submit_info, caps);
+}
+
+/** Send information about dirty rectangles to VBVA.  If necessary we enable
+ * VBVA first, as this is normally disabled after a change of master in case
+ * the new master does not send dirty rectangle information (is this even
+ * allowed?) */
+void vbox_framebuffer_dirty_rectangles(struct drm_framebuffer *fb,
+                                       struct drm_clip_rect *rects,
+                                       unsigned num_rects)
+{
+    struct vbox_private *vbox = fb->dev->dev_private;
+    struct drm_crtc *crtc;
+    unsigned i;
+
+    LogFunc(("vboxvideo: %d: fb=%p, num_rects=%u, vbox=%p\n", __LINE__, fb,
+             num_rects, vbox));
+    mutex_lock(&vbox->hw_mutex);
+    list_for_each_entry(crtc, &fb->dev->mode_config.crtc_list, head) {
+        if (CRTC_FB(crtc) == fb) {
+            vbox_enable_accel(vbox);
+            for (i = 0; i < num_rects; ++i)
+            {
+                unsigned crtc_id = to_vbox_crtc(crtc)->crtc_id;
+                VBVACMDHDR cmd_hdr;
+
+                if (   rects[i].x1 >   crtc->x
+                                      + crtc->hwmode.hdisplay
+                    || rects[i].y1 >   crtc->y
+                                      + crtc->hwmode.vdisplay
+                    || rects[i].x2 < crtc->x
+                    || rects[i].y2 < crtc->y)
+                    continue;
+                cmd_hdr.x = (int16_t)rects[i].x1;
+                cmd_hdr.y = (int16_t)rects[i].y1;
+                cmd_hdr.w = (uint16_t)rects[i].x2 - rects[i].x1;
+                cmd_hdr.h = (uint16_t)rects[i].y2 - rects[i].y1;
+                if (VBoxVBVABufferBeginUpdate(&vbox->vbva_info[crtc_id],
+                                              &vbox->submit_info))
+                {
+                    VBoxVBVAWrite(&vbox->vbva_info[crtc_id], &vbox->submit_info, &cmd_hdr,
+                                  sizeof(cmd_hdr));
+                    VBoxVBVABufferEndUpdate(&vbox->vbva_info[crtc_id]);
+                }
+            }
+        }
+    }
+    mutex_unlock(&vbox->hw_mutex);
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+}
+
+static int vbox_user_framebuffer_dirty(struct drm_framebuffer *fb,
+                                       struct drm_file *file_priv,
+                                       unsigned flags, unsigned color,
+                                       struct drm_clip_rect *rects,
+                                       unsigned num_rects)
+{
+    vbox_framebuffer_dirty_rectangles(fb, rects, num_rects);
+    return 0;
+}
+
+static const struct drm_framebuffer_funcs vbox_fb_funcs = {
+    .destroy = vbox_user_framebuffer_destroy,
+    .dirty = vbox_user_framebuffer_dirty,
+};
+
+
+int vbox_framebuffer_init(struct drm_device *dev,
+             struct vbox_framebuffer *vbox_fb,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) || defined(RHEL_73)
+             const
+#endif
+             struct DRM_MODE_FB_CMD *mode_cmd,
+             struct drm_gem_object *obj)
+{
+    int ret;
+
+    LogFunc(("vboxvideo: %d: dev=%p, vbox_fb=%p, obj=%p\n", __LINE__, dev,
+             vbox_fb, obj));
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+    drm_helper_mode_fill_fb_struct(dev, &vbox_fb->base, mode_cmd);
+#else
+    drm_helper_mode_fill_fb_struct(&vbox_fb->base, mode_cmd);
+#endif
+    vbox_fb->obj = obj;
+    ret = drm_framebuffer_init(dev, &vbox_fb->base, &vbox_fb_funcs);
+    if (ret) {
+        DRM_ERROR("framebuffer init failed %d\n", ret);
+        LogFunc(("vboxvideo: %d\n", __LINE__));
+        return ret;
+    }
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    return 0;
+}
+
+static struct drm_framebuffer *
+vbox_user_framebuffer_create(struct drm_device *dev,
+           struct drm_file *filp,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) || defined(RHEL_73)
+           const
+#endif
+           struct drm_mode_fb_cmd2 *mode_cmd)
+{
+    struct drm_gem_object *obj;
+    struct vbox_framebuffer *vbox_fb;
+    int ret;
+
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) || defined(RHEL_74)
+    obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
+#else
+    obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
+#endif
+    if (obj == NULL)
+        return ERR_PTR(-ENOENT);
+
+    vbox_fb = kzalloc(sizeof(*vbox_fb), GFP_KERNEL);
+    if (!vbox_fb) {
+        drm_gem_object_unreference_unlocked(obj);
+        return ERR_PTR(-ENOMEM);
+    }
+
+    ret = vbox_framebuffer_init(dev, vbox_fb, mode_cmd, obj);
+    if (ret) {
+        drm_gem_object_unreference_unlocked(obj);
+        kfree(vbox_fb);
+        return ERR_PTR(ret);
+    }
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    return &vbox_fb->base;
+}
+
+static const struct drm_mode_config_funcs vbox_mode_funcs = {
+    .fb_create = vbox_user_framebuffer_create,
+};
+
+static void vbox_accel_fini(struct vbox_private *vbox)
+{
+    if (vbox->vbva_info)
+    {
+        vbox_disable_accel(vbox);
+        kfree(vbox->vbva_info);
+        vbox->vbva_info = NULL;
+    }
+}
+
+static int vbox_accel_init(struct vbox_private *vbox)
+{
+    unsigned i;
+    LogFunc(("vboxvideo: %d: vbox=%p, vbox->num_crtcs=%u, vbox->vbva_info=%p\n",
+             __LINE__, vbox, (unsigned)vbox->num_crtcs, vbox->vbva_info));
+    if (!vbox->vbva_info)
+    {
+        vbox->vbva_info = kzalloc(  sizeof(struct VBVABUFFERCONTEXT)
+                                  * vbox->num_crtcs,
+                                  GFP_KERNEL);
+        if (!vbox->vbva_info)
+            return -ENOMEM;
+    }
+    /* Take a command buffer for each screen from the end of usable VRAM. */
+    vbox->available_vram_size -= vbox->num_crtcs * VBVA_MIN_BUFFER_SIZE;
+    for (i = 0; i < vbox->num_crtcs; ++i)
+        VBoxVBVASetupBufferContext(&vbox->vbva_info[i],
+                                   vbox->available_vram_size + i * VBVA_MIN_BUFFER_SIZE,
+                                   VBVA_MIN_BUFFER_SIZE);
+    LogFunc(("vboxvideo: %d: vbox->vbva_info=%p, vbox->available_vram_size=%u\n",
+             __LINE__, vbox->vbva_info, (unsigned)vbox->available_vram_size));
+    return 0;
+}
+
+/** Allocation function for the HGSMI heap and data. */
+static DECLCALLBACK(void *) alloc_hgsmi_environ(void *environ, HGSMISIZE size)
+{
+    NOREF(environ);
+    return kmalloc(size, GFP_KERNEL);
+}
+
+
+/** Free function for the HGSMI heap and data. */
+static DECLCALLBACK(void) free_hgsmi_environ(void *environ, void *ptr)
+{
+    NOREF(environ);
+    kfree(ptr);
+}
+
+
+/** Pointers to the HGSMI heap and data manipulation functions. */
+static HGSMIENV hgsmi_environ =
+{
+    NULL,
+    alloc_hgsmi_environ,
+    free_hgsmi_environ
+};
+
+
+/** Do we support the 4.3 plus mode hint reporting interface? */
+static bool have_hgsmi_mode_hints(struct vbox_private *vbox)
+{
+    uint32_t have_hints, have_cursor;
+
+    return    RT_SUCCESS(VBoxQueryConfHGSMI(&vbox->submit_info, VBOX_VBVA_CONF32_MODE_HINT_REPORTING, &have_hints))
+           && RT_SUCCESS(VBoxQueryConfHGSMI(&vbox->submit_info, VBOX_VBVA_CONF32_GUEST_CURSOR_REPORTING, &have_cursor))
+           && have_hints == VINF_SUCCESS
+           && have_cursor == VINF_SUCCESS;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) && !defined(RHEL_73)
+# define pci_iomap_range(dev, bar, offset, maxlen) \
+    ioremap(pci_resource_start(dev, bar) + offset, maxlen)
+#endif
+
+/** Set up our heaps and data exchange buffers in VRAM before handing the rest
+ *  to the memory manager. */
+static int vbox_hw_init(struct vbox_private *vbox)
+{
+    uint32_t base_offset, map_start, guest_heap_offset, guest_heap_size, host_flags_offset;
+    void *guest_heap;
+
+    vbox->full_vram_size = VBoxVideoGetVRAMSize();
+    vbox->any_pitch = VBoxVideoAnyWidthAllowed();
+    DRM_INFO("VRAM %08x\n", vbox->full_vram_size);
+    VBoxHGSMIGetBaseMappingInfo(vbox->full_vram_size, &base_offset, NULL,
+                                &guest_heap_offset, &guest_heap_size, &host_flags_offset);
+    map_start = (uint32_t)max((int)base_offset
+                              - VBOX_MAX_SCREENS * VBVA_MIN_BUFFER_SIZE, 0);
+    vbox->mapped_vram = pci_iomap_range(vbox->dev->pdev, 0, map_start,
+                                        vbox->full_vram_size - map_start);
+    if (!vbox->mapped_vram)
+        return -ENOMEM;
+    vbox->vram_map_start = map_start;
+    guest_heap = ((uint8_t *)vbox->mapped_vram) + base_offset - map_start
+                   + guest_heap_offset;
+    vbox->host_flags_offset = base_offset - map_start + host_flags_offset;
+    if (RT_FAILURE(VBoxHGSMISetupGuestContext(&vbox->submit_info, guest_heap,
+                                              guest_heap_size,
+                                              base_offset + guest_heap_offset,
+                                              &hgsmi_environ)))
+        return -ENOMEM;
+    /* Reduce available VRAM size to reflect the guest heap. */
+    vbox->available_vram_size = base_offset;
+    /* Linux drm represents monitors as a 32-bit array. */
+    vbox->num_crtcs = min(VBoxHGSMIGetMonitorCount(&vbox->submit_info),
+                          (uint32_t)VBOX_MAX_SCREENS);
+    if (!have_hgsmi_mode_hints(vbox))
+        return -ENOTSUPP;
+    vbox->last_mode_hints = kzalloc(sizeof(VBVAMODEHINT) * vbox->num_crtcs, GFP_KERNEL);
+    if (!vbox->last_mode_hints)
+        return -ENOMEM;
+    return vbox_accel_init(vbox);
+}
+
+static void vbox_hw_fini(struct vbox_private *vbox)
+{
+    vbox_accel_fini(vbox);
+    if (vbox->last_mode_hints)
+        kfree(vbox->last_mode_hints);
+    vbox->last_mode_hints = NULL;
+}
+
+int vbox_driver_load(struct drm_device *dev, unsigned long flags)
+{
+    struct vbox_private *vbox;
+    int ret = 0;
+
+    LogFunc(("vboxvideo: %d: dev=%p\n", __LINE__, dev));
+    if (!VBoxHGSMIIsSupported())
+        return -ENODEV;
+    vbox = kzalloc(sizeof(struct vbox_private), GFP_KERNEL);
+    if (!vbox)
+        return -ENOMEM;
+
+    dev->dev_private = vbox;
+    vbox->dev = dev;
+
+    mutex_init(&vbox->hw_mutex);
+
+    ret = vbox_hw_init(vbox);
+    if (ret)
+        goto out_free;
+
+    ret = vbox_mm_init(vbox);
+    if (ret)
+        goto out_free;
+
+    drm_mode_config_init(dev);
+
+    dev->mode_config.funcs = (void *)&vbox_mode_funcs;
+    dev->mode_config.min_width = 64;
+    dev->mode_config.min_height = 64;
+    dev->mode_config.preferred_depth = 24;
+    dev->mode_config.max_width = VBE_DISPI_MAX_XRES;
+    dev->mode_config.max_height = VBE_DISPI_MAX_YRES;
+
+    ret = vbox_mode_init(dev);
+    if (ret)
+        goto out_free;
+
+    ret = vbox_irq_init(vbox);
+    if (ret)
+        goto out_free;
+
+    ret = vbox_fbdev_init(dev);
+    if (ret)
+        goto out_free;
+    LogFunc(("vboxvideo: %d: vbox=%p, vbox->mapped_vram=%p, vbox->full_vram_size=%u\n",
+             __LINE__, vbox, vbox->mapped_vram, (unsigned)vbox->full_vram_size));
+    return 0;
+out_free:
+    vbox_driver_unload(dev);
+    LogFunc(("vboxvideo: %d: ret=%d\n", __LINE__, ret));
+    return ret;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+void vbox_driver_unload(struct drm_device *dev)
+#else
+int vbox_driver_unload(struct drm_device *dev)
+#endif
+{
+    struct vbox_private *vbox = dev->dev_private;
+
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    vbox_fbdev_fini(dev);
+    vbox_irq_fini(vbox);
+    vbox_mode_fini(dev);
+    if (dev->mode_config.funcs)
+        drm_mode_config_cleanup(dev);
+
+    vbox_hw_fini(vbox);
+    vbox_mm_fini(vbox);
+    if (vbox->mapped_vram)
+        pci_iounmap(dev->pdev, vbox->mapped_vram);
+    kfree(vbox);
+    dev->dev_private = NULL;
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
+    return 0;
+#endif
+}
+
+/** @note this is described in the DRM framework documentation.  AST does not
+ *        have it, but we get an oops on driver unload if it is not present. */
+void vbox_driver_lastclose(struct drm_device *dev)
+{
+    struct vbox_private *vbox = dev->dev_private;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) || defined(RHEL_73)
+    if (vbox->fbdev)
+        drm_fb_helper_restore_fbdev_mode_unlocked(&vbox->fbdev->helper);
+#else
+    drm_modeset_lock_all(dev);
+    if (vbox->fbdev)
+        drm_fb_helper_restore_fbdev_mode(&vbox->fbdev->helper);
+    drm_modeset_unlock_all(dev);
+#endif
+}
+
+int vbox_gem_create(struct drm_device *dev,
+           u32 size, bool iskernel,
+           struct drm_gem_object **obj)
+{
+    struct vbox_bo *vboxbo;
+    int ret;
+
+    LogFunc(("vboxvideo: %d: dev=%p, size=%u, iskernel=%u\n", __LINE__,
+             dev, (unsigned)size, (unsigned)iskernel));
+    *obj = NULL;
+
+    size = roundup(size, PAGE_SIZE);
+    if (size == 0)
+        return -EINVAL;
+
+    ret = vbox_bo_create(dev, size, 0, 0, &vboxbo);
+    if (ret) {
+        if (ret != -ERESTARTSYS)
+            DRM_ERROR("failed to allocate GEM object\n");
+        return ret;
+    }
+    *obj = &vboxbo->gem;
+    LogFunc(("vboxvideo: %d: obj=%p\n", __LINE__, obj));
+    return 0;
+}
+
+int vbox_dumb_create(struct drm_file *file,
+            struct drm_device *dev,
+            struct drm_mode_create_dumb *args)
+{
+    int ret;
+    struct drm_gem_object *gobj;
+    u32 handle;
+
+    LogFunc(("vboxvideo: %d: args->width=%u, args->height=%u, args->bpp=%u\n",
+             __LINE__, (unsigned)args->width, (unsigned)args->height,
+             (unsigned)args->bpp));
+    args->pitch = args->width * ((args->bpp + 7) / 8);
+    args->size = args->pitch * args->height;
+
+    ret = vbox_gem_create(dev, args->size, false,
+                 &gobj);
+    if (ret)
+        return ret;
+
+    ret = drm_gem_handle_create(file, gobj, &handle);
+    drm_gem_object_unreference_unlocked(gobj);
+    if (ret)
+        return ret;
+
+    args->handle = handle;
+    LogFunc(("vboxvideo: %d: args->handle=%u\n", __LINE__,
+             (unsigned)args->handle));
+    return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && !defined(RHEL_73)
+int vbox_dumb_destroy(struct drm_file *file,
+             struct drm_device *dev,
+             uint32_t handle)
+{
+    LogFunc(("vboxvideo: %d: dev=%p, handle=%u\n", __LINE__, dev,
+             (unsigned)handle));
+    return drm_gem_handle_delete(file, handle);
+}
+#endif
+
+static void vbox_bo_unref(struct vbox_bo **bo)
+{
+    struct ttm_buffer_object *tbo;
+
+    if ((*bo) == NULL)
+        return;
+
+    LogFunc(("vboxvideo: %d: bo=%p\n", __LINE__, bo));
+    tbo = &((*bo)->bo);
+    ttm_bo_unref(&tbo);
+    if (tbo == NULL)
+        *bo = NULL;
+
+}
+void vbox_gem_free_object(struct drm_gem_object *obj)
+{
+    struct vbox_bo *vbox_bo = gem_to_vbox_bo(obj);
+
+    LogFunc(("vboxvideo: %d: vbox_bo=%p\n", __LINE__, vbox_bo));
+    vbox_bo_unref(&vbox_bo);
+}
+
+
+static inline u64 vbox_bo_mmap_offset(struct vbox_bo *bo)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && !defined(RHEL_73)
+    return bo->bo.addr_space_offset;
+#else
+    return drm_vma_node_offset_addr(&bo->bo.vma_node);
+#endif
+}
+int
+vbox_dumb_mmap_offset(struct drm_file *file,
+             struct drm_device *dev,
+             uint32_t handle,
+             uint64_t *offset)
+{
+    struct drm_gem_object *obj;
+    int ret;
+    struct vbox_bo *bo;
+
+    LogFunc(("vboxvideo: %d: dev=%p, handle=%u\n", __LINE__,
+             dev, (unsigned)handle));
+    mutex_lock(&dev->struct_mutex);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) || defined(RHEL_74)
+    obj = drm_gem_object_lookup(file, handle);
+#else
+    obj = drm_gem_object_lookup(dev, file, handle);
+#endif
+    if (obj == NULL) {
+        ret = -ENOENT;
+        goto out_unlock;
+    }
+
+    bo = gem_to_vbox_bo(obj);
+    *offset = vbox_bo_mmap_offset(bo);
+
+    drm_gem_object_unreference(obj);
+    ret = 0;
+    LogFunc(("vboxvideo: %d: bo=%p, *offset=%llu\n", __LINE__,
+             bo, (unsigned long long)*offset));
+out_unlock:
+    mutex_unlock(&dev->struct_mutex);
+    return ret;
+
+}
diff --git a/ubuntu/vbox/vboxvideo/vbox_mode.c b/ubuntu/vbox/vboxvideo/vbox_mode.c
new file mode 100644 (file)
index 0000000..2b96e5e
--- /dev/null
@@ -0,0 +1,835 @@
+/* $Id: vbox_mode.c $ */
+/** @file
+ * VirtualBox Additions Linux kernel video driver
+ */
+
+/*
+ * Copyright (C) 2013-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.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on
+ * ast_mode.c
+ * with the following copyright and permission notice:
+ *
+ * Copyright 2012 Red Hat Inc.
+ * Parts based on xf86-video-ast
+ * Copyright (c) 2005 ASPEED Technology Inc.
+ *
+ * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+/*
+ * Authors: Dave Airlie <airlied@redhat.com>
+ */
+#include "vbox_drv.h"
+
+#include <VBox/VBoxVideo.h>
+
+#include <linux/export.h>
+#include <drm/drm_crtc_helper.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) || defined(RHEL_73)
+# include <drm/drm_plane_helper.h>
+#endif
+
+static int vbox_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
+                            uint32_t handle, uint32_t width, uint32_t height,
+                            int32_t hot_x, int32_t hot_y);
+static int vbox_cursor_move(struct drm_crtc *crtc, int x, int y);
+
+/** Set a graphics mode.  Poke any required values into registers, do an HGSMI
+ * mode set and tell the host we support advanced graphics functions.
+ */
+static void vbox_do_modeset(struct drm_crtc *crtc,
+                            const struct drm_display_mode *mode)
+{
+    struct vbox_crtc   *vbox_crtc = to_vbox_crtc(crtc);
+    struct vbox_private *vbox;
+    int width, height, bpp, pitch;
+    unsigned crtc_id;
+    uint16_t flags;
+
+    LogFunc(("vboxvideo: %d: vbox_crtc=%p, CRTC_FB(crtc)=%p\n", __LINE__,
+             vbox_crtc, CRTC_FB(crtc)));
+    vbox = crtc->dev->dev_private;
+    width = mode->hdisplay ? mode->hdisplay : 640;
+    height = mode->vdisplay ? mode->vdisplay : 480;
+    crtc_id = vbox_crtc->crtc_id;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+    bpp   = crtc->enabled ? CRTC_FB(crtc)->format->cpp[0] * 8 : 32;
+    pitch = crtc->enabled ? CRTC_FB(crtc)->pitches[0] : width * bpp / 8;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+    bpp   = crtc->enabled ? CRTC_FB(crtc)->bits_per_pixel : 32;
+    pitch = crtc->enabled ? CRTC_FB(crtc)->pitches[0] : width * bpp / 8;
+#else
+    bpp   = crtc->enabled ? CRTC_FB(crtc)->bits_per_pixel : 32;
+    pitch = crtc->enabled ? CRTC_FB(crtc)->pitch : width * bpp / 8;
+#endif
+    /* This is the old way of setting graphics modes.  It assumed one screen
+     * and a frame-buffer at the start of video RAM.  On older versions of
+     * VirtualBox, certain parts of the code still assume that the first
+     * screen is programmed this way, so try to fake it. */
+    if (   vbox_crtc->crtc_id == 0
+        && crtc->enabled
+        && vbox_crtc->fb_offset / pitch < 0xffff - crtc->y
+        && vbox_crtc->fb_offset % (bpp / 8) == 0)
+        VBoxVideoSetModeRegisters(width, height, pitch * 8 / bpp,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+                          CRTC_FB(crtc)->format->cpp[0] * 8,
+#else
+                          CRTC_FB(crtc)->bits_per_pixel,
+#endif
+                          0,
+                          vbox_crtc->fb_offset % pitch / bpp * 8 + crtc->x,
+                          vbox_crtc->fb_offset / pitch + crtc->y);
+    flags = VBVA_SCREEN_F_ACTIVE;
+    flags |= (crtc->enabled && !vbox_crtc->blanked ? 0 : VBVA_SCREEN_F_BLANK);
+    flags |= (vbox_crtc->disconnected ? VBVA_SCREEN_F_DISABLED : 0);
+    VBoxHGSMIProcessDisplayInfo(&vbox->submit_info, vbox_crtc->crtc_id,
+                                crtc->x, crtc->y,
+                                crtc->x * bpp / 8 + crtc->y * pitch,
+                                pitch, width, height,
+                                vbox_crtc->blanked ? 0 : bpp, flags);
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+}
+
+static int vbox_set_view(struct drm_crtc *crtc)
+{
+    struct vbox_crtc   *vbox_crtc = to_vbox_crtc(crtc);
+    struct vbox_private *vbox = crtc->dev->dev_private;
+    void *p;
+
+    LogFunc(("vboxvideo: %d: vbox_crtc=%p\n", __LINE__, vbox_crtc));
+    /* Tell the host about the view.  This design originally targeted the
+     * Windows XP driver architecture and assumed that each screen would have
+     * a dedicated frame buffer with the command buffer following it, the whole
+     * being a "view".  The host works out which screen a command buffer belongs
+     * to by checking whether it is in the first view, then whether it is in the
+     * second and so on.  The first match wins.  We cheat around this by making
+     * the first view be the managed memory plus the first command buffer, the
+     * second the same plus the second buffer and so on. */
+    p = VBoxHGSMIBufferAlloc(&vbox->submit_info, sizeof(VBVAINFOVIEW), HGSMI_CH_VBVA,
+                             VBVA_INFO_VIEW);
+    if (p)
+    {
+        VBVAINFOVIEW *pInfo = (VBVAINFOVIEW *)p;
+        pInfo->u32ViewIndex = vbox_crtc->crtc_id;
+        pInfo->u32ViewOffset = vbox_crtc->fb_offset;
+        pInfo->u32ViewSize =   vbox->available_vram_size - vbox_crtc->fb_offset
+                             + vbox_crtc->crtc_id * VBVA_MIN_BUFFER_SIZE;
+        pInfo->u32MaxScreenSize = vbox->available_vram_size - vbox_crtc->fb_offset;
+        VBoxHGSMIBufferSubmit(&vbox->submit_info, p);
+        VBoxHGSMIBufferFree(&vbox->submit_info, p);
+    }
+    else
+        return -ENOMEM;
+    LogFunc(("vboxvideo: %d: p=%p\n", __LINE__, p));
+    return 0;
+}
+
+static void vbox_crtc_load_lut(struct drm_crtc *crtc)
+{
+
+}
+
+static void vbox_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+    struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
+    struct vbox_private *vbox = crtc->dev->dev_private;
+
+    LogFunc(("vboxvideo: %d: vbox_crtc=%p, mode=%d\n", __LINE__, vbox_crtc,
+             mode));
+    switch (mode) {
+    case DRM_MODE_DPMS_ON:
+        vbox_crtc->blanked = false;
+        break;
+    case DRM_MODE_DPMS_STANDBY:
+    case DRM_MODE_DPMS_SUSPEND:
+    case DRM_MODE_DPMS_OFF:
+        vbox_crtc->blanked = true;
+        break;
+    }
+    mutex_lock(&vbox->hw_mutex);
+    vbox_do_modeset(crtc, &crtc->hwmode);
+    mutex_unlock(&vbox->hw_mutex);
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+}
+
+static bool vbox_crtc_mode_fixup(struct drm_crtc *crtc,
+                const struct drm_display_mode *mode,
+                struct drm_display_mode *adjusted_mode)
+{
+    return true;
+}
+
+/* We move buffers which are not in active use out of VRAM to save memory. */
+static int vbox_crtc_do_set_base(struct drm_crtc *crtc,
+                struct drm_framebuffer *fb,
+                int x, int y, int atomic)
+{
+    struct vbox_private *vbox = crtc->dev->dev_private;
+    struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
+    struct drm_gem_object *obj;
+    struct vbox_framebuffer *vbox_fb;
+    struct vbox_bo *bo;
+    int ret;
+    u64 gpu_addr;
+
+    LogFunc(("vboxvideo: %d: fb=%p, vbox_crtc=%p\n", __LINE__, fb, vbox_crtc));
+    /* push the previous fb to system ram */
+    if (!atomic && fb) {
+        vbox_fb = to_vbox_framebuffer(fb);
+        obj = vbox_fb->obj;
+        bo = gem_to_vbox_bo(obj);
+        ret = vbox_bo_reserve(bo, false);
+        if (ret)
+            return ret;
+        vbox_bo_push_sysram(bo);
+        vbox_bo_unreserve(bo);
+    }
+
+    vbox_fb = to_vbox_framebuffer(CRTC_FB(crtc));
+    obj = vbox_fb->obj;
+    bo = gem_to_vbox_bo(obj);
+
+    ret = vbox_bo_reserve(bo, false);
+    if (ret)
+        return ret;
+
+    ret = vbox_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
+    if (ret) {
+        vbox_bo_unreserve(bo);
+        return ret;
+    }
+
+    if (&vbox->fbdev->afb == vbox_fb) {
+        /* if pushing console in kmap it */
+        ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
+        if (ret)
+            DRM_ERROR("failed to kmap fbcon\n");
+        else
+            vbox_fbdev_set_base(vbox, gpu_addr);
+    }
+    vbox_bo_unreserve(bo);
+
+    /* vbox_set_start_address_crt1(crtc, (u32)gpu_addr); */
+    vbox_crtc->fb_offset = gpu_addr;
+    if (vbox_crtc->crtc_id == 0) {
+        vbox->input_mapping_width = CRTC_FB(crtc)->width;
+        vbox->input_mapping_height = CRTC_FB(crtc)->height;
+    }
+    LogFunc(("vboxvideo: %d: vbox_fb=%p, obj=%p, bo=%p, gpu_addr=%u\n",
+             __LINE__, vbox_fb, obj, bo, (unsigned)gpu_addr));
+    return 0;
+}
+
+static int vbox_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+                 struct drm_framebuffer *old_fb)
+{
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    return vbox_crtc_do_set_base(crtc, old_fb, x, y, 0);
+}
+
+static int vbox_crtc_mode_set(struct drm_crtc *crtc,
+                 struct drm_display_mode *mode,
+                 struct drm_display_mode *adjusted_mode,
+                 int x, int y,
+                 struct drm_framebuffer *old_fb)
+{
+    struct vbox_private *vbox = crtc->dev->dev_private;
+    int rc = 0;
+
+    LogFunc(("vboxvideo: %d: vbox=%p\n", __LINE__, vbox));
+    vbox_crtc_mode_set_base(crtc, x, y, old_fb);
+    mutex_lock(&vbox->hw_mutex);
+    rc = vbox_set_view(crtc);
+    if (!rc)
+        vbox_do_modeset(crtc, mode);
+    /* Note that the input mapping is always relative to the first screen. */
+    VBoxHGSMIUpdateInputMapping(&vbox->submit_info, 0, 0,
+                                vbox->input_mapping_width,
+                                vbox->input_mapping_height);
+    mutex_unlock(&vbox->hw_mutex);
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    return rc;
+}
+
+static void vbox_crtc_disable(struct drm_crtc *crtc)
+{
+
+}
+
+static void vbox_crtc_prepare(struct drm_crtc *crtc)
+{
+
+}
+
+static void vbox_crtc_commit(struct drm_crtc *crtc)
+{
+
+}
+
+
+static const struct drm_crtc_helper_funcs vbox_crtc_helper_funcs = {
+    .dpms = vbox_crtc_dpms,
+    .mode_fixup = vbox_crtc_mode_fixup,
+    .mode_set = vbox_crtc_mode_set,
+    /* .mode_set_base = vbox_crtc_mode_set_base, */
+    .disable = vbox_crtc_disable,
+    .load_lut = vbox_crtc_load_lut,
+    .prepare = vbox_crtc_prepare,
+    .commit = vbox_crtc_commit,
+
+};
+
+static void vbox_crtc_reset(struct drm_crtc *crtc)
+{
+
+}
+
+
+static void vbox_crtc_destroy(struct drm_crtc *crtc)
+{
+    drm_crtc_cleanup(crtc);
+    kfree(crtc);
+}
+
+static const struct drm_crtc_funcs vbox_crtc_funcs = {
+    .cursor_move = vbox_cursor_move,
+    .cursor_set2 = vbox_cursor_set2,
+    .reset = vbox_crtc_reset,
+    .set_config = drm_crtc_helper_set_config,
+    /* .gamma_set = vbox_crtc_gamma_set, */
+    .destroy = vbox_crtc_destroy,
+};
+
+static struct vbox_crtc *vbox_crtc_init(struct drm_device *dev, unsigned i)
+{
+    struct vbox_crtc *vbox_crtc;
+
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    vbox_crtc = kzalloc(sizeof(struct vbox_crtc), GFP_KERNEL);
+    if (!vbox_crtc)
+        return NULL;
+    vbox_crtc->crtc_id = i;
+
+    drm_crtc_init(dev, &vbox_crtc->base, &vbox_crtc_funcs);
+    drm_mode_crtc_set_gamma_size(&vbox_crtc->base, 256);
+    drm_crtc_helper_add(&vbox_crtc->base, &vbox_crtc_helper_funcs);
+    LogFunc(("vboxvideo: %d: crtc=%p\n", __LINE__, vbox_crtc));
+
+    return vbox_crtc;
+}
+
+static void vbox_encoder_destroy(struct drm_encoder *encoder)
+{
+    LogFunc(("vboxvideo: %d: encoder=%p\n", __LINE__, encoder));
+    drm_encoder_cleanup(encoder);
+    kfree(encoder);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) && !defined(RHEL_73)
+static struct drm_encoder *drm_encoder_find(struct drm_device *dev, uint32_t id)
+{
+     struct drm_mode_object *mo;
+     mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
+     return mo ? obj_to_encoder(mo) : NULL;
+}
+#endif
+
+static struct drm_encoder *vbox_best_single_encoder(struct drm_connector *connector)
+{
+    int enc_id = connector->encoder_ids[0];
+
+    LogFunc(("vboxvideo: %d: connector=%p\n", __LINE__, connector));
+    /* pick the encoder ids */
+    if (enc_id)
+        return drm_encoder_find(connector->dev, enc_id);
+    LogFunc(("vboxvideo: %d\n", __LINE__));
+    return NULL;
+}
+
+
+static const struct drm_encoder_funcs vbox_enc_funcs = {
+    .destroy = vbox_encoder_destroy,
+};
+
+static void vbox_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+
+}
+
+static bool vbox_mode_fixup(struct drm_encoder *encoder,
+               const struct drm_display_mode *mode,
+               struct drm_display_mode *adjusted_mode)
+{
+    return true;
+}
+
+static void vbox_encoder_mode_set(struct drm_encoder *encoder,
+                   struct drm_display_mode *mode,
+                   struct drm_display_mode *adjusted_mode)
+{
+}
+
+static void vbox_encoder_prepare(struct drm_encoder *encoder)
+{
+
+}
+
+static void vbox_encoder_commit(struct drm_encoder *encoder)
+{
+
+}
+
+
+static const struct drm_encoder_helper_funcs vbox_enc_helper_funcs = {
+    .dpms = vbox_encoder_dpms,
+    .mode_fixup = vbox_mode_fixup,
+    .prepare = vbox_encoder_prepare,
+    .commit = vbox_encoder_commit,
+    .mode_set = vbox_encoder_mode_set,
+};
+
+static struct drm_encoder *vbox_encoder_init(struct drm_device *dev, unsigned i)
+{
+    struct vbox_encoder *vbox_encoder;
+
+    LogFunc(("vboxvideo: %d: dev=%d\n", __LINE__));
+    vbox_encoder = kzalloc(sizeof(struct vbox_encoder), GFP_KERNEL);
+    if (!vbox_encoder)
+        return NULL;
+
+    drm_encoder_init(dev, &vbox_encoder->base, &vbox_enc_funcs,
+                     DRM_MODE_ENCODER_DAC
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) || defined(RHEL_73)
+                     , NULL
+#endif
+                     );
+    drm_encoder_helper_add(&vbox_encoder->base, &vbox_enc_helper_funcs);
+
+    vbox_encoder->base.possible_crtcs = 1 << i;
+    LogFunc(("vboxvideo: %d: vbox_encoder=%p\n", __LINE__, vbox_encoder));
+    return &vbox_encoder->base;
+}
+
+/** Generate EDID data with a mode-unique serial number for the virtual
+ *  monitor to try to persuade Unity that different modes correspond to
+ *  different monitors and it should not try to force the same resolution on
+ *  them. */
+static void vbox_set_edid(struct drm_connector *connector, int width,
+                          int height)
+{
+    enum { EDID_SIZE = 128 };
+    unsigned char edid[EDID_SIZE] = {
+        0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, /* header */
+        0x58, 0x58, /* manufacturer (VBX) */
+        0x00, 0x00, /* product code */
+        0x00, 0x00,0x00, 0x00, /* serial number goes here */
+        0x01, /* week of manufacture */
+        0x00, /* year of manufacture */
+        0x01, 0x03, /* EDID version */
+        0x80, /* capabilities - digital */
+        0x00, /* horiz. res in cm, zero for projectors */
+        0x00, /* vert. res in cm */
+        0x78, /* display gamma (120 == 2.2). */
+        0xEE, /* features (standby, suspend, off, RGB, standard colour space,
+               * preferred timing mode) */
+        0xEE, 0x91, 0xA3, 0x54, 0x4C, 0x99, 0x26, 0x0F, 0x50, 0x54,
+            /* chromaticity for standard colour space. */
+        0x00, 0x00, 0x00, /* no default timings */
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+        0x01, 0x01, 0x01, 0x01, /* no standard timings */
+        0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x02, 0x02, 0x02, 0x02,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* descriptor block 1 goes here */
+        0x00, 0x00, 0x00, 0xFD, 0x00, /* descriptor block 2, monitor ranges */
+        0x00, 0xC8, 0x00, 0xC8, 0x64, 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+        0x20, /* 0-200Hz vertical, 0-200KHz horizontal, 1000MHz pixel clock */
+        0x00, 0x00, 0x00, 0xFC, 0x00, /* descriptor block 3, monitor name */
+        'V', 'B', 'O', 'X', ' ', 'm', 'o', 'n', 'i', 't', 'o', 'r', '\n',
+        0x00, 0x00, 0x00, 0x10, 0x00, /* descriptor block 4: dummy data */
+        0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+        0x20,
+        0x00, /* number of extensions */
+        0x00 /* checksum goes here */
+    };
+    int clock = (width + 6) * (height + 6) * 60 / 10000;
+    unsigned i;
+    unsigned sum = 0;
+
+    edid[12] = width & 0xff;
+    edid[13] = width >> 8;
+    edid[14] = height & 0xff;
+    edid[15] = height >> 8;
+    edid[54] = clock & 0xff;
+    edid[55] = clock >> 8;
+    edid[56] = width & 0xff;
+    edid[58] = (width >> 4) & 0xf0;
+    edid[59] = height & 0xff;
+    edid[61] = (height >> 4) & 0xf0;
+    for (i = 0; i < EDID_SIZE - 1; ++i)
+        sum += edid[i];
+    edid[EDID_SIZE - 1] = (0x100 - (sum & 0xFF)) & 0xFF;
+    drm_mode_connector_update_edid_property(connector, (struct edid *)edid);
+}
+
+static int vbox_get_modes(struct drm_connector *connector)
+{
+    struct vbox_connector *vbox_connector = NULL;
+    struct drm_display_mode *mode = NULL;
+    struct vbox_private *vbox = NULL;
+    unsigned num_modes = 0;
+    int preferred_width, preferred_height;
+
+    LogFunc(("vboxvideo: %d: connector=%p\n", __LINE__, connector));
+    vbox_connector = to_vbox_connector(connector);
+    vbox = connector->dev->dev_private;
+    /* Heuristic: we do not want to tell the host that we support dynamic
+     * resizing unless we feel confident that the user space client using
+     * the video driver can handle hot-plug events.  So the first time modes
+     * are queried after a "master" switch we tell the host that we do not,
+     * and immediately after we send the client a hot-plug notification as
+     * a test to see if they will respond and query again.
+     * That is also the reason why capabilities are reported to the host at
+     * this place in the code rather than elsewhere.
+     * We need to report the flags location before reporting the IRQ
+     * capability. */
+    VBoxHGSMIReportFlagsLocation(&vbox->submit_info,   vbox->vram_map_start
+                                                     + vbox->host_flags_offset);
+    if (vbox_connector->vbox_crtc->crtc_id == 0)
+        vbox_report_caps(vbox);
+    if (!vbox->initial_mode_queried) {
+        if (vbox_connector->vbox_crtc->crtc_id == 0) {
+            vbox->initial_mode_queried = true;
+            vbox_report_hotplug(vbox);
+        }
+        return drm_add_modes_noedid(connector, 800, 600);
+    }
+    num_modes = drm_add_modes_noedid(connector, 2560, 1600);
+    preferred_width = vbox_connector->mode_hint.width ? vbox_connector->mode_hint.width : 1024;
+    preferred_height = vbox_connector->mode_hint.height ? vbox_connector->mode_hint.height : 768;
+    mode = drm_cvt_mode(connector->dev, preferred_width, preferred_height, 60, false,
+                         false, false);
+    if (mode)
+    {
+        mode->type |= DRM_MODE_TYPE_PREFERRED;
+        drm_mode_probed_add(connector, mode);
+        ++num_modes;
+    }
+    vbox_set_edid(connector, preferred_width, preferred_height);
+    return num_modes;
+}
+
+static int vbox_mode_valid(struct drm_connector *connector,
+              struct drm_display_mode *mode)
+{
+    return MODE_OK;
+}
+
+static void vbox_connector_destroy(struct drm_connector *connector)
+{
+    struct vbox_connector *vbox_connector = NULL;
+
+    LogFunc(("vboxvideo: %d: connector=%p\n", __LINE__, connector));
+    vbox_connector = to_vbox_connector(connector);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) && !defined(RHEL_73)
+    drm_sysfs_connector_remove(connector);
+#else
+    drm_connector_unregister(connector);
+#endif
+    drm_connector_cleanup(connector);
+    kfree(connector);
+}
+
+static enum drm_connector_status
+vbox_connector_detect(struct drm_connector *connector, bool force)
+{
+    struct vbox_connector *vbox_connector = NULL;
+
+    (void) force;
+    LogFunc(("vboxvideo: %d: connector=%p\n", __LINE__, connector));
+    vbox_connector = to_vbox_connector(connector);
+    return vbox_connector->mode_hint.disconnected ?
+                connector_status_disconnected : connector_status_connected;
+}
+
+static int vbox_fill_modes(struct drm_connector *connector, uint32_t max_x, uint32_t max_y)
+{
+    struct vbox_connector *vbox_connector;
+    struct drm_device *dev;
+    struct drm_display_mode *mode, *iterator;
+
+    LogFunc(("vboxvideo: %d: connector=%p, max_x=%lu, max_y = %lu\n", __LINE__,
+             connector, (unsigned long)max_x, (unsigned long)max_y));
+    vbox_connector = to_vbox_connector(connector);
+    dev = vbox_connector->base.dev;
+    list_for_each_entry_safe(mode, iterator, &connector->modes, head)
+    {
+        list_del(&mode->head);
+        drm_mode_destroy(dev, mode);
+    }
+    return drm_helper_probe_single_connector_modes(connector, max_x, max_y);
+}
+
+static const struct drm_connector_helper_funcs vbox_connector_helper_funcs = {
+    .mode_valid = vbox_mode_valid,
+    .get_modes = vbox_get_modes,
+    .best_encoder = vbox_best_single_encoder,
+};
+
+static const struct drm_connector_funcs vbox_connector_funcs = {
+    .dpms = drm_helper_connector_dpms,
+    .detect = vbox_connector_detect,
+    .fill_modes = vbox_fill_modes,
+    .destroy = vbox_connector_destroy,
+};
+
+static int vbox_connector_init(struct drm_device *dev,
+                               struct vbox_crtc *vbox_crtc,
+                               struct drm_encoder *encoder)
+{
+    struct vbox_connector *vbox_connector;
+    struct drm_connector *connector;
+
+    LogFunc(("vboxvideo: %d: dev=%p, encoder=%p\n", __LINE__, dev,
+             encoder));
+    vbox_connector = kzalloc(sizeof(struct vbox_connector), GFP_KERNEL);
+    if (!vbox_connector)
+        return -ENOMEM;
+
+    connector = &vbox_connector->base;
+    vbox_connector->vbox_crtc = vbox_crtc;
+
+    drm_connector_init(dev, connector, &vbox_connector_funcs,
+                       DRM_MODE_CONNECTOR_VGA);
+    drm_connector_helper_add(connector, &vbox_connector_helper_funcs);
+
+    connector->interlace_allowed = 0;
+    connector->doublescan_allowed = 0;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) || defined(RHEL_73)
+    drm_mode_create_suggested_offset_properties(dev);
+    drm_object_attach_property(&connector->base,
+                               dev->mode_config.suggested_x_property, 0);
+    drm_object_attach_property(&connector->base,
+                               dev->mode_config.suggested_y_property, 0);
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) && !defined(RHEL_73)
+    drm_sysfs_connector_add(connector);
+#else
+    drm_connector_register(connector);
+#endif
+
+    drm_mode_connector_attach_encoder(connector, encoder);
+
+    LogFunc(("vboxvideo: %d: connector=%p\n", __LINE__, connector));
+    return 0;
+}
+
+int vbox_mode_init(struct drm_device *dev)
+{
+    struct vbox_private *vbox = dev->dev_private;
+    struct drm_encoder *encoder;
+    struct vbox_crtc *vbox_crtc;
+    unsigned i;
+    /* vbox_cursor_init(dev); */
+    LogFunc(("vboxvideo: %d: dev=%p\n", __LINE__, dev));
+    for (i = 0; i < vbox->num_crtcs; ++i)
+    {
+        vbox_crtc = vbox_crtc_init(dev, i);
+        if (!vbox_crtc)
+            return -ENOMEM;
+        encoder = vbox_encoder_init(dev, i);
+        if (!encoder)
+            return -ENOMEM;
+        vbox_connector_init(dev, vbox_crtc, encoder);
+    }
+    return 0;
+}
+
+void vbox_mode_fini(struct drm_device *dev)
+{
+    /* vbox_cursor_fini(dev); */
+}
+
+
+/** Copy the ARGB image and generate the mask, which is needed in case the host
+ *  does not support ARGB cursors.  The mask is a 1BPP bitmap with the bit set
+ *  if the corresponding alpha value in the ARGB image is greater than 0xF0. */
+static void copy_cursor_image(u8 *src, u8 *dst, int width, int height,
+                              size_t mask_size)
+{
+    unsigned i, j;
+    size_t line_size = (width + 7) / 8;
+
+    memcpy(dst + mask_size, src, width * height * 4);
+    for (i = 0; i < height; ++i)
+        for (j = 0; j < width; ++j)
+            if (((uint32_t *)src)[i * width + j] > 0xf0000000)
+                dst[i * line_size + j / 8] |= (0x80 >> (j % 8));
+}
+
+static int vbox_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
+                            uint32_t handle, uint32_t width, uint32_t height,
+                            int32_t hot_x, int32_t hot_y)
+{
+    struct vbox_private *vbox = crtc->dev->dev_private;
+    struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
+    struct drm_gem_object *obj;
+    struct vbox_bo *bo;
+    int ret, rc;
+    struct ttm_bo_kmap_obj uobj_map;
+    u8 *src;
+    u8 *dst = NULL;
+    u32 caps = 0;
+    size_t data_size, mask_size;
+    bool src_isiomem;
+
+    /* Re-set this regularly as in 5.0.20 and earlier the information was lost
+     * on save and restore. */
+    VBoxHGSMIUpdateInputMapping(&vbox->submit_info, 0, 0,
+                                vbox->input_mapping_width,
+                                vbox->input_mapping_height);
+    if (!handle) {
+        bool cursor_enabled = false;
+        struct drm_crtc *crtci;
+
+        /* Hide cursor. */
+        vbox_crtc->cursor_enabled = false;
+        list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list, head)
+            if (to_vbox_crtc(crtci)->cursor_enabled)
+                cursor_enabled = true;
+        if (!cursor_enabled)
+            VBoxHGSMIUpdatePointerShape(&vbox->submit_info, 0, 0, 0, 0, 0, NULL, 0);
+        return 0;
+    }
+    vbox_crtc->cursor_enabled = true;
+    if (   width > VBOX_MAX_CURSOR_WIDTH || height > VBOX_MAX_CURSOR_HEIGHT
+        || width == 0 || height == 0)
+        return -EINVAL;
+    rc = VBoxQueryConfHGSMI(&vbox->submit_info,
+                            VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &caps);
+    ret = -RTErrConvertToErrno(rc);
+    if (ret)
+        return ret;
+    if (   caps & VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER
+        || !(caps & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE))
+        /* -EINVAL means cursor_set2() not supported, -EAGAIN means
+         * retry at once. */
+        return -EBUSY;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) || defined(RHEL_74)
+    obj = drm_gem_object_lookup(file_priv, handle);
+#else
+    obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
+#endif
+    if (obj)
+    {
+        bo = gem_to_vbox_bo(obj);
+        ret = vbox_bo_reserve(bo, false);
+        if (!ret)
+        {
+            /* The mask must be calculated based on the alpha channel, one bit
+             * per ARGB word, and must be 32-bit padded. */
+            mask_size  = ((width + 7) / 8 * height + 3) & ~3;
+            data_size = width * height * 4 + mask_size;
+            vbox->cursor_hot_x = min((uint32_t)max(hot_x, 0), width);
+            vbox->cursor_hot_y = min((uint32_t)max(hot_y, 0), height);
+            vbox->cursor_width = width;
+            vbox->cursor_height = height;
+            vbox->cursor_data_size = data_size;
+            dst = vbox->cursor_data;
+            ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &uobj_map);
+            if (!ret)
+            {
+                src = ttm_kmap_obj_virtual(&uobj_map, &src_isiomem);
+                if (!src_isiomem)
+                {
+                    uint32_t flags =   VBOX_MOUSE_POINTER_VISIBLE
+                                      | VBOX_MOUSE_POINTER_SHAPE
+                                      | VBOX_MOUSE_POINTER_ALPHA;
+                    copy_cursor_image(src, dst, width, height, mask_size);
+                    rc = VBoxHGSMIUpdatePointerShape(&vbox->submit_info, flags,
+                                                     vbox->cursor_hot_x,
+                                                     vbox->cursor_hot_y,
+                                                     width, height, dst,
+                                                     data_size);
+                    ret = -RTErrConvertToErrno(rc);
+                }
+                else
+                    DRM_ERROR("src cursor bo should be in main memory\n");
+                ttm_bo_kunmap(&uobj_map);
+            }
+            else
+                vbox->cursor_data_size = 0;
+            vbox_bo_unreserve(bo);
+        }
+        drm_gem_object_unreference_unlocked(obj);
+    }
+    else
+    {
+        DRM_ERROR("Cannot find cursor object %x for crtc\n", handle);
+        ret = -ENOENT;
+    }
+    return ret;
+}
+
+static int vbox_cursor_move(struct drm_crtc *crtc,
+               int x, int y)
+{
+    struct vbox_private *vbox = crtc->dev->dev_private;
+    uint32_t flags =   VBOX_MOUSE_POINTER_VISIBLE
+                      | VBOX_MOUSE_POINTER_SHAPE
+                      | VBOX_MOUSE_POINTER_ALPHA;
+    uint32_t host_x, host_y;
+    uint32_t hot_x = 0;
+    uint32_t hot_y = 0;
+    int rc;
+
+    /* We compare these to unsigned later and don't need to handle negative. */
+    if (x + crtc->x < 0 || y + crtc->y < 0 || vbox->cursor_data_size == 0)
+        return 0;
+    rc = VBoxHGSMICursorPosition(&vbox->submit_info, true, x + crtc->x,
+                                 y + crtc->y, &host_x, &host_y);
+    /* Work around a bug after save and restore in 5.0.20 and earlier. */
+    if (RT_FAILURE(rc) || (host_x == 0 && host_y == 0))
+        return -RTErrConvertToErrno(rc);
+    if (x + crtc->x < host_x)
+        hot_x = min(host_x - x - crtc->x, vbox->cursor_width);
+    if (y + crtc->y < host_y)
+        hot_y = min(host_y - y - crtc->y, vbox->cursor_height);
+    if (hot_x == vbox->cursor_hot_x && hot_y == vbox->cursor_hot_y)
+        return 0;
+    vbox->cursor_hot_x = hot_x;
+    vbox->cursor_hot_y = hot_y;
+    rc = VBoxHGSMIUpdatePointerShape(&vbox->submit_info, flags, hot_x, hot_y,
+                                     vbox->cursor_width, vbox->cursor_height,
+                                     vbox->cursor_data,
+                                     vbox->cursor_data_size);
+    return -RTErrConvertToErrno(rc);
+}
diff --git a/ubuntu/vbox/vboxvideo/vbox_prime.c b/ubuntu/vbox/vboxvideo/vbox_prime.c
new file mode 100644 (file)
index 0000000..00c1711
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 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.
+ * --------------------------------------------------------------------
+
+ * Copyright 2017 Canonical
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Andreas Pokorny
+ */
+
+#include "vbox_drv.h"
+
+/* Based on qxl_prime.c:
+ * Empty Implementations as there should not be any other driver for a virtual
+ * device that might share buffers with vboxvideo */
+
+int vbox_gem_prime_pin(struct drm_gem_object *obj)
+{
+    WARN_ONCE(1, "not implemented");
+    return -ENOSYS;
+}
+
+void vbox_gem_prime_unpin(struct drm_gem_object *obj)
+{
+    WARN_ONCE(1, "not implemented");
+}
+
+
+struct sg_table *vbox_gem_prime_get_sg_table(struct drm_gem_object *obj)
+{
+    WARN_ONCE(1, "not implemented");
+    return ERR_PTR(-ENOSYS);
+}
+
+struct drm_gem_object *vbox_gem_prime_import_sg_table(
+        struct drm_device *dev,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) && !defined(RHEL_73)
+        size_t size,
+#else
+        struct dma_buf_attachment *attach,
+#endif
+        struct sg_table *table)
+{
+    WARN_ONCE(1, "not implemented");
+    return ERR_PTR(-ENOSYS);
+}
+
+void *vbox_gem_prime_vmap(struct drm_gem_object *obj)
+{
+    WARN_ONCE(1, "not implemented");
+    return ERR_PTR(-ENOSYS);
+}
+
+void vbox_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
+{
+    WARN_ONCE(1, "not implemented");
+}
+
+int vbox_gem_prime_mmap(struct drm_gem_object *obj,
+        struct vm_area_struct *area)
+{
+    WARN_ONCE(1, "not implemented");
+    return -ENOSYS;
+}
diff --git a/ubuntu/vbox/vboxvideo/vbox_ttm.c b/ubuntu/vbox/vboxvideo/vbox_ttm.c
new file mode 100644 (file)
index 0000000..1f4280d
--- /dev/null
@@ -0,0 +1,518 @@
+/* $Id: vbox_ttm.c $ */
+/** @file
+ * VirtualBox Additions Linux kernel video driver
+ */
+
+/*
+ * Copyright (C) 2013-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.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on
+ * ast_ttm.c
+ * with the following copyright and permission notice:
+ *
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+/*
+ * Authors: Dave Airlie <airlied@redhat.com>
+ */
+#include "vbox_drv.h"
+#include <ttm/ttm_page_alloc.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) && !defined(RHEL_73)
+# define PLACEMENT_FLAGS(placement) (placement)
+#else
+# define PLACEMENT_FLAGS(placement) (placement).flags
+#endif
+
+static inline struct vbox_private *
+vbox_bdev(struct ttm_bo_device *bd)
+{
+    return container_of(bd, struct vbox_private, ttm.bdev);
+}
+
+static int
+vbox_ttm_mem_global_init(struct drm_global_reference *ref)
+{
+    return ttm_mem_global_init(ref->object);
+}
+
+static void
+vbox_ttm_mem_global_release(struct drm_global_reference *ref)
+{
+    ttm_mem_global_release(ref->object);
+}
+
+/**
+ * Adds the vbox memory manager object/structures to the global memory manager.
+ */
+static int vbox_ttm_global_init(struct vbox_private *vbox)
+{
+    struct drm_global_reference *global_ref;
+    int r;
+
+    global_ref = &vbox->ttm.mem_global_ref;
+    global_ref->global_type = DRM_GLOBAL_TTM_MEM;
+    global_ref->size = sizeof(struct ttm_mem_global);
+    global_ref->init = &vbox_ttm_mem_global_init;
+    global_ref->release = &vbox_ttm_mem_global_release;
+    r = drm_global_item_ref(global_ref);
+    if (r != 0) {
+        DRM_ERROR("Failed setting up TTM memory accounting "
+              "subsystem.\n");
+        return r;
+    }
+
+    vbox->ttm.bo_global_ref.mem_glob =
+        vbox->ttm.mem_global_ref.object;
+    global_ref = &vbox->ttm.bo_global_ref.ref;
+    global_ref->global_type = DRM_GLOBAL_TTM_BO;
+    global_ref->size = sizeof(struct ttm_bo_global);
+    global_ref->init = &ttm_bo_global_init;
+    global_ref->release = &ttm_bo_global_release;
+    r = drm_global_item_ref(global_ref);
+    if (r != 0) {
+        DRM_ERROR("Failed setting up TTM BO subsystem.\n");
+        drm_global_item_unref(&vbox->ttm.mem_global_ref);
+        return r;
+    }
+    return 0;
+}
+
+/**
+ * Removes the vbox memory manager object from the global memory manager.
+ */
+static void
+vbox_ttm_global_release(struct vbox_private *vbox)
+{
+    if (vbox->ttm.mem_global_ref.release == NULL)
+        return;
+
+    drm_global_item_unref(&vbox->ttm.bo_global_ref.ref);
+    drm_global_item_unref(&vbox->ttm.mem_global_ref);
+    vbox->ttm.mem_global_ref.release = NULL;
+}
+
+
+static void vbox_bo_ttm_destroy(struct ttm_buffer_object *tbo)
+{
+    struct vbox_bo *bo;
+
+    bo = container_of(tbo, struct vbox_bo, bo);
+
+    drm_gem_object_release(&bo->gem);
+    kfree(bo);
+}
+
+static bool vbox_ttm_bo_is_vbox_bo(struct ttm_buffer_object *bo)
+{
+    if (bo->destroy == &vbox_bo_ttm_destroy)
+        return true;
+    return false;
+}
+
+static int
+vbox_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+             struct ttm_mem_type_manager *man)
+{
+    switch (type) {
+    case TTM_PL_SYSTEM:
+        man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+        man->available_caching = TTM_PL_MASK_CACHING;
+        man->default_caching = TTM_PL_FLAG_CACHED;
+        break;
+    case TTM_PL_VRAM:
+        man->func = &ttm_bo_manager_func;
+        man->flags = TTM_MEMTYPE_FLAG_FIXED |
+            TTM_MEMTYPE_FLAG_MAPPABLE;
+        man->available_caching = TTM_PL_FLAG_UNCACHED |
+            TTM_PL_FLAG_WC;
+        man->default_caching = TTM_PL_FLAG_WC;
+        break;
+    default:
+        DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
+        return -EINVAL;
+    }
+    return 0;
+}
+
+static void
+vbox_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
+{
+    struct vbox_bo *vboxbo = vbox_bo(bo);
+
+    if (!vbox_ttm_bo_is_vbox_bo(bo))
+        return;
+
+    vbox_ttm_placement(vboxbo, TTM_PL_FLAG_SYSTEM);
+    *pl = vboxbo->placement;
+}
+
+static int vbox_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
+{
+    return 0;
+}
+
+static int vbox_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
+                  struct ttm_mem_reg *mem)
+{
+    struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+    struct vbox_private *vbox = vbox_bdev(bdev);
+
+    mem->bus.addr = NULL;
+    mem->bus.offset = 0;
+    mem->bus.size = mem->num_pages << PAGE_SHIFT;
+    mem->bus.base = 0;
+    mem->bus.is_iomem = false;
+    if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
+        return -EINVAL;
+    switch (mem->mem_type) {
+    case TTM_PL_SYSTEM:
+        /* system memory */
+        return 0;
+    case TTM_PL_VRAM:
+        mem->bus.offset = mem->start << PAGE_SHIFT;
+        mem->bus.base = pci_resource_start(vbox->dev->pdev, 0);
+        mem->bus.is_iomem = true;
+        break;
+    default:
+        return -EINVAL;
+        break;
+    }
+    return 0;
+}
+
+static void vbox_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
+{
+}
+
+static int vbox_bo_move(struct ttm_buffer_object *bo,
+               bool evict, bool interruptible,
+               bool no_wait_gpu,
+               struct ttm_mem_reg *new_mem)
+{
+    int r;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) && !defined(RHEL_74)
+    r = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) && !defined(RHEL_74)
+    r = ttm_bo_move_memcpy(bo, evict, interruptible, no_wait_gpu, new_mem);
+#else
+    r = ttm_bo_move_memcpy(bo, interruptible, no_wait_gpu, new_mem);
+#endif
+    return r;
+}
+
+
+static void vbox_ttm_backend_destroy(struct ttm_tt *tt)
+{
+    ttm_tt_fini(tt);
+    kfree(tt);
+}
+
+static struct ttm_backend_func vbox_tt_backend_func = {
+    .destroy = &vbox_ttm_backend_destroy,
+};
+
+
+static struct ttm_tt *vbox_ttm_tt_create(struct ttm_bo_device *bdev,
+                 unsigned long size, uint32_t page_flags,
+                 struct page *dummy_read_page)
+{
+    struct ttm_tt *tt;
+
+    tt = kzalloc(sizeof(struct ttm_tt), GFP_KERNEL);
+    if (tt == NULL)
+        return NULL;
+    tt->func = &vbox_tt_backend_func;
+    if (ttm_tt_init(tt, bdev, size, page_flags, dummy_read_page)) {
+        kfree(tt);
+        return NULL;
+    }
+    return tt;
+}
+
+static int vbox_ttm_tt_populate(struct ttm_tt *ttm)
+{
+    return ttm_pool_populate(ttm);
+}
+
+static void vbox_ttm_tt_unpopulate(struct ttm_tt *ttm)
+{
+    ttm_pool_unpopulate(ttm);
+}
+
+struct ttm_bo_driver vbox_bo_driver = {
+    .ttm_tt_create = vbox_ttm_tt_create,
+    .ttm_tt_populate = vbox_ttm_tt_populate,
+    .ttm_tt_unpopulate = vbox_ttm_tt_unpopulate,
+    .init_mem_type = vbox_bo_init_mem_type,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0) || defined(RHEL_74)
+    .eviction_valuable = ttm_bo_eviction_valuable,
+#endif
+    .evict_flags = vbox_bo_evict_flags,
+    .move = vbox_bo_move,
+    .verify_access = vbox_bo_verify_access,
+    .io_mem_reserve = &vbox_ttm_io_mem_reserve,
+    .io_mem_free = &vbox_ttm_io_mem_free,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+    .io_mem_pfn = ttm_bo_default_io_mem_pfn,
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)) \
+    || defined(RHEL_74)
+    .lru_tail = &ttm_bo_default_lru_tail,
+    .swap_lru_tail = &ttm_bo_default_swap_lru_tail,
+#endif
+};
+
+int vbox_mm_init(struct vbox_private *vbox)
+{
+    int ret;
+    struct drm_device *dev = vbox->dev;
+    struct ttm_bo_device *bdev = &vbox->ttm.bdev;
+
+    ret = vbox_ttm_global_init(vbox);
+    if (ret)
+        return ret;
+
+    ret = ttm_bo_device_init(&vbox->ttm.bdev,
+                 vbox->ttm.bo_global_ref.ref.object,
+                 &vbox_bo_driver,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) || defined(RHEL_73)
+                 dev->anon_inode->i_mapping,
+#endif
+                 DRM_FILE_PAGE_OFFSET,
+                 true);
+    if (ret) {
+        DRM_ERROR("Error initialising bo driver; %d\n", ret);
+        return ret;
+    }
+
+    ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
+                 vbox->available_vram_size >> PAGE_SHIFT);
+    if (ret) {
+        DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
+        return ret;
+    }
+
+#ifdef DRM_MTRR_WC
+    vbox->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 0),
+                    pci_resource_len(dev->pdev, 0),
+                    DRM_MTRR_WC);
+#else
+    vbox->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
+                    pci_resource_len(dev->pdev, 0));
+#endif
+
+    vbox->ttm.mm_initialised = true;
+    return 0;
+}
+
+void vbox_mm_fini(struct vbox_private *vbox)
+{
+#ifdef DRM_MTRR_WC
+    struct drm_device *dev = vbox->dev;
+#endif
+    if (!vbox->ttm.mm_initialised)
+        return;
+    ttm_bo_device_release(&vbox->ttm.bdev);
+
+    vbox_ttm_global_release(vbox);
+
+#ifdef DRM_MTRR_WC
+    drm_mtrr_del(vbox->fb_mtrr,
+             pci_resource_start(dev->pdev, 0),
+             pci_resource_len(dev->pdev, 0), DRM_MTRR_WC);
+#else
+    arch_phys_wc_del(vbox->fb_mtrr);
+#endif
+}
+
+void vbox_ttm_placement(struct vbox_bo *bo, int domain)
+{
+    u32 c = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) && !defined(RHEL_73)
+    bo->placement.fpfn = 0;
+    bo->placement.lpfn = 0;
+#else
+    unsigned i;
+#endif
+
+    bo->placement.placement = bo->placements;
+    bo->placement.busy_placement = bo->placements;
+    if (domain & TTM_PL_FLAG_VRAM)
+        PLACEMENT_FLAGS(bo->placements[c++]) = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
+    if (domain & TTM_PL_FLAG_SYSTEM)
+        PLACEMENT_FLAGS(bo->placements[c++]) = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
+    if (!c)
+        PLACEMENT_FLAGS(bo->placements[c++]) = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
+    bo->placement.num_placement = c;
+    bo->placement.num_busy_placement = c;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) || defined(RHEL_73)
+    for (i = 0; i < c; ++i) {
+        bo->placements[i].fpfn = 0;
+        bo->placements[i].lpfn = 0;
+    }
+#endif
+}
+
+int vbox_bo_create(struct drm_device *dev, int size, int align,
+          uint32_t flags, struct vbox_bo **pvboxbo)
+{
+    struct vbox_private *vbox = dev->dev_private;
+    struct vbox_bo *vboxbo;
+    size_t acc_size;
+    int ret;
+
+    vboxbo = kzalloc(sizeof(struct vbox_bo), GFP_KERNEL);
+    if (!vboxbo)
+        return -ENOMEM;
+
+    ret = drm_gem_object_init(dev, &vboxbo->gem, size);
+    if (ret) {
+        kfree(vboxbo);
+        return ret;
+    }
+
+    vboxbo->bo.bdev = &vbox->ttm.bdev;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0) && !defined(RHEL_73)
+    vboxbo->bo.bdev->dev_mapping = dev->dev_mapping;
+#endif
+
+    vbox_ttm_placement(vboxbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
+
+    acc_size = ttm_bo_dma_acc_size(&vbox->ttm.bdev, size,
+                       sizeof(struct vbox_bo));
+
+    ret = ttm_bo_init(&vbox->ttm.bdev, &vboxbo->bo, size,
+              ttm_bo_type_device, &vboxbo->placement,
+              align >> PAGE_SHIFT, false, NULL, acc_size,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) || defined(RHEL_73)
+              NULL,
+#endif
+              NULL, vbox_bo_ttm_destroy);
+    if (ret)
+        return ret;
+
+    *pvboxbo = vboxbo;
+    return 0;
+}
+
+static inline u64 vbox_bo_gpu_offset(struct vbox_bo *bo)
+{
+    return bo->bo.offset;
+}
+
+int vbox_bo_pin(struct vbox_bo *bo, u32 pl_flag, u64 *gpu_addr)
+{
+    int i, ret;
+
+    if (bo->pin_count) {
+        bo->pin_count++;
+        if (gpu_addr)
+            *gpu_addr = vbox_bo_gpu_offset(bo);
+        return 0;
+    }
+
+    vbox_ttm_placement(bo, pl_flag);
+    for (i = 0; i < bo->placement.num_placement; i++)
+        PLACEMENT_FLAGS(bo->placements[i]) |= TTM_PL_FLAG_NO_EVICT;
+    ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
+    if (ret)
+        return ret;
+
+    bo->pin_count = 1;
+    if (gpu_addr)
+        *gpu_addr = vbox_bo_gpu_offset(bo);
+    return 0;
+}
+
+int vbox_bo_unpin(struct vbox_bo *bo)
+{
+    int i, ret;
+    if (!bo->pin_count) {
+        DRM_ERROR("unpin bad %p\n", bo);
+        return 0;
+    }
+    bo->pin_count--;
+    if (bo->pin_count)
+        return 0;
+
+    for (i = 0; i < bo->placement.num_placement ; i++)
+        PLACEMENT_FLAGS(bo->placements[i]) &= ~TTM_PL_FLAG_NO_EVICT;
+    ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
+    if (ret)
+        return ret;
+
+    return 0;
+}
+
+/* Move a vbox-owned buffer object to system memory if no one else has it
+ * pinned.  The caller must have pinned it previously, and this call will
+ * release the caller's pin. */
+int vbox_bo_push_sysram(struct vbox_bo *bo)
+{
+    int i, ret;
+    if (!bo->pin_count) {
+        DRM_ERROR("unpin bad %p\n", bo);
+        return 0;
+    }
+    bo->pin_count--;
+    if (bo->pin_count)
+        return 0;
+
+    if (bo->kmap.virtual)
+        ttm_bo_kunmap(&bo->kmap);
+
+    vbox_ttm_placement(bo, TTM_PL_FLAG_SYSTEM);
+    for (i = 0; i < bo->placement.num_placement ; i++)
+        PLACEMENT_FLAGS(bo->placements[i]) |= TTM_PL_FLAG_NO_EVICT;
+
+    ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
+    if (ret) {
+        DRM_ERROR("pushing to VRAM failed\n");
+        return ret;
+    }
+    return 0;
+}
+
+int vbox_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+    struct drm_file *file_priv;
+    struct vbox_private *vbox;
+
+    if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
+        return -EINVAL;
+
+    file_priv = filp->private_data;
+    vbox = file_priv->minor->dev->dev_private;
+    return ttm_bo_mmap(filp, vma, &vbox->ttm.bdev);
+}
diff --git a/ubuntu/vbox/vboxvideo/version-generated.h b/ubuntu/vbox/vboxvideo/version-generated.h
new file mode 100644 (file)
index 0000000..24cdc17
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef ___version_generated_h___
+#define ___version_generated_h___
+
+#define VBOX_VERSION_MAJOR 5
+#define VBOX_VERSION_MINOR 1
+#define VBOX_VERSION_BUILD 28
+#define VBOX_VERSION_STRING_RAW "5.1.28"
+#define VBOX_VERSION_STRING "5.1.28_Ubuntu"
+#define VBOX_API_VERSION_STRING "5_1"
+
+#define VBOX_PRIVATE_BUILD_DESC "Private build by buildd"
+
+#endif